29 import nwpservice.wps.namelistwps
30 import nwpservice.wps.metgrid
40 '''Class for managing preparation and execution of metgrid components
46 wpswrf_distro_path=None,
52 ungribbed_data_dict=None,
53 geogrid_data_dict=None,
54 custom_metgrid_tbl_path=None,
59 '''Check and initialise the class
64 wpswrf_distro_path : str
65 (Optional) Full path to the WPS/WRF distribution to be used.
66 This is assumed to have been installed in a way that is compatible
67 with the nwpservice module. If arg is not present, uses a default
70 (Optional) Full path to a directory (assumed to have already
71 been created), to be used as scratch space for setting up and
72 running this metgrid instance. If arg is not present, uses a
74 start_time_dt : datetime
75 Time of first ungribbed file(s)
76 stop_time_dt : datetime
77 Time of last ungribbed file(s)
79 Interval (in hours) between ungribbed files
81 Number of domain nests represented in geogrid data, and in
82 the metgrid data that will be produced
84 (Optional) Number of MPI tasks to use for running this instance
85 of metgrid. If arg is not present, non-MPI execution is assumed.
86 ungribbed_data_dict : dict
87 Necessary information on the ungribbed files. We expect dict with
88 entries {'FG_NAME' : <path>, ...}. Note that the 'FG_NAME' is
89 not expected to adhere to any kind of workflow convention. This
90 method simply uses what it's given
91 geogrid_data_dict : dict
92 Necessary information on the geogrid files. We expect dict with
93 entries {'path' : <path>, 'filelist' : [list of geogrid files]}.
94 This implies that the geogrid files are all in the same src
96 custom_metgrid_tbl_path : str
97 (Optional) Path to a METGRID.TBL to be used for this run. If arg
98 is not present, then we assume that no custom file is needed.
100 Python logging level (e.g. logging.INFO)
105 These are examples of the geogrid_data_dict ungribbed_data_dict
109 geogrid_data_dict = {
110 'path' : '/path/to/dir/with/geogrid/files'
111 'filelist' : ['geo_em.d01.nc', 'geo_em.d02.nc']
114 ungribbed_data_dict = {
115 'ECMWF_ML' : '/path/to/dir/with/ecmwf_ml/ungribbed_files',
116 'ECMWF_SFC' : '/path/to/dir/with/ecmwf_sfc/ungribbed_files',
117 'ECMWF_PRES' : '/path/to/dir/with/pres/ungribbed_files'
129 LOGGER.debug(
'started')
136 if not wpswrf_distro_path:
137 wpswrf_distro_path = DEFAULTS.wpswrf_distro_path()
141 raise FileNotFoundError(
'wpswrf_distro_path not found: %s' %
144 if not working_rootdir:
145 working_rootdir = DEFAULTS.working_scratch_rootdir()
148 raise FileNotFoundError(
'working_rootdir not found: %s' %
155 raise ValueError(
"Missing num_nests arg")
157 raise ValueError(
"num_nests: %d" % num_nests)
165 if custom_metgrid_tbl_path:
166 if not os.path.isfile(custom_metgrid_tbl_path):
167 raise FileNotFoundError(
168 'Path not found: %s' % custom_metgrid_tbl_path)
174 geogrid_dir = geogrid_data_dict[
'path_to_files']
175 geogrid_files = geogrid_data_dict[
'files_list']
177 raise ValueError(
'Wrong number geogrid files: %d' % len(geogrid_files))
178 for fname
in geogrid_files:
179 fpath = os.path.join(geogrid_dir, fname)
180 if not os.path.isfile(fpath):
181 raise FileNotFoundError(
'fpath: %s' % fpath)
185 ungrib_fg_keys = list(ungribbed_data_dict.keys())
186 for fg_key
in ungrib_fg_keys:
187 ug_path = ungribbed_data_dict[fg_key]
188 LOGGER.debug(
'ug_path: %s' % ug_path)
189 curr_dt = start_time_dt
190 while curr_dt <= stop_time_dt:
191 LOGGER.debug(
'curr_dt: %s' % curr_dt)
192 curr_timestr = curr_dt.strftime(
'%Y-%m-%d_%H')
193 LOGGER.debug(
'curr_timestr: %s' % curr_timestr)
194 fname = fg_key +
':' + curr_timestr
195 expected_path = os.path.join(ug_path, fname)
196 if not os.path.isfile(expected_path):
197 raise FileNotFoundError(
'expected_path: %s' % expected_path)
198 curr_dt += datetime.timedelta(hours=hours_intvl)
206 if 1 <= num_mpi_tasks <= DEFAULTS.max_mpi_tasks():
208 mpirunpath = DEFAULTS.mpirun_path()
209 if os.path.isfile(mpirunpath)
and \
210 os.access(mpirunpath, os.X_OK):
214 raise FileNotFoundError(
'mpirun not executable: %s' %
217 raise ValueError(
'Bad num_mpi_tasks value: %d' % num_mpi_tasks)
237 '''Set up and run, via nwpservice module, instance of metgrid
241 metgrid_output_stagedir : str
242 (Optional) Full path to dir where metgrid files will be staged.
243 If not specified, no staging will be done. If specified, we
244 assume the dir already exists.
249 Dictionary with manifest of the metgrid files and the location
250 (if applicable) of staged files
254 LOGGER.debug(
'Starting run_metgrid()...')
260 LOGGER.debug(
'namelist_wps_path: %s' % namelist_wps_path)
270 fg_name_list.append(ugkey)
276 section_data_dict = {
279 'start_date_list' : [start_time_str]*self.
_num_nests,
280 'end_date_list' : [end_time_str]*self.
_num_nests,
281 'interval_seconds' : interval_secs
284 'fg_name' : fg_name_list
288 myobj = nwpservice.wps.namelistwps.NamelistWpsWriter(
289 destpath=namelist_wps_path,
290 section_data_dict=section_data_dict
292 LOGGER.debug(
'Writing namelist: %s' % namelist_wps_path)
297 LOGGER.debug(
'domainpath: %s' % domainpath)
300 nwpmetgrid_obj = nwpservice.wps.metgrid.Metgrid(
302 wpswrf_rundir=domainpath,
306 namelist_wps=namelist_wps_path,
307 output_dir=metgrid_output_stagedir,
313 nwpmetgrid_obj.setup()
314 output_manifest = nwpmetgrid_obj.run()
315 LOGGER.debug(
'output_manifest: %s' % output_manifest)
319 stage_success = nwpmetgrid_obj.stage_output(auxfiles=
True)
321 staging_dir = metgrid_output_stagedir
326 'metgrid_output_manifest' : output_manifest,
327 'staging_dir' : staging_dir,
330 LOGGER.debug(
'return_dict: %s' % return_dict)