From 452902f7a5e6c663d39cad7aa08701a826cd8a30 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Thu, 15 Aug 2024 12:46:13 -0400 Subject: [PATCH 01/48] Update parameters.py --- flepimop/gempyor_pkg/src/gempyor/parameters.py | 1 + 1 file changed, 1 insertion(+) diff --git a/flepimop/gempyor_pkg/src/gempyor/parameters.py b/flepimop/gempyor_pkg/src/gempyor/parameters.py index b01fb52ab..492404274 100644 --- a/flepimop/gempyor_pkg/src/gempyor/parameters.py +++ b/flepimop/gempyor_pkg/src/gempyor/parameters.py @@ -23,6 +23,7 @@ ## TODO: ideally here path_prefix should not be used and all files loaded from modinf +# Test comment to check for proper branch creation class Parameters: # Minimal object to be easily picklable for // runs From 9a7f4a3b466da346623349887156f223f94b4bf6 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Thu, 15 Aug 2024 14:21:22 -0400 Subject: [PATCH 02/48] Update parameters.py --- flepimop/gempyor_pkg/src/gempyor/parameters.py | 1 - 1 file changed, 1 deletion(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/parameters.py b/flepimop/gempyor_pkg/src/gempyor/parameters.py index 492404274..b01fb52ab 100644 --- a/flepimop/gempyor_pkg/src/gempyor/parameters.py +++ b/flepimop/gempyor_pkg/src/gempyor/parameters.py @@ -23,7 +23,6 @@ ## TODO: ideally here path_prefix should not be used and all files loaded from modinf -# Test comment to check for proper branch creation class Parameters: # Minimal object to be easily picklable for // runs From d063762f99fc6cbb64e9053f6c22fbd1d3ab68e2 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Mon, 16 Sep 2024 15:58:22 -0400 Subject: [PATCH 03/48] Improved readability/consistency of errors/exceptions in 5 gempyor files. Adjusted formatting, punctuation, clarity, syntax, etc. in the errors/exceptions in `gempyor`'s initial_conditions.py, parameters.py, compartments.py, config_validator.py, inference.py. This will likely be one of three pulls to address GH-281. --- .../gempyor_pkg/src/gempyor/compartments.py | 54 +++++++++++------ .../src/gempyor/config_validator.py | 59 ++++++++++++++----- flepimop/gempyor_pkg/src/gempyor/inference.py | 6 +- .../src/gempyor/initial_conditions.py | 35 +++++++---- .../gempyor_pkg/src/gempyor/parameters.py | 25 ++++---- 5 files changed, 117 insertions(+), 62 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/compartments.py b/flepimop/gempyor_pkg/src/gempyor/compartments.py index ec87cf7e5..027ea671c 100644 --- a/flepimop/gempyor_pkg/src/gempyor/compartments.py +++ b/flepimop/gempyor_pkg/src/gempyor/compartments.py @@ -25,7 +25,7 @@ def __init__(self, seir_config=None, compartments_config=None, compartments_file self.times_set += 1 if self.times_set == 0: - raise ValueError("Compartments object not set, no config or file provided") + raise ValueError("Compartments object not set, no config or file provided.") return def constructFromConfig(self, seir_config, compartment_config): @@ -375,7 +375,9 @@ def get_comp_idx(self, comp_dict: dict, error_info: str = "no information") -> i comp_idx = self.compartments[mask].index.values if len(comp_idx) != 1: raise ValueError( - f"The provided dictionary does not allow to isolate a compartment: {comp_dict} isolate {self.compartments[mask]} from options {self.compartments}. The get_comp_idx function was called by'{error_info}'." + f"The provided dictionary does not allow to isolate a compartment: {comp_dict} " + f" isolate {self.compartments[mask]} from options {self.compartments}. " + f"The get_comp_idx function was called by '{error_info}'." ) return comp_idx[0] @@ -395,7 +397,7 @@ def get_transition_array(self): rc = compartment if rc == -1: print(self.compartments) - raise ValueError(f"Could not find {colname} defined by {elem} in compartments") + raise ValueError(f"Could not find {colname} defined by {elem} in compartments.") transition_array[cit, it] = rc unique_strings = [] @@ -424,8 +426,11 @@ def get_transition_array(self): candidate = reduce(lambda a, b: a + "*" + b, elem) candidate = candidate.replace(" ", "") # candidate = candidate.replace("*1", "") - if not candidate in unique_strings: - raise ValueError("Something went wrong") + if candidate not in unique_strings: + raise ValueError( + f"Candidate '{candidate}' from 'rate' column is not in the list of unique strings. " + f"Unique strings: {unique_strings}" + ) rc = [it for it, x in enumerate(unique_strings) if x == candidate][0] transition_array[2][it] = rc @@ -464,8 +469,11 @@ def get_transition_array(self): candidate = reduce(lambda a, b: a + "*" + b, y) candidate = candidate.replace(" ", "") # candidate = candidate.replace("*1", "") - if not candidate in unique_strings: - raise ValueError("Something went wrong") + if candidate not in unique_strings: + raise ValueError( + f"Proportion exponent '{candidate}' is not found in the list of unique strings. " + f"Unique strings: {unique_strings}" + ) rc = [it for it, x in enumerate(unique_strings) if x == candidate][0] proportion_info[2][proportion_compartment_index] = rc proportion_compartment_index += 1 @@ -490,7 +498,10 @@ def get_transition_array(self): if self.compartments["name"][compartment] == elem3: rc = compartment if rc == -1: - raise ValueError(f"Could not find proportional_to {elem3} in compartments") + raise ValueError( + f"Could not find proportional_to {elem3} in compartments. " + f"Available compartments: {self.compartments}" + ) proportion_array[proportion_index] = rc proportion_index += 1 @@ -554,7 +565,10 @@ def parse_parameter_strings_to_numpy_arrays_v2(self, parameters, parameter_names f = sp.sympify(formula, locals=symbolic_parameters_namespace) parsed_formulas.append(f) except Exception as e: - print(f"Cannot parse formula: '{formula}' from parameters {parameter_names}") + print( + f"Cannot parse formula: '{formula}' :" + f"from parameters: {parameter_names}." + ) raise (e) # Print the error message for debugging # the list order needs to be right. @@ -600,10 +614,10 @@ def parse_parameter_strings_to_numpy_arrays( not operators ): # empty list means all have been tried. Usually there just remains one string in string_list at that time. raise ValueError( - f"""Could not parse string {string_list}. - This usually mean that '{string_list[0]}' is a parameter name that is not defined - or that it contains an operator that is not in the list of supported operator: ^,*,/,+,-. - The defined parameters are {parameter_names}.""" + f"Could not parse string {string_list}. " + f"This usually mean that '{string_list[0]}' is a parameter name that is not defined " + f" or that it contains an operator that is not in the list of supported operator: ^,*,/,+,-. " + f"The defined parameters are {parameter_names}." ) split_strings = [x.split(operators[0]) for x in string_list] @@ -710,12 +724,14 @@ def list_access_element_safe(thing, idx, dimension=None, encapsulate_as_list=Fal try: return list_access_element(thing, idx, dimension, encapsulate_as_list) except Exception as e: - print(f"Error {e}:") - print(f">>> in list_access_element_safe for {thing} at index {idx}") - print(">>> This is often, but not always because the object above is a list (there are brackets around it).") - print(">>> and in this case it is not broadcast, so if you want to it to be broadcasted, you need remove the brackets around it.") - print(f"dimension: {dimension}") - raise e + raise Exception( + f"Error {e}: " + f"in list_access_element_safe for {thing} at index {idx}. " + f"This is often, but not always because the object above is a list (there are brackets around it). " + f"and in this case it is not broadcast, so if you want to it to be broadcasted, you need remove the brackets around it. " + f"dimension: {dimension}." + ) + def list_access_element(thing, idx, dimension=None, encapsulate_as_list=False): diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index 95f6e3029..3b8b9a36d 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -52,7 +52,7 @@ def plugin_filecheck(cls, values): method = values.get('method') plugin_file_path = values.get('plugin_file_path') if method == 'plugin' and not plugin_file_path: - raise ValueError('Error in InitialConditions: a plugin file path is required when method is plugin') + raise ValueError(f'Error in InitialConditions: a plugin file path is required when method is plugin.') return values @@ -70,11 +70,20 @@ def validate_seedingfile(cls, values): seeding_file_type = values.get('seeding_file_type') seeding_file = values.get('seeding_file') if method == 'PoissonDistributed' and not lambda_file: - raise ValueError(f'Error in Seeding: A lambda_file is required when method is {method}') + raise ValueError( + f'Error in Seeding: A lambda_file is required when method is {method} ' + f'Current value: {lambda_file}.' + ) if method == 'FolderDraw' and not seeding_file_type: - raise ValueError('Error in Seeding: A seeding_file_type is required when method is FolderDraw') + raise ValueError( + f'Error in Seeding: A seeding_file_type is required when method is FolderDraw' + f'Current value: {seeding_file_type}.' + ) if method == 'FromFile' and not seeding_file: - raise ValueError('Error in Seeding: A seeding_file is required when method is FromFile') + raise ValueError( + f'Error in Seeding: A seeding_file is required when method is FromFile ' + f'Current value: {seeding_file}.' + ) return values @model_validator(mode='before') @@ -82,7 +91,10 @@ def plugin_filecheck(cls, values): method = values.get('method') plugin_file_path = values.get('plugin_file_path') if method == 'plugin' and not plugin_file_path: - raise ValueError('Error in Seeding: a plugin file path is required when method is plugin') + raise ValueError( + f'Error in Seeding: a plugin file path is required when method is plugin' + f'Current value: {plugin_file_path!r}. Please specify the path to the plugin file.' + ) return values class IntegrationConfig(BaseModel): @@ -107,11 +119,11 @@ def check_distr(cls, values): b = values.get('b') if distr != 'fixed': if not mean and not sd: - raise ValueError('Error in value: mean and sd must be provided for non-fixed distributions') + raise ValueError('Mean and sd must be provided for non-fixed distributions.') if distr == 'truncnorm' and not a and not b: - raise ValueError('Error in value: a and b must be provided for truncated normal distributions') + raise ValueError('a and b must be provided for truncated normal distributions.') if distr == 'fixed' and not value: - raise ValueError('Error in value: value must be provided for fixed distributions') + raise ValueError('Value must be provided for fixed distributions') return values class BaseParameterConfig(BaseModel): @@ -130,7 +142,10 @@ def which_value(cls, values): value = values.get('value') is not None timeseries = values.get('timeseries') is not None if value and timeseries: - raise ValueError('Error in seir::parameters: your parameter is both a timeseries and a value, please choose one') + raise ValueError( + f'Configuration error in seir::parameters: your parameter is both a timeseries and a value, please choose one. ' + f'Current values - value: {values.get('value')!r}, timeseries: {values.get('timeseries')!r}.' + ) return values @@ -203,7 +218,11 @@ def which_source(cls, values): incidence = values.get('incidence') prevalence = values.get('prevalence') if incidence and prevalence: - raise ValueError('Error in outcomes::source. Can only be incidence or prevalence, not both.') + raise ValueError( + f'Configuration error in outcomes::source.' + f'Value can only be incidence or prevalence, not both.' + f'Current values - incidence: {values.get('incidence')!r}, prevalence: {values.get('prevalence')!r}.' + ) return values # @model_validator(mode='before') # DOES NOT WORK @@ -256,7 +275,7 @@ def check_paramfromfile_type(cls, values): param_subpop_file = values.get('param_subpop_file') is not None if param_from_file and not param_subpop_file: - raise ValueError(f"Error in outcome: 'param_subpop_file' is required when 'param_from_file' is True") + raise ValueError(f"Error in outcome: 'param_subpop_file' is required when 'param_from_file' is True.") return values class ResampleConfig(BaseModel): @@ -320,9 +339,15 @@ def verify_inference(cls, values): inference_present = values.get('inference') is not None start_date_groundtruth = values.get('start_date_groundtruth') is not None if inference_present and not start_date_groundtruth: - raise ValueError('Inference mode is enabled but no groundtruth dates are provided') + raise ValueError( + f'Inference mode is enabled, but no groundtruth dates are provided.' + f'Please provide groundtruth dates.' + ) elif start_date_groundtruth and not inference_present: - raise ValueError('Groundtruth dates are provided but inference mode is not enabled') + raise ValueError( + f'Groundtruth dates are provided, but inference mode is not enabled.' + f'Please enable inference mode.' + ) return values @model_validator(mode='before') @@ -331,7 +356,9 @@ def check_dates(cls, values): end_date = values.get('end_date') if start_date and end_date: if end_date <= start_date: - raise ValueError('end_date must be greater than start_date') + raise ValueError( + f'`end_date` ({end_date}) must be greater than `start_date` ({start_date})).' + ) return values @model_validator(mode='before') @@ -339,5 +366,7 @@ def init_or_seed(cls, values): init = values.get('initial_conditions') seed = values.get('seeding') if not init or seed: - raise ValueError('either initial_conditions or seeding must be provided') + raise ValueError( + f'At least one of `initial_conditions` or `seeding` must be provided.' + ) return values diff --git a/flepimop/gempyor_pkg/src/gempyor/inference.py b/flepimop/gempyor_pkg/src/gempyor/inference.py index 81b1c22d0..d1f3397d7 100644 --- a/flepimop/gempyor_pkg/src/gempyor/inference.py +++ b/flepimop/gempyor_pkg/src/gempyor/inference.py @@ -268,9 +268,9 @@ def autodetect_scenarios(config): if len(seir_modifiers_scenarios) != 1 or len(outcome_modifiers_scenarios) != 1: raise ValueError( - f"Inference only support configurations files with one scenario, got" - f"seir: {seir_modifiers_scenarios}" - f"outcomes: {outcome_modifiers_scenarios}" + f"Inference only supports configuration files with one scenario, recieved:\n" + f"SEIR modifiers: {seir_modifiers_scenarios}." + f"Outcomes modifiers: {outcome_modifiers_scenarios}." ) return seir_modifiers_scenarios[0], outcome_modifiers_scenarios[0] diff --git a/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py b/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py index 554f3910c..1b50c0988 100644 --- a/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py +++ b/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py @@ -99,7 +99,7 @@ def get_from_config(self, sim_id: int, modinf) -> np.ndarray: allow_missing_subpops=self.allow_missing_subpops, ) else: - raise NotImplementedError(f"unknown initial conditions method [got: {method}]") + raise NotImplementedError(f"Unknown initial conditions method [recieved: {method}].") # check that the inputed values sums to the subpop population: check_population(y0=y0, modinf=modinf, ignore_population_checks=self.ignore_population_checks) @@ -122,16 +122,20 @@ def check_population(y0, modinf, ignore_population_checks=False): if abs(n_y0 - n_pop) > 1: error = True print( - f"ERROR: subpop_names {pl} (idx: pl_idx) has a population from initial condition of {n_y0} while population from geodata is {n_pop} (absolute difference should be < 1, here is {abs(n_y0-n_pop)})" + f"ERROR: subpop_names {pl} (idx: pl_idx) has a population from initial condition of {n_y0} " + f"while population from geodata is {n_pop}." + f"(absolute difference should be < 1, here is {abs(n_y0-n_pop)})." ) if error and not ignore_population_checks: raise ValueError( - """ geodata and initial condition do not agree on population size (see messages above). Use ignore_population_checks: True to ignore""" + f"Geodata and initial condition do not agree on population size (see messages above). " + f"Use `ignore_population_checks: True` to ignore." ) elif error and ignore_population_checks: print( - """ Ignoring the previous population mismatch errors because you added flag 'ignore_population_checks'. This is dangerous""" + f"WARNING: population mismatch errors ignored because `ignore_population_checks` is set to `True`." + f"Execution will continue, but this is not recommended." ) @@ -162,8 +166,9 @@ def read_initial_condition_from_tidydataframe( ic_df_compartment_val = 0.0 else: raise ValueError( - f"Initial Conditions: Could not set compartment {comp_name} (id: {comp_idx}) in subpop {pl} (id: {pl_idx}). The data from the init file is {states_pl}. \n \ - Use 'allow_missing_compartments' to default to 0 for compartments without initial conditions" + f"ERROR: Multiple rows ({len(ic_df_compartment_val)}) match for compartment '{comp_name}' in the initial conditions file. " + f"Filters used: {filters.to_dict()}. Matches: {ic_df_compartment_val.tolist()}. " + f"Ensure that each compartment has a unique initial condition entry." ) if "rest" in str(ic_df_compartment_val).strip().lower(): rests.append([comp_idx, pl_idx]) @@ -177,7 +182,7 @@ def read_initial_condition_from_tidydataframe( logger.critical( f"No initial conditions for for subpop {pl}, assuming everyone (n={modinf.subpop_pop[pl_idx]}) in the first metacompartment ({modinf.compartments.compartments['name'].iloc[0]})" ) - raise ValueError("THERE IS A BUG; REPORT THIS MESSAGE. Past implemenation was buggy") + raise ValueError("THERE IS A BUG; REPORT THIS MESSAGE. Past implemenation was buggy.") # TODO: this is probably ok but highlighting for consistency if "proportional" in self.initial_conditions_config.keys(): if self.initial_conditions_config["proportional"].get(): @@ -188,7 +193,8 @@ def read_initial_condition_from_tidydataframe( y0[0, pl_idx] = modinf.subpop_pop[pl_idx] else: raise ValueError( - f"subpop {pl} does not exist in initial_conditions::states_file. You can set allow_missing_subpops=TRUE to bypass this error" + f"Subpop {pl} does not exist in `initial_conditions::states_file`. " + f"You can set `allow_missing_subpops=TRUE` to bypass this error." ) if rests: # not empty for comp_idx, pl_idx in rests: @@ -229,7 +235,7 @@ def read_initial_condition_from_seir_output(ic_df, modinf, allow_missing_subpops ic_df = ic_df[(ic_df["date"] == str(modinf.ti)) & (ic_df["mc_value_type"] == "prevalence")] if ic_df.empty: - raise ValueError(f"There is no entry for initial time ti in the provided initial_conditions::states_file.") + raise ValueError(f"No entry provided for initial time `ti` in the `initial_conditions::states_file.`") y0 = np.zeros((modinf.compartments.compartments.shape[0], modinf.nsubpops)) for comp_idx, comp_name in modinf.compartments.compartments["name"].items(): @@ -244,18 +250,20 @@ def read_initial_condition_from_seir_output(ic_df, modinf, allow_missing_subpops if len(ic_df_compartment) > 1: # ic_df_compartment = ic_df_compartment.iloc[0] raise ValueError( - f"ERROR: Several ({len(ic_df_compartment)}) rows are matches for compartment {mc_name} in init file: filter {filters} returned {ic_df_compartment}" + f"ERROR: Several ({len(ic_df_compartment)}) rows are matches for compartment {mc_name} in init file: filter {filters}. " + f"returned: {ic_df_compartment}." ) elif ic_df_compartment.empty: if allow_missing_compartments: ic_df_compartment = pd.DataFrame(0, columns=ic_df_compartment.columns, index=[0]) else: raise ValueError( - f"Initial Conditions: Could not set compartment {comp_name} (id: {comp_idx}) in subpop {pl} (id: {pl_idx}). The data from the init file is {ic_df_compartment[pl]}." + f"Initial Conditions: could not set compartment {comp_name} (id: {comp_idx}) in subpop {pl} (id: {pl_idx}). " + f"The data from the init file is {ic_df_compartment[pl]}." ) elif ic_df_compartment["mc_name"].iloc[0] != comp_name: print( - f"WARNING: init file mc_name {ic_df_compartment['mc_name'].iloc[0]} does not match compartment mc_name {comp_name}" + f"WARNING: init file `mc_name` {ic_df_compartment['mc_name'].iloc[0]} does not match compartment `mc_name` {comp_name}." ) for pl_idx, pl in enumerate(modinf.subpop_struct.subpop_names): @@ -273,6 +281,7 @@ def read_initial_condition_from_seir_output(ic_df, modinf, allow_missing_subpops y0[0, pl_idx] = modinf.subpop_pop[pl_idx] else: raise ValueError( - f"subpop {pl} does not exist in initial_conditions::states_file. You can set allow_missing_subpops=TRUE to bypass this error" + f"Subpop {pl} does not exist in `initial_conditions::states_file`. " + f"You can set `allow_missing_subpops=TRUE` to bypass this error." ) return y0 diff --git a/flepimop/gempyor_pkg/src/gempyor/parameters.py b/flepimop/gempyor_pkg/src/gempyor/parameters.py index b01fb52ab..2243039b4 100644 --- a/flepimop/gempyor_pkg/src/gempyor/parameters.py +++ b/flepimop/gempyor_pkg/src/gempyor/parameters.py @@ -74,8 +74,9 @@ def __init__( print("loaded col :", sorted(list(df.columns))) print("geodata col:", sorted(subpop_names)) raise ValueError( - f"""ERROR loading file {fn_name} for parameter {pn}: the number of non 'date' - columns are {len(df.columns)}, expected {len(subpop_names)} (the number of subpops) or one.""" + f"Error loading file {fn_name} for parameter {pn}: " + f"the number of non-'date' columns is {len(df.columns)}, " + f"expected {len(subpop_names)} (number of subpopulations) or one." ) df = df[str(ti) : str(tf)] @@ -83,21 +84,21 @@ def __init__( print("config dates:", pd.date_range(ti, tf)) print("loaded dates:", df.index) raise ValueError( - f"""ERROR loading file {fn_name} for parameter {pn}: - the 'date' entries of the provided file do not include all the days specified to be modeled by - the config. the provided file includes {len(df.index)} days between {str(df.index[0])} to {str(df.index[-1])}, - while there are {len(pd.date_range(ti, tf))} days in the config time span of {ti}->{tf}. The file must contain entries for the - the exact start and end dates from the config. """ + f"ERROR loading file {fn_name} for parameter {pn}: " + f"the 'date' entries of the provided file do not include all the days specified to be modeled by " + f"the config. the provided file includes {len(df.index)} days between {str(df.index[0])} to {str(df.index[-1])}, " + f"while there are {len(pd.date_range(ti, tf))} days in the config time span of {ti}->{tf}. The file must contain entries for the " + f"the exact start and end dates from the config." ) if not (pd.date_range(ti, tf) == df.index).all(): print("config dates:", pd.date_range(ti, tf)) print("loaded dates:", df.index) raise ValueError( - f"""ERROR loading file {fn_name} for parameter {pn}: - the 'date' entries of the provided file do not include all the days specified to be modeled by - the config. the provided file includes {len(df.index)} days between {str(df.index[0])} to {str(df.index[-1])}, - while there are {len(pd.date_range(ti, tf))} days in the config time span of {ti}->{tf}. The file must contain entries for the - the exact start and end dates from the config. """ + f"ERROR loading file {fn_name} for parameter {pn}: " + f"the 'date' entries of the provided file do not include all the days specified to be modeled by " + f" the config. the provided file includes {len(df.index)} days between {str(df.index[0])} to {str(df.index[-1])}, " + f"while there are {len(pd.date_range(ti, tf))} days in the config time span of {ti}->{tf}. The file must contain entries for the " + f"the exact start and end dates from the config." ) self.pdata[pn]["ts"] = df From add67d1e4378c540004052a1049067aaf8857458 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Fri, 20 Sep 2024 16:26:09 -0400 Subject: [PATCH 04/48] Attempting to fix errors by changing the regexs in some of the test files. --- .../tests/parameters/test_parameters_class.py | 10 +++++----- flepimop/gempyor_pkg/tests/seir/test_ic.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py index 4bfb86fd2..af8d186ef 100644 --- a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py +++ b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py @@ -237,9 +237,9 @@ def test_timeseries_parameter_has_insufficient_columns_value_error( with pytest.raises( ValueError, match=( - rf"^ERROR loading file {tmp_file} for parameter sigma\: the number of " - rf"non 'date'\s+columns are {actual_columns}, expected " - rf"{mock_inputs.number_of_subpops()} \(the number of subpops\) or " + rf"^Error loading file {tmp_file} for parameter sigma\: the number of " + rf"non- 'date'\s+columns is {actual_columns}, expected " + rf"{mock_inputs.number_of_subpops()} \(number of subpops\) or " rf"one\.$" ), ): @@ -288,10 +288,10 @@ def test_timeseries_parameter_has_insufficient_dates_value_error( rf"to be modeled by\s+the config\. the provided file includes " rf"{(timeseries_end_date - timeseries_start_date).days + 1} days " rf"between {timeseries_start_date}( 00\:00\:00)? to " - rf"{timeseries_end_date}( 00\:00\:00)?,\s+while there are " + rf"{timeseries_end_date}( 00\:00\:00)?, while there are " rf"{mock_inputs.number_of_days()} days in the config time span of " rf"{mock_inputs.ti}->{mock_inputs.tf}\. The file must contain entries " - rf"for the\s+the exact start and end dates from the config\. $" + rf"for the the exact start and end dates from the config\. $" ), ): mock_inputs.create_parameters_instance() diff --git a/flepimop/gempyor_pkg/tests/seir/test_ic.py b/flepimop/gempyor_pkg/tests/seir/test_ic.py index b4cd240ee..e2d78eb35 100644 --- a/flepimop/gempyor_pkg/tests/seir/test_ic.py +++ b/flepimop/gempyor_pkg/tests/seir/test_ic.py @@ -44,7 +44,7 @@ def test_IC_allow_missing_node_compartments_success(self): sic.get_from_config(sim_id=100, modinf=s) def test_IC_IC_notImplemented_fail(self): - with pytest.raises(NotImplementedError, match=r".*unknown.*initial.*conditions.*"): + with pytest.raises(NotImplementedError, match=r"^Unknown initial conditions method \[received: .*\]\.$"): config.clear() config.read(user=False) config.set_file(f"{DATA_DIR}/config.yml") From 3b4e4909890fa79b0e5ae030421e6fc7f8b22a19 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Fri, 27 Sep 2024 15:28:34 -0400 Subject: [PATCH 05/48] Another attempt to fix RegExs in test files --- .../tests/parameters/test_parameters_class.py | 23 ++++++++----------- flepimop/gempyor_pkg/tests/seir/test_ic.py | 2 +- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py index af8d186ef..e66aca4c2 100644 --- a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py +++ b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py @@ -237,10 +237,9 @@ def test_timeseries_parameter_has_insufficient_columns_value_error( with pytest.raises( ValueError, match=( - rf"^Error loading file {tmp_file} for parameter sigma\: the number of " - rf"non- 'date'\s+columns is {actual_columns}, expected " - rf"{mock_inputs.number_of_subpops()} \(number of subpops\) or " - rf"one\.$" + rf"^Error loading file {tmp_file} for parameter sigma: " + rf"the number of non-'date' columns is {actual_columns}, expected {mock_inputs.number_of_subpops()} " + rf"\(number of subpopulations\) or one\.$" ), ): mock_inputs.create_parameters_instance() @@ -283,15 +282,13 @@ def test_timeseries_parameter_has_insufficient_dates_value_error( with pytest.raises( ValueError, match=( - rf"^ERROR loading file {tmp_file} for parameter sigma\:\s+the \'date\' " - rf"entries of the provided file do not include all the days specified " - rf"to be modeled by\s+the config\. the provided file includes " - rf"{(timeseries_end_date - timeseries_start_date).days + 1} days " - rf"between {timeseries_start_date}( 00\:00\:00)? to " - rf"{timeseries_end_date}( 00\:00\:00)?, while there are " - rf"{mock_inputs.number_of_days()} days in the config time span of " - rf"{mock_inputs.ti}->{mock_inputs.tf}\. The file must contain entries " - rf"for the the exact start and end dates from the config\. $" + rf"^ERROR loading file {tmp_file} for parameter sigma: " + rf"the 'date' entries of the provided file do not include " + rf"all the days specified to be modeled by the config\. the provided file includes " + rf"{(timeseries_end_date - timeseries_start_date).days + 1} days between " + rf"{timeseries_start_date} to {timeseries_end_date}, while there are " + rf"{mock_inputs.number_of_days()} days in the config time span of {mock_inputs.ti}->{mock_inputs.tf}\. " + rf"The file must contain entries for the exact start and end dates from the config\.$" ), ): mock_inputs.create_parameters_instance() diff --git a/flepimop/gempyor_pkg/tests/seir/test_ic.py b/flepimop/gempyor_pkg/tests/seir/test_ic.py index e2d78eb35..a24f141ea 100644 --- a/flepimop/gempyor_pkg/tests/seir/test_ic.py +++ b/flepimop/gempyor_pkg/tests/seir/test_ic.py @@ -44,7 +44,7 @@ def test_IC_allow_missing_node_compartments_success(self): sic.get_from_config(sim_id=100, modinf=s) def test_IC_IC_notImplemented_fail(self): - with pytest.raises(NotImplementedError, match=r"^Unknown initial conditions method \[received: .*\]\.$"): + with pytest.raises(NotImplementedError, match=r"^Unknown initial conditions method \[received: .*?\]\.$"): config.clear() config.read(user=False) config.set_file(f"{DATA_DIR}/config.yml") From e3df5d8e11332e043bab71d5a22e169e7b9938f6 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Wed, 2 Oct 2024 16:18:21 -0400 Subject: [PATCH 06/48] Update initial_conditions.py --- flepimop/gempyor_pkg/src/gempyor/initial_conditions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py b/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py index 1b50c0988..c17fd78be 100644 --- a/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py +++ b/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py @@ -99,7 +99,7 @@ def get_from_config(self, sim_id: int, modinf) -> np.ndarray: allow_missing_subpops=self.allow_missing_subpops, ) else: - raise NotImplementedError(f"Unknown initial conditions method [recieved: {method}].") + raise NotImplementedError(f"Unknown initial conditions method [received: {method}].") # check that the inputed values sums to the subpop population: check_population(y0=y0, modinf=modinf, ignore_population_checks=self.ignore_population_checks) From 2066ee43776706fcb4ca2055415eb74a324cf810 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Wed, 2 Oct 2024 16:45:19 -0400 Subject: [PATCH 07/48] Update parameters.py --- flepimop/gempyor_pkg/src/gempyor/parameters.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/parameters.py b/flepimop/gempyor_pkg/src/gempyor/parameters.py index 02f4bbba6..c9d1886ec 100644 --- a/flepimop/gempyor_pkg/src/gempyor/parameters.py +++ b/flepimop/gempyor_pkg/src/gempyor/parameters.py @@ -136,7 +136,7 @@ def __init__( f"ERROR loading file {fn_name} for parameter {pn}: " f"the 'date' entries of the provided file do not include all the days specified to be modeled by " f"the config. the provided file includes {len(df.index)} days between {str(df.index[0])} to {str(df.index[-1])}, " - f"while there are {len(pd.date_range(ti, tf))} days in the config time span of {ti}->{tf}. The file must contain entries for the " + f"while there are {len(pd.date_range(ti, tf))} days in the config time span of {ti}->{tf}. The file must contain entries for " f"the exact start and end dates from the config." ) if not (pd.date_range(ti, tf) == df.index).all(): @@ -145,8 +145,8 @@ def __init__( raise ValueError( f"ERROR loading file {fn_name} for parameter {pn}: " f"the 'date' entries of the provided file do not include all the days specified to be modeled by " - f" the config. the provided file includes {len(df.index)} days between {str(df.index[0])} to {str(df.index[-1])}, " - f"while there are {len(pd.date_range(ti, tf))} days in the config time span of {ti}->{tf}. The file must contain entries for the " + f"the config. the provided file includes {len(df.index)} days between {str(df.index[0])} to {str(df.index[-1])}, " + f"while there are {len(pd.date_range(ti, tf))} days in the config time span of {ti}->{tf}. The file must contain entries for " f"the exact start and end dates from the config." ) From 2b3feedd668dc952d9eab11be6e6e3335798b54b Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 4 Oct 2024 14:03:07 -0400 Subject: [PATCH 08/48] Update flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py index e66aca4c2..f5b5fe150 100644 --- a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py +++ b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py @@ -286,7 +286,7 @@ def test_timeseries_parameter_has_insufficient_dates_value_error( rf"the 'date' entries of the provided file do not include " rf"all the days specified to be modeled by the config\. the provided file includes " rf"{(timeseries_end_date - timeseries_start_date).days + 1} days between " - rf"{timeseries_start_date} to {timeseries_end_date}, while there are " + rf"{timeseries_start_date}( 00:00:00)? to {timeseries_end_date}( 00:00:00)?, while there are " rf"{mock_inputs.number_of_days()} days in the config time span of {mock_inputs.ti}->{mock_inputs.tf}\. " rf"The file must contain entries for the exact start and end dates from the config\.$" ), From 72aaa843bbd907b570d1b0ca8694fb6f762d25c4 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Fri, 4 Oct 2024 15:03:10 -0400 Subject: [PATCH 09/48] Small adjustments to compartments.py --- flepimop/gempyor_pkg/src/gempyor/compartments.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/compartments.py b/flepimop/gempyor_pkg/src/gempyor/compartments.py index 027ea671c..d9be0f8ef 100644 --- a/flepimop/gempyor_pkg/src/gempyor/compartments.py +++ b/flepimop/gempyor_pkg/src/gempyor/compartments.py @@ -396,8 +396,7 @@ def get_transition_array(self): if self.compartments["name"][compartment] == elem: rc = compartment if rc == -1: - print(self.compartments) - raise ValueError(f"Could not find {colname} defined by {elem} in compartments.") + raise ValueError(f"Could not find {colname} defined by {elem} in {self.compartments}.") transition_array[cit, it] = rc unique_strings = [] @@ -616,7 +615,7 @@ def parse_parameter_strings_to_numpy_arrays( raise ValueError( f"Could not parse string {string_list}. " f"This usually mean that '{string_list[0]}' is a parameter name that is not defined " - f" or that it contains an operator that is not in the list of supported operator: ^,*,/,+,-. " + f"or that it contains an operator that is not in the list of supported operators: ^,*,/,+,-. " f"The defined parameters are {parameter_names}." ) From 4639721d846e4bce477f3326f4a9872823d9c09c Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Fri, 4 Oct 2024 15:44:58 -0400 Subject: [PATCH 10/48] Some more small syntactical adjustments. --- .../src/gempyor/config_validator.py | 50 +++++++++---------- .../src/gempyor/initial_conditions.py | 5 +- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index 3b8b9a36d..acacd8b35 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -42,9 +42,9 @@ def validate_initial_file_check(cls, values): initial_conditions_file = values.get('initial_conditions_file') initial_file_type = values.get('initial_file_type') if method in {'FromFile', 'SetInitialConditions'} and not initial_conditions_file: - raise ValueError(f'Error in InitialConditions: An initial_conditions_file is required when method is {method}') + raise ValueError(f"Error in InitialConditions: An initial_conditions_file is required when method is {method}") if method in {'InitialConditionsFolderDraw','SetInitialConditionsFolderDraw'} and not initial_file_type: - raise ValueError(f'Error in InitialConditions: initial_file_type is required when method is {method}') + raise ValueError(f"Error in InitialConditions: initial_file_type is required when method is {method}") return values @model_validator(mode='before') @@ -52,7 +52,7 @@ def plugin_filecheck(cls, values): method = values.get('method') plugin_file_path = values.get('plugin_file_path') if method == 'plugin' and not plugin_file_path: - raise ValueError(f'Error in InitialConditions: a plugin file path is required when method is plugin.') + raise ValueError(f"Error in InitialConditions: a plugin file path is required when method is plugin.") return values @@ -71,18 +71,18 @@ def validate_seedingfile(cls, values): seeding_file = values.get('seeding_file') if method == 'PoissonDistributed' and not lambda_file: raise ValueError( - f'Error in Seeding: A lambda_file is required when method is {method} ' - f'Current value: {lambda_file}.' + f"Error in Seeding: A lambda_file is required when method is {method} " + f"Current value: {lambda_file}." ) if method == 'FolderDraw' and not seeding_file_type: raise ValueError( - f'Error in Seeding: A seeding_file_type is required when method is FolderDraw' - f'Current value: {seeding_file_type}.' + f"Error in Seeding: A seeding_file_type is required when method is FolderDraw" + f"Current value: {seeding_file_type}." ) if method == 'FromFile' and not seeding_file: raise ValueError( - f'Error in Seeding: A seeding_file is required when method is FromFile ' - f'Current value: {seeding_file}.' + f"Error in Seeding: A seeding_file is required when method is FromFile " + f"Current value: {seeding_file}." ) return values @@ -92,8 +92,8 @@ def plugin_filecheck(cls, values): plugin_file_path = values.get('plugin_file_path') if method == 'plugin' and not plugin_file_path: raise ValueError( - f'Error in Seeding: a plugin file path is required when method is plugin' - f'Current value: {plugin_file_path!r}. Please specify the path to the plugin file.' + f"Error in Seeding: a plugin file path is required when method is plugin " + f"Current value: {plugin_file_path!r}. Please specify the path to the plugin file." ) return values @@ -119,11 +119,11 @@ def check_distr(cls, values): b = values.get('b') if distr != 'fixed': if not mean and not sd: - raise ValueError('Mean and sd must be provided for non-fixed distributions.') + raise ValueError(f"Mean and sd must be provided for non-fixed distributions.") if distr == 'truncnorm' and not a and not b: - raise ValueError('a and b must be provided for truncated normal distributions.') + raise ValueError(f"a and b must be provided for truncated normal distributions.") if distr == 'fixed' and not value: - raise ValueError('Value must be provided for fixed distributions') + raise ValueError(f"Value must be provided for fixed distributions") return values class BaseParameterConfig(BaseModel): @@ -143,8 +143,8 @@ def which_value(cls, values): timeseries = values.get('timeseries') is not None if value and timeseries: raise ValueError( - f'Configuration error in seir::parameters: your parameter is both a timeseries and a value, please choose one. ' - f'Current values - value: {values.get('value')!r}, timeseries: {values.get('timeseries')!r}.' + f"Configuration error in seir::parameters: your parameter is both a timeseries and a value, please choose one. " + f"Current values - value: {values.get('value')!r}, timeseries: {values.get('timeseries')!r}." ) return values @@ -219,9 +219,9 @@ def which_source(cls, values): prevalence = values.get('prevalence') if incidence and prevalence: raise ValueError( - f'Configuration error in outcomes::source.' - f'Value can only be incidence or prevalence, not both.' - f'Current values - incidence: {values.get('incidence')!r}, prevalence: {values.get('prevalence')!r}.' + f"Configuration error in outcomes::source." + f"Value can only be incidence or prevalence, not both." + f"Current values - incidence: {values.get('incidence')!r}, prevalence: {values.get('prevalence')!r}." ) return values @@ -340,13 +340,13 @@ def verify_inference(cls, values): start_date_groundtruth = values.get('start_date_groundtruth') is not None if inference_present and not start_date_groundtruth: raise ValueError( - f'Inference mode is enabled, but no groundtruth dates are provided.' - f'Please provide groundtruth dates.' + f"Inference mode is enabled, but no groundtruth dates are provided." + f"Please provide groundtruth dates." ) elif start_date_groundtruth and not inference_present: raise ValueError( - f'Groundtruth dates are provided, but inference mode is not enabled.' - f'Please enable inference mode.' + f"Groundtruth dates are provided, but inference mode is not enabled." + f"Please enable inference mode." ) return values @@ -357,7 +357,7 @@ def check_dates(cls, values): if start_date and end_date: if end_date <= start_date: raise ValueError( - f'`end_date` ({end_date}) must be greater than `start_date` ({start_date})).' + f"`end_date` ({end_date}) must be later than `start_date` ({start_date}))." ) return values @@ -367,6 +367,6 @@ def init_or_seed(cls, values): seed = values.get('seeding') if not init or seed: raise ValueError( - f'At least one of `initial_conditions` or `seeding` must be provided.' + f"At least one of `initial_conditions` or `seeding` must be provided." ) return values diff --git a/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py b/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py index c17fd78be..396308ee4 100644 --- a/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py +++ b/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py @@ -182,7 +182,7 @@ def read_initial_condition_from_tidydataframe( logger.critical( f"No initial conditions for for subpop {pl}, assuming everyone (n={modinf.subpop_pop[pl_idx]}) in the first metacompartment ({modinf.compartments.compartments['name'].iloc[0]})" ) - raise ValueError("THERE IS A BUG; REPORT THIS MESSAGE. Past implemenation was buggy.") + raise ValueError(f"THERE IS A BUG; REPORT THIS MESSAGE. Past implemenation was buggy.") # TODO: this is probably ok but highlighting for consistency if "proportional" in self.initial_conditions_config.keys(): if self.initial_conditions_config["proportional"].get(): @@ -235,7 +235,8 @@ def read_initial_condition_from_seir_output(ic_df, modinf, allow_missing_subpops ic_df = ic_df[(ic_df["date"] == str(modinf.ti)) & (ic_df["mc_value_type"] == "prevalence")] if ic_df.empty: - raise ValueError(f"No entry provided for initial time `ti` in the `initial_conditions::states_file.`") + raise ValueError(f"No entry provided for initial time `ti` in the `initial_conditions::states_file.` " + f"`ti`: {modinf.ti}.") y0 = np.zeros((modinf.compartments.compartments.shape[0], modinf.nsubpops)) for comp_idx, comp_name in modinf.compartments.compartments["name"].items(): From 064ec7ef1226a982acd2c1a759d212d4313f4b2c Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Mon, 14 Oct 2024 12:24:09 -0400 Subject: [PATCH 11/48] Update flepimop/gempyor_pkg/src/gempyor/compartments.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/compartments.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/compartments.py b/flepimop/gempyor_pkg/src/gempyor/compartments.py index d9be0f8ef..43f5aa5e3 100644 --- a/flepimop/gempyor_pkg/src/gempyor/compartments.py +++ b/flepimop/gempyor_pkg/src/gempyor/compartments.py @@ -427,8 +427,7 @@ def get_transition_array(self): # candidate = candidate.replace("*1", "") if candidate not in unique_strings: raise ValueError( - f"Candidate '{candidate}' from 'rate' column is not in the list of unique strings. " - f"Unique strings: {unique_strings}" + f"Candidate '{candidate}' from 'rate' column is not in the list of unique strings: {unique_strings}" ) rc = [it for it, x in enumerate(unique_strings) if x == candidate][0] transition_array[2][it] = rc From f614127688a634e5639a11774a0e48799e17f69c Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Wed, 16 Oct 2024 09:56:35 -0400 Subject: [PATCH 12/48] Continuing to evolve error/exception messags Making '' and `` conventions consistent, removing unnecessary f-strings, added some warnings.warn() statements instead of print() statements. --- .../gempyor_pkg/src/gempyor/compartments.py | 62 +++++++++---------- .../src/gempyor/config_validator.py | 47 +++++++------- flepimop/gempyor_pkg/src/gempyor/inference.py | 8 +-- .../src/gempyor/initial_conditions.py | 52 ++++++++-------- .../gempyor_pkg/src/gempyor/parameters.py | 18 +++--- 5 files changed, 91 insertions(+), 96 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/compartments.py b/flepimop/gempyor_pkg/src/gempyor/compartments.py index d9be0f8ef..ac15e2de4 100644 --- a/flepimop/gempyor_pkg/src/gempyor/compartments.py +++ b/flepimop/gempyor_pkg/src/gempyor/compartments.py @@ -127,10 +127,10 @@ def expand_transition_elements(self, single_transition_config, problem_dimension ) except Exception as e: print(f"Error {e}:") - print(f">>> in expand_transition_elements for `source:` at index {it.multi_index}") - print(f">>> this transition source is: {single_transition_config['source']}") - print(f">>> this transition destination is: {single_transition_config['destination']}") - print(f"transition_dimension: {problem_dimension}") + print(f">>> in expand_transition_elements for `source:` at index '{it.multi_index}'") + print(f">>> this transition source is: '{single_transition_config['source']}'") + print(f">>> this transition destination is: '{single_transition_config['destination']}'") + print(f"transition_dimension: '{problem_dimension}'") raise e try: @@ -139,10 +139,10 @@ def expand_transition_elements(self, single_transition_config, problem_dimension ) except Exception as e: print(f"Error {e}:") - print(f">>> in expand_transition_elements for `destination:` at index {it.multi_index}") - print(f">>> this transition source is: {single_transition_config['source']}") - print(f">>> this transition destination is: {single_transition_config['destination']}") - print(f"transition_dimension: {problem_dimension}") + print(f">>> in expand_transition_elements for `destination:` at index '{it.multi_index}'") + print(f">>> this transition source is: '{single_transition_config['source']}'") + print(f">>> this transition destination is: '{single_transition_config['destination']}'") + print(f"transition_dimension: '{problem_dimension}'") raise e try: @@ -151,10 +151,10 @@ def expand_transition_elements(self, single_transition_config, problem_dimension ) except Exception as e: print(f"Error {e}:") - print(f">>> in expand_transition_elements for `rate:` at index {it.multi_index}") - print(f">>> this transition source is: {single_transition_config['source']}") - print(f">>> this transition destination is: {single_transition_config['destination']}") - print(f"transition_dimension: {problem_dimension}") + print(f">>> in expand_transition_elements for `rate:` at index '{it.multi_index}'") + print(f">>> this transition source is: '{single_transition_config['source']}'") + print(f">>> this transition destination is: '{single_transition_config['destination']}'") + print(f"transition_dimension: '{problem_dimension}'") raise e try: @@ -173,10 +173,10 @@ def expand_transition_elements(self, single_transition_config, problem_dimension ) except Exception as e: print(f"Error {e}:") - print(f">>> in expand_transition_elements for `proportional_to:` at index {it.multi_index}") - print(f">>> this transition source is: {single_transition_config['source']}") - print(f">>> this transition destination is: {single_transition_config['destination']}") - print(f"transition_dimension: {problem_dimension}") + print(f">>> in expand_transition_elements for `proportional_to:` at index '{it.multi_index}'") + print(f">>> this transition source is: '{single_transition_config['source']}'") + print(f">>> this transition destination is: '{single_transition_config['destination']}'") + print(f"transition_dimension: '{problem_dimension}'") raise e if "proportion_exponent" in single_transition_config: # if proportion_exponent is not defined, it is set to 1 @@ -198,10 +198,10 @@ def expand_transition_elements(self, single_transition_config, problem_dimension ) except Exception as e: print(f"Error {e}:") - print(f">>> in expand_transition_elements for `proportion_exponent:` at index {it.multi_index}") - print(f">>> this transition source is: {single_transition_config['source']}") - print(f">>> this transition destination is: {single_transition_config['destination']}") - print(f"transition_dimension: {problem_dimension}") + print(f">>> in expand_transition_elements for `proportion_exponent:` at index '{it.multi_index}'") + print(f">>> this transition source is: '{single_transition_config['source']}'") + print(f">>> this transition destination is: '{single_transition_config['destination']}'") + print(f"transition_dimension: '{problem_dimension}'") raise e else: new_transition_config["proportion_exponent"][it.multi_index] = ["1"] * proportion_size @@ -375,8 +375,8 @@ def get_comp_idx(self, comp_dict: dict, error_info: str = "no information") -> i comp_idx = self.compartments[mask].index.values if len(comp_idx) != 1: raise ValueError( - f"The provided dictionary does not allow to isolate a compartment: {comp_dict} " - f" isolate {self.compartments[mask]} from options {self.compartments}. " + f"The provided dictionary does not allow an isolated compartment: '{comp_dict}' " + f"Isolate '{self.compartments[mask]}'. " f"The get_comp_idx function was called by '{error_info}'." ) return comp_idx[0] @@ -396,7 +396,7 @@ def get_transition_array(self): if self.compartments["name"][compartment] == elem: rc = compartment if rc == -1: - raise ValueError(f"Could not find {colname} defined by {elem} in {self.compartments}.") + raise ValueError(f"Could not find '{colname}' defined by '{elem}' in '{self.compartments}'.") transition_array[cit, it] = rc unique_strings = [] @@ -428,7 +428,7 @@ def get_transition_array(self): if candidate not in unique_strings: raise ValueError( f"Candidate '{candidate}' from 'rate' column is not in the list of unique strings. " - f"Unique strings: {unique_strings}" + f"Unique strings: '{unique_strings}'" ) rc = [it for it, x in enumerate(unique_strings) if x == candidate][0] transition_array[2][it] = rc @@ -470,8 +470,7 @@ def get_transition_array(self): # candidate = candidate.replace("*1", "") if candidate not in unique_strings: raise ValueError( - f"Proportion exponent '{candidate}' is not found in the list of unique strings. " - f"Unique strings: {unique_strings}" + f"Proportion exponent '{candidate}' is not found in the list of unique strings: '{unique_strings}'" ) rc = [it for it, x in enumerate(unique_strings) if x == candidate][0] proportion_info[2][proportion_compartment_index] = rc @@ -565,8 +564,7 @@ def parse_parameter_strings_to_numpy_arrays_v2(self, parameters, parameter_names parsed_formulas.append(f) except Exception as e: print( - f"Cannot parse formula: '{formula}' :" - f"from parameters: {parameter_names}." + f"Cannot parse formula: '{formula}' from parameters: '{parameter_names}'." ) raise (e) # Print the error message for debugging @@ -613,10 +611,10 @@ def parse_parameter_strings_to_numpy_arrays( not operators ): # empty list means all have been tried. Usually there just remains one string in string_list at that time. raise ValueError( - f"Could not parse string {string_list}. " + f"Could not parse string '{string_list}'. " f"This usually mean that '{string_list[0]}' is a parameter name that is not defined " f"or that it contains an operator that is not in the list of supported operators: ^,*,/,+,-. " - f"The defined parameters are {parameter_names}." + f"The defined parameters are '{parameter_names}'." ) split_strings = [x.split(operators[0]) for x in string_list] @@ -725,10 +723,10 @@ def list_access_element_safe(thing, idx, dimension=None, encapsulate_as_list=Fal except Exception as e: raise Exception( f"Error {e}: " - f"in list_access_element_safe for {thing} at index {idx}. " + f"in list_access_element_safe for '{thing}' at index '{idx}'. " f"This is often, but not always because the object above is a list (there are brackets around it). " f"and in this case it is not broadcast, so if you want to it to be broadcasted, you need remove the brackets around it. " - f"dimension: {dimension}." + f"dimension: '{dimension}'." ) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index acacd8b35..b1bcd7cce 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -42,9 +42,9 @@ def validate_initial_file_check(cls, values): initial_conditions_file = values.get('initial_conditions_file') initial_file_type = values.get('initial_file_type') if method in {'FromFile', 'SetInitialConditions'} and not initial_conditions_file: - raise ValueError(f"Error in InitialConditions: An initial_conditions_file is required when method is {method}") + raise ValueError(f"Error in InitialConditions: An initial_conditions_file is required when method is '{method}'.") if method in {'InitialConditionsFolderDraw','SetInitialConditionsFolderDraw'} and not initial_file_type: - raise ValueError(f"Error in InitialConditions: initial_file_type is required when method is {method}") + raise ValueError(f"Error in InitialConditions: initial_file_type is required when method is '{method}'.") return values @model_validator(mode='before') @@ -52,7 +52,7 @@ def plugin_filecheck(cls, values): method = values.get('method') plugin_file_path = values.get('plugin_file_path') if method == 'plugin' and not plugin_file_path: - raise ValueError(f"Error in InitialConditions: a plugin file path is required when method is plugin.") + raise ValueError("Error in InitialConditions: a plugin file path is required when method is plugin.") return values @@ -71,18 +71,18 @@ def validate_seedingfile(cls, values): seeding_file = values.get('seeding_file') if method == 'PoissonDistributed' and not lambda_file: raise ValueError( - f"Error in Seeding: A lambda_file is required when method is {method} " - f"Current value: {lambda_file}." + f"Error in Seeding: A lambda_file is required when method is '{method}'. " + f"Current value: '{lambda_file}'." ) if method == 'FolderDraw' and not seeding_file_type: raise ValueError( - f"Error in Seeding: A seeding_file_type is required when method is FolderDraw" - f"Current value: {seeding_file_type}." + f"Error in Seeding: A seeding_file_type is required when method is FolderDraw. " + f"Current value: '{seeding_file_type}'." ) if method == 'FromFile' and not seeding_file: raise ValueError( - f"Error in Seeding: A seeding_file is required when method is FromFile " - f"Current value: {seeding_file}." + f"Error in Seeding: A seeding_file is required when method is FromFile. " + f"Current value: '{seeding_file}'." ) return values @@ -92,8 +92,8 @@ def plugin_filecheck(cls, values): plugin_file_path = values.get('plugin_file_path') if method == 'plugin' and not plugin_file_path: raise ValueError( - f"Error in Seeding: a plugin file path is required when method is plugin " - f"Current value: {plugin_file_path!r}. Please specify the path to the plugin file." + f"Error in Seeding: a plugin file path is required when method is plugin. " + f"Current value: '{plugin_file_path!r}'. Please specify the path to the plugin file." ) return values @@ -119,11 +119,11 @@ def check_distr(cls, values): b = values.get('b') if distr != 'fixed': if not mean and not sd: - raise ValueError(f"Mean and sd must be provided for non-fixed distributions.") + raise ValueError("Mean and sd must be provided for non-fixed distributions.") if distr == 'truncnorm' and not a and not b: - raise ValueError(f"a and b must be provided for truncated normal distributions.") + raise ValueError("a and b must be provided for truncated normal distributions.") if distr == 'fixed' and not value: - raise ValueError(f"Value must be provided for fixed distributions") + raise ValueError("Value must be provided for fixed distributions.") return values class BaseParameterConfig(BaseModel): @@ -144,7 +144,7 @@ def which_value(cls, values): if value and timeseries: raise ValueError( f"Configuration error in seir::parameters: your parameter is both a timeseries and a value, please choose one. " - f"Current values - value: {values.get('value')!r}, timeseries: {values.get('timeseries')!r}." + f"Current values - value: '{values.get('value')!r}', timeseries: '{values.get('timeseries')!r}'." ) return values @@ -221,7 +221,7 @@ def which_source(cls, values): raise ValueError( f"Configuration error in outcomes::source." f"Value can only be incidence or prevalence, not both." - f"Current values - incidence: {values.get('incidence')!r}, prevalence: {values.get('prevalence')!r}." + f"Current values - incidence: '{values.get('incidence')!r}', prevalence: '{values.get('prevalence')!r}'." ) return values @@ -258,9 +258,9 @@ def check_outcome_type(cls, values): source_present = values.get('source') is not None if sum_present and source_present: - raise ValueError(f"Error in outcome: Both 'sum' and 'source' are present. Choose one.") + raise ValueError("Error in outcome: Both 'sum' and 'source' are present. Choose one.") elif not sum_present and not source_present: - raise ValueError(f"Error in outcome: Neither 'sum' nor 'source' is present. Choose one.") + raise ValueError("Error in outcome: Neither 'sum' nor 'source' is present. Choose one.") return values class OutcomesConfig(BaseModel): @@ -275,7 +275,7 @@ def check_paramfromfile_type(cls, values): param_subpop_file = values.get('param_subpop_file') is not None if param_from_file and not param_subpop_file: - raise ValueError(f"Error in outcome: 'param_subpop_file' is required when 'param_from_file' is True.") + raise ValueError("Error in outcome: `param_subpop_file` is required when `param_from_file` is 'True'.") return values class ResampleConfig(BaseModel): @@ -339,14 +339,11 @@ def verify_inference(cls, values): inference_present = values.get('inference') is not None start_date_groundtruth = values.get('start_date_groundtruth') is not None if inference_present and not start_date_groundtruth: - raise ValueError( - f"Inference mode is enabled, but no groundtruth dates are provided." - f"Please provide groundtruth dates." + raise ValueError("Inference mode is enabled, but no groundtruth dates are provided. Please provide groundtruth dates." ) elif start_date_groundtruth and not inference_present: raise ValueError( - f"Groundtruth dates are provided, but inference mode is not enabled." - f"Please enable inference mode." + f"Groundtruth dates are provided, but inference mode is not enabled. Please enable inference mode." ) return values @@ -357,7 +354,7 @@ def check_dates(cls, values): if start_date and end_date: if end_date <= start_date: raise ValueError( - f"`end_date` ({end_date}) must be later than `start_date` ({start_date}))." + f"`end_date` ('{end_date}') must be later than `start_date` ('{start_date}'))." ) return values diff --git a/flepimop/gempyor_pkg/src/gempyor/inference.py b/flepimop/gempyor_pkg/src/gempyor/inference.py index a03239e5b..fa28991de 100644 --- a/flepimop/gempyor_pkg/src/gempyor/inference.py +++ b/flepimop/gempyor_pkg/src/gempyor/inference.py @@ -269,8 +269,8 @@ def autodetect_scenarios(config): if len(seir_modifiers_scenarios) != 1 or len(outcome_modifiers_scenarios) != 1: raise ValueError( f"Inference only supports configuration files with one scenario, recieved:\n" - f"SEIR modifiers: {seir_modifiers_scenarios}." - f"Outcomes modifiers: {outcome_modifiers_scenarios}." + f"SEIR modifiers: '{seir_modifiers_scenarios}'." + f"Outcomes modifiers: '{outcome_modifiers_scenarios}'." ) return seir_modifiers_scenarios[0], outcome_modifiers_scenarios[0] @@ -417,7 +417,7 @@ def get_all_sim_arguments(self): def get_logloss(self, proposal): if not self.inferpar.check_in_bound(proposal=proposal): if not self.silent: - print("OUT OF BOUND!!") + print("OUT OF BOUNDS!!") return -np.inf, -np.inf, -np.inf snpi_df_mod, hnpi_df_mod = self.inferpar.inject_proposal( @@ -438,7 +438,7 @@ def get_logloss(self, proposal): model_df=outcomes_df, subpop_names=self.modinf.subpop_struct.subpop_names ) if not self.silent: - print(f"llik is {ll_total}") + print(f"llik is '{ll_total}' ") return ll_total, logloss, regularizations diff --git a/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py b/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py index 396308ee4..3e5b67490 100644 --- a/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py +++ b/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py @@ -8,6 +8,7 @@ from .simulation_component import SimulationComponent from . import utils from .utils import read_df +import warnings import os logger = logging.getLogger(__name__) @@ -99,7 +100,7 @@ def get_from_config(self, sim_id: int, modinf) -> np.ndarray: allow_missing_subpops=self.allow_missing_subpops, ) else: - raise NotImplementedError(f"Unknown initial conditions method [received: {method}].") + raise NotImplementedError(f"Unknown initial conditions method [received: '{method}'].") # check that the inputed values sums to the subpop population: check_population(y0=y0, modinf=modinf, ignore_population_checks=self.ignore_population_checks) @@ -121,21 +122,20 @@ def check_population(y0, modinf, ignore_population_checks=False): n_pop = modinf.subpop_pop[pl_idx] if abs(n_y0 - n_pop) > 1: error = True - print( - f"ERROR: subpop_names {pl} (idx: pl_idx) has a population from initial condition of {n_y0} " - f"while population from geodata is {n_pop}." - f"(absolute difference should be < 1, here is {abs(n_y0-n_pop)})." + warnings.warn( + f"ERROR: subpop_names {pl} (idx: plx_idx) has a population from initial condition of {n_y0} " + f"while population geodata is {n_pop}. " + f"(absolute difference should be <1, here is {abs(n_y0-n_pop)})." ) if error and not ignore_population_checks: - raise ValueError( - f"Geodata and initial condition do not agree on population size (see messages above). " - f"Use `ignore_population_checks: True` to ignore." + raise ValueError("Geodata and initial condition do not agree on population size. Use `ignore_population_checks: True` to ignore." ) elif error and ignore_population_checks: - print( - f"WARNING: population mismatch errors ignored because `ignore_population_checks` is set to `True`." - f"Execution will continue, but this is not recommended." + warnings.warn( + "WARNING: Population mismatch errors ignored because `ignore_population_checks` is set to `True`. " + "Execution will continue, but this is not recommended.", + UserWarning ) @@ -159,16 +159,15 @@ def read_initial_condition_from_tidydataframe( ]["amount"] if len(ic_df_compartment_val) > 1: raise ValueError( - f"ERROR: Several ({len(ic_df_compartment_val)}) rows are matches for compartment {comp_name} in init file: filters returned {ic_df_compartment_val}" + f"Several ('{len(ic_df_compartment_val)}') rows are matches for compartment '{comp_name}' in init file: filters returned '{ic_df_compartment_val}'" ) elif ic_df_compartment_val.empty: if allow_missing_compartments: ic_df_compartment_val = 0.0 else: raise ValueError( - f"ERROR: Multiple rows ({len(ic_df_compartment_val)}) match for compartment '{comp_name}' in the initial conditions file. " - f"Filters used: {filters.to_dict()}. Matches: {ic_df_compartment_val.tolist()}. " - f"Ensure that each compartment has a unique initial condition entry." + f"Multiple rows match for compartment '{comp_name}' in the initial conditions file; ensure each compartment has a unique entry. " + f"Filters used: '{filters.to_dict()}'. Matches: '{ic_df_compartment_val.tolist()}'." ) if "rest" in str(ic_df_compartment_val).strip().lower(): rests.append([comp_idx, pl_idx]) @@ -182,7 +181,7 @@ def read_initial_condition_from_tidydataframe( logger.critical( f"No initial conditions for for subpop {pl}, assuming everyone (n={modinf.subpop_pop[pl_idx]}) in the first metacompartment ({modinf.compartments.compartments['name'].iloc[0]})" ) - raise ValueError(f"THERE IS A BUG; REPORT THIS MESSAGE. Past implemenation was buggy.") + raise RuntimeError("There is a bug; report this message. Past implemenation was buggy.") # TODO: this is probably ok but highlighting for consistency if "proportional" in self.initial_conditions_config.keys(): if self.initial_conditions_config["proportional"].get(): @@ -193,7 +192,7 @@ def read_initial_condition_from_tidydataframe( y0[0, pl_idx] = modinf.subpop_pop[pl_idx] else: raise ValueError( - f"Subpop {pl} does not exist in `initial_conditions::states_file`. " + f"Subpop '{pl}' does not exist in `initial_conditions::states_file`. " f"You can set `allow_missing_subpops=TRUE` to bypass this error." ) if rests: # not empty @@ -236,7 +235,7 @@ def read_initial_condition_from_seir_output(ic_df, modinf, allow_missing_subpops ic_df = ic_df[(ic_df["date"] == str(modinf.ti)) & (ic_df["mc_value_type"] == "prevalence")] if ic_df.empty: raise ValueError(f"No entry provided for initial time `ti` in the `initial_conditions::states_file.` " - f"`ti`: {modinf.ti}.") + f"`ti`: '{modinf.ti}'.") y0 = np.zeros((modinf.compartments.compartments.shape[0], modinf.nsubpops)) for comp_idx, comp_name in modinf.compartments.compartments["name"].items(): @@ -251,27 +250,28 @@ def read_initial_condition_from_seir_output(ic_df, modinf, allow_missing_subpops if len(ic_df_compartment) > 1: # ic_df_compartment = ic_df_compartment.iloc[0] raise ValueError( - f"ERROR: Several ({len(ic_df_compartment)}) rows are matches for compartment {mc_name} in init file: filter {filters}. " - f"returned: {ic_df_compartment}." + f"Several ('{len(ic_df_compartment)}') rows are matches for compartment '{mc_name}' in init file: " + f"filter '{filters}'. " + f"returned: '{ic_df_compartment}'." ) elif ic_df_compartment.empty: if allow_missing_compartments: ic_df_compartment = pd.DataFrame(0, columns=ic_df_compartment.columns, index=[0]) else: raise ValueError( - f"Initial Conditions: could not set compartment {comp_name} (id: {comp_idx}) in subpop {pl} (id: {pl_idx}). " - f"The data from the init file is {ic_df_compartment[pl]}." + f"Initial Conditions: could not set compartment '{comp_name}' (id: '{comp_idx}') in subpop '{pl}' (id: '{pl_idx}'). " + f"The data from the init file is '{ic_df_compartment[pl]}'." ) elif ic_df_compartment["mc_name"].iloc[0] != comp_name: - print( - f"WARNING: init file `mc_name` {ic_df_compartment['mc_name'].iloc[0]} does not match compartment `mc_name` {comp_name}." + warnings.warn( + f"{ic_df_compartment['mc_name'].iloc[0]} does not match compartment `mc_name` {comp_name}." ) for pl_idx, pl in enumerate(modinf.subpop_struct.subpop_names): if pl in ic_df.columns: y0[comp_idx, pl_idx] = float(ic_df_compartment[pl].iloc[0]) elif allow_missing_subpops: - raise ValueError("THERE IS A BUG; REPORT THIS MESSAGE. Past implemenation was buggy") + raise ValueError("There is a bug; report this message. Past implemenation was buggy") # TODO this should set the full subpop, not just the 0th commpartment logger.critical( f"No initial conditions for for subpop {pl}, assuming everyone (n={modinf.subpop_pop[pl_idx]}) in the first metacompartments ({modinf.compartments.compartments['name'].iloc[0]})" @@ -282,7 +282,7 @@ def read_initial_condition_from_seir_output(ic_df, modinf, allow_missing_subpops y0[0, pl_idx] = modinf.subpop_pop[pl_idx] else: raise ValueError( - f"Subpop {pl} does not exist in `initial_conditions::states_file`. " + f"Subpop '{pl}' does not exist in `initial_conditions::states_file`. " f"You can set `allow_missing_subpops=TRUE` to bypass this error." ) return y0 diff --git a/flepimop/gempyor_pkg/src/gempyor/parameters.py b/flepimop/gempyor_pkg/src/gempyor/parameters.py index c9d1886ec..248e9254c 100644 --- a/flepimop/gempyor_pkg/src/gempyor/parameters.py +++ b/flepimop/gempyor_pkg/src/gempyor/parameters.py @@ -123,9 +123,9 @@ def __init__( print("loaded col :", sorted(list(df.columns))) print("geodata col:", sorted(subpop_names)) raise ValueError( - f"Error loading file {fn_name} for parameter {pn}: " - f"the number of non-'date' columns is {len(df.columns)}, " - f"expected {len(subpop_names)} (number of subpopulations) or one." + f"Issue loading file '{fn_name}' for parameter '{pn}': " + f"the number of non-'date' columns is '{len(df.columns)}', " + f"expected '{len(subpop_names)}' (number of subpopulations) or one." ) df = df[str(ti) : str(tf)] @@ -133,20 +133,20 @@ def __init__( print("config dates:", pd.date_range(ti, tf)) print("loaded dates:", df.index) raise ValueError( - f"ERROR loading file {fn_name} for parameter {pn}: " + f"Issue loading file '{fn_name}' for parameter '{pn}': " f"the 'date' entries of the provided file do not include all the days specified to be modeled by " - f"the config. the provided file includes {len(df.index)} days between {str(df.index[0])} to {str(df.index[-1])}, " - f"while there are {len(pd.date_range(ti, tf))} days in the config time span of {ti}->{tf}. The file must contain entries for " + f"the config. the provided file includes '{len(df.index)}' days between '{str(df.index[0])}' to '{str(df.index[-1])}', " + f"while there are '{len(pd.date_range(ti, tf))}' days in the config time span of '{ti}->{tf}'. The file must contain entries for " f"the exact start and end dates from the config." ) if not (pd.date_range(ti, tf) == df.index).all(): print("config dates:", pd.date_range(ti, tf)) print("loaded dates:", df.index) raise ValueError( - f"ERROR loading file {fn_name} for parameter {pn}: " + f"Issue loading file '{fn_name}' for parameter '{pn}': " f"the 'date' entries of the provided file do not include all the days specified to be modeled by " - f"the config. the provided file includes {len(df.index)} days between {str(df.index[0])} to {str(df.index[-1])}, " - f"while there are {len(pd.date_range(ti, tf))} days in the config time span of {ti}->{tf}. The file must contain entries for " + f"the config. the provided file includes '{len(df.index)}' days between '{str(df.index[0])}' to '{str(df.index[-1])}', " + f"while there are '{len(pd.date_range(ti, tf))}' days in the config time span of '{ti}'->'{tf}'. The file must contain entries for " f"the exact start and end dates from the config." ) From 3b20e8af462efc1a33eee397c3acaf5f7a54fe12 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Wed, 16 Oct 2024 11:37:11 -0400 Subject: [PATCH 13/48] Fixing reg-exs --- .../tests/parameters/test_parameters_class.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py index f5b5fe150..8f8aaf7aa 100644 --- a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py +++ b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py @@ -237,8 +237,8 @@ def test_timeseries_parameter_has_insufficient_columns_value_error( with pytest.raises( ValueError, match=( - rf"^Error loading file {tmp_file} for parameter sigma: " - rf"the number of non-'date' columns is {actual_columns}, expected {mock_inputs.number_of_subpops()} " + rf"^Issue loading file '{tmp_file}' for parameter 'sigma': " + rf"the number of non-'date' columns is '{actual_columns}', expected '{mock_inputs.number_of_subpops()}' " rf"\(number of subpopulations\) or one\.$" ), ): @@ -282,12 +282,12 @@ def test_timeseries_parameter_has_insufficient_dates_value_error( with pytest.raises( ValueError, match=( - rf"^ERROR loading file {tmp_file} for parameter sigma: " + rf"^Issue loading file '{tmp_file}' for parameter 'sigma': " rf"the 'date' entries of the provided file do not include " rf"all the days specified to be modeled by the config\. the provided file includes " rf"{(timeseries_end_date - timeseries_start_date).days + 1} days between " - rf"{timeseries_start_date}( 00:00:00)? to {timeseries_end_date}( 00:00:00)?, while there are " - rf"{mock_inputs.number_of_days()} days in the config time span of {mock_inputs.ti}->{mock_inputs.tf}\. " + rf"'{timeseries_start_date}'( 00:00:00)? to '{timeseries_end_date}'( 00:00:00)?, while there are " + rf"'{mock_inputs.number_of_days()}' days in the config time span of '{mock_inputs.ti}'->'{mock_inputs.tf}'\. " rf"The file must contain entries for the exact start and end dates from the config\.$" ), ): From afee28512ded3c447831dee47daba9582ab4aba5 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Wed, 16 Oct 2024 11:45:07 -0400 Subject: [PATCH 14/48] Updating RegEx --- flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py index 8f8aaf7aa..756d0cc92 100644 --- a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py +++ b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py @@ -285,7 +285,7 @@ def test_timeseries_parameter_has_insufficient_dates_value_error( rf"^Issue loading file '{tmp_file}' for parameter 'sigma': " rf"the 'date' entries of the provided file do not include " rf"all the days specified to be modeled by the config\. the provided file includes " - rf"{(timeseries_end_date - timeseries_start_date).days + 1} days between " + rf"'{(timeseries_end_date - timeseries_start_date).days + 1}' days between " rf"'{timeseries_start_date}'( 00:00:00)? to '{timeseries_end_date}'( 00:00:00)?, while there are " rf"'{mock_inputs.number_of_days()}' days in the config time span of '{mock_inputs.ti}'->'{mock_inputs.tf}'\. " rf"The file must contain entries for the exact start and end dates from the config\.$" From 2eaa42748e5266c44dd0b3c5f556de4ddebfe010 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Wed, 16 Oct 2024 12:17:46 -0400 Subject: [PATCH 15/48] Fixing RegExs again UGH! --- .../gempyor_pkg/tests/parameters/test_parameters_class.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py index 756d0cc92..78fab1270 100644 --- a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py +++ b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py @@ -284,11 +284,11 @@ def test_timeseries_parameter_has_insufficient_dates_value_error( match=( rf"^Issue loading file '{tmp_file}' for parameter 'sigma': " rf"the 'date' entries of the provided file do not include " - rf"all the days specified to be modeled by the config\. the provided file includes " + rf"all the days specified to be modeled by the config. the provided file includes " rf"'{(timeseries_end_date - timeseries_start_date).days + 1}' days between " rf"'{timeseries_start_date}'( 00:00:00)? to '{timeseries_end_date}'( 00:00:00)?, while there are " rf"'{mock_inputs.number_of_days()}' days in the config time span of '{mock_inputs.ti}'->'{mock_inputs.tf}'\. " - rf"The file must contain entries for the exact start and end dates from the config\.$" + rf"The file must contain entries for the exact start and end dates from the config.$" ), ): mock_inputs.create_parameters_instance() From 48a78ee60e203eac42ccfeeb607046abcbea0b48 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Wed, 16 Oct 2024 12:31:34 -0400 Subject: [PATCH 16/48] I'm losing my mind with this RegEx --- flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py index 78fab1270..1df019049 100644 --- a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py +++ b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py @@ -287,7 +287,7 @@ def test_timeseries_parameter_has_insufficient_dates_value_error( rf"all the days specified to be modeled by the config. the provided file includes " rf"'{(timeseries_end_date - timeseries_start_date).days + 1}' days between " rf"'{timeseries_start_date}'( 00:00:00)? to '{timeseries_end_date}'( 00:00:00)?, while there are " - rf"'{mock_inputs.number_of_days()}' days in the config time span of '{mock_inputs.ti}'->'{mock_inputs.tf}'\. " + rf"'{mock_inputs.number_of_days()}' days in the config time span of '{mock_inputs.ti}'->'{mock_inputs.tf}'. " rf"The file must contain entries for the exact start and end dates from the config.$" ), ): From 6e1410f12ea732907731ae42398779e1ec5787b2 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Wed, 16 Oct 2024 12:43:51 -0400 Subject: [PATCH 17/48] Update test_parameters_class.py --- flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py index 1df019049..bd7991c1e 100644 --- a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py +++ b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py @@ -286,7 +286,7 @@ def test_timeseries_parameter_has_insufficient_dates_value_error( rf"the 'date' entries of the provided file do not include " rf"all the days specified to be modeled by the config. the provided file includes " rf"'{(timeseries_end_date - timeseries_start_date).days + 1}' days between " - rf"'{timeseries_start_date}'( 00:00:00)? to '{timeseries_end_date}'( 00:00:00)?, while there are " + rf"'{timeseries_start_date}( 00:00:00)?' to '{timeseries_end_date}( 00:00:00)?', while there are " rf"'{mock_inputs.number_of_days()}' days in the config time span of '{mock_inputs.ti}'->'{mock_inputs.tf}'. " rf"The file must contain entries for the exact start and end dates from the config.$" ), From 5c09a3cf866278b89762fbd5cbda1222236256bd Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Wed, 16 Oct 2024 13:36:49 -0400 Subject: [PATCH 18/48] Update flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- .../tests/parameters/test_parameters_class.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py index bd7991c1e..25bdfc512 100644 --- a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py +++ b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py @@ -282,13 +282,14 @@ def test_timeseries_parameter_has_insufficient_dates_value_error( with pytest.raises( ValueError, match=( - rf"^Issue loading file '{tmp_file}' for parameter 'sigma': " - rf"the 'date' entries of the provided file do not include " - rf"all the days specified to be modeled by the config. the provided file includes " - rf"'{(timeseries_end_date - timeseries_start_date).days + 1}' days between " - rf"'{timeseries_start_date}( 00:00:00)?' to '{timeseries_end_date}( 00:00:00)?', while there are " - rf"'{mock_inputs.number_of_days()}' days in the config time span of '{mock_inputs.ti}'->'{mock_inputs.tf}'. " - rf"The file must contain entries for the exact start and end dates from the config.$" + f"^Issue loading file '{tmp_file}' for parameter 'sigma': the 'date' " + "entries of the provided file do not include all the days specified to " + f"be modeled by the config. the provided file includes '{file_days}' " + f"days between '{timeseries_start_date}( 00:00:00)?' to " + f"'{timeseries_end_date}( 00:00:00)?', while there are " + f"'{mock_inputs.number_of_days()}' days in the config time span of " + f"'{mock_inputs.ti}->{mock_inputs.tf}'. The file must contain " + "entries for the exact start and end dates from the config.$" ), ): mock_inputs.create_parameters_instance() From 278543713bf491e3d8735605b6f889584021db13 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Wed, 16 Oct 2024 14:48:58 -0400 Subject: [PATCH 19/48] Shortening a verbose error --- flepimop/gempyor_pkg/src/gempyor/parameters.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/parameters.py b/flepimop/gempyor_pkg/src/gempyor/parameters.py index 248e9254c..450a3638a 100644 --- a/flepimop/gempyor_pkg/src/gempyor/parameters.py +++ b/flepimop/gempyor_pkg/src/gempyor/parameters.py @@ -134,20 +134,14 @@ def __init__( print("loaded dates:", df.index) raise ValueError( f"Issue loading file '{fn_name}' for parameter '{pn}': " - f"the 'date' entries of the provided file do not include all the days specified to be modeled by " - f"the config. the provided file includes '{len(df.index)}' days between '{str(df.index[0])}' to '{str(df.index[-1])}', " - f"while there are '{len(pd.date_range(ti, tf))}' days in the config time span of '{ti}->{tf}'. The file must contain entries for " - f"the exact start and end dates from the config." + f"The 'date' entries of the provided file do not include all the days specified to be modeled by the config." ) if not (pd.date_range(ti, tf) == df.index).all(): print("config dates:", pd.date_range(ti, tf)) print("loaded dates:", df.index) raise ValueError( f"Issue loading file '{fn_name}' for parameter '{pn}': " - f"the 'date' entries of the provided file do not include all the days specified to be modeled by " - f"the config. the provided file includes '{len(df.index)}' days between '{str(df.index[0])}' to '{str(df.index[-1])}', " - f"while there are '{len(pd.date_range(ti, tf))}' days in the config time span of '{ti}'->'{tf}'. The file must contain entries for " - f"the exact start and end dates from the config." + f"the 'date' entries of the provided file do not include all the days specified to be modeled by the config." ) self.pdata[pn]["ts"] = df From 4cc651f339de31139692371c1f56841231df6282 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Wed, 16 Oct 2024 16:20:35 -0400 Subject: [PATCH 20/48] RegEx update --- .../gempyor_pkg/tests/parameters/test_parameters_class.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py index 25bdfc512..4cc620a3b 100644 --- a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py +++ b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py @@ -284,12 +284,7 @@ def test_timeseries_parameter_has_insufficient_dates_value_error( match=( f"^Issue loading file '{tmp_file}' for parameter 'sigma': the 'date' " "entries of the provided file do not include all the days specified to " - f"be modeled by the config. the provided file includes '{file_days}' " - f"days between '{timeseries_start_date}( 00:00:00)?' to " - f"'{timeseries_end_date}( 00:00:00)?', while there are " - f"'{mock_inputs.number_of_days()}' days in the config time span of " - f"'{mock_inputs.ti}->{mock_inputs.tf}'. The file must contain " - "entries for the exact start and end dates from the config.$" + f"be modeled by the config.$" ), ): mock_inputs.create_parameters_instance() From be85d72067403bad9440bb563d1cf01c588e9399 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Fri, 18 Oct 2024 09:50:54 -0400 Subject: [PATCH 21/48] Regex edit.. --- flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py index 4cc620a3b..5fa8364c3 100644 --- a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py +++ b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py @@ -282,7 +282,7 @@ def test_timeseries_parameter_has_insufficient_dates_value_error( with pytest.raises( ValueError, match=( - f"^Issue loading file '{tmp_file}' for parameter 'sigma': the 'date' " + f"^Issue loading file '{tmp_file}' for parameter 'sigma': Tßhe 'date' " "entries of the provided file do not include all the days specified to " f"be modeled by the config.$" ), From fb549c4f308243c14e53d3a23cb6e97e0cc1ffd6 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Fri, 18 Oct 2024 10:03:24 -0400 Subject: [PATCH 22/48] Regex edit --- flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py index 5fa8364c3..377bb800e 100644 --- a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py +++ b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py @@ -282,7 +282,7 @@ def test_timeseries_parameter_has_insufficient_dates_value_error( with pytest.raises( ValueError, match=( - f"^Issue loading file '{tmp_file}' for parameter 'sigma': Tßhe 'date' " + f"Issue loading file '{tmp_file}' for parameter 'sigma': The 'date' " "entries of the provided file do not include all the days specified to " f"be modeled by the config.$" ), From 135aa542f7b06f1d58f74089db19c9b2ae71cf9f Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:29:23 -0400 Subject: [PATCH 23/48] Update flepimop/gempyor_pkg/src/gempyor/compartments.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/compartments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/compartments.py b/flepimop/gempyor_pkg/src/gempyor/compartments.py index 6842d7e26..ac8ac4d33 100644 --- a/flepimop/gempyor_pkg/src/gempyor/compartments.py +++ b/flepimop/gempyor_pkg/src/gempyor/compartments.py @@ -427,7 +427,7 @@ def get_transition_array(self): # candidate = candidate.replace("*1", "") if candidate not in unique_strings: raise ValueError( - f"Candidate '{candidate}' from 'rate' column is not in the list of unique strings: {unique_strings}" + f"Candidate '{candidate}' from 'rate' column is not in the list of unique strings: {unique_strings}." ) rc = [it for it, x in enumerate(unique_strings) if x == candidate][0] transition_array[2][it] = rc From 681ff790471619f3f05fdd9aeb2d20e495c9714b Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:29:50 -0400 Subject: [PATCH 24/48] Update flepimop/gempyor_pkg/src/gempyor/compartments.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/compartments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/compartments.py b/flepimop/gempyor_pkg/src/gempyor/compartments.py index ac8ac4d33..02b7c3d05 100644 --- a/flepimop/gempyor_pkg/src/gempyor/compartments.py +++ b/flepimop/gempyor_pkg/src/gempyor/compartments.py @@ -469,7 +469,7 @@ def get_transition_array(self): # candidate = candidate.replace("*1", "") if candidate not in unique_strings: raise ValueError( - f"Proportion exponent '{candidate}' is not found in the list of unique strings: '{unique_strings}'" + f"Proportion exponent '{candidate}' is not found in the list of unique strings: '{unique_strings}'." ) rc = [it for it, x in enumerate(unique_strings) if x == candidate][0] proportion_info[2][proportion_compartment_index] = rc From 1549b5bc4e4b696ed3f422b4a9b9a7aa60c27449 Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:34:30 -0400 Subject: [PATCH 25/48] Update flepimop/gempyor_pkg/src/gempyor/compartments.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/compartments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/compartments.py b/flepimop/gempyor_pkg/src/gempyor/compartments.py index 02b7c3d05..85ec66a54 100644 --- a/flepimop/gempyor_pkg/src/gempyor/compartments.py +++ b/flepimop/gempyor_pkg/src/gempyor/compartments.py @@ -497,7 +497,7 @@ def get_transition_array(self): if rc == -1: raise ValueError( f"Could not find proportional_to {elem3} in compartments. " - f"Available compartments: {self.compartments}" + f"Available compartments: {self.compartments}." ) proportion_array[proportion_index] = rc From cbfd0934f8450573f6317bf7148554da5cfc289b Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:34:40 -0400 Subject: [PATCH 26/48] Update flepimop/gempyor_pkg/src/gempyor/compartments.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/compartments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/compartments.py b/flepimop/gempyor_pkg/src/gempyor/compartments.py index 85ec66a54..35b907c25 100644 --- a/flepimop/gempyor_pkg/src/gempyor/compartments.py +++ b/flepimop/gempyor_pkg/src/gempyor/compartments.py @@ -563,7 +563,7 @@ def parse_parameter_strings_to_numpy_arrays_v2(self, parameters, parameter_names parsed_formulas.append(f) except Exception as e: print( - f"Cannot parse formula: '{formula}' from parameters: '{parameter_names}'." + f"Cannot parse formula '{formula}' from parameters: '{parameter_names}'." ) raise (e) # Print the error message for debugging From ccfb6e01f482fdb319fe40fc5be2e1406dde0dc0 Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:34:57 -0400 Subject: [PATCH 27/48] Update flepimop/gempyor_pkg/src/gempyor/config_validator.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/config_validator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index b1bcd7cce..6475ebfb2 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -42,7 +42,7 @@ def validate_initial_file_check(cls, values): initial_conditions_file = values.get('initial_conditions_file') initial_file_type = values.get('initial_file_type') if method in {'FromFile', 'SetInitialConditions'} and not initial_conditions_file: - raise ValueError(f"Error in InitialConditions: An initial_conditions_file is required when method is '{method}'.") + raise ValueError(f"An `initial_conditions_file` is required when method is '{method}'.") if method in {'InitialConditionsFolderDraw','SetInitialConditionsFolderDraw'} and not initial_file_type: raise ValueError(f"Error in InitialConditions: initial_file_type is required when method is '{method}'.") return values From e83f250bd32087f4e90af673f280ee076c366086 Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:35:36 -0400 Subject: [PATCH 28/48] Update flepimop/gempyor_pkg/src/gempyor/config_validator.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/config_validator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index 6475ebfb2..b5da57514 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -44,7 +44,7 @@ def validate_initial_file_check(cls, values): if method in {'FromFile', 'SetInitialConditions'} and not initial_conditions_file: raise ValueError(f"An `initial_conditions_file` is required when method is '{method}'.") if method in {'InitialConditionsFolderDraw','SetInitialConditionsFolderDraw'} and not initial_file_type: - raise ValueError(f"Error in InitialConditions: initial_file_type is required when method is '{method}'.") + raise ValueError(f"An `initial_file_type` is required when method is '{method}'.") return values @model_validator(mode='before') From 6eed1e30612659cbb148db407548f446cccfad06 Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:35:57 -0400 Subject: [PATCH 29/48] Update flepimop/gempyor_pkg/src/gempyor/config_validator.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/config_validator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index b5da57514..c41a979b8 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -52,7 +52,7 @@ def plugin_filecheck(cls, values): method = values.get('method') plugin_file_path = values.get('plugin_file_path') if method == 'plugin' and not plugin_file_path: - raise ValueError("Error in InitialConditions: a plugin file path is required when method is plugin.") + raise ValueError("A plugin file path is required when method is plugin.") return values From 08e25a3cbfb1c02d7dad70447d7420805ea0d55d Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:37:59 -0400 Subject: [PATCH 30/48] Update flepimop/gempyor_pkg/src/gempyor/config_validator.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/config_validator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index c41a979b8..19c95d91e 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -71,8 +71,8 @@ def validate_seedingfile(cls, values): seeding_file = values.get('seeding_file') if method == 'PoissonDistributed' and not lambda_file: raise ValueError( - f"Error in Seeding: A lambda_file is required when method is '{method}'. " - f"Current value: '{lambda_file}'." + f"A `lambda_file` is required when method is '{method}', " + f"was given '{lambda_file}'." ) if method == 'FolderDraw' and not seeding_file_type: raise ValueError( From e68dc8a26d9a724c1594111210b239503f8ef105 Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:38:20 -0400 Subject: [PATCH 31/48] Update flepimop/gempyor_pkg/src/gempyor/config_validator.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/config_validator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index 19c95d91e..d5acabc79 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -76,8 +76,8 @@ def validate_seedingfile(cls, values): ) if method == 'FolderDraw' and not seeding_file_type: raise ValueError( - f"Error in Seeding: A seeding_file_type is required when method is FolderDraw. " - f"Current value: '{seeding_file_type}'." + f"A `seeding_file_type` is required when method is 'FolderDraw', " + f"was given '{seeding_file_type}'." ) if method == 'FromFile' and not seeding_file: raise ValueError( From 960f4d230b72f0e835f44066fbaefc2598930d22 Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:39:42 -0400 Subject: [PATCH 32/48] Update flepimop/gempyor_pkg/src/gempyor/config_validator.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/config_validator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index d5acabc79..cbc14b450 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -81,8 +81,8 @@ def validate_seedingfile(cls, values): ) if method == 'FromFile' and not seeding_file: raise ValueError( - f"Error in Seeding: A seeding_file is required when method is FromFile. " - f"Current value: '{seeding_file}'." + f"A `seeding_file` is required when method is 'FromFile', " + f"was given '{seeding_file}'." ) return values From 2b75d6adce2d60e3fe09cfcd8458b6151cfcb0bf Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:41:54 -0400 Subject: [PATCH 33/48] Update flepimop/gempyor_pkg/src/gempyor/config_validator.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/config_validator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index cbc14b450..775f2811b 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -92,8 +92,8 @@ def plugin_filecheck(cls, values): plugin_file_path = values.get('plugin_file_path') if method == 'plugin' and not plugin_file_path: raise ValueError( - f"Error in Seeding: a plugin file path is required when method is plugin. " - f"Current value: '{plugin_file_path!r}'. Please specify the path to the plugin file." + f"A plugin file path is required when method is 'plugin', " + f"was given '{plugin_file_path!r}'." ) return values From 5d999ddb7e814eda021fff81357084dd041f8aa2 Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:42:16 -0400 Subject: [PATCH 34/48] Update flepimop/gempyor_pkg/src/gempyor/config_validator.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/config_validator.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index 775f2811b..02cf695c0 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -143,8 +143,7 @@ def which_value(cls, values): timeseries = values.get('timeseries') is not None if value and timeseries: raise ValueError( - f"Configuration error in seir::parameters: your parameter is both a timeseries and a value, please choose one. " - f"Current values - value: '{values.get('value')!r}', timeseries: '{values.get('timeseries')!r}'." + f"Parsed a parameter with both a timeseries, '{values.get('timeseries')!r}', and a value, '{values.get('value')!r}', please choose one." ) return values From a15184ec2955da52ad724af5ac24b20e13404508 Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:43:21 -0400 Subject: [PATCH 35/48] Update flepimop/gempyor_pkg/src/gempyor/config_validator.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/config_validator.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index 02cf695c0..1157bcbb5 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -218,9 +218,7 @@ def which_source(cls, values): prevalence = values.get('prevalence') if incidence and prevalence: raise ValueError( - f"Configuration error in outcomes::source." - f"Value can only be incidence or prevalence, not both." - f"Current values - incidence: '{values.get('incidence')!r}', prevalence: '{values.get('prevalence')!r}'." + f"Parsed a source with both an incidence, '{values.get('incidence')!r}', and prevalence, '{values.get('prevalence')!r}', please choose one." ) return values From 2b2a2811938ae2db2230a206d4407e99cabf0874 Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:43:55 -0400 Subject: [PATCH 36/48] Update flepimop/gempyor_pkg/src/gempyor/config_validator.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/config_validator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index 1157bcbb5..ec92946a1 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -255,7 +255,7 @@ def check_outcome_type(cls, values): source_present = values.get('source') is not None if sum_present and source_present: - raise ValueError("Error in outcome: Both 'sum' and 'source' are present. Choose one.") + raise ValueError("Both 'sum' and 'source' are present, please choose one.") elif not sum_present and not source_present: raise ValueError("Error in outcome: Neither 'sum' nor 'source' is present. Choose one.") return values From 76b5adfebff88d86f492fdca3b365112198d20c6 Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:44:12 -0400 Subject: [PATCH 37/48] Update flepimop/gempyor_pkg/src/gempyor/initial_conditions.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/initial_conditions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py b/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py index 3e5b67490..17b43b859 100644 --- a/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py +++ b/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py @@ -271,7 +271,7 @@ def read_initial_condition_from_seir_output(ic_df, modinf, allow_missing_subpops if pl in ic_df.columns: y0[comp_idx, pl_idx] = float(ic_df_compartment[pl].iloc[0]) elif allow_missing_subpops: - raise ValueError("There is a bug; report this message. Past implemenation was buggy") + raise RuntimeError("There is a bug; report this message. Past implemenation was buggy") # TODO this should set the full subpop, not just the 0th commpartment logger.critical( f"No initial conditions for for subpop {pl}, assuming everyone (n={modinf.subpop_pop[pl_idx]}) in the first metacompartments ({modinf.compartments.compartments['name'].iloc[0]})" From a0ae5e35b7a03bc73d40d270fba727c21aabdd1f Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:44:30 -0400 Subject: [PATCH 38/48] Update flepimop/gempyor_pkg/src/gempyor/config_validator.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/config_validator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index ec92946a1..4bdafb035 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -257,7 +257,7 @@ def check_outcome_type(cls, values): if sum_present and source_present: raise ValueError("Both 'sum' and 'source' are present, please choose one.") elif not sum_present and not source_present: - raise ValueError("Error in outcome: Neither 'sum' nor 'source' is present. Choose one.") + raise ValueError("Neither 'sum' nor 'source' is present, please choose one.") return values class OutcomesConfig(BaseModel): From 0c14d668fd8ebff8db11264046fe6d0e144a42a7 Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:44:58 -0400 Subject: [PATCH 39/48] Update flepimop/gempyor_pkg/src/gempyor/config_validator.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/config_validator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index 4bdafb035..01f449dd4 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -272,7 +272,7 @@ def check_paramfromfile_type(cls, values): param_subpop_file = values.get('param_subpop_file') is not None if param_from_file and not param_subpop_file: - raise ValueError("Error in outcome: `param_subpop_file` is required when `param_from_file` is 'True'.") + raise ValueError("A `param_subpop_file` is required when `param_from_file` is 'True'.") return values class ResampleConfig(BaseModel): From 9a6ba69d5fb02fbbe68246349774e8c0e762e815 Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:48:08 -0400 Subject: [PATCH 40/48] Update flepimop/gempyor_pkg/src/gempyor/config_validator.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/config_validator.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index 01f449dd4..ff4a73edc 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -336,8 +336,7 @@ def verify_inference(cls, values): inference_present = values.get('inference') is not None start_date_groundtruth = values.get('start_date_groundtruth') is not None if inference_present and not start_date_groundtruth: - raise ValueError("Inference mode is enabled, but no groundtruth dates are provided. Please provide groundtruth dates." - ) + raise ValueError("Inference mode is enabled, but no groundtruth dates are provided. Please provide groundtruth dates.") elif start_date_groundtruth and not inference_present: raise ValueError( f"Groundtruth dates are provided, but inference mode is not enabled. Please enable inference mode." From 4ca01af67cabf5480556fdcf68aca7adebcebbd3 Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:48:53 -0400 Subject: [PATCH 41/48] Update flepimop/gempyor_pkg/src/gempyor/config_validator.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/config_validator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index ff4a73edc..9b43692b1 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -339,7 +339,7 @@ def verify_inference(cls, values): raise ValueError("Inference mode is enabled, but no groundtruth dates are provided. Please provide groundtruth dates.") elif start_date_groundtruth and not inference_present: raise ValueError( - f"Groundtruth dates are provided, but inference mode is not enabled. Please enable inference mode." + "Groundtruth dates are provided, but inference mode is not enabled. Please enable inference mode." ) return values From 88e310db1fc7bfd34a28496779a6015ca4445a45 Mon Sep 17 00:00:00 2001 From: Emily Przykucki <100221052+emprzy@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:49:22 -0400 Subject: [PATCH 42/48] Update flepimop/gempyor_pkg/src/gempyor/inference.py Co-authored-by: Timothy Willard <9395586+TimothyWillard@users.noreply.github.com> --- flepimop/gempyor_pkg/src/gempyor/inference.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/inference.py b/flepimop/gempyor_pkg/src/gempyor/inference.py index fa28991de..36287f8ce 100644 --- a/flepimop/gempyor_pkg/src/gempyor/inference.py +++ b/flepimop/gempyor_pkg/src/gempyor/inference.py @@ -268,8 +268,8 @@ def autodetect_scenarios(config): if len(seir_modifiers_scenarios) != 1 or len(outcome_modifiers_scenarios) != 1: raise ValueError( - f"Inference only supports configuration files with one scenario, recieved:\n" - f"SEIR modifiers: '{seir_modifiers_scenarios}'." + f"Inference only supports configuration files with one scenario, recieved " + f"SEIR modifiers: '{seir_modifiers_scenarios}', and " f"Outcomes modifiers: '{outcome_modifiers_scenarios}'." ) From 01d11a7dfd05c980ce6bbdfd4a5625fc8223476b Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Fri, 18 Oct 2024 14:42:19 -0400 Subject: [PATCH 43/48] Update parameters.py and test_parameters_class.py --- flepimop/gempyor_pkg/src/gempyor/initial_conditions.py | 8 ++++---- flepimop/gempyor_pkg/src/gempyor/parameters.py | 6 ++++-- .../gempyor_pkg/tests/parameters/test_parameters_class.py | 6 +++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py b/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py index 17b43b859..eff95b6b8 100644 --- a/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py +++ b/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py @@ -123,9 +123,9 @@ def check_population(y0, modinf, ignore_population_checks=False): if abs(n_y0 - n_pop) > 1: error = True warnings.warn( - f"ERROR: subpop_names {pl} (idx: plx_idx) has a population from initial condition of {n_y0} " - f"while population geodata is {n_pop}. " - f"(absolute difference should be <1, here is {abs(n_y0-n_pop)})." + f"`subpop_names` '{pl}' (idx: plx_idx) has a population from initial condition of '{n_y0}' " + f"while population geodata is '{n_pop}'. " + f"(absolute difference should be <1, here is '{abs(n_y0-n_pop)}')." ) if error and not ignore_population_checks: @@ -133,7 +133,7 @@ def check_population(y0, modinf, ignore_population_checks=False): ) elif error and ignore_population_checks: warnings.warn( - "WARNING: Population mismatch errors ignored because `ignore_population_checks` is set to `True`. " + "Population mismatch errors ignored because `ignore_population_checks` is set to `True`. " "Execution will continue, but this is not recommended.", UserWarning ) diff --git a/flepimop/gempyor_pkg/src/gempyor/parameters.py b/flepimop/gempyor_pkg/src/gempyor/parameters.py index 450a3638a..35526084c 100644 --- a/flepimop/gempyor_pkg/src/gempyor/parameters.py +++ b/flepimop/gempyor_pkg/src/gempyor/parameters.py @@ -134,14 +134,16 @@ def __init__( print("loaded dates:", df.index) raise ValueError( f"Issue loading file '{fn_name}' for parameter '{pn}': " - f"The 'date' entries of the provided file do not include all the days specified to be modeled by the config." + f"Provided file dates span '{str(df.index[0])}' to '{str(df.index[-1])}', " + f"but the config dates span '{ti}' to '{tf}'." ) if not (pd.date_range(ti, tf) == df.index).all(): print("config dates:", pd.date_range(ti, tf)) print("loaded dates:", df.index) raise ValueError( f"Issue loading file '{fn_name}' for parameter '{pn}': " - f"the 'date' entries of the provided file do not include all the days specified to be modeled by the config." + f"Provided file dates span '{str(df.index[0])}' to '{str(df.index[-1])}', " + f"but the config dates span '{ti}' to '{tf}'." ) self.pdata[pn]["ts"] = df diff --git a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py index 377bb800e..09b278914 100644 --- a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py +++ b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py @@ -282,9 +282,9 @@ def test_timeseries_parameter_has_insufficient_dates_value_error( with pytest.raises( ValueError, match=( - f"Issue loading file '{tmp_file}' for parameter 'sigma': The 'date' " - "entries of the provided file do not include all the days specified to " - f"be modeled by the config.$" + f"Issue loading file '{tmp_file}' for parameter 'sigma': " + f"Provided file dates span '{timeseries_start_date}( 00\:00\:00)?' to '{timeseries_end_date}( 00\:00\:00)?', " + f"but the config dates span '{mock_inputs.ti}' to '{mock_inputs.tf}'.$" ), ): mock_inputs.create_parameters_instance() From 7096ef1df77149d3f6f5216e90306d3d7be2d2bd Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Mon, 4 Nov 2024 15:13:46 -0500 Subject: [PATCH 44/48] Updated compartments.py, config_validaor.py, inference.py, parameters.py, and one regex in test_ic.py --- .../gempyor_pkg/src/gempyor/compartments.py | 12 ++++++------ .../gempyor_pkg/src/gempyor/config_validator.py | 17 ++++------------- flepimop/gempyor_pkg/src/gempyor/inference.py | 4 ++-- flepimop/gempyor_pkg/src/gempyor/parameters.py | 14 +++++++++----- flepimop/gempyor_pkg/tests/seir/test_ic.py | 2 +- 5 files changed, 22 insertions(+), 27 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/compartments.py b/flepimop/gempyor_pkg/src/gempyor/compartments.py index 35b907c25..cff807559 100644 --- a/flepimop/gempyor_pkg/src/gempyor/compartments.py +++ b/flepimop/gempyor_pkg/src/gempyor/compartments.py @@ -375,9 +375,9 @@ def get_comp_idx(self, comp_dict: dict, error_info: str = "no information") -> i comp_idx = self.compartments[mask].index.values if len(comp_idx) != 1: raise ValueError( - f"The provided dictionary does not allow an isolated compartment: '{comp_dict}' " + f"The provided dictionary does not allow an isolated compartment: '{comp_dict}'. " f"Isolate '{self.compartments[mask]}'. " - f"The get_comp_idx function was called by '{error_info}'." + f"The `get_comp_idx` function was called by '{error_info}'." ) return comp_idx[0] @@ -496,8 +496,8 @@ def get_transition_array(self): rc = compartment if rc == -1: raise ValueError( - f"Could not find proportional_to {elem3} in compartments. " - f"Available compartments: {self.compartments}." + f"Could not find `proportional_to` '{elem3}' in compartments. " + f"Available compartments: '{self.compartments}'." ) proportion_array[proportion_index] = rc @@ -611,8 +611,8 @@ def parse_parameter_strings_to_numpy_arrays( ): # empty list means all have been tried. Usually there just remains one string in string_list at that time. raise ValueError( f"Could not parse string '{string_list}'. " - f"This usually mean that '{string_list[0]}' is a parameter name that is not defined " - f"or that it contains an operator that is not in the list of supported operators: ^,*,/,+,-. " + f"This usually means that '{string_list[0]}' is a parameter name that is not defined " + f"or that it contains an operator that is not in the list of supported operators: '{operators}'. " f"The defined parameters are '{parameter_names}'." ) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index 9b43692b1..93aa4d6ff 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -70,20 +70,11 @@ def validate_seedingfile(cls, values): seeding_file_type = values.get('seeding_file_type') seeding_file = values.get('seeding_file') if method == 'PoissonDistributed' and not lambda_file: - raise ValueError( - f"A `lambda_file` is required when method is '{method}', " - f"was given '{lambda_file}'." - ) + raise ValueError("A `lambda_file` is required when method is 'PoissonDistributed'.") if method == 'FolderDraw' and not seeding_file_type: - raise ValueError( - f"A `seeding_file_type` is required when method is 'FolderDraw', " - f"was given '{seeding_file_type}'." - ) + raise ValueError("A `seeding_file_type` is required when method is 'FolderDraw'.") if method == 'FromFile' and not seeding_file: - raise ValueError( - f"A `seeding_file` is required when method is 'FromFile', " - f"was given '{seeding_file}'." - ) + raise ValueError("A `seeding_file` is required when method is 'FromFile'.") return values @model_validator(mode='before') @@ -358,7 +349,7 @@ def check_dates(cls, values): def init_or_seed(cls, values): init = values.get('initial_conditions') seed = values.get('seeding') - if not init or seed: + if not (init or seed): raise ValueError( f"At least one of `initial_conditions` or `seeding` must be provided." ) diff --git a/flepimop/gempyor_pkg/src/gempyor/inference.py b/flepimop/gempyor_pkg/src/gempyor/inference.py index 36287f8ce..25289349d 100644 --- a/flepimop/gempyor_pkg/src/gempyor/inference.py +++ b/flepimop/gempyor_pkg/src/gempyor/inference.py @@ -268,7 +268,7 @@ def autodetect_scenarios(config): if len(seir_modifiers_scenarios) != 1 or len(outcome_modifiers_scenarios) != 1: raise ValueError( - f"Inference only supports configuration files with one scenario, recieved " + f"Inference only supports configuration files with one scenario, received " f"SEIR modifiers: '{seir_modifiers_scenarios}', and " f"Outcomes modifiers: '{outcome_modifiers_scenarios}'." ) @@ -417,7 +417,7 @@ def get_all_sim_arguments(self): def get_logloss(self, proposal): if not self.inferpar.check_in_bound(proposal=proposal): if not self.silent: - print("OUT OF BOUNDS!!") + print("`llik` is -inf (out of bound proposal)") return -np.inf, -np.inf, -np.inf snpi_df_mod, hnpi_df_mod = self.inferpar.inject_proposal( diff --git a/flepimop/gempyor_pkg/src/gempyor/parameters.py b/flepimop/gempyor_pkg/src/gempyor/parameters.py index 35526084c..c013d7388 100644 --- a/flepimop/gempyor_pkg/src/gempyor/parameters.py +++ b/flepimop/gempyor_pkg/src/gempyor/parameters.py @@ -133,17 +133,21 @@ def __init__( print("config dates:", pd.date_range(ti, tf)) print("loaded dates:", df.index) raise ValueError( - f"Issue loading file '{fn_name}' for parameter '{pn}': " - f"Provided file dates span '{str(df.index[0])}' to '{str(df.index[-1])}', " - f"but the config dates span '{ti}' to '{tf}'." + f"Issue loading file '{fn_name}' for parameter '{pn}': " + f"the 'date' entries of the provided file do not include all the days specified to be modeled by " + f"the config. The provided file includes '{len(df.index)}' days between '{str(df.index[0])}' and '{str(df.index[-1])}', " + f"while there are '{len(pd.date_range(ti, tf))}' days in the config time span of '{ti}' to '{tf}'. " + f"The file must contain entries for the exact start and end dates from the config." ) if not (pd.date_range(ti, tf) == df.index).all(): print("config dates:", pd.date_range(ti, tf)) print("loaded dates:", df.index) raise ValueError( f"Issue loading file '{fn_name}' for parameter '{pn}': " - f"Provided file dates span '{str(df.index[0])}' to '{str(df.index[-1])}', " - f"but the config dates span '{ti}' to '{tf}'." + f"the 'date' entries of the provided file do not include all the days specified to be modeled by " + f"the config. The provided file includes '{len(df.index)}' days between '{str(df.index[0])}' and '{str(df.index[-1])}', " + f"while there are '{len(pd.date_range(ti, tf))}' days in the config time span of '{ti}' to '{tf}'. " + f"The file must contain entries for the exact start and end dates from the config." ) self.pdata[pn]["ts"] = df diff --git a/flepimop/gempyor_pkg/tests/seir/test_ic.py b/flepimop/gempyor_pkg/tests/seir/test_ic.py index a24f141ea..b4cd240ee 100644 --- a/flepimop/gempyor_pkg/tests/seir/test_ic.py +++ b/flepimop/gempyor_pkg/tests/seir/test_ic.py @@ -44,7 +44,7 @@ def test_IC_allow_missing_node_compartments_success(self): sic.get_from_config(sim_id=100, modinf=s) def test_IC_IC_notImplemented_fail(self): - with pytest.raises(NotImplementedError, match=r"^Unknown initial conditions method \[received: .*?\]\.$"): + with pytest.raises(NotImplementedError, match=r".*unknown.*initial.*conditions.*"): config.clear() config.read(user=False) config.set_file(f"{DATA_DIR}/config.yml") From 99b4aec107a13180cf565b3313b98dd4dba65b43 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Wed, 6 Nov 2024 13:52:42 -0500 Subject: [PATCH 45/48] Update parameters.py Updating an error message to be more streamlined, and also match the RegEx in test_parameters_class.py --- flepimop/gempyor_pkg/src/gempyor/parameters.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/parameters.py b/flepimop/gempyor_pkg/src/gempyor/parameters.py index 0a45883cb..7ab0de151 100644 --- a/flepimop/gempyor_pkg/src/gempyor/parameters.py +++ b/flepimop/gempyor_pkg/src/gempyor/parameters.py @@ -128,20 +128,16 @@ def __init__( print("loaded dates:", df.index) raise ValueError( f"Issue loading file '{fn_name}' for parameter '{pn}': " - f"the 'date' entries of the provided file do not include all the days specified to be modeled by " - f"the config. The provided file includes '{len(df.index)}' days between '{str(df.index[0])}' and '{str(df.index[-1])}', " - f"while there are '{len(pd.date_range(ti, tf))}' days in the config time span of '{ti}' to '{tf}'. " - f"The file must contain entries for the exact start and end dates from the config." + f"Provided file dates span '{str(df.index[0])}' to '{str(df.index[-1])}', " + f"but the config dates span '{ti}' to '{tf}'." ) if not (pd.date_range(ti, tf) == df.index).all(): print("config dates:", pd.date_range(ti, tf)) print("loaded dates:", df.index) raise ValueError( f"Issue loading file '{fn_name}' for parameter '{pn}': " - f"the 'date' entries of the provided file do not include all the days specified to be modeled by " - f"the config. The provided file includes '{len(df.index)}' days between '{str(df.index[0])}' and '{str(df.index[-1])}', " - f"while there are '{len(pd.date_range(ti, tf))}' days in the config time span of '{ti}' to '{tf}'. " - f"The file must contain entries for the exact start and end dates from the config." + f"Provided file dates span '{str(df.index[0])}' to '{str(df.index[-1])}', " + f"but the config dates span '{ti}' to '{tf}'." ) self.pdata[pn]["ts"] = df From d2f8cc28ba02ffde86b0fb03bd73e10ac2ba6b77 Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Wed, 6 Nov 2024 14:58:19 -0500 Subject: [PATCH 46/48] Applying `black` to this branch Allowing black to reformat my code --- .../gempyor_pkg/src/gempyor/compartments.py | 143 +++++++++++------- .../src/gempyor/config_validator.py | 89 ++++++----- flepimop/gempyor_pkg/src/gempyor/dev/steps.py | 4 +- flepimop/gempyor_pkg/src/gempyor/inference.py | 7 +- .../src/gempyor/initial_conditions.py | 26 ++-- flepimop/gempyor_pkg/src/gempyor/seeding.py | 16 +- .../gempyor_pkg/src/gempyor/steps_source.py | 4 +- .../tests/parameters/test_parameters_class.py | 4 +- .../gempyor_pkg/tests/utils/test_utils.py | 1 - 9 files changed, 174 insertions(+), 120 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/compartments.py b/flepimop/gempyor_pkg/src/gempyor/compartments.py index 445759cbc..e521edffc 100644 --- a/flepimop/gempyor_pkg/src/gempyor/compartments.py +++ b/flepimop/gempyor_pkg/src/gempyor/compartments.py @@ -143,50 +143,68 @@ def expand_transition_elements(self, single_transition_config, problem_dimension ) # it is an iterator that will go through all the indexes of the array for x in it: try: - new_transition_config["source"][it.multi_index] = ( - list_recursive_convert_to_string( - self.access_original_config_by_multi_index( - single_transition_config["source"], it.multi_index - ) + new_transition_config["source"][ + it.multi_index + ] = list_recursive_convert_to_string( + self.access_original_config_by_multi_index( + single_transition_config["source"], it.multi_index ) ) except Exception as e: print(f"Error {e}:") - print(f">>> in expand_transition_elements for `source:` at index '{it.multi_index}'") - print(f">>> this transition source is: '{single_transition_config['source']}'") - print(f">>> this transition destination is: '{single_transition_config['destination']}'") + print( + f">>> in expand_transition_elements for `source:` at index '{it.multi_index}'" + ) + print( + f">>> this transition source is: '{single_transition_config['source']}'" + ) + print( + f">>> this transition destination is: '{single_transition_config['destination']}'" + ) print(f"transition_dimension: '{problem_dimension}'") raise e try: - new_transition_config["destination"][it.multi_index] = ( - list_recursive_convert_to_string( - self.access_original_config_by_multi_index( - single_transition_config["destination"], it.multi_index - ) + new_transition_config["destination"][ + it.multi_index + ] = list_recursive_convert_to_string( + self.access_original_config_by_multi_index( + single_transition_config["destination"], it.multi_index ) ) except Exception as e: print(f"Error {e}:") - print(f">>> in expand_transition_elements for `destination:` at index '{it.multi_index}'") - print(f">>> this transition source is: '{single_transition_config['source']}'") - print(f">>> this transition destination is: '{single_transition_config['destination']}'") + print( + f">>> in expand_transition_elements for `destination:` at index '{it.multi_index}'" + ) + print( + f">>> this transition source is: '{single_transition_config['source']}'" + ) + print( + f">>> this transition destination is: '{single_transition_config['destination']}'" + ) print(f"transition_dimension: '{problem_dimension}'") raise e try: - new_transition_config["rate"][it.multi_index] = ( - list_recursive_convert_to_string( - self.access_original_config_by_multi_index( - single_transition_config["rate"], it.multi_index - ) + new_transition_config["rate"][ + it.multi_index + ] = list_recursive_convert_to_string( + self.access_original_config_by_multi_index( + single_transition_config["rate"], it.multi_index ) ) except Exception as e: print(f"Error {e}:") - print(f">>> in expand_transition_elements for `rate:` at index '{it.multi_index}'") - print(f">>> this transition source is: '{single_transition_config['source']}'") - print(f">>> this transition destination is: '{single_transition_config['destination']}'") + print( + f">>> in expand_transition_elements for `rate:` at index '{it.multi_index}'" + ) + print( + f">>> this transition source is: '{single_transition_config['source']}'" + ) + print( + f">>> this transition destination is: '{single_transition_config['destination']}'" + ) print(f"transition_dimension: '{problem_dimension}'") raise e @@ -206,9 +224,15 @@ def expand_transition_elements(self, single_transition_config, problem_dimension ) except Exception as e: print(f"Error {e}:") - print(f">>> in expand_transition_elements for `proportional_to:` at index '{it.multi_index}'") - print(f">>> this transition source is: '{single_transition_config['source']}'") - print(f">>> this transition destination is: '{single_transition_config['destination']}'") + print( + f">>> in expand_transition_elements for `proportional_to:` at index '{it.multi_index}'" + ) + print( + f">>> this transition source is: '{single_transition_config['source']}'" + ) + print( + f">>> this transition destination is: '{single_transition_config['destination']}'" + ) print(f"transition_dimension: '{problem_dimension}'") raise e @@ -221,23 +245,29 @@ def expand_transition_elements(self, single_transition_config, problem_dimension it.multi_index, problem_dimension, ) - new_transition_config["proportion_exponent"][it.multi_index] = ( - list_recursive_convert_to_string( - [ - self.access_original_config_by_multi_index( - single_transition_config["proportion_exponent"][p_idx], - it.multi_index, - problem_dimension, - ) - for p_idx in range(proportion_size) - ] - ) + new_transition_config["proportion_exponent"][ + it.multi_index + ] = list_recursive_convert_to_string( + [ + self.access_original_config_by_multi_index( + single_transition_config["proportion_exponent"][p_idx], + it.multi_index, + problem_dimension, + ) + for p_idx in range(proportion_size) + ] ) except Exception as e: print(f"Error {e}:") - print(f">>> in expand_transition_elements for `proportion_exponent:` at index '{it.multi_index}'") - print(f">>> this transition source is: '{single_transition_config['source']}'") - print(f">>> this transition destination is: '{single_transition_config['destination']}'") + print( + f">>> in expand_transition_elements for `proportion_exponent:` at index '{it.multi_index}'" + ) + print( + f">>> this transition source is: '{single_transition_config['source']}'" + ) + print( + f">>> this transition destination is: '{single_transition_config['destination']}'" + ) print(f"transition_dimension: '{problem_dimension}'") raise e else: @@ -349,7 +379,6 @@ def unformat_proportion_exponent( def parse_single_transition( self, seir_config, single_transition_config, fake_config=False ): - ## This method relies on having run parse_compartments if not fake_config: single_transition_config = single_transition_config.get() @@ -475,7 +504,9 @@ def get_transition_array(self): if self.compartments["name"][compartment] == elem: rc = compartment if rc == -1: - raise ValueError(f"Could not find '{colname}' defined by '{elem}' in '{self.compartments}'.") + raise ValueError( + f"Could not find '{colname}' defined by '{elem}' in '{self.compartments}'." + ) transition_array[cit, it] = rc unique_strings = [] @@ -543,9 +574,9 @@ def get_transition_array(self): proportion_info[0][ current_proportion_sum_it ] = current_proportion_sum_start - proportion_info[1][current_proportion_sum_it] = ( - current_proportion_sum_start + len(elem_tmp) - ) + proportion_info[1][ + current_proportion_sum_it + ] = current_proportion_sum_start + len(elem_tmp) current_proportion_sum_it += 1 current_proportion_sum_start += len(elem_tmp) proportion_compartment_index = 0 @@ -557,7 +588,7 @@ def get_transition_array(self): if candidate not in unique_strings: raise ValueError( f"Proportion exponent '{candidate}' is not found in the list of unique strings: '{unique_strings}'." - ) + ) rc = [it for it, x in enumerate(unique_strings) if x == candidate][0] proportion_info[2][proportion_compartment_index] = rc proportion_compartment_index += 1 @@ -707,7 +738,7 @@ def parse_parameter_strings_to_numpy_arrays( not operators ): # empty list means all have been tried. Usually there just remains one string in string_list at that time. raise ValueError( - f"Could not parse string '{string_list}'. " + f"Could not parse string '{string_list}'. " f"This usually means that '{string_list[0]}' is a parameter name that is not defined " f"or that it contains an operator that is not in the list of supported operators: '{operators}'. " f"The defined parameters are '{parameter_names}'." @@ -730,14 +761,14 @@ def parse_parameter_strings_to_numpy_arrays( if not is_totally_resolvable: not_resolvable_indices = [it for it, x in enumerate(is_resolvable) if not x] - tmp_rc[not_resolvable_indices] = ( - self.parse_parameter_strings_to_numpy_arrays( - parameters, - parameter_names, - [string[not is_resolvable]], - operator_reduce_lambdas, - operators[1:], - ) + tmp_rc[ + not_resolvable_indices + ] = self.parse_parameter_strings_to_numpy_arrays( + parameters, + parameter_names, + [string[not is_resolvable]], + operator_reduce_lambdas, + operators[1:], ) for numeric_index in [x for x in range(len(is_numeric)) if is_numeric[x]]: tmp_rc[numeric_index] = parameters[0] * 0 + float(string[numeric_index]) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index 74909631c..128fbc6b8 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -65,20 +65,27 @@ class InitialConditionsConfig(BaseModel): @model_validator(mode="before") def validate_initial_file_check(cls, values): - method = values.get('method') - initial_conditions_file = values.get('initial_conditions_file') - initial_file_type = values.get('initial_file_type') - if method in {'FromFile', 'SetInitialConditions'} and not initial_conditions_file: - raise ValueError(f"An `initial_conditions_file` is required when method is '{method}'.") - if method in {'InitialConditionsFolderDraw','SetInitialConditionsFolderDraw'} and not initial_file_type: - raise ValueError(f"An `initial_file_type` is required when method is '{method}'.") + method = values.get("method") + initial_conditions_file = values.get("initial_conditions_file") + initial_file_type = values.get("initial_file_type") + if method in {"FromFile", "SetInitialConditions"} and not initial_conditions_file: + raise ValueError( + f"An `initial_conditions_file` is required when method is '{method}'." + ) + if ( + method in {"InitialConditionsFolderDraw", "SetInitialConditionsFolderDraw"} + and not initial_file_type + ): + raise ValueError( + f"An `initial_file_type` is required when method is '{method}'." + ) return values @model_validator(mode="before") def plugin_filecheck(cls, values): - method = values.get('method') - plugin_file_path = values.get('plugin_file_path') - if method == 'plugin' and not plugin_file_path: + method = values.get("method") + plugin_file_path = values.get("plugin_file_path") + if method == "plugin" and not plugin_file_path: raise ValueError("A plugin file path is required when method is plugin.") return values @@ -106,23 +113,27 @@ class SeedingConfig(BaseModel): @model_validator(mode="before") def validate_seedingfile(cls, values): - method = values.get('method') - lambda_file = values.get('lambda_file') - seeding_file_type = values.get('seeding_file_type') - seeding_file = values.get('seeding_file') - if method == 'PoissonDistributed' and not lambda_file: - raise ValueError("A `lambda_file` is required when method is 'PoissonDistributed'.") - if method == 'FolderDraw' and not seeding_file_type: - raise ValueError("A `seeding_file_type` is required when method is 'FolderDraw'.") - if method == 'FromFile' and not seeding_file: + method = values.get("method") + lambda_file = values.get("lambda_file") + seeding_file_type = values.get("seeding_file_type") + seeding_file = values.get("seeding_file") + if method == "PoissonDistributed" and not lambda_file: + raise ValueError( + "A `lambda_file` is required when method is 'PoissonDistributed'." + ) + if method == "FolderDraw" and not seeding_file_type: + raise ValueError( + "A `seeding_file_type` is required when method is 'FolderDraw'." + ) + if method == "FromFile" and not seeding_file: raise ValueError("A `seeding_file` is required when method is 'FromFile'.") return values @model_validator(mode="before") def plugin_filecheck(cls, values): - method = values.get('method') - plugin_file_path = values.get('plugin_file_path') - if method == 'plugin' and not plugin_file_path: + method = values.get("method") + plugin_file_path = values.get("plugin_file_path") + if method == "plugin" and not plugin_file_path: raise ValueError( f"A plugin file path is required when method is 'plugin', " f"was given '{plugin_file_path!r}'." @@ -158,10 +169,14 @@ def check_distr(cls, values): b = values.get("b") if distr != "fixed": if not mean and not sd: - raise ValueError("Mean and sd must be provided for non-fixed distributions.") - if distr == 'truncnorm' and not a and not b: - raise ValueError("a and b must be provided for truncated normal distributions.") - if distr == 'fixed' and not value: + raise ValueError( + "Mean and sd must be provided for non-fixed distributions." + ) + if distr == "truncnorm" and not a and not b: + raise ValueError( + "a and b must be provided for truncated normal distributions." + ) + if distr == "fixed" and not value: raise ValueError("Value must be provided for fixed distributions.") return values @@ -169,9 +184,9 @@ def check_distr(cls, values): class BaseParameterConfig(BaseModel): value: Optional[ValueConfig] = None modifier_parameter: Optional[str] = None - name: Optional[str] = ( - None # this is only for outcomes, to build outcome_prevalence_name (how to restrict this?) - ) + name: Optional[ + str + ] = None # this is only for outcomes, to build outcome_prevalence_name (how to restrict this?) class SeirParameterConfig(BaseParameterConfig): @@ -282,7 +297,7 @@ def which_source(cls, values): if incidence and prevalence: raise ValueError( f"Parsed a source with both an incidence, '{values.get('incidence')!r}', and prevalence, '{values.get('prevalence')!r}', please choose one." - ) + ) return values # @model_validator(mode='before') # DOES NOT WORK @@ -339,7 +354,9 @@ def check_paramfromfile_type(cls, values): param_subpop_file = values.get("param_subpop_file") is not None if param_from_file and not param_subpop_file: - raise ValueError("A `param_subpop_file` is required when `param_from_file` is 'True'.") + raise ValueError( + "A `param_subpop_file` is required when `param_from_file` is 'True'." + ) return values @@ -423,7 +440,9 @@ def verify_inference(cls, values): inference_present = values.get("inference") is not None start_date_groundtruth = values.get("start_date_groundtruth") is not None if inference_present and not start_date_groundtruth: - raise ValueError("Inference mode is enabled, but no groundtruth dates are provided. Please provide groundtruth dates.") + raise ValueError( + "Inference mode is enabled, but no groundtruth dates are provided. Please provide groundtruth dates." + ) elif start_date_groundtruth and not inference_present: raise ValueError( "Groundtruth dates are provided, but inference mode is not enabled. Please enable inference mode." @@ -443,10 +462,10 @@ def check_dates(cls, values): @model_validator(mode="before") def init_or_seed(cls, values): - init = values.get('initial_conditions') - seed = values.get('seeding') + init = values.get("initial_conditions") + seed = values.get("seeding") if not (init or seed): raise ValueError( f"At least one of `initial_conditions` or `seeding` must be provided." - ) + ) return values diff --git a/flepimop/gempyor_pkg/src/gempyor/dev/steps.py b/flepimop/gempyor_pkg/src/gempyor/dev/steps.py index 1bbf5b207..3ddde56ee 100644 --- a/flepimop/gempyor_pkg/src/gempyor/dev/steps.py +++ b/flepimop/gempyor_pkg/src/gempyor/dev/steps.py @@ -1693,9 +1693,7 @@ def rk4_integrate(today, x): ## Return "UniTuple(float64[:, :, :], 2) (" ## return states and cumlative states, both [ ndays x ncompartments x nspatial_nodes ] ## Dimensions - "int32," - "int32," - "int32," ## ncompartments ## nspatial_nodes ## Number of days + "int32," "int32," "int32," ## ncompartments ## nspatial_nodes ## Number of days ## Parameters "float64[:, :, :]," "float64," ## Parameters [ nparameters x ndays x nspatial_nodes] ## dt diff --git a/flepimop/gempyor_pkg/src/gempyor/inference.py b/flepimop/gempyor_pkg/src/gempyor/inference.py index aae76eaff..823ba52b3 100644 --- a/flepimop/gempyor_pkg/src/gempyor/inference.py +++ b/flepimop/gempyor_pkg/src/gempyor/inference.py @@ -353,9 +353,10 @@ def __init__( config.set_file(os.path.join(path_prefix, config_filepath)) - self.seir_modifiers_scenario, self.outcome_modifiers_scenario = ( - autodetect_scenarios(config) - ) + ( + self.seir_modifiers_scenario, + self.outcome_modifiers_scenario, + ) = autodetect_scenarios(config) if run_id is None: run_id = file_paths.run_id() diff --git a/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py b/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py index b86226cca..1926b5513 100644 --- a/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py +++ b/flepimop/gempyor_pkg/src/gempyor/initial_conditions.py @@ -116,7 +116,9 @@ def get_from_config(self, sim_id: int, modinf) -> np.ndarray: allow_missing_subpops=self.allow_missing_subpops, ) else: - raise NotImplementedError(f"Unknown initial conditions method [received: '{method}'].") + raise NotImplementedError( + f"Unknown initial conditions method [received: '{method}']." + ) # check that the inputed values sums to the subpop population: check_population( @@ -147,13 +149,14 @@ def check_population(y0, modinf, ignore_population_checks=False): ) if error and not ignore_population_checks: - raise ValueError("Geodata and initial condition do not agree on population size. Use `ignore_population_checks: True` to ignore." + raise ValueError( + "Geodata and initial condition do not agree on population size. Use `ignore_population_checks: True` to ignore." ) elif error and ignore_population_checks: warnings.warn( - "Population mismatch errors ignored because `ignore_population_checks` is set to `True`. " - "Execution will continue, but this is not recommended.", - UserWarning + "Population mismatch errors ignored because `ignore_population_checks` is set to `True`. " + "Execution will continue, but this is not recommended.", + UserWarning, ) @@ -201,7 +204,9 @@ def read_initial_condition_from_tidydataframe( logger.critical( f"No initial conditions for for subpop {pl}, assuming everyone (n={modinf.subpop_pop[pl_idx]}) in the first metacompartment ({modinf.compartments.compartments['name'].iloc[0]})" ) - raise RuntimeError("There is a bug; report this message. Past implemenation was buggy.") + raise RuntimeError( + "There is a bug; report this message. Past implemenation was buggy." + ) # TODO: this is probably ok but highlighting for consistency if "proportional" in self.initial_conditions_config.keys(): if self.initial_conditions_config["proportional"].get(): @@ -258,8 +263,9 @@ def read_initial_condition_from_seir_output( (ic_df["date"] == str(modinf.ti)) & (ic_df["mc_value_type"] == "prevalence") ] if ic_df.empty: - raise ValueError(f"No entry provided for initial time `ti` in the `initial_conditions::states_file.` " - f"`ti`: '{modinf.ti}'." + raise ValueError( + f"No entry provided for initial time `ti` in the `initial_conditions::states_file.` " + f"`ti`: '{modinf.ti}'." ) y0 = np.zeros((modinf.compartments.compartments.shape[0], modinf.nsubpops)) @@ -300,7 +306,9 @@ def read_initial_condition_from_seir_output( if pl in ic_df.columns: y0[comp_idx, pl_idx] = float(ic_df_compartment[pl].iloc[0]) elif allow_missing_subpops: - raise RuntimeError("There is a bug; report this message. Past implemenation was buggy") + raise RuntimeError( + "There is a bug; report this message. Past implemenation was buggy" + ) # TODO this should set the full subpop, not just the 0th commpartment logger.critical( f"No initial conditions for for subpop {pl}, assuming everyone (n={modinf.subpop_pop[pl_idx]}) in the first metacompartments ({modinf.compartments.compartments['name'].iloc[0]})" diff --git a/flepimop/gempyor_pkg/src/gempyor/seeding.py b/flepimop/gempyor_pkg/src/gempyor/seeding.py index 53b81c8dc..885c446ba 100644 --- a/flepimop/gempyor_pkg/src/gempyor/seeding.py +++ b/flepimop/gempyor_pkg/src/gempyor/seeding.py @@ -59,15 +59,15 @@ def _DataFrame2NumbaDict(df, amounts, modinf) -> nb.typed.Dict: source_dict, error_info=f"(seeding source at idx={idx}, row_index={row_index}, row=>>{row}<<)", ) - seeding_dict["seeding_destinations"][idx] = ( - modinf.compartments.get_comp_idx( - destination_dict, - error_info=f"(seeding destination at idx={idx}, row_index={row_index}, row=>>{row}<<)", - ) - ) - seeding_dict["seeding_subpops"][idx] = ( - modinf.subpop_struct.subpop_names.index(row["subpop"]) + seeding_dict["seeding_destinations"][ + idx + ] = modinf.compartments.get_comp_idx( + destination_dict, + error_info=f"(seeding destination at idx={idx}, row_index={row_index}, row=>>{row}<<)", ) + seeding_dict["seeding_subpops"][ + idx + ] = modinf.subpop_struct.subpop_names.index(row["subpop"]) seeding_amounts[idx] = amounts[idx] # id_seed+=1 else: diff --git a/flepimop/gempyor_pkg/src/gempyor/steps_source.py b/flepimop/gempyor_pkg/src/gempyor/steps_source.py index ea6f7ad21..13d5a7ed5 100644 --- a/flepimop/gempyor_pkg/src/gempyor/steps_source.py +++ b/flepimop/gempyor_pkg/src/gempyor/steps_source.py @@ -30,9 +30,7 @@ ## Return "UniTuple(float64[:, :, :], 2) (" ## return states and cumlative states, both [ ndays x ncompartments x nspatial_nodes ] ## Dimensions - "int32," - "int32," - "int32," ## ncompartments ## nspatial_nodes ## Number of days + "int32," "int32," "int32," ## ncompartments ## nspatial_nodes ## Number of days ## Parameters "float64[:, :, :]," "float64," ## Parameters [ nparameters x ndays x nspatial_nodes] ## dt diff --git a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py index e18cdaca2..f82cf2a27 100644 --- a/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py +++ b/flepimop/gempyor_pkg/tests/parameters/test_parameters_class.py @@ -237,8 +237,8 @@ def test_timeseries_parameter_has_insufficient_columns_value_error( with pytest.raises( ValueError, match=( - rf"^Issue loading file '{tmp_file}' for parameter 'sigma': " - rf"the number of non-'date' columns is '{actual_columns}', expected '{mock_inputs.number_of_subpops()}' " + rf"^Issue loading file '{tmp_file}' for parameter 'sigma': " + rf"the number of non-'date' columns is '{actual_columns}', expected '{mock_inputs.number_of_subpops()}' " rf"\(number of subpopulations\) or one\.$" ), ): diff --git a/flepimop/gempyor_pkg/tests/utils/test_utils.py b/flepimop/gempyor_pkg/tests/utils/test_utils.py index 058e2401b..87e7c4fbb 100644 --- a/flepimop/gempyor_pkg/tests/utils/test_utils.py +++ b/flepimop/gempyor_pkg/tests/utils/test_utils.py @@ -115,7 +115,6 @@ def test_create_resume_out_filename(): def test_create_resume_input_filename(): - result = utils.create_resume_input_filename( flepi_slot_index="2", resume_run_index="321", From cde6acbcb20eaf313dfcc1a7e3e2c702cdb6b59b Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Fri, 8 Nov 2024 11:07:11 -0500 Subject: [PATCH 47/48] linting my code with `black` --- .../gempyor_pkg/src/gempyor/compartments.py | 74 +++++++++---------- .../src/gempyor/config_validator.py | 6 +- flepimop/gempyor_pkg/src/gempyor/dev/steps.py | 4 +- flepimop/gempyor_pkg/src/gempyor/seeding.py | 16 ++-- .../gempyor_pkg/src/gempyor/steps_source.py | 4 +- 5 files changed, 54 insertions(+), 50 deletions(-) diff --git a/flepimop/gempyor_pkg/src/gempyor/compartments.py b/flepimop/gempyor_pkg/src/gempyor/compartments.py index e521edffc..da503357f 100644 --- a/flepimop/gempyor_pkg/src/gempyor/compartments.py +++ b/flepimop/gempyor_pkg/src/gempyor/compartments.py @@ -143,11 +143,11 @@ def expand_transition_elements(self, single_transition_config, problem_dimension ) # it is an iterator that will go through all the indexes of the array for x in it: try: - new_transition_config["source"][ - it.multi_index - ] = list_recursive_convert_to_string( - self.access_original_config_by_multi_index( - single_transition_config["source"], it.multi_index + new_transition_config["source"][it.multi_index] = ( + list_recursive_convert_to_string( + self.access_original_config_by_multi_index( + single_transition_config["source"], it.multi_index + ) ) ) except Exception as e: @@ -165,11 +165,11 @@ def expand_transition_elements(self, single_transition_config, problem_dimension raise e try: - new_transition_config["destination"][ - it.multi_index - ] = list_recursive_convert_to_string( - self.access_original_config_by_multi_index( - single_transition_config["destination"], it.multi_index + new_transition_config["destination"][it.multi_index] = ( + list_recursive_convert_to_string( + self.access_original_config_by_multi_index( + single_transition_config["destination"], it.multi_index + ) ) ) except Exception as e: @@ -187,11 +187,11 @@ def expand_transition_elements(self, single_transition_config, problem_dimension raise e try: - new_transition_config["rate"][ - it.multi_index - ] = list_recursive_convert_to_string( - self.access_original_config_by_multi_index( - single_transition_config["rate"], it.multi_index + new_transition_config["rate"][it.multi_index] = ( + list_recursive_convert_to_string( + self.access_original_config_by_multi_index( + single_transition_config["rate"], it.multi_index + ) ) ) except Exception as e: @@ -245,17 +245,17 @@ def expand_transition_elements(self, single_transition_config, problem_dimension it.multi_index, problem_dimension, ) - new_transition_config["proportion_exponent"][ - it.multi_index - ] = list_recursive_convert_to_string( - [ - self.access_original_config_by_multi_index( - single_transition_config["proportion_exponent"][p_idx], - it.multi_index, - problem_dimension, - ) - for p_idx in range(proportion_size) - ] + new_transition_config["proportion_exponent"][it.multi_index] = ( + list_recursive_convert_to_string( + [ + self.access_original_config_by_multi_index( + single_transition_config["proportion_exponent"][p_idx], + it.multi_index, + problem_dimension, + ) + for p_idx in range(proportion_size) + ] + ) ) except Exception as e: print(f"Error {e}:") @@ -574,9 +574,9 @@ def get_transition_array(self): proportion_info[0][ current_proportion_sum_it ] = current_proportion_sum_start - proportion_info[1][ - current_proportion_sum_it - ] = current_proportion_sum_start + len(elem_tmp) + proportion_info[1][current_proportion_sum_it] = ( + current_proportion_sum_start + len(elem_tmp) + ) current_proportion_sum_it += 1 current_proportion_sum_start += len(elem_tmp) proportion_compartment_index = 0 @@ -761,14 +761,14 @@ def parse_parameter_strings_to_numpy_arrays( if not is_totally_resolvable: not_resolvable_indices = [it for it, x in enumerate(is_resolvable) if not x] - tmp_rc[ - not_resolvable_indices - ] = self.parse_parameter_strings_to_numpy_arrays( - parameters, - parameter_names, - [string[not is_resolvable]], - operator_reduce_lambdas, - operators[1:], + tmp_rc[not_resolvable_indices] = ( + self.parse_parameter_strings_to_numpy_arrays( + parameters, + parameter_names, + [string[not is_resolvable]], + operator_reduce_lambdas, + operators[1:], + ) ) for numeric_index in [x for x in range(len(is_numeric)) if is_numeric[x]]: tmp_rc[numeric_index] = parameters[0] * 0 + float(string[numeric_index]) diff --git a/flepimop/gempyor_pkg/src/gempyor/config_validator.py b/flepimop/gempyor_pkg/src/gempyor/config_validator.py index 128fbc6b8..37e749c6d 100644 --- a/flepimop/gempyor_pkg/src/gempyor/config_validator.py +++ b/flepimop/gempyor_pkg/src/gempyor/config_validator.py @@ -184,9 +184,9 @@ def check_distr(cls, values): class BaseParameterConfig(BaseModel): value: Optional[ValueConfig] = None modifier_parameter: Optional[str] = None - name: Optional[ - str - ] = None # this is only for outcomes, to build outcome_prevalence_name (how to restrict this?) + name: Optional[str] = ( + None # this is only for outcomes, to build outcome_prevalence_name (how to restrict this?) + ) class SeirParameterConfig(BaseParameterConfig): diff --git a/flepimop/gempyor_pkg/src/gempyor/dev/steps.py b/flepimop/gempyor_pkg/src/gempyor/dev/steps.py index 3ddde56ee..1bbf5b207 100644 --- a/flepimop/gempyor_pkg/src/gempyor/dev/steps.py +++ b/flepimop/gempyor_pkg/src/gempyor/dev/steps.py @@ -1693,7 +1693,9 @@ def rk4_integrate(today, x): ## Return "UniTuple(float64[:, :, :], 2) (" ## return states and cumlative states, both [ ndays x ncompartments x nspatial_nodes ] ## Dimensions - "int32," "int32," "int32," ## ncompartments ## nspatial_nodes ## Number of days + "int32," + "int32," + "int32," ## ncompartments ## nspatial_nodes ## Number of days ## Parameters "float64[:, :, :]," "float64," ## Parameters [ nparameters x ndays x nspatial_nodes] ## dt diff --git a/flepimop/gempyor_pkg/src/gempyor/seeding.py b/flepimop/gempyor_pkg/src/gempyor/seeding.py index 885c446ba..53b81c8dc 100644 --- a/flepimop/gempyor_pkg/src/gempyor/seeding.py +++ b/flepimop/gempyor_pkg/src/gempyor/seeding.py @@ -59,15 +59,15 @@ def _DataFrame2NumbaDict(df, amounts, modinf) -> nb.typed.Dict: source_dict, error_info=f"(seeding source at idx={idx}, row_index={row_index}, row=>>{row}<<)", ) - seeding_dict["seeding_destinations"][ - idx - ] = modinf.compartments.get_comp_idx( - destination_dict, - error_info=f"(seeding destination at idx={idx}, row_index={row_index}, row=>>{row}<<)", + seeding_dict["seeding_destinations"][idx] = ( + modinf.compartments.get_comp_idx( + destination_dict, + error_info=f"(seeding destination at idx={idx}, row_index={row_index}, row=>>{row}<<)", + ) + ) + seeding_dict["seeding_subpops"][idx] = ( + modinf.subpop_struct.subpop_names.index(row["subpop"]) ) - seeding_dict["seeding_subpops"][ - idx - ] = modinf.subpop_struct.subpop_names.index(row["subpop"]) seeding_amounts[idx] = amounts[idx] # id_seed+=1 else: diff --git a/flepimop/gempyor_pkg/src/gempyor/steps_source.py b/flepimop/gempyor_pkg/src/gempyor/steps_source.py index 13d5a7ed5..ea6f7ad21 100644 --- a/flepimop/gempyor_pkg/src/gempyor/steps_source.py +++ b/flepimop/gempyor_pkg/src/gempyor/steps_source.py @@ -30,7 +30,9 @@ ## Return "UniTuple(float64[:, :, :], 2) (" ## return states and cumlative states, both [ ndays x ncompartments x nspatial_nodes ] ## Dimensions - "int32," "int32," "int32," ## ncompartments ## nspatial_nodes ## Number of days + "int32," + "int32," + "int32," ## ncompartments ## nspatial_nodes ## Number of days ## Parameters "float64[:, :, :]," "float64," ## Parameters [ nparameters x ndays x nspatial_nodes] ## dt From 7b4f6e8ecc8ef4bf113e0dc5442dbdab16aa7dab Mon Sep 17 00:00:00 2001 From: Emily Przykucki Date: Fri, 8 Nov 2024 12:17:02 -0500 Subject: [PATCH 48/48] Capitalization correct in a RegEx in `test_ic.py` --- flepimop/gempyor_pkg/tests/seir/test_ic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flepimop/gempyor_pkg/tests/seir/test_ic.py b/flepimop/gempyor_pkg/tests/seir/test_ic.py index e9c275347..6d39a8ad6 100644 --- a/flepimop/gempyor_pkg/tests/seir/test_ic.py +++ b/flepimop/gempyor_pkg/tests/seir/test_ic.py @@ -48,7 +48,7 @@ def test_IC_allow_missing_node_compartments_success(self): sic.get_from_config(sim_id=100, modinf=s) def test_IC_IC_notImplemented_fail(self): - with pytest.raises(NotImplementedError, match=r".*unknown.*initial.*conditions.*"): + with pytest.raises(NotImplementedError, match=r".*Unknown.*initial.*conditions.*"): config.clear() config.read(user=False) config.set_file(f"{DATA_DIR}/config.yml")