1 """!Describes regribbing operations using an algebraic structure.
3 This module provides an object-oriented interface to the low-level
4 GRIB manipulation routines in produtil.gribop. It also sits on top of
5 the produtil.datastore module, providing a means to grab GRIB files
6 from Task and Product objects, processing them upon availability."""
8 import os,stat,errno,os.path,copy,threading, collections, logging
12 InvalidRegribResult,RegribProductError,NoProductError, \
13 ProductAmbiguityError,RegribManyError, \
14 RegribKeyError,RegribGridError,GridlessError,GridMismatchError,\
22 __all__=[
'GRIBOp',
'GRIB2Op',
'GRIB1Op',
'GRIBGrid',
'GRIBSubsetter',
23 'GRIB1Merge',
'Regrib',
'GRIB1',
'GRIB2',
'GRIB1File',
24 'GRIB2File',
'UpstreamGRIB1',
'GRIB2Product',
'quarterDegree']
37 """!This is the abstract base class of Regrib and RegribMany and
38 should not be instantiated directly. It exists only to reduce
40 def __init__(self,logger=None,prodargs=None,prodkwargs=None,_base=None,
41 cnvgrib_g12=
None,cnvgrib_g21=
None,wgrib=
None,copygb=
None):
42 """!Creates a RegribBase.
44 @param _base Do not use. The _base should be another
45 RegribBase to copy. If this is specified, all other
46 arguments are ignored, and the _base is copied. This is
47 the implementation of self.copy()
49 @param logger the logging.Logger that should be used when regribbing
50 @param prodargs a list of additional arguments to send to "products"
52 @param prodkwargs a dict of additional keyword arguments to send to
55 @param cnvgrib_g12 The "cnvgrib -p32 -g12" program (a
56 produtil.prog.ImmutableRunner) to convert from GRIB1 to GRIB2.
57 (Other compression types besides -p32 are okay.)
58 @param cnvgrib_g21 The "cnvgrib -g21" program (a
59 produtil.prog.ImmutableRunner) to convert from GRIB2 to GRIB1
60 @param wgrib the wgrib program, with no arguments,
61 a produtil.prog.ImmutableRunner
62 @param copygb the copygb program, with no arguments,
63 a produtil.prog.ImmutableRunner"""
75 assert(copygb
is not None)
76 if copygb
is None: copygb=alias(exe(
'copygb'))
77 if wgrib
is None: wgrib=alias(exe(
'wgrib'))
78 if cnvgrib_g12
is None: cnvgrib_g12=alias(exe(
'cnvgrib')[
'-g12',
'-p32'])
79 if cnvgrib_g21
is None: cnvgrib_g21=alias(exe(
'cnvgrib')[
'-g21'])
91 if prodkwargs
is None:
98 """!Returns the copygb ImmutableRunner"""
101 """!Returns the cnvgrib -p32 -g12 command, which should be an
105 """!Returns the cnvgrib -g21 command, which should be an
109 """!Returns the wgrib command, which should be an
113 """!Returns the logger.Logging object to use for logging
114 messages, or None if no logger was provided to the
118 """!Sets the logger.Logging object to use for logging
120 @param val the new logger"""
124 """!Returns the array of arguments to send to the products
128 """!Returns a dict of keyword arguments to send to the products
133 """!Sets the sync_frequently flag.
134 @param flag if True, the sync program is called frequently"""
137 """!Returns the value of the sync_frequently flag.
138 @returns True if sync is to be called frequently, and False
144 sync_frequently=property(getsync_frequently,setsync_frequently,
None,
145 """Boolean flag: should we call sync frequently?""")
149 logger=property(getlog,setlog,
None,
150 """Either None or the logging.Logger object for this Regrib.""")
154 prodargs=property(getprodargs,
None,
None,
155 """A list of additional positional arguments to send to Task.products.""")
159 prodkwargs=property(getprodkwargs,
None,
None,
160 """A dict of additional keyword arguments to send to Task.products.""")
164 wgrib=property(getwgrib,
None,
None,
165 """Returns None or a wgrib object suitable for produtil.run.run""")
169 copygb=property(getcopygb,
None,
None,
170 """Returns None or a copygb object suitable for produtil.run.run""")
175 cnvgrib_g21=property(getcnvgrib_g21,
None,
None,
176 """Returns None or a cnvgrib -g21 object suitable for produtil.run.run""")
181 cnvgrib_g12=property(getcnvgrib_g12,
None,
None,
182 """Returns None or a cnvgrib -g12 object suitable for produtil.run.run""")
187 """!This is a helper class intended to be used internally by
188 RegribMany. It performs a small number of GRIB manipulations
189 intended to produce the result of a single GRIB expression."""
190 def __init__(self,result,op,workprefix=None,**kwargs):
191 """!Creates a Regrib object whose result has the given name (in
192 "result") and produces the output of the specified operation
193 "op", prepending the given prefix "workprefix" to temporary
194 and output filenames.
195 @param result the name of this operation result, for
196 referencing it again in a RegribMany object after the
197 operation is complete.
198 @param op the operation to perform
200 @param kwargs Additional keyword arguments are sent to
201 RegribBase.__init__()"""
202 super(Regrib,self).
__init__(**kwargs)
207 """!Sets the work directory and filename prefix to the given
208 value, or sets it to a reasonable default if workprefix is
209 None or missing. The work prefix is not necessarily a
210 directory: it can include additional text to prepend to the
213 @param workprefix The new work directory and filename
215 if workprefix
is None:
216 self.
_workprefix=os.path.join(
'./',os.path.basename(result)+
'.step')
219 def reset(self,result,op,workprefix=None):
220 """!Discards all temporary data, and re-initializes this object
221 for the specified result name, operator and workprefix. This
222 is used by RegribMany to re-use a single Regrib object over
225 @param result the new result object to return, if queried
226 @param op the new operation to return if queried
227 @param workprefix the new work directory and filename prefix"""
233 """!Returns the GRIBBase object that performs this Regrib's work."""
238 op=property(getop,
None,
None,
239 """Returns the GRIBBase object that performs this Regrib's work""")
241 """!Returns True if this Regrib object's operator is "ready"
242 (according to is_ready) and False otherwise.
244 @param kwargs Additional keyword arguments passed to GRIBBase.is_ready(), called on self.op.
245 @returns The result of GRIBBase.is_ready(), called on self.op"""
246 return self.op.is_ready(self,**kwargs)
248 """!Returns True if the specified kwargs are valid for this
249 Regrib object's operator and False otherwise.
251 @param kwargs Additional keyword arguments passed to GRIBBase.input_valid() called on self.op
252 @returns the result of GRIBBase.is_ready(), called on self.op"""
253 return self.op.input_valid(self,**kwargs)
255 """!Runs this Regrib object's operator's make function with the
256 given keyword arguments, returning the results.
258 @param kwargs Additional keyword arguments passed to GRIBBase.make() called on self.op
259 @returns the result of GRIBBase.is_ready(), called on self.op"""
260 result=self.op.make(self,**kwargs)
261 assert(result
is not None)
262 if not (isinstance(result,GRIBBase)
or isinstance(result,GRIBGrid)):
264 'Invalid result for type=%s repr=%s which came from running '
265 'self.op.make(**kwargs) on an op=%s and kwargs=%s'%
266 (type(result).__name__,repr(result),repr(self.
op),
270 """!Generates a temporary filename to use for the specified
271 GRIB1/2 file's index file.
273 @param grib the grib filename
274 @returns the suggested filename for the wgrib -s output"""
275 if not isinstance(grib,basestring):
276 raise TypeError(
'Regrib.indextemp requires a string argument, not %s'
277 %(type(grib).__name__))
279 return grib+
'.wgrib_s'
283 os.path.basename(grib))
286 """!Returns a tuple (grib,index) containing a suggested GRIB1/2
287 filename and index filename.
289 @param what The optional argument "what" must contain no shell
290 metacharacters and is incorporated into the file name."""
295 return (out,out+
'.wgrib_s')
297 """!Creates a name of a temporary file.
299 @param what The "what" argument is a terse explanation of the
300 purpose of the file (such as "merge" or "to-grib2") to include
302 @returns The suggested filename."""
312 """!Runs regrib operations on many input times, sending output to
313 an hwrf.gribtask.GRIBTask.
315 This class keeps track of a set of named regribbing operations
316 and target grids. Each operation may connect to another by name,
317 allowing the output of one operation to be the input to one or
318 more other operations. The RegribMany.make can then produce the
319 output of an operation, on the condition that its inputs from
320 earlier operations are ready.
322 The RegribMany is not intended to be used alone. Instead, the
323 GRIBTask class in hwrf.gribtask should be used to execute
324 RegribMany tasks. You can run multiple GRIBTasks at the same
325 time, on the same RegribMany outputs, and the GRIBTasks will
326 automatically work together via file locking and a database to
327 produce the outputs in parallel, as fast as possible.
329 Here is a simple example of the use of a RegribMany object:
332 # This code assumes a PostManyWRF object is available as "mypost",
333 # and HWRFConfig as "conf", and two WRFDomain are available as
334 # "d01" and "d02". We also assume the post has already been run.
337 getd01 = igrb1(mypost,domain=d01)
338 getd02 = igrb1(mypost,domain=d02)
339 r.add('cgrid',clatlon(getd02,res=[0.05,0.05],size=[30.,30.],
340 scan=136,n=[600,600]))
341 r.add('cGRIB1',getd01*r.grid('cgrid')+getd02*r.grid('cgrid'))
342 r.add('cGRIB2',r.GRIB('cGRIB1') * GRIB2)
343 r.to_intercom('output_f{fahr:03d}.grib2','cGRIB2')
344 gribber = GribTask(conf.datastore,conf,'mygrib',r,conf.cycle,
349 Now lets step through that and explain what it does.
352 r = RegribMany() - creates a RegribMany.
355 First, we create the RegribMany object. We're actually doing this
356 in a sloppy way: it will search the $PATH for cnvgrib, wgrib, and
357 other programs. It is better to specify the exact location. That
358 can be done by passing arguments to the RegribMany constructor.
359 See the RegribBase instructor for a list.
362 getd01 = igrb1(mypost,domain=d01)
363 getd02 = igrb1(mypost,domain=d02)
366 This creates a pair of GRIB1Selectors, operations recognized by
367 RegribMany. A GRIB1Selector takes a Task, in this case mypost,
368 and calls its "products" function to get a Product as input to the
369 next step in a regribbing operation. The domain=d01 is passed
370 into products, as is the time=X for each time X the RegribMany
374 r.add('cgrid',clatlon(getd02,res=[0.05,0.05],size=[30.,30.],
375 scan=136,n=[600,600]))
378 This instructs the RegribMany to add an operation to its
379 dictionary. The operation is called "cgrid", and consists of a
380 GRIBGridCompute created by the clatlon function, defined later in
381 this module. The clatlon takes our getd02, and creates a 30x30
382 degree, 600x600 gridpoint, 0.05 degree grid, centered on that
383 domain at each time. If domain d02 moves, this clatlon output
384 will be a moving domain.
388 r.add('cGRIB1',getd01*r.grid('cgrid')+getd02*r.grid('cgrid'))
391 This adds another operation to the RegribMany's dictionary, this
392 time a grib output operation called cGRIB1. The r.grid('cgrid')
393 looks up the cgrid operation we just inserted, connecting that to
394 the cGRIB1. Recall that getd01 and getd02 are also operations,
395 and produce a GRIB1 file. When we multiply that by a grid, it
396 creates a new operation that will use copygb to output a new GRIB1
397 file on that grid. Hence, we have created two temporary files:
400 getd01*r.grid('cgrid') = domain 1's post output on the cgrid
401 getd02*r.grid('cgrid') = domain 2's post output on the cgrid
404 When we add those two together, it pastes the second one on top of
405 the first via a copygb merge operation. That result is then
409 r.add('cGRIB2',r.GRIB('cGRIB1') * GRIB2)
412 This adds a third operation to the RegribMany, called cGRIB2. The
413 r.GRIB('cGRIB1') looks up the operation that creates cGRIB1,
414 connecting that to the new cGRIB2. When we multiply by the
415 special constant GRIB2, it creates a new operation to convert that
419 r.to_com('output_0p05_degree_f{fahr:03d}.grib2','cGRIB2')
422 This sets the delivery location for the cGRIB2 outputs. It will
423 create files with names like:
426 output_0p05_degree_048.grib2 # 48hr output file
429 Without that command, the output will go to automatically-generated
430 locations somewhere in intercom, which is likely not what you want.
433 gribber = GRIBTask(conf.datastore,conf,'mygrib',r,conf.cycle,
437 This creates a GRIBTask that will execute the regribber we just made.
439 The GRIBTask is configured to be able to run our RegribMany for
440 all forecast times starting at the analysis time (conf.cycle) and
441 running to 126 hours afterwards (126*3600), every six hours
442 (6*3600). The GRIBTask will set the time= keyword argument to
443 mypost.products, allowing each RegribMany operation to run on the
450 This tells the gribber to run to completion, generating our output
452 def __init__(self,_copy=None,workprefix=None,**kwargs):
453 """!Creats a new RegribMany.
455 @param workprefix The workprefix, if specified,
456 sets the location in which to run. The _copy is used by the
457 self.copy() for copying.
459 @param _copy,kwargs All other arguments are passed to the
460 superclass RegribBase.__init__ constructor ."""
461 assert(
'time' not in kwargs)
463 if _copy
is not None:
464 RegribBase.__init__(self,_base=_copy)
466 self.
_gens=dict(_copy._gens)
467 self.
_order=list(_copy._order)
468 self.
_kwargs=dict(_copy._kwargs)
469 self.
_delivery=copy.copy(_copy._delivery)
473 assert(
not (
not 'copygb' in kwargs
or kwargs[
'copygb']
is None ) )
474 RegribBase.__init__(self,**kwargs)
475 if workprefix
is None:
483 self.
_lock=threading.RLock()
485 """!Has no effect. This is for forward compatibility to a
486 later thread-safe implementation.
487 @note This used to be implemented but it turns out that
488 Python locks are VERY slow, so the locking had to be
489 removed. Multiple simultaneous regrib operrations are now
490 done through multiple processes"""
493 """!Has no effect. This is for forward compatibility to a
494 later thread-safe implementation.
495 @param etype,evalue,traceback Exception information.
496 @note This used to be implemented but it turns out that
497 Python locks are VERY slow, so the locking had to be
498 removed. Multiple simultaneous regrib operations are now
499 done through multiple processes."""
502 """!Returns True if an operation by the given name exists.
503 @param name the operation name to query"""
505 return name
in self.
_gens
507 """!Erases all cached results."""
511 """!Returns a copy of self with no cached results."""
515 """!Returns a GRIB1Fetcher object that will grab the GRIB1 data
517 @param name the operation name to query"""
521 """!Iterates over all non-GRIBOp operations yielding tuples
522 containing the name and operation."""
523 for k,v
in self._gens.iteritems():
524 if not isinstance(v,GRIBOp):
527 """!Iterates over all GRIBOp operations yielding tuples
528 containing the name and operation."""
529 for k,v
in self._gens.iteritems():
530 if isinstance(v,GRIBOp):
533 """!Returns True if the name corresponds to a grid
534 @param name the operation name to query"""
535 return isinstance(self._gens.get(name,
None),GRIBGridBase)
537 """!Returns a GRIBGridFetcher object that will grab the grid
538 structure with the given name.
539 @param name the operation name to query"""
543 """!Returns a GRIBSubsetterFetcher object that will grab the
544 GRIB subsetter with the given name.
545 @param name the operation name to query"""
548 def add(self,name,arg,**kwargs):
549 """!Adds the given generator "arg" under the specified name (in
550 "name") to this object.
551 @param name the operation name to query
552 @param arg A object of a subclass of GRIBBase
553 @param kwargs Stored for later passing to function calls to arg"""
555 assert name
not in self.
_gens
557 self._order.append(name)
558 self.
_kwargs[name]=dict(kwargs)
559 def to_com(self,location,name,category=None,prodname=None,keep=True):
560 """!Requests delivery to the com directory in file "location"
563 @param category,prodname The category and prodname are used to
564 create the FileProduct object.
565 @param keep Sent to the final deliver_file operation. It
566 should be left as True.
567 @param name the operation's name
568 @param location the destination, which will be sent through
569 hwrf.config.HWRFConfig.conftimestrinterp() by the
570 hwrf.gribtask.GRIBTask"""
571 assert(isinstance(location,basestring))
572 assert(isinstance(name,basestring))
573 assert(category
is None or isinstance(category,basestring))
574 assert(prodname
is None or isinstance(prodname,basestring))
575 assert(isinstance(keep,bool))
577 if not name
in self.
_gens:
578 raise RegribKeyError(
'%s: no such key'%(name,))
579 deldat=[
'com',name,location,category,prodname,keep]
580 self._delivery.append(deldat)
582 def to_intercom(self,location,name,category=None,prodname=None,keep=True):
583 """!Requests delivery to the intercom directory in file
584 "location" of operation "name".
585 @param category,prodname The category and prodname are used to
586 create the FileProduct object.
587 @param keep Sent to the final deliver_file operation. It
588 should be left as True.
589 @param name the operation's name
590 @param location the destination, which will be sent through
591 hwrf.config.HWRFConfig.conftimestrinterp() by the
592 hwrf.gribtask.GRIBTask"""
593 assert(isinstance(location,basestring))
594 assert(isinstance(name,basestring))
595 assert(category
is None or isinstance(category,basestring))
596 assert(prodname
is None or isinstance(prodname,basestring))
597 assert(isinstance(keep,bool))
599 if not name
in self.
_gens:
600 raise RegribKeyError(
'%s: no such key'%(name,))
601 deldat=[
'intercom',name,location,category,prodname,keep]
602 self._delivery.append(deldat)
605 """!Iterates over all deliveries yielding a six element tuple
607 @param name The name of the operation of interest.
609 1. "com" or "intercom"
611 3. location within target directory
612 4. requested category or None
613 5. requested prodname or None
614 6. keep flag from the to_com or to_intercom"""
615 for (where,iname,loc,cat,prod,keep)
in self.
_delivery:
616 if name
is None or name==iname:
617 yield where,iname,loc,cat,prod,keep
619 """!Returns True if there are any requested deliveries and
622 @returns True if to_com() or to_intercom() were called for a known name."""
626 """!Returns True if there is a cached result for the specified
629 @param kwargs The keyword arguments are passed on to the
630 get_data routine for the caching object (usually an
631 hwrf.gribtask.GRIBTask).
632 @param name The operation name."""
633 if self.
_data is None:
637 args[
'regribmany']=self
640 return self._data.get_data(name,**args)
is not None
642 """!Determines if the specified operation is ready.
644 @param name Obtains the operation by the specified name.
645 @param kwargs The is_ready funciton is called on the named
646 operation's generator, passing the given keyword arguments to
650 if 'regribmany' in kwargs:
651 return op.is_ready(**kwargs)
654 args[
'regribmany']=self
655 return op.is_ready(**args)
657 """!Determines if it is possible to run the specified operation
658 with the given keyword arguments.
660 @param name Obtains the operation by the specified name.
661 @param kwargs The input_valid function is called on the
662 generator for the named operation, passing these keyword
666 if 'regribmany' in kwargs:
667 return op.input_valid(**kwargs)
670 args[
'regribmany']=self
671 return op.input_valid(**args)
673 """!Executes the operation previously stored in
674 self.add(), passing it the given keyword arguments,
675 returning the result. If a cache is available (usually a
676 GRIBTask), stores the result in that cache.
678 @param name the name of the operation of interest
679 @param kwargs Passed to the make function in the generator
680 for the named operation"""
683 args[
'regribmany']=self
685 if self.
_data is not None:
687 got=self._data.get_data(name,**args)
688 if got
is not None:
return got
690 r=
Regrib(name,op,workprefix=os.path.join(
692 result=r.make(**args)
693 if not (isinstance(result,GRIBBase)
or isinstance(op,GRIBGrid)):
694 raise InvalidRegribResult(
695 'Invalid result for %s: type=%s repr=%s which came from '
696 'running r.make(**args) on an r=%s and args=%s'%
697 (str(name),type(result).__name__,repr(result),repr(r),
700 if self.
_data is not None:
701 self._data.set_data(name,result,**args)
704 """!Iterates over the names provided to self.add(name,...) in
705 the order they were added."""
726 """Eight bytes: the minimum required size of a non-empty GRIB1 or
727 GRIB2 file. This size is chosen because it is not possible for a file
728 to be smaller than this and still meet the GRIB standard.
729 Realistically, the file should be much larger."""
732 """!Internal function for validating GRIB files.
734 This is a low-level implementation function. It should not be
735 called directly. This checks a file to make sure it exists, is a
736 regular file (or symlink to a regular file) and is large enough to
737 plausibly contain some GRIB1 or GRIB2 data. Returns True for such
738 plausible files and False otherwise. Does not open the file, and
739 performs only a single stat. Uses errno ENOENT (no such file or
740 directory) and ELOOP (too many symbolic links) to detect
741 non-existence. Other exceptions will be passed to the caller.
742 @param regrib a regrib for logging information
743 @param filename the name of the file of interest"""
745 if regrib.logger
is not None:
746 regrib.logger.warning(
747 'checkgrib: filename=None. Probable code error.')
751 sizeok=s.st_size>GRIB_FILE_MIN_SIZE
753 if regrib.logger
is not None:
754 regrib.logger.warning(
'%s: size=%d < 8 bytes'
755 %(str(filename),s.st_size))
757 typeok=stat.S_ISREG(s.st_mode)
759 if regrib.logger
is not None:
760 regrib.logger.warning(
'%s: not a regular file'
761 %(str(filename),s.st_size))
763 except EnvironmentError
as e:
764 if e.errno == errno.ENOENT:
765 if regrib.logger
is not None:
766 regrib.logger.warning(
'%s: input GRIB1/2 file does not exist: %s'%(str(filename),os.strerror(e.errno)))
768 elif e.errno == errno.ELOOP:
769 if regrib.logger
is not None:
770 regrib.logger.warning(
'%s: input GRIB1/2 file path results in too many symlinks (likely a symbolic link loop): %s'%(str(filename),os.strerror(e.errno)))
777 """!Converts GRIB1 file to GRIB2
779 This is a low-level implementation function. It should not be
780 called directly. This function is sent as a parameter to GRIB1Op
781 to produce a GRIB2 version of a GRIB1 file. It uses
782 regrib.cnvgrib_g12 to perform the conversion.
784 @param op The GRIBBase operation running this funciton.
785 @param regrib a Regrib for data information
786 @param infile The input filename.
787 @param args,kwargs Ignored
788 @returns a new GRIB2File for the output file"""
789 (outfile,outindex)=regrib.gribtemp(
'grb2')
790 cmd=regrib.cnvgrib_g12[infile.grib1file,outfile]
791 if regrib.logger
is not None:
792 regrib.logger.info(repr(cmd))
793 if regrib.sync_frequently:
797 raise RegribError(
'ERROR: regrib.cnvgrib_g12 command failed with '
798 'exit status %d'%(ex,))
802 """!Converts GRIB2 files to GRIB1
804 This is a low-level implementation function. It should not be
805 called directly. This function is sent as a parameter to GRIB2Op
806 to produce a GRIB1 version of a GRIB2 file. It uses
807 regrib.cnvgrib_g21 to do the conversion.
809 @param op The GRIBBase operation running this funciton.
810 @param regrib a Regrib for data information
811 @param infile The input filename.
812 @param args,kwargs Ignored
813 @returns a new GRIB1File for the output file
814 @warning This is not used by any HWRF configuration and
815 has not been tested in a while."""
816 (outfile,outindex)=regrib.gribtemp(
'grb1')
817 cmd=regrib.cnvgrib_g21[infile.grib2file,outfile]
818 if regrib.logger
is not None:
819 regrib.logger.info(repr(cmd))
820 if regrib.sync_frequently:
824 raise RegribError(
'ERROR: regrib.cnvgrib_g21 command failed with '
825 'exit status %d'%(ex,))
829 """!Performs regridding and merges two files in a single operation.
831 This is a low-level implementation function. It should not be
832 called directly. This function is sent as a parameter to GRIB1Op
833 to do a copygb regrid AND merge in a single operation (one call to
834 the copygb program). The grid argument is the target grid, and
835 the in1 and in2 arguments are the input GRIB1 files.
837 @param op The GRIBBase operation running this funciton.
838 @param regrib a Regrib for data information
839 @param in1,in2 The input filenames.
840 @param grid The GRIBGrid that provides grid information.
841 @param kwargs Ignored
842 @returns a GRIB1File for the output file, which may be in1 or in2, or a new GRIB1File"""
845 raise GridlessError(
'No GRIB1 grid in input grid object'
846 ' (grid.grib1grid is None).')
855 (outfile,outindex)=regrib.gribtemp(
'merge.grb1')
856 cmd=regrib.copygb[
'-xg'+grid,
'-M',file1,file2,outfile]
857 if regrib.logger
is not None:
858 regrib.logger.info(repr(cmd))
859 if regrib.sync_frequently:
863 message=
'%s + %s: GRIB1 merge failed: exit status %d'%(
865 if regrib.logger
is not None:
866 regrib.logger.error(message)
881 '%s, %s: both inputs to GRIB1 regribmerge are empty or '
882 'missing.'%(file1,file2))
885 """!Runs the grbindex program on a GRIB1 file.
887 This is a low-level implementation function. It should not be
888 called directly. This function adds a grbindex output to the
889 specified input file's product, unless one is already available.
890 Unlike most action_* functions, this one does not create a new
891 GRIBFile or GRIBProduct, instead it modifies the existing one to
892 add the location of the grbindex output.
894 @param op The GRIBBase operation running this funciton.
895 @param regrib a Regrib for data information
896 @param ingrib The input GRIBBase that represents the input file.
897 @param task An hwrf.hwrftask.HWRFTask to provide the path to
899 @param kwargs Ignored
901 assert(task
is not None)
902 assert(ingrib
is not None)
904 infile=ingrib.grib1file
905 inindex=ingrib.grib1grbindex
909 if logger
is not None:
910 logger.info(
'%s: make the grbindex'%(infile,))
911 inindex=infile+
'.grbindex'
912 grbindex=alias(exe(task.getexe(
'grbindex')))
913 if regrib.sync_frequently:
916 ingrib.grib1grbindex=inindex
917 elif logger
is not None:
918 logger.info(
'%s: already has grbindex %s'%(infile,inindex))
922 """!Merges two GRIB1 files that must already have the same grid.
924 This is a low-level implementation function. It should not be
925 called directly. This function is sent as a parameter to GRIB1Op
926 to do a copygb merge (-xM) of two GRIB1 files to produce a single
927 GRIB1 file. It requires that at least one of the files have a
928 known grid, and if both have a known grid then their grids must
930 @param op The GRIBBase operation running this funciton.
931 @param regrib a Regrib for data information
932 @param in1,in2 The input GRIBGrid objects that provide filenames
933 @param kwargs Ignored
934 @returns The resulting GRIB1File, which may be in1, in2 or a new
936 @bug This function calls pwd and ls -l if things go wrong. It
937 needs to use produtil.listing instead."""
940 if grid1
is None and grid2
is None:
942 '%s: unable to guess the grid for this GRIB merge'
949 raise GridMismatchError(
950 'input grids to not match in GRIB merge: (%s) != (%s)'
962 (outfile,outindex)=regrib.gribtemp(
'merge.grb1')
963 cmd=regrib.copygb[
'-g'+grid,
'-xM',file1,file2,outfile]
964 if regrib.logger
is not None:
965 regrib.logger.info(repr(cmd))
966 if regrib.sync_frequently:
970 message=
'%s + %s: GRIB1 merge failed: exit status %d'%(
972 if regrib.logger
is not None:
973 regrib.logger.error(message)
987 raise GRIBInputError(
'%s, %s: both inputs to GRIB1 merge are empty or missing.'%(file1,file2))
990 """!Regrids a GRIB1 file.
992 This is a low-level implementation function. It should not be
993 called directly. This is sent as a parameter to GRIB1Op to
994 convert a GRIB1 file from one grid to another. The output has a
995 known grid, so it can be sent into an action_grib1merge.
996 @param op The GRIBBase operation running this funciton.
997 @param regrib a Regrib for data information
998 @param infile The input filename.
999 @param ingrid Input GRIB1Grid that specifies the target grid.
1000 @param args,kwargs Ignored
1001 @returns a new GRIB1File for the output file"""
1002 (outfile,outindex) = regrib.gribtemp(
'to_'+ingrid.gridname)
1003 grid=ingrid.grib1grid
1005 raise GridlessError(
1006 'Tried to regrid a GRIB1 file, but the GRIBGrid did not have '
1007 'GRIB1 grid information.')
1008 cmd=regrib.copygb[
'-g'+ingrid.grib1grid,
'-x',infile.grib1file,outfile]
1009 if regrib.logger
is not None:
1010 regrib.logger.info(repr(cmd))
1011 if regrib.sync_frequently:
1015 raise RegribError(
'ERROR: copygb regrid command failed with '
1016 'exit status %d'%(ex,))
1018 return GRIB1File(outfile,
None,ingrid.grib1grid)
1021 """!Subsets a GRIB1 file.
1023 This is a low-level implementation function. It should not be
1024 called directly. It subsets a GRIB1 file infile using the given
1025 subsetter. The subsetter should have a list of strings accessible
1026 via subsetter.grib1sub. It should also have a name accessible
1027 through subsetter.subsetname. The wgrib -s output of infile is
1028 scanned. Any line in wgrib -s's output that contains the entirety
1029 of any line in the subsetter.grib1sub is retained. The subsetting
1030 is done via wgrib -i -grib (infile) -o (outfile).
1032 @param op The GRIBBase operation running this funciton.
1033 @param regrib a Regrib for data information
1034 @param infile The input filename.
1035 @param subsetter A GRIBSubsetter that chooses the fields to keep.
1036 @param args,kwargs Ignored
1037 @returns a new GRIB1File for the output file"""
1038 (outfile,outindex)=regrib.gribtemp(
'sub_'+subsetter.subsetname)
1039 if subsetter.grib1sub
is None:
1040 raise SubsetlessError(
'%s: cannot create: no GRIB1 subsetter '
1041 'for subset %s'%(outfile,subname))
1043 index=infile.wgrib_s(regrib)
1044 subindex=[line
for line
in subsetter.grib1sub(index)]
1045 cmd=regrib.wgrib[
'-i',
'-grib',infile.grib1file,
'-o',outfile] \
1046 <<
'\n'.join(subindex)
1047 if regrib.logger
is not None:
1048 regrib.logger.info(repr(cmd))
1049 if regrib.sync_frequently:
1051 ex=run(cmd,logger=regrib.logger)
1053 raise RegribError(
'ERROR: wgrib subset command failed with '
1054 'exit status %d'%(ex,))
1055 return GRIB1File(outfile,
None,infile.grib1grid,
1056 infile.nscenter,infile.ewcenter)
1058 def action_clatlon(op,regrib,name,center,nsres,ewres,nssize,ewsize,
1059 nscount,ewcount,scan,**kwargs):
1060 """!Generates a latitude-longitude grid centered on a GRIB file or
1063 This is an internal implementation function that should not be
1064 called directly. It queries the center object's nscenter and
1065 ewcenter properties to get the objects location. It then adds a
1066 border around that, creating a GRIB1 grid 255 grid specification
1067 centered on the @c center object.
1068 @param op The GRIBBase operation running this funciton.
1069 @param center The GRIBBase operation on which to center the grid
1070 @param regrib a Regrib for data information
1071 @param name the name of the resulting grid, for storage in
1073 @param nsres,ewres GRIB1 grid 255 resolution information
1074 @param nssize,ewsize GRIB1 grid 255 size information, but in degrees.
1075 It will be converted to millidegrees for passing to underlying
1076 GRIB manipulation programs.
1077 @param nscount,ewcount Number of gridpoints in each direction,
1078 for the GRIB1 grid 255 information.
1079 @param scan GRIB1 grid 255 scanning mode byte
1080 @param kwargs Ignored
1081 @returns a new GRIBGrid for the new grid"""
1082 assert (regrib.logger
is not None)
1083 regrib.logger.info(
'IN CLATLON')
1084 nscen=float(center.nscenter)
1085 ewcen=float(center.ewcenter)
1086 if regrib.logger
is not None:
1088 'CLATLON: nsres=%s ewres=%s nssize=%s ewsize=%s nscount=%s '
1089 'ewcount=%s nscen=%f ewcen=%f'%
1090 (repr(nsres),repr(ewres),repr(nssize),repr(ewsize),
1091 repr(nscount),repr(ewcount),nscen,ewcen))
1092 iewres = int(ewres*1000)
1093 insres = int(nsres*1000)
1095 inscount = int(nscount)
1096 iewcount = int(ewcount)
1097 inlat = int(nscen*1000+1000*nssize/2)
1098 islat = int(nscen*1000-1000*nssize/2)
1099 ielon = int(ewcen*1000+1000*ewsize/2)
1100 iwlon = int(ewcen*1000-1000*ewsize/2)
1101 if 0!=(int(scan)&128):
1102 if regrib.logger
is not None:
1103 regrib.logger.info(
'CLATLON scan=%d, swap EW'%(int(scan),))
1104 (ielon,iwlon)=(iwlon,ielon)
1105 if 0!=(int(scan)&64):
1106 if regrib.logger
is not None:
1107 regrib.logger.info(
'CLATLON scan=%d, swap NS'%(int(scan),))
1108 (inlat,islat)=(islat,inlat)
1109 if 0!=(int(scan)&32):
1110 if regrib.logger
is not None:
1111 regrib.logger.info(
'CLATLON scan=%d, swap NS-EW sizes'
1113 (ewcount,nscount)=(nscount,ewcount)
1116 s =
'255 0 %d %d %d %d %d %d %d %d %d 0' % \
1117 ( inscount, iewcount, inlat, ielon, iscan, islat,
1118 iwlon, insres, iewres )
1124 """!Base class for the regridding object tree.
1126 This is the abstract base class for all GRIB files, operators,
1127 subsetters and grids. Everything that is representable as an
1128 Regrib operation is a subclass of GRIBBase. This class should
1129 never be instantiated directly."""
1131 """!Returns True if this object and its subobjects are all
1132 ready for a call to make, and False otherwise.
1133 @param args,kwargs Ignored, but used by subclasses."""
1136 """!Returns True if the specified kwargs are valid and False
1138 @param kwargs Ignored, but used by subclasses"""
1141 """!Runs the action this object should perform and returns
1142 another GRIBBase object.
1143 @param regrib a Regrib for data information
1144 @param kwargs Ignored, but used by subclasses."""
1148 """!This abstract base class represents something that is able to
1149 produce a GRIBGrid object when make() is called."""
1151 class GRIBGrid(GRIBGridBase):
1152 """!This class represents a GRIB1 or GRIB2 grid specification."""
1153 def __init__(self,gridname,grib1grid=None,grib2grid=None):
1154 """!Creates a GRIBGrid with a given name, a copygb -g style
1155 GRIB1 grid specification and a GRIB2 grid specification that
1156 is currently unused.
1157 @param gridname The gridname is mandatory and will be used to
1158 generate temporary filenames.
1159 @param grib1grid The GRIB1 grid information, a string
1160 @param grib2grid The GRIB2 grid information (unsupported)"""
1166 """!Returns True. The grid information is always ready.
1167 @param args,kwargs Ignored, but used by subclasses."""
1170 """!Returns True. The grid information is always available,
1171 regardless of the kwargs.
1172 @param kwargs Ignored, but used by subclasses."""
1175 """!Returns self. This grid is the output grid of this grid.
1176 @param args,kwargs Ignored, but used by subclasses."""
1179 """!Returns the name of this grid, as provided to the
1183 """!Returns the GRIB1 (wgrib) style grid information, as sent
1184 to the constructor's grib1grid argument."""
1187 """!This is a placeholder to return the GRIB2-style grid
1188 information. At present, it returns whatever was sent to the
1189 constructor's grib2grid argument"""
1194 gridname=property(getgridname,
None,
None,
1195 """The name of this grid. This is used to generate output filenames when regridding.""")
1199 grib1grid=property(getgrib1grid,
None,
None,
1200 """A string to send to copygb's -g parameter for interpolating to this grid.""")
1204 grib2grid=property(getgrib2grid,
None,
None,
1205 """GRIB2 regridding information, currently unused.""")
1210 quarterDegree=
GRIBGrid(
'Quarter_Degree_Grid_193',
'193',
None)
1213 """!This class represents a GRIBGrid that is stored in a RegribMany
1214 object. It is able to check for readiness via RegribMany.is_ready
1215 and produce a result via RegribMany.make."""
1217 """!GRIBGridFetcher constructor
1218 @param name The name of the grid that is fetched. This is used
1219 to generate temporary filenames and is used in RegribMany for
1220 the generator name."""
1223 """!Calls kwargs['regribmany'].has_data to see if the specified
1224 operation has produced its grid.
1225 @param args,kwargs Passed to source.has_data. The meaning
1226 is implementation-specific, but generally the kwargs are
1227 used for string replacement in an hwrf.config.HWRFConfig"""
1228 source=kwargs[
'regribmany']
1230 return source.has_data(self.
_name,*args,**kwargs)
1232 """!Calls kwargs['regribmany'].input_valid to see if the
1233 specified kwargs make a valid input to the operation.
1234 @param kwargs Passed to source.input_valid. The meaning
1235 is implementation-specific, but generally the kwargs are
1236 used for string replacement in an hwrf.config.HWRFConfig"""
1237 source=kwargs[
'regribmany']
1239 return source.input_valid(self.
_name,**kwargs)
1241 """!Calls kwargs['regribmany'].make to produce the grid.
1242 @param args,kwargs Passed to source.make. The meaning
1243 is implementation-specific, but generally the kwargs are
1244 used for string replacement in an hwrf.config.HWRFConfig"""
1245 source=kwargs[
'regribmany']
1247 return source.make(self.
_name,**kwargs)
1250 """!This class represents a GRIBGrid that must be computed from
1251 some other input, usually a GRIB file. This is used to create
1252 storm-centered or E-grid GRIB-centered grids for the HWRF."""
1254 """!Creates a new GRIBGridCompute with the given name and
1255 action. The action is a function or callable object that
1256 takes this object, the regrib, the name and the contents of
1257 args. Also, any keyword arguments given to self.make are
1259 @param name The name of the computed grid.
1260 @param action The function that computes the grid.
1261 @param args Additional positional arguments are sent to the function."""
1264 self.
_args=list(args)
1266 """!Returns the logical "or" of is_ready(*args,**kwargs) called
1267 on all subobjects. Subobjects that are not instances of
1268 GRIBBase are assumed to be ready.
1269 @param args,kwargs Passed to arg.is_ready, for all args sent to
1270 the constructor that are subclasses of GRIBBase"""
1271 for arg
in self.
_args:
1272 if isinstance(arg,GRIBBase)
and not arg.is_ready(*args,**kwargs):
1276 """!Returns the logical "or" of input_valid(**kwargs) called on
1277 all subobjects. Subobjects that are not instances of GRIBBase
1278 are assumed to be ready.
1279 @param args,kwargs Passed to arg.input_valid, for all args sent to
1280 the constructor that are subclasses of GRIBBase"""
1281 for arg
in self.
_args:
1282 if isinstance(arg,GRIBBase)
and not arg.input_valid(**kwargs):
1286 """!Runs the action specified in the constructor, providing as
1287 arguments regrib, and the result of running make on all of the
1288 other arguments sent to the constructor.
1289 @param regrib The Regrib object for data storage.
1290 @param kwargs Passed to arg.make, for all args sent to
1291 the constructor that are subclasses of GRIBBase"""
1293 for arg
in self.
_args:
1294 if isinstance(arg,GRIBBase):
1295 args.append(arg.make(regrib,**kwargs))
1298 return self.
_action(self,regrib,self.
_name,*args,**kwargs)
1301 """!Represents a specific location on the earth as a latitude,
1302 longitude pair. This is meant to be used with action_clatlon to
1303 generate fixed lat-lon grids."""
1305 """!FixedLocation constructor
1306 @param lat,lon The fixed location in degrees North and East."""
1307 self.
__lat=float(lat)
1308 self.
__lon=float(lon)
1310 """!Returns the point's latitude"""
1313 """!Returns the point's longitude."""
1316 """!Sets the point's latitude
1317 @param val The new latitude in degrees North."""
1320 """!Sets the point's longitude.
1321 @param val The new longitude in degrees East"""
1326 nscenter=property(getlat,setlat,
None,
1327 """The latitude of this fixed location.""")
1331 ewcenter=property(getlon,setlon,
None,
1332 """The longitude of this fixed location.""")
1334 def clatlon(center,res,size,n,scan=136,name=None):
1335 """!Create a GRIBGridCompute that makes a lat-lon grid.
1337 Returns a GRIBGridCompute that will produce a lat-lon grid
1338 centered on the given object. The provided object must have
1339 nscenter and ewcenter properties that produce real lats and lons
1340 that are positive North and positive East. The res parameter is a
1341 two element array containing the resolution in degrees.
1343 @param name the new grid's name
1344 @param center An object on which to center. Must have nscenter and ewcenter
1346 @param res The GRIB1 grid 255 resolution information in a two-element array.
1347 @param size The size parameter is a two-element array containing the
1349 @param n The n parameter contains the number of gridpoints.
1350 @param scan The "scan" parameter is the scanning mode parameter: 128
1351 means E-W are reversed, 64 means N-S are reversed, and 32 means
1352 the data is transposed.
1354 @note All three, res, size and n, are two element arrays with the
1355 N-S value first and the E-W value second. These are turned into
1356 a GRIB1 grid 255 specification."""
1357 assert(len(n)==2
and n[0]>0
and n[1]>0)
1358 assert(len(size)==2
and size[0]>0
and size[1]>0)
1359 assert(scan>=0
and scan<=255)
1360 assert(len(res)==2
and res[0]>0
and res[1]>0)
1362 name=
'clatlon%dx%dp'%(int(n[0]),int(n[1]))
1363 return GRIBGridCompute(name,action_clatlon,center,res[0],res[1],size[0],
1364 size[1],n[0],n[1],scan)
1367 """!A GRIBBase that subsets GRIB files, keeping only certain parameters."""
1368 def __init__(self,subsetname,grib1sub=None,grib2sub=None):
1369 """!GRIBSubsetter constructor.
1371 Creates a GRIBSubsetter with a given name, a callable
1372 object grib1sub that will be sent to
1373 produtil.gribop.grib1subset, and an unused grib2sub that will
1374 be used for GRIB2 subsetting one day.
1375 @param grib1sub Callable object that iterates over
1376 wgrib -s output and yields only fields that should be kept,
1377 potentially in a new order.
1378 @param grib2sub Unsupported: GRIB2 subsetter.
1379 @param subsetname The subsetname is mandatory and will be used to
1380 generate temporary filenames."""
1381 super(GRIBSubsetter,self).
__init__()
1386 """!Returns True. The subsetter is its own product, so it is
1388 @param args,kwargs Ignored, but used by subclasses. """
1391 """!Returns True. The subsetter's product (itself) does not
1392 vary with the kwargs, so any input is valid.
1393 @param kwargs Ignored, but used by subclasses."""
1396 """!Returns self. The subsetter is its own product.
1397 @param args,kwargs Ignored, but used by subclasses."""
1400 """!Returns a name of this subset for use in filenames."""
1403 """!Returns an iterator that takes as its only argument an
1404 array of lines of wgrib -s output."""
1407 """!This is a placeholder for future GRIB2 subsetting
1413 subsetname=property(getsubsetname,
None,
None,
1414 """The name of this GRIB1/2 subset. This is used to generate
1415 output filenames.""")
1420 grib1sub=property(getgrib1sub,
None,
None,
1421 """A callable object to send to produtil.gribop.grib1subset's
1422 subsetter argument.""")
1426 grib2sub=property(getgrib2sub,
None,
None,
1427 """GRIB2 subsetting information, currently unused.""")
1430 """!This class grabs a GRIBSubsetter from a RegribMany object."""
1432 """!GRIBSubsetterFetcher constructor
1433 @param name the name of the subset"""
1436 """!Calls kwargs['regribmany'].input_valid to see if the kwargs
1438 @param kwargs Contains a regribmany key mapping to a RegribMany object"""
1439 source=kwargs[
'regribmany']
1441 return source.input_valid(self.
_name,**kwargs)
1443 """!Calls kwargs['regribmany'].has_data to see if the operation
1444 has produced its subsetter yet.
1445 @param kwargs Contains a regribmany key mapping to a RegribMany object.
1446 Is also passed to has_data
1447 @param args Additional positional arguments passed to has_data"""
1448 source=kwargs[
'regribmany']
1450 return source.has_data(self.
_name,*args,**kwargs)
1452 """!Calls kwargs['regribmany'].make to produce the subsetter.
1453 @param args,kwargs Passed to source.make. The meaning
1454 is implementation-specific, but generally the kwargs are
1455 used for string replacement in an hwrf.config.HWRFConfig"""
1456 source=kwargs[
'regribmany']
1458 return source.make(self.
_name,**kwargs)
1463 """!This is the abstract base class for all GRIB1 and GRIB2 files
1464 and operators. It should never be instantiated directly."""
1466 """!Creates a GRIBOp that has a number of child GRIBBase
1467 objects, with a specified action to perform in the GRIBOp.make
1468 method. The action should be a callable object that takes as
1469 input a Regrib, the contents of args and any keyword arguments
1471 @param action the function that performs the operation
1472 @param args arguments to the action"""
1474 self.
_args=list(args)
1476 """!Returns the action, a function or callable object."""
1479 """!Iterates over all child GRIBBase objects."""
1480 for arg
in self.
_args:
1485 action=property(getaction,
None,
None,
1486 """Returns the callable object that performs this object's work""")
1488 """!Returns the logical "and" of is_ready(*args,**kwargs)
1489 called on all subobjects.
1490 @param args,kwargs Passed to arg.is_ready. The meaning
1491 is implementation-specific, but generally the kwargs are
1492 used for string replacement in an hwrf.config.HWRFConfig"""
1493 for arg
in self.
args():
1494 if not arg.is_ready(*args,**kwargs):
1498 """!Returns the logical "and" of input_valid(**kwargs) called
1500 @param kwargs Passed to source.has_data. The meaning
1501 is implementation-specific, but generally the kwargs are
1502 used for string replacement in an hwrf.config.HWRFConfig"""
1503 for arg
in self.
args():
1504 if not arg.input_valid(**kwargs):
1508 """!Runs the action specified in the constructor, providing as
1509 arguments regrib, and the result of running make on all of the
1510 other arguments sent to the constructor.
1511 @param regrib a Regrib for data storage
1512 @param kwargs Passed to the action. The meaning
1513 is implementation-specific, but generally the kwargs are
1514 used for string replacement in an hwrf.config.HWRFConfig"""
1516 for arg
in self.
args():
1517 result=arg.make(regrib,**kwargs)
1518 assert(result
is not None)
1519 assert(isinstance(result,GRIBBase))
1521 return self.
_action(self,regrib,*args,**kwargs)
1523 """!A string representation of this GRIB operation."""
1524 return '<%s %s %s>'%(type(self).__name__,repr(self.
_action),
1525 ','.join([repr(x)
for x
in self.
args()]))
1528 """!This subclass of GRIBOp produces GRIB2 files, and can be
1529 converted to GRIB1 via obj*GRIB1 or obj.to_grib1(). Calls to
1530 obj.to_grib2() or obj*GRIB2 simply return self."""
1532 """!GRIB2Op constructor
1533 @param action,args Passed to GRIBOp.__init__"""
1534 super(GRIB2Op,self).
__init__(action,*args)
1536 """!Returns a GRIB2Op that converts this operation's output to GRIB1"""
1537 return GRIB2Op(action_grib2to1,self)
1539 """!Returns self (converting GRIB2 to GRIB2 is a no-op)"""
1542 """!If grid is the special constant GRIB1, this is the same as to_grib1(),
1543 if GRIB2, then returns self. Otherwise, returns NotImplemented to indicate
1544 that GRIB2 regridding is not implemented yet.
1545 @param grid The constant GRIB1, GRIB2, or a GRIBGrid"""
1550 return NotImplemented
1553 """!This subclass of GRIBOp produces GRIB1 files. It introduces a
1554 number of convenience calls:
1556 * file1 + file2 + file3 = a copygb merge of the three files
1557 * file1*grid = copygb interpolate file1 to the specified GRIBGrid
1558 * file1*GRIB2 = convert to GRIB2
1559 * file1*GRIB1 = no-op (returns self)
1560 * file1/subsetter = subsets the GRIB1 file using the given GRIBSubsetter
1562 These can be combined, of course, and follow the usual Python
1563 order of precedence:
1565 * (file1*grid + file2*grid + file3/subsetter*grid)*GRIB1
1567 As with the GRIB2Op, there are also to_grib1() and to_grib2()
1568 methods which return self, and a GRIB2 conversion of self,
1571 """!Creates a new GRIB1Op, passing all arguments to the
1572 superclass constructor.
1573 @param action,args Passed to GRIBOp.__init__"""
1574 super(GRIB1Op,self).
__init__(action,*args)
1576 """!Returns self. The GRIB1Op already produces a GRIB1 file."""
1579 """!Returns a GRIB2Op that will make a GRIB2 version of this
1580 operation's output."""
1581 return GRIB2Op(action_grib1to2,self)
1583 """!Returns a GRIB1Op that will ask copygb to merge the other
1584 grid on top of this one.
1585 @param grid The target grid (GRIBGrid) for both objects
1586 @param other The other GRIB1 file producer to regrid. """
1587 if not isinstance(grid,GRIBGridBase):
1589 'First argument to GRIB1Op.regridmerge must be a '
1590 'GRIBGridBase subclass, not a %s.'
1591 %(type(grid).__name__,))
1592 return GRIB1Op(action_grib1regridmerge,grid,self,other.to_grib1())
1594 """!Returns a GRIB1Op that will run grbindex and save the
1595 results, unless that has already been done."""
1596 return GRIB1Op(action_grbindex,self)
1598 """!Returns a GRIB1Op that will subset this one using the
1599 specified subsetter.
1600 @param subsetter a GRIBSubsetter to do the subsetting."""
1601 if isinstance(subsetter,GRIBSubsetter):
1602 return GRIB1Op(action_grib1subset,self,subsetter)
1603 return NotImplemented
1605 """!If the grid is a GRIBGridBase, returns a GRIB1Op that will
1606 regrid this GRIB1Op's output to that grid. If grid is the
1607 special constant GRIB2, returns self.to_grib2. If it is the
1608 constant GRIB1, returns self.to_grib1. Otherwise, returns
1610 @param grid Constants GRIB1, GRIB2, or a GRIBGridBase"""
1611 if isinstance(grid,GRIBGridBase):
1612 return GRIB1Op(action_grib1regrid,self,grid)
1617 return NotImplemented
1619 """!If the argument is a GRIBOp, returns a GRIB1Op that will
1620 paste a GRIB1 version of that operations output onto this
1621 operation's output. For any other argument type, returns
1623 @param other a GRIBOp whose output will be interpolated
1624 on top of this one."""
1625 if isinstance(other,GRIBOp):
1626 return GRIB1Op(action_grib1merge,self,other.to_grib1())
1627 return NotImplemented
1632 """!The GRIB1Fetcher is a GRIB1Op subclass that fetches a GRIB1
1633 file from a RegribMany."""
1635 """!Creates a GRIB1Fetcher for the specified operation name.
1636 @param name the name of this operation for temporary filename
1640 """!Calls kwargs['regribmany'].input_valid to determine if the
1641 specified keyword arguments make a valid input to the
1643 @param kwargs Contains a regribmany key mapping to a RegribMany object.
1644 Is also passed to source.input_valid"""
1645 source=kwargs[
'regribmany']
1647 return source.input_valid(self.
_name,**kwargs)
1649 """!Calls kwargs['regribmany'].has_data to see if there is
1650 cached output from the operation.
1651 @param kwargs Contains a regribmany key mapping to a RegribMany object.
1652 Is also passed to source.has_data.
1653 @param args Positional arguments passed to source.has_data"""
1654 source=kwargs[
'regribmany']
1656 return source.has_data(self.
_name,*args,**kwargs)
1658 """!Calls kwargs['regribmany'].make to produce the operation's
1660 @param kwargs Contains a regribmany key mapping to a RegribMany object.
1661 Is also passed to source.make.
1662 @param args Additional positional arguments are unused."""
1663 source=kwargs[
'regribmany']
1665 return source.make(self.
_name,**kwargs)
1668 """!This subclass of GRIB1Op represents a GRIB1 file on disk that
1669 is ALREADY PRESENT. Its is_ready function is overridden to assume
1670 the file is always ready, and its "make" method simply returns
1672 def __init__(self,grib1file,grib1index,grib1grid,
1673 nscenter=
None,ewcenter=
None,grib1grbindex=
None):
1674 """!GRIB1File constructor.
1675 @param grib1file The file path.
1676 @param grib1index Path to the wgrib -s output
1677 @param grib1grid Grid information.
1678 @param nscenter,ewcenter Latitude and longitude of the grid center point,
1679 in degrees North and East
1680 @param grib1grbindex Path to the grbindex output."""
1681 super(GRIB1File,self).
__init__(
None)
1686 if not (ewcenter
is None or float(ewcenter)
is not None):
1687 raise TypeError(
'ewcenter must be None, or an int or float, not a %s (ewcenter=%s)'
1688 %(ewcenter.__class__.__name__,repr(ewcenter)))
1689 if not (nscenter
is None or float(nscenter)
is not None):
1690 raise TypeError(
'nscenter must be None, or an int or float, not a %s (nscenter=%s)'
1691 %(nscenter.__class__.__name__,repr(nscenter)))
1696 """!Returns True. The file is already present, so any kwargs
1698 @param kwargs Ignored."""
1701 """!Returns True. The operation is ready to run because it has
1702 nothing to do: the file is already present.
1703 @param args,kwargs Ignored."""
1706 """!Returns self. This class represents a GRIB1 file, so it is
1708 @param args,kwargs Ignored."""
1711 """!Returns the domain center latitude."""
1714 """!Returns the domain center longitude."""
1717 """!Returns the GRIB1 file's location."""
1720 """!Returns the location of the file that stores the output of
1724 """!Returns the location of the file that stores the output of
1725 the grbindex program run on the GRIB1 file."""
1728 """!Sets the location of the file that stores the output of
1729 the grbindex program run on the GRIB1 file."""
1732 """!Returns the GRIB1 grid information as a string."""
1735 """!Returns the output of wgrib -s run on this file, which may
1736 be from cached data.
1737 @param regrib a Regrib for data storage"""
1741 if indexfile
is None or not os.path.exists(indexfile):
1742 indexfile=regrib.indextemp(self.
grib1file)
1743 index=runstr(regrib.wgrib[
'-s',self.
grib1file])
1744 with open(indexfile,
'wt')
as f:
1747 with open(indexfile,
'rt')
as f:
1754 resultfile=property(getgrib1file,
None,
None,
1755 'The path to the result file, in this case the GRIB1 file.')
1759 grib1file=property(getgrib1file,
None,
None,
1760 'The path to the GRIB1 file which is assumed to already exist.')
1764 grib1index=property(getgrib1index,
None,
None,
1765 'Either None or the wgrib -s index file for the GRIB1 file.')
1769 grib1grbindex=property(getgrib1grbindex,setgrib1grbindex,
None,
1770 'Either None or the grbindex binary index file for the GRIB1 file.')
1774 grib1grid=property(getgrib1grid,
None,
None,
1775 "Either None or the copygb -g argument data for the GRIB1 file's grid")
1779 nscenter=property(getnscenter,
None,
None,
1780 'Returns None or the center latitude of this GRIB1 file.')
1784 ewcenter=property(getewcenter,
None,
None,
1785 'Returns None or the center longitude of this GRIB1 file.')
1788 """!This subclass of GRIB2Op represents a GRIB2 file on disk that
1789 is ALREADY PRESENT. Its is_ready function is overridden to assume
1790 the file is always ready, and its "make" method simply returns
1793 """!GRIB2File constructor
1794 @param grib2file The grib2 file path.
1795 @param grib2index The grib 2 index file path.
1796 @param grib2grid GRIB2 grid information."""
1797 super(GRIB2File,self).
__init__(
None)
1802 """!Returns True. The operation is ready to run because it has
1803 nothing to do: the file is already present.
1804 @param args,kwargs Ignored."""
1807 """!Returns True. The file is already present, so any kwargs
1809 @param kwargs Ignored."""
1812 """!Returns self. This class represents a GRIB2 file, so it is
1814 @param args,kwargs Ignored."""
1817 """!Returns the GRIB2 file's location."""
1820 """!This is a placeholder for future development. It returns
1821 the grib2index argument from the constructor."""
1824 """!This is a placeholder for future development. It returns
1825 the grib2grid argument from the constructor."""
1830 resultfile=property(getgrib2file,
None,
None,
1831 'The path to the result file, in this case the GRIB2 file.')
1835 grib2file=property(getgrib2file,
None,
None,
1836 'The path to the GRIB2 file which is assumed to already exist.')
1840 grib2index=property(getgrib2index,
None,
None,
1841 'This is a placeholder for future GRIB2 subsetting support')
1845 grib2grid=property(getgrib2grid,
None,
None,
1846 "This is a placeholder for future GRIB2 regridding support")
1849 """!This subclass of GRIB1Op and UpstreamFile represents a GRIB1
1850 file that is produced by an upstream workflow. The is_ready
1851 subroutine calls self.check to check the modification time and
1852 file size. The make subroutine copies the file to a local
1855 """!UpstreamGRIB1 constructor
1856 @param dstore the produtil.datastore.Datastore for database info
1857 @param args,kwargs All other arguments passed to produtil.datastore.UpstreamFile.__init__"""
1858 UpstreamFile.__init__(self,dstore,*args,**kwargs)
1859 GRIB1Op.__init__(self,
None)
1861 """!Runs the check function on the upstream product, and
1862 returns its results. If the frominfo argument is in kwargs,
1863 it is passed as the first positional parameter to check.
1864 @param kwargs The frominfo argument to UpstreamFile.check()
1865 @param args Additional positional arguments are ignored."""
1866 if 'frominfo' in kwargs:
1867 return self.
check(kwargs[
'frominfo'])
1872 @param kwargs Keyword arguments are ignored."""
1874 def make(self,regrib,*args,**kwargs):
1875 """!Calls deliver_file to copy the file to a temporary location
1876 decided by regrib.gribtemp. Returns a GRIB1File for that
1878 @param regrib a Regrib for data storage
1879 @param args,kwargs All other arguments are ignored."""
1881 (filename,index)=regrib.gribtemp(
'upstream.'+os.path.basename(loc))
1886 resultfile=property(UpstreamFile.getlocation,
None,
None,
1887 'The path to the result file, in this case self.location.')
1890 """!This object produces a GRIB1Op from a call to a Task object's
1891 Task.product. This is the class that underlies the implementation
1894 """!Creates a GRIB1Selector for the specified task.
1896 @param task The task whose products function is called.
1897 @param kwargs All other arguments are sent to task.products."""
1901 """!Returns True if the task's product is available.
1902 @param kwargs All keyword arguments are sent to select()"""
1903 product=self.
select(kwargs)
1904 return product.is_available()
1906 """!Returns True if select() is able to find a product and
1907 False if NoProductError is raised.
1908 @param kwargs Keyword arguments are passed to select()"""
1910 product=self.
select(kwargs)
1912 except NoProductError:
1915 """!Calls self.select(kwargs) to get the product, and calls
1917 @param regrib A Regrib for data storage
1918 @param kwargs Keyword arguments are passed to select()"""
1919 product=self.
select(kwargs)
1920 if not isinstance(product,GRIB1Op):
1922 return product.make(regrib,**kwargs)
1924 """!Attempts to attain a Product from the supplied Task.
1927 Calls a Task's products function to get the Product of
1928 interest. The kwargs is a dict of keyword arguments to pass
1929 to task.products. Those will override any keyword arguments
1930 that were sent to the constructor. If more than one Product
1931 is yielded, then ProductAmbiguityError is raised. If no
1932 Product is yielded, NoProductError is raised. If the returned
1933 Product is not a GRIBBase, TypeError is raised. Otherwise,
1934 the result is returned.
1936 @param kwargs a dict to pass to task.products"""
1939 products=[p
for p
in self._task.products(**arg)]
1941 raise ProductAmbiguityError(
'Specified arguments produced more than one product.')
1942 elif len(products)==0:
1943 raise NoProductError(
'Specified arguments produced no product.')
1946 if not isinstance(p,GRIBBase):
1948 'ERROR: in GRIB1Selector, a Task.products call '
1949 'returned something that was not a GRIBBase object. '
1950 'It returned a %s %s.'%(type(p).__name__,repr(p)))
1953 """!Returns a Pythonic representation of self"""
1954 return '%s(%s)'%(self.__class__.__name__,self._task.__class__.__name__)
1957 """!This is a convenient alias for the GRIB1Selector constructor.
1958 @param task,kwargs Passed to GRIB1Selector.__init__()"""
1964 """!This class represents a GRIB2 file that is produced by this
1965 workflow. It is a direct subclass of both GRIB2File and
1968 """!Creates a new GRIB2Product.
1970 @param dstore The dstore is the produtil.datastore.Datastore
1971 for database storage.
1972 @param args,kwargs All other arguments are passed on to
1973 FileProduct's constructor.
1974 @note The GRIB2File constructor is initialized with None for
1975 the file, index and grid."""
1976 assert(
'location' in kwargs
and kwargs[
'location']!=
'' )
1977 FileProduct.__init__(self,dstore,*args,**kwargs)
1978 GRIB2File.__init__(self,
None,
None,
None)
1982 """!Returns True. Since this object is already its product,
1983 any kwargs make a valid input.
1984 @param kwargs Ignored."""
1987 """!Calls self.check to see if the product is available.
1989 @param args Additional positional arguments are ignored.
1990 @param kwargs Additional keyword arguments. If frominfo is in
1991 the kwargs, it is passed as the first positional argument to
1993 if 'frominfo' in kwargs:
1994 return self.
check(kwrargs[
'frominfo'])
1997 def make(self,regrib,*args,**kwargs):
1998 """!Calls deliver_file to copy the file to a new temporary
1999 location from regrib.gribtemp. Returns a GRIB2File for that
2001 @param regrib A Regrib for data storage
2002 @param args,kwargs All other arguments are ignored."""
2004 (filename,index)=regrib.gribtemp(
'prod.'+os.path.basename(loc))
2008 """!Sets the grib2 grid information.
2009 @param grid GRIB2 grid information."""
2010 if grid
is None or grid==
'' or grid==
'None':
return
2011 self[
'grib2grid']=grid
2013 """!Returns the grib2 grid information."""
2014 return self.
get(
'grib2grid',
None)
2016 """!Clears the grib2 grid information."""
2017 del self[
'grib2grid']
2021 grib2grid=property(getgrib2grid,setgrib2grid,delgrib2grid,
2022 """The GRIB2 grid information if known.""")
2025 """!Sets the grib2 index information."""
2026 if index
is None or index==
'' or index==
'None':
return
2027 self[
'grib2index']=index
2029 """!Gets the grib2 index information, or returns None if unknown."""
2030 return self.
get(
'grib2index',
None)
2032 """!Cleares the stored information about the index location.
2033 Does NOT delete the index file."""
2034 del self[
'grib2index']
2038 grib2index=property(getgrib2index,setgrib2index,delgrib2index,
2039 """The disk location of the GRIB2 index file.""")
2042 """!Returns the location of the GRIB2 file from self.location."""
2045 """!Sets the location of the GRIB2 file by setting self.location."""
2050 grib2file=property(getgrib2file,setgrib2file,
None,
2051 """Synonym for self.location""")
2055 resultfile=property(getgrib2file,setgrib2file,
None,
2056 """Synonym for self.location""")
2058 def deliver(self,location=None,index=None,grbindex=None,frominfo=None,
2059 keep=
True,logger=
None):
2060 """!Delivers a GRIB2 file to its destination. May also deliver
2061 other files associated with that GRIB2 file.
2063 @param location Delivery location.
2064 @param index Index file delivery location
2065 @param grbindex Ignored.
2066 @param frominfo Either a source filename, or a GRIB2Op.
2067 @param keep If True, the source file will be copied instead of moved.
2068 @param logger A logging.Logger for log information."""
2069 if isinstance(frominfo,basestring):
2071 FileProduct.deliver(self,location=location,frominfo=frominfo,
2074 elif not isinstance(frominfo,GRIB2Op):
2076 'GRIB2Product.deliver requires a frominfo that is either '
2077 'a string filename or a GRIB2Op.')
2080 with self.dstore.transaction():
2081 loc=location if(location
is not None)
else self.
location
2084 '%s: no location known when delivering product. '
2085 'Specify a location to deliver().'%(self.
did))
2086 (fromindex,toindex)=(
None,
None)
2088 fromindex=frominfo.grib2index
2089 except AttributeError, KeyError:
pass
2091 fromloc=frominfo.grib2file
2092 except AttributeError, KeyError:
2093 fromloc=frominfo.resultfile
2094 toindex=str(index)
if (index
is not None)
else '%s.wgrib_s'%(loc,)
2097 assert(fromloc
is not None and fromloc!=
'')
2098 assert(loc
is not None and loc!=
'')
2102 if fromindex
is not None and toindex
is not None and \
2109 with self.dstore.transaction():
2114 except AttributeError,KeyError:
pass
2119 """!Deletes the delivered GRIB2 file and discards the index and
2120 grid information."""
2122 if loc
is not None and loc!=
'':
2125 with self.dstore.transaction():
2133 """!This class represents a GRIB1 file produced by this workflow.
2134 It stores grid information, if available, and will also deliver an
2135 index file if one exists. It is a direct subclass of both
2136 FileProduct and GRIB1File."""
2138 """!Creates a new GRIB1Product.
2140 @param dstore The dstore is the produtil.datastore.Datastore.
2141 @param args Positional arguments, passed to the FileProduct
2143 @param kwargs Keyword arguments. The kwargs must specify the
2144 file location as a non-empty string.
2146 @note The GRIB1File is initialized with the various indexes
2147 and grid missing (None)."""
2148 assert(
'location' in kwargs
and kwargs[
'location']!=
'' )
2149 FileProduct.__init__(self,dstore,*args,**kwargs)
2150 GRIB1File.__init__(self,
None,
None,
None)
2154 """!Returns True. This object is its own product, so any
2156 @param kwargs Keyword arguments are ignored."""
2159 """!Runs self.check and returns the result.
2160 @param args Positional arguments are ignored.
2161 @param kwargs Keyword arguments. If frominfo is in kwargs, it
2162 is sent as the first positional argument to check."""
2163 if 'frominfo' in kwargs:
2164 return self.
check(kwargs[
'frominfo'])
2167 def make(self,regrib,*args,**kwargs):
2168 """!Gets a temporary filename from gribtemp, and copies the
2169 GRIB1 file there. Returns a new GRIB1File object for that
2171 @param regrib A Regrib for data storage
2172 @param args,kwargs All other arguments are ignored."""
2174 (filename,index)=regrib.gribtemp(
'prod.'+os.path.basename(loc))
2179 """!Sets the GRIB1 grid information; modifies the grib1grid
2180 metadata in the datastore.
2181 @param grid the new grid information"""
2182 self[
'grib1grid']=grid
2184 """!Returns the GRIB1 grid information from the grib1grid
2185 metadata in the datastore."""
2186 return self.
get(
'grib1grid',
None)
2188 """!Discards GRIB1 grid information by removing the grib1grid
2189 metadata from the datastore."""
2190 del self[
'grib1grid']
2194 grib1grid=property(getgrib1grid,setgrib1grid,delgrib1grid,
2195 """The GRIB1 grid (GDS) information if known.""")
2198 """!Sets the output location of grbindex to the given location,
2199 and sets the grib1grbindex metadata value.
2200 @param index Location of the grbindex output."""
2201 self[
'grib1grbindex']=index
2203 """!Returns the output location of grbindex from the
2204 grib1grbindex metadata value."""
2205 return self.
get(
'grib1grbindex',
None)
2207 """!Cleares the stored information about the grbindex binary
2208 index file location for this GRIB1 product by deleting the
2209 grib1grbindex metadata value. Does NOT delete the grbindex
2211 del self[
'grib1grbindex']
2215 grib1grbindex=property(getgrib1grbindex,setgrib1grbindex,delgrib1grbindex,
2216 """The disk location of the GRIB1 grbindex binary index file.""")
2219 """!Sets the output location of wgrib -s and sets the
2220 grib1index metadata value.
2221 @param index Location of the wgrib -s output."""
2222 self[
'grib1index']=index
2224 """!Returns the output location of wgrib -s from the grib1index
2226 return self.
get(
'grib1index',
None)
2228 """!Cleares the stored information about the index location.
2229 Does NOT delete the index file."""
2230 del self[
'grib1index']
2234 grib1index=property(getgrib1index,setgrib1index,delgrib1index,
2235 """The disk location of the GRIB1 index file, from wgrib -s.""")
2238 """!Returns the GRIB1 file location from self.location."""
2241 """!Sets the GRIB1 file location. Same as setting self.location.
2242 @param val New file location."""
2247 grib1file=property(getgrib1file,setgrib1file,
None,
2248 """Synonym for self.location""")
2252 resultfile=property(getgrib1file,setgrib1file,
None,
2253 """Synonym for self.location""")
2255 def deliver(self,location=None,index=None,grbindex=None,
2256 frominfo=
None,keep=
True,logger=
None):
2257 """!Delivers the GRIB1 data, and possibly the various index
2260 If frominfo is supplied, then that file is
2261 delivered, and no other action is performed. Otherwise, the
2262 file is delivered from self.location to the supplied location,
2263 the grib1index is delivered to the same location with an added
2264 ".wgrib_s" extension and the grib1grbindex is delivered with a
2265 ".grbindex" extension.
2267 @param location GRIB file delivery location
2268 @param index Delivery wgrib -s output location
2269 @param grbindex Where to deliver the output of grbindex
2270 @param frominfo Source information; see above.
2271 @param keep If False, source files can be moved instead of copied.
2272 @param logger a logging.Logger for log messages."""
2273 if isinstance(frominfo,basestring):
2275 FileProduct.deliver(
2276 self,location=location,frominfo=frominfo,keep=keep)
2278 elif not isinstance(frominfo,GRIB1Op):
2279 raise TypeError(
'GRIB1Product.deliver requires a frominfo '
2280 'that is either a string filename or a GRIB1Op.')
2283 with self.dstore.transaction():
2284 loc=location if(location
is not None)
else self.
location
2287 '%s: no location known when delivering '
2288 'product. Specify a location to deliver().'
2290 (fromindex,toindex)=(
None,
None)
2292 fromindex=frominfo.grib1index
2293 except AttributeError, KeyError:
pass
2295 fromloc=frominfo.grib1file
2296 except AttributeError, KeyError:
2297 fromloc=frominfo.resultfile
2299 fromgrbindex=frominfo.grib1grbindex
2300 except AttributeError, KeyError:
2301 if fromloc.find(
'hwrftrk')>=0:
2302 raise NoIndexError(
'hwrf track input has no grib1grbindex')
2303 if fromgrbindex
is None and fromloc.find(
'hwrftrk')>=0:
2304 raise NoIndexError(
'hwrf track input has a grib1grbindex=None')
2305 toindex=str(index)
if (index
is not None)
else '%s.wgrib_s'%(loc,)
2306 togrbindex=str(grbindex)
if (grbindex
is not None) \
2307 else '%s.grbindex'%(loc,)
2310 assert(fromloc
is not None and fromloc!=
'')
2311 assert(loc
is not None and loc!=
'')
2315 if fromindex
is not None and toindex
is not None and \
2318 fromindex,toindex,keep=keep,logger=logger)
2322 if fromgrbindex
is not None and togrbindex
is not None and \
2325 fromgrbindex,togrbindex,keep=keep,logger=logger)
2328 if fromloc.find(
'hwrftrk')>=0:
2333 assert(havegrbindex)
2337 with self.dstore.transaction():
2343 except AttributeError,KeyError:
pass
2348 """!Undoes the effect of deliver(), removing the destination
2349 index files and GRIB file."""
2351 if loc
is not None and loc!=
'':
2357 with self.dstore.transaction():
def getgrib1grid(self)
Returns the GRIB1 (wgrib) style grid information, as sent to the constructor's grib1grid argument...
def make(self, regrib, kwargs)
Runs the action specified in the constructor, providing as arguments regrib, and the result of runnin...
def deliver_file
This moves or copies the file "infile" to "outfile" in a unit operation; outfile will never be seen i...
def delgrib1index(self)
Cleares the stored information about the index location.
def make(self, args, kwargs)
Calls kwargs['regribmany'].make to produce the operation's output.
def getgrib1sub(self)
Returns an iterator that takes as its only argument an array of lines of wgrib -s output...
def set_workprefix
Sets the work directory and filename prefix to the given value, or sets it to a reasonable default if...
def make(self, regrib, args, kwargs)
Calls deliver_file to copy the file to a temporary location decided by regrib.gribtemp.
def setlog(self, val)
Sets the logger.Logging object to use for logging messages.
def getprodargs(self)
Returns the array of arguments to send to the products iterators.
def action_grib1regrid(op, regrib, infile, ingrid, args, kwargs)
Regrids a GRIB1 file.
This class represents a GRIB2 file that is produced by this workflow.
Runs regrib operations on many input times, sending output to an hwrf.gribtask.GRIBTask.
def getgrib2grid(self)
This is a placeholder for future development.
def __init__
GRIBSubsetter constructor.
def getgrib1grid(self)
Returns the GRIB1 grid information as a string.
def setlon(self, val)
Sets the point's longitude.
Superclass of errors used by Regrib.
def __init__(self, name)
GRIBSubsetterFetcher constructor.
def GRIBOps(self)
Iterates over all GRIBOp operations yielding tuples containing the name and operation.
def __init__(self, action, args)
Creates a new GRIB1Op, passing all arguments to the superclass constructor.
def input_valid(self, kwargs)
Returns the logical "and" of input_valid(**kwargs) called on all subobjects.
def getprodkwargs(self)
Returns a dict of keyword arguments to send to the products iterators.
def getlog(self)
Returns the logger.Logging object to use for logging messages, or None if no logger was provided to t...
def delgrib1grbindex(self)
Cleares the stored information about the grbindex binary index file location for this GRIB1 product b...
This is the abstract base class for all GRIB1 and GRIB2 files and operators.
def getgrib1grbindex(self)
Returns the output location of grbindex from the grib1grbindex metadata value.
def getgrib2index(self)
This is a placeholder for future development.
def input_valid(self, name, kwargs)
Determines if it is possible to run the specified operation with the given keyword arguments...
def undeliver(self)
Deletes the delivered GRIB2 file and discards the index and grid information.
Raised when delivering data, but no location is provided.
A subclass of Product that represents file delivery.
The GRIB1Fetcher is a GRIB1Op subclass that fetches a GRIB1 file from a RegribMany.
def wgrib_s(self, regrib)
Returns the output of wgrib -s run on this file, which may be from cached data.
def __init__
GRIB1File constructor.
def names(self)
Iterates over the names provided to self.add(name,...) in the order they were added.
def remove_file
Deletes the specified file.
def deliver
Delivers a GRIB2 file to its destination.
Base class for the regridding object tree.
def getgrib1file(self)
Returns the GRIB1 file location from self.location.
def has_data(self, name, kwargs)
Returns True if there is a cached result for the specified operation.
def has_name(self, name)
Returns True if an operation by the given name exists.
def getgrib2file(self)
Returns the GRIB2 file's location.
def input_valid(self, kwargs)
Calls kwargs['regribmany'].input_valid to determine if the specified keyword arguments make a valid i...
def input_valid(self, kwargs)
Calls kwargs['regribmany'].input_valid to see if the kwargs make a valid input.
def getcnvgrib_g12(self)
Returns the cnvgrib -p32 -g12 command, which should be an ImmutableRunner.
def gribtemp
Returns a tuple (grib,index) containing a suggested GRIB1/2 filename and index filename.
def action_grib2to1(op, regrib, infile, args, kwargs)
Converts GRIB2 files to GRIB1.
def action_grbindex(op, regrib, ingrib, task=None, kwargs)
Runs the grbindex program on a GRIB1 file.
grib2index
This is a placeholder for future GRIB2 subsetting support.
def indextemp(self, grib)
Generates a temporary filename to use for the specified GRIB1/2 file's index file.
def is_grid(self, name)
Returns True if the name corresponds to a grid.
This subclass of GRIBOp produces GRIB1 files.
def make(self, args, kwargs)
Calls kwargs['regribmany'].make to produce the grid.
This subclass of GRIBOp produces GRIB2 files, and can be converted to GRIB1 via obj*GRIB1 or obj...
def __init__(self, name, action, args)
Creates a new GRIBGridCompute with the given name and action.
def to_grib2(self)
Returns a GRIB2Op that will make a GRIB2 version of this operation's output.
def is_ready(self, args, kwargs)
Returns True.
def to_grib2(self)
Returns self (converting GRIB2 to GRIB2 is a no-op)
def undeliver(self)
Undoes the effect of deliver(), removing the destination index files and GRIB file.
def __init__(self, action, args)
GRIB2Op constructor.
def action_grib1to2(op, regrib, infile, args, kwargs)
Converts GRIB1 file to GRIB2.
def input_valid(self, kwargs)
Returns True.
def input_valid(self, args, kwargs)
Returns the logical "or" of input_valid(**kwargs) called on all subobjects.
def action_grib1merge(op, regrib, in1, in2, kwargs)
Merges two GRIB1 files that must already have the same grid.
def checkrun(arg, logger=None, kwargs)
This is a simple wrapper round run that raises ExitStatusException if the program exit status is non-...
def tempfile
Creates a name of a temporary file.
def is_ready(self, args, kwargs)
Runs the check function on the upstream product, and returns its results.
def make(self, args, kwargs)
Returns self.
def is_ready(self, args, kwargs)
Calls kwargs['regribmany'].has_data to see if the specified operation has produced its grid...
def getgrib1file(self)
Returns the GRIB1 file's location.
def subset(self, name)
Returns a GRIBSubsetterFetcher object that will grab the GRIB subsetter with the given name...
def input_valid(self, kwargs)
Returns True.
def is_ready(self, args, kwargs)
Calls self.check to see if the product is available.
def action_grib1regridmerge(op, regrib, grid, in1, in2, kwargs)
Performs regridding and merges two files in a single operation.
def getwgrib(self)
Returns the wgrib command, which should be an ImmutableRunner.
def setgrib2index(self, index)
Sets the grib2 index information.
def setgrib2grid(self, grid)
Sets the grib2 grid information.
def make(self, kwargs)
Runs this Regrib object's operator's make function with the given keyword arguments, returning the results.
def to_com
Requests delivery to the com directory in file "location" of operation "name".
def __init__(self, _copy=None, workprefix=None, kwargs)
Creats a new RegribMany.
A GRIBBase that subsets GRIB files, keeping only certain parameters.
def is_ready(self, args, kwargs)
Returns True.
def getlat(self)
Returns the point's latitude.
def setsync_frequently(self, flag)
Sets the sync_frequently flag.
A shell-like syntax for running serial, MPI and OpenMP programs.
def setgrib2file(self, val)
Sets the location of the GRIB2 file by setting self.location.
def reset
Discards all temporary data, and re-initializes this object for the specified result name...
def make(self, regrib, kwargs)
Calls self.select(kwargs) to get the product, and calls make on the result.
def input_valid(self, kwargs)
Returns True.
def getgrib1index(self)
Returns the output location of wgrib -s from the grib1index metadata value.
def __div__(self, subsetter)
Returns a GRIB1Op that will subset this one using the specified subsetter.
def make_grbindex(self)
Returns a GRIB1Op that will run grbindex and save the results, unless that has already been done...
def args(self)
Iterates over all child GRIBBase objects.
def __enter__(self)
Has no effect.
This subclass of GRIB2Op represents a GRIB2 file on disk that is ALREADY PRESENT. ...
This is the abstract base class of Regrib and RegribMany and should not be instantiated directly...
def get
Alias for self.meta() Returns the value of the specified metadata key or returns default if it is uns...
def is_ready(self, args, kwargs)
Calls kwargs['regribmany'].has_data to see if there is cached output from the operation.
def make(self, regrib, args, kwargs)
Gets a temporary filename from gribtemp, and copies the GRIB1 file there.
This class represents a GRIBGrid that must be computed from some other input, usually a GRIB file...
This subclass of GRIB1Op and UpstreamFile represents a GRIB1 file that is produced by an upstream wor...
def isnonempty(filename)
Returns True if the filename refers to an existent file that is non-empty, and False otherwise...
def is_ready(self, args, kwargs)
Runs self.check and returns the result.
def is_ready(self, args, kwargs)
Returns the logical "or" of is_ready(*args,**kwargs) called on all subobjects.
def getgrib2file(self)
Returns the location of the GRIB2 file from self.location.
Stores products and tasks in an sqlite3 database file.
location
Read-write property, an alias for getlocation() and setlocation().
def to_intercom
Requests delivery to the intercom directory in file "location" of operation "name".
def __init__(self, task, kwargs)
Creates a GRIB1Selector for the specified task.
def make(self, args, kwargs)
Returns self.
def setgrib1grbindex(self, index)
Sets the output location of grbindex to the given location, and sets the grib1grbindex metadata value...
def __repr__(self)
A string representation of this GRIB operation.
def __init__(self, action, args)
Creates a GRIBOp that has a number of child GRIBBase objects, with a specified action to perform in t...
def is_ready(self, kwargs)
Returns True if this Regrib object's operator is "ready" (according to is_ready) and False otherwise...
This object produces a GRIB1Op from a call to a Task object's Task.product.
def is_ready(self, args, kwargs)
Returns True.
This abstract base class represents something that is able to produce a GRIBGrid object when make() i...
grib1grid
Read-only: either None or the copygb -g argument data for the GRIB1 file's grid.
def getlon(self)
Returns the point's longitude.
def getgrib2grid(self)
Returns the grib2 grid information.
def input_valid(self, kwargs)
Returns True.
def setgrib1index(self, index)
Sets the output location of wgrib -s and sets the grib1index metadata value.
def action_grib1subset(op, regrib, infile, subsetter, args, kwargs)
Subsets a GRIB1 file.
def input_valid(self, kwargs)
Returns True.
def __exit__(self, etype, evalue, traceback)
Has no effect.
def to_grib1(self)
Returns a GRIB2Op that converts this operation's output to GRIB1.
def make(self, name, kwargs)
Executes the operation previously stored in self.add(), passing it the given keyword arguments...
grib1file
Read-only: the path to the GRIB1 file which is assumed to already exist.
def getgrib1index(self)
Returns the location of the file that stores the output of wgrib -s.
def make(self, args, kwargs)
Calls kwargs['regribmany'].make to produce the subsetter.
def is_ready(self, kwargs)
Returns True if the task's product is available.
def reset(self)
Erases all cached results.
def input_valid(self, kwargs)
Returns True if select() is able to find a product and False if NoProductError is raised...
def input_valid(self, kwargs)
Returns True.
def add(self, name, arg, kwargs)
Adds the given generator "arg" under the specified name (in "name") to this object.
def is_ready(self, name, kwargs)
Determines if the specified operation is ready.
Represents a specific location on the earth as a latitude, longitude pair.
def is_ready(self, args, kwargs)
Returns True.
def select(self, kwargs)
Attempts to attain a Product from the supplied Task.
def __init__(self, dstore, args, kwargs)
UpstreamGRIB1 constructor.
def copy(self)
Returns a copy of self with no cached results.
def getgrib1grbindex(self)
Returns the location of the file that stores the output of the grbindex program run on the GRIB1 file...
def getsync_frequently(self)
Returns the value of the sync_frequently flag.
This class represents a GRIB1 file produced by this workflow.
def __init__
Creates a RegribBase.
This subclass of GRIB1Op represents a GRIB1 file on disk that is ALREADY PRESENT. ...
def getaction(self)
Returns the action, a function or callable object.
grib1index
Read-only: either None or the wgrib -s index file for the GRIB1 file.
def make(self, args, kwargs)
Returns self.
def nonGRIBOps(self)
Iterates over all non-GRIBOp operations yielding tuples containing the name and operation.
def __mul__(self, grid)
If the grid is a GRIBGridBase, returns a GRIB1Op that will regrid this GRIB1Op's output to that grid...
This class represents a GRIB1 or GRIB2 grid specification.
grib1grbindex
Mutable property: either None or the grbindex binary index file for the GRIB1 file.
def __mul__(self, grid)
If grid is the special constant GRIB1, this is the same as to_grib1(), if GRIB2, then returns self...
def __init__(self, dstore, args, kwargs)
Creates a new GRIB2Product.
def getgrib2index(self)
Gets the grib2 index information, or returns None if unknown.
This is a helper class intended to be used internally by RegribMany.
def deliver
Delivers the GRIB1 data, and possibly the various index files as well.
def __repr__(self)
Returns a Pythonic representation of self.
did
Read-only property, an alias for getid().
def setgrib1grbindex(self, here)
Sets the location of the file that stores the output of the grbindex program run on the GRIB1 file...
def __init__
Creates a GRIBGrid with a given name, a copygb -g style GRIB1 grid specification and a GRIB2 grid spe...
def __init__(self, grib2file, grib2index, grib2grid)
GRIB2File constructor.
def delgrib2grid(self)
Clears the grib2 grid information.
def checkgrib(regrib, filename)
Internal function for validating GRIB files.
def __init__(self, lat, lon)
FixedLocation constructor.
def input_valid(self, kwargs)
Returns True if the specified kwargs are valid and False otherwise.
def input_valid(self, kwargs)
Returns True if the specified kwargs are valid for this Regrib object's operator and False otherwise...
def input_valid(self, kwargs)
Returns True.
def getsubsetname(self)
Returns a name of this subset for use in filenames.
def input_valid(self, kwargs)
Calls kwargs['regribmany'].input_valid to see if the specified kwargs make a valid input to the opera...
def delgrib1grid(self)
Discards GRIB1 grid information by removing the grib1grid metadata from the datastore.
def make(self, regrib, kwargs)
Runs the action specified in the constructor, providing as arguments regrib, and the result of runnin...
def __init__(self, name)
GRIBGridFetcher constructor.
def __init__(self, dstore, args, kwargs)
Creates a new GRIB1Product.
def __add__(self, other)
If the argument is a GRIBOp, returns a GRIB1Op that will paste a GRIB1 version of that operations out...
def setlat(self, val)
Sets the point's latitude.
Exceptions raised by the hwrf package.
def __init__(self, name)
Creates a GRIB1Fetcher for the specified operation name.
def getop(self)
Returns the GRIBBase object that performs this Regrib's work.
def regridmerge(self, grid, other)
Returns a GRIB1Op that will ask copygb to merge the other grid on top of this one.
def getgrib2sub(self)
This is a placeholder for future GRIB2 subsetting support.
def deliveries
Iterates over all deliveries yielding a six element tuple.
def getgrib1grid(self)
Returns the GRIB1 grid information from the grib1grid metadata in the datastore.
def igrb1(task, kwargs)
This is a convenient alias for the GRIB1Selector constructor.
def call_callbacks
Calls all delivery callback functions.
This class represents a GRIBGrid that is stored in a RegribMany object.
def getnscenter(self)
Returns the domain center latitude.
def grid(self, name)
Returns a GRIBGridFetcher object that will grab the grid structure with the given name...
def __init__(self, result, op, workprefix=None, kwargs)
Creates a Regrib object whose result has the given name (in "result") and produces the output of the ...
def is_ready(self, args, kwargs)
Returns True if this object and its subobjects are all ready for a call to make, and False otherwise...
def getcopygb(self)
Returns the copygb ImmutableRunner.
def getgrib2grid(self)
This is a placeholder to return the GRIB2-style grid information.
def getcnvgrib_g21(self)
Returns the cnvgrib -g21 command, which should be an ImmutableRunner.
def delgrib2index(self)
Cleares the stored information about the index location.
def make(self, regrib, kwargs)
Runs the action this object should perform and returns another GRIBBase object.
def action_clatlon(op, regrib, name, center, nsres, ewres, nssize, ewsize, nscount, ewcount, scan, kwargs)
Generates a latitude-longitude grid centered on a GRIB file or specified point.
This class grabs a GRIBSubsetter from a RegribMany object.
def to_grib1(self)
Returns self.
def has_deliveries(self)
Returns True if there are any requested deliveries and False otherwise.
def check(self, kwargs)
Asks the product to check its own availability and update the database.
def setgrib1file(self, val)
Sets the GRIB1 file location.
def make(self, regrib, args, kwargs)
Calls deliver_file to copy the file to a new temporary location from regrib.gribtemp.
def make(self, args, kwargs)
Returns self.
op
The GRIBBase object that performs this Regrib's work.
def setgrib1grid(self, grid)
Sets the GRIB1 grid information; modifies the grib1grid metadata in the datastore.
def GRIB(self, name)
Returns a GRIB1Fetcher object that will grab the GRIB1 data with the given name.
def is_ready(self, args, kwargs)
Returns the logical "and" of is_ready(*args,**kwargs) called on all subobjects.
def getewcenter(self)
Returns the domain center longitude.
def is_ready(self, args, kwargs)
Calls kwargs['regribmany'].has_data to see if the operation has produced its subsetter yet...
Represents a Product created by an external workflow.
def clatlon
Create a GRIBGridCompute that makes a lat-lon grid.
grib2grid
This is a placeholder for future GRIB2 regridding support.
def getgridname(self)
Returns the name of this grid, as provided to the constructor.