Skip to content

Commit

Permalink
Per #1898, add support for setting optional -diag argument to tc_pair…
Browse files Browse the repository at this point in the history
…s, refactored logic to set a/b/edeck arguments to remove unnecessary class variables
  • Loading branch information
georgemccabe committed Nov 7, 2022
1 parent 185e90e commit 44fc9f5
Showing 1 changed file with 61 additions and 51 deletions.
112 changes: 61 additions & 51 deletions metplus/wrappers/tc_pairs_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,6 @@ def __init__(self, config, instance=None):
self.app_path = os.path.join(config.getdir('MET_BIN_DIR', ''),
self.app_name)
super().__init__(config, instance=instance)
self.adeck = []
self.bdeck = []
self.edeck = []

def create_c_dict(self):
"""! Create a dictionary containing all the values set in the
Expand Down Expand Up @@ -191,12 +188,12 @@ def create_c_dict(self):
)
c_dict['VALID_BEG'] = self.get_wrapper_or_generic_config('VALID_BEG')
c_dict['VALID_END'] = self.get_wrapper_or_generic_config('VALID_END')
c_dict['ADECK_DIR'] = \
self.config.getdir('TC_PAIRS_ADECK_INPUT_DIR', '')
c_dict['BDECK_DIR'] = \
self.config.getdir('TC_PAIRS_BDECK_INPUT_DIR', '')
c_dict['EDECK_DIR'] = \
self.config.getdir('TC_PAIRS_EDECK_INPUT_DIR', '')
c_dict['ADECK_DIR'] = self.config.getdir('TC_PAIRS_ADECK_INPUT_DIR',
'')
c_dict['BDECK_DIR'] = self.config.getdir('TC_PAIRS_BDECK_INPUT_DIR',
'')
c_dict['EDECK_DIR'] = self.config.getdir('TC_PAIRS_EDECK_INPUT_DIR',
'')
c_dict['OUTPUT_DIR'] = self.config.getdir('TC_PAIRS_OUTPUT_DIR', '')
if not c_dict['OUTPUT_DIR']:
self.log_error('TC_PAIRS_OUTPUT_DIR must be set')
Expand Down Expand Up @@ -225,22 +222,28 @@ def create_c_dict(self):
'TC_PAIRS_DLAND_FILE')

c_dict['ADECK_TEMPLATE'] = (
self.config.getraw('filename_templates',
self.config.getraw('config',
'TC_PAIRS_ADECK_TEMPLATE',
'')
)

c_dict['BDECK_TEMPLATE'] = (
self.config.getraw('filename_templates',
self.config.getraw('config',
'TC_PAIRS_BDECK_TEMPLATE')
)

c_dict['EDECK_TEMPLATE'] = (
self.config.getraw('filename_templates',
self.config.getraw('config',
'TC_PAIRS_EDECK_TEMPLATE',
'')
)

# read optional -diag argument variables
c_dict['DIAG_TEMPLATE'] = (
self.config.getraw('config', 'TC_PAIRS_DIAG_INPUT_TEMPLATE')
)
c_dict['DIAG_DIR'] = self.config.getdir('TC_PAIRS_DIAG_INPUT_DIR', '')

# handle output template
output_template = (
self.config.getraw('config', 'TC_PAIRS_OUTPUT_TEMPLATE')
Expand Down Expand Up @@ -578,6 +581,7 @@ def process_data(self, basin, cyclone, time_info):

# find corresponding adeck or edeck files
for bdeck_file in bdeck_files:
self.clear()
self.logger.debug(f'Found BDECK: {bdeck_file}')

# get current basin/cyclone that corresponds to bdeck
Expand Down Expand Up @@ -617,9 +621,11 @@ def process_data(self, basin, cyclone, time_info):
bdeck_list = self.reformat_files(bdeck_list, 'B', time_info)
edeck_list = self.reformat_files(edeck_list, 'E', time_info)

self.adeck = adeck_list
self.bdeck = bdeck_list
self.edeck = edeck_list
self.args.append(f"-bdeck {' '.join(bdeck_list)}")
if adeck_list:
self.args.append(f"-adeck {' '.join(adeck_list)}")
if edeck_list:
self.args.append(f"-edeck {' '.join(edeck_list)}")

# change wildcard basin/cyclone to 'all' for output filename
if current_basin == self.WILDCARDS['basin']:
Expand All @@ -630,6 +636,11 @@ def process_data(self, basin, cyclone, time_info):
time_storm_info = time_info.copy()
time_storm_info['basin'] = current_basin
time_storm_info['cyclone'] = current_cyclone

# find -diag file if requested
if not self._handle_diag_file(time_storm_info):
return []

if not self.find_and_check_output_file(time_info=time_storm_info,
check_extension='.tcst'):
return []
Expand Down Expand Up @@ -811,39 +822,15 @@ def get_command(self):
output file, as there is a default.
Build command to run from arguments
"""
if self.app_path is None:
self.log_error("No app path specified. You must use a subclass")
return None

