29 import nwpservice.wps.namelistwps
30 import nwpservice.wps.ungrib
40 '''Class for managing preparation and execution of ungrib components
46 '''Initialises the class
60 wrfstart_time_str=None,
61 wrfstop_time_str=None,
65 '''Verifies that all expected grib files of type gfs_ctbto are
71 Full path to dir containing all expected grib files
73 Specific class of gfs_ctbto file (0.5, 1.0, 0.5.fv3)
74 wrfstart_time_str : str
75 Start time of WRF simulation in YYYYMMDDHH[mmss] format
76 wrfstop_time_str : str
77 Stop time of WRF simulation in YYYYMMDDHH[mmss] format
79 Expected interval (in hours) between GRIB files
84 Dictionary with 'verified' and 'missing files' keys
87 VALID_SUBTYPES = [
'1.0',
'0.5',
'0.5.fv3']
91 return_dict = {
'verified_correct' :
True,
'missing_files' : []}
93 GFS_CTBTO_FILENAME_PREFIX =
'GD'
96 if subtype
not in VALID_SUBTYPES:
97 raise ValueError(
'Invalid subtype: %s' % subtype)
100 wrfstart_time_str = wrfstart_time_str.ljust(14,
'0')
101 wrfstop_time_str = wrfstop_time_str.ljust(14,
'0')
104 wrfstart_dt = datetime.datetime.strptime(wrfstart_time_str,
106 wrfstop_dt = datetime.datetime.strptime(wrfstop_time_str,
116 curr_time_dt = wrfstart_dt
118 while curr_time_dt <= wrfstop_dt:
119 LOGGER.debug(
'Verifying: %s' % curr_time_dt)
121 year =
'%04d' % curr_time_dt.year
122 month =
"%02d" % curr_time_dt.month
123 day =
"%02d" % curr_time_dt.day
124 hour =
"%02d" % curr_time_dt.hour
125 fname = GFS_CTBTO_FILENAME_PREFIX + year[2:4] + month + day + hour
126 metpath = os.path.join(rootdir,
131 LOGGER.debug(
'Checking for: %s' % metpath)
132 if not os.path.exists(metpath):
133 return_dict[
'verified_correct'] =
False
134 LOGGER.warning(
'Unable to find metpath: %s' % metpath)
135 return_dict[
'missing_files'].append(metpath)
138 curr_time_dt += datetime.timedelta(hours=hour_intvl)
146 wrfstart_time_str=None,
147 wrfstop_time_str=None,
152 '''Verifies that all expected grib files of type ecmwf_ml are
158 Full path to dir containing all expected grib files
159 wrfstart_time_str : str
160 Start time of WRF simulation in YYYYMMDDHH[mmss] format
161 wrfstop_time_str : str
162 Stop time of WRF simulation in YYYYMMDDHH[mmss] format
164 Expected interval (in hours) between GRIB files
169 Dictionary with 'verified' and 'missing files' keys
174 return_dict = {
'verified_correct' :
True,
'missing_files' : []}
176 ECMWF_ML_FILENAME_PREFIX =
'EA'
179 wrfstart_time_str = wrfstart_time_str.ljust(14,
'0')
180 wrfstop_time_str = wrfstop_time_str.ljust(14,
'0')
183 wrfstart_dt = datetime.datetime.strptime(wrfstart_time_str,
185 wrfstop_dt = datetime.datetime.strptime(wrfstop_time_str,
195 curr_time_dt = wrfstart_dt
197 while curr_time_dt <= wrfstop_dt:
198 LOGGER.debug(
'Verifying: %s' % curr_time_dt)
200 year =
'%04d' % curr_time_dt.year
201 month =
"%02d" % curr_time_dt.month
202 day =
"%02d" % curr_time_dt.day
203 hour =
"%02d" % curr_time_dt.hour
204 fname = ECMWF_ML_FILENAME_PREFIX + year + month + day + hour
206 metpath = os.path.join(rootdir,
210 LOGGER.debug(
'Checking for: %s' % metpath)
211 if not os.path.exists(metpath):
212 return_dict[
'verified_correct'] =
False
213 LOGGER.warning(
'Unable to find metpath: %s' % metpath)
214 return_dict[
'missing_files'].append(metpath)
217 curr_time_dt += datetime.timedelta(hours=hour_intvl)
225 wrfstart_time_str=None,
226 wrfstop_time_str=None,
231 '''Verifies that all expected grib files of type ecmwf_sfc are
237 Full path to dir containing all expected grib files
238 wrfstart_time_str : str
239 Start time of WRF simulation in YYYYMMDDHH[mmss] format
240 wrfstop_time_str : str
241 Stop time of WRF simulation in YYYYMMDDHH[mmss] format
243 Expected interval (in hours) between GRIB files
248 Dictionary with 'verified' and 'missing files' keys
253 return_dict = {
'verified_correct' :
True,
'missing_files' : []}
255 ECMWF_SFC_FILENAME_PREFIX =
'EA'
258 wrfstart_time_str = wrfstart_time_str.ljust(14,
'0')
259 wrfstop_time_str = wrfstop_time_str.ljust(14,
'0')
262 wrfstart_dt = datetime.datetime.strptime(wrfstart_time_str,
264 wrfstop_dt = datetime.datetime.strptime(wrfstop_time_str,
274 curr_time_dt = wrfstart_dt
276 while curr_time_dt <= wrfstop_dt:
277 LOGGER.debug(
'Verifying: %s' % curr_time_dt)
279 year =
'%04d' % curr_time_dt.year
280 month =
"%02d" % curr_time_dt.month
281 day =
"%02d" % curr_time_dt.day
282 hour =
"%02d" % curr_time_dt.hour
283 fname = ECMWF_SFC_FILENAME_PREFIX + year + month + day + hour
285 metpath = os.path.join(rootdir,
289 LOGGER.debug(
'Checking for: %s' % metpath)
290 if not os.path.exists(metpath):
291 return_dict[
'verified_correct'] =
False
292 LOGGER.warning(
'Unable to find metpath: %s' % metpath)
293 return_dict[
'missing_files'].append(metpath)
296 curr_time_dt += datetime.timedelta(hours=hour_intvl)
302 wpswrf_distro_path=None,
303 working_scratch_rootdir=None,
304 start_time_dt=None, stop_time_dt=None,
306 ungrib_prefix='FILE',
307 vtable_custom_path=None,
308 grib_type=None, grib_subtype=None,
310 ungrib_output_stagedir=None):
312 '''Set up and run, via nwpservice module, instance of ungrib
316 wpswrf_distro_path : str
317 Full path to the WPS/WRF distribution to be used. This is assumed
318 to have been installed in a way that is compatible with the
320 working_scratch_rootdir : str
321 Full path to a directory (assumed to have already been created),
322 to be used as scratch space for setting up and running this
324 start_time_dt : datetime
325 Start time of GRIB retrieval
326 stop_time_dt : datetime
327 Stop time of GRIB retrieval
329 Interval (in hours) between GRIB files
331 (Optional, defaults to 'FILE') String to use for the ungrib
333 vtable_custom_path : str
334 (Optional) Path to a custom vtable to use for this instance
336 Type of grib file (this needs to be documented better)
338 Subtype of grib file (this needs to be documented better)
340 Full path to dir containing the GRIB files
341 ungrib_output_stagedir : str
342 (Optional) Full path to dir where ungribbed files will be staged.
343 If not specified, no staging will be done. If specified, we
344 assume the dir already exists.
349 Dictionary with manifest of the ungribbed files and the location
350 (if applicable) of staged files
354 LOGGER.debug(
'Start _run_single_ungrib()')
361 metdata_tmp_dir = os.path.join(working_scratch_rootdir,
362 'tmpmetdata-' + grib_type)
363 LOGGER.debug(
'metdata_tmp_dir: %s' % metdata_tmp_dir)
365 os.mkdir(metdata_tmp_dir, 0o755)
367 raise OSError(
'mkdir failed: %s' % metdata_tmp_dir)
380 namelist_wps_path = os.path.join(working_scratch_rootdir,
381 'namelist.wps_' + grib_type)
382 LOGGER.debug(
'namelist_wps_path: %s' % namelist_wps_path)
389 grib_subtype=grib_subtype,
390 grib_rootdir=grib_rootdir,
391 start_time_dt=start_time_dt,
392 end_time_dt=stop_time_dt,
393 hour_intvl=hours_intvl,
394 newdir=metdata_tmp_dir)
395 LOGGER.debug(
'links to grib files: %s' % os.listdir(metdata_tmp_dir))
400 start_time_str = start_time_dt.strftime(
'%Y%m%d%H%M%S')
401 end_time_str = stop_time_dt.strftime(
'%Y%m%d%H%M%S')
402 interval_secs = int(hours_intvl*3600)
405 section_data_dict = {
408 'start_date_list' : [start_time_str],
409 'end_date_list' : [end_time_str],
410 'interval_seconds' : interval_secs
413 'out_format' :
'WPS',
414 'prefix' : ungrib_prefix
418 myobj = nwpservice.wps.namelistwps.NamelistWpsWriter(
419 destpath=namelist_wps_path,
420 section_data_dict=section_data_dict,
423 LOGGER.debug(
'Writing namelist: %s' % namelist_wps_path)
428 domainpath = os.path.join(working_scratch_rootdir,
429 'ungrib_rundir_' + grib_type)
430 if grib_type ==
'gfs_ctbto':
432 vtable_userdef =
None
433 elif grib_type ==
'ecmwf_ml':
434 metdatatype =
'ecmwfml'
435 vtable_userdef=vtable_custom_path
436 elif grib_type ==
'ecmwf_sfc':
437 metdatatype =
'ecmwfsfc'
438 vtable_userdef=vtable_custom_path
440 raise ValueError(
'grib_type not yet supported here: %s' % grib_type)
441 ungrib_obj = nwpservice.wps.ungrib.Ungrib(
442 wpswrf_distro_path=wpswrf_distro_path,
443 wpswrf_rundir=domainpath,
444 namelist_wps=namelist_wps_path,
445 metdatadir=metdata_tmp_dir,
446 metdatatype=metdatatype,
447 vtable_userdef=vtable_custom_path,
448 output_dir=ungrib_output_stagedir,
453 output_manifest = ungrib_obj.run()
454 LOGGER.debug(
'output_manifest: %s' % output_manifest)
458 stage_success = ungrib_obj.stage_output(auxfiles=
False)
460 staging_dir = ungrib_output_stagedir
465 'ungrib_output_manifest' : output_manifest,
466 'staging_dir' : staging_dir,
467 'hours_intvl' : hours_intvl
470 LOGGER.debug(
'return_dict: %s' % return_dict)
479 start_time_dt=None, end_time_dt=None,
484 '''Sets up a dir of all expected GRIB files in a flat space
486 Ungrib ultimately needs to make links to all of the GRIB files so that
487 the links are all in the same directory. This sets up a dir beforehand
488 that gets them all (via links) into a single dir, simplifying the
489 setup of ungrib down the road
495 Type of grib file (this needs to be documented better)
497 Subtype of grib file (this needs to be documented better)
499 Full path to dir containing the GRIB files
500 start_time_dt : datetime
501 Start time of GRIB retrieval
502 stop_time_dt : datetime
503 Stop time of GRIB retrieval
505 Interval (in hours) between GRIB files
507 Full path to the dir containing the links in "flat file space"
508 Dir is assumed to already exist
516 VALID_METDATA_TYPES = [
'gfs_ctbto',
'ecmwf_sfc',
'ecmwf_ml']
518 if grib_type
not in VALID_METDATA_TYPES:
519 raise ValueError(
'Invalid grib_type: %s' % grib_type)
521 if not os.path.isdir(grib_rootdir):
522 raise ValueError(
'grib_rootdir not a directory: %s' % grib_rootdir)
524 if not os.path.isdir(newdir):
525 raise ValueError(
'newdir not a directory: %s' % newdir)
528 curr_time_dt = start_time_dt
529 while curr_time_dt <= end_time_dt:
530 LOGGER.debug(
'curr_time_dt: %s' % curr_time_dt)
536 if grib_type ==
'gfs_ctbto':
537 timestr = curr_time_dt.strftime(
'%y%m%d%H')
538 rel_path =
'%04d/%02d/%02d/%s/GD%8s' % \
539 (curr_time_dt.year, curr_time_dt.month,
540 curr_time_dt.day, grib_subtype,
543 full_path = os.path.join(grib_rootdir, rel_path)
544 LOGGER.debug(
'full_path: %s' % full_path)
546 link_name =
'GD%8s' % timestr
547 link_path = os.path.join(newdir, link_name)
548 LOGGER.debug(
'link_path: %s' % link_path)
549 elif grib_type ==
'ecmwf_ml':
550 timestr = curr_time_dt.strftime(
'%Y%m%d%H')
552 rel_path =
'%04d/%02d/%02d/EA%10s.ml' % \
553 (curr_time_dt.year, curr_time_dt.month,
554 curr_time_dt.day, timestr)
556 full_path = os.path.join(grib_rootdir, rel_path)
557 LOGGER.debug(
'full_path: %s' % full_path)
559 link_name =
'EA%10s.ml' % timestr
560 link_path = os.path.join(newdir, link_name)
561 LOGGER.debug(
'link_path: %s' % link_path)
562 elif grib_type ==
'ecmwf_sfc':
563 timestr = curr_time_dt.strftime(
'%Y%m%d%H')
565 rel_path =
'%04d/%02d/%02d/EA%10s.sfc' % \
566 (curr_time_dt.year, curr_time_dt.month,
567 curr_time_dt.day, timestr)
569 full_path = os.path.join(grib_rootdir, rel_path)
570 LOGGER.debug(
'full_path: %s' % full_path)
572 link_name =
'EA%10s.sfc' % timestr
573 link_path = os.path.join(newdir, link_name)
574 LOGGER.debug(
'link_path: %s' % link_path)
576 raise ValueError(
'Unsupported grib_type: %s' % grib_type)
580 os.symlink(full_path, link_path)
582 OSError(
"Failed to make link: %s" % link_path)
585 curr_time_dt += datetime.timedelta(hours=hour_intvl)