36 import logging, sys, os, getopt
46 """!Sets up the used parts of the produtil package. This does NOT
47 call produtil.setup.setup(). Instead, it installs the signal
48 handlers and sets up the Python logging module directly. No other
49 parts of the produtil package are initialized."""
54 global handler, logger
56 handler=logging.StreamHandler(sys.stderr)
57 handler.setFormatter(logging.Formatter(
58 'hwrf_revital:%(levelname)s:%(asctime)s: %(message)s',
60 logger=logging.getLogger()
61 logger.setLevel(logging.INFO)
62 logger.addHandler(handler)
82 PARA = (
'YES' == os.environ.get(
'PARAFLAG',
'YES') )
88 """!Sets tcvitals and message file locations for non-NCO runs."""
89 global tcvlocs, messagedir, inputs
91 "/scratch3/NCEPDEV/hwrf/noscrub/input/SYNDAT-PLUS",
92 "/scratch3/NCEPDEV/hwrf/noscrub/input/SYNDAT",
93 "/scratch1/portfolios/NCEPDEV/hwrf/noscrub/input/SYNDAT-PLUS",
94 "/scratch1/portfolios/NCEPDEV/hwrf/noscrub/input/SYNDAT",
95 "/lfs3/projects/hwrf-data/hwrf-input/SYNDAT-PLUS",
96 "/lfs3/projects/hwrf-data/hwrf-input/SYNDAT",
97 "/hwrf/noscrub/input/SYNDAT-PLUS",
98 "/hwrf/noscrub/input/SYNDAT",
99 "/gpfs/gp1/nco/ops/com/arch/prod/syndat/",
100 "/gpfs/tp1/nco/ops/com/arch/prod/syndat/",
103 "/scratch3/NCEPDEV/hwrf/noscrub/input/MESSAGES",
104 "/scratch1/portfolios/NCEPDEV/hwrf/noscrub/input/MESSAGES",
105 "/lfs1/projects/hwrf-vd/hwrf-input/MESSAGES",
106 "/com/hur/prod/inpdata"
108 if 'CASE_ROOT' in os.environ
and os.environ[
'CASE_ROOT']==
'FORECAST':
109 tcvlocs=[
'/com/arch/prod/syndat']
111 tcvlocs.append(
'/com/arch/prod/syndat')
115 usage_message=
'''hwrf_generate_vitals.py version 5.7.1
117 hwrf_generate_vitals.py 11L 2015
119 Generates cycle lists and other information from TCVitals data.
123 hwrf_generate_vitals.py [options] STORMID YEAR
125 The STORMID must be a capital, three-character storm identifier such
126 as 11L or 18E or 04S. The only valid basin letters are the ones found
127 in the tcvitals database.
129 The year must be four digits.
134 -W 14 => Set the "weak storm" threshold to 14 knots.
135 -n => Disable renumbering of invests to non-invests.
136 -N => Enable renaming of storms to last name seen.
137 -u => Unrenumber and unrename after renumbering and
138 renaming, discarding unrelated cycles
139 -R => Output data in Rocoto <cycledef> tags.
140 -H => Do not use. Special output format for HHS.
144 """!Prints a usage message on stderr and exits with status 1."""
145 sys.stderr.write(usage_message)
147 sys.stderr.write(
'\nSCRIPT IS ABORTING DUE TO ERROR: %s\n'%(why,))
153 """!Main program. Parses arguments, reads inputs, writes outputs."""
155 global logger, inputs, tcvlocs, messagedir, forecast, PARA
163 (optlist,args) = getopt.getopt(sys.argv[1:],
'HvnW:NuR')
164 for opt,val
in optlist:
166 logger.setLevel(logging.DEBUG)
167 logger.debug(
'Verbosity enabled.')
170 logger.debug(
'Weak storm threshold is now %d'%(threshold,))
173 logger.info(
'Disabling renumbering due to -n')
176 logger.info(
'Enabling renaming.')
179 logger.info(
'Enabling un-renumbering and un-renaming.')
180 elif opt==
'-H': format=
'HHS'
181 elif opt==
'-R': format=
'rocoto'
183 logger.error(
'Invalid option %s'%(opt,))
185 except (getopt.GetoptError,ValueError,TypeError)
as e:
189 if unrenumber
and format==
'tcvitals':
190 logger.info(
'Switching to "renumbering" format output.')
200 if 'COMINARCH' in os.environ:
201 tcvlocs = [ os.environ[
'COMINARCH'], ]
202 elif 'envir' in os.environ:
203 tcvlocs = [
'/com/arch/'+envir+
'/syndat', ]
205 fail(
'ERROR: Both $COMINARCH and $envir are unset in '
206 '$PARAFLAG=NO mode. Cannot find tcvitals.')
208 if 'mesagdir' in os.environ:
209 messagedir = [ os.environ[
'mesagdir'], ]
210 elif 'envir' in os.environ:
211 messagedir = [
'/com/hur/'+envir+
'/inpdata', ]
213 fail(
'ERROR: Both $mesagdir and $envir are unset in '
214 '$PARAFLAG=NO mode. Cannot find tcvitals.')
217 if 'CASE_ROOT' in os.environ
and os.environ[
'CASE_ROOT']==
'FORECAST':
220 inputs.extend([os.path.join(d,
'message%d'%(1+x,)) \
225 print>>sys.stderr,
'ERROR: Script requires at least two '\
226 'arguments: stormid and year'
229 stormid=str(args[0]).upper()
234 stormnum=int(stormid[0:2])
235 tcvyears_in=[ int(x)
for x
in str(args[1]).split()]
239 def check_test_vitals(vl):
240 """This is a replacement for hwrf.storminfo.name_number_okay for
241 use with TEST storms and internal stormids. It allows through
242 only the storm numbers matching stormnum, regardless of the
243 storm name (usually TEST and UNKNOWN would be dropped)."""
244 logger.info(
'Keeping only storm number %d in vitals'%(stormnum,))
246 if vital.stnum==stormnum:
248 elif getattr(vital,
'old_stnum',
'XX')==stormnum:
251 for tcvyear
in tcvyears_in:
252 if tcvyear
not in xset:
254 tcvyears.append(tcvyear)
256 if len(args)>2
and args[2]!=
'':
257 renumberlog=open(str(sys.argv[3]),
'wt')
262 for tcvyear
in tcvyears:
263 tcvfile=os.path.join(str(args[3]),
'syndat_tcvitals.%04d'%(tcvyear,))
264 if not os.path.isdir(tcvfile):
265 logger.error(
'%s: syndat file does not exist'%(tcvfile,))
267 inputs.append(tcvfile)
269 for tcvyear
in tcvyears:
270 for thatdir
in tcvlocs:
271 thatfile=os.path.join(thatdir,
'syndat_tcvitals.%04d'%(tcvyear,))
273 inputs.append(thatfile)
276 logger.debug(
'%s: empty or non-existent'%(thatfile,))
280 logger.info(
'List of input files: %s'%( repr(inputs), ))
281 logger.info(
'Read input files...')
282 revital.readfiles(inputs,raise_all=
False)
285 'Not renumbering because renumbering is disabled via -n')
286 logger.info(
'Cleaning up vitals instead.')
287 revital.clean_up_vitals()
289 logger.info(
'Renumber invests with weak storm threshold %d...'
291 revital.renumber(threshold=threshold,
292 discard_duplicates=unrenumber)
294 logger.info(
'Not renumbering invests when storm of '
295 'interest is 90-99.')
296 logger.info(
'Cleaning up vitals instead.')
297 revital.clean_up_vitals()
299 logger.info(
'Fake stormid requested. Running limited clean-up.')
300 revital.clean_up_vitals(name_number_checker=check_test_vitals)
301 if rename
and stormnum<50:
302 logger.info(
'Renaming storms.')
305 logger.info(
'Not renaming storms because storm id is >=50')
308 logger.info(
'Unrenumbering and unrenaming storms.')
309 revital.swap_numbers()
312 logger.info(
'Reformat vitals...')
313 if format==
'rocoto' and stormid==
'00X':
314 cycleset=set([ vit.YMDH
for vit
in revital ])
316 elif format==
'rocoto':
319 def okcycles(revital):
321 if vit.stormid3==stormid:
323 cycleset=set([ ymdh
for ymdh
in okcycles(revital) ])
326 revital.print_vitals(sys.stdout,renumberlog=renumberlog,
327 format=format,old=
True)
329 revital.print_vitals(sys.stdout,renumberlog=renumberlog,
330 stormid=stormid,format=format,old=
True)
331 except Exception
as e:
332 logger.info(str(e),exc_info=
True)
333 logger.critical(
'ERROR: %s'%(str(e),))
335 if __name__==
'__main__': main()
This module provides a set of utility functions to do filesystem operations.
def install_handlers
Installs signal handlers that will raise exceptions.
Sets up signal handlers to ensure a clean exit.
def cycles_as_entity(cycleset)
Returns a set of Rocoto XML tags to add to an XML file.
Defines the Revital class which manipulates tcvitals files.
def isnonempty(filename)
Returns True if the filename refers to an existent file that is non-empty, and False otherwise...
This module contains utilities for plugging HWRF into the Rocoto workflow manager.
This class reads one or more tcvitals files and rewrites them as requested.