if not self.adeck and not self.edeck:
self.log_error('Neither ADECK nor EDECK files set')
return None

if not self.bdeck:
self.log_error('BDECK file not set')
return None

config_file = self.c_dict['CONFIG_FILE']
if not config_file:
self.log_error('Config file not set')
return None

output_path = self.get_output_path()
if not output_path:
self.log_error('Output path not set')
return None

cmd = '{} -v {}'.format(self.app_path, self.c_dict['VERBOSITY'])
cmd += ' -bdeck {}'.format(' '.join(self.bdeck))

if self.adeck:
cmd += ' -adeck {}'.format(' '.join(self.adeck))

if self.edeck:
cmd += ' -edeck {}'.format(' '.join(self.edeck))

cmd += ' -config {} -out {}'.format(config_file, output_path)

cmd = (f"{self.app_path} -v {self.c_dict['VERBOSITY']}"
f" {' '.join(self.args)}"
f" -config {self.c_dict['CONFIG_FILE']}"
f" -out {output_path}")
return cmd

def read_modify_write_file(self, in_csvfile, storm_month, missing_values,
Expand Down Expand Up @@ -917,20 +904,23 @@ def _read_all_files(self, input_dict):
self.c_dict['BASIN'] = self.c_dict.get('BASIN_LIST', '')

# Set up the environment variable to be used in the tc_pairs Config
self.bdeck = [self.c_dict['BDECK_DIR']]
self.args.append(f"-bdeck {' '.join(self.c_dict['BDECK_DIR'])}")
#self.bdeck = [self.c_dict['BDECK_DIR']]

adeck_dir = self.c_dict['ADECK_DIR']
edeck_dir = self.c_dict['EDECK_DIR']
if self.c_dict['ADECK_DIR']:
self.args.append(f"-adeck {' '.join(self.c_dict['ADECK_DIR'])}")

if adeck_dir:
self.adeck = [adeck_dir]

if edeck_dir:
self.edeck = [edeck_dir]
if self.c_dict['EDECK_DIR']:
self.args.append(f"-edeck {' '.join(self.c_dict['EDECK_DIR'])}")

# get output filename from template
time_info = ti_calculate(input_dict)
time_storm_info = self._add_storm_info_to_dict(time_info)

# handle -diag file if requested
if not self._handle_diag_file(time_storm_info):
return []

if not self.find_and_check_output_file(time_info=time_storm_info,
check_extension='.tcst'):
return []
Expand All @@ -940,6 +930,26 @@ def _read_all_files(self, input_dict):
self.build()
return self.all_commands

def _handle_diag_file(self, time_info):
"""! Get optional -diag argument file path if requested.
@param time_info dictionary containing values to substitute into
filename template
@returns True if file was found successfully or no file was requested.
False if the file does not exist.
"""
if not self.c_dict['DIAG_TEMPLATE']:
return True

filepath = os.path.join(self.c_dict['DIAG_DIR'],
self.c_dict['DIAG_TEMPLATE'])
filepath = do_string_sub(filepath, **time_info)
if not os.path.exists(filepath):
self.log_error(f'Diag file does not exist: {filepath}')
return False

self.args.append(f'-diag {filepath}')
return True

def _add_storm_info_to_dict(self, time_info):
"""! Read from self.c_dict and add storm information to dictionary.
Expand Down

0 comments on commit 44fc9f5

Please sign in to comment.