From cca5194178aff749d352b0bb845f2dd2f0297fd7 Mon Sep 17 00:00:00 2001 From: George McCabe <23407799+georgemccabe@users.noreply.github.com> Date: Fri, 1 Nov 2024 09:17:26 -0600 Subject: [PATCH] Per #2762, improve how the accumulation amounts are handling using relativedelta to ensure that the correct number of seconds are used for each search window when using inconsistent time intervals like months or years --- metplus/wrappers/pcp_combine_wrapper.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/metplus/wrappers/pcp_combine_wrapper.py b/metplus/wrappers/pcp_combine_wrapper.py index f36dc37fa..3324f519f 100755 --- a/metplus/wrappers/pcp_combine_wrapper.py +++ b/metplus/wrappers/pcp_combine_wrapper.py @@ -649,7 +649,8 @@ def get_accumulation(self, time_info, accum, data_src, accum_relative = get_relativedelta(accum, 'S') # using 1 hour for now smallest_input_accum = min( - [lev['amount'] for lev in self.c_dict['ACCUM_DICT_LIST']] + [ti_get_seconds_from_relativedelta(lev['amount'], search_time) + for lev in self.c_dict['ACCUM_DICT_LIST']] ) if smallest_input_accum == 9999999: smallest_input_accum = 3600 @@ -743,8 +744,9 @@ def _add_file_and_field_info_to_args(self, search_file, field_info, def _find_file_for_accum(self, accum_dict, total_accum, time_info, search_time, data_src, custom): - if (accum_dict['amount'] > total_accum and - accum_dict['template'] is None): + # get number of seconds from relativedelta accum amount using search time + accum_seconds = ti_get_seconds_from_relativedelta(accum_dict['amount'], search_time) + if accum_seconds > total_accum and accum_dict['template'] is None: return None, None, None self.c_dict['SUPPRESS_WARNINGS'] = True @@ -771,7 +773,7 @@ def _find_file_for_accum(self, accum_dict, total_accum, time_info, "than remaining accumulation.") return None, None, None else: - accum_amount = accum_dict['amount'] + accum_amount = accum_seconds search_time_info = { 'valid': search_time, @@ -806,7 +808,8 @@ def get_lowest_fcst_file(self, valid_time, data_src, custom): self.c_dict[data_src+'_MAX_FORECAST'], 'H' ) smallest_input_accum = min( - [lev['amount'] for lev in self.c_dict['ACCUM_DICT_LIST']] + [ti_get_seconds_from_relativedelta(lev['amount'], valid_time) + for lev in self.c_dict['ACCUM_DICT_LIST']] ) # if smallest input accumulation is greater than an hour, search hourly @@ -860,6 +863,9 @@ def find_input_file(self, init_time, valid_time, search_accum, data_src, custom): lead = 0 in_template = self.c_dict[data_src+'_INPUT_TEMPLATE'] + # use rel_time as offset to compute seconds from + # relativedelta search_accum for time_info level -- can be init or valid + rel_time = valid_time if ('{lead?' in in_template or ('{init?' in in_template and '{valid?' in in_template)): @@ -870,15 +876,17 @@ def find_input_file(self, init_time, valid_time, search_accum, data_src, # ti_calculate cannot currently handle both init and valid lead = (valid_time - init_time).total_seconds() input_dict = {'init': init_time, 'lead': lead} + rel_time = init_time else: if self.c_dict[f'{data_src}_CONSTANT_INIT']: input_dict = {'init': init_time} + rel_time = init_time else: input_dict = {'valid': valid_time} time_info = ti_calculate(input_dict) time_info['custom'] = custom - time_info['level'] = int(search_accum) + time_info['level'] = ti_get_seconds_from_relativedelta(search_accum, rel_time) input_path = self.find_data(time_info, data_type=data_src, return_list=True, mandatory=False) if input_path: @@ -1003,8 +1011,8 @@ def _build_input_accum_list(self, data_src, time_info): template = accum accum = '9999999S' - # convert accum amount to seconds from time string - amount = get_seconds_from_string(accum, 'H', time_info['valid']) + # convert accum amount to relativedelta from time string + amount = get_relativedelta(accum, default_unit='H') accum_dict_list.append({'amount': amount, 'name': name,