39 '''Class for managing preparation and execution of srm component
41 This component currently uses the standard ATM Pipeline flexpart2ctbt
42 for the conversion. This means that, as-is, it will not process
43 an OUTGRID nest, but only the top-level nest.
54 '''Check and initialise the class
59 (Optional) Full path to the SRM executable. This is assumed
60 to have been installed in a way that is compatible with the
61 ehratm module. If arg is not present, uses a default value
63 (Optional) Full path to a directory (assumed to have already
64 been created), to be used as scratch space for setting up and
65 running this srm instance. If arg is not present, uses a
66 default value. A 'srm_rundir' subdir will be created in here
68 Full path to a directory containing the FlexWRF binary output files,
69 including the header file
71 (Optional) List of integers designating the vertical levels (indexed from 1)
72 to produce SRM files for. If arg is not present, assumes [1]
74 Python logging level (e.g. logging.INFO)
88 LOGGER.debug(
'started')
92 if not os.path.isfile(srm_exec_path):
93 raise FileNotFoundError(
'srm_exec_path not found: %s' %
95 if not os.access(srm_exec_path, os.X_OK):
96 raise FileNotFoundError(
'srm_exec_path not executable: %s' %
106 if not working_rootdir:
107 working_rootdir = DEFAULTS.working_scratch_rootdir()
110 raise FileNotFoundError(
'working_rootdir not found: %s' %
118 raise FileNotFoundError(
'Failed to create srm_rundir: %s' %
126 if not os.path.isdir(flexwrfout_dir):
127 raise FileNotFoundError(
'flexwrfout_dir not found: %s' %
132 raise Exception(
'No flexwrfout_dir specified')
134 if type(levels_list)
is not list:
135 raise ValueError(
'levels_list is not a list')
137 for level
in levels_list:
138 if type(level)
is not int:
139 raise ValueError(
'levels_list has a non-integer element')
150 '''Set up and run, via command line, an instance of flexpart2ctbt
151 for each level in the levels_list
155 srm_output_stagedir : str
156 (Optional) Full path to dir where srm output files will be staged.
157 If not specified, no staging will be done. If specified, we
158 assume the dir already exists.
160 (Optional) Factor by which to multiply concentrations
162 (Optional) NOT YET IMPLEMENTED - compresses resulting SRM
168 Dictionary with manifest of the srm output files and the location
169 (if applicable) of staged files
173 LOGGER.debug(
'Starting run_srm()...')
178 LOGGER.warning(
'SRM compress is not yet implemented.')
184 if srm_output_stagedir:
185 if not os.path.isdir(srm_output_stagedir):
186 raise FileNotFoundError(
187 'srm_output_stagedir not found: %s' % srm_output_stagedir
189 if not os.access(srm_output_stagedir, os.W_OK):
190 raise FileNotFoundError(
191 'srm_output_stagedir not writable: %s' % srm_output_stagedir
196 srm_output_manifest = {}
198 srm_output_manifest[
'levels'] = {}
202 LOGGER.debug(
'Creating SRM file for level: %d' % level)
206 level_output_manifest = {str(level) :
None}
209 control_fname =
'control_level_%02d' % level
210 cfh = open(control_fname,
'w')
213 cfh.write(
'============================================\n')
214 cfh.write(
'%d\n' % level)
215 cfh.write(
'%e\n' % multiplier)
217 cfh.write(
'l%d\n' % level)
222 subprocess.call(the_command, shell=
True)
239 digits_14 =
'[0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
240 digits_14 +=
'[0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
241 prepattern =
'*.fp.' + digits_14 +
'.l'
242 prepattern +=
'%1d' % level
243 pattern_conc = prepattern +
'.srm'
244 pattern_dry = prepattern +
'.l0.dry.srm'
245 pattern_wet = prepattern +
'.l0.wet.srm'
249 for fname
in os.listdir(
'.'):
250 if fnmatch.fnmatch(fname, pattern_conc):
251 matched_fnames.append(fname)
252 elif fnmatch.fnmatch(fname, pattern_dry):
253 matched_fnames.append(fname)
254 elif fnmatch.fnmatch(fname, pattern_wet):
255 matched_fnames.append(fname)
257 LOGGER.debug(
'matched_fnames: %s' % matched_fnames)
261 for fname
in matched_fnames:
263 bytes = os.path.getsize(fname)
264 file_info = {
'bytes' : bytes}
265 level_manifest[fname] = file_info
268 srm_output_manifest[
'levels'] = {str(level) : level_manifest}
270 LOGGER.debug(
'matched_fnames: %s' % matched_fnames)
271 LOGGER.debug(
'srm_output_manifest: %s' % srm_output_manifest)
278 staging_dir=srm_output_stagedir,
281 LOGGER.debug(
'stage_success: %s' % stage_success)
283 staging_dir = srm_output_stagedir
290 'srm_output_manifest' : srm_output_manifest,
291 'staging_dir' : staging_dir
293 LOGGER.debug(
'return_dict: %s' % return_dict)
300 '''Stages output to specified dir
302 Stages the output (met_em*) and, optionally, other runtime files to
308 Must already exist and be writable. If not specified,
309 then self._output_dir is used. If that wasn't specified,
310 then we abort and return False to caller
312 If set to True, will also copy in the metgrid.log* files
317 return value : boolean
318 True or False based on success of operation
323 if os.path.isdir(staging_dir)
and os.access(staging_dir, os.W_OK):
324 dest_dir = staging_dir
325 LOGGER.debug(
'dest_dir: %s' % dest_dir)
327 LOGGER.error(
'staging_dir not accessible and/or writable: %s',
331 LOGGER.info(
'No valid, writable staging dir. Returning None')
335 srm_files = [os.path.basename(x)
for
338 LOGGER.debug(
'Copying srm files: %s' % srm_files)
345 control_files = [os.path.basename(x)
for
346 x
in glob.glob(self.
_srm_rundir +
'/control_level_*')]
347 auxfile_list = control_files
348 LOGGER.debug(
'Copying aux files: %s' % auxfile_list)
349 for f
in auxfile_list: