From 98e74b55a34be32d0dd402420c5e6170816d3e3e Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 3 Apr 2024 07:54:39 +1000 Subject: [PATCH 001/161] Add support for selecting subsets of data for calibration --- atomica/calibration.py | 58 ++++++++++++++++++++++++++++++++---------- atomica/utils.py | 2 +- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/atomica/calibration.py b/atomica/calibration.py index ed827fd6..daabd1c7 100644 --- a/atomica/calibration.py +++ b/atomica/calibration.py @@ -46,10 +46,17 @@ def _update_parset(parset, y_factors, pars_to_adjust): raise NotImplementedError -def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, project): - # y-factors, array of y-factors to apply to specified output_quantities - # pars_to_adjust - list of tuples (par_name,pop_name,...) recognized by parset.update() - # output_quantities - a tuple like (pop,var,weight,metric) understood by model.get_pop[pop].getVar +def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, project) -> float: + """ + Run the model for a given set of y-factors and return the objective/goodness-of-fit + + :param y_factors: array of y-factors to apply to specified output_quantities + :param pars_to_adjust: list of tuples (par_name,pop_name,...) recognized by parset.update() + :param output_quantities: a tuple containing (pop, var, weight, metric, start_year, end_year) - start year and end year are inclusive + :param parset: + :param project: + :return: The value of the objective function defined by the output_quantities + """ _update_parset(parset, y_factors, pars_to_adjust) @@ -60,7 +67,8 @@ def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, p objective = 0.0 - for var_label, pop_name, weight, metric in output_quantities: + for var_label, pop_name, weight, metric, start_time, end_time in output_quantities: + target = project.data.get_ts(var_label, pop_name) # This is the TimeSeries with the data for the requested quantity if target is None: continue @@ -68,6 +76,12 @@ def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, p continue var = result.model.get_pop(pop_name).get_variable(var_label) data_t, data_v = target.get_arrays() + inds = (data_t >= start_time) & (data_t <= end_time) + if np.count_nonzero(inds) == 0: + # If no time points remain after filtering down to the time points the user requested + continue + data_t = data_t[inds] + data_v = data_v[inds] # Interpolate the model outputs onto the data times # If there is data outside the range when the model was simulated, don't @@ -114,7 +128,7 @@ def _calc_wape(y_obs, y_fit): return abs(y_fit - y_obs) / (y_obs.mean() + calibration_settings["tolerance"]) -def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, max_time=60, method="asd", **kwargs) -> ParameterSet: +def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, max_time=60, method="asd", time_period=(-np.inf, np.inf), **kwargs) -> ParameterSet: """ Run automated calibration @@ -125,8 +139,13 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, relevant to the parameter independently, or 'all' which will instead operate on the meta y factor. :param output_quantities: list of tuples, (var_label,pop_name,weight,metric), for use in the objective - function. pop_name=None will expand to all pops. pop_name='all' is not supported + function. pop_name=None will expand to all pops. pop_name='all' is not supported. The + output can optionally contain (var_label, pop_name, weight, metric, start_year, end_year) + to select a subset of the data for evaluating the objective. The start year and end year + specified here will take precedence over the time_period argument :param max_time: If using ASD, the maximum run time + :param time_period: Tuple of start and end years to use for the objective function. Applies to all outputs unless + the output has an explicitly specified start and end year :param method: 'asd' or 'pso'. If using 'pso' all upper and lower limits must be finite :param kwargs: Dictionary of additional arguments to be passed to the optimization function, e.g. stepsize or pinitial :return: A calibrated :class:`ParameterSet` @@ -145,15 +164,26 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, pars_to_adjust = p2 # Expand out pop=None in output_quantities - o2 = [] + outputs = [] for output_tuple in output_quantities: - if output_tuple[1] is None: # If the pop name is None - pops = project.data.pops.keys() - for pop_name in pops: - o2.append((output_tuple[0], pop_name, output_tuple[2], output_tuple[3])) + var_label = output_tuple[0] + pop_name = output_tuple[1] + weight = output_tuple[2] + metric = output_tuple[3] + if len(output_tuple) == 6: + start_time = output_tuple[4] + end_time = output_tuple[5] else: - o2.append(output_tuple) - output_quantities = o2 + start_time = time_period[0] + end_time = time_period[1] + + if pop_name is None: # If the pop name is None + for pop in project.data.pops.keys(): + outputs.append((var_label, pop, weight, metric, start_time, end_time)) + else: + outputs.append((var_label, pop_name, weight, metric, start_time, end_time)) + + output_quantities = outputs args = { "project": project, diff --git a/atomica/utils.py b/atomica/utils.py index ee342e54..9e7dc3ce 100644 --- a/atomica/utils.py +++ b/atomica/utils.py @@ -489,7 +489,7 @@ def remove_after(self, t_remove) -> None: """ Remove times from start - :param tval: Remove times up to but not including this time + :param tval: Remove times after but not including this time """ From 08bfb32be1de6439a4c16426f8bbd2b8b21bc2df Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Fri, 26 Apr 2024 17:30:14 +0200 Subject: [PATCH 002/161] Enable specifying initial values for the y-factors --- atomica/calibration.py | 70 +++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/atomica/calibration.py b/atomica/calibration.py index daabd1c7..ec3444ab 100644 --- a/atomica/calibration.py +++ b/atomica/calibration.py @@ -79,6 +79,7 @@ def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, p inds = (data_t >= start_time) & (data_t <= end_time) if np.count_nonzero(inds) == 0: # If no time points remain after filtering down to the time points the user requested + logger.info(f'No data points remaining after filtering down to requested time period. Skipping...') continue data_t = data_t[inds] data_v = data_v[inds] @@ -152,15 +153,22 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, """ + # Expand out pop=None in pars_to_adjust p2 = [] for par_tuple in pars_to_adjust: + if len(par_tuple) == 5: + initial_value = par_tuple[4] + else: + initial_value = None + if par_tuple[1] is None: # If the pop name is None par = parset.pars[par_tuple[0]] for pop_name in par.pops: - p2.append((par_tuple[0], pop_name, par_tuple[2], par_tuple[3])) + p2.append((par_tuple[0], pop_name, par_tuple[2], par_tuple[3], initial_value)) else: - p2.append(par_tuple) + p2.append((par_tuple[0], par_tuple[1], par_tuple[2], par_tuple[3], initial_value)) + pars_to_adjust = p2 # Expand out pop=None in output_quantities @@ -185,30 +193,56 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, output_quantities = outputs - args = { - "project": project, - "parset": parset.copy(), - "pars_to_adjust": pars_to_adjust, - "output_quantities": output_quantities, - } - x0 = [] xmin = [] xmax = [] + filtered_pars_to_adjust = [] + parset = parset.copy() + for i, x in enumerate(pars_to_adjust): - par_name, pop_name, scale_min, scale_max = x + par_name, pop_name, scale_min, scale_max, initial_value = x + if par_name in parset.pars: par = parset.pars[par_name] - if pop_name == "all": - x0.append(par.meta_y_factor) - else: - x0.append(par.y_factor[pop_name]) else: tokens = par_name.split("_from_") par = parset.transfers[tokens[0]][tokens[1]] - x0.append(par.y_factor[pop_name]) - xmin.append(scale_min) - xmax.append(scale_max) + + #if initial_value has not been explicitly set in the tuple: use y_factor in parset + if initial_value is None: + if pop_name == "all": + initial_value = par.meta_y_factor + else: + initial_value = par.y_factor[pop_name] + #if this value is outside the min and max bounds, make it equal to min or max (whichever is closest) + #if min == max, this should make the initial value equal to min and max + initial_value = np.clip(initial_value, scale_min, scale_max) + else: + assert (initial_value >= scale_min) and (initial_value <= scale_max), 'Initial value is not consistent with the lower/upper bounds' + + #update y_factors in parset + if initial_value is not None: #if statement redundant? + if pop_name == 'all': + par.meta_y_factor = initial_value + else: + par.y_factor[pop_name] = initial_value + + if scale_min != scale_max: + # Only include the y-factor in the adjustments made in the optimization function if a range + # of y-factor values is permitted + filtered_pars_to_adjust.append(x) + x0.append(initial_value) + xmin.append(scale_min) + xmax.append(scale_max) + + + + args = { + "project": project, + "parset": parset, + "pars_to_adjust": filtered_pars_to_adjust, + "output_quantities": output_quantities, + } original_sim_end = project.settings.sim_end project.settings.sim_end = min(project.data.tvec[-1], original_sim_end) @@ -254,7 +288,7 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, finally: project.settings.sim_end = original_sim_end # Restore the simulation end year - _update_parset(args["parset"], x1, pars_to_adjust) + _update_parset(args["parset"], x1, args["pars_to_adjust"]) # Log out the commands required for equivalent manual calibration if desired for i, x in enumerate(pars_to_adjust): From 875b2ac75766b9d303b6f0be6291ad821e9daea7 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Fri, 31 May 2024 17:15:12 +1000 Subject: [PATCH 003/161] Change *_time to *_year, and permit superfluous arguments --- atomica/calibration.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/atomica/calibration.py b/atomica/calibration.py index ec3444ab..45790d2a 100644 --- a/atomica/calibration.py +++ b/atomica/calibration.py @@ -46,10 +46,12 @@ def _update_parset(parset, y_factors, pars_to_adjust): raise NotImplementedError -def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, project) -> float: +def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, project, *args, **kwargs) -> float: """ Run the model for a given set of y-factors and return the objective/goodness-of-fit + Additional extra arguments will be ignored but will not raise an error. + :param y_factors: array of y-factors to apply to specified output_quantities :param pars_to_adjust: list of tuples (par_name,pop_name,...) recognized by parset.update() :param output_quantities: a tuple containing (pop, var, weight, metric, start_year, end_year) - start year and end year are inclusive @@ -67,7 +69,7 @@ def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, p objective = 0.0 - for var_label, pop_name, weight, metric, start_time, end_time in output_quantities: + for var_label, pop_name, weight, metric, start_year, end_year in output_quantities: target = project.data.get_ts(var_label, pop_name) # This is the TimeSeries with the data for the requested quantity if target is None: @@ -76,7 +78,7 @@ def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, p continue var = result.model.get_pop(pop_name).get_variable(var_label) data_t, data_v = target.get_arrays() - inds = (data_t >= start_time) & (data_t <= end_time) + inds = (data_t >= start_year) & (data_t <= end_year) if np.count_nonzero(inds) == 0: # If no time points remain after filtering down to the time points the user requested logger.info(f'No data points remaining after filtering down to requested time period. Skipping...') @@ -135,13 +137,13 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, :param project: A project instance to provide data and sim settings :param parset: A :class:`ParameterSet` instance to calibrate - :param pars_to_adjust: list of tuples, (par_name,pop_name,lower_limit,upper_limit) + :param pars_to_adjust: list of tuples, `(par_name, pop_name, lower_bound, upper_bound, initial_value)` the pop name can be None, which will be expanded to all populations relevant to the parameter independently, or 'all' which will instead operate on the meta y factor. :param output_quantities: list of tuples, (var_label,pop_name,weight,metric), for use in the objective function. pop_name=None will expand to all pops. pop_name='all' is not supported. The - output can optionally contain (var_label, pop_name, weight, metric, start_year, end_year) + output can optionally contain `(var_label, pop_name, weight, metric, start_year, end_year)` to select a subset of the data for evaluating the objective. The start year and end year specified here will take precedence over the time_period argument :param max_time: If using ASD, the maximum run time @@ -179,17 +181,17 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, weight = output_tuple[2] metric = output_tuple[3] if len(output_tuple) == 6: - start_time = output_tuple[4] - end_time = output_tuple[5] + start_year = output_tuple[4] + end_year = output_tuple[5] else: - start_time = time_period[0] - end_time = time_period[1] + start_year = time_period[0] + end_year = time_period[1] if pop_name is None: # If the pop name is None for pop in project.data.pops.keys(): - outputs.append((var_label, pop, weight, metric, start_time, end_time)) + outputs.append((var_label, pop, weight, metric, start_year, end_year)) else: - outputs.append((var_label, pop_name, weight, metric, start_time, end_time)) + outputs.append((var_label, pop_name, weight, metric, start_year, end_year)) output_quantities = outputs From 0b4270fb129ccced0f45cab6b199f9a4fc7ddbb7 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Fri, 31 May 2024 18:19:48 +0200 Subject: [PATCH 004/161] Only call ASD if there are pars to adjust left after filtering --- atomica/calibration.py | 85 ++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 41 deletions(-) diff --git a/atomica/calibration.py b/atomica/calibration.py index 45790d2a..d4cbf288 100644 --- a/atomica/calibration.py +++ b/atomica/calibration.py @@ -249,48 +249,51 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, original_sim_end = project.settings.sim_end project.settings.sim_end = min(project.data.tvec[-1], original_sim_end) - try: - if method == "asd": - optim_args = { - "stepsize": 0.1, - "maxiters": 2000, - "sinc": 1.5, - "sdec": 2.0, - "reltol": 1e-3, - "abstol": 1e-6, - "xmin": xmin, - "xmax": xmax, - } - optim_args.update(kwargs) - - if max_time is not None: - optim_args["maxtime"] = max_time - - log_level = logger.getEffectiveLevel() - if log_level < logging.WARNING: - optim_args["verbose"] = 2 + if len(filtered_pars_to_adjust) > 0: + try: + if method == "asd": + optim_args = { + "stepsize": 0.1, + "maxiters": 2000, + "sinc": 1.5, + "sdec": 2.0, + "reltol": 1e-3, + "abstol": 1e-6, + "xmin": xmin, + "xmax": xmax, + } + optim_args.update(kwargs) + + if max_time is not None: + optim_args["maxtime"] = max_time + + log_level = logger.getEffectiveLevel() + if log_level < logging.WARNING: + optim_args["verbose"] = 2 + else: + optim_args["verbose"] = 0 + + opt_result = sc.asd(_calculate_objective, x0, args, **optim_args) + x1 = opt_result["x"] + elif method == "pso": + import pyswarm + + optim_args = {"maxiter": 3, "lb": xmin, "ub": xmax, "minstep": 1e-3, "debug": True} + if np.any(~np.isfinite(xmin)) or np.any(~np.isfinite(xmax)): + errormsg = "PSO optimization requires finite upper and lower bounds to specify the search domain (i.e. every parameter being adjusted needs to have finite bounds)" + raise Exception(errormsg) + + x1, _ = pyswarm.pso(_calculate_objective, kwargs=args, **optim_args) else: - optim_args["verbose"] = 0 - - opt_result = sc.asd(_calculate_objective, x0, args, **optim_args) - x1 = opt_result["x"] - elif method == "pso": - import pyswarm - - optim_args = {"maxiter": 3, "lb": xmin, "ub": xmax, "minstep": 1e-3, "debug": True} - if np.any(~np.isfinite(xmin)) or np.any(~np.isfinite(xmax)): - errormsg = "PSO optimization requires finite upper and lower bounds to specify the search domain (i.e. every parameter being adjusted needs to have finite bounds)" - raise Exception(errormsg) - - x1, _ = pyswarm.pso(_calculate_objective, kwargs=args, **optim_args) - else: - raise Exception("Unrecognized method") - except Exception as e: - raise e - finally: - project.settings.sim_end = original_sim_end # Restore the simulation end year - - _update_parset(args["parset"], x1, args["pars_to_adjust"]) + raise Exception("Unrecognized method") + except Exception as e: + raise e + finally: + project.settings.sim_end = original_sim_end # Restore the simulation end year + + _update_parset(args["parset"], x1, args["pars_to_adjust"]) + else: + logger.info('No parameters to adjust provided to the optimisation function. Skipping optimisation...') # Log out the commands required for equivalent manual calibration if desired for i, x in enumerate(pars_to_adjust): From adc6e2ac958c37dad0db2231f24203b0a94c4f0a Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 3 Jun 2024 17:56:59 +1000 Subject: [PATCH 005/161] Add YAML calibration file --- atomica/utils.py | 19 ++ atomica/yaml_calibration.py | 485 ++++++++++++++++++++++++++++++++++++ 2 files changed, 504 insertions(+) create mode 100644 atomica/yaml_calibration.py diff --git a/atomica/utils.py b/atomica/utils.py index 9e7dc3ce..c33b7618 100644 --- a/atomica/utils.py +++ b/atomica/utils.py @@ -36,6 +36,7 @@ "parallel_progress", "start_logging", "stop_logging", + "get_sigfigs_necessary", ] @@ -982,3 +983,21 @@ def stop_logging() -> None: logger.removeHandler(handler) # Don't terminate the loop, if by some change there is more than one handler # (not supposed to happen though) then we would want to close them all + + +def get_sigfigs_necessary(x, y, min_sigfigs: int = 2) -> int: + """ + Get how many significant figures are necessary to tell the difference berween two numbers + + :param x, y: numbers to compare + :param min_sigfigs: minimum number of sigfigs to use if no difference + :return: Number of significant figures required + """ + msf = min_sigfigs + assert sc.isnumber(x) and sc.isnumber(y), f'Cannot compare sigfigs as {x} and {y} are not both numbers' + if x == y or np.isnan(x) or np.isnan(y): + return msf + else: + while sc.sigfig(x=x, sigfigs=msf) == sc.sigfig(x=y, sigfigs=msf): + msf += 1 + return msf diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py new file mode 100644 index 00000000..4bb7bb13 --- /dev/null +++ b/atomica/yaml_calibration.py @@ -0,0 +1,485 @@ +""" +This file implements YAML calibration, a mechanism of programming multiple automated calibration steps +(and related operations). Essentially this scheme coordinates repeated calls to at.calibrate with different +adjustables and measurables in a pre-defined sequence of automated calibration steps. +""" + +import sciris as sc +from pathlib import Path +import atomica as at +from collections import defaultdict, Counter +import numpy as np +import yaml + +__all__ = ['build', 'run'] + +def _get_named_nodes(): + """ + Return dictionary with all named Node subclasses + """ + return {x._name: x for x in BaseNode.__subclasses__() if x._name is not None} + +def build(instructions=None, context=None, name='calibration'): + """ + Construct nodes representing a calibration + + :param instructions: A dictionary of attributes/settings defined for this node OR a string filename + containing a YAML file that can be loaded to provide instructions + :param context: A dictionary of attributes/settings inherited from parent nodes + :param name: The name to assign this node + :param fname: Optionally read the instructions from a file + :return: A Node subclass instance, the type of which depends on the instructions + """ + + if (sc.isstring(instructions) or isinstance(instructions, Path)) and Path(instructions).exists(): + with open(instructions) as file: + instructions = yaml.load(file, Loader=yaml.FullLoader) + + named_nodes = _get_named_nodes() + if isinstance(instructions, dict) and ('adjustables' in instructions or (context is not None and 'adjustables' in context)) and ('measurables' in instructions or (context is not None and 'measurables' in context)): + return CalibrationNode(instructions, context, name) + elif name in named_nodes: + return named_nodes[name](instructions, context, name) + else: + return Section(instructions, context, name) + +def run(node, project, parset, savedir=None, save_intermediate=False, log_output:bool=False,*args, **kwargs): + """ + Run YAML calibration + + This will execute the YAML calibration using the passed-in node (or instructions to build a node), and any associated children + + :param node: Calibration node to execute. If not a node (i.e., a YAML file, or node instructions), it will be converted into a node + :param P: Project to which to apply these instructions + :param parset: An `at.ParameterSet` instance to calibrate + :param savedir: Optionally specify a directory to save the results. Defaults to the current working directory + :param save_intermediate: Set whether to save intermediate calibrations (defaults to False) + :return new_parset: A calibrated `at.ParameterSet` instance + """ + + if not isinstance(node, BaseNode): + node = build(node) + + parset = sc.dcp(project.parset(parset)) + + if savedir is None: + savedir = Path('.') + else: + savedir = Path(savedir) + + nodes = list(node.walk()) # Make a flat list of all nodes to execute in order + n_steps = len([x for x in nodes if not isinstance(x[1], Section)]) + n = 1 + + if log_output: + at.start_logging(savedir/'calibration_log.txt') + + at.logger.info(f'Starting calibration ({n_steps} steps)') + + for n_reps, node in nodes: + + if isinstance(node, Section): + at.logger.info(f'\nSection "{node.name}" (repeat {n_reps} of {node.repeats})') + else: + at.logger.info(f'\nStep {n} of {n_steps} "{node.name} (repeat {n_reps} of {node.repeats})') + parset = node.apply(project, parset, savedir, save_intermediate, *args, **kwargs) + n += 1 + + if save_intermediate and not isinstance(node, SaveCalibrationNode): + output = savedir / f'intermediate_calibration_{n:0{len(str(n_steps))}}_{self.name.replace(" ", "_")}' + parset.save_calibration(output) + at.logger.info(f'Saved intermediate calibration to {output}') + + at.logger.info(f'\nCalibration completed') + + if log_output: + at.stop_logging() + + return parset + + +class BaseNode: + """ + Node base class + + The base node class implements basic node features. Typically there should not be any + instances of this class, only instances of subclasses + """ + + _name = None # If specified, this key can be used as the name of the step to create a node of this type + + def __init__(self, instructions, context, name): + self.name = name + self.instructions = sc.dcp(instructions) + self.context = context # Attributes inherited from parent nodes + self.children = [] + self.validate() + + def walk(self): + n_reps = 0 + for repeat in range(self.repeats): + n_reps += 1 + yield (n_reps, self) + for child in self.children: + yield from child.walk() + + @property + def n_steps(self): + if type(self) == BaseNode: + return self.repeats * sum(child.n_steps for child in self.children) + else: + return self.repeats + + def __repr__(self): + return f'<{self.__class__.__name__} "{self.name}" x{self.repeats}>' + + def __str__(self, indent=0): + """ + Print a tree representation of this node and all children + + :param indent: Recursively increase the indent for child nodes + :return: + """ + s = '\t' * indent + self.__repr__() + for child in self.children: + s += '\n' + child.__str__(indent=indent + 1) + return s + + @property + def attributes(self): + return sc.mergedicts(self.context, self.instructions) + + def __getitem__(self, item): + # Directly index the Node to extract attributes without merging the dictionaries every time + if item in self.instructions: + return self.instructions[item] + elif item in self.context: + return self.context[item] + else: + raise KeyError(item) + + def __setitem__(self, key, value): + self.instructions[key] = value + + def __contains__(self, item): + return item in self.instructions or item in self.context + + @property + def repeats(self): + # Although repeats may be part of the context, we only repeat a node if the instructions requested a repeat + # i.e., repeats are not inherited + if isinstance(self.instructions, dict) and 'repeats' in self.instructions: + return self.instructions['repeats'] + else: + return 1 + + def validate(self): + """ + Validate/sanitize contents of this node + + If the node isn't valid, an error should be raised + """ + return + + def apply(self, project: at.Project, parset: at.ParameterSet, savedir, *args, **kwargs) -> tuple: + """ + Perform the action associated with this node + """ + return parset + +class Section(BaseNode): + """ + A section node is a special kind of node, that contains other nodes + """ + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.children = self.make_children() + self.validate() + + def make_children(self): + + children = [] + + # Remove any keys in the instructions that correspond to named nodes + # These should be used as instructions for the child node, rather than + # forming part of the context that is passed down to all children + named_nodes = _get_named_nodes() + step_instructions = {k: v for k, v in self.instructions.items() if isinstance(v, dict) or k in named_nodes} + for k in step_instructions: + del self.instructions[k] + + # Create the child nodes + for name, instructions in step_instructions.items(): + children.append(build(instructions, self.attributes, name)) + + return children + +class CalibrationNode(BaseNode): + + # Order for list of adjustable parameters and default values + adj_defaults = { + 'lower_bound': 0.1, + 'upper_bound': 10.0, + 'initial_value': None, + } + + # Order for list of measurable parameters and default values + meas_defaults = { + 'weight': 1.0, + 'metric': 'fractional', + 'start_year': -np.inf, + 'end_year': np.inf, + } + + @staticmethod + def parse_list(l, defaults): + # Routine to parse list of arguments into a dictionary of values + d = {} + for k, v in zip(list(defaults.keys())[:len(l)], l): + d[k] = v + return d + + def validate(self): + """ + Pre-parse calibration inputs + """ + + def process_key(s): + # Sanitize key name with optional space separating pop name + if ' ' in s: + return tuple([x for x in s.split(' ') if x]) + else: + return (s.strip(), None) + + def process_inputs(inputs, defaults): + # Process adjustables and measurables, which can be specified in a list representation or nested dict representation + # In list representation, the input is a list of lists, where the first item in each list is the quantity (with optional population) and + # the remaining items are the supported arguments for the input type, in the order defined by the defaults dictionary. + # In a dict representation, the key is the quantity with optional population, and then the value can either be a list (in the order defined by the dictionary) + # or a dictionary explicitly naming the inputs. + # This function returns a flat dictionary with {(quantity, pop_name):{argument:value}} e.g., {('b_rate','0-5'):{'lower_bound':0.5}}. + # In the dict representation, the key can be a comma separated list of quantities with optional values e.g., 'b_rate 0-5, d_rate'. In the list representation, + # multiple quantities are not supported (as a comma is already used to separate the arguments) + out = {} + + if sc.isstring(inputs): + # Support a comma separated string with "quantity pop" specifications of adjustables and measurables + # In this case, default values should be used for all other items. Proceed by splitting into a list + inputs = inputs.split(',') + + if isinstance(inputs, (tuple, list)): + for l in inputs: + l = sc.promotetolist(l) + key, pop_name = process_key(l[0].strip()) + d = self.parse_list(l[1:], defaults) + out[key, pop_name] = sc.mergedicts(out.get((key, pop_name), {}), d) + elif isinstance(inputs, dict): + for keys, v in inputs.items(): + for key in keys.split(','): + key, pop_name = process_key(key.strip()) + if isinstance(v, (tuple, list)): + d = self.parse_list(v, defaults) + else: + d = v.copy() + out[key, pop_name] = sc.mergedicts(out.get((key, pop_name), {}), d) + + return out + + self['adjustables'] = process_inputs(self['adjustables'], self.adj_defaults) + self['measurables'] = process_inputs(self['measurables'], self.meas_defaults) + + # Validate adjustables + def check_optional_number(key, v, defaults): + if key in v and v[key] is not None: + if not sc.isnumber(v[key], isnan=False): + raise TypeError(f"Adjustable argument '{key}' needs to be a number or None (defaults to {defaults[key]}). Provided value: {v[key]} ") + + assert len(self['adjustables']) > 0, f'Cannot calibrate with no adjustables for calibration section {self.name}' + for (quantity, pop_name), v in self['adjustables'].items(): + assert 'pop_name' not in v, f'Setting the population name through "pop_name: {v["pop_name"]}" is not supported. Instead, the name of the adjustable quantity should include the population name ("{quantity} {v["pop_name"]}")' + assert isinstance(quantity, str), f'Adjustable codename {quantity} needs to be a string' + assert pop_name is None or isinstance(pop_name, str), f'Adjustable population {pop_name} needs to be a string or None (defaults to all populations for that parameter)' + check_optional_number('lower_bound',v, self.adj_defaults) + check_optional_number('upper_bound',v, self.adj_defaults) + check_optional_number('initial_value',v, self.adj_defaults) + + # Validate measurables + assert len(self['measurables']) > 0, f'Cannot calibrate with no measurables for calibration section {self.name}' + for (quantity, pop_name), v in self['measurables'].items(): + assert isinstance(quantity, str), f'Measurable codename {quantity} needs to be a string' + assert pop_name is None or isinstance(pop_name, str), f'Adjustable population {pop_name} needs to be a string or None (defaults to all populations for that parameter)' + assert 'metric' not in v or v['metric'] is None or isinstance(v["metric"], str), f"Measurable metric {v['metric']} needs to be a number or None (defaults to 'fractional')" + + check_optional_number('weight',v, self.meas_defaults) + check_optional_number('start_year',v, self.meas_defaults) + check_optional_number('end_year',v, self.meas_defaults) + + def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, quiet=False, compare_results=False, **kwargs) -> tuple: + + step_name = self.name + attributes = self.attributes + + at.logger.info(f'Calibrating adjustable(s) {[adj[0] for adj in attributes["adjustables"]]} to match measurable(s) {[mea[0] for mea in attributes["measurables"]]}...') + + # Expand adjustables + adjustables = [] + par_names = {x[0] for x in attributes['adjustables']}.intersection(x.name for x in parset.all_pars()) + pop_names = {x[1] for x in attributes['adjustables']}.intersection({*parset.pop_names} | {'all', None}) + + for par_name, pop_name in attributes['adjustables']: + + if par_name not in par_names: + at.logger.warning(f"Extra YAML adjustable parameter '{par_name}' does not exist in this project's framework and will be ignored") + continue + elif pop_name not in pop_names: + at.logger.warning(f"Extra YAML adjustable population '{pop_name}' does not exist in this project's databook and will be ignored") + continue + + if pop_name is None: + pops = parset.pop_names + else: + pops = sc.promotetolist(pop_name) + + for pop in pops: + d = sc.mergedicts(self.adj_defaults, attributes['adjustables'].get((par_name, None), None), attributes['adjustables'].get((par_name, pop), None)) + adjustables.append((par_name, pop, d['lower_bound'], d['upper_bound'], d['initial_value'])) + + # Expand measurables + measurables = [] + par_names = {x[0] for x in attributes['measurables']}.intersection(x.name for x in parset.all_pars()) # TODO: This is probably OK for now but will need to support transfer parameters and validate that pars have databook entries in the future + pop_names = {x[1] for x in attributes['measurables']}.intersection({*parset.pop_names} | {None}) + + for par_name, pop_name in attributes['measurables']: + + if par_name not in par_names: + at.logger.warning(f"Extra YAML measurable variable '{par_name}' does not exist in this project's framework and will be ignored") + continue + elif pop_name not in pop_names: + at.logger.warning(f"Extra YAML measurable population '{pop_name}' does not exist in this project's databook and will be ignored") + continue + + if pop_name is None: + pops = parset.pop_names + else: + pops = sc.promotetolist(pop_name) + + for pop in pops: + d = sc.mergedicts(self.meas_defaults, attributes['measurables'].get((par_name, None), None), attributes['measurables'].get((par_name, pop), None)) + measurables.append((par_name, pop_name, d['weight'], d['metric'], d['start_year'], d['end_year'])) + + # Calibration + if len(adjustables): + + kwargs = sc.mergedicts(self.attributes, kwargs) + + del kwargs['adjustables'] # supplied via the adjustables variable + del kwargs['measurables'] # supplied via the measurables variable + + if 'repeats' in kwargs: + del kwargs['repeats'] + + if quiet: + with at.Quiet(show_warnings=False): + new_cal_parset = at.calibrate(project, parset, adjustables, measurables, **kwargs) + else: + new_cal_parset = at.calibrate(project, parset, adjustables, measurables, **kwargs) + else: + new_cal_parset = parset + + at.logger.info(f'Completed "{step_name}"...') + made_changes = False + + for par, pop, *_ in adjustables: + if pop == 'all': + old = parset.pars[par].meta_y_factor + new = new_cal_parset.pars[par].meta_y_factor + else: + old = parset.pars[par].y_factor[pop] + new = new_cal_parset.pars[par].y_factor[pop] + + if new != old: + at.logger.info(f'...adjusted the y-factor for {par} in {pop} from {old} to {new}') + made_changes = True + else: + at.logger.debug(f'...did NOT adjust the y-factor for {par} in {pop} from {old} to {new}') + + if not made_changes: + at.logger.info(f'...made no changes!') + + if compare_results: + base_res = project.run_sim(parset=parset) + cal_res = project.run_sim(parset=new_cal_parset) + for par_name in [par_measure[0] for par_measure in measurables]: + base_rms_error = 0 + cal_rms_error = 0 + for pop in parset.pars[par_name].ts.keys(): + for time_par_ind, time_value in enumerate(parset.pars[par_name].ts[pop].t): + data_time_val = parset.pars[par_name].ts[pop].vals[time_par_ind] + base_res_time_ind = list(base_res.get_variable(par_name, pop)[0].t).index(time_value) + base_time_val = base_res.get_variable(par_name, pop)[0].vals[base_res_time_ind] + cal_res_time_ind = list(cal_res.get_variable(par_name, pop)[0].t).index(time_value) # probably redundant as they *should* be the same + cal_time_val = cal_res.get_variable(par_name, pop)[0].vals[cal_res_time_ind] + + base_rms_error += (data_time_val - base_time_val) ** 2 + cal_rms_error += (data_time_val - cal_time_val) ** 2 + + sf = at.get_sigfigs_necessary(base_time_val, cal_time_val) + at.logger.info(f'...for parameter {par_name} and population {pop} at time {time_value} the data value was {sc.sigfig(data_time_val, sf)}, the baseline value was {sc.sigfig(base_time_val, sf)}, and the calibrated value was {sc.sigfig(cal_time_val, sf)}.') + + base_rms_error = base_rms_error ** 0.5 + cal_rms_error = cal_rms_error ** 0.5 + sf = get_sigfigs_necessary(base_rms_error, cal_rms_error) + at.logger.info(f'...RMS error for parameter {par_name} has changed from baseline {sc.sigfig(base_rms_error, sf)} to calibrated {sc.sigfig(cal_rms_error, sf)}') + + return new_cal_parset + + +class InitializationNode(BaseNode): + _name = 'set_initialization' + + def __init__(self, instructions, context, name): + if not isinstance(instructions, dict): + instructions = {'year': instructions} + super().__init__(instructions, context, name) + + def validate(self): + assert 'year' in self, f'Initialisation year must be specified' + assert sc.isnumber(self['year']), f'Reinitialisation year {self["year"]} must be numeric.' + + def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, **kwargs) -> tuple: + new_settings = sc.dcp(project.settings) + new_settings.update_time_vector(end=self['year']) + res = at.run_model(settings=new_settings, framework=project.framework, parset=parset) + parset.set_initialization(res, self['year']) + return parset + + +class ClearInitializationNode(BaseNode): + _name = 'clear_initialization' + + def __init__(self, instructions, context, name): + super().__init__(instructions=None, context=context, name=name) + + def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, **kwargs) -> tuple: + parset.initialization = None + return parset + + +class SaveCalibrationNode(BaseNode): + """ + Block in YAML file with "save calibration: " + """ + + _name = 'save_calibration' + + def __init__(self, instructions, context, name): + if not isinstance(instructions, dict): + instructions = {'fname': instructions} + super().__init__(instructions, context, name) + + def validate(self): + assert self['fname'] is not None, 'A "save calibration" node must have a file name explicitly specified' + + def apply(self, project: at.Project, parset: at.ParameterSet, savedir=None, *args, **kwargs) -> tuple: + parset.save_calibration(savedir / self['fname']) + return parset From 134f1ad867f332e8e4302986840ccd615666eb45 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 3 Jun 2024 17:57:11 +1000 Subject: [PATCH 006/161] Improve default handling --- atomica/calibration.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/atomica/calibration.py b/atomica/calibration.py index 45790d2a..cea7d7b4 100644 --- a/atomica/calibration.py +++ b/atomica/calibration.py @@ -131,7 +131,7 @@ def _calc_wape(y_obs, y_fit): return abs(y_fit - y_obs) / (y_obs.mean() + calibration_settings["tolerance"]) -def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, max_time=60, method="asd", time_period=(-np.inf, np.inf), **kwargs) -> ParameterSet: +def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, max_time=None, method="asd", time_period=(-np.inf, np.inf), **kwargs) -> ParameterSet: """ Run automated calibration @@ -223,11 +223,10 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, assert (initial_value >= scale_min) and (initial_value <= scale_max), 'Initial value is not consistent with the lower/upper bounds' #update y_factors in parset - if initial_value is not None: #if statement redundant? - if pop_name == 'all': - par.meta_y_factor = initial_value - else: - par.y_factor[pop_name] = initial_value + if pop_name == 'all': + par.meta_y_factor = initial_value + else: + par.y_factor[pop_name] = initial_value if scale_min != scale_max: # Only include the y-factor in the adjustments made in the optimization function if a range @@ -260,12 +259,10 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, "abstol": 1e-6, "xmin": xmin, "xmax": xmax, + "maxtime": 60 if max_time is None else max_time, } optim_args.update(kwargs) - if max_time is not None: - optim_args["maxtime"] = max_time - log_level = logger.getEffectiveLevel() if log_level < logging.WARNING: optim_args["verbose"] = 2 From 34a3978d00b6a1a326e0cd4a608544bb2d900c8c Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 3 Jun 2024 17:57:26 +1000 Subject: [PATCH 007/161] Update Project.calibrate() to support YAML --- atomica/project.py | 71 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/atomica/project.py b/atomica/project.py index e6881957..32877240 100644 --- a/atomica/project.py +++ b/atomica/project.py @@ -577,7 +577,18 @@ def run_sampled_sims(self, parset, progset=None, progset_instructions=None, resu return results - def calibrate(self, parset=None, adjustables=None, measurables=None, max_time=60, save_to_project=False, new_name=None, default_min_scale=0.0, default_max_scale=2.0, default_weight=1.0, default_metric="fractional", **kwargs) -> ParameterSet: + def calibrate(self, + parset=None, + adjustables=None, + measurables=None, + save_to_project=False, + new_name=None, + default_min_scale=0.0, + default_max_scale=2.0, + default_weight=1.0, + default_metric="fractional", + yaml=None, + **kwargs) -> ParameterSet: """ Method to perform automatic calibration. @@ -603,6 +614,23 @@ def calibrate(self, parset=None, adjustables=None, measurables=None, max_time=60 To calibrate a project-attached parameter set in place, provide its key as the new name argument to this method. Current fitting metrics are: "fractional", "meansquare", "wape" Note that scaling limits are absolute, not relative. + + Additional keyword arguments will be passed to `at.calibrate` so additional arguments such as `max_time` + or `methods` can be provided to this function. + + :param parset: + :param adjustables: + :param measurables: + :param save_to_project: + :param new_name: + :param default_min_scale: + :param default_max_scale: + :param default_weight: + :param default_metric: + :param yaml: Optionally specify a YAML file or YAML calibration dictionary to use for calibration + :param kwargs: + :return: + """ if parset is None: @@ -610,23 +638,36 @@ def calibrate(self, parset=None, adjustables=None, measurables=None, max_time=60 elif not isinstance(parset, ParameterSet): parset = self.parsets[parset] + if yaml is not None: + import atomica.yaml_calibration # Avoid circular import + assert adjustables is None, "If a YAML file is specified, adjustables should not be set" + assert measurables is None, "If a YAML file is specified, measurables should not be set" + new_parset = atomica.yaml_calibration.run(yaml, self, parset, **kwargs) + else: + if adjustables is None: + adjustables = list(self.framework.pars.index[~self.framework.pars["calibrate"].isnull()]) + adjustables += list(self.framework.comps.index[~self.framework.comps["calibrate"].isnull()]) + adjustables += list(self.framework.characs.index[~self.framework.characs["calibrate"].isnull()]) + + if measurables is None: + measurables = list(self.framework.comps.index) + measurables += list(self.framework.characs.index) + + for index, adjustable in enumerate(adjustables): + if sc.isstring(adjustable): # Assume that a parameter name was passed in if not a tuple. + adjustables[index] = (adjustable, None, default_min_scale, default_max_scale) + + for index, measurable in enumerate(measurables): + if sc.isstring(measurable): # Assume that a parameter name was passed in if not a tuple. + measurables[index] = (measurable, None, default_weight, default_metric) + + new_parset = calibrate(project=self, parset=parset, pars_to_adjust=adjustables, output_quantities=measurables, **kwargs) + + if new_name is None: new_name = parset.name + " (auto-calibrated)" - if adjustables is None: - adjustables = list(self.framework.pars.index[~self.framework.pars["calibrate"].isnull()]) - adjustables += list(self.framework.comps.index[~self.framework.comps["calibrate"].isnull()]) - adjustables += list(self.framework.characs.index[~self.framework.characs["calibrate"].isnull()]) - if measurables is None: - measurables = list(self.framework.comps.index) - measurables += list(self.framework.characs.index) - for index, adjustable in enumerate(adjustables): - if sc.isstring(adjustable): # Assume that a parameter name was passed in if not a tuple. - adjustables[index] = (adjustable, None, default_min_scale, default_max_scale) - for index, measurable in enumerate(measurables): - if sc.isstring(measurable): # Assume that a parameter name was passed in if not a tuple. - measurables[index] = (measurable, None, default_weight, default_metric) - new_parset = calibrate(project=self, parset=parset, pars_to_adjust=adjustables, output_quantities=measurables, max_time=max_time, **kwargs) new_parset.name = new_name # The new parset is a calibrated copy of the old, so change id. + if save_to_project: self.parsets.append(new_parset) From d757dbc28d2ba68986bd4867650fdc0038843b63 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Tue, 4 Jun 2024 18:55:21 +0200 Subject: [PATCH 008/161] Minor bug fix, type hints -Change self.name (undefined) to node.name -Update type hints -Remove unused imports --- atomica/yaml_calibration.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 4bb7bb13..5b48d580 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -7,12 +7,16 @@ import sciris as sc from pathlib import Path import atomica as at -from collections import defaultdict, Counter import numpy as np import yaml +import time +from at_tools import get_sigfigs_necessary __all__ = ['build', 'run'] +from atomica import ParameterSet + + def _get_named_nodes(): """ Return dictionary with all named Node subclasses @@ -74,23 +78,24 @@ def run(node, project, parset, savedir=None, save_intermediate=False, log_output if log_output: at.start_logging(savedir/'calibration_log.txt') - at.logger.info(f'Starting calibration ({n_steps} steps)') + at.logger.info(f'\nStarting calibration ({n_steps} steps)') for n_reps, node in nodes: if isinstance(node, Section): at.logger.info(f'\nSection "{node.name}" (repeat {n_reps} of {node.repeats})') else: - at.logger.info(f'\nStep {n} of {n_steps} "{node.name} (repeat {n_reps} of {node.repeats})') + at.logger.info(f'\nStep {n} of {n_steps}: "{node.name}" (repeat {n_reps} of {node.repeats})') parset = node.apply(project, parset, savedir, save_intermediate, *args, **kwargs) n += 1 if save_intermediate and not isinstance(node, SaveCalibrationNode): - output = savedir / f'intermediate_calibration_{n:0{len(str(n_steps))}}_{self.name.replace(" ", "_")}' + output = savedir / f'intermediate_calibration_{n:0{len(str(n_steps))}}_{node.name.replace(" ", "_")}' parset.save_calibration(output) at.logger.info(f'Saved intermediate calibration to {output}') - at.logger.info(f'\nCalibration completed') + t = time.process_time() + at.logger.info(f'\nCalibration completed. Total time elapsed: {round(t, 2)} seconds ({round(t/60, 2)} minutes)') if log_output: at.stop_logging() @@ -181,7 +186,7 @@ def validate(self): """ return - def apply(self, project: at.Project, parset: at.ParameterSet, savedir, *args, **kwargs) -> tuple: + def apply(self, project: at.Project, parset: at.ParameterSet, savedir, *args, **kwargs) -> ParameterSet: """ Perform the action associated with this node """ @@ -314,7 +319,7 @@ def check_optional_number(key, v, defaults): check_optional_number('start_year',v, self.meas_defaults) check_optional_number('end_year',v, self.meas_defaults) - def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, quiet=False, compare_results=False, **kwargs) -> tuple: + def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, quiet=False, compare_results=False, **kwargs) -> ParameterSet: step_name = self.name attributes = self.attributes @@ -446,7 +451,7 @@ def validate(self): assert 'year' in self, f'Initialisation year must be specified' assert sc.isnumber(self['year']), f'Reinitialisation year {self["year"]} must be numeric.' - def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, **kwargs) -> tuple: + def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, **kwargs) -> ParameterSet: new_settings = sc.dcp(project.settings) new_settings.update_time_vector(end=self['year']) res = at.run_model(settings=new_settings, framework=project.framework, parset=parset) @@ -460,7 +465,7 @@ class ClearInitializationNode(BaseNode): def __init__(self, instructions, context, name): super().__init__(instructions=None, context=context, name=name) - def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, **kwargs) -> tuple: + def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, **kwargs) -> ParameterSet: parset.initialization = None return parset @@ -480,6 +485,6 @@ def __init__(self, instructions, context, name): def validate(self): assert self['fname'] is not None, 'A "save calibration" node must have a file name explicitly specified' - def apply(self, project: at.Project, parset: at.ParameterSet, savedir=None, *args, **kwargs) -> tuple: + def apply(self, project: at.Project, parset: at.ParameterSet, savedir=None, *args, **kwargs) -> ParameterSet: parset.save_calibration(savedir / self['fname']) return parset From 367490259882bfa86e1b31139b541596e6731b4f Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Wed, 5 Jun 2024 16:07:56 +0200 Subject: [PATCH 009/161] Implemented make_constant_parset option for reinitialisation node --- atomica/yaml_calibration.py | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 5b48d580..ce7e1e51 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -442,19 +442,34 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui class InitializationNode(BaseNode): _name = 'set_initialization' - def __init__(self, instructions, context, name): - if not isinstance(instructions, dict): - instructions = {'year': instructions} - super().__init__(instructions, context, name) + def __init__(self, instructions, context, name ): + new_instructions = {'constant_parset': False} + + if isinstance(instructions, dict): + new_instructions.update(instructions) + elif type(instructions) is int: + new_instructions.update({'year': instructions}) + elif isinstance(instructions, (tuple, list)): + sc.promotetolist(instructions) + new_instructions.update({'year': instructions[0]}) + if len(instructions) > 1: + new_instructions.update({'constant_parset': instructions[1]}) + + super().__init__(new_instructions, context, name) def validate(self): - assert 'year' in self, f'Initialisation year must be specified' - assert sc.isnumber(self['year']), f'Reinitialisation year {self["year"]} must be numeric.' + assert 'year' in self, f'Initialization year must be specified' + assert sc.isnumber(self['year']), f'Initialization year {self["year"]} must be numeric.' + if 'constant_parset' in self: + assert type(self['constant_parset']) == bool, f'Constant parset (optional) {self["constant_parset"]} must be a boolean.' def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, **kwargs) -> ParameterSet: + p2 = sc.dcp(parset) + if self.instructions['constant_parset']: + p2 = parset.make_constant(year=project.settings.sim_start) new_settings = sc.dcp(project.settings) new_settings.update_time_vector(end=self['year']) - res = at.run_model(settings=new_settings, framework=project.framework, parset=parset) + res = at.run_model(settings=new_settings, framework=project.framework, parset=p2) parset.set_initialization(res, self['year']) return parset From fcae52bcb50af4535a29dbfa04a193091ca9cefc Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:54:46 +0200 Subject: [PATCH 010/161] Bug fix: Let max_time update from yaml Make max_time set in yaml take precedence over max_time in run_calibration argument --- atomica/calibration.py | 2 +- atomica/yaml_calibration.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atomica/calibration.py b/atomica/calibration.py index 4d6b920c..f7858ac3 100644 --- a/atomica/calibration.py +++ b/atomica/calibration.py @@ -260,7 +260,7 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, "abstol": 1e-6, "xmin": xmin, "xmax": xmax, - "maxtime": 60 if max_time is None else max_time, + "maxtime": 60 if max_time is None else max_time } optim_args.update(kwargs) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index ce7e1e51..cb0725b7 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -375,7 +375,7 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui # Calibration if len(adjustables): - kwargs = sc.mergedicts(self.attributes, kwargs) + kwargs = sc.mergedicts(kwargs, self.attributes) del kwargs['adjustables'] # supplied via the adjustables variable del kwargs['measurables'] # supplied via the measurables variable From b58a5d4c7231e5680b77c82830720745ac3ad703 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:46:28 +0200 Subject: [PATCH 011/161] Revert last update Arguments in calibration function will take precedence over parameters in yaml file --- atomica/yaml_calibration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index cb0725b7..ce7e1e51 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -375,7 +375,7 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui # Calibration if len(adjustables): - kwargs = sc.mergedicts(kwargs, self.attributes) + kwargs = sc.mergedicts(self.attributes, kwargs) del kwargs['adjustables'] # supplied via the adjustables variable del kwargs['measurables'] # supplied via the measurables variable From 68553959ec964229c9f857d55d1f5292b2920252 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Mon, 17 Jun 2024 16:29:15 +0200 Subject: [PATCH 012/161] Fixed measurables populations not expanding properly --- atomica/yaml_calibration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index ce7e1e51..7d593f46 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -370,7 +370,7 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui for pop in pops: d = sc.mergedicts(self.meas_defaults, attributes['measurables'].get((par_name, None), None), attributes['measurables'].get((par_name, pop), None)) - measurables.append((par_name, pop_name, d['weight'], d['metric'], d['start_year'], d['end_year'])) + measurables.append((par_name, pop, d['weight'], d['metric'], d['start_year'], d['end_year'])) # Calibration if len(adjustables): From 193418e91d12e7a6aff85234e92c6807f4d62f0d Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Sun, 30 Jun 2024 07:06:12 +1000 Subject: [PATCH 013/161] Add missing dependency for deployment --- azure-pipelines.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 50fc1d9c..5f41210b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -115,6 +115,7 @@ jobs: inputs: versionSpec: '3.12' - script: | + python -m pip install setuptools python -m pip install wheel python -m pip install twine python setup.py build From 44c766fb1980de8c0c731a924e1ea05e5aa0e1c6 Mon Sep 17 00:00:00 2001 From: Phillip Luong Date: Thu, 4 Jul 2024 15:20:52 +1000 Subject: [PATCH 014/161] Implement total population calibration if the population for a measurable is 'total', then we will use the PlotData object to collect the timeseries for the total value of the measurable, which will then be used to calculate the objective function --- atomica/calibration.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/atomica/calibration.py b/atomica/calibration.py index ed827fd6..591d40a3 100644 --- a/atomica/calibration.py +++ b/atomica/calibration.py @@ -12,6 +12,7 @@ from .system import logger from .parameters import ParameterSet import logging +import atomica __all__ = ["calibrate"] @@ -43,7 +44,6 @@ def _update_parset(parset, y_factors, pars_to_adjust): tokens = par_name.split("_from_") par = parset.transfers[tokens[0]][tokens[1]] par.y_factor[pop_name] = y_factors[i] - raise NotImplementedError def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, project): @@ -66,14 +66,21 @@ def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, p continue if not target.has_time_data: # Only use this output quantity if the user entered time-specific data continue - var = result.model.get_pop(pop_name).get_variable(var_label) + if pop_name == 'Total': + var = atomica.PlotData(result, outputs=var_label, pops = 'total', project=project) + else: + var = result.model.get_pop(pop_name).get_variable(var_label) + data_t, data_v = target.get_arrays() # Interpolate the model outputs onto the data times # If there is data outside the range when the model was simulated, don't # extrapolate the model outputs y = data_v - y2 = np.interp(data_t, var[0].t, var[0].vals, left=np.nan, right=np.nan) + if pop_name == 'Total': + y2 = np.interp(data_t, var.tvals()[0], var.series[0].vals, left=np.nan, right=np.nan) + else: + y2 = np.interp(data_t, var[0].t, var[0].vals, left=np.nan, right=np.nan) idx = ~np.isnan(y) & ~np.isnan(y2) objective += weight * sum(_calculate_fitscore(y[idx], y2[idx], metric)) @@ -243,7 +250,6 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, tokens = par_name.split("_from_") par = args["parset"].transfers[tokens[0]][tokens[1]] logger.debug("parset.transfers['{}']['{}'].y_factor['{}']={:.2f}".format(tokens[0], tokens[1], pop_name, par.y_factor[pop_name])) - raise NotImplementedError # Transfers might be handled differently in Atomica args["parset"].name = "calibrated_" + args["parset"].name From 64721797d7dc042d53b42727c0542a504ef364cf Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Thu, 4 Jul 2024 12:52:45 +0200 Subject: [PATCH 015/161] Enable spaces within adjustable/measurable and pop labels Parses '~' in yaml file labels as spaces --- atomica/yaml_calibration.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 7d593f46..865043ab 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -252,9 +252,9 @@ def validate(self): def process_key(s): # Sanitize key name with optional space separating pop name if ' ' in s: - return tuple([x for x in s.split(' ') if x]) + return tuple([x.replace('~', ' ') for x in s.split(' ') if x]) else: - return (s.strip(), None) + return (s.strip().replace('~', ' '), None) def process_inputs(inputs, defaults): # Process adjustables and measurables, which can be specified in a list representation or nested dict representation From 6dc0f8dc8ee7d4aefd5a3a81553a7f4425ce51a6 Mon Sep 17 00:00:00 2001 From: Phillip Luong Date: Fri, 5 Jul 2024 14:25:58 +1000 Subject: [PATCH 016/161] Slight adjustments to tvec --- atomica/calibration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/calibration.py b/atomica/calibration.py index 591d40a3..84f1f86a 100644 --- a/atomica/calibration.py +++ b/atomica/calibration.py @@ -78,7 +78,7 @@ def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, p # extrapolate the model outputs y = data_v if pop_name == 'Total': - y2 = np.interp(data_t, var.tvals()[0], var.series[0].vals, left=np.nan, right=np.nan) + y2 = np.interp(data_t, var.series[0].tvec, var.series[0].vals, left=np.nan, right=np.nan) else: y2 = np.interp(data_t, var[0].t, var[0].vals, left=np.nan, right=np.nan) From 0cd77e105ee9b4965612e33e1a4df1825900004b Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 10 Jul 2024 14:17:36 +1000 Subject: [PATCH 017/161] Reduce case sensitivity --- atomica/calibration.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/atomica/calibration.py b/atomica/calibration.py index 2347221c..7cd6e682 100644 --- a/atomica/calibration.py +++ b/atomica/calibration.py @@ -34,7 +34,7 @@ def _update_parset(parset, y_factors, pars_to_adjust): pop_name = x[1] if par_name in parset.pars: - if pop_name == "all": + if pop_name.lower() == "all": par = parset.pars[par_name] par.meta_y_factor = y_factors[i] else: @@ -66,7 +66,8 @@ def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, p continue if not target.has_time_data: # Only use this output quantity if the user entered time-specific data continue - if pop_name == 'Total': + + if pop_name.lower() == 'total': var = atomica.PlotData(result, outputs=var_label, pops = 'total', project=project) else: var = result.model.get_pop(pop_name).get_variable(var_label) @@ -77,7 +78,7 @@ def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, p # If there is data outside the range when the model was simulated, don't # extrapolate the model outputs y = data_v - if pop_name == 'Total': + if pop_name.lower() == 'total': y2 = np.interp(data_t, var.series[0].tvec, var.series[0].vals, left=np.nan, right=np.nan) else: y2 = np.interp(data_t, var[0].t, var[0].vals, left=np.nan, right=np.nan) @@ -179,7 +180,7 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, par_name, pop_name, scale_min, scale_max = x if par_name in parset.pars: par = parset.pars[par_name] - if pop_name == "all": + if pop_name.lower() == "all": x0.append(par.meta_y_factor) else: x0.append(par.y_factor[pop_name]) @@ -244,7 +245,7 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, if par_name in parset.pars: par = args["parset"].pars[par_name] - if pop_name == "all": + if pop_name.lower() == "all": logger.debug("parset.get_par('{}').meta_y_factor={:.2f}".format(par_name, par.meta_y_factor)) else: logger.debug("parset.get_par('{}').y_factor['{}']={:.2f}".format(par_name, pop_name, par.y_factor[pop_name])) From 773dd787a506e884a6bd4e36dbaa29ec0155d26a Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Fri, 12 Jul 2024 12:57:02 +1000 Subject: [PATCH 018/161] Update docstring, version and changelog --- CHANGELOG.md | 5 +++++ atomica/calibration.py | 7 ++++++- atomica/version.py | 4 ++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53b1bd35..9576263c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ This file records changes to the codebase grouped by version release. Unreleased changes are generally only present during development (relevant parts of the changelog can be written and saved in that section before a version number has been assigned) +## [1.28.6] - 2023-07-12 + +- Support entering `'total'` as the population name in auto-calibration measurables to calibrate aggregated values across populations in the model to aggregate values entered in the databook under a 'Total' population + + ## [1.28.5] - 2023-06-28 - Enable automated calibration of transfers and updated documentation to cover this feature diff --git a/atomica/calibration.py b/atomica/calibration.py index 7cd6e682..a8066683 100644 --- a/atomica/calibration.py +++ b/atomica/calibration.py @@ -136,7 +136,12 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, as the ``pop_name``. For example, to automatically calibrate an aging transfer 'age' from 5-14 to 15-64, the tuple would contain ``pars_to_adjust=[('age_from_5-14','15-64',...)]`` :param output_quantities: list of tuples, (var_label,pop_name,weight,metric), for use in the objective - function. pop_name=None will expand to all pops. pop_name='all' is not supported + function. pop_name=None will expand to all pops. pop_name='all' is not supported. In some cases, + it may be desirable to fit to an aggregated total value across populations. In such cases, the + databook should have an extra row in the TDVE table for a population called "Total". The measurable + can then be given pop_name="Total" which will cause the Atomica model outputs to be aggregated over + all populations, and the aggregate value compared to the "Total" data. The aggregation methods will + be automatically selected depending on units of the quantity (sum for "number" units, average for others). :param max_time: If using ASD, the maximum run time :param method: 'asd' or 'pso'. If using 'pso' all upper and lower limits must be finite :param kwargs: Dictionary of additional arguments to be passed to the optimization function, e.g. stepsize or pinitial diff --git a/atomica/version.py b/atomica/version.py index 235b678a..ffdfcfc0 100644 --- a/atomica/version.py +++ b/atomica/version.py @@ -6,6 +6,6 @@ import sciris as sc -version = "1.28.5" -versiondate = "2024-06-28" +version = "1.28.6" +versiondate = "2024-07-12" gitinfo = sc.gitinfo(__file__) From 75b697a319a22cb0a9c955bbd7049410c8966c02 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Tue, 23 Jul 2024 19:39:51 +0200 Subject: [PATCH 019/161] Prevent doubling up of print statements on save --- atomica/yaml_calibration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 865043ab..0bbe672e 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -91,8 +91,8 @@ def run(node, project, parset, savedir=None, save_intermediate=False, log_output if save_intermediate and not isinstance(node, SaveCalibrationNode): output = savedir / f'intermediate_calibration_{n:0{len(str(n_steps))}}_{node.name.replace(" ", "_")}' + at.logger.info(f'Saving intermediate calibration...') parset.save_calibration(output) - at.logger.info(f'Saved intermediate calibration to {output}') t = time.process_time() at.logger.info(f'\nCalibration completed. Total time elapsed: {round(t, 2)} seconds ({round(t/60, 2)} minutes)') From ea5b2c77389c5777bd55adac7e8dd12745161067 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Tue, 23 Jul 2024 19:40:32 +0200 Subject: [PATCH 020/161] Prevent doubling up of populations in optimisation and print statements --- atomica/yaml_calibration.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 0bbe672e..890b7c3c 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -324,10 +324,10 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui step_name = self.name attributes = self.attributes - at.logger.info(f'Calibrating adjustable(s) {[adj[0] for adj in attributes["adjustables"]]} to match measurable(s) {[mea[0] for mea in attributes["measurables"]]}...') + at.logger.info(f'Calibrating adjustable(s) {set([adj[0] for adj in attributes["adjustables"]])} to match measurable(s) {set([mea[0] for mea in attributes["measurables"]])}...') # Expand adjustables - adjustables = [] + adjustables = {} par_names = {x[0] for x in attributes['adjustables']}.intersection(x.name for x in parset.all_pars()) pop_names = {x[1] for x in attributes['adjustables']}.intersection({*parset.pop_names} | {'all', None}) @@ -346,8 +346,13 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui pops = sc.promotetolist(pop_name) for pop in pops: - d = sc.mergedicts(self.adj_defaults, attributes['adjustables'].get((par_name, None), None), attributes['adjustables'].get((par_name, pop), None)) - adjustables.append((par_name, pop, d['lower_bound'], d['upper_bound'], d['initial_value'])) + d = sc.mergedicts(self.adj_defaults, attributes['adjustables'].get((par_name, None), None), attributes['adjustables'].get((par_name, pop), None)) + adjustables[(par_name, pop)] = (d['lower_bound'], d['upper_bound'], d['initial_value']) + # for par_name in attributes['adjustables'].copy(): + # # if attributes['adjustables'].get((par_name, None)) is not None: + # attributes['adjustables'].pop((par_name, None), None) + adjustables = [(*k, *v) for k,v in adjustables.items()] + # Expand measurables measurables = [] From c7c6a8b2e2deed9955ba303fbc82084d83d1ed2d Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Tue, 23 Jul 2024 19:41:34 +0200 Subject: [PATCH 021/161] Set default value for minval in optim_args --- atomica/calibration.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atomica/calibration.py b/atomica/calibration.py index f7858ac3..53da44f0 100644 --- a/atomica/calibration.py +++ b/atomica/calibration.py @@ -260,7 +260,8 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, "abstol": 1e-6, "xmin": xmin, "xmax": xmax, - "maxtime": 60 if max_time is None else max_time + "maxtime": 60 if max_time is None else max_time, + "minval": 0, } optim_args.update(kwargs) From 453295f4c93c52c5d021bcbb27e7ab4e6630c0d4 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Tue, 23 Jul 2024 19:43:30 +0200 Subject: [PATCH 022/161] Ability to set verbose from kwargs --- atomica/calibration.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/atomica/calibration.py b/atomica/calibration.py index 53da44f0..6ba8f700 100644 --- a/atomica/calibration.py +++ b/atomica/calibration.py @@ -265,11 +265,12 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, } optim_args.update(kwargs) - log_level = logger.getEffectiveLevel() - if log_level < logging.WARNING: - optim_args["verbose"] = 2 - else: - optim_args["verbose"] = 0 + if 'verbose' not in optim_args: + log_level = logger.getEffectiveLevel() + if log_level < logging.WARNING: + optim_args["verbose"] = 2 + else: + optim_args["verbose"] = 0 opt_result = sc.asd(_calculate_objective, x0, args, **optim_args) x1 = opt_result["x"] From 5f0c05dd74c1a13da3490003977deb575939ef58 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Wed, 24 Jul 2024 14:49:56 +0200 Subject: [PATCH 023/161] Prevent doubling up of measurables populations --- atomica/yaml_calibration.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 890b7c3c..bc59e6b9 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -355,7 +355,7 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui # Expand measurables - measurables = [] + measurables = {} par_names = {x[0] for x in attributes['measurables']}.intersection(x.name for x in parset.all_pars()) # TODO: This is probably OK for now but will need to support transfer parameters and validate that pars have databook entries in the future pop_names = {x[1] for x in attributes['measurables']}.intersection({*parset.pop_names} | {None}) @@ -374,8 +374,12 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui pops = sc.promotetolist(pop_name) for pop in pops: - d = sc.mergedicts(self.meas_defaults, attributes['measurables'].get((par_name, None), None), attributes['measurables'].get((par_name, pop), None)) - measurables.append((par_name, pop, d['weight'], d['metric'], d['start_year'], d['end_year'])) + d = sc.mergedicts(self.meas_defaults, attributes['measurables'].get((par_name, None), None), attributes['measurables'].get((par_name, pop), None)) + measurables[(par_name, pop)] = (d['weight'], d['metric'], d['start_year'], d['end_year']) + # for par_name in attributes['adjustables'].copy(): + # # if attributes['adjustables'].get((par_name, None)) is not None: + # attributes['adjustables'].pop((par_name, None), None) + measurables = [(*k, *v) for k,v in measurables.items()] # Calibration if len(adjustables): From 4779a1ccdff5a7ee9d125c5e3e7c0bd0fcb83484 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:53:13 +0200 Subject: [PATCH 024/161] Refactoring for consistency -Rename Section to SectionNode -Consistency in the quotes inside variables (for searchability) -Docstring formatting -Delete unused code comments --- atomica/yaml_calibration.py | 40 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index bc59e6b9..c5e9f0c6 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -45,7 +45,7 @@ def build(instructions=None, context=None, name='calibration'): elif name in named_nodes: return named_nodes[name](instructions, context, name) else: - return Section(instructions, context, name) + return SectionNode(instructions, context, name) def run(node, project, parset, savedir=None, save_intermediate=False, log_output:bool=False,*args, **kwargs): """ @@ -72,7 +72,7 @@ def run(node, project, parset, savedir=None, save_intermediate=False, log_output savedir = Path(savedir) nodes = list(node.walk()) # Make a flat list of all nodes to execute in order - n_steps = len([x for x in nodes if not isinstance(x[1], Section)]) + n_steps = len([x for x in nodes if not isinstance(x[1], SectionNode)]) n = 1 if log_output: @@ -82,7 +82,7 @@ def run(node, project, parset, savedir=None, save_intermediate=False, log_output for n_reps, node in nodes: - if isinstance(node, Section): + if isinstance(node, SectionNode): at.logger.info(f'\nSection "{node.name}" (repeat {n_reps} of {node.repeats})') else: at.logger.info(f'\nStep {n} of {n_steps}: "{node.name}" (repeat {n_reps} of {node.repeats})') @@ -192,7 +192,7 @@ def apply(self, project: at.Project, parset: at.ParameterSet, savedir, *args, ** """ return parset -class Section(BaseNode): +class SectionNode(BaseNode): """ A section node is a special kind of node, that contains other nodes """ @@ -250,21 +250,25 @@ def validate(self): """ def process_key(s): - # Sanitize key name with optional space separating pop name + """ + Sanitize key name with optional space separating pop name + """ if ' ' in s: return tuple([x.replace('~', ' ') for x in s.split(' ') if x]) else: return (s.strip().replace('~', ' '), None) def process_inputs(inputs, defaults): - # Process adjustables and measurables, which can be specified in a list representation or nested dict representation - # In list representation, the input is a list of lists, where the first item in each list is the quantity (with optional population) and - # the remaining items are the supported arguments for the input type, in the order defined by the defaults dictionary. - # In a dict representation, the key is the quantity with optional population, and then the value can either be a list (in the order defined by the dictionary) - # or a dictionary explicitly naming the inputs. - # This function returns a flat dictionary with {(quantity, pop_name):{argument:value}} e.g., {('b_rate','0-5'):{'lower_bound':0.5}}. - # In the dict representation, the key can be a comma separated list of quantities with optional values e.g., 'b_rate 0-5, d_rate'. In the list representation, - # multiple quantities are not supported (as a comma is already used to separate the arguments) + """ + Process adjustables and measurables, which can be specified in a list representation or nested dict representation + In list representation, the input is a list of lists, where the first item in each list is the quantity (with optional population) and + the remaining items are the supported arguments for the input type, in the order defined by the defaults dictionary. + In a dict representation, the key is the quantity with optional population, and then the value can either be a list (in the order defined by the dictionary) + or a dictionary explicitly naming the inputs. + This function returns a flat dictionary with {(quantity, pop_name):{argument:value}} e.g., {('b_rate','0-5'):{'lower_bound':0.5}}. + In the dict representation, the key can be a comma separated list of quantities with optional values e.g., 'b_rate 0-5, d_rate'. In the list representation, + multiple quantities are not supported (as a comma is already used to separate the arguments), but multiple lists (one for each quantity) can be provided. + """ out = {} if sc.isstring(inputs): @@ -293,12 +297,12 @@ def process_inputs(inputs, defaults): self['adjustables'] = process_inputs(self['adjustables'], self.adj_defaults) self['measurables'] = process_inputs(self['measurables'], self.meas_defaults) - # Validate adjustables def check_optional_number(key, v, defaults): if key in v and v[key] is not None: if not sc.isnumber(v[key], isnan=False): raise TypeError(f"Adjustable argument '{key}' needs to be a number or None (defaults to {defaults[key]}). Provided value: {v[key]} ") + # Validate adjustables assert len(self['adjustables']) > 0, f'Cannot calibrate with no adjustables for calibration section {self.name}' for (quantity, pop_name), v in self['adjustables'].items(): assert 'pop_name' not in v, f'Setting the population name through "pop_name: {v["pop_name"]}" is not supported. Instead, the name of the adjustable quantity should include the population name ("{quantity} {v["pop_name"]}")' @@ -324,7 +328,7 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui step_name = self.name attributes = self.attributes - at.logger.info(f'Calibrating adjustable(s) {set([adj[0] for adj in attributes["adjustables"]])} to match measurable(s) {set([mea[0] for mea in attributes["measurables"]])}...') + at.logger.info(f"Calibrating adjustable(s) {set([adj[0] for adj in attributes['adjustables']])} to match measurable(s) {set([mea[0] for mea in attributes['measurables']])}...") # Expand adjustables adjustables = {} @@ -348,9 +352,6 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui for pop in pops: d = sc.mergedicts(self.adj_defaults, attributes['adjustables'].get((par_name, None), None), attributes['adjustables'].get((par_name, pop), None)) adjustables[(par_name, pop)] = (d['lower_bound'], d['upper_bound'], d['initial_value']) - # for par_name in attributes['adjustables'].copy(): - # # if attributes['adjustables'].get((par_name, None)) is not None: - # attributes['adjustables'].pop((par_name, None), None) adjustables = [(*k, *v) for k,v in adjustables.items()] @@ -376,9 +377,6 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui for pop in pops: d = sc.mergedicts(self.meas_defaults, attributes['measurables'].get((par_name, None), None), attributes['measurables'].get((par_name, pop), None)) measurables[(par_name, pop)] = (d['weight'], d['metric'], d['start_year'], d['end_year']) - # for par_name in attributes['adjustables'].copy(): - # # if attributes['adjustables'].get((par_name, None)) is not None: - # attributes['adjustables'].pop((par_name, None), None) measurables = [(*k, *v) for k,v in measurables.items()] # Calibration From 839981ec9bd637b1ccd07befbeca5e4da0c30e75 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Fri, 26 Jul 2024 14:43:30 +1000 Subject: [PATCH 025/161] Enable transfer calibration --- atomica/calibration.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/atomica/calibration.py b/atomica/calibration.py index 6ba8f700..a17c4565 100644 --- a/atomica/calibration.py +++ b/atomica/calibration.py @@ -43,7 +43,6 @@ def _update_parset(parset, y_factors, pars_to_adjust): tokens = par_name.split("_from_") par = parset.transfers[tokens[0]][tokens[1]] par.y_factor[pop_name] = y_factors[i] - raise NotImplementedError def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, project, *args, **kwargs) -> float: @@ -311,7 +310,6 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, tokens = par_name.split("_from_") par = args["parset"].transfers[tokens[0]][tokens[1]] logger.debug("parset.transfers['{}']['{}'].y_factor['{}']={:.2f}".format(tokens[0], tokens[1], pop_name, par.y_factor[pop_name])) - raise NotImplementedError # Transfers might be handled differently in Atomica args["parset"].name = "calibrated_" + args["parset"].name From 08617f7b5e65c6a969d930389668cc0e2d3cf7c8 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Fri, 26 Jul 2024 14:43:57 +1000 Subject: [PATCH 026/161] Support '_from_' transfer naming in `ParameterSet.get_par()` --- atomica/calibration.py | 33 +++++++++++++-------------------- atomica/parameters.py | 12 ++++++++++-- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/atomica/calibration.py b/atomica/calibration.py index a17c4565..19ae89b6 100644 --- a/atomica/calibration.py +++ b/atomica/calibration.py @@ -20,31 +20,24 @@ calibration_settings["tolerance"] = 1e-6 -def _update_parset(parset, y_factors, pars_to_adjust): - # Insert updated y-values into the parset - # - parset : a ParameterSet object - # - y_factors : Array with as many elements as pars_to_adjust - # - pars_to_adjust : Array of tuples (par_name,pop_name,...) with special value pop='all' supported to set meta factor - # Must have as many elements as y_factors. pop=None is not allowed - it must be converted - # to a full list of pops previously (in perform_autofit) +def _update_parset(parset, y_factors, pars_to_adjust) -> None: + """ - for i, x in enumerate(pars_to_adjust): - par_name = x[0] - pop_name = x[1] + :param parset: a ParameterSet object + :param y_factors: Array with as many elements as pars_to_adjust + :param pars_to_adjust: Array of tuples (par_name,pop_name,...) with special value pop='all' supported to set meta factor + Must have as many elements as y_factors. pop=None is not allowed - it must be converted + to a full list of pops previously (in perform_autofit) + :return: None (parset is modified in-place) + """ - if par_name in parset.pars: - if pop_name == "all": - par = parset.pars[par_name] - par.meta_y_factor = y_factors[i] - else: - parset.pars[par_name].y_factor[pop_name] = y_factors[i] + for i, (par_name, pop_name, *_) in enumerate(pars_to_adjust): + par = parset.get_par(par_name) + if pop_name == "all": + par.meta_y_factor = y_factors[i] else: - # Handle transfers here - tokens = par_name.split("_from_") - par = parset.transfers[tokens[0]][tokens[1]] par.y_factor[pop_name] = y_factors[i] - def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, project, *args, **kwargs) -> float: """ Run the model for a given set of y-factors and return the objective/goodness-of-fit diff --git a/atomica/parameters.py b/atomica/parameters.py index 5f668300..49b177db 100644 --- a/atomica/parameters.py +++ b/atomica/parameters.py @@ -490,7 +490,10 @@ def get_par(self, name: str, pop: str = None) -> Parameter: The parameter values for interactions and transfers are stored keyed by the source/from population. Thus, if the quantity name is an interaction or transfer, it is also necessary to specify the source population in order - to return a :class:`Parameter` instance. + to return a :class:`Parameter` instance. However, transfer parameters can + also be identified by a parameter name "_from_" such + that ``ParameterSet.get_par('age','5-14')`` is equivalent to + ``ParameterSet.get_par('age_from_5-14')``. :param name: The code name of a parameter, interaction, or transfer :param pop: @@ -507,7 +510,12 @@ def get_par(self, name: str, pop: str = None) -> Parameter: assert not pd.isna(pop), f'"{name}" is an interaction, so the ``pop`` must be specified' return self.interactions[name][pop] else: - raise KeyError(f'Parameter "{name}" not found') + for transfer in self.transfers.values(): + for par in transfer.values(): + if par.name == name: + return par + + raise KeyError(f'Parameter "{name}" not found') def sample(self, constant=True): """ From 7dfbecca7e1f309a439d4a442c2ca82cfb9d632f Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Fri, 26 Jul 2024 14:44:15 +1000 Subject: [PATCH 027/161] Clarify warning --- atomica/yaml_calibration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index bc59e6b9..c8775cc4 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -334,7 +334,7 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui for par_name, pop_name in attributes['adjustables']: if par_name not in par_names: - at.logger.warning(f"Extra YAML adjustable parameter '{par_name}' does not exist in this project's framework and will be ignored") + at.logger.warning(f"Extra YAML adjustable parameter '{par_name}' does not exist in this project's framework/parset and will be ignored") continue elif pop_name not in pop_names: at.logger.warning(f"Extra YAML adjustable population '{pop_name}' does not exist in this project's databook and will be ignored") From 9c206786ddb8eae6fc59726a543a20ad38b8473b Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Fri, 26 Jul 2024 14:44:50 +1000 Subject: [PATCH 028/161] Check for extra 'population' rows (this is specifically used for 'total') --- atomica/yaml_calibration.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index c8775cc4..ddbce1a4 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -365,8 +365,9 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui at.logger.warning(f"Extra YAML measurable variable '{par_name}' does not exist in this project's framework and will be ignored") continue elif pop_name not in pop_names: - at.logger.warning(f"Extra YAML measurable population '{pop_name}' does not exist in this project's databook and will be ignored") - continue + if pop_name not in project.data.tdve[par_name].ts.keys(): + at.logger.warning(f"Extra YAML measurable population '{pop_name}' does not exist in this project's databook and will be ignored") + continue if pop_name is None: pops = parset.pop_names From d7e05631917a70bdfcd2816366aaa1e11c8b25b1 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Fri, 26 Jul 2024 14:45:29 +1000 Subject: [PATCH 029/161] Support _from_ syntax in yaml calibration --- atomica/yaml_calibration.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index ddbce1a4..eb077394 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -405,12 +405,13 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui made_changes = False for par, pop, *_ in adjustables: - if pop == 'all': - old = parset.pars[par].meta_y_factor - new = new_cal_parset.pars[par].meta_y_factor + + if pop == "all": + old = parset.get_par(par).meta_y_factor + new = new_cal_parset.get_par(par).meta_y_factor else: - old = parset.pars[par].y_factor[pop] - new = new_cal_parset.pars[par].y_factor[pop] + old = parset.get_par(par).y_factor[pop] + new = new_cal_parset.get_par(par).y_factor[pop] if new != old: at.logger.info(f'...adjusted the y-factor for {par} in {pop} from {old} to {new}') From 4c90bc493e04768d4cc28cb4d5ab8939776fc21c Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Fri, 26 Jul 2024 14:45:36 +1000 Subject: [PATCH 030/161] Remove unused code --- atomica/yaml_calibration.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index eb077394..f4e21d42 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -348,9 +348,7 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui for pop in pops: d = sc.mergedicts(self.adj_defaults, attributes['adjustables'].get((par_name, None), None), attributes['adjustables'].get((par_name, pop), None)) adjustables[(par_name, pop)] = (d['lower_bound'], d['upper_bound'], d['initial_value']) - # for par_name in attributes['adjustables'].copy(): - # # if attributes['adjustables'].get((par_name, None)) is not None: - # attributes['adjustables'].pop((par_name, None), None) + adjustables = [(*k, *v) for k,v in adjustables.items()] @@ -377,9 +375,7 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui for pop in pops: d = sc.mergedicts(self.meas_defaults, attributes['measurables'].get((par_name, None), None), attributes['measurables'].get((par_name, pop), None)) measurables[(par_name, pop)] = (d['weight'], d['metric'], d['start_year'], d['end_year']) - # for par_name in attributes['adjustables'].copy(): - # # if attributes['adjustables'].get((par_name, None)) is not None: - # attributes['adjustables'].pop((par_name, None), None) + measurables = [(*k, *v) for k,v in measurables.items()] # Calibration From 4d3e6f3be06f1031c953951a9b5e201dab7adad1 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Fri, 26 Jul 2024 14:52:05 +1000 Subject: [PATCH 031/161] Update to limit support to 'total' and make it case insensitive --- atomica/yaml_calibration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index f4e21d42..bfa69faa 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -363,7 +363,7 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui at.logger.warning(f"Extra YAML measurable variable '{par_name}' does not exist in this project's framework and will be ignored") continue elif pop_name not in pop_names: - if pop_name not in project.data.tdve[par_name].ts.keys(): + if not (pop_name.lower() == 'total' and pop_name.lower() in {x.lower() for x in project.data.tdve[par_name].ts.keys()}): at.logger.warning(f"Extra YAML measurable population '{pop_name}' does not exist in this project's databook and will be ignored") continue From a5e12e4196469968fd68a50d660b1eb1b80745fe Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Fri, 26 Jul 2024 15:09:55 +1000 Subject: [PATCH 032/161] Make warning clearer --- atomica/data.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/atomica/data.py b/atomica/data.py index 4422e715..1087055c 100644 --- a/atomica/data.py +++ b/atomica/data.py @@ -413,7 +413,9 @@ def from_spreadsheet(spreadsheet, framework): ts.units = tdve.allowed_units[0] if not spec["databook page"]: - logger.warning('A TDVE table for "%s" (%s) was read in and will be used, but the Framework did not mark this quantity as appearing in the databook', tdve.name, code_name) + # Note that if the parameter doesn't have a databook page and the framework is valid, then the parameter must have a function. Therefore, + # if data is also read in, it will not change the simulation outputs and would only be used for calibration/validation + logger.warning('A TDVE table for "%s" (%s) was read in and data will be available for calibration, but the Framework did not mark this quantity as appearing in the databook', tdve.name, code_name) tdve.comment = spec["guidance"] if code_name in self.tdve: From be8a3e146ee7039276aadaab5b85a658191b08a5 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Fri, 26 Jul 2024 16:19:34 +1000 Subject: [PATCH 033/161] Possible fix for duplicated initial values --- atomica/calibration.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/atomica/calibration.py b/atomica/calibration.py index 638b8bb6..8c1e5d97 100644 --- a/atomica/calibration.py +++ b/atomica/calibration.py @@ -213,15 +213,7 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, for i, x in enumerate(pars_to_adjust): par_name, pop_name, scale_min, scale_max, initial_value = x - if par_name in parset.pars: - par = parset.pars[par_name] - if pop_name.lower() == "all": - x0.append(par.meta_y_factor) - else: - x0.append(par.y_factor[pop_name]) - else: - tokens = par_name.split("_from_") - par = parset.transfers[tokens[0]][tokens[1]] + par = parset.get_par(par_name) #if initial_value has not been explicitly set in the tuple: use y_factor in parset if initial_value is None: From 493972f652dd2683494fa7a443a91aa4ce244287 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 19 Aug 2024 22:06:52 +1000 Subject: [PATCH 034/161] Use Atomica's copy of get_sigfigs_necessary() --- atomica/yaml_calibration.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index bfa69faa..2929a1c3 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -10,7 +10,6 @@ import numpy as np import yaml import time -from at_tools import get_sigfigs_necessary __all__ = ['build', 'run'] @@ -440,7 +439,7 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui base_rms_error = base_rms_error ** 0.5 cal_rms_error = cal_rms_error ** 0.5 - sf = get_sigfigs_necessary(base_rms_error, cal_rms_error) + sf = at.get_sigfigs_necessary(base_rms_error, cal_rms_error) at.logger.info(f'...RMS error for parameter {par_name} has changed from baseline {sc.sigfig(base_rms_error, sf)} to calibrated {sc.sigfig(cal_rms_error, sf)}') return new_cal_parset From 07999d000e1e25102d6890534e438755e69c6593 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 19 Aug 2024 22:07:01 +1000 Subject: [PATCH 035/161] Ensure output directory exists --- atomica/yaml_calibration.py | 1 + 1 file changed, 1 insertion(+) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 2929a1c3..4636dbb7 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -69,6 +69,7 @@ def run(node, project, parset, savedir=None, save_intermediate=False, log_output savedir = Path('.') else: savedir = Path(savedir) + savedir.mkdir(exist_ok=True, parents=True) nodes = list(node.walk()) # Make a flat list of all nodes to execute in order n_steps = len([x for x in nodes if not isinstance(x[1], Section)]) From ded6fed1737fcf3f53911f85ab5b678999a9db99 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:38:07 +0200 Subject: [PATCH 036/161] Rename start_year, end_year to cal_start, cal_end --- atomica/yaml_calibration.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 4c4c4e99..3baeda5f 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -232,8 +232,8 @@ class CalibrationNode(BaseNode): meas_defaults = { 'weight': 1.0, 'metric': 'fractional', - 'start_year': -np.inf, - 'end_year': np.inf, + 'cal_start': -np.inf, + 'cal_end': np.inf, } @staticmethod @@ -320,8 +320,8 @@ def check_optional_number(key, v, defaults): assert 'metric' not in v or v['metric'] is None or isinstance(v["metric"], str), f"Measurable metric {v['metric']} needs to be a number or None (defaults to 'fractional')" check_optional_number('weight',v, self.meas_defaults) - check_optional_number('start_year',v, self.meas_defaults) - check_optional_number('end_year',v, self.meas_defaults) + check_optional_number('cal_start',v, self.meas_defaults) + check_optional_number('cal_end',v, self.meas_defaults) def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, quiet=False, compare_results=False, **kwargs) -> ParameterSet: @@ -377,7 +377,7 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui for pop in pops: d = sc.mergedicts(self.meas_defaults, attributes['measurables'].get((par_name, None), None), attributes['measurables'].get((par_name, pop), None)) - measurables[(par_name, pop)] = (d['weight'], d['metric'], d['start_year'], d['end_year']) + measurables[(par_name, pop)] = (d['weight'], d['metric'], d['cal_start'], d['cal_end']) measurables = [(*k, *v) for k,v in measurables.items()] # Calibration From 4fa576552135dae2647158ec3dbdb491df1507a6 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:39:05 +0200 Subject: [PATCH 037/161] Rename year to init_year --- atomica/yaml_calibration.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 3baeda5f..a9402559 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -457,18 +457,18 @@ def __init__(self, instructions, context, name ): if isinstance(instructions, dict): new_instructions.update(instructions) elif type(instructions) is int: - new_instructions.update({'year': instructions}) + new_instructions.update({'init_year': instructions}) elif isinstance(instructions, (tuple, list)): sc.promotetolist(instructions) - new_instructions.update({'year': instructions[0]}) + new_instructions.update({'init_year': instructions[0]}) if len(instructions) > 1: new_instructions.update({'constant_parset': instructions[1]}) super().__init__(new_instructions, context, name) def validate(self): - assert 'year' in self, f'Initialization year must be specified' - assert sc.isnumber(self['year']), f'Initialization year {self["year"]} must be numeric.' + assert 'init_year' in self, f'Initialization year must be specified' + assert sc.isnumber(self['init_year']), f'Initialization year {self["init_year"]} must be numeric.' if 'constant_parset' in self: assert type(self['constant_parset']) == bool, f'Constant parset (optional) {self["constant_parset"]} must be a boolean.' @@ -477,9 +477,9 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, **k if self.instructions['constant_parset']: p2 = parset.make_constant(year=project.settings.sim_start) new_settings = sc.dcp(project.settings) - new_settings.update_time_vector(end=self['year']) + new_settings.update_time_vector(end=self['init_year']) res = at.run_model(settings=new_settings, framework=project.framework, parset=p2) - parset.set_initialization(res, self['year']) + parset.set_initialization(res, self['init_year']) return parset From b3649b7c94672f4e5ada3e5ba3c937303900e9ad Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:45:34 +0200 Subject: [PATCH 038/161] Enable user to set the constant parset year Enable constant parset year setting from inside initialization node, and also from inherited context --- atomica/yaml_calibration.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index a9402559..213cf9e6 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -382,7 +382,7 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui # Calibration if len(adjustables): - + # note: attributes = instructions + context kwargs = sc.mergedicts(self.attributes, kwargs) del kwargs['adjustables'] # supplied via the adjustables variable @@ -452,7 +452,7 @@ class InitializationNode(BaseNode): _name = 'set_initialization' def __init__(self, instructions, context, name ): - new_instructions = {'constant_parset': False} + new_instructions = {} if isinstance(instructions, dict): new_instructions.update(instructions) @@ -470,12 +470,15 @@ def validate(self): assert 'init_year' in self, f'Initialization year must be specified' assert sc.isnumber(self['init_year']), f'Initialization year {self["init_year"]} must be numeric.' if 'constant_parset' in self: - assert type(self['constant_parset']) == bool, f'Constant parset (optional) {self["constant_parset"]} must be a boolean.' + assert isinstance(self['constant_parset'], int), f'Constant parset (optional) {self["constant_parset"]} must be numeric (boolean, or int to specify constant parset year).' def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, **kwargs) -> ParameterSet: p2 = sc.dcp(parset) - if self.instructions['constant_parset']: - p2 = parset.make_constant(year=project.settings.sim_start) + if 'constant_parset' in self: + if self['constant_parset'] == True: + p2 = parset.make_constant(year=project.settings.sim_start) + elif type(self['constant_parset']) == int: #constant parset year was provided + p2 = parset.make_constant(year=self['constant_parset']) new_settings = sc.dcp(project.settings) new_settings.update_time_vector(end=self['init_year']) res = at.run_model(settings=new_settings, framework=project.framework, parset=p2) From 0b96e1461a4c7931b3123f0773554264e6d30777 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:48:04 +0200 Subject: [PATCH 039/161] Yaml calibration testing Initial testing step --- tests/test_yaml.py | 83 ++++++++++++++++++++++ tests/yaml_tests/config_stepsize_test.yaml | 34 +++++++++ 2 files changed, 117 insertions(+) create mode 100644 tests/test_yaml.py create mode 100644 tests/yaml_tests/config_stepsize_test.yaml diff --git a/tests/test_yaml.py b/tests/test_yaml.py new file mode 100644 index 00000000..b3346ca2 --- /dev/null +++ b/tests/test_yaml.py @@ -0,0 +1,83 @@ +# import unittest +import atomica as at +import os +import pytest +import numpy as np +import sciris as sc +import at_tools as att + +# class MyTestCase(unittest.TestCase): +# def test_something(self): +# self.assertEqual(True, False) # add assertion here +# +# +# if __name__ == '__main__': +# unittest.main() + + +# Basic minimum working product test to verify all yaml features run + +testdir = at.parent_dir() +tmpdir = testdir / 'temp' +yaml_dir = 'yaml_tests' + +# List yaml files in directory +yaml_files = list() +for f in os.listdir(testdir/yaml_dir): + yaml_files.append(f) + + +def run_auto_calibration(proj): + """Run an automatic calibration + + :param proj: A Project object + :return: + """ + + proj.calibrate(max_time=10, new_name="auto") + + return + + +# Testing optimizations and calibrations could be expensive +# Using the parametrize decorator means Pytest will treat +# each function call as a separate test, which can be run in parallel +# simply by adding `pytest -n 4` for instance. Or via tox +# `tox -- -o -n 4` (because the default config is to use n=2 for TravisCI) +@pytest.mark.parametrize("yaml_fname", yaml_files) +def test_yaml_calibration(yaml_fname): + + #set these once outside test itself? + fw_ver = '2_8_1' + db_ver = '2_8' + country = 'PAK' + dis = 'typh' + + F = at.ProjectFramework(f"framework_bivalent_combined_v{fw_ver}.xlsx") + D = at.ProjectData.from_spreadsheet(f"databook_bivalent_{country}_v{db_ver}.xlsx", framework=F) + P = at.Project(framework=F, databook=D, do_run=False) + P.settings.update_time_vector(start=2000, end=2050, dt=1/52) + cal = P.make_parset() + + print(f"\n\nTESTING yaml config {yaml_fname}") + + #import yaml config + config_file_path = f'{yaml_dir}/{yaml_fname}' + config = att.ProjectConfig.from_yaml(config_file_path) #TODO change this to not rely on atomica tools? + #or can import in all the diff ways - make function + + #run calibration with yaml instructions + newcal = config.run_calibration(P, parset=cal, quiet=False, savedir=tmpdir, save_intermediate=False, verbose=0, max_time=1) + #also run in several diff ways? Or have a separate test for that? + + # Test saving the calibration + # save() + + print("Test complete") + + +if __name__ == "__main__": + + np.seterr(all="raise") + for f in yaml_files: + test_yaml_calibration(f) diff --git a/tests/yaml_tests/config_stepsize_test.yaml b/tests/yaml_tests/config_stepsize_test.yaml new file mode 100644 index 00000000..84dc1a56 --- /dev/null +++ b/tests/yaml_tests/config_stepsize_test.yaml @@ -0,0 +1,34 @@ +--- +#Timestep for the model +sim_dt: 0.019 + +#Ordered instructions for how to calibrate the model + #adj order: (adjustable var_label, populations to adjust for (default all), minimum value (default 0.1), maximum value (default 10), initial y_factor value (optional, default is parset value)) + #meas order: #(measurable var_label, populations to measure for (default all), weight (default 1.0), metric (default "fractional"), start_year (optional), end_year (optional)) +calibration: + time_period : [2019,2040] + max_time: 1 + + Population calibration: + max_time: 1 + + round 1: + stepsize: 0.5 + match population sizes 1: + adjustables: + b_rate,mig_rate: [ 0.1,10 ] + measurables: [alive] + + round 2: + match population sizes 2: + stepsize: 0.5 + adjustables: + b_rate,mig_rate: [ 0.1,10 ] + measurables: [alive] + +# round 3: +# match population sizes 3: +# adjustables: +# stepsize: 0.5 +# b_rate,mig_rate: [ 0.1,10 ] +# measurables: [ alive ] From edebd861826b038865bfe36466bad0fb24a34a96 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 21 Aug 2024 16:09:42 +1000 Subject: [PATCH 040/161] Enable adding a custom provenance to default values that will populate new databooks --- atomica/data.py | 12 +++---- atomica/framework.py | 31 ++++++++++++++++-- .../library/framework_template_advanced.xlsx | Bin 59446 -> 60662 bytes atomica/system.py | 2 ++ 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/atomica/data.py b/atomica/data.py index 1087055c..18535a8e 100644 --- a/atomica/data.py +++ b/atomica/data.py @@ -22,8 +22,6 @@ import pandas as pd import itertools -_DEFAULT_PROVENANCE = "Framework-supplied default" - __all__ = ["InvalidDatabook", "ProjectData"] @@ -303,7 +301,7 @@ class instance (e.g. if creating a new databook). ts = TimeSeries(units=interpop.allowed_units[0]) ts.insert(None, spec["default value"]) interpop.ts[(from_pop, to_pop)] = ts - interpop.ts_attributes["Provenance"][(from_pop, to_pop)] = _DEFAULT_PROVENANCE + interpop.ts_attributes["Provenance"][(from_pop, to_pop)] = spec["provenance"] if "provenance" in spec else FS.DEFAULT_PROVENANCE # Finally, insert parameter and characteristic default values for df in [framework.comps, framework.characs, framework.pars]: @@ -315,7 +313,7 @@ class instance (e.g. if creating a new databook). tdve = data.tdve[spec.name] for key, ts in tdve.ts.items(): ts.insert(None, spec["default value"]) - tdve.ts_attributes["Provenance"][key] = _DEFAULT_PROVENANCE + tdve.ts_attributes["Provenance"][key] = spec["provenance"] if "provenance" in spec else FS.DEFAULT_PROVENANCE return data @@ -491,8 +489,10 @@ def validate(self, framework) -> bool: for pop in self.pops.keys(): self.tdve[spec_name].ts[pop] = TimeSeries(assumption=spec["default value"], units=units) tdve_page = framework.sheets["databook pages"][0][framework.sheets["databook pages"][0]["datasheet code name"] == spec["databook page"]]["datasheet title"].values[0] - if tdve_page in self.tdve_pages: - self.tdve_pages[tdve_page].append(spec_name) + for existing in self.tdve_pages.keys(): + if existing.lower() == tdve_page.lower(): + self.tdve_pages[existing].append(spec_name) + break else: self.tdve_pages[tdve_page] = [spec_name] else: diff --git a/atomica/framework.py b/atomica/framework.py index 7e686f49..7028bcd0 100644 --- a/atomica/framework.py +++ b/atomica/framework.py @@ -627,7 +627,17 @@ def _sanitize_compartments(self) -> None: self.sheets["compartments"] = [pd.DataFrame(columns=["code name", "display name"])] required_columns = ["display name"] - defaults = {"is sink": "n", "is source": "n", "is junction": "n", "databook page": None, "default value": None, "databook order": None, "guidance": None, "population type": None} # Default is for it to be randomly ordered if the databook page is not None + defaults = { + "is sink": "n", + "is source": "n", + "is junction": "n", + "databook page": None, + "default value": None, + "population type": None, + "databook order": None, # Default is for it to be randomly ordered if the databook page is not None + "guidance": None, + "provenance": FS.DEFAULT_PROVENANCE, + } valid_content = { "display name": None, # Valid content being `None` means that it just cannot be empty "is sink": {"y", "n"}, @@ -707,7 +717,16 @@ def _sanitize_characteristics(self) -> None: self.sheets["characteristics"] = [pd.DataFrame(columns=["code name", "display name"])] required_columns = ["display name"] - defaults = {"components": None, "denominator": None, "default value": None, "databook page": None, "databook order": None, "guidance": None, "population type": None} + defaults = { + "components": None, + "denominator": None, + "default value": None, + "databook page": None, + "databook order": None, + "guidance": None, + "population type": None, + "provenance": FS.DEFAULT_PROVENANCE, + } valid_content = { "display name": None, "components": None, @@ -801,7 +820,12 @@ def _sanitize_interactions(self) -> None: self.sheets["interactions"] = [pd.DataFrame(columns=["code name", "display name", "to population type", "from population type"])] required_columns = ["display name"] - defaults = {"default value": None, "from population type": None, "to population type": None} + defaults = { + "default value": None, + "from population type": None, + "to population type": None, + "provenance": FS.DEFAULT_PROVENANCE, + } valid_content = { "display name": None, } @@ -843,6 +867,7 @@ def _sanitize_parameters(self) -> None: "population type": None, "is derivative": "n", "timed": "n", + "provenance": FS.DEFAULT_PROVENANCE, } valid_content = { "display name": None, diff --git a/atomica/library/framework_template_advanced.xlsx b/atomica/library/framework_template_advanced.xlsx index 639bfb54bddd519144064c58098eac526d575247..73cc42986d11480ba79cc3ed11291d9a82790ed6 100644 GIT binary patch delta 45843 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 YG|F!fV8aCffMG8~Sg0*z<)5|x2ctp1u>b%7 delta 44592 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 Date: Mon, 26 Aug 2024 12:27:52 +0200 Subject: [PATCH 041/161] Add yaml tests --- tests/yaml_tests/config_caltime_test.yaml | 39 ++++++++++++++++++++++ tests/yaml_tests/config_maxtime_test.yaml | 36 ++++++++++++++++++++ tests/yaml_tests/config_simtime_test.yaml | 37 ++++++++++++++++++++ tests/yaml_tests/config_stepsize_test.yaml | 4 +-- 4 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 tests/yaml_tests/config_caltime_test.yaml create mode 100644 tests/yaml_tests/config_maxtime_test.yaml create mode 100644 tests/yaml_tests/config_simtime_test.yaml diff --git a/tests/yaml_tests/config_caltime_test.yaml b/tests/yaml_tests/config_caltime_test.yaml new file mode 100644 index 00000000..ea61d264 --- /dev/null +++ b/tests/yaml_tests/config_caltime_test.yaml @@ -0,0 +1,39 @@ +--- +#Timestep for the model +sim_dt: 0.019 +cal_start: 2000 +cal_end: 2040 + +#Ordered instructions for how to calibrate the model + #adj order: (adjustable var_label, populations to adjust for (default all), minimum value (default 0.1), maximum value (default 10), initial y_factor value (optional, default is parset value)) + #meas order: #(measurable var_label, populations to measure for (default all), weight (default 1.0), metric (default "fractional"), start_year (optional), end_year (optional)) +calibration: + cal_start: 2000 + cal_end: 2040 + + Population calibration: + + round 1: + cal_start: 2000 + cal_end: 2040 + match population sizes 1: + adjustables: + b_rate,mig_rate: [ 0.1,10 ] + measurables: [alive] + + round 2: + match population sizes 2: + cal_start: 2000 #is this meant to work? + cal_end: 2040 + adjustables: + b_rate,mig_rate: [ 0.1,10 ] + measurables: [alive] + + round 3: + match population sizes 3: + adjustables: + b_rate,mig_rate: [ 0.1,10 ] + measurables: + alive: + cal_start: 2000 + cal_end: 2040 diff --git a/tests/yaml_tests/config_maxtime_test.yaml b/tests/yaml_tests/config_maxtime_test.yaml new file mode 100644 index 00000000..16f1cc8f --- /dev/null +++ b/tests/yaml_tests/config_maxtime_test.yaml @@ -0,0 +1,36 @@ +--- +#Timestep for the model +sim_dt: 0.019 +cal_start: 2000 +cal_end: 2040 + +#Ordered instructions for how to calibrate the model + #adj order: (adjustable var_label, populations to adjust for (default all), minimum value (default 0.1), maximum value (default 10), initial y_factor value (optional, default is parset value)) + #meas order: #(measurable var_label, populations to measure for (default all), weight (default 1.0), metric (default "fractional"), start_year (optional), end_year (optional)) +calibration: + max_time: 1 + + Population calibration: + + round 1: + max_time: 1 + match population sizes 1: + adjustables: + b_rate,mig_rate: [ 0.1,10 ] + measurables: [alive] + + round 2: + match population sizes 2: + max_time: 1 + adjustables: + b_rate,mig_rate: [ 0.1,10 ] + measurables: [alive] + +# round 3: +# match population sizes 3: +# adjustables: +# b_rate,mig_rate: [ 0.1,10 ] +# b_rate: +# cal_start: 2000 #is this meant to work? +# cal_end: 2040 +# measurables: [ alive ] diff --git a/tests/yaml_tests/config_simtime_test.yaml b/tests/yaml_tests/config_simtime_test.yaml new file mode 100644 index 00000000..34a372ee --- /dev/null +++ b/tests/yaml_tests/config_simtime_test.yaml @@ -0,0 +1,37 @@ +--- +#Timestep for the model +sim_dt: 0.019 +sim_start: 2000 +sim_end: 2040 + +#Ordered instructions for how to calibrate the model + #adj order: (adjustable var_label, populations to adjust for (default all), minimum value (default 0.1), maximum value (default 10), initial y_factor value (optional, default is parset value)) + #meas order: #(measurable var_label, populations to measure for (default all), weight (default 1.0), metric (default "fractional"), start_year (optional), end_year (optional)) +calibration: + sim_start: 2000 + sim_end: 2040 + + Population calibration: + + round 1: + sim_start: 2000 + sim_end: 2040 + match population sizes 1: + adjustables: + b_rate,mig_rate: [ 0.1,10 ] + measurables: [alive] + + round 2: + match population sizes 2: + sim_start: 2000 #is this meant to work? + sim_end: 2040 + adjustables: + b_rate,mig_rate: [ 0.1,10 ] + measurables: [alive] + +# round 3: +# match population sizes 3: +# adjustables: +# stepsize: 0.5 +# b_rate,mig_rate: [ 0.1,10 ] +# measurables: [ alive ] diff --git a/tests/yaml_tests/config_stepsize_test.yaml b/tests/yaml_tests/config_stepsize_test.yaml index 84dc1a56..40a1f91b 100644 --- a/tests/yaml_tests/config_stepsize_test.yaml +++ b/tests/yaml_tests/config_stepsize_test.yaml @@ -6,11 +6,9 @@ sim_dt: 0.019 #adj order: (adjustable var_label, populations to adjust for (default all), minimum value (default 0.1), maximum value (default 10), initial y_factor value (optional, default is parset value)) #meas order: #(measurable var_label, populations to measure for (default all), weight (default 1.0), metric (default "fractional"), start_year (optional), end_year (optional)) calibration: - time_period : [2019,2040] - max_time: 1 + stepsize: 1 Population calibration: - max_time: 1 round 1: stepsize: 0.5 From 02f7e21f1c3b9a25202eecd8cd9ceb43bb2972e0 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Tue, 27 Aug 2024 17:19:30 +0200 Subject: [PATCH 042/161] Add yaml tests --- tests/yaml_tests/config_bounds_test.yaml | 13 +++++ tests/yaml_tests/config_cal_formats.yaml | 47 +++++++++++++++++++ .../config_nonexistent_setting_test.yaml | 31 ++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 tests/yaml_tests/config_bounds_test.yaml create mode 100644 tests/yaml_tests/config_cal_formats.yaml create mode 100644 tests/yaml_tests/config_nonexistent_setting_test.yaml diff --git a/tests/yaml_tests/config_bounds_test.yaml b/tests/yaml_tests/config_bounds_test.yaml new file mode 100644 index 00000000..855078f5 --- /dev/null +++ b/tests/yaml_tests/config_bounds_test.yaml @@ -0,0 +1,13 @@ + +calibration: + pop cal: + + match population sizes: + adjustables: + b_rate, mig_rate: [ 0.1, 10 ] + measurables: alive + + turn off epi y-factors: + adjustables: + typ_active_inf, typ_car, par_active_inf, par_car: [0, 0] #set y-factor w/o going through cal algorithm + measurables: deaths \ No newline at end of file diff --git a/tests/yaml_tests/config_cal_formats.yaml b/tests/yaml_tests/config_cal_formats.yaml new file mode 100644 index 00000000..4151f3fe --- /dev/null +++ b/tests/yaml_tests/config_cal_formats.yaml @@ -0,0 +1,47 @@ +--- +#Timestep for the model +sim_dt: 0.019 + +#Ordered instructions for how to calibrate the model + #adj order: (adjustable var_label, populations to adjust for (default all), minimum value (default 0.1), maximum value (default 10), initial y_factor value (optional, default is parset value)) + #meas order: #(measurable var_label, populations to measure for (default all), weight (default 1.0), metric (default "fractional"), start_year (optional), end_year (optional)) +calibration: + + Population calibration: + + #dict format + match population sizes 1: + adjustables: + b_rate: + lower_bound: 0.1 + upper_bound: 10 + mig_rate: + starting_y_factor: 1.2 + measurables: + alive: + metric: fractional + + #combined format + match population sizes 2: + version 1: + adjustables: + b_rate: [ 0.1,10 ] + mig_rate: [ 0.1,10 ] + measurables: + alive: [1.0] + + version 2: + adjustables: + b_rate, mig_rate: [ 0.1,10 ] + measurables: + alive: [1.0] + + #list format + match population sizes 3: + adjustables: [[b_rate, 0.1, 10], [mig_rate, 0.1, 10]] + measurables: [alive] + + #string format + match population sizes 4: + adjustables: [b_rate, mig_rate] + measurables: alive diff --git a/tests/yaml_tests/config_nonexistent_setting_test.yaml b/tests/yaml_tests/config_nonexistent_setting_test.yaml new file mode 100644 index 00000000..00382e70 --- /dev/null +++ b/tests/yaml_tests/config_nonexistent_setting_test.yaml @@ -0,0 +1,31 @@ +--- +#Timestep for the model +sim_dt: 0.019 + +#Ordered instructions for how to calibrate the model + #adj order: (adjustable var_label, populations to adjust for (default all), minimum value (default 0.1), maximum value (default 10), initial y_factor value (optional, default is parset value)) + #meas order: #(measurable var_label, populations to measure for (default all), weight (default 1.0), metric (default "fractional"), start_year (optional), end_year (optional)) +calibration: + strawberry: 2 + Population calibration: + + round 1: + raddish: 3 + match population sizes 1: + adjustables: + b_rate,mig_rate: [ 0.1,10 ] + measurables: [alive] + + round 2: + match population sizes 2: + kiwi: 4 + adjustables: + b_rate,mig_rate: [ 0.1,10 ] + measurables: [alive] + +# round 3: +# match population sizes 3: +# adjustables: +# stepsize: 0.5 +# b_rate,mig_rate: [ 0.1,10 ] +# measurables: [ alive ] From d5457305be4fbdddfe62499adf101a546149a0d8 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Tue, 27 Aug 2024 17:21:07 +0200 Subject: [PATCH 043/161] Add repeats test, update simtime test --- tests/yaml_tests/config_repeats_test.yaml | 36 +++++++++++++++++++++++ tests/yaml_tests/config_simtime_test.yaml | 7 ----- 2 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 tests/yaml_tests/config_repeats_test.yaml diff --git a/tests/yaml_tests/config_repeats_test.yaml b/tests/yaml_tests/config_repeats_test.yaml new file mode 100644 index 00000000..76f59b5e --- /dev/null +++ b/tests/yaml_tests/config_repeats_test.yaml @@ -0,0 +1,36 @@ +--- +#Timestep for the model +sim_dt: 0.019 +cal_start: 2000 +cal_end: 2040 + +#Ordered instructions for how to calibrate the model + #adj order: (adjustable var_label, populations to adjust for (default all), minimum value (default 0.1), maximum value (default 10), initial y_factor value (optional, default is parset value)) + #meas order: #(measurable var_label, populations to measure for (default all), weight (default 1.0), metric (default "fractional"), start_year (optional), end_year (optional)) +calibration: + repeats: 1 + + Population calibration: + repeats: 1 + round 1: + repeats: 1 + match population sizes 1: + adjustables: + b_rate,mig_rate: [ 0.1,10 ] + measurables: [alive] + + round 2: + match population sizes 2: + repeats: 1 #should error? + adjustables: + b_rate,mig_rate: [ 0.1,10 ] + measurables: [alive] + +# round 3: +# match population sizes 3: +# adjustables: +# b_rate,mig_rate: [ 0.1,10 ] +# b_rate: +# cal_start: 2000 #is this meant to work? +# cal_end: 2040 +# measurables: [ alive ] diff --git a/tests/yaml_tests/config_simtime_test.yaml b/tests/yaml_tests/config_simtime_test.yaml index 34a372ee..a3f13b1c 100644 --- a/tests/yaml_tests/config_simtime_test.yaml +++ b/tests/yaml_tests/config_simtime_test.yaml @@ -28,10 +28,3 @@ calibration: adjustables: b_rate,mig_rate: [ 0.1,10 ] measurables: [alive] - -# round 3: -# match population sizes 3: -# adjustables: -# stepsize: 0.5 -# b_rate,mig_rate: [ 0.1,10 ] -# measurables: [ alive ] From dfd04a5f3767d5c26864a910f024e18d69903e81 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Tue, 27 Aug 2024 17:54:36 +0200 Subject: [PATCH 044/161] Enable calibrating transfers --- atomica/yaml_calibration.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 213cf9e6..8cd3d175 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -251,10 +251,12 @@ def validate(self): def process_key(s): """ - Sanitize key name with optional space separating pop name + Sanitize key name with optional commas or spaces separating pop name/s from par name """ - if ' ' in s: - return tuple([x.replace('~', ' ') for x in s.split(' ') if x]) + if ',' in s: + return tuple([x.strip().replace('~', ' ') for x in s.split(',') if x]) + elif ' ' in s: + return tuple([x.strip().replace('~', ' ') for x in s.split(' ') if x]) else: return (s.strip().replace('~', ' '), None) From 2e0eb357a509de4fd9eb1e8c9b44589073de19e0 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Thu, 29 Aug 2024 12:40:21 +1000 Subject: [PATCH 045/161] Improve float formatting --- atomica/plotting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/plotting.py b/atomica/plotting.py index 9529ab8d..819dc7ce 100644 --- a/atomica/plotting.py +++ b/atomica/plotting.py @@ -590,7 +590,7 @@ def time_aggregate(self, t_bins, time_aggregation=None, interpolation_method=Non if sc.isstring(t_bins) and t_bins == "all": s.t_labels = ["All"] else: - s.t_labels = ["%d-%d" % (low, high) for low, high in zip(lower, upper)] + s.t_labels = [f"{np.format_float_positional(low,trim='-')}-{np.format_float_positional(high,trim='-')}" for low, high in zip(lower, upper)] return self From 6a2c09719e571917288f89e21b20a2ea9c4bb95b Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Thu, 29 Aug 2024 12:40:43 +1000 Subject: [PATCH 046/161] Add validation of time aggregation type --- atomica/plotting.py | 1 + 1 file changed, 1 insertion(+) diff --git a/atomica/plotting.py b/atomica/plotting.py index 819dc7ce..f2383a4b 100644 --- a/atomica/plotting.py +++ b/atomica/plotting.py @@ -203,6 +203,7 @@ def __init__(self, results, outputs=None, pops=None, output_aggregation=None, po assert output_aggregation in [None, "sum", "average", "weighted"] assert pop_aggregation in [None, "sum", "average", "weighted"] + assert time_aggregation in [None, "integrate", "average"] # First, get all of the pops and outputs requested by flattening the lists pops_required = _extract_labels(pops) From 98d010bd3f39c9f626a86ea3f6a558d1f8ac9564 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Thu, 29 Aug 2024 12:40:52 +1000 Subject: [PATCH 047/161] Fix time aggregation validation --- atomica/plotting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/plotting.py b/atomica/plotting.py index f2383a4b..1aa1708f 100644 --- a/atomica/plotting.py +++ b/atomica/plotting.py @@ -307,7 +307,7 @@ def placeholder_pop(): displayed_annualization_warning = False for dep_label in dep_labels: vars = pop.get_variable(dep_label) - if t_bins is not None and (isinstance(vars[0], Link) or isinstance(vars[0], Parameter)) and time_aggregation == "sum" and not displayed_annualization_warning: + if t_bins is not None and (isinstance(vars[0], Link) or isinstance(vars[0], Parameter)) and time_aggregation == "integrate" and not displayed_annualization_warning: raise Exception("Function includes Parameter/Link so annualized rates are being used. Aggregation should therefore use 'average' rather than 'sum'.") deps[dep_label] = vars par._fcn = fcn From 44627afcc061f4262a3e4a86e96aab0da4c4e60f Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Thu, 29 Aug 2024 12:41:03 +1000 Subject: [PATCH 048/161] Improve comment --- atomica/excel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/excel.py b/atomica/excel.py index 2a0119ce..e864fde5 100644 --- a/atomica/excel.py +++ b/atomica/excel.py @@ -403,7 +403,7 @@ def __init__(self, code_name: str, full_name: str, tvec: np.array, from_pops: li self.ts = ts if ts is not None else sc.odict() self.attributes = {} #: Attributes associated with the table - self.ts_attributes = {} #: Attributes associated with each TimeSeries row + self.ts_attributes = {} #: Attributes associated with each TimeSeries row. This is a dict-of-dicts with `ts_attributes[attribute]={pop:value}` e.g., ts_attributes["Provenance"] = {'popA': 'value', 'popB': 'value'} self.ts_attributes["Provenance"] = {} # Include provenance attribute by default self.assumption_heading = "Constant" #: Heading to use for assumption column From f3faa269e449e133c563bb5160ef0d1ba54e7853 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Thu, 29 Aug 2024 17:48:00 +0200 Subject: [PATCH 049/161] Process calibration inputs with parentheses Adjustables/measurables and populations can now be differentiated in the yaml file by separating the par_name from the pop_name/s with commas, and placing them in parentheses. Examples: (b_rate, 0-4): ... (aging, 0-4, 5-14): ... --> transfer The previous notation is still supported: b_rate 0-4: ... --- atomica/yaml_calibration.py | 45 +++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 8cd3d175..97267bde 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -10,6 +10,7 @@ import numpy as np import yaml import time +import re __all__ = ['build', 'run'] @@ -249,16 +250,30 @@ def validate(self): Pre-parse calibration inputs """ + def separate_keys(s): + """ + Separate inputs that kave been defined together as one key in the YAML file + """ + s1 = re.findall(r'\(.*?\)', s) + s2 = s + for x in s1: + s2 = s2.replace(x, '') + all_strings = [x for x in s1 if x] + s2 = re.sub(r'(,\s)+', ', ', s2).strip(', ').split(',') + if s2 != ['']: + all_strings += s2 + return all_strings + def process_key(s): """ Sanitize key name with optional commas or spaces separating pop name/s from par name """ - if ',' in s: - return tuple([x.strip().replace('~', ' ') for x in s.split(',') if x]) + if '(' and ')' in s: + return tuple([x.strip() for x in s.strip('() ').split(',') if x]) elif ' ' in s: - return tuple([x.strip().replace('~', ' ') for x in s.split(' ') if x]) + return tuple([x.strip() for x in s.split(' ') if x]) else: - return (s.strip().replace('~', ' '), None) + return (s.strip(), None) def process_inputs(inputs, defaults): """ @@ -281,19 +296,35 @@ def process_inputs(inputs, defaults): if isinstance(inputs, (tuple, list)): for l in inputs: l = sc.promotetolist(l) + #TODO enable and test transfers in full list format key, pop_name = process_key(l[0].strip()) d = self.parse_list(l[1:], defaults) out[key, pop_name] = sc.mergedicts(out.get((key, pop_name), {}), d) + elif isinstance(inputs, dict): for keys, v in inputs.items(): - for key in keys.split(','): - key, pop_name = process_key(key.strip()) + + separated_keys = separate_keys(keys) + for key in separated_keys: + #separate par name from pop name/s + keyspops = process_key(key.strip()) + if len(keyspops) == 2: + key, pop_name = keyspops + else: + assert len(keyspops) == 3, f'Number of populations must be 1, 2 or None)' + key, pop_name, pop_name2 = keyspops + + #process values if isinstance(v, (tuple, list)): d = self.parse_list(v, defaults) else: d = v.copy() - out[key, pop_name] = sc.mergedicts(out.get((key, pop_name), {}), d) + #add keys and values to outputs dict + if len(keyspops) == 2: + out[key, pop_name] = sc.mergedicts(out.get((key, pop_name), {}), d) + else: + out[key, pop_name, pop_name2] = sc.mergedicts(out.get((key, pop_name), {}), d) return out self['adjustables'] = process_inputs(self['adjustables'], self.adj_defaults) From f903c2794615f1a78201bd0ac2ec397f5a2437cd Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Fri, 30 Aug 2024 09:46:27 +1000 Subject: [PATCH 050/161] Don't create databook spreadsheets unnecessarily --- CHANGELOG.md | 9 ++++++++- atomica/project.py | 2 +- atomica/version.py | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9576263c..935876aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,18 @@ This file records changes to the codebase grouped by version release. Unreleased changes are generally only present during development (relevant parts of the changelog can be written and saved in that section before a version number has been assigned) +## [1.28.7] - 2023-08-12 + +- `Project.load_databook()` will no longer populate `Project.databook` when a `ProjectData` instance is supplied rather than a spreadsheet. The intention of `Project.databook` as opposed to `Project.data.to_spreadsheet()` is that the original databook may contain comments or other content that is not preserved when the databook is loaded into a `ProjectData` instance. Therefore, `Project.databook` serves as a record of the original inputs. However, in previous versions of Atomica, if a `ProjectData` instance was provided rather than a spreadsheet, `ProjectData.to_spreadsheet()` would be used to populate `Project.databook`. For large databooks, this can be computationally expensive and particularly affect the use case of passing in a preloaded databook to improve performance. Since the conversion of the `ProjectData` to a spreadsheet upon loading offers no functional difference to creating the spreadsheet from `Project.data` when required, Atomica no longer performs this conversion upfront. + +*Backwards-compatibility notes* + +- If accessing `Project.databook`, in some cases this may now be `None` rather than an `sc.Spreadsheet()`. If that occurs, `Project.data.to_spreadsheet()` should be used to produce an equivalent spreadsheet. + ## [1.28.6] - 2023-07-12 - Support entering `'total'` as the population name in auto-calibration measurables to calibrate aggregated values across populations in the model to aggregate values entered in the databook under a 'Total' population - ## [1.28.5] - 2023-06-28 - Enable automated calibration of transfers and updated documentation to cover this feature diff --git a/atomica/project.py b/atomica/project.py index e6881957..5049533e 100644 --- a/atomica/project.py +++ b/atomica/project.py @@ -260,7 +260,7 @@ def load_databook(self, databook_path, make_default_parset: bool = True, do_run: if isinstance(databook_path, ProjectData): # If the user passed in a ProjectData instance, use it directly data = databook_path - databook = data.to_spreadsheet() + databook = None else: if isinstance(databook_path, sc.Spreadsheet): databook = databook_path diff --git a/atomica/version.py b/atomica/version.py index ffdfcfc0..9955dee6 100644 --- a/atomica/version.py +++ b/atomica/version.py @@ -6,6 +6,6 @@ import sciris as sc -version = "1.28.6" -versiondate = "2024-07-12" +version = "1.28.7" +versiondate = "2024-08-30" gitinfo = sc.gitinfo(__file__) From 837203ddc0029cf5f302ab986eb209531fc6fe25 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Fri, 30 Aug 2024 15:11:18 +1000 Subject: [PATCH 051/161] Fix calibrating transfers with no to_population specified --- atomica/calibration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/calibration.py b/atomica/calibration.py index 8c1e5d97..9306cdea 100644 --- a/atomica/calibration.py +++ b/atomica/calibration.py @@ -174,7 +174,7 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, initial_value = None if par_tuple[1] is None: # If the pop name is None - par = parset.pars[par_tuple[0]] + par = parset.get_par(par_tuple[0]) for pop_name in par.pops: p2.append((par_tuple[0], pop_name, par_tuple[2], par_tuple[3], initial_value)) else: From e243d6dcf98b7eaf355e77697863719c51017823 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Fri, 30 Aug 2024 13:09:56 +0200 Subject: [PATCH 052/161] Finish enabling transfers in dict form --- atomica/yaml_calibration.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 97267bde..de29b8b9 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -312,7 +312,8 @@ def process_inputs(inputs, defaults): key, pop_name = keyspops else: assert len(keyspops) == 3, f'Number of populations must be 1, 2 or None)' - key, pop_name, pop_name2 = keyspops + key = f'{keyspops[0]}_from_{keyspops[1]}' + pop_name = keyspops[2] #process values if isinstance(v, (tuple, list)): @@ -321,10 +322,7 @@ def process_inputs(inputs, defaults): d = v.copy() #add keys and values to outputs dict - if len(keyspops) == 2: - out[key, pop_name] = sc.mergedicts(out.get((key, pop_name), {}), d) - else: - out[key, pop_name, pop_name2] = sc.mergedicts(out.get((key, pop_name), {}), d) + out[key, pop_name] = sc.mergedicts(out.get((key, pop_name), {}), d) return out self['adjustables'] = process_inputs(self['adjustables'], self.adj_defaults) From bb5f09b8671a1cf6ad8e515058af6fee4e3594f1 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Fri, 30 Aug 2024 17:15:34 +0200 Subject: [PATCH 053/161] Fix check_optional_number TypeError Fixed print statement in TypeError --- atomica/yaml_calibration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index de29b8b9..98c5e779 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -331,7 +331,7 @@ def process_inputs(inputs, defaults): def check_optional_number(key, v, defaults): if key in v and v[key] is not None: if not sc.isnumber(v[key], isnan=False): - raise TypeError(f"Adjustable argument '{key}' needs to be a number or None (defaults to {defaults[key]}). Provided value: {v[key]} ") + raise TypeError(f"Adjustable argument {key} needs to be a number or None (defaults to {defaults[key]}). Provided value: {v[key]} ") # Validate adjustables assert len(self['adjustables']) > 0, f'Cannot calibrate with no adjustables for calibration section {self.name}' From bf48a2ab052eba8c12a6f6be85f33a6c6bc16831 Mon Sep 17 00:00:00 2001 From: alina-muellenmeister Date: Tue, 3 Sep 2024 16:04:57 +1000 Subject: [PATCH 054/161] update cal_start and cal_end --- atomica/yaml_calibration.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index de29b8b9..75ed91f3 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -366,6 +366,8 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui par_names = {x[0] for x in attributes['adjustables']}.intersection(x.name for x in parset.all_pars()) pop_names = {x[1] for x in attributes['adjustables']}.intersection({*parset.pop_names} | {'all', None}) + adj_defaults = {k:self.attributes[k] if k in self.attributes else self.adj_defaults[k] for k in self.adj_defaults} + for par_name, pop_name in attributes['adjustables']: if par_name not in par_names: @@ -381,7 +383,7 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui pops = sc.promotetolist(pop_name) for pop in pops: - d = sc.mergedicts(self.adj_defaults, attributes['adjustables'].get((par_name, None), None), attributes['adjustables'].get((par_name, pop), None)) + d = sc.mergedicts(adj_defaults, attributes['adjustables'].get((par_name, None), None), attributes['adjustables'].get((par_name, pop), None)) adjustables[(par_name, pop)] = (d['lower_bound'], d['upper_bound'], d['initial_value']) adjustables = [(*k, *v) for k,v in adjustables.items()] @@ -391,6 +393,8 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui par_names = {x[0] for x in attributes['measurables']}.intersection(x.name for x in parset.all_pars()) # TODO: This is probably OK for now but will need to support transfer parameters and validate that pars have databook entries in the future pop_names = {x[1] for x in attributes['measurables']}.intersection({*parset.pop_names} | {None}) + meas_defaults = {k: self.attributes[k] if k in self.attributes else self.meas_defaults[k] for k in self.meas_defaults} + for par_name, pop_name in attributes['measurables']: if par_name not in par_names: @@ -407,7 +411,7 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui pops = sc.promotetolist(pop_name) for pop in pops: - d = sc.mergedicts(self.meas_defaults, attributes['measurables'].get((par_name, None), None), attributes['measurables'].get((par_name, pop), None)) + d = sc.mergedicts(meas_defaults, attributes['measurables'].get((par_name, None), None), attributes['measurables'].get((par_name, pop), None)) measurables[(par_name, pop)] = (d['weight'], d['metric'], d['cal_start'], d['cal_end']) measurables = [(*k, *v) for k,v in measurables.items()] From 623ef388408c6346a10620166601484f4aa7a449 Mon Sep 17 00:00:00 2001 From: alina-muellenmeister Date: Thu, 5 Sep 2024 08:43:25 +1000 Subject: [PATCH 055/161] save a copy of the yaml file --- atomica/yaml_calibration.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 75ed91f3..a237d110 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -6,6 +6,7 @@ import sciris as sc from pathlib import Path +import shutil import atomica as at import numpy as np import yaml @@ -61,17 +62,20 @@ def run(node, project, parset, savedir=None, save_intermediate=False, log_output :return new_parset: A calibrated `at.ParameterSet` instance """ - if not isinstance(node, BaseNode): - node = build(node) - - parset = sc.dcp(project.parset(parset)) - if savedir is None: savedir = Path('.') else: savedir = Path(savedir) savedir.mkdir(exist_ok=True, parents=True) + if not isinstance(node, BaseNode): + # Save a copy of the yaml-file if saving log output + if isinstance(node, Path) and log_output: + shutil.copyfile(node, savedir / node.name) + node = build(node) + + parset = sc.dcp(project.parset(parset)) + nodes = list(node.walk()) # Make a flat list of all nodes to execute in order n_steps = len([x for x in nodes if not isinstance(x[1], SectionNode)]) n = 1 From eac53fd09e15e3834c640958a2ce43362d1c4207 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Thu, 5 Sep 2024 16:04:47 +1000 Subject: [PATCH 056/161] Add guard to prevent setting time_period if YAML file is in use --- atomica/project.py | 1 + 1 file changed, 1 insertion(+) diff --git a/atomica/project.py b/atomica/project.py index c024ae51..68925a48 100644 --- a/atomica/project.py +++ b/atomica/project.py @@ -642,6 +642,7 @@ def calibrate(self, import atomica.yaml_calibration # Avoid circular import assert adjustables is None, "If a YAML file is specified, adjustables should not be set" assert measurables is None, "If a YAML file is specified, measurables should not be set" + assert 'time_period' not in kwargs, "If a YAML file is specified, time_period should not be set - instead, set cal_start and cal_end in the YAML file" new_parset = atomica.yaml_calibration.run(yaml, self, parset, **kwargs) else: if adjustables is None: From 5d93853f7686249183523f533f9d48c2a87bf5af Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Thu, 5 Sep 2024 16:10:37 +1000 Subject: [PATCH 057/161] Clear existing initializations when loading calibrations --- CHANGELOG.md | 8 ++++++++ atomica/parameters.py | 2 ++ atomica/version.py | 4 ++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 935876aa..b6cb48a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ This file records changes to the codebase grouped by version release. Unreleased changes are generally only present during development (relevant parts of the changelog can be written and saved in that section before a version number has been assigned) + +version = "1.28.8" +versiondate = "2024-09-05" + +## [1.28.8] - 2023-09-05 + +- `ParameterSet.load_calibration()` now clears any existing initialization if the calibration being loaded does not contain an initialization. Previously, the absence of an 'initialization' sheet in the calibration would be treated as not making any change to the initialization. This could cause calibrations to become mixed if a calibration without an initialization was loaded after a calibration with an initialization. Now, a missing initialization sheet is treated as meaning 'no initialization' and any existing initialization will be cleared when the calibration is loaded. + ## [1.28.7] - 2023-08-12 - `Project.load_databook()` will no longer populate `Project.databook` when a `ProjectData` instance is supplied rather than a spreadsheet. The intention of `Project.databook` as opposed to `Project.data.to_spreadsheet()` is that the original databook may contain comments or other content that is not preserved when the databook is loaded into a `ProjectData` instance. Therefore, `Project.databook` serves as a record of the original inputs. However, in previous versions of Atomica, if a `ProjectData` instance was provided rather than a spreadsheet, `ProjectData.to_spreadsheet()` would be used to populate `Project.databook`. For large databooks, this can be computationally expensive and particularly affect the use case of passing in a preloaded databook to improve performance. Since the conversion of the `ProjectData` to a spreadsheet upon loading offers no functional difference to creating the spreadsheet from `Project.data` when required, Atomica no longer performs this conversion upfront. diff --git a/atomica/parameters.py b/atomica/parameters.py index 49b177db..630f3e62 100644 --- a/atomica/parameters.py +++ b/atomica/parameters.py @@ -685,5 +685,7 @@ def load_calibration(self, spreadsheet: sc.Spreadsheet) -> None: if "Initialization" in excelfile.sheet_names: self.initialization = Initialization.from_excel(excelfile) + else: + self.initialization = None logger.debug("Loaded calibration from file") diff --git a/atomica/version.py b/atomica/version.py index 9955dee6..d2cd1f18 100644 --- a/atomica/version.py +++ b/atomica/version.py @@ -6,6 +6,6 @@ import sciris as sc -version = "1.28.7" -versiondate = "2024-08-30" +version = "1.28.8" +versiondate = "2024-09-05" gitinfo = sc.gitinfo(__file__) From a6b38d5fa6e4b2f1f14acead6c65de49449ea231 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Sat, 7 Sep 2024 07:38:17 +1000 Subject: [PATCH 058/161] Make initialization slightly more permissive if value is 0 --- atomica/parameters.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/atomica/parameters.py b/atomica/parameters.py index 630f3e62..bdcf39e4 100644 --- a/atomica/parameters.py +++ b/atomica/parameters.py @@ -299,7 +299,19 @@ def apply(self, pop, framework=None, parset=None) -> None: if (comp.name, pop.name) not in self.values: comp._vals[:, 0] = 0 else: - comp._vals[:, 0] = self.values[(comp.name, pop.name)] + if len(self.values[(comp.name, pop.name)]) != comp._vals.shape[0]: + # If there is a mismatch between the saved initialization duration and the + # duration for the current simulation, if the values were all zero it would probably + # be safe to assume the values can remain zero. If there are fewer time points in the saved + # initialization we *could* insert them, however, there is a risk that the time points are different + # because the step size was changed rather than the duration being changed, so it would not be valid + # to do that. Therefore, if the sizes don't match and any values are nonzero, simply raise an error + if np.all(self.values[(comp.name, pop.name)] == 0): + comp._vals[:, 0] = 0 + else: + raise Exception(f'The saved initialization for "{comp.name}" ({pop.name}) has {len(self.values[(comp.name, pop.name)])} time points, but the current parameters lead to a timed compartment duration with {comp._vals.shape[0]} time points. As nonzero values are present, the initialization cannot be applied.') + else: + comp._vals[:, 0] = self.values[(comp.name, pop.name)] else: if (comp.name, pop.name) not in self.values: comp.vals[0] = 0 From cb78ee62e7ab580fd80a119fada1b530cdf111b3 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 9 Sep 2024 12:25:26 +1000 Subject: [PATCH 059/161] Fix a numerical precision edge case when calculating simulation time vector --- CHANGELOG.md | 8 ++++++-- atomica/project.py | 7 +++++-- atomica/version.py | 4 ++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6cb48a7..cea574c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,13 @@ This file records changes to the codebase grouped by version release. Unreleased changes are generally only present during development (relevant parts of the changelog can be written and saved in that section before a version number has been assigned) +## [1.29.0] - 2023-09-09 -version = "1.28.8" -versiondate = "2024-09-05" +- `ProjectSettings` now computes the simulation time vector in a more robust way to reduce edge cases where the reported `sim_dt` doesn't match the input. + +*Backwards-compatibility notes* + +- In some edge cases, the simulation time points in the output may be different. In those cases, the difference between simulation time points in the model output would not have matched the model input, although the correct time step would have been used to calculate parameter values. In these cases, there may be an extra time point in the model output. Re-running the model should produce results that are close to the original results. ## [1.28.8] - 2023-09-05 diff --git a/atomica/project.py b/atomica/project.py index 68925a48..2ab71bb0 100644 --- a/atomica/project.py +++ b/atomica/project.py @@ -94,8 +94,11 @@ def tvec(self) -> np.ndarray: :return: Array of simulation times """ - - return np.linspace(self.sim_start, self.sim_end, int((self.sim_end - self.sim_start) / self.sim_dt) + 1) + # The int(np.float32()) helps cases where the numerical precision results in unwanted truncation e.g., + # running a model over the range [2000,2066) with dt=1/12, it calculates 791.9999999999982 time steps + # rather than 792, in that case we can convert to a float32 to effectively round it to 792 before + # taking the integer. This should generally be safe for the types of values that get used for simulation years + return np.linspace(self.sim_start, self.sim_end, int(np.float32(((self.sim_end - self.sim_start) / self.sim_dt))) + 1) def update_time_vector(self, start: float = None, end: float = None, dt: float = None) -> None: """ diff --git a/atomica/version.py b/atomica/version.py index d2cd1f18..62595080 100644 --- a/atomica/version.py +++ b/atomica/version.py @@ -6,6 +6,6 @@ import sciris as sc -version = "1.28.8" -versiondate = "2024-09-05" +version = "1.29.0" +versiondate = "2024-09-09" gitinfo = sc.gitinfo(__file__) From 14b56c70467fb3124cc9e3e796f11dc45d3a7854 Mon Sep 17 00:00:00 2001 From: alina-muellenmeister Date: Thu, 12 Sep 2024 08:09:47 +1000 Subject: [PATCH 060/161] allow for 0 timed compartment durations --- atomica/parameters.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atomica/parameters.py b/atomica/parameters.py index bdcf39e4..51949121 100644 --- a/atomica/parameters.py +++ b/atomica/parameters.py @@ -299,7 +299,8 @@ def apply(self, pop, framework=None, parset=None) -> None: if (comp.name, pop.name) not in self.values: comp._vals[:, 0] = 0 else: - if len(self.values[(comp.name, pop.name)]) != comp._vals.shape[0]: + vals = self.values[(comp.name, pop.name)] + if (comp._vals.shape[0] > 1 and len(vals) != comp._vals.shape[0]) or (comp._vals.shape[0] == 1 and not np.isscalar(vals)): # If there is a mismatch between the saved initialization duration and the # duration for the current simulation, if the values were all zero it would probably # be safe to assume the values can remain zero. If there are fewer time points in the saved From ddf30ef496271703a5fbbd44008e4fd1407a4bbe Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Thu, 19 Sep 2024 21:16:01 +0200 Subject: [PATCH 061/161] improve process_key() --- atomica/yaml_calibration.py | 47 +++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index eba6e180..1549948b 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -254,21 +254,42 @@ def validate(self): Pre-parse calibration inputs """ - def separate_keys(s): + def separate_keys(keys_str: str) -> list: """ - Separate inputs that kave been defined together as one key in the YAML file + Separate inputs that kave been defined together as one key in the YAML file into a list of strnigs. """ - s1 = re.findall(r'\(.*?\)', s) - s2 = s - for x in s1: - s2 = s2.replace(x, '') - all_strings = [x for x in s1 if x] - s2 = re.sub(r'(,\s)+', ', ', s2).strip(', ').split(',') - if s2 != ['']: - all_strings += s2 - return all_strings - - def process_key(s): + in_brackets = False + brackets_str = '' + nobrackets_str = '' + separated_keys = [] + + for ch in keys_str: + if ch == '(': + in_brackets = True + continue + elif ch == ')': + in_brackets = False + separated_keys.append(brackets_str) + brackets_str = '' + continue + + if in_brackets: + brackets_str += ch + else: + if ch == ',': + if nobrackets_str == ' ' or nobrackets_str == '': + nobrackets_str = '' + continue + else: + separated_keys.append(nobrackets_str) + nobrackets_str = '' + else: + nobrackets_str += ch + + if nobrackets_str != '' and nobrackets_str != ' ': + separated_keys.append(nobrackets_str) + + return [x.strip() for x in separated_keys] """ Sanitize key name with optional commas or spaces separating pop name/s from par name """ From 9c1e77dc2aa9d8b4ee9f866dc14a25300f2828a3 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Mon, 23 Sep 2024 15:34:50 +0200 Subject: [PATCH 062/161] Enable transfers in list format, deprecate pop space formatting -Space between par and pop is deprecated - now pops must be specified in a tuple with the par -Transfers are now supported in all formats --- atomica/yaml_calibration.py | 76 +++++++++++++++++++++++++++++-------- 1 file changed, 60 insertions(+), 16 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 1549948b..f076a8fa 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -245,6 +245,13 @@ class CalibrationNode(BaseNode): def parse_list(l, defaults): # Routine to parse list of arguments into a dictionary of values d = {} + #convert number strings back to numerical values + for i, e in enumerate(l.copy()): + try: + l[i] = float(e) + except ValueError: + pass + for k, v in zip(list(defaults.keys())[:len(l)], l): d[k] = v return d @@ -290,15 +297,39 @@ def separate_keys(keys_str: str) -> list: separated_keys.append(nobrackets_str) return [x.strip() for x in separated_keys] + + def process_key(key: str) -> tuple: """ - Sanitize key name with optional commas or spaces separating pop name/s from par name + Sanitize key name, separating optional pop name/s from par name + #TODO add example and further explanation """ - if '(' and ')' in s: - return tuple([x.strip() for x in s.strip('() ').split(',') if x]) - elif ' ' in s: - return tuple([x.strip() for x in s.split(' ') if x]) + if ',' in key: + return tuple([x.strip() for x in key.strip('() ').split(',') if x]) else: - return (s.strip(), None) + return (key.strip(), None) + + def process_list(l) -> (str,list): + """description""" + if len(l) == 1: + #if the list is already just one string, return that string as key with None pop and vals + return (l[0].strip('() '), None), None + elif '(' in str(l): + # separate out the parenthesis contents as the par/pop/s, + # then output the key (par, pop tuple) and value + + # process keys + s = str(l).strip("[] ").replace("'", "") + s1 = re.findall(r'\(.*?\)', s) + key = process_key(s1[0].replace('(', '').replace(')', '')) + + # process values/settings + value = s.replace(s1[0], '').strip(', ').split(',') + value = [x.strip(', ') for x in value if x] + return key, value + else: + key = process_key(l[0]) + value = l[1:] + return key, value def process_inputs(inputs, defaults): """ @@ -321,33 +352,46 @@ def process_inputs(inputs, defaults): if isinstance(inputs, (tuple, list)): for l in inputs: l = sc.promotetolist(l) - #TODO enable and test transfers in full list format - key, pop_name = process_key(l[0].strip()) - d = self.parse_list(l[1:], defaults) - out[key, pop_name] = sc.mergedicts(out.get((key, pop_name), {}), d) + keyspops, v = process_list(l) + + #process key + if len(keyspops) == 2: + key, pop_name = keyspops + else: + assert len(keyspops) == 3, f'Number of populations must be 0, 1 or 2.' + key = f'{keyspops[0]}_from_{keyspops[1]}' + pop_name = keyspops[2] + + #process value + if v is None: + value = defaults + else: + value = self.parse_list(v, defaults) + + out[key, pop_name] = sc.mergedicts(out.get((key, pop_name), {}), value) elif isinstance(inputs, dict): for keys, v in inputs.items(): separated_keys = separate_keys(keys) for key in separated_keys: - #separate par name from pop name/s + #separate par name from pop name keyspops = process_key(key.strip()) if len(keyspops) == 2: key, pop_name = keyspops else: - assert len(keyspops) == 3, f'Number of populations must be 1, 2 or None)' + assert len(keyspops) == 3, f'Number of populations must be 0, 1 or 2.' key = f'{keyspops[0]}_from_{keyspops[1]}' pop_name = keyspops[2] #process values if isinstance(v, (tuple, list)): - d = self.parse_list(v, defaults) + value = self.parse_list(v, defaults) else: - d = v.copy() + value = v.copy() #add keys and values to outputs dict - out[key, pop_name] = sc.mergedicts(out.get((key, pop_name), {}), d) + out[key, pop_name] = sc.mergedicts(out.get((key, pop_name), {}), value) return out self['adjustables'] = process_inputs(self['adjustables'], self.adj_defaults) @@ -415,7 +459,7 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui # Expand measurables measurables = {} - par_names = {x[0] for x in attributes['measurables']}.intersection(x.name for x in parset.all_pars()) # TODO: This is probably OK for now but will need to support transfer parameters and validate that pars have databook entries in the future + par_names = {x[0] for x in attributes['measurables']}.intersection(x.name for x in parset.all_pars()) # TODO: This is probably OK for now but will need to validate that pars have databook entries in the future pop_names = {x[1] for x in attributes['measurables']}.intersection({*parset.pop_names} | {None}) meas_defaults = {k: self.attributes[k] if k in self.attributes else self.meas_defaults[k] for k in self.meas_defaults} From ba0d0b6cb8f37b5739729daf603f019a813c05bf Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Mon, 23 Sep 2024 15:35:16 +0200 Subject: [PATCH 063/161] Enable dict format with empty values --- atomica/yaml_calibration.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index f076a8fa..7ae99fcb 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -387,6 +387,8 @@ def process_inputs(inputs, defaults): #process values if isinstance(v, (tuple, list)): value = self.parse_list(v, defaults) + elif v is None: + value = defaults else: value = v.copy() From a437acd0967d81b6d4ebe7e42ff97354ee4cf892 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Mon, 23 Sep 2024 16:37:14 +0200 Subject: [PATCH 064/161] Improve testing of whether constant_parset is a number (not bool) --- atomica/yaml_calibration.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 7ae99fcb..49c6211b 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -581,9 +581,11 @@ def validate(self): def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, **kwargs) -> ParameterSet: p2 = sc.dcp(parset) if 'constant_parset' in self: - if self['constant_parset'] == True: + if self['constant_parset'] == False: + pass + elif self['constant_parset'] == True: p2 = parset.make_constant(year=project.settings.sim_start) - elif type(self['constant_parset']) == int: #constant parset year was provided + elif sc.isnumber(self['constant_parset']): #constant parset year was provided p2 = parset.make_constant(year=self['constant_parset']) new_settings = sc.dcp(project.settings) new_settings.update_time_vector(end=self['init_year']) From 5b73362a3ec4bb278740d519bb1bee987edc73ad Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Mon, 23 Sep 2024 16:45:27 +0200 Subject: [PATCH 065/161] Rename initial_value to starting_y_factor --- atomica/yaml_calibration.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 49c6211b..b1a02dc2 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -230,7 +230,7 @@ class CalibrationNode(BaseNode): adj_defaults = { 'lower_bound': 0.1, 'upper_bound': 10.0, - 'initial_value': None, + 'starting_y_factor': None, } # Order for list of measurable parameters and default values @@ -412,7 +412,7 @@ def check_optional_number(key, v, defaults): assert pop_name is None or isinstance(pop_name, str), f'Adjustable population {pop_name} needs to be a string or None (defaults to all populations for that parameter)' check_optional_number('lower_bound',v, self.adj_defaults) check_optional_number('upper_bound',v, self.adj_defaults) - check_optional_number('initial_value',v, self.adj_defaults) + check_optional_number('starting_y_factor',v, self.adj_defaults) # Validate measurables assert len(self['measurables']) > 0, f'Cannot calibrate with no measurables for calibration section {self.name}' @@ -455,7 +455,7 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui for pop in pops: d = sc.mergedicts(adj_defaults, attributes['adjustables'].get((par_name, None), None), attributes['adjustables'].get((par_name, pop), None)) - adjustables[(par_name, pop)] = (d['lower_bound'], d['upper_bound'], d['initial_value']) + adjustables[(par_name, pop)] = (d['lower_bound'], d['upper_bound'], d['starting_y_factor']) adjustables = [(*k, *v) for k,v in adjustables.items()] From fb0a4ba8c5b3555fbfaa72ebf3294ca8bc936e36 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Mon, 23 Sep 2024 19:09:26 +0200 Subject: [PATCH 066/161] Expand docstrings, add type hints --- atomica/yaml_calibration.py | 61 +++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index b1a02dc2..9b97f7a1 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -263,7 +263,10 @@ def validate(self): def separate_keys(keys_str: str) -> list: """ - Separate inputs that kave been defined together as one key in the YAML file into a list of strnigs. + Separate inputs that kave been defined together as one key in the YAML file but actually represent multiple + parameters. + :param str keys_str: Unprocessed input key from the YAML file. + :return list : A list of strings, each of which represents a single key. """ in_brackets = False brackets_str = '' @@ -300,16 +303,42 @@ def separate_keys(keys_str: str) -> list: def process_key(key: str) -> tuple: """ - Sanitize key name, separating optional pop name/s from par name - #TODO add example and further explanation + Sanitize the key name, separating the parameter codename from the optional population name/s. + :par str key: Key representing an adjustable or measurable parameter. It can also contain one or two + population names (two in the case of a transfer), separated from the parameter name by a comma. + :returns: A tuple of the parameter codename and population name/s. Population defaults to None + if not specified. + + EXAMPLES: + INPUT: 'b_rate' + OUTPUT: (b_rate, None) + + INPUT: 'b_rate, 0-4' + OUTPUT: (b_rate, 0-4) + + INPUT: 'aging, 0-4, 5-14' + OUTPUT: (aging, 0-4, 5-14) """ if ',' in key: return tuple([x.strip() for x in key.strip('() ').split(',') if x]) else: return (key.strip(), None) - def process_list(l) -> (str,list): - """description""" + def process_list(l: list) -> (tuple,list): + """ + Process list-format inputs and separate them into a key (par_name, pop_name tuple) and a value (list of + parameter settings). + @param l: List representing the settings for one parameter. + @return: tuple key: Tuple of the parameter codename and the population (default None). + list value: List of calibration settings for this parameter. + + EXAMPLES: + INPUT: [b_rate, 0.1, 10] + OUTPUT: (b_rate, None) ; [0.1, 10] + + INPUT: [(b_rate, 0-4), 0.1, 10, 1.5] + OUTPUT: (b_rate, 0-4) ; [0.1, 10, 1.5] + """ if len(l) == 1: #if the list is already just one string, return that string as key with None pop and vals return (l[0].strip('() '), None), None @@ -331,16 +360,22 @@ def process_list(l) -> (str,list): value = l[1:] return key, value - def process_inputs(inputs, defaults): + def process_inputs(inputs, defaults: dict) -> dict: """ - Process adjustables and measurables, which can be specified in a list representation or nested dict representation - In list representation, the input is a list of lists, where the first item in each list is the quantity (with optional population) and - the remaining items are the supported arguments for the input type, in the order defined by the defaults dictionary. - In a dict representation, the key is the quantity with optional population, and then the value can either be a list (in the order defined by the dictionary) - or a dictionary explicitly naming the inputs. + Process adjustables and measurables, which can be specified as a string, list or nested dict representation. + * In string representation, only the parameter name is specified, and the default settings are used. + * In list representation, the input is a list of lists, where the first item in each list is the parameter + (with optional population) and the remaining items are the supported arguments for the input type, in the + order defined by the defaults dictionary. + *In dict representation, the key is the quantity with optional population, and the value can either be + a list (in the order defined by the dictionary) or a dictionary explicitly naming the inputs. + This function returns a flat dictionary with {(quantity, pop_name):{argument:value}} e.g., {('b_rate','0-5'):{'lower_bound':0.5}}. - In the dict representation, the key can be a comma separated list of quantities with optional values e.g., 'b_rate 0-5, d_rate'. In the list representation, - multiple quantities are not supported (as a comma is already used to separate the arguments), but multiple lists (one for each quantity) can be provided. + In the dict representation, the key can be a comma separated list of quantities with optional values e.g., + 'b_rate 0-5, d_rate'. + In the list representation, multiple quantities are not supported (as a comma is already used to separate + the arguments), but multiple lists (one for each quantity) can be provided. + #TODO could add examples """ out = {} From b90b9ba9c5e13425b62222309ae24a290b3eaf72 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Mon, 23 Sep 2024 19:14:32 +0200 Subject: [PATCH 067/161] Make tuple conversion more explicit --- atomica/yaml_calibration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 9b97f7a1..4c042e68 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -322,7 +322,7 @@ def process_key(key: str) -> tuple: if ',' in key: return tuple([x.strip() for x in key.strip('() ').split(',') if x]) else: - return (key.strip(), None) + return tuple(key.strip(), None) def process_list(l: list) -> (tuple,list): """ From d84419761a518987591f6a4192cc86e2f3647680 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Mon, 23 Sep 2024 19:48:44 +0200 Subject: [PATCH 068/161] Fix tuple conversion --- atomica/yaml_calibration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 4c042e68..9b97f7a1 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -322,7 +322,7 @@ def process_key(key: str) -> tuple: if ',' in key: return tuple([x.strip() for x in key.strip('() ').split(',') if x]) else: - return tuple(key.strip(), None) + return (key.strip(), None) def process_list(l: list) -> (tuple,list): """ From 89f2bf804ea09b1fec00c860ddf79f293984ff69 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Tue, 24 Sep 2024 09:08:13 +1000 Subject: [PATCH 069/161] Improve robustness for timed compartments with 0 duration --- atomica/parameters.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/atomica/parameters.py b/atomica/parameters.py index bdcf39e4..ff08e42c 100644 --- a/atomica/parameters.py +++ b/atomica/parameters.py @@ -299,7 +299,8 @@ def apply(self, pop, framework=None, parset=None) -> None: if (comp.name, pop.name) not in self.values: comp._vals[:, 0] = 0 else: - if len(self.values[(comp.name, pop.name)]) != comp._vals.shape[0]: + vals = self.values[(comp.name, pop.name)] + if (comp._vals.shape[0] > 1 and len(vals) != comp._vals.shape[0]) or (comp._vals.shape[0] == 1 and not np.isscalar(vals)): # If there is a mismatch between the saved initialization duration and the # duration for the current simulation, if the values were all zero it would probably # be safe to assume the values can remain zero. If there are fewer time points in the saved @@ -356,13 +357,13 @@ def from_excel(cls, excelfile: pd.ExcelFile): metadata, value_df = atomica.excel.read_dataframes(excelfile.book['Initialization']) values = {} - for k,s in value_df.T.reset_index().T.set_index([0,1]).iterrows(): + for k, s in value_df.T.reset_index().T.set_index([0, 1]).iterrows(): v = s.dropna().values values[k] = v[0] if len(v) == 1 else v self = cls(values) - for k,v in metadata.T.reset_index().T.set_index(0)[1].to_dict().items(): + for k, v in metadata.T.reset_index().T.set_index(0)[1].to_dict().items(): setattr(self, k, v) return self From 14af4d8476a91abf539b7a00f942a681af8d948d Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Tue, 24 Sep 2024 09:08:36 +1000 Subject: [PATCH 070/161] Update migration version package --- atomica/migration.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atomica/migration.py b/atomica/migration.py index 7c893a48..69b98f65 100644 --- a/atomica/migration.py +++ b/atomica/migration.py @@ -13,7 +13,7 @@ import sys import io -from distutils.version import LooseVersion +from packaging.version import Version from .system import logger from .version import version, gitinfo import sciris as sc @@ -198,7 +198,7 @@ def migrate(obj, registry=migrations, version=version, gitinfo=gitinfo): print("Skipping migration") return obj # If migration is disabled then don't make any changes EXCEPT to add in version and gitinfo which may otherwise be hard to catch - migrations_to_run = sorted(registry[type(obj).__name__], key=lambda m: LooseVersion(m.original_version)) + migrations_to_run = sorted(registry[type(obj).__name__], key=lambda m: Version(m.original_version)) if sc.compareversions(obj.version, version) >= 0: return obj else: From b89c19f61712fb58c5f60813696eece2516a1bfe Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Tue, 24 Sep 2024 18:09:25 +1000 Subject: [PATCH 071/161] Update YAML tests --- azure-pipelines.yml | 24 +----- tests/test_tox_yaml.py | 52 ++++++++++++ tests/test_yaml.py | 83 ------------------- tests/yaml_tests/config_bounds_test.yaml | 4 +- tests/yaml_tests/config_cal_formats.yaml | 20 ++--- tests/yaml_tests/config_caltime_test.yaml | 12 +-- tests/yaml_tests/config_maxtime_test.yaml | 12 +-- .../config_nonexistent_setting_test.yaml | 12 +-- tests/yaml_tests/config_repeats_test.yaml | 12 +-- tests/yaml_tests/config_simtime_test.yaml | 8 +- tests/yaml_tests/config_stepsize_test.yaml | 12 +-- 11 files changed, 99 insertions(+), 152 deletions(-) create mode 100644 tests/test_tox_yaml.py delete mode 100644 tests/test_yaml.py diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 5f41210b..e2bf892e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -39,34 +39,12 @@ jobs: testRunTitle: 'Publish test results for Python $(python.version)' condition: succeededOrFailed() - - task: PublishCodeCoverageResults@1 + - task: PublishCodeCoverageResults@2 inputs: codeCoverageTool: Cobertura summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml' # reportDirectory: '$(System.DefaultWorkingDirectory)/**/htmlcov' -- job: 'flake8' - pool: - vmImage: 'ubuntu-latest' - steps: - - task: UsePythonVersion@0 - displayName: 'Select python version' - inputs: - versionSpec: '3.12' - - script: python -m pip install flake8 flake8-junit-report - displayName: 'Install flake8' - - script: flake8 atomica tests --exit-zero --output-file flake8.txt - # Note - using --exit-zero will cause flake8 'errors' to show up as 'errors' in Azure Pipelines - # but the test will have been considered to pass. Therefore, the overall tests suite will still - # be considered to be passing as long as tox runs, and flake8 errors are just guidance for style - displayName: 'Run flake8' - - script: flake8_junit flake8.txt flake8_junit.xml - displayName: 'Generate flake8 junit output' - - task: PublishTestResults@2 - inputs: - testResultsFiles: '**/flake8_junit.xml' - testRunTitle: 'Publish flake8 results' - - job: 'docs' condition: and(ne(variables['Build.Reason'], 'PullRequest'), ne(variables['Build.Reason'], 'Schedule')) # Skip if it's a PR build or a scheduled build pool: diff --git a/tests/test_tox_yaml.py b/tests/test_tox_yaml.py new file mode 100644 index 00000000..0e19195f --- /dev/null +++ b/tests/test_tox_yaml.py @@ -0,0 +1,52 @@ +# import unittest +import atomica as at +import os +import pytest +import numpy as np +import sciris as sc + +# Basic minimum working product test to verify all yaml features run +testdir = at.parent_dir() +tmpdir = testdir / 'temp' +yaml_dir = testdir/'yaml_tests' + +# List yaml files in directory +yaml_files = list(yaml_dir.glob('*.yaml')) + + +@pytest.fixture() +def project(): + P = at.demo('udt_dyn', do_run=False) + P.settings.update_time_vector(start=2000, end=2050, dt=1/52) + return P + +def test_save_intermediate(project): + project.calibrate(yaml=yaml_files[0], parset=project.make_parset(), quiet=False, savedir=tmpdir/'yaml_save_test', save_intermediate=True, verbose=0, max_time=0.1) + +@pytest.mark.parametrize("yaml_fname", yaml_files, ids=[x.stem for x in yaml_files]) +def test_yaml_calibration(project, yaml_fname): + + # TODO - this demo project has only one population. It would be good + # to have a test with multiple populations and where there is a space in the population name + + print(f"\n\nTESTING yaml config {yaml_fname}") + + # run calibration with yaml instructions + # config_file_path = yaml_dir/yaml_fname + # print(config_file_path) + project.calibrate(yaml=yaml_fname, parset=project.make_parset(), quiet=False, savedir=tmpdir, save_intermediate=False, verbose=0, max_time=0.1) + + #or can import in all the diff ways - make function + #also run in several diff ways? Or have a separate test for that? + + # Test saving the calibration + # save() + + print("Test complete") + + +if __name__ == "__main__": + + np.seterr(all="raise") + for f in yaml_files: + test_yaml_calibration(f) diff --git a/tests/test_yaml.py b/tests/test_yaml.py deleted file mode 100644 index b3346ca2..00000000 --- a/tests/test_yaml.py +++ /dev/null @@ -1,83 +0,0 @@ -# import unittest -import atomica as at -import os -import pytest -import numpy as np -import sciris as sc -import at_tools as att - -# class MyTestCase(unittest.TestCase): -# def test_something(self): -# self.assertEqual(True, False) # add assertion here -# -# -# if __name__ == '__main__': -# unittest.main() - - -# Basic minimum working product test to verify all yaml features run - -testdir = at.parent_dir() -tmpdir = testdir / 'temp' -yaml_dir = 'yaml_tests' - -# List yaml files in directory -yaml_files = list() -for f in os.listdir(testdir/yaml_dir): - yaml_files.append(f) - - -def run_auto_calibration(proj): - """Run an automatic calibration - - :param proj: A Project object - :return: - """ - - proj.calibrate(max_time=10, new_name="auto") - - return - - -# Testing optimizations and calibrations could be expensive -# Using the parametrize decorator means Pytest will treat -# each function call as a separate test, which can be run in parallel -# simply by adding `pytest -n 4` for instance. Or via tox -# `tox -- -o -n 4` (because the default config is to use n=2 for TravisCI) -@pytest.mark.parametrize("yaml_fname", yaml_files) -def test_yaml_calibration(yaml_fname): - - #set these once outside test itself? - fw_ver = '2_8_1' - db_ver = '2_8' - country = 'PAK' - dis = 'typh' - - F = at.ProjectFramework(f"framework_bivalent_combined_v{fw_ver}.xlsx") - D = at.ProjectData.from_spreadsheet(f"databook_bivalent_{country}_v{db_ver}.xlsx", framework=F) - P = at.Project(framework=F, databook=D, do_run=False) - P.settings.update_time_vector(start=2000, end=2050, dt=1/52) - cal = P.make_parset() - - print(f"\n\nTESTING yaml config {yaml_fname}") - - #import yaml config - config_file_path = f'{yaml_dir}/{yaml_fname}' - config = att.ProjectConfig.from_yaml(config_file_path) #TODO change this to not rely on atomica tools? - #or can import in all the diff ways - make function - - #run calibration with yaml instructions - newcal = config.run_calibration(P, parset=cal, quiet=False, savedir=tmpdir, save_intermediate=False, verbose=0, max_time=1) - #also run in several diff ways? Or have a separate test for that? - - # Test saving the calibration - # save() - - print("Test complete") - - -if __name__ == "__main__": - - np.seterr(all="raise") - for f in yaml_files: - test_yaml_calibration(f) diff --git a/tests/yaml_tests/config_bounds_test.yaml b/tests/yaml_tests/config_bounds_test.yaml index 855078f5..13c4a025 100644 --- a/tests/yaml_tests/config_bounds_test.yaml +++ b/tests/yaml_tests/config_bounds_test.yaml @@ -4,8 +4,8 @@ calibration: match population sizes: adjustables: - b_rate, mig_rate: [ 0.1, 10 ] - measurables: alive + b_rate, inf_death: [ 0.1, 10 ] + measurables: all_people turn off epi y-factors: adjustables: diff --git a/tests/yaml_tests/config_cal_formats.yaml b/tests/yaml_tests/config_cal_formats.yaml index 4151f3fe..85eb63f0 100644 --- a/tests/yaml_tests/config_cal_formats.yaml +++ b/tests/yaml_tests/config_cal_formats.yaml @@ -15,10 +15,10 @@ calibration: b_rate: lower_bound: 0.1 upper_bound: 10 - mig_rate: + inf_death: starting_y_factor: 1.2 measurables: - alive: + all_people: metric: fractional #combined format @@ -26,22 +26,22 @@ calibration: version 1: adjustables: b_rate: [ 0.1,10 ] - mig_rate: [ 0.1,10 ] + inf_death: [ 0.1,10 ] measurables: - alive: [1.0] + all_people: [1.0] version 2: adjustables: - b_rate, mig_rate: [ 0.1,10 ] + b_rate, inf_death: [ 0.1,10 ] measurables: - alive: [1.0] + all_people: [1.0] #list format match population sizes 3: - adjustables: [[b_rate, 0.1, 10], [mig_rate, 0.1, 10]] - measurables: [alive] + adjustables: [[b_rate, 0.1, 10], [inf_death, 0.1, 10]] + measurables: [all_people] #string format match population sizes 4: - adjustables: [b_rate, mig_rate] - measurables: alive + adjustables: [b_rate, inf_death] + measurables: all_people diff --git a/tests/yaml_tests/config_caltime_test.yaml b/tests/yaml_tests/config_caltime_test.yaml index ea61d264..deb40fb0 100644 --- a/tests/yaml_tests/config_caltime_test.yaml +++ b/tests/yaml_tests/config_caltime_test.yaml @@ -18,22 +18,22 @@ calibration: cal_end: 2040 match population sizes 1: adjustables: - b_rate,mig_rate: [ 0.1,10 ] - measurables: [alive] + b_rate,inf_death: [ 0.1,10 ] + measurables: [all_people] round 2: match population sizes 2: cal_start: 2000 #is this meant to work? cal_end: 2040 adjustables: - b_rate,mig_rate: [ 0.1,10 ] - measurables: [alive] + b_rate,inf_death: [ 0.1,10 ] + measurables: [all_people] round 3: match population sizes 3: adjustables: - b_rate,mig_rate: [ 0.1,10 ] + b_rate,inf_death: [ 0.1,10 ] measurables: - alive: + all_people: cal_start: 2000 cal_end: 2040 diff --git a/tests/yaml_tests/config_maxtime_test.yaml b/tests/yaml_tests/config_maxtime_test.yaml index 16f1cc8f..95d8f9a8 100644 --- a/tests/yaml_tests/config_maxtime_test.yaml +++ b/tests/yaml_tests/config_maxtime_test.yaml @@ -16,21 +16,21 @@ calibration: max_time: 1 match population sizes 1: adjustables: - b_rate,mig_rate: [ 0.1,10 ] - measurables: [alive] + b_rate,inf_death: [ 0.1,10 ] + measurables: [all_people] round 2: match population sizes 2: max_time: 1 adjustables: - b_rate,mig_rate: [ 0.1,10 ] - measurables: [alive] + b_rate,inf_death: [ 0.1,10 ] + measurables: [all_people] # round 3: # match population sizes 3: # adjustables: -# b_rate,mig_rate: [ 0.1,10 ] +# b_rate,inf_death: [ 0.1,10 ] # b_rate: # cal_start: 2000 #is this meant to work? # cal_end: 2040 -# measurables: [ alive ] +# measurables: [ all_people ] diff --git a/tests/yaml_tests/config_nonexistent_setting_test.yaml b/tests/yaml_tests/config_nonexistent_setting_test.yaml index 00382e70..cd7e6b44 100644 --- a/tests/yaml_tests/config_nonexistent_setting_test.yaml +++ b/tests/yaml_tests/config_nonexistent_setting_test.yaml @@ -13,19 +13,19 @@ calibration: raddish: 3 match population sizes 1: adjustables: - b_rate,mig_rate: [ 0.1,10 ] - measurables: [alive] + b_rate,inf_death: [ 0.1,10 ] + measurables: [all_people] round 2: match population sizes 2: kiwi: 4 adjustables: - b_rate,mig_rate: [ 0.1,10 ] - measurables: [alive] + b_rate,inf_death: [ 0.1,10 ] + measurables: [all_people] # round 3: # match population sizes 3: # adjustables: # stepsize: 0.5 -# b_rate,mig_rate: [ 0.1,10 ] -# measurables: [ alive ] +# b_rate,inf_death: [ 0.1,10 ] +# measurables: [ all_people ] diff --git a/tests/yaml_tests/config_repeats_test.yaml b/tests/yaml_tests/config_repeats_test.yaml index 76f59b5e..dcd60944 100644 --- a/tests/yaml_tests/config_repeats_test.yaml +++ b/tests/yaml_tests/config_repeats_test.yaml @@ -16,21 +16,21 @@ calibration: repeats: 1 match population sizes 1: adjustables: - b_rate,mig_rate: [ 0.1,10 ] - measurables: [alive] + b_rate,inf_death: [ 0.1,10 ] + measurables: [all_people] round 2: match population sizes 2: repeats: 1 #should error? adjustables: - b_rate,mig_rate: [ 0.1,10 ] - measurables: [alive] + b_rate,inf_death: [ 0.1,10 ] + measurables: [all_people] # round 3: # match population sizes 3: # adjustables: -# b_rate,mig_rate: [ 0.1,10 ] +# b_rate,inf_death: [ 0.1,10 ] # b_rate: # cal_start: 2000 #is this meant to work? # cal_end: 2040 -# measurables: [ alive ] +# measurables: [ all_people ] diff --git a/tests/yaml_tests/config_simtime_test.yaml b/tests/yaml_tests/config_simtime_test.yaml index a3f13b1c..2800f5e4 100644 --- a/tests/yaml_tests/config_simtime_test.yaml +++ b/tests/yaml_tests/config_simtime_test.yaml @@ -18,13 +18,13 @@ calibration: sim_end: 2040 match population sizes 1: adjustables: - b_rate,mig_rate: [ 0.1,10 ] - measurables: [alive] + b_rate,inf_death: [ 0.1,10 ] + measurables: [all_people] round 2: match population sizes 2: sim_start: 2000 #is this meant to work? sim_end: 2040 adjustables: - b_rate,mig_rate: [ 0.1,10 ] - measurables: [alive] + b_rate,inf_death: [ 0.1,10 ] + measurables: [all_people] diff --git a/tests/yaml_tests/config_stepsize_test.yaml b/tests/yaml_tests/config_stepsize_test.yaml index 40a1f91b..d94db8f3 100644 --- a/tests/yaml_tests/config_stepsize_test.yaml +++ b/tests/yaml_tests/config_stepsize_test.yaml @@ -14,19 +14,19 @@ calibration: stepsize: 0.5 match population sizes 1: adjustables: - b_rate,mig_rate: [ 0.1,10 ] - measurables: [alive] + b_rate,inf_death: [ 0.1,10 ] + measurables: [all_people] round 2: match population sizes 2: stepsize: 0.5 adjustables: - b_rate,mig_rate: [ 0.1,10 ] - measurables: [alive] + b_rate,inf_death: [ 0.1,10 ] + measurables: [all_people] # round 3: # match population sizes 3: # adjustables: # stepsize: 0.5 -# b_rate,mig_rate: [ 0.1,10 ] -# measurables: [ alive ] +# b_rate,inf_death: [ 0.1,10 ] +# measurables: [ all_people ] From dc2a70237e9e427b6aa65698bc0afacd48e2086c Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 25 Sep 2024 14:54:47 +1000 Subject: [PATCH 072/161] Change aggregation logic for characteristics --- atomica/plotting.py | 98 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 21 deletions(-) diff --git a/atomica/plotting.py b/atomica/plotting.py index 9529ab8d..84f8bc50 100644 --- a/atomica/plotting.py +++ b/atomica/plotting.py @@ -139,20 +139,36 @@ class PlotData: :param output_aggregation: If an output aggregation is requested, combine the outputs listed using one of - - 'sum' - just add values together - - 'average' - unweighted average of quantities + - 'sum' - just add values together. If summing together characteristics with a denominator, then + all of the items being included in the sum must have the same denominator. This denominator + will then continue to be tracked for the sum. + - 'average' - unweighted average of quantities. If averaging characteristics with a denominator, then + the denominator will be dropped afterwards (so subsequent population aggregation - 'weighted' - weighted average where the weight is the - compartment size, characteristic value, or link source - compartment size (summed over duplicate links). 'weighted' - method cannot be used with non-transition parameters and a - KeyError will result in that case - - :param pop_aggregation: Same as output_aggregation, except that 'weighted' - uses population sizes. Note that output aggregation is performed - before population aggregation. This also means that population - aggregation can be used to combine already aggregated outputs (e.g. - can first sum 'sus'+'vac' within populations, and then take weighted - average across populations) + - Link source compartment size, or + - Characteristic denominator size, or + - Compartment size + depending on the quantities being aggregated. If one quantity has a denominator, then + all quantities must have denominators. This method cannot be used with non-transition parameters and a + KeyError will result in that case. Note that if using this method to aggregate characteristics, there + should generally not be any overlap in the compartments contributing to the denominators. + + For aggregating characteristics, the behaviour for combining characteristics ``a/b`` and ``c/d`` is as follows: + + - 'sum' will give ``(a+c)/b`` and raise an error if ``b!=d``. The denominator ``b`` can be used for weighted population aggregation. + - 'average' will give ``((a/b)+(c/d))/2``. No denominator is tracked for weighted population aggregation, so such aggregation would use the total population size. + - 'weighted' will give ``(a+c)/(b+d)``. The denominator ``b+d`` can be used for weighted population aggregation. + + The default is 'average' for dimensionless units, probabilities, rates etc. and 'sum' for everything else, with the exception of characteristics + with denominators, where 'sum' is used by default. + + :param pop_aggregation: Same options as output_aggregation, except that 'weighted' + uses population sizes OR characteristic denominator size. Note that output aggregation + is performed before population aggregation. This also means that population + aggregation can be used to combine already aggregated outputs (e.g. + can first sum 'sus'+'vac' within populations, and then take weighted + average across populations). This weighting is principally intended for aggregating + nondimensional quantities (fractions, proportions etc.). :param project: Optionally provide a :class:`Project` object, which will be used to convert names to labels in the outputs for plotting. @@ -221,9 +237,11 @@ def __init__(self, results, outputs=None, pops=None, output_aggregation=None, po aggregated_outputs = defaultdict(dict) # Dict with aggregated_outputs[pop_label][aggregated_output_label] aggregated_units = dict() # Dict with aggregated_units[aggregated_output_label] aggregated_timescales = dict() + aggregated_denominators = defaultdict(dict) # Store aggregated denominators where available at the same dimensionality as outputs output_units = dict() output_timescales = dict() compsize = dict() + denomsize = dict() # Characteristic denominator size popsize = dict() # Defaultdict won't throw key error when checking outputs. data_label = defaultdict(str) # Label used to identify which data to plot, maps output label to data label. @@ -280,7 +298,8 @@ def __init__(self, results, outputs=None, pops=None, output_aggregation=None, po output_units[output_label] = vars[0].units output_timescales[output_label] = None data_label[output_label] = vars[0].name - + if isinstance(vars[0], Characteristic) and vars[0].denominator is not None: + denomsize[output_label] = vars[0].denominator.vals else: raise Exception("Unknown type") @@ -328,14 +347,20 @@ def placeholder_pop(): aggregated_outputs[pop_label][output_name] = data_dict[output_name] aggregated_units[output_name] = "unknown" # Also, we don't know what the units of a function are aggregated_timescales[output_name] = None # Timescale is lost + aggregated_denominators[pop_label][output_name] = None # Denominators are not tracked continue units = list(set([output_units[x] for x in labels])) timescales = list(set([np.nan if isna(output_timescales[x]) else output_timescales[x] for x in labels])) # Ensure that None and nan don't appear as different timescales + # Set default aggregation method depending on the units of the quantity if output_aggregation is None: - if units[0] in ["", FS.QUANTITY_TYPE_FRACTION, FS.QUANTITY_TYPE_PROPORTION, FS.QUANTITY_TYPE_PROBABILITY, FS.QUANTITY_TYPE_RATE]: + if labels[0] in denomsize: + # We are aggregating characteristics with denominators, so we want to aggregate with summation + # on the assumption that all of the characteristics being aggregated have the same denominator + output_aggregation = "sum" + elif units[0] in ["", FS.QUANTITY_TYPE_FRACTION, FS.QUANTITY_TYPE_PROPORTION, FS.QUANTITY_TYPE_PROBABILITY, FS.QUANTITY_TYPE_RATE]: output_aggregation = "average" else: output_aggregation = "sum" @@ -344,7 +369,7 @@ def placeholder_pop(): logger.warning("Aggregation for output '%s' is mixing units, this is almost certainly not desired.", output_name) aggregated_units[output_name] = "unknown" else: - if units[0] in ["", FS.QUANTITY_TYPE_FRACTION, FS.QUANTITY_TYPE_PROPORTION, FS.QUANTITY_TYPE_PROBABILITY, FS.QUANTITY_TYPE_RATE] and output_aggregation == "sum" and len(labels) > 1: # Dimensionless, like prevalance + if units[0] in ["", FS.QUANTITY_TYPE_FRACTION, FS.QUANTITY_TYPE_PROPORTION, FS.QUANTITY_TYPE_PROBABILITY, FS.QUANTITY_TYPE_RATE] and output_aggregation == "sum" and len(labels) > 1 and not labels[0] in denomsize: # Dimensionless, like prevalance logger.warning("Output '%s' is not in number units, so output aggregation probably should not be 'sum'.", output_name) aggregated_units[output_name] = output_units[labels[0]] @@ -356,16 +381,43 @@ def placeholder_pop(): if output_aggregation == "sum": aggregated_outputs[pop_label][output_name] = sum(data_dict[x] for x in labels) # Add together all the outputs + + # If summing characteristics that have denominators, then all quantities should have denominators, and they should all be equal + # For example, summing SP-TB and SN-TB prevalance where they both have the 'alive' denominator + has_denominator = [x in denomsize for x in labels] + assert all(has_denominator) or not any(has_denominator) # An output aggregation must either have no quantities with denominators, or only contain quantities with denominators + if all(has_denominator): + for label in labels: + assert np.all(denomsize[label] == denomsize[labels[0]]), 'When aggregating characteristics with denominators, if summing them (default) then all quantities must have the same denominator. The "weighted" aggregation can be used to combine characteristics with different denominators, on the assumption that their denominators do not overlap.' + aggregated_denominators[pop_label][output_name] = denomsize[labels[0]] + elif not any(has_denominator): + aggregated_denominators[pop_label][output_name] = None + else: + raise Exception(f"When aggregating outputs, if any quantities being aggregated have denominators, then they must all have denominators. These quantities have denominators {[x for x in labels if x in denomsize]} while these do not {[x for x in labels if x not in denomsize]}") + elif output_aggregation == "average": - aggregated_outputs[pop_label][output_name] = sum(data_dict[x] for x in labels) # Add together all the outputs + aggregated_outputs[pop_label][output_name] = sum(data_dict[x] for x in labels) aggregated_outputs[pop_label][output_name] /= len(labels) + aggregated_denominators[pop_label][output_name] = None # If taking a direct average then drop the denominator elif output_aggregation == "weighted": - aggregated_outputs[pop_label][output_name] = sum(data_dict[x] * compsize[x] for x in labels) # Add together all the outputs - aggregated_outputs[pop_label][output_name] /= sum([compsize[x] for x in labels]) + has_denominator = [x in denomsize for x in labels] + assert all(has_denominator) or not any(has_denominator) # An output aggregation must either have no quantities with denominators, or only contain quantities with denominators + if all(has_denominator): + # Take weighted average based on denominator size, and then store the combined denominator further population aggregation + aggregated_outputs[pop_label][output_name] = sum(data_dict[x] * denomsize[x] for x in labels) + aggregated_denominators[pop_label][output_name] = sum([denomsize[x] for x in labels]) + aggregated_outputs[pop_label][output_name] /= aggregated_denominators[pop_label][output_name] + elif not any(has_denominator): + aggregated_outputs[pop_label][output_name] = sum(data_dict[x] * compsize[x] for x in labels) + aggregated_outputs[pop_label][output_name] /= sum([compsize[x] for x in labels]) + aggregated_denominators[pop_label][output_name] = None # If taking a direct average then drop the denominator + else: + raise Exception(f"When aggregating outputs, if any quantities being aggregated have denominators, then they must all have denominators. These quantities have denominators {[x for x in labels if x in denomsize]} while these do not {[x for x in labels if x not in denomsize]}") else: aggregated_outputs[pop_label][output] = data_dict[output] aggregated_units[output] = output_units[output] aggregated_timescales[output] = output_timescales[output] + aggregated_denominators[pop_label][output] = denomsize.get(output) # Now aggregate over populations # If we have requested a reduction over populations, this is done for every output present @@ -390,8 +442,12 @@ def placeholder_pop(): vals = sum(aggregated_outputs[x][output_name] for x in pop_labels) # Add together all the outputs vals /= len(pop_labels) elif pop_aggregation == "weighted": - numerator = sum(aggregated_outputs[x][output_name] * popsize[x] for x in pop_labels) # Add together all the outputs - denominator = sum([popsize[x] for x in pop_labels]) + if aggregated_denominators[pop_labels[0]][output_name] is not None: + weights = {x:aggregated_denominators[x][output_name] for x in pop_labels} + else: + weights = {x:popsize[x] for x in pop_labels} + numerator = sum(aggregated_outputs[x][output_name] * weights[x] for x in pop_labels) # Add together all the outputs + denominator = sum([weights[x] for x in pop_labels]) vals = np.divide(numerator, denominator, out=np.full(numerator.shape, np.nan, dtype=float), where=numerator != 0) else: raise Exception("Unknown pop aggregation method") From 194d85ae05428019da88eea33277a2666d9ac017 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 25 Sep 2024 15:03:33 +1000 Subject: [PATCH 073/161] Update default for characteristics --- atomica/plotting.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/atomica/plotting.py b/atomica/plotting.py index 84f8bc50..f8ee3f28 100644 --- a/atomica/plotting.py +++ b/atomica/plotting.py @@ -427,9 +427,12 @@ def placeholder_pop(): pop_name = list(pop.keys())[0] pop_labels = pop[pop_name] - # Set population aggregation method depending on + # Set population aggregation method depending on the quantity being aggregated if pop_aggregation is None: - if aggregated_units[output_name] in ["", FS.QUANTITY_TYPE_FRACTION, FS.QUANTITY_TYPE_PROPORTION, FS.QUANTITY_TYPE_PROBABILITY, FS.QUANTITY_TYPE_RATE]: + if aggregated_denominators[pop_labels[0]][output_name] is not None: + # Outputs with denominators use these for a weighted average by default + pop_aggregation = "weighted" + elif aggregated_units[output_name] in ["", FS.QUANTITY_TYPE_FRACTION, FS.QUANTITY_TYPE_PROPORTION, FS.QUANTITY_TYPE_PROBABILITY, FS.QUANTITY_TYPE_RATE]: pop_aggregation = "average" else: pop_aggregation = "sum" From 7eb03e6fe83a6f173e03d0ff7863e18f71b38963 Mon Sep 17 00:00:00 2001 From: alina-muellenmeister Date: Thu, 3 Oct 2024 16:40:55 +1000 Subject: [PATCH 074/161] add a devtest to check numerical precision of time vector --- tests/test_time_vector.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 tests/test_time_vector.py diff --git a/tests/test_time_vector.py b/tests/test_time_vector.py new file mode 100644 index 00000000..f8cc04f4 --- /dev/null +++ b/tests/test_time_vector.py @@ -0,0 +1,33 @@ +# Test time vector +# The problem: +# In atomica, we want to include the end year: Say we're running a simulation from 2000 to 2050 -> +# we want to be able to get the results for year 2000, 2001, ... and 2050. Hence, we need to run +# more time steps after 2050 + +# # On develop branch: Creates 611 entries -> if taken the integer,the last year doesn't have enough entries +# On temporal weights: Creates 612 entries -> but 13 in 2038 and 11 in 2048 + +import atomica as at +import numpy as np + + +def test_time_vector(): + # Creating a setting object + analysis_years = (2000, 2050) + dt = 1 / 12 + settings = at.ProjectSettings(sim_start=analysis_years[0], sim_end=analysis_years[1] + 1 - dt, sim_dt=dt) #: Atomica project settings + tvec = settings.tvec #: Simulation/result time points + + assert len(set(np.unique(tvec.astype(int), return_counts=True)[1])) == 1 + + # on temporal weights branch: np.linspace(self.sim_start, self.sim_end, int(np.float32(((self.sim_end - self.sim_start) / self.sim_dt))) + 1) + # tvec = np.linspace(2000, 2051-1/12, int(np.float32(((2051-1/12 - 2000) / (1/12)))) + 1) + + # on develop branch: np.linspace(self.sim_start, self.sim_end, int((self.sim_end - self.sim_start) / self.sim_dt) + 1) + # develop: tvec = np.linspace(2000, 2051-1/12, int((2051-1/12 - 2000) / (1/12)) + 1) + # np.unique(tvec.astype(int), return_counts=True) + + + +if __name__ == "__main__": + test_time_vector() \ No newline at end of file From 86950e51675569e59a7a900dc226a87c7629ef44 Mon Sep 17 00:00:00 2001 From: alina-muellenmeister Date: Thu, 3 Oct 2024 16:41:25 +1000 Subject: [PATCH 075/161] specify dtype in np.linspace --- atomica/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/project.py b/atomica/project.py index 2ab71bb0..b7256485 100644 --- a/atomica/project.py +++ b/atomica/project.py @@ -98,7 +98,7 @@ def tvec(self) -> np.ndarray: # running a model over the range [2000,2066) with dt=1/12, it calculates 791.9999999999982 time steps # rather than 792, in that case we can convert to a float32 to effectively round it to 792 before # taking the integer. This should generally be safe for the types of values that get used for simulation years - return np.linspace(self.sim_start, self.sim_end, int(np.float32(((self.sim_end - self.sim_start) / self.sim_dt))) + 1) + return np.linspace(self.sim_start, self.sim_end, int(np.float32(((self.sim_end - self.sim_start) / self.sim_dt))) + 1, dtype='float32') def update_time_vector(self, start: float = None, end: float = None, dt: float = None) -> None: """ From e7a8d4d6ff63b1bb65e39178893e48b8d23316b3 Mon Sep 17 00:00:00 2001 From: alina-muellenmeister Date: Fri, 4 Oct 2024 15:34:37 +1000 Subject: [PATCH 076/161] clean up dev test --- tests/test_time_vector.py | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/tests/test_time_vector.py b/tests/test_time_vector.py index f8cc04f4..27d5c969 100644 --- a/tests/test_time_vector.py +++ b/tests/test_time_vector.py @@ -2,32 +2,24 @@ # The problem: # In atomica, we want to include the end year: Say we're running a simulation from 2000 to 2050 -> # we want to be able to get the results for year 2000, 2001, ... and 2050. Hence, we need to run -# more time steps after 2050 +# more time steps after 2050, in particular up to 2051-1/12 -# # On develop branch: Creates 611 entries -> if taken the integer,the last year doesn't have enough entries -# On temporal weights: Creates 612 entries -> but 13 in 2038 and 11 in 2048 +# Currently, at.ProjectSettings.tvec creates 611 entries -> if taken the integer,the last year doesn't have enough entries import atomica as at import numpy as np +import pandas as pd def test_time_vector(): + # Test 1 # Creating a setting object analysis_years = (2000, 2050) dt = 1 / 12 settings = at.ProjectSettings(sim_start=analysis_years[0], sim_end=analysis_years[1] + 1 - dt, sim_dt=dt) #: Atomica project settings tvec = settings.tvec #: Simulation/result time points - - assert len(set(np.unique(tvec.astype(int), return_counts=True)[1])) == 1 - - # on temporal weights branch: np.linspace(self.sim_start, self.sim_end, int(np.float32(((self.sim_end - self.sim_start) / self.sim_dt))) + 1) - # tvec = np.linspace(2000, 2051-1/12, int(np.float32(((2051-1/12 - 2000) / (1/12)))) + 1) - - # on develop branch: np.linspace(self.sim_start, self.sim_end, int((self.sim_end - self.sim_start) / self.sim_dt) + 1) - # develop: tvec = np.linspace(2000, 2051-1/12, int((2051-1/12 - 2000) / (1/12)) + 1) - # np.unique(tvec.astype(int), return_counts=True) - + assert len(set(np.unique(tvec.astype(int), return_counts=True)[1])) == 1 # or pd.Series(tvec).astype(int).value_counts() if __name__ == "__main__": - test_time_vector() \ No newline at end of file + test_time_vector() From ab3e4eacaf4ddcd53a13adff4e66737ab9282952 Mon Sep 17 00:00:00 2001 From: alina-muellenmeister Date: Fri, 4 Oct 2024 15:37:39 +1000 Subject: [PATCH 077/161] update assert --- tests/test_time_vector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_time_vector.py b/tests/test_time_vector.py index 27d5c969..652445cb 100644 --- a/tests/test_time_vector.py +++ b/tests/test_time_vector.py @@ -18,7 +18,7 @@ def test_time_vector(): dt = 1 / 12 settings = at.ProjectSettings(sim_start=analysis_years[0], sim_end=analysis_years[1] + 1 - dt, sim_dt=dt) #: Atomica project settings tvec = settings.tvec #: Simulation/result time points - assert len(set(np.unique(tvec.astype(int), return_counts=True)[1])) == 1 # or pd.Series(tvec).astype(int).value_counts() + assert set(np.unique(tvec.astype(int), return_counts=True)[1]) == {1/dt} # or pd.Series(tvec).astype(int).value_counts() if __name__ == "__main__": From 8af5553a3e2468d36662122fe60f11be1a7ed930 Mon Sep 17 00:00:00 2001 From: alina-muellenmeister Date: Fri, 4 Oct 2024 15:38:44 +1000 Subject: [PATCH 078/161] following Kelvin's suggestion: Updating to np.arange(), multiply by step size and add add sim start --- atomica/project.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/atomica/project.py b/atomica/project.py index b7256485..2dda2c1a 100644 --- a/atomica/project.py +++ b/atomica/project.py @@ -88,17 +88,13 @@ def tvec(self) -> np.ndarray: """ Return simulation time vector - This method uses `linspace` rather than `arange` to avoid accumulating numerical errors that prevent - integer years aligning exactly. + This method uses `arange` with a step size of 1, then multiplies with the correct step size and add sim start time. :return: Array of simulation times """ - # The int(np.float32()) helps cases where the numerical precision results in unwanted truncation e.g., - # running a model over the range [2000,2066) with dt=1/12, it calculates 791.9999999999982 time steps - # rather than 792, in that case we can convert to a float32 to effectively round it to 792 before - # taking the integer. This should generally be safe for the types of values that get used for simulation years - return np.linspace(self.sim_start, self.sim_end, int(np.float32(((self.sim_end - self.sim_start) / self.sim_dt))) + 1, dtype='float32') + + return np.arange(round((self.sim_end - self.sim_start) / self.sim_dt) + 1) * self.sim_dt + self.sim_start def update_time_vector(self, start: float = None, end: float = None, dt: float = None) -> None: """ From 10ade850d8559f9097bea2fad1b147e2ddf75504 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Tue, 15 Oct 2024 06:25:20 +1000 Subject: [PATCH 079/161] Make timed compartment size check more robust --- atomica/parameters.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/atomica/parameters.py b/atomica/parameters.py index ff08e42c..d3fc6f65 100644 --- a/atomica/parameters.py +++ b/atomica/parameters.py @@ -299,17 +299,17 @@ def apply(self, pop, framework=None, parset=None) -> None: if (comp.name, pop.name) not in self.values: comp._vals[:, 0] = 0 else: - vals = self.values[(comp.name, pop.name)] - if (comp._vals.shape[0] > 1 and len(vals) != comp._vals.shape[0]) or (comp._vals.shape[0] == 1 and not np.isscalar(vals)): - # If there is a mismatch between the saved initialization duration and the - # duration for the current simulation, if the values were all zero it would probably - # be safe to assume the values can remain zero. If there are fewer time points in the saved - # initialization we *could* insert them, however, there is a risk that the time points are different - # because the step size was changed rather than the duration being changed, so it would not be valid - # to do that. Therefore, if the sizes don't match and any values are nonzero, simply raise an error + vals = sc.promotetoarray(self.values[(comp.name, pop.name)]) + if comp._vals.shape[0] != vals.shape[0]: if np.all(self.values[(comp.name, pop.name)] == 0): + # If there is a mismatch between the saved initialization duration and the + # duration for the current simulation AND if the values were all zero it is probably + # safe to assume the values can remain zero - this considerably increases flexibility in usage comp._vals[:, 0] = 0 else: + # Otherwise, although we could try and guess how to assign the values, there is a risk that the time points + # are different because the step size was changed rather than the duration being changed. Therefore, + # if the sizes don't match and any values are nonzero, simply raise an error raise Exception(f'The saved initialization for "{comp.name}" ({pop.name}) has {len(self.values[(comp.name, pop.name)])} time points, but the current parameters lead to a timed compartment duration with {comp._vals.shape[0]} time points. As nonzero values are present, the initialization cannot be applied.') else: comp._vals[:, 0] = self.values[(comp.name, pop.name)] From 7acb21375583d61ec6aa714ffd51875eb184eae5 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 16 Oct 2024 10:28:14 +1000 Subject: [PATCH 080/161] Fix array length in time aggregation using Kelvin's approach --- atomica/plotting.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/atomica/plotting.py b/atomica/plotting.py index 1aa1708f..9604fe37 100644 --- a/atomica/plotting.py +++ b/atomica/plotting.py @@ -546,8 +546,7 @@ def time_aggregate(self, t_bins, time_aggregation=None, interpolation_method=Non max_step = 0.5 * min(np.diff(s.tvec)) # Subdivide for trapezoidal integration with at least 2 divisions per timestep. Could be a lot of memory for integrating daily timesteps over a full simulation, but unlikely to be prohibitive vals = np.full(lower.shape, fill_value=np.nan) for i, (l, u) in enumerate(zip(lower, upper)): - n = np.ceil((u - l) / max_step) + 1 # Add 1 so that in most cases, we can use the actual timestep values - t2 = np.linspace(l, u, int(n)) + t2 = np.arange(round((u - l) / max_step) + 1) * max_step + l if interpolation_method == "linear": v2 = np.interp(t2, s.tvec, s.vals, left=np.nan, right=np.nan) # Return NaN outside bounds - it should never be valid to use extrapolated output values in time aggregation vals[i] = np.trapz(y=v2 / scale, x=t2) # Note division by timescale here, which annualizes it From 641bc7cc2fbf85d12d6850beb17fdd24eca06880 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 16 Oct 2024 11:47:04 +1000 Subject: [PATCH 081/161] Use exact time points when within numerical tolerance --- atomica/plotting.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/atomica/plotting.py b/atomica/plotting.py index 9604fe37..5ad7c0df 100644 --- a/atomica/plotting.py +++ b/atomica/plotting.py @@ -547,6 +547,16 @@ def time_aggregate(self, t_bins, time_aggregation=None, interpolation_method=Non vals = np.full(lower.shape, fill_value=np.nan) for i, (l, u) in enumerate(zip(lower, upper)): t2 = np.arange(round((u - l) / max_step) + 1) * max_step + l + # Numerical precision issues can cause the wrong bin to be used. This is particularly noticable for 'previous' + # e.g., if the interpolated finer bins have 2025.9999999 instead of 2026 causing the 2025 value to be + # used instead, this can cause a significant overestimation if the value is changing rapidly. Therefore + # we need to perform an extra step of using the exact bin values within some tolerance. The values are on + # the order of 0.002 (1 day, in years) so the default np.isclose() should be sufficient. However, we may want to apply this + # to linear interpolation as well because if the bin falls numerically *outside* the bounds, it will be extrapolated + # as NaN which we wouldn't want + nearest = np.searchsorted(s.tvec, t2, side='left') + isclose = np.isclose(s.tvec[nearest], t2) + t2[isclose] = s.tvec[nearest[isclose]] if interpolation_method == "linear": v2 = np.interp(t2, s.tvec, s.vals, left=np.nan, right=np.nan) # Return NaN outside bounds - it should never be valid to use extrapolated output values in time aggregation vals[i] = np.trapz(y=v2 / scale, x=t2) # Note division by timescale here, which annualizes it From b5d0bc712d15b4a890e0381a84519be12817de9a Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Fri, 18 Oct 2024 16:22:29 +1000 Subject: [PATCH 082/161] Add missing test framework --- tests/timed_initialization_test_framework.xlsx | Bin 0 -> 37023 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/timed_initialization_test_framework.xlsx diff --git a/tests/timed_initialization_test_framework.xlsx b/tests/timed_initialization_test_framework.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..796297da42684835cdbca268e78ffe57f9faa914 GIT binary patch literal 37023 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 W;&9+pFi=oW!7T^utIYfTy!#)mpJ@yL literal 0 HcmV?d00001 From b842bb681aaa036217ce9b5c86b799648d69f598 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Tue, 29 Oct 2024 09:40:15 +1000 Subject: [PATCH 083/161] WIP --- CHANGELOG.md | 12 ++++++++++++ atomica/plotting.py | 19 ++++++++++++++++--- atomica/version.py | 4 ++-- tests/test_tox_library.py | 2 +- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 935876aa..13195598 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ This file records changes to the codebase grouped by version release. Unreleased changes are generally only present during development (relevant parts of the changelog can be written and saved in that section before a version number has been assigned) + + +## [1.28.7] - 2023-10-29 + +- If aggregating characteristics with a denominator, weighted aggregations use the denominator of the quantity rather than the total population size to perform the weighting. This can be useful for quantities that are proportions of things other than the population size e.g., proportion of active infections that are diagnosed +- If aggregating characteristics with a denominator, weighted aggregation will be used by default (rather than 'average') + +*Backwards-compatibility notes* + +- Results obtained when aggregating characteristics with a denominator using the 'weighted' method will change. To reproduce the previous results, it is necessary to perform the population size weighting manually by removing the aggregation, then extracting the population sizes, and using those to aggregate the outputs. This is considered to be a rare use case because the updated result is a more useful weighting compared to the previous result. +- Results obtained when aggregating characteristics with a denominator _without_ explicitly specifying a method will change, because 'weighted' aggregation is now used by default. + ## [1.28.7] - 2023-08-12 - `Project.load_databook()` will no longer populate `Project.databook` when a `ProjectData` instance is supplied rather than a spreadsheet. The intention of `Project.databook` as opposed to `Project.data.to_spreadsheet()` is that the original databook may contain comments or other content that is not preserved when the databook is loaded into a `ProjectData` instance. Therefore, `Project.databook` serves as a record of the original inputs. However, in previous versions of Atomica, if a `ProjectData` instance was provided rather than a spreadsheet, `ProjectData.to_spreadsheet()` would be used to populate `Project.databook`. For large databooks, this can be computationally expensive and particularly affect the use case of passing in a preloaded databook to improve performance. Since the conversion of the `ProjectData` to a spreadsheet upon loading offers no functional difference to creating the spreadsheet from `Project.data` when required, Atomica no longer performs this conversion upfront. diff --git a/atomica/plotting.py b/atomica/plotting.py index f8ee3f28..1f9ce1a1 100644 --- a/atomica/plotting.py +++ b/atomica/plotting.py @@ -353,24 +353,37 @@ def placeholder_pop(): units = list(set([output_units[x] for x in labels])) timescales = list(set([np.nan if isna(output_timescales[x]) else output_timescales[x] for x in labels])) # Ensure that None and nan don't appear as different timescales + # Define default aggregation methods + default_aggregations = { + FS.QUANTITY_TYPE_FRACTION: 'average', + FS.QUANTITY_TYPE_PROPORTION: 'average', + FS.QUANTITY_TYPE_PROBABILITY: 'average', + FS.QUANTITY_TYPE_RATE: 'average', + FS.QUANTITY_TYPE_NUMBER: 'sum', + FS.QUANTITY_TYPE_DURATION: 'sum' + } # Set default aggregation method depending on the units of the quantity if output_aggregation is None: if labels[0] in denomsize: + # If aggregating characteristics with denominators, then we want to use # We are aggregating characteristics with denominators, so we want to aggregate with summation # on the assumption that all of the characteristics being aggregated have the same denominator output_aggregation = "sum" elif units[0] in ["", FS.QUANTITY_TYPE_FRACTION, FS.QUANTITY_TYPE_PROPORTION, FS.QUANTITY_TYPE_PROBABILITY, FS.QUANTITY_TYPE_RATE]: output_aggregation = "average" - else: + elif units[0] in [FS.QUANTITY_TYPE_NUMBER, FS.QUANTITY_TYPE_DURATION]: output_aggregation = "sum" + else: + logger.warning(f'Unit quantity "{units[0]}" was not recognized and an output aggregation method was not specified, using "sum" by default') + if len(units) > 1: logger.warning("Aggregation for output '%s' is mixing units, this is almost certainly not desired.", output_name) aggregated_units[output_name] = "unknown" else: - if units[0] in ["", FS.QUANTITY_TYPE_FRACTION, FS.QUANTITY_TYPE_PROPORTION, FS.QUANTITY_TYPE_PROBABILITY, FS.QUANTITY_TYPE_RATE] and output_aggregation == "sum" and len(labels) > 1 and not labels[0] in denomsize: # Dimensionless, like prevalance - logger.warning("Output '%s' is not in number units, so output aggregation probably should not be 'sum'.", output_name) + if units[0] in AVG_UNITS and output_aggregation == "sum" and len(labels) > 1 and not labels[0] in denomsize: # Dimensionless, like prevalance + logger.warning(f"Output '{output_name}' is in '{units[0]}' units, so output aggregation probably should not be 'sum'.") aggregated_units[output_name] = output_units[labels[0]] if len(timescales) > 1: diff --git a/atomica/version.py b/atomica/version.py index 9955dee6..fd17c0ff 100644 --- a/atomica/version.py +++ b/atomica/version.py @@ -6,6 +6,6 @@ import sciris as sc -version = "1.28.7" -versiondate = "2024-08-30" +version = "1.28.8" +versiondate = "2024-10-29" gitinfo = sc.gitinfo(__file__) diff --git a/tests/test_tox_library.py b/tests/test_tox_library.py index 704742dc..f9c78d57 100644 --- a/tests/test_tox_library.py +++ b/tests/test_tox_library.py @@ -239,6 +239,6 @@ def test_model(model): if __name__ == "__main__": np.seterr(all="raise") - # models = ['tb'] + models = ['combined'] for m in models: test_model(m) From 863d8df013339160609dbd6d1264fc40c3d043e7 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 30 Oct 2024 15:37:05 +1000 Subject: [PATCH 084/161] Update default aggregation method and selection of default method --- CHANGELOG.md | 5 +- atomica/__init__.py | 4 + atomica/calibration.py | 6 +- atomica/migration.py | 3 +- atomica/model.py | 1 - atomica/parameters.py | 8 +- atomica/plotting.py | 181 +++++++++++++++---------- docs/examples/Plot-Units.ipynb | 2 +- docs/examples/Plotting.ipynb | 95 ++++++++++--- tests/README.md | 2 +- tests/test_api_workflow.py | 2 +- tests/test_ensemble_parallel.py | 2 +- tests/test_horizontal_bars.py | 2 +- tests/test_tox_bad_frameworks.py | 2 +- tests/test_tox_calibration.py | 2 +- tests/test_tox_cascade.py | 2 +- tests/test_tox_combined.py | 4 +- tests/test_tox_databooks.py | 2 +- tests/test_tox_derivative.py | 2 +- tests/test_tox_docgen.py | 2 +- tests/test_tox_ensemble_cascade.py | 2 +- tests/test_tox_extra.py | 2 +- tests/test_tox_frameworks.py | 2 +- tests/test_tox_indirect_programs.py | 2 +- tests/test_tox_junctions.py | 2 +- tests/test_tox_library.py | 4 +- tests/test_tox_logging.py | 2 +- tests/test_tox_migration.py | 2 +- tests/test_tox_no_compartments.py | 2 +- tests/test_tox_no_initialization.py | 2 +- tests/test_tox_progbooks.py | 2 +- tests/test_tox_program_calculation.py | 2 +- tests/test_tox_reconciliation.py | 2 +- tests/test_tox_results.py | 2 +- tests/test_tox_save.py | 2 +- tests/test_tox_seasonal.py | 2 +- tests/test_tox_shortcut_init.py | 2 +- tests/test_tox_stochastic.py | 2 +- tests/test_tox_table_parsing.py | 2 +- tests/test_tox_timed_compartments.py | 2 +- tests/text_tox_timed_initialization.py | 31 +++-- tests/validate_integration.py | 2 +- 42 files changed, 255 insertions(+), 149 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13195598..fb24bb9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,13 @@ This file records changes to the codebase grouped by version release. Unreleased changes are generally only present during development (relevant parts of the changelog can be written and saved in that section before a version number has been assigned) - - ## [1.28.7] - 2023-10-29 - If aggregating characteristics with a denominator, weighted aggregations use the denominator of the quantity rather than the total population size to perform the weighting. This can be useful for quantities that are proportions of things other than the population size e.g., proportion of active infections that are diagnosed - If aggregating characteristics with a denominator, weighted aggregation will be used by default (rather than 'average') +- Output aggregation of durations now uses 'sum' instead of 'average' by default +- If no aggregation method is specified, the aggregation method will now be selected separately for each output +- Population aggregation of non-number units now uses 'weighted' by default rather than 'average' *Backwards-compatibility notes* diff --git a/atomica/__init__.py b/atomica/__init__.py index fa6a254f..0ba03568 100644 --- a/atomica/__init__.py +++ b/atomica/__init__.py @@ -95,3 +95,7 @@ from .scenarios import * from .system import * from .utils import * + +import pathlib + +rootdir = pathlib.Path(__file__).parent.parent diff --git a/atomica/calibration.py b/atomica/calibration.py index a8066683..d9ba1d63 100644 --- a/atomica/calibration.py +++ b/atomica/calibration.py @@ -67,8 +67,8 @@ def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, p if not target.has_time_data: # Only use this output quantity if the user entered time-specific data continue - if pop_name.lower() == 'total': - var = atomica.PlotData(result, outputs=var_label, pops = 'total', project=project) + if pop_name.lower() == "total": + var = atomica.PlotData(result, outputs=var_label, pops="total", project=project) else: var = result.model.get_pop(pop_name).get_variable(var_label) @@ -78,7 +78,7 @@ def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, p # If there is data outside the range when the model was simulated, don't # extrapolate the model outputs y = data_v - if pop_name.lower() == 'total': + if pop_name.lower() == "total": y2 = np.interp(data_t, var.series[0].tvec, var.series[0].vals, left=np.nan, right=np.nan) else: y2 = np.interp(data_t, var[0].t, var[0].vals, left=np.nan, right=np.nan) diff --git a/atomica/migration.py b/atomica/migration.py index 7c893a48..ea536eff 100644 --- a/atomica/migration.py +++ b/atomica/migration.py @@ -807,9 +807,8 @@ def _convert_framework_columns(framework): framework._validate() return framework + @migration("ParameterSet", "1.28.3", "1.28.4", "Add initialization atttribute") def _parset_add_initialization(parset): parset.initialization = None return parset - - diff --git a/atomica/model.py b/atomica/model.py index 173de76d..2e67badf 100644 --- a/atomica/model.py +++ b/atomica/model.py @@ -1848,7 +1848,6 @@ def initialize_compartments(self, parset: ParameterSet, framework, t_init: float """ - if not self.comps: # If this population has no compartments, then nothing needs to be done return diff --git a/atomica/parameters.py b/atomica/parameters.py index 5f668300..d6bae416 100644 --- a/atomica/parameters.py +++ b/atomica/parameters.py @@ -341,16 +341,16 @@ def from_excel(cls, excelfile: pd.ExcelFile): """ # excelfile = spreadsheet.pandas() - metadata, value_df = atomica.excel.read_dataframes(excelfile.book['Initialization']) + metadata, value_df = atomica.excel.read_dataframes(excelfile.book["Initialization"]) values = {} - for k,s in value_df.T.reset_index().T.set_index([0,1]).iterrows(): + for k, s in value_df.T.reset_index().T.set_index([0, 1]).iterrows(): v = s.dropna().values values[k] = v[0] if len(v) == 1 else v self = cls(values) - for k,v in metadata.T.reset_index().T.set_index(0)[1].to_dict().items(): + for k, v in metadata.T.reset_index().T.set_index(0)[1].to_dict().items(): setattr(self, k, v) return self @@ -534,7 +534,7 @@ def make_constant(self, year: float): :param year: Year to use for interpolation :return: A copy of the ParameterSet with constant parameters """ - ps = self.copy(f'{self.name} (constant)') + ps = self.copy(f"{self.name} (constant)") for par in ps.all_pars(): for ts in par.ts.values(): ts.insert(None, ts.interpolate(year)) diff --git a/atomica/plotting.py b/atomica/plotting.py index 1f9ce1a1..be690e5e 100644 --- a/atomica/plotting.py +++ b/atomica/plotting.py @@ -43,6 +43,28 @@ settings["dpi"] = 150 # average quality settings["transparent"] = False +# Define default aggregation methods for standard units +DEFAULT_OUTPUT_AGGREGATIONS = { + FS.QUANTITY_TYPE_FRACTION: "average", + FS.QUANTITY_TYPE_PROPORTION: "average", + FS.QUANTITY_TYPE_PROBABILITY: "average", + FS.QUANTITY_TYPE_RATE: "average", + FS.QUANTITY_TYPE_DURATION: "sum", # e.g., diagnosis time + treatment time should be summed within a population + FS.QUANTITY_TYPE_NUMBER: "sum", + "Number of people": "sum", # This unit is used by compartments and characteristics without denominators +} + +DEFAULT_POP_AGGREGATIONS = { + FS.QUANTITY_TYPE_FRACTION: "weighted", + FS.QUANTITY_TYPE_PROPORTION: "weighted", + FS.QUANTITY_TYPE_PROBABILITY: "weighted", + FS.QUANTITY_TYPE_RATE: "weighted", + FS.QUANTITY_TYPE_DURATION: "weighted", # e.g., diagnosis time should be averaged across populations + FS.QUANTITY_TYPE_NUMBER: "sum", + "Number of people": "sum", # This unit is used by compartments and characteristics without denominators + "": "weighted", # This unit is used by characteristics with denominators +} + def save_figs(figs, path=".", prefix="", fnames=None, file_format="png") -> None: """ @@ -143,7 +165,8 @@ class PlotData: all of the items being included in the sum must have the same denominator. This denominator will then continue to be tracked for the sum. - 'average' - unweighted average of quantities. If averaging characteristics with a denominator, then - the denominator will be dropped afterwards (so subsequent population aggregation + the denominator will be dropped afterwards (so subsequent population aggregation will be + performed based on total population size) - 'weighted' - weighted average where the weight is the - Link source compartment size, or - Characteristic denominator size, or @@ -159,16 +182,20 @@ class PlotData: - 'average' will give ``((a/b)+(c/d))/2``. No denominator is tracked for weighted population aggregation, so such aggregation would use the total population size. - 'weighted' will give ``(a+c)/(b+d)``. The denominator ``b+d`` can be used for weighted population aggregation. - The default is 'average' for dimensionless units, probabilities, rates etc. and 'sum' for everything else, with the exception of characteristics - with denominators, where 'sum' is used by default. + The default is 'weighted' for dimensionless units, probabilities, rates, and fractions, and 'sum' for everything else, with the exception of characteristics + with denominators, where + - 'sum' is used if the characteristics all have the same denominator + - 'weighted' is used if the characteristics all have different denominators + - 'average' is used otherwise - :param pop_aggregation: Same options as output_aggregation, except that 'weighted' - uses population sizes OR characteristic denominator size. Note that output aggregation + :param pop_aggregation: Same options as output_aggregation, except + - 'weighted' uses population sizes OR characteristic denominator size. Note that output aggregation is performed before population aggregation. This also means that population aggregation can be used to combine already aggregated outputs (e.g. can first sum 'sus'+'vac' within populations, and then take weighted average across populations). This weighting is principally intended for aggregating nondimensional quantities (fractions, proportions etc.). + - By default, quantities in 'duration' units are averaged across populations rather than summed. :param project: Optionally provide a :class:`Project` object, which will be used to convert names to labels in the outputs for plotting. @@ -237,11 +264,12 @@ def __init__(self, results, outputs=None, pops=None, output_aggregation=None, po aggregated_outputs = defaultdict(dict) # Dict with aggregated_outputs[pop_label][aggregated_output_label] aggregated_units = dict() # Dict with aggregated_units[aggregated_output_label] aggregated_timescales = dict() - aggregated_denominators = defaultdict(dict) # Store aggregated denominators where available at the same dimensionality as outputs + aggregated_denominators = defaultdict(dict) # Store aggregated denominators where available at the same dimensionality as outputs output_units = dict() output_timescales = dict() compsize = dict() - denomsize = dict() # Characteristic denominator size + denoms = sc.odict() # Record denominators associated with input characteristics + popsize = dict() # Defaultdict won't throw key error when checking outputs. data_label = defaultdict(str) # Label used to identify which data to plot, maps output label to data label. @@ -299,7 +327,7 @@ def __init__(self, results, outputs=None, pops=None, output_aggregation=None, po output_timescales[output_label] = None data_label[output_label] = vars[0].name if isinstance(vars[0], Characteristic) and vars[0].denominator is not None: - denomsize[output_label] = vars[0].denominator.vals + denoms[output_label] = vars[0].denominator # Record the denominator for this quantity else: raise Exception("Unknown type") @@ -322,10 +350,9 @@ def placeholder_pop(): par = Parameter(pop=placeholder_pop, name=output_label) fcn, dep_labels = parse_function(f_stack_str) deps = {} - displayed_annualization_warning = False for dep_label in dep_labels: vars = pop.get_variable(dep_label) - if t_bins is not None and (isinstance(vars[0], Link) or isinstance(vars[0], Parameter)) and time_aggregation == "sum" and not displayed_annualization_warning: + if t_bins is not None and (isinstance(vars[0], Link) or isinstance(vars[0], Parameter)) and time_aggregation == "sum": raise Exception("Function includes Parameter/Link so annualized rates are being used. Aggregation should therefore use 'average' rather than 'sum'.") deps[dep_label] = vars par._fcn = fcn @@ -339,7 +366,7 @@ def placeholder_pop(): # Third pass, aggregate them according to any aggregations present for output in outputs: # For each final output if isinstance(output, dict): - output_name = list(output.keys())[0] + output_name = list(output.keys())[0] # nb. there should be only one item in the output dict at this point labels = output[output_name] # If this was a function, aggregation over outputs doesn't apply so just put it straight in. @@ -347,42 +374,43 @@ def placeholder_pop(): aggregated_outputs[pop_label][output_name] = data_dict[output_name] aggregated_units[output_name] = "unknown" # Also, we don't know what the units of a function are aggregated_timescales[output_name] = None # Timescale is lost - aggregated_denominators[pop_label][output_name] = None # Denominators are not tracked + aggregated_denominators[pop_label][output_name] = None # Denominators are not tracked continue units = list(set([output_units[x] for x in labels])) timescales = list(set([np.nan if isna(output_timescales[x]) else output_timescales[x] for x in labels])) # Ensure that None and nan don't appear as different timescales - # Define default aggregation methods - default_aggregations = { - FS.QUANTITY_TYPE_FRACTION: 'average', - FS.QUANTITY_TYPE_PROPORTION: 'average', - FS.QUANTITY_TYPE_PROBABILITY: 'average', - FS.QUANTITY_TYPE_RATE: 'average', - FS.QUANTITY_TYPE_NUMBER: 'sum', - FS.QUANTITY_TYPE_DURATION: 'sum' - } - - # Set default aggregation method depending on the units of the quantity - if output_aggregation is None: - if labels[0] in denomsize: - # If aggregating characteristics with denominators, then we want to use - # We are aggregating characteristics with denominators, so we want to aggregate with summation - # on the assumption that all of the characteristics being aggregated have the same denominator - output_aggregation = "sum" - elif units[0] in ["", FS.QUANTITY_TYPE_FRACTION, FS.QUANTITY_TYPE_PROPORTION, FS.QUANTITY_TYPE_PROBABILITY, FS.QUANTITY_TYPE_RATE]: - output_aggregation = "average" - elif units[0] in [FS.QUANTITY_TYPE_NUMBER, FS.QUANTITY_TYPE_DURATION]: - output_aggregation = "sum" + # Set default aggregation method depending on the units of the quantity. If the aggregation method has not been specified + # then select a default aggregation method separately for each output + if output_aggregation is not None: + aggregation = output_aggregation + elif denoms: + try: + denominators = set([denoms[x].name for x in labels]) + except KeyError as e: + raise Exception("If an aggregation includes characteristics with denominators, then all of the included quantities must be characteristics with denominators") from e + + if len(denominators) == 1: + # If all characteristics share the same denominator e.g., SP and SN prevalence, then we want to add the characteristics together + aggregation = "sum" + elif len(denominators) == len(labels): + # If all characteristics have different denominators e.g., proportion of SP/SN on treatment aggregated over SP and SN, then use weighted averaging + aggregation = "weighted" else: - logger.warning(f'Unit quantity "{units[0]}" was not recognized and an output aggregation method was not specified, using "sum" by default') - + # Otherwise if mixing denominators, use a direct average. In general this should not happen because the result is not readily interpretable + aggregation = "average" + elif units[0] in DEFAULT_OUTPUT_AGGREGATIONS: + aggregation = DEFAULT_OUTPUT_AGGREGATIONS[units[0]] + else: + logger.warning(f'Unit quantity "{units[0]}" was not recognized and an output aggregation method was not specified, using "sum" by default') + aggregation = "sum" if len(units) > 1: logger.warning("Aggregation for output '%s' is mixing units, this is almost certainly not desired.", output_name) aggregated_units[output_name] = "unknown" else: - if units[0] in AVG_UNITS and output_aggregation == "sum" and len(labels) > 1 and not labels[0] in denomsize: # Dimensionless, like prevalance + # If the user has requested a sum for a unit that doesn't use summation by default, there's a decent chance that this is a mistake + if aggregation == "sum" and DEFAULT_OUTPUT_AGGREGATIONS.get(units[0], "sum") != "sum" and len(labels) > 1 and not labels[0] in denoms: # Dimensionless, like prevalance logger.warning(f"Output '{output_name}' is in '{units[0]}' units, so output aggregation probably should not be 'sum'.") aggregated_units[output_name] = output_units[labels[0]] @@ -392,45 +420,56 @@ def placeholder_pop(): else: aggregated_timescales[output_name] = output_timescales[labels[0]] - if output_aggregation == "sum": + # Perform additional validation on the denominators + if denoms: + unique_denoms = set([denoms[x].name for x in labels]) + + if len(unique_denoms) > 1 and len(unique_denoms) < len(labels): + logger.warning("When aggregating characteristics with denominators, they should generally either all have the same denominator, or all have different denominators. Partially duplicate denominators is likely not desired.") + + if len(unique_denoms) > 1: + # Check that the denominators are non-overlapping + comps = [set(result.framework.get_charac_includes(x)) for x in labels] + if sum(len(x) for x in comps) != len(set().union(*comps)): + logger.warning("When aggregating characteristics with different denominators, generally there should be no overlap in the denominators. However, some compartments are shared between the requested characteristic denominators. Unless this is intentional, this is likely a mistake that should be investigated.") + + if aggregation == "sum": aggregated_outputs[pop_label][output_name] = sum(data_dict[x] for x in labels) # Add together all the outputs # If summing characteristics that have denominators, then all quantities should have denominators, and they should all be equal # For example, summing SP-TB and SN-TB prevalance where they both have the 'alive' denominator - has_denominator = [x in denomsize for x in labels] - assert all(has_denominator) or not any(has_denominator) # An output aggregation must either have no quantities with denominators, or only contain quantities with denominators + has_denominator = [x in denoms for x in labels] if all(has_denominator): - for label in labels: - assert np.all(denomsize[label] == denomsize[labels[0]]), 'When aggregating characteristics with denominators, if summing them (default) then all quantities must have the same denominator. The "weighted" aggregation can be used to combine characteristics with different denominators, on the assumption that their denominators do not overlap.' - aggregated_denominators[pop_label][output_name] = denomsize[labels[0]] + assert len(set([denoms[x].name for x in labels])) == 1, 'When aggregating characteristics with denominators, if summing them then all quantities must have the same denominator. The "weighted" aggregation can be used to combine characteristics with different denominators, on the assumption that their denominators do not overlap.' + aggregated_denominators[pop_label][output_name] = denoms[0].vals elif not any(has_denominator): aggregated_denominators[pop_label][output_name] = None else: - raise Exception(f"When aggregating outputs, if any quantities being aggregated have denominators, then they must all have denominators. These quantities have denominators {[x for x in labels if x in denomsize]} while these do not {[x for x in labels if x not in denomsize]}") + raise Exception(f"When aggregating outputs, if any quantities being aggregated have denominators, then they must all have denominators. These quantities have denominators {[x for x in labels if x in denoms]} while these do not {[x for x in labels if x not in denoms]}") - elif output_aggregation == "average": + elif aggregation == "average": aggregated_outputs[pop_label][output_name] = sum(data_dict[x] for x in labels) aggregated_outputs[pop_label][output_name] /= len(labels) - aggregated_denominators[pop_label][output_name] = None # If taking a direct average then drop the denominator - elif output_aggregation == "weighted": - has_denominator = [x in denomsize for x in labels] + aggregated_denominators[pop_label][output_name] = None # If taking a direct average then drop the denominator + elif aggregation == "weighted": + has_denominator = [x in denoms for x in labels] assert all(has_denominator) or not any(has_denominator) # An output aggregation must either have no quantities with denominators, or only contain quantities with denominators if all(has_denominator): # Take weighted average based on denominator size, and then store the combined denominator further population aggregation - aggregated_outputs[pop_label][output_name] = sum(data_dict[x] * denomsize[x] for x in labels) - aggregated_denominators[pop_label][output_name] = sum([denomsize[x] for x in labels]) + aggregated_outputs[pop_label][output_name] = sum(data_dict[x] * denoms[x].vals for x in labels) + aggregated_denominators[pop_label][output_name] = sum([denoms[x].vals for x in labels]) aggregated_outputs[pop_label][output_name] /= aggregated_denominators[pop_label][output_name] elif not any(has_denominator): aggregated_outputs[pop_label][output_name] = sum(data_dict[x] * compsize[x] for x in labels) aggregated_outputs[pop_label][output_name] /= sum([compsize[x] for x in labels]) aggregated_denominators[pop_label][output_name] = None # If taking a direct average then drop the denominator else: - raise Exception(f"When aggregating outputs, if any quantities being aggregated have denominators, then they must all have denominators. These quantities have denominators {[x for x in labels if x in denomsize]} while these do not {[x for x in labels if x not in denomsize]}") + raise Exception(f"When aggregating outputs, if any quantities being aggregated have denominators, then they must all have denominators. These quantities have denominators {[x for x in labels if x in denoms]} while these do not {[x for x in labels if x not in denoms]}") else: aggregated_outputs[pop_label][output] = data_dict[output] aggregated_units[output] = output_units[output] aggregated_timescales[output] = output_timescales[output] - aggregated_denominators[pop_label][output] = denomsize.get(output) + aggregated_denominators[pop_label][output] = denoms[output].vals if output in denoms else None # Now aggregate over populations # If we have requested a reduction over populations, this is done for every output present @@ -441,32 +480,38 @@ def placeholder_pop(): pop_labels = pop[pop_name] # Set population aggregation method depending on the quantity being aggregated - if pop_aggregation is None: - if aggregated_denominators[pop_labels[0]][output_name] is not None: - # Outputs with denominators use these for a weighted average by default - pop_aggregation = "weighted" - elif aggregated_units[output_name] in ["", FS.QUANTITY_TYPE_FRACTION, FS.QUANTITY_TYPE_PROPORTION, FS.QUANTITY_TYPE_PROBABILITY, FS.QUANTITY_TYPE_RATE]: - pop_aggregation = "average" - else: - pop_aggregation = "sum" + if pop_aggregation is not None: + aggregation = pop_aggregation + elif aggregated_denominators[pop_labels[0]][output_name] is not None: + # Outputs with denominators use weighted by default + aggregation = "weighted" + elif aggregated_units[output_name] in DEFAULT_POP_AGGREGATIONS: + aggregation = DEFAULT_POP_AGGREGATIONS[aggregated_units[output_name]] + else: + logger.warning(f'Unit quantity "{aggregated_units[output_name]}" was not recognized and an output aggregation method was not specified, using "sum" by default') + aggregation = "sum" - if pop_aggregation == "sum": - if aggregated_units[output_name] in ["", FS.QUANTITY_TYPE_FRACTION, FS.QUANTITY_TYPE_PROPORTION, FS.QUANTITY_TYPE_PROBABILITY, FS.QUANTITY_TYPE_RATE] and len(pop_labels) > 1: - logger.warning("Output '%s' is not in number units, so population aggregation probably should not be 'sum'", output_name) + # Perform aggregation + if aggregation == "sum": + if aggregation == "sum" and DEFAULT_POP_AGGREGATIONS.get(aggregated_units[output_name], "sum") != "sum" and len(pop_labels) > 1: + logger.warning(f"Output '{output_name}' is in '{aggregated_units[output_name]}' units, so output aggregation should probably be '{DEFAULT_POP_AGGREGATIONS.get(aggregated_units[output_name])}', not 'sum'.") vals = sum(aggregated_outputs[x][output_name] for x in pop_labels) # Add together all the outputs - elif pop_aggregation == "average": + elif aggregation == "average": + if aggregated_denominators[pop_labels[0]][output_name] is not None: + logger.warning(f"Output '{output_name}' has a denominator, so output aggregation should probably be 'weighted' rather than 'average'") vals = sum(aggregated_outputs[x][output_name] for x in pop_labels) # Add together all the outputs vals /= len(pop_labels) - elif pop_aggregation == "weighted": + elif aggregation == "weighted": if aggregated_denominators[pop_labels[0]][output_name] is not None: - weights = {x:aggregated_denominators[x][output_name] for x in pop_labels} + weights = {x: aggregated_denominators[x][output_name] for x in pop_labels} else: - weights = {x:popsize[x] for x in pop_labels} + weights = {x: popsize[x] for x in pop_labels} numerator = sum(aggregated_outputs[x][output_name] * weights[x] for x in pop_labels) # Add together all the outputs denominator = sum([weights[x] for x in pop_labels]) vals = np.divide(numerator, denominator, out=np.full(numerator.shape, np.nan, dtype=float), where=numerator != 0) else: - raise Exception("Unknown pop aggregation method") + raise Exception(f'Unknown population aggregation method "{aggregation}"') + self.series.append(Series(tvecs[result_label], vals, result_label, pop_name, output_name, data_label[output_name], units=aggregated_units[output_name], timescale=aggregated_timescales[output_name], data_pop=pop_name)) else: vals = aggregated_outputs[pop][output_name] @@ -2064,7 +2109,7 @@ def _extract_labels(input_arrays) -> set: for x in input_arrays: if isinstance(x, dict): k = list(x.keys()) - assert len(k) == 1, "Aggregation dict can only have one key" + assert len(k) == 1, "Aggregation dict can only have one key, for multiple aggregations, use a list of dicts" if sc.isstring(x[k[0]]): continue else: diff --git a/docs/examples/Plot-Units.ipynb b/docs/examples/Plot-Units.ipynb index 4abc8f50..50ad6dd1 100644 --- a/docs/examples/Plot-Units.ipynb +++ b/docs/examples/Plot-Units.ipynb @@ -30,7 +30,7 @@ "metadata": {}, "outputs": [], "source": [ - "testdir = at.parent_dir()\n", + "testdir = at.rootdir/'tests'\n", "P = at.Project(framework='unit_demo_framework.xlsx',databook='unit_demo_databook.xlsx')\n", "P.load_progbook('unit_demo_progbook.xlsx')\n", "res = P.run_sim('default','default',at.ProgramInstructions(start_year=2018))" diff --git a/docs/examples/Plotting.ipynb b/docs/examples/Plotting.ipynb index 7c8d3180..a3ff512c 100644 --- a/docs/examples/Plotting.ipynb +++ b/docs/examples/Plotting.ipynb @@ -335,7 +335,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Some aggregations do not make sense. For instance, if you aggregate prevalances, they should be averaged, not summed. In cases where the code is able to identify this, a warning will be displayed:" + "Some aggregations do not make sense. For instance, if you aggregate prevalances, a weighted average should be performed. In cases where the code is able to identify this, a warning will be displayed:" ] }, { @@ -348,11 +348,21 @@ "figs = at.plot_series(d)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "d = at.PlotData(par_results,pop_aggregation='average',pops='total',outputs=['ac_prev'])\n", + "figs = at.plot_series(d)" + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ - "If you do not specify an aggregation method, the aggregation method will automatically be selected based on the units of the quantity being plotted. Non-dimensional quantities, proportions, fractions, and prevalances will be averaged instead of summed. " + "If you do not specify an aggregation method, the aggregation method will automatically be selected based on the units of the quantity being plotted. Non-dimensional quantities, proportions, fractions, and prevalances will use a population-weighted average instead of summation." ] }, { @@ -365,6 +375,57 @@ "figs = at.plot_series(d)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Characteristic aggregations\n", + "\n", + "The default aggregation for characteristics with denominators incorporates information about the denominators to select the aggregation method. For output aggregations involving characteristics, if the characteristics share a common denominator, they will be summed. This is useful for summing characteristics like prevalance of mutually exclusive strains e.g., SP and SN prevalence for TB:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "d = at.PlotData(par_results,pops='total',outputs=['sp_prev',\n", + " 'sn_prev',\n", + " 'ac_prev',\n", + " {'Aggregated':['sp_prev','sn_prev']}])\n", + "figs = at.plot_series(d)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note how the use of summation means that aggregating the SP and SN prevalences returns a value equal to the framework's definition of total prevalence. Alternatively, if aggregating characteristics with different denominators e.g., if there was a characteristic for diagnosed infections as a proportion of all infections, for SP and SN TB separately, a weighted average will be used to combine the characteristics. If neither of these statements are true, a raw average will be used, and a warning will be displayed. If aggregating characteristics that have different denominators, these should generally be no overlap in the compartments for those denominators in order for the weighted average to make sense. If any common compartments are detected, a warning will be displayed. \n", + "\n", + "For population aggregations of characteristics with denominators, the characteristic denominator will be used to perform weighted averages, rather than the total population size. This is useful when the denominator is something other than the population size. For example, the diagnosis sufficiency is given by people diagnosis divided by all infections. We can calculate this at the population level explicitly by summing the number of people diagnosed and the number of known infections and dividing the totals, and also by using aggregation of a characteristic that uses the number of infections as a denominator. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "d1 = at.PlotData(par_results, 'known_inf',pops='total')\n", + "d2 = at.PlotData(par_results, 'ac_inf' ,pops='total')\n", + "d = at.PlotData(par_results, 'diag_suff' ,pops='total', pop_aggregation='weighted')\n", + "figs = at.plot_series(d)\n", + "figs[0].axes[0].plot(d1.series[0].tvec, d1.series[0].vals/d2.series[0].vals, 'r--');" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice how the `'weighted'` average method produces the expected result, using the characteristic's denominator (`ac_inf`) as the weighting factor rather than the total population size. " + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -429,9 +490,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This is obviously incorrect because the value is greater than 1. Instead, we need to specify that we are averaging across populations. However, note that because the aggregation is an arbitrary function, the units of the output quantity are unknown. Therefore, a warning is not displayed (because the code does not know what the units are).\n", - "\n", - "Because the populations have very different sizes, a popsize-weighted average would be most appropriate:" + "This is obviously incorrect because the value is greater than 1. Because the aggregation is an arbitrary function, the units of the output quantity are unknown, and Atomica defaults to using summation for the aggregation. We need to instead explicitly specify the aggregation method. As the populations have very different sizes, a popsize-weighted average would be most appropriate." ] }, { @@ -444,6 +503,15 @@ "figs = at.plot_series(d)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -486,17 +554,6 @@ "figs = at.plot_series(d)" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Characteristic prevalance units (dimensionless)\n", - "d = at.PlotData(par_results,pops='total',output_aggregation='average',pop_aggregation='average',outputs=[{'Test':['lt_prev','spd_prev']}])\n", - "figs = at.plot_series(d)" - ] - }, { "cell_type": "code", "execution_count": null, @@ -2455,9 +2512,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Python [conda env:atomica311] *", + "display_name": "Python [conda env:atomica312]", "language": "python", - "name": "conda-env-atomica311-py" + "name": "conda-env-atomica312-py" }, "language_info": { "codemirror_mode": { @@ -2469,7 +2526,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.5" + "version": "3.12.2" }, "toc": { "base_numbering": 1, diff --git a/tests/README.md b/tests/README.md index 993869d9..6a6171a9 100644 --- a/tests/README.md +++ b/tests/README.md @@ -12,6 +12,6 @@ to the `site-packages` directory instead of the repo. Therefore, inside the test In practice, it can be useful to simply define the following two variables at the start of a test script: ```python -testdir = at.parent_dir() +testdir = at.rootdir/'tests' tmpdir = testdir / "temp" ``` \ No newline at end of file diff --git a/tests/test_api_workflow.py b/tests/test_api_workflow.py index 0d4ac4e0..07e9366e 100644 --- a/tests/test_api_workflow.py +++ b/tests/test_api_workflow.py @@ -11,7 +11,7 @@ test = "sir" # This test workflow only works with the SIR model -testdir = at.parent_dir() +testdir = at.rootdir / "tests" tmpdir = testdir / "temp" F = at.ProjectFramework(at.LIBRARY_PATH / test + "_framework.xlsx") diff --git a/tests/test_ensemble_parallel.py b/tests/test_ensemble_parallel.py index 33afdf99..2c31c87a 100644 --- a/tests/test_ensemble_parallel.py +++ b/tests/test_ensemble_parallel.py @@ -10,7 +10,7 @@ if __name__ == "__main__": # BASIC SETUP - testdir = at.parent_dir() + testdir = at.rootdir / "tests" P = at.Project(framework=testdir / "test_uncertainty_framework.xlsx", databook=testdir / "test_uncertainty_databook.xlsx") low_uncertainty_progset = at.ProgramSet.from_spreadsheet(testdir / "test_uncertainty_low_progbook.xlsx", project=P) high_uncertainty_progset = at.ProgramSet.from_spreadsheet(testdir / "test_uncertainty_high_progbook.xlsx", project=P) diff --git a/tests/test_horizontal_bars.py b/tests/test_horizontal_bars.py index fcc85b1c..1559f907 100644 --- a/tests/test_horizontal_bars.py +++ b/tests/test_horizontal_bars.py @@ -2,7 +2,7 @@ from atomica import ProjectFramework, Project import os -testdir = at.parent_dir() +testdir = at.rootdir / "tests" tmpdir = testdir / "temp" F = ProjectFramework(testdir / "framework_sir_dynamic.xlsx") diff --git a/tests/test_tox_bad_frameworks.py b/tests/test_tox_bad_frameworks.py index 1833cd4c..d2205968 100644 --- a/tests/test_tox_bad_frameworks.py +++ b/tests/test_tox_bad_frameworks.py @@ -6,7 +6,7 @@ import atomica as at import pytest -testdir = at.parent_dir() # Must be relative to current file to work with tox +testdir = at.rootdir / "tests" # Must be relative to current file to work with tox fdir = testdir / "bad_frameworks" # List available models based on which framework files exist diff --git a/tests/test_tox_calibration.py b/tests/test_tox_calibration.py index 39e2b71b..118c767c 100644 --- a/tests/test_tox_calibration.py +++ b/tests/test_tox_calibration.py @@ -4,7 +4,7 @@ import atomica as at import pytest -testdir = at.parent_dir() +testdir = at.rootdir / "tests" tmpdir = testdir / "temp" diff --git a/tests/test_tox_cascade.py b/tests/test_tox_cascade.py index 5ebbbc91..895b252a 100644 --- a/tests/test_tox_cascade.py +++ b/tests/test_tox_cascade.py @@ -5,7 +5,7 @@ import os import pytest -testdir = at.parent_dir() +testdir = at.rootdir / "tests" tmpdir = testdir / "temp" try: diff --git a/tests/test_tox_combined.py b/tests/test_tox_combined.py index c26536a4..6559e052 100644 --- a/tests/test_tox_combined.py +++ b/tests/test_tox_combined.py @@ -2,7 +2,7 @@ import numpy as np import atomica as at -testdir = at.parent_dir() +testdir = at.rootdir / "tests" tmpdir = testdir / "temp" @@ -91,7 +91,7 @@ def test_combined_plots(): def test_combined_order(): - testdir = at.parent_dir() # Must be relative to current file to work with tox + testdir = at.rootdir / "tests" # Must be relative to current file to work with tox P = at.Project(framework=testdir / "test_order_framework.xlsx", databook=testdir / "test_order_databook.xlsx") res = P.results[0] diff --git a/tests/test_tox_databooks.py b/tests/test_tox_databooks.py index 7958424f..c852d58a 100644 --- a/tests/test_tox_databooks.py +++ b/tests/test_tox_databooks.py @@ -6,7 +6,7 @@ from atomica import ProjectFramework, Project, ProjectData import sciris as sc -testdir = at.parent_dir() +testdir = at.rootdir / "tests" tmpdir = testdir / "temp" diff --git a/tests/test_tox_derivative.py b/tests/test_tox_derivative.py index fc9e9ded..b44dbc20 100644 --- a/tests/test_tox_derivative.py +++ b/tests/test_tox_derivative.py @@ -8,7 +8,7 @@ def test_derivative(): - testdir = at.parent_dir() # Must be relative to current file to work with tox + testdir = at.rootdir / "tests" # Must be relative to current file to work with tox F = at.ProjectFramework(testdir / "framework_derivative_test.xlsx") D = at.ProjectData.new(F, np.arange(2000, 2010), pops={"mosquitos": "Mosquitos"}, transfers=0) diff --git a/tests/test_tox_docgen.py b/tests/test_tox_docgen.py index b5d98ab6..a5bbafd4 100644 --- a/tests/test_tox_docgen.py +++ b/tests/test_tox_docgen.py @@ -7,7 +7,7 @@ import sciris as sc import pytest -testdir = at.parent_dir() +testdir = at.rootdir / "tests" tmpdir = testdir / "temp" frameworks = list() for f in at.LIBRARY_PATH.iterdir(): diff --git a/tests/test_tox_ensemble_cascade.py b/tests/test_tox_ensemble_cascade.py index a98f2986..a5b09f13 100644 --- a/tests/test_tox_ensemble_cascade.py +++ b/tests/test_tox_ensemble_cascade.py @@ -10,7 +10,7 @@ def test_ensemble_cascade(): # BASIC SETUP - testdir = at.parent_dir() + testdir = at.rootdir / "tests" P = at.Project(framework=testdir / "test_uncertainty_framework.xlsx", databook=testdir / "test_uncertainty_databook.xlsx") diff --git a/tests/test_tox_extra.py b/tests/test_tox_extra.py index 7fa4c4ce..5112f6bf 100644 --- a/tests/test_tox_extra.py +++ b/tests/test_tox_extra.py @@ -4,7 +4,7 @@ def test_extra_data_pop(): - testdir = at.parent_dir() + testdir = at.rootdir / "tests" F_path = testdir / "framework_sir_dynamic.xlsx" D_path = testdir / "databook_sir_dynamic_extra.xlsx" diff --git a/tests/test_tox_frameworks.py b/tests/test_tox_frameworks.py index 303ee535..eac01c48 100644 --- a/tests/test_tox_frameworks.py +++ b/tests/test_tox_frameworks.py @@ -5,7 +5,7 @@ import pytest import pandas as pd -testdir = at.parent_dir() +testdir = at.rootdir / "tests" tmpdir = testdir / "temp" frameworks = [ diff --git a/tests/test_tox_indirect_programs.py b/tests/test_tox_indirect_programs.py index 4949fbd7..29fa5c5e 100644 --- a/tests/test_tox_indirect_programs.py +++ b/tests/test_tox_indirect_programs.py @@ -2,7 +2,7 @@ import numpy as np import os -testdir = at.parent_dir() # Must be relative to current file to work with tox +testdir = at.rootdir / "tests" # Must be relative to current file to work with tox def test_indirect_programs(): diff --git a/tests/test_tox_junctions.py b/tests/test_tox_junctions.py index d28c054c..102f59e6 100644 --- a/tests/test_tox_junctions.py +++ b/tests/test_tox_junctions.py @@ -4,7 +4,7 @@ import atomica as at import os -testdir = at.parent_dir() # Must be relative to current file to work with tox +testdir = at.rootdir / "tests" # Must be relative to current file to work with tox def test_junctions(): diff --git a/tests/test_tox_library.py b/tests/test_tox_library.py index f9c78d57..286bd48b 100644 --- a/tests/test_tox_library.py +++ b/tests/test_tox_library.py @@ -8,7 +8,7 @@ import numpy as np import sciris as sc -testdir = at.parent_dir() +testdir = at.rootdir / "tests" tmpdir = testdir / "temp" # List available models based on which framework files exist @@ -239,6 +239,6 @@ def test_model(model): if __name__ == "__main__": np.seterr(all="raise") - models = ['combined'] + models = ["combined"] for m in models: test_model(m) diff --git a/tests/test_tox_logging.py b/tests/test_tox_logging.py index 6a5e8e34..6b585ae2 100644 --- a/tests/test_tox_logging.py +++ b/tests/test_tox_logging.py @@ -2,7 +2,7 @@ import atomica as at -testdir = at.parent_dir() +testdir = at.rootdir / "tests" tmpdir = testdir / "temp" diff --git a/tests/test_tox_migration.py b/tests/test_tox_migration.py index 63393827..2308294e 100644 --- a/tests/test_tox_migration.py +++ b/tests/test_tox_migration.py @@ -14,7 +14,7 @@ def test_migration(): at.logger.setLevel("DEBUG") - testdir = at.parent_dir() + testdir = at.rootdir / "tests" tmpdir = testdir / "temp" P = at.Project.load(testdir / "migration_test_with_scenarios.prj") diff --git a/tests/test_tox_no_compartments.py b/tests/test_tox_no_compartments.py index 765d90e8..0b5e84a4 100644 --- a/tests/test_tox_no_compartments.py +++ b/tests/test_tox_no_compartments.py @@ -3,7 +3,7 @@ import os import pytest -testdir = at.parent_dir() # Must be relative to current file to work with tox +testdir = at.rootdir / "tests" # Must be relative to current file to work with tox def test_no_compartments(): diff --git a/tests/test_tox_no_initialization.py b/tests/test_tox_no_initialization.py index 4583ff8f..22cc8831 100644 --- a/tests/test_tox_no_initialization.py +++ b/tests/test_tox_no_initialization.py @@ -4,7 +4,7 @@ import atomica as at import numpy as np -testdir = at.parent_dir() +testdir = at.rootdir / "tests" tmpdir = testdir / "temp" diff --git a/tests/test_tox_progbooks.py b/tests/test_tox_progbooks.py index 71de7db6..fe480a08 100644 --- a/tests/test_tox_progbooks.py +++ b/tests/test_tox_progbooks.py @@ -3,7 +3,7 @@ import sciris as sc import pytest -testdir = at.parent_dir() +testdir = at.rootdir / "tests" tmpdir = testdir / "temp" diff --git a/tests/test_tox_program_calculation.py b/tests/test_tox_program_calculation.py index 72f2f6a9..463a3be5 100644 --- a/tests/test_tox_program_calculation.py +++ b/tests/test_tox_program_calculation.py @@ -2,7 +2,7 @@ import numpy as np import os -testdir = at.parent_dir() # Must be relative to current file to work with tox +testdir = at.rootdir / "tests" # Must be relative to current file to work with tox def test_program_coverage_calculation(): diff --git a/tests/test_tox_reconciliation.py b/tests/test_tox_reconciliation.py index 5169ca93..f3610f9e 100644 --- a/tests/test_tox_reconciliation.py +++ b/tests/test_tox_reconciliation.py @@ -1,7 +1,7 @@ import pytest import atomica as at -testdir = at.parent_dir() +testdir = at.rootdir / "tests" tmpdir = testdir / "temp" models = ["tb", "tb_simple", "hypertension_dyn"] diff --git a/tests/test_tox_results.py b/tests/test_tox_results.py index 030c368d..ef53678f 100644 --- a/tests/test_tox_results.py +++ b/tests/test_tox_results.py @@ -8,7 +8,7 @@ import pytest -testdir = at.parent_dir() +testdir = at.rootdir / "tests" tmpdir = testdir / "temp" diff --git a/tests/test_tox_save.py b/tests/test_tox_save.py index 5217ce25..748d940a 100644 --- a/tests/test_tox_save.py +++ b/tests/test_tox_save.py @@ -1,7 +1,7 @@ import numpy as np import atomica as at -testdir = at.parent_dir() +testdir = at.rootdir / "tests" tmpdir = testdir / "temp" diff --git a/tests/test_tox_seasonal.py b/tests/test_tox_seasonal.py index 43ee7b65..d80addf9 100644 --- a/tests/test_tox_seasonal.py +++ b/tests/test_tox_seasonal.py @@ -7,7 +7,7 @@ def test_seasonal(): - testdir = at.parent_dir() + testdir = at.rootdir / "tests" tmpdir = testdir / "temp" F_path = testdir / "framework_seasonal_test.xlsx" diff --git a/tests/test_tox_shortcut_init.py b/tests/test_tox_shortcut_init.py index 8ded6b58..634bdf49 100644 --- a/tests/test_tox_shortcut_init.py +++ b/tests/test_tox_shortcut_init.py @@ -6,7 +6,7 @@ from numpy.testing import assert_allclose import pytest -testdir = at.parent_dir() +testdir = at.rootdir / "tests" tmpdir = testdir / "temp" diff --git a/tests/test_tox_stochastic.py b/tests/test_tox_stochastic.py index b9b45708..e4ca9225 100644 --- a/tests/test_tox_stochastic.py +++ b/tests/test_tox_stochastic.py @@ -6,7 +6,7 @@ def test_stochastic(): - testdir = at.parent_dir() # Must be relative to current file to work with tox + testdir = at.rootdir / "tests" # Must be relative to current file to work with tox F0 = at.ProjectFramework(testdir / "framework_sir_dynamic.xlsx") P0 = at.Project(name="test", framework=F0, do_run=False) diff --git a/tests/test_tox_table_parsing.py b/tests/test_tox_table_parsing.py index 77caf269..24e07b7a 100644 --- a/tests/test_tox_table_parsing.py +++ b/tests/test_tox_table_parsing.py @@ -5,7 +5,7 @@ import atomica as at import os -testdir = at.parent_dir() # Must be relative to current file to work with tox +testdir = at.rootdir / "tests" # Must be relative to current file to work with tox def test_table_parsing(): diff --git a/tests/test_tox_timed_compartments.py b/tests/test_tox_timed_compartments.py index c8db579f..2574f4f4 100644 --- a/tests/test_tox_timed_compartments.py +++ b/tests/test_tox_timed_compartments.py @@ -16,7 +16,7 @@ # # -testdir = at.parent_dir() +testdir = at.rootdir / "tests" tmpdir = testdir / "temp" diff --git a/tests/text_tox_timed_initialization.py b/tests/text_tox_timed_initialization.py index 66782372..91346ba3 100644 --- a/tests/text_tox_timed_initialization.py +++ b/tests/text_tox_timed_initialization.py @@ -15,9 +15,10 @@ # # P.load_databook(at.LIBRARY_PATH+'tb_databook.xlsx') # P = at.demo('tb',do_run=True) -testdir = at.parent_dir() +testdir = at.rootdir / "tests" tmpdir = testdir / "temp" + def test_timed_initialization(): F = at.ProjectFramework(testdir / "timed_initialization_test_framework.xlsx") @@ -32,17 +33,16 @@ def set_initialization_basic(F, D, year, y_factor=True): ps2 = at.ParameterSet(F, D, "basic") # Set initial compartment sizes for initialization quantities - for qty in itertools.chain(F.characs.index[F.characs['setup weight'] > 0], F.comps.index[F.comps['setup weight'] > 0]): + for qty in itertools.chain(F.characs.index[F.characs["setup weight"] > 0], F.comps.index[F.comps["setup weight"] > 0]): for pop in D.pops: if y_factor: ps2.pars[qty].meta_y_factor = 1 - ps2.pars[qty].y_factor[pop] = res.get_variable(qty, pop)[0].vals[-1]/ps2.pars[qty].ts[pop].interpolate(year) + ps2.pars[qty].y_factor[pop] = res.get_variable(qty, pop)[0].vals[-1] / ps2.pars[qty].ts[pop].interpolate(year) else: ps2.pars[qty].ts[pop].insert(year, res.get_variable(qty, pop)[0].vals[-1]) return ps2 - P = at.Project(framework=F, databook=D, do_run=False) P.settings.sim_dt = 1 / 12 P.settings.sim_start = 2018 @@ -52,24 +52,25 @@ def set_initialization_basic(F, D, year, y_factor=True): # Basic steady state initialization ps = set_initialization_basic(F, D, 2018) - res2 = P.run_sim(ps, result_name='basic') + res2 = P.run_sim(ps, result_name="basic") # Advanced steady state initialization - ps2 = at.ParameterSet(F,D) + ps2 = at.ParameterSet(F, D) ps2.set_initialization(res1, 2021) - res3 = P.run_sim(ps2, result_name='advanced') + res3 = P.run_sim(ps2, result_name="advanced") - ps2.pars['alive'].y_factor[0] = 1.1 + ps2.pars["alive"].y_factor[0] = 1.1 - ps2.save_calibration(tmpdir/'test_cal.xlsx') - res3 = P.run_sim(ps2, result_name='advanced') + ps2.save_calibration(tmpdir / "test_cal.xlsx") + res3 = P.run_sim(ps2, result_name="advanced") - ps4 = P.make_parset('saved') - ps4.load_calibration(tmpdir/'test_cal.xlsx') - res4 = P.run_sim(ps4, result_name='loaded') + ps4 = P.make_parset("saved") + ps4.load_calibration(tmpdir / "test_cal.xlsx") + res4 = P.run_sim(ps4, result_name="loaded") d = at.PlotData([res1, res2, res3, res4], ["sus", "inf", "rec"]) at.plot_series(d) -if __name__ == '__main__': - test_timed_initialization() \ No newline at end of file + +if __name__ == "__main__": + test_timed_initialization() diff --git a/tests/validate_integration.py b/tests/validate_integration.py index 17dfce03..9df2661c 100644 --- a/tests/validate_integration.py +++ b/tests/validate_integration.py @@ -47,7 +47,7 @@ def validate(r1, r2): @pytest.mark.parametrize("model", models) def test_validate_model(model): - testdir = at.parent_dir() + testdir = at.rootdir / "tests" tmpdir = testdir / "temp" framework_file = at.LIBRARY_PATH / f"{model}_framework.xlsx" From e45110619d972bbc97504e1a47aaab6c6a2c233b Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 30 Oct 2024 15:40:24 +1000 Subject: [PATCH 085/161] Remove flake8 job, change development status --- azure-pipelines.yml | 22 ---------------------- setup.py | 2 +- tox.ini | 17 ----------------- 3 files changed, 1 insertion(+), 40 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 5f41210b..e0211c8f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -45,28 +45,6 @@ jobs: summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml' # reportDirectory: '$(System.DefaultWorkingDirectory)/**/htmlcov' -- job: 'flake8' - pool: - vmImage: 'ubuntu-latest' - steps: - - task: UsePythonVersion@0 - displayName: 'Select python version' - inputs: - versionSpec: '3.12' - - script: python -m pip install flake8 flake8-junit-report - displayName: 'Install flake8' - - script: flake8 atomica tests --exit-zero --output-file flake8.txt - # Note - using --exit-zero will cause flake8 'errors' to show up as 'errors' in Azure Pipelines - # but the test will have been considered to pass. Therefore, the overall tests suite will still - # be considered to be passing as long as tox runs, and flake8 errors are just guidance for style - displayName: 'Run flake8' - - script: flake8_junit flake8.txt flake8_junit.xml - displayName: 'Generate flake8 junit output' - - task: PublishTestResults@2 - inputs: - testResultsFiles: '**/flake8_junit.xml' - testRunTitle: 'Publish flake8 results' - - job: 'docs' condition: and(ne(variables['Build.Reason'], 'PullRequest'), ne(variables['Build.Reason'], 'Schedule')) # Skip if it's a PR build or a scheduled build pool: diff --git a/setup.py b/setup.py index eb71024a..53a5d85c 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules", - "Development Status :: 4 - Beta", + "Development Status :: 5 - Production/Stable", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", diff --git a/tox.ini b/tox.ini index e81a142c..8172f379 100644 --- a/tox.ini +++ b/tox.ini @@ -29,20 +29,3 @@ filterwarnings = ignore::PendingDeprecationWarning ignore::UserWarning:.*openpyxl -[flake8] -# Use these commands to call autopep8 to tidy up whitespace/trivial formatting -# -# autopep8 --in-place -j 0 --recursive atomica -# autopep8 --in-place -j 0 --recursive tests -# -# Alternatively, use Black via -# -# pip install black -# black -l 999 . # Use `-l 999` to more or less ignore line length - -exclude = .git,__pycache__,docs,build,dist,junit,.tox -ignore = E501,F401,E401,E402,C901,F403 - -# flake8 does not check with E203 properly with list slices -extend-ignore = E203 - From f478bab6f729db764eacc69ac4f4f77ac722a1ca Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 30 Oct 2024 15:41:59 +1000 Subject: [PATCH 086/161] Change test result publishing version --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e0211c8f..e2bf892e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -39,7 +39,7 @@ jobs: testRunTitle: 'Publish test results for Python $(python.version)' condition: succeededOrFailed() - - task: PublishCodeCoverageResults@1 + - task: PublishCodeCoverageResults@2 inputs: codeCoverageTool: Cobertura summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml' From b740afabc84bf9452233022174f863a2f0abd4a9 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 30 Oct 2024 15:49:23 +1000 Subject: [PATCH 087/161] Update date --- atomica/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/version.py b/atomica/version.py index fd17c0ff..23c4754c 100644 --- a/atomica/version.py +++ b/atomica/version.py @@ -7,5 +7,5 @@ import sciris as sc version = "1.28.8" -versiondate = "2024-10-29" +versiondate = "2024-10-30" gitinfo = sc.gitinfo(__file__) From f80c2a29b4474f14a360827aba00ad8babea03ef Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 30 Oct 2024 21:53:06 +1000 Subject: [PATCH 088/161] Revert test path - original implementation was needed for tox --- docs/examples/Plot-Units.ipynb | 2 +- tests/README.md | 2 +- tests/test_api_workflow.py | 2 +- tests/test_ensemble_parallel.py | 2 +- tests/test_horizontal_bars.py | 2 +- tests/test_tox_bad_frameworks.py | 2 +- tests/test_tox_calibration.py | 2 +- tests/test_tox_cascade.py | 2 +- tests/test_tox_combined.py | 4 ++-- tests/test_tox_databooks.py | 2 +- tests/test_tox_derivative.py | 2 +- tests/test_tox_docgen.py | 2 +- tests/test_tox_ensemble_cascade.py | 2 +- tests/test_tox_extra.py | 2 +- tests/test_tox_frameworks.py | 2 +- tests/test_tox_indirect_programs.py | 2 +- tests/test_tox_junctions.py | 2 +- tests/test_tox_library.py | 2 +- tests/test_tox_logging.py | 2 +- tests/test_tox_migration.py | 2 +- tests/test_tox_no_compartments.py | 2 +- tests/test_tox_no_initialization.py | 2 +- tests/test_tox_progbooks.py | 2 +- tests/test_tox_program_calculation.py | 2 +- tests/test_tox_reconciliation.py | 2 +- tests/test_tox_results.py | 2 +- tests/test_tox_save.py | 2 +- tests/test_tox_seasonal.py | 2 +- tests/test_tox_shortcut_init.py | 2 +- tests/test_tox_stochastic.py | 2 +- tests/test_tox_table_parsing.py | 2 +- tests/test_tox_timed_compartments.py | 2 +- tests/text_tox_timed_initialization.py | 2 +- tests/validate_integration.py | 2 +- 34 files changed, 35 insertions(+), 35 deletions(-) diff --git a/docs/examples/Plot-Units.ipynb b/docs/examples/Plot-Units.ipynb index 50ad6dd1..4abc8f50 100644 --- a/docs/examples/Plot-Units.ipynb +++ b/docs/examples/Plot-Units.ipynb @@ -30,7 +30,7 @@ "metadata": {}, "outputs": [], "source": [ - "testdir = at.rootdir/'tests'\n", + "testdir = at.parent_dir()\n", "P = at.Project(framework='unit_demo_framework.xlsx',databook='unit_demo_databook.xlsx')\n", "P.load_progbook('unit_demo_progbook.xlsx')\n", "res = P.run_sim('default','default',at.ProgramInstructions(start_year=2018))" diff --git a/tests/README.md b/tests/README.md index 6a6171a9..993869d9 100644 --- a/tests/README.md +++ b/tests/README.md @@ -12,6 +12,6 @@ to the `site-packages` directory instead of the repo. Therefore, inside the test In practice, it can be useful to simply define the following two variables at the start of a test script: ```python -testdir = at.rootdir/'tests' +testdir = at.parent_dir() tmpdir = testdir / "temp" ``` \ No newline at end of file diff --git a/tests/test_api_workflow.py b/tests/test_api_workflow.py index 07e9366e..0d4ac4e0 100644 --- a/tests/test_api_workflow.py +++ b/tests/test_api_workflow.py @@ -11,7 +11,7 @@ test = "sir" # This test workflow only works with the SIR model -testdir = at.rootdir / "tests" +testdir = at.parent_dir() tmpdir = testdir / "temp" F = at.ProjectFramework(at.LIBRARY_PATH / test + "_framework.xlsx") diff --git a/tests/test_ensemble_parallel.py b/tests/test_ensemble_parallel.py index 2c31c87a..33afdf99 100644 --- a/tests/test_ensemble_parallel.py +++ b/tests/test_ensemble_parallel.py @@ -10,7 +10,7 @@ if __name__ == "__main__": # BASIC SETUP - testdir = at.rootdir / "tests" + testdir = at.parent_dir() P = at.Project(framework=testdir / "test_uncertainty_framework.xlsx", databook=testdir / "test_uncertainty_databook.xlsx") low_uncertainty_progset = at.ProgramSet.from_spreadsheet(testdir / "test_uncertainty_low_progbook.xlsx", project=P) high_uncertainty_progset = at.ProgramSet.from_spreadsheet(testdir / "test_uncertainty_high_progbook.xlsx", project=P) diff --git a/tests/test_horizontal_bars.py b/tests/test_horizontal_bars.py index 1559f907..fcc85b1c 100644 --- a/tests/test_horizontal_bars.py +++ b/tests/test_horizontal_bars.py @@ -2,7 +2,7 @@ from atomica import ProjectFramework, Project import os -testdir = at.rootdir / "tests" +testdir = at.parent_dir() tmpdir = testdir / "temp" F = ProjectFramework(testdir / "framework_sir_dynamic.xlsx") diff --git a/tests/test_tox_bad_frameworks.py b/tests/test_tox_bad_frameworks.py index d2205968..1833cd4c 100644 --- a/tests/test_tox_bad_frameworks.py +++ b/tests/test_tox_bad_frameworks.py @@ -6,7 +6,7 @@ import atomica as at import pytest -testdir = at.rootdir / "tests" # Must be relative to current file to work with tox +testdir = at.parent_dir() # Must be relative to current file to work with tox fdir = testdir / "bad_frameworks" # List available models based on which framework files exist diff --git a/tests/test_tox_calibration.py b/tests/test_tox_calibration.py index 118c767c..39e2b71b 100644 --- a/tests/test_tox_calibration.py +++ b/tests/test_tox_calibration.py @@ -4,7 +4,7 @@ import atomica as at import pytest -testdir = at.rootdir / "tests" +testdir = at.parent_dir() tmpdir = testdir / "temp" diff --git a/tests/test_tox_cascade.py b/tests/test_tox_cascade.py index 895b252a..5ebbbc91 100644 --- a/tests/test_tox_cascade.py +++ b/tests/test_tox_cascade.py @@ -5,7 +5,7 @@ import os import pytest -testdir = at.rootdir / "tests" +testdir = at.parent_dir() tmpdir = testdir / "temp" try: diff --git a/tests/test_tox_combined.py b/tests/test_tox_combined.py index 6559e052..c26536a4 100644 --- a/tests/test_tox_combined.py +++ b/tests/test_tox_combined.py @@ -2,7 +2,7 @@ import numpy as np import atomica as at -testdir = at.rootdir / "tests" +testdir = at.parent_dir() tmpdir = testdir / "temp" @@ -91,7 +91,7 @@ def test_combined_plots(): def test_combined_order(): - testdir = at.rootdir / "tests" # Must be relative to current file to work with tox + testdir = at.parent_dir() # Must be relative to current file to work with tox P = at.Project(framework=testdir / "test_order_framework.xlsx", databook=testdir / "test_order_databook.xlsx") res = P.results[0] diff --git a/tests/test_tox_databooks.py b/tests/test_tox_databooks.py index c852d58a..7958424f 100644 --- a/tests/test_tox_databooks.py +++ b/tests/test_tox_databooks.py @@ -6,7 +6,7 @@ from atomica import ProjectFramework, Project, ProjectData import sciris as sc -testdir = at.rootdir / "tests" +testdir = at.parent_dir() tmpdir = testdir / "temp" diff --git a/tests/test_tox_derivative.py b/tests/test_tox_derivative.py index b44dbc20..fc9e9ded 100644 --- a/tests/test_tox_derivative.py +++ b/tests/test_tox_derivative.py @@ -8,7 +8,7 @@ def test_derivative(): - testdir = at.rootdir / "tests" # Must be relative to current file to work with tox + testdir = at.parent_dir() # Must be relative to current file to work with tox F = at.ProjectFramework(testdir / "framework_derivative_test.xlsx") D = at.ProjectData.new(F, np.arange(2000, 2010), pops={"mosquitos": "Mosquitos"}, transfers=0) diff --git a/tests/test_tox_docgen.py b/tests/test_tox_docgen.py index a5bbafd4..b5d98ab6 100644 --- a/tests/test_tox_docgen.py +++ b/tests/test_tox_docgen.py @@ -7,7 +7,7 @@ import sciris as sc import pytest -testdir = at.rootdir / "tests" +testdir = at.parent_dir() tmpdir = testdir / "temp" frameworks = list() for f in at.LIBRARY_PATH.iterdir(): diff --git a/tests/test_tox_ensemble_cascade.py b/tests/test_tox_ensemble_cascade.py index a5b09f13..a98f2986 100644 --- a/tests/test_tox_ensemble_cascade.py +++ b/tests/test_tox_ensemble_cascade.py @@ -10,7 +10,7 @@ def test_ensemble_cascade(): # BASIC SETUP - testdir = at.rootdir / "tests" + testdir = at.parent_dir() P = at.Project(framework=testdir / "test_uncertainty_framework.xlsx", databook=testdir / "test_uncertainty_databook.xlsx") diff --git a/tests/test_tox_extra.py b/tests/test_tox_extra.py index 5112f6bf..7fa4c4ce 100644 --- a/tests/test_tox_extra.py +++ b/tests/test_tox_extra.py @@ -4,7 +4,7 @@ def test_extra_data_pop(): - testdir = at.rootdir / "tests" + testdir = at.parent_dir() F_path = testdir / "framework_sir_dynamic.xlsx" D_path = testdir / "databook_sir_dynamic_extra.xlsx" diff --git a/tests/test_tox_frameworks.py b/tests/test_tox_frameworks.py index eac01c48..303ee535 100644 --- a/tests/test_tox_frameworks.py +++ b/tests/test_tox_frameworks.py @@ -5,7 +5,7 @@ import pytest import pandas as pd -testdir = at.rootdir / "tests" +testdir = at.parent_dir() tmpdir = testdir / "temp" frameworks = [ diff --git a/tests/test_tox_indirect_programs.py b/tests/test_tox_indirect_programs.py index 29fa5c5e..4949fbd7 100644 --- a/tests/test_tox_indirect_programs.py +++ b/tests/test_tox_indirect_programs.py @@ -2,7 +2,7 @@ import numpy as np import os -testdir = at.rootdir / "tests" # Must be relative to current file to work with tox +testdir = at.parent_dir() # Must be relative to current file to work with tox def test_indirect_programs(): diff --git a/tests/test_tox_junctions.py b/tests/test_tox_junctions.py index 102f59e6..d28c054c 100644 --- a/tests/test_tox_junctions.py +++ b/tests/test_tox_junctions.py @@ -4,7 +4,7 @@ import atomica as at import os -testdir = at.rootdir / "tests" # Must be relative to current file to work with tox +testdir = at.parent_dir() # Must be relative to current file to work with tox def test_junctions(): diff --git a/tests/test_tox_library.py b/tests/test_tox_library.py index 286bd48b..110dd246 100644 --- a/tests/test_tox_library.py +++ b/tests/test_tox_library.py @@ -8,7 +8,7 @@ import numpy as np import sciris as sc -testdir = at.rootdir / "tests" +testdir = at.parent_dir() tmpdir = testdir / "temp" # List available models based on which framework files exist diff --git a/tests/test_tox_logging.py b/tests/test_tox_logging.py index 6b585ae2..6a5e8e34 100644 --- a/tests/test_tox_logging.py +++ b/tests/test_tox_logging.py @@ -2,7 +2,7 @@ import atomica as at -testdir = at.rootdir / "tests" +testdir = at.parent_dir() tmpdir = testdir / "temp" diff --git a/tests/test_tox_migration.py b/tests/test_tox_migration.py index 2308294e..63393827 100644 --- a/tests/test_tox_migration.py +++ b/tests/test_tox_migration.py @@ -14,7 +14,7 @@ def test_migration(): at.logger.setLevel("DEBUG") - testdir = at.rootdir / "tests" + testdir = at.parent_dir() tmpdir = testdir / "temp" P = at.Project.load(testdir / "migration_test_with_scenarios.prj") diff --git a/tests/test_tox_no_compartments.py b/tests/test_tox_no_compartments.py index 0b5e84a4..765d90e8 100644 --- a/tests/test_tox_no_compartments.py +++ b/tests/test_tox_no_compartments.py @@ -3,7 +3,7 @@ import os import pytest -testdir = at.rootdir / "tests" # Must be relative to current file to work with tox +testdir = at.parent_dir() # Must be relative to current file to work with tox def test_no_compartments(): diff --git a/tests/test_tox_no_initialization.py b/tests/test_tox_no_initialization.py index 22cc8831..4583ff8f 100644 --- a/tests/test_tox_no_initialization.py +++ b/tests/test_tox_no_initialization.py @@ -4,7 +4,7 @@ import atomica as at import numpy as np -testdir = at.rootdir / "tests" +testdir = at.parent_dir() tmpdir = testdir / "temp" diff --git a/tests/test_tox_progbooks.py b/tests/test_tox_progbooks.py index fe480a08..71de7db6 100644 --- a/tests/test_tox_progbooks.py +++ b/tests/test_tox_progbooks.py @@ -3,7 +3,7 @@ import sciris as sc import pytest -testdir = at.rootdir / "tests" +testdir = at.parent_dir() tmpdir = testdir / "temp" diff --git a/tests/test_tox_program_calculation.py b/tests/test_tox_program_calculation.py index 463a3be5..72f2f6a9 100644 --- a/tests/test_tox_program_calculation.py +++ b/tests/test_tox_program_calculation.py @@ -2,7 +2,7 @@ import numpy as np import os -testdir = at.rootdir / "tests" # Must be relative to current file to work with tox +testdir = at.parent_dir() # Must be relative to current file to work with tox def test_program_coverage_calculation(): diff --git a/tests/test_tox_reconciliation.py b/tests/test_tox_reconciliation.py index f3610f9e..5169ca93 100644 --- a/tests/test_tox_reconciliation.py +++ b/tests/test_tox_reconciliation.py @@ -1,7 +1,7 @@ import pytest import atomica as at -testdir = at.rootdir / "tests" +testdir = at.parent_dir() tmpdir = testdir / "temp" models = ["tb", "tb_simple", "hypertension_dyn"] diff --git a/tests/test_tox_results.py b/tests/test_tox_results.py index ef53678f..030c368d 100644 --- a/tests/test_tox_results.py +++ b/tests/test_tox_results.py @@ -8,7 +8,7 @@ import pytest -testdir = at.rootdir / "tests" +testdir = at.parent_dir() tmpdir = testdir / "temp" diff --git a/tests/test_tox_save.py b/tests/test_tox_save.py index 748d940a..5217ce25 100644 --- a/tests/test_tox_save.py +++ b/tests/test_tox_save.py @@ -1,7 +1,7 @@ import numpy as np import atomica as at -testdir = at.rootdir / "tests" +testdir = at.parent_dir() tmpdir = testdir / "temp" diff --git a/tests/test_tox_seasonal.py b/tests/test_tox_seasonal.py index d80addf9..43ee7b65 100644 --- a/tests/test_tox_seasonal.py +++ b/tests/test_tox_seasonal.py @@ -7,7 +7,7 @@ def test_seasonal(): - testdir = at.rootdir / "tests" + testdir = at.parent_dir() tmpdir = testdir / "temp" F_path = testdir / "framework_seasonal_test.xlsx" diff --git a/tests/test_tox_shortcut_init.py b/tests/test_tox_shortcut_init.py index 634bdf49..8ded6b58 100644 --- a/tests/test_tox_shortcut_init.py +++ b/tests/test_tox_shortcut_init.py @@ -6,7 +6,7 @@ from numpy.testing import assert_allclose import pytest -testdir = at.rootdir / "tests" +testdir = at.parent_dir() tmpdir = testdir / "temp" diff --git a/tests/test_tox_stochastic.py b/tests/test_tox_stochastic.py index e4ca9225..b9b45708 100644 --- a/tests/test_tox_stochastic.py +++ b/tests/test_tox_stochastic.py @@ -6,7 +6,7 @@ def test_stochastic(): - testdir = at.rootdir / "tests" # Must be relative to current file to work with tox + testdir = at.parent_dir() # Must be relative to current file to work with tox F0 = at.ProjectFramework(testdir / "framework_sir_dynamic.xlsx") P0 = at.Project(name="test", framework=F0, do_run=False) diff --git a/tests/test_tox_table_parsing.py b/tests/test_tox_table_parsing.py index 24e07b7a..77caf269 100644 --- a/tests/test_tox_table_parsing.py +++ b/tests/test_tox_table_parsing.py @@ -5,7 +5,7 @@ import atomica as at import os -testdir = at.rootdir / "tests" # Must be relative to current file to work with tox +testdir = at.parent_dir() # Must be relative to current file to work with tox def test_table_parsing(): diff --git a/tests/test_tox_timed_compartments.py b/tests/test_tox_timed_compartments.py index 2574f4f4..c8db579f 100644 --- a/tests/test_tox_timed_compartments.py +++ b/tests/test_tox_timed_compartments.py @@ -16,7 +16,7 @@ # # -testdir = at.rootdir / "tests" +testdir = at.parent_dir() tmpdir = testdir / "temp" diff --git a/tests/text_tox_timed_initialization.py b/tests/text_tox_timed_initialization.py index 91346ba3..80e0ff48 100644 --- a/tests/text_tox_timed_initialization.py +++ b/tests/text_tox_timed_initialization.py @@ -15,7 +15,7 @@ # # P.load_databook(at.LIBRARY_PATH+'tb_databook.xlsx') # P = at.demo('tb',do_run=True) -testdir = at.rootdir / "tests" +testdir = at.parent_dir() tmpdir = testdir / "temp" diff --git a/tests/validate_integration.py b/tests/validate_integration.py index 9df2661c..17dfce03 100644 --- a/tests/validate_integration.py +++ b/tests/validate_integration.py @@ -47,7 +47,7 @@ def validate(r1, r2): @pytest.mark.parametrize("model", models) def test_validate_model(model): - testdir = at.rootdir / "tests" + testdir = at.parent_dir() tmpdir = testdir / "temp" framework_file = at.LIBRARY_PATH / f"{model}_framework.xlsx" From 2b4cfcbdf0a0e89aa5282894b579becaeaa1cfa5 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Thu, 31 Oct 2024 15:23:22 +1000 Subject: [PATCH 089/161] Handle out of bounds bins in time aggregation more explicitly without throwing an error --- atomica/plotting.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/atomica/plotting.py b/atomica/plotting.py index 1d5c2b9c..6a3e3673 100644 --- a/atomica/plotting.py +++ b/atomica/plotting.py @@ -619,12 +619,16 @@ def time_aggregate(self, t_bins, time_aggregation=None, interpolation_method=Non interpolation_method = "linear" if not hasattr(t_bins, "__len__"): - # If a scalar bin is provided, then it is + # If a scalar bin is provided, then it is assumed to correspond to the bin width, in which case we need + # to create uniformly spaced bins up to the last complete bin. if t_bins > (self.series[0].tvec[-1] - self.series[0].tvec[0]): # If bin width is greater than the sim duration, treat it the same as aggregating over all times t_bins = "all" else: if not (self.series[0].tvec[-1] - self.series[0].tvec[0]) % t_bins: + # If the simulation ends in a multiple of the t_bins, then we can have a final bin extending up to the last + # simulation year. If we just use tvec[-1] in np.arange then that final bin will be excluded. So we add + # t_bins on to that final bin to ensure it's included. upper = self.series[0].tvec[-1] + t_bins else: upper = self.series[0].tvec[-1] @@ -663,6 +667,12 @@ def time_aggregate(self, t_bins, time_aggregation=None, interpolation_method=Non max_step = 0.5 * min(np.diff(s.tvec)) # Subdivide for trapezoidal integration with at least 2 divisions per timestep. Could be a lot of memory for integrating daily timesteps over a full simulation, but unlikely to be prohibitive vals = np.full(lower.shape, fill_value=np.nan) for i, (l, u) in enumerate(zip(lower, upper)): + + # For bins that partially extend out of bounds, return NaN as the value immediately + if l < s.tvec[0] or u > s.tvec[-1]: + vals[i] = np.nan + continue + t2 = np.arange(round((u - l) / max_step) + 1) * max_step + l # Numerical precision issues can cause the wrong bin to be used. This is particularly noticable for 'previous' # e.g., if the interpolated finer bins have 2025.9999999 instead of 2026 causing the 2025 value to be From f0246eca410c43d013d76c9a9015ab870c43cb38 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 4 Nov 2024 15:06:23 +1000 Subject: [PATCH 090/161] Improve time aggregation to no longer interpolate unless necessary --- CHANGELOG.md | 4 +++- atomica/plotting.py | 48 ++++++++++++++++++++++++++++----------------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d999d3f..aae5da61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,12 +7,14 @@ This file records changes to the codebase grouped by version release. Unreleased - `ProjectSettings` now computes the simulation time vector in a more robust way to reduce edge cases where the reported `sim_dt` doesn't match the input. - `ParameterSet.load_calibration()` now clears any existing initialization if the calibration being loaded does not contain an initialization. Previously, the absence of an 'initialization' sheet in the calibration would be treated as not making any change to the initialization. This could cause calibrations to become mixed if a calibration without an initialization was loaded after a calibration with an initialization. Now, a missing initialization sheet is treated as meaning 'no initialization' and any existing initialization will be cleared when the calibration is loaded. - `Project.load_databook()` will no longer populate `Project.databook` when a `ProjectData` instance is supplied rather than a spreadsheet. The intention of `Project.databook` as opposed to `Project.data.to_spreadsheet()` is that the original databook may contain comments or other content that is not preserved when the databook is loaded into a `ProjectData` instance. Therefore, `Project.databook` serves as a record of the original inputs. However, in previous versions of Atomica, if a `ProjectData` instance was provided rather than a spreadsheet, `ProjectData.to_spreadsheet()` would be used to populate `Project.databook`. For large databooks, this can be computationally expensive and particularly affect the use case of passing in a preloaded databook to improve performance. Since the conversion of the `ProjectData` to a spreadsheet upon loading offers no functional difference to creating the spreadsheet from `Project.data` when required, Atomica no longer performs this conversion upfront. +- `PlotData.time_aggregate()` now only interpolates if necessary, using simulated time points as much as possible. *Backwards-compatibility notes* - In some edge cases, the simulation time points in the output may be different. In those cases, the difference between simulation time points in the model output would not have matched the model input, although the correct time step would have been used to calculate parameter values. In these cases, there may be an extra time point in the model output. Re-running the model should produce results that are close to the original results. - If accessing `Project.databook`, in some cases this may now be `None` rather than an `sc.Spreadsheet()`. If that occurs, `Project.data.to_spreadsheet()` should be used to produce an equivalent spreadsheet. - +- Time aggregation of `PlotData` may produce slightly different results due to the more accurate selection of time points in this version. +- ## [1.28.7] - 2024-10-29 - If aggregating characteristics with a denominator, weighted aggregations use the denominator of the quantity rather than the total population size to perform the weighting. This can be useful for quantities that are proportions of things other than the population size e.g., proportion of active infections that are diagnosed diff --git a/atomica/plotting.py b/atomica/plotting.py index 6a3e3673..826fc997 100644 --- a/atomica/plotting.py +++ b/atomica/plotting.py @@ -661,34 +661,46 @@ def time_aggregate(self, t_bins, time_aggregation=None, interpolation_method=Non else: scale = 1.0 - # We interpolate in time-aggregation because the time bins are independent of the step size. In contrast, - # accumulation preserves the same time bins, so we don't need the interpolation step and instead go straight - # to summation or trapezoidal integration - max_step = 0.5 * min(np.diff(s.tvec)) # Subdivide for trapezoidal integration with at least 2 divisions per timestep. Could be a lot of memory for integrating daily timesteps over a full simulation, but unlikely to be prohibitive vals = np.full(lower.shape, fill_value=np.nan) - for i, (l, u) in enumerate(zip(lower, upper)): + lower_idx = np.searchsorted(s.tvec, lower, side='left') # Time index for bin start + upper_idx = np.searchsorted(s.tvec, upper, side='right') # Time index for bin end + + for i, (l, u, l_idx, u_idx) in enumerate(zip(lower, upper, lower_idx, upper_idx)): # For bins that partially extend out of bounds, return NaN as the value immediately if l < s.tvec[0] or u > s.tvec[-1]: vals[i] = np.nan continue + elif l == u: + vals[i] = 0 + continue + + # The bins will consist of the actual simulation time points, plus + # partial bins that are interpolated before and after if the requested + # bins don't line up with the simulation timepoints + idx = np.arange(l_idx,u_idx) + t2 = s.tvec[idx] + interpolate = False + if t2[0] > l or t2[-1] < u: + interpolate = True + t2 = list(t2) + if t2[0] > l: + t2.insert(0,l) + if t2[-1] < u: + t2.append(u) + t2 = np.array(t2, dtype=float) - t2 = np.arange(round((u - l) / max_step) + 1) * max_step + l - # Numerical precision issues can cause the wrong bin to be used. This is particularly noticable for 'previous' - # e.g., if the interpolated finer bins have 2025.9999999 instead of 2026 causing the 2025 value to be - # used instead, this can cause a significant overestimation if the value is changing rapidly. Therefore - # we need to perform an extra step of using the exact bin values within some tolerance. The values are on - # the order of 0.002 (1 day, in years) so the default np.isclose() should be sufficient. However, we may want to apply this - # to linear interpolation as well because if the bin falls numerically *outside* the bounds, it will be extrapolated - # as NaN which we wouldn't want - nearest = np.searchsorted(s.tvec, t2, side='left') - isclose = np.isclose(s.tvec[nearest], t2) - t2[isclose] = s.tvec[nearest[isclose]] if interpolation_method == "linear": - v2 = np.interp(t2, s.tvec, s.vals, left=np.nan, right=np.nan) # Return NaN outside bounds - it should never be valid to use extrapolated output values in time aggregation + if interpolate: + v2 = np.interp(t2, s.tvec, s.vals, left=np.nan, right=np.nan) # Return NaN outside bounds - it should never be valid to use extrapolated output values in time aggregation + else: + v2 = s.vals[idx] vals[i] = np.trapz(y=v2 / scale, x=t2) # Note division by timescale here, which annualizes it elif interpolation_method == "previous": - v2 = scipy.interpolate.interp1d(s.tvec, s.vals, kind="previous", copy=False, assume_sorted=True, bounds_error=False, fill_value=(np.nan, np.nan))(t2) + if interpolate: + v2 = scipy.interpolate.interp1d(s.tvec, s.vals, kind="previous", copy=False, assume_sorted=True, bounds_error=False, fill_value=(np.nan, np.nan))(t2) + else: + v2 = s.vals[idx] vals[i] = sum(v2[:-1] / scale * np.diff(t2)) s.tvec = (lower + upper) / 2.0 From adaf5eb775315def10e082087e188e784ca855b4 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 13 Nov 2024 13:25:22 +1000 Subject: [PATCH 091/161] Tweak text --- docs/examples/Plotting.ipynb | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/docs/examples/Plotting.ipynb b/docs/examples/Plotting.ipynb index a3ff512c..dd4c50b0 100644 --- a/docs/examples/Plotting.ipynb +++ b/docs/examples/Plotting.ipynb @@ -1593,19 +1593,29 @@ "- `np.arange(2005,2040,5) = array([2005, 2010, 2015, 2020, 2025, 2030, 2035])` so the last bin is correct\n", "- `np.arange(2005,2045,5) = array([2005, 2010, 2015, 2020, 2025, 2030, 2035, 2040])` so the final bin is out of bounds\n", "\n", - "If you simply specify the bin size, e.g. `t_bins = 5` then the middle example will automatically be used. \n", - "\n", - "
\n", - "In general, it is easiest to only specify the bin width, as long as you are happy for the bins to start from the first simulation year\n", - "
\n", - "\n", - "Finally, note that because time aggregation is implemented by `PlotData`, you can apply time aggregation to `plot_series` as well as `plot_bars` e.g. if you want to plot actual annual values." + "If you simply specify the bin size, e.g. `t_bins = 5` then the middle example will automatically be used. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "d = at.PlotData([par_results,scen_results],pops=['0-4','5-14'],outputs=['sus','vac'],t_bins=5)\n", + "d.series[0].t_labels" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ + "
\n", + "In general, it is easiest to only specify the bin width, as long as you are happy for the bins to start from the first simulation year\n", + "
\n", + "\n", + "Finally, note that because time aggregation is implemented by `PlotData`, you can apply time aggregation to `plot_series` as well as `plot_bars` e.g. if you want to plot actual annual values.\n", + "\n", "So, to make our bar graph, we first select the results, pops, and outputs using the `PlotData` constructor, then perform any necessary time aggregation, and finally render the plot using `plotBars`:" ] }, From 4aeeb94f369a6fdef8eea39eabd7093c3fd0ff61 Mon Sep 17 00:00:00 2001 From: Rowanmh Date: Thu, 6 Feb 2025 19:42:48 +1100 Subject: [PATCH 092/161] Add code for a 'Databook default all' column in the framework If set for a parameter, then when creating a new databook it will just fill in an 'All' population instead of each population row. --- atomica/data.py | 8 ++++++-- atomica/excel.py | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/atomica/data.py b/atomica/data.py index 18535a8e..d8531d7d 100644 --- a/atomica/data.py +++ b/atomica/data.py @@ -261,13 +261,15 @@ class instance (e.g. if creating a new databook). pop_type = spec.get("population type") databook_order = spec.get("databook order") full_name = spec["display name"] + default_all = spec.get("databook default all") + allowed_units = [framework.get_databook_units(full_name)] if pd.isna(databook_order): order = np.inf else: order = databook_order pages[databook_page].append((spec.name, order)) - data.tdve[spec.name] = TimeDependentValuesEntry(full_name, data.tvec, allowed_units=[framework.get_databook_units(full_name)], comment=spec["guidance"], pop_type=pop_type) + data.tdve[spec.name] = TimeDependentValuesEntry(full_name, data.tvec, allowed_units=allowed_units, comment=spec["guidance"], pop_type=pop_type, default_all=default_all) data.tdve[spec.name].write_units = True data.tdve[spec.name].write_uncertainty = True if obj_type == "pars": @@ -276,6 +278,8 @@ class instance (e.g. if creating a new databook). data.tdve[spec.name].tvec = [] # If parameter is timed, don't show any years data.tdve[spec.name].write_uncertainty = False # Don't show uncertainty for timed parameters. In theory users could manually add the column and sample over it, but because the duration is rounded to the timestep, it's likely to have confusing stepped effects data.tdve[spec.name].pop_type = pop_type + if default_all: + data.tdve[spec.name].ts['All'] = TimeSeries(units=allowed_units[0]) # Now convert pages to full names and sort them into the correct order for _, spec in framework.sheets["databook pages"][0].iterrows(): @@ -654,7 +658,7 @@ def add_pop(self, code_name: str, full_name: str, pop_type: str = None) -> None: # Since TDVEs in databooks must have the unit set in the framework, all ts objects must share the same units # And, there is only supposed to be one type of unit allowed for TDVE tables (if the unit is empty, it will be 'N.A.') # so can just pick the first of the allowed units - if tdve.pop_type == pop_type: + if tdve.pop_type == pop_type and not (hasattr(tdve, 'default_all') and tdve.default_all): tdve.ts[code_name] = TimeSeries(units=tdve.allowed_units[0]) def rename_pop(self, existing_code_name: str, new_code_name: str, new_full_name: str) -> None: diff --git a/atomica/excel.py b/atomica/excel.py index e864fde5..9501b184 100644 --- a/atomica/excel.py +++ b/atomica/excel.py @@ -884,7 +884,7 @@ class TimeDependentValuesEntry: """ - def __init__(self, name, tvec: np.array = None, ts=None, allowed_units: list = None, comment: str = None, pop_type: str = None): + def __init__(self, name, tvec: np.array = None, ts=None, allowed_units: list = None, comment: str = None, pop_type: str = None, default_all: bool = False): if ts is None: ts = sc.odict() @@ -906,6 +906,8 @@ def __init__(self, name, tvec: np.array = None, ts=None, allowed_units: list = N self.write_units = None #: Write a column for units (if None, units will be written if any of the TimeSeries have units) self.write_uncertainty = None #: Write a column for uncertainty (if None, uncertainty will be written if any of the TimeSeries have uncertainty) self.write_assumption = None #: Write a column for assumption/constant (if None, assumption will be written if any of the TimeSeries have an assumption) + + self.default_all = default_all #If the TDVE should by default only have the 'All' population in the databook e.g. the same value for all populations unless exceptions are manually entered def __repr__(self): output = sc.prepr(self) From fdb66fea89d3b8eaf9408bbda14a54472b2e48c9 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Thu, 13 Feb 2025 20:31:48 +0100 Subject: [PATCH 093/161] Add hierarchical YAML test --- .../config_hierarchical_syntax_test.yaml | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tests/yaml_tests/config_hierarchical_syntax_test.yaml diff --git a/tests/yaml_tests/config_hierarchical_syntax_test.yaml b/tests/yaml_tests/config_hierarchical_syntax_test.yaml new file mode 100644 index 00000000..9dcc1ba3 --- /dev/null +++ b/tests/yaml_tests/config_hierarchical_syntax_test.yaml @@ -0,0 +1,23 @@ +calibration: + pop cal: + repeats: 1 + + match population sizes: + adjustables: + #general, then pop-specific + b_rate, mig_rate: [ 0.1, 10 ] + (b_rate, 0-4): + initial_value: 2 + upper_bound: 10 + lower_bound: 0.1 + + typ_active_inf, typ_car, par_active_inf, par_car: [0, 0] + measurables: alive + + + other formats, hierarchical tests: + adjustables: #[ [ b_rate, 0.1, 10 ], [ mig_rate ] ] + b_rate, mig_rate: [ 0.1, 10 ] + (b_rate, 0-4), mig_rate: [ 0.5, 20 ] + (b_rate, 0-4): + initial_value: 1.2 \ No newline at end of file From 999d1396dcf5ca85814b0e7ad14d37350f80239f Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Thu, 13 Feb 2025 21:26:50 +0100 Subject: [PATCH 094/161] Add stripped tutorial notebooks --- docs/general/YAML_calibration.ipynb | 491 ++++++++++++ .../tutorial/T7/T7_YAML_autocalibration.ipynb | 722 ++++++++++++++++++ 2 files changed, 1213 insertions(+) create mode 100644 docs/general/YAML_calibration.ipynb create mode 100644 docs/tutorial/T7/T7_YAML_autocalibration.ipynb diff --git a/docs/general/YAML_calibration.ipynb b/docs/general/YAML_calibration.ipynb new file mode 100644 index 00000000..bd8c7dab --- /dev/null +++ b/docs/general/YAML_calibration.ipynb @@ -0,0 +1,491 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "0", + "metadata": {}, + "source": [ + "# YAML calibration documentation" + ] + }, + { + "cell_type": "markdown", + "id": "1", + "metadata": {}, + "source": [ + "This page contains additional information about features and functionality supported by the YAML calibration system\n" + ] + }, + { + "cell_type": "markdown", + "id": "2", + "metadata": {}, + "source": [ + "## YAML internal structure\n", + "\n", + "The native representation of the YAML calibration is as a graph of 'nodes' where each node corresponds to either an action or a section containing other nodes. Each node has associated with it a collection of attributes/settings defined for that node (`instructions`), and a collection of attributes inherited from all parent nodes (`context`). The `atomica.yaml_calibration.build()` function takes in the content of the YAML file and loads it into a tree of `at.yaml_calibration.BaseNode` instances with a root node called 'calibration' at the top level. For example, consider the following YAML file:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3", + "metadata": {}, + "outputs": [], + "source": [ + "import atomica as at\n", + "print(open('T7_YAML_3_repeats.yaml').read())" + ] + }, + { + "cell_type": "markdown", + "id": "4", + "metadata": {}, + "source": [ + "This file would be loaded into the following tree of nodes:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5", + "metadata": {}, + "outputs": [], + "source": [ + "import atomica.yaml_calibration \n", + "nodes = at.yaml_calibration.build('T7_YAML_3_repeats.yaml') \n", + "print(nodes)" + ] + }, + { + "cell_type": "markdown", + "id": "6", + "metadata": {}, + "source": [ + "Section nodes have a `children` attribute that in turn contains others nodes:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7", + "metadata": {}, + "outputs": [], + "source": [ + "nodes.children[0].children[0]" + ] + }, + { + "cell_type": "markdown", + "id": "8", + "metadata": {}, + "source": [ + "The nodes corresponding to actions each have their own type, with methods that implement the action performed by the node:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9", + "metadata": {}, + "outputs": [], + "source": [ + "nodes.children[0].children[0].children[0]" + ] + }, + { + "cell_type": "markdown", + "id": "10", + "metadata": {}, + "source": [ + "The context for a node consists of all settings defined in the node's parents. For example, the 'Match population sizes' node inherits the 'repeats' context from the parent 'calibration' node:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11", + "metadata": {}, + "outputs": [], + "source": [ + "nodes.children[0].children[0].children[0].context" + ] + }, + { + "cell_type": "markdown", + "id": "12", + "metadata": {}, + "source": [ + "The 'instructions' for the 'Match population sizes' node contains all of the settings that are defined within the node itself - in this case, the adjustables and measurables:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13", + "metadata": {}, + "outputs": [], + "source": [ + "nodes.children[0].children[0].children[0].instructions" + ] + }, + { + "cell_type": "markdown", + "id": "14", + "metadata": {}, + "source": [ + "The YAML file is executed by sequentially traversing the tree of nodes, and calling the `apply()` method on each node in turn. The order of execution can be obtained using the `walk()` method e.g., " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "15", + "metadata": {}, + "outputs": [], + "source": [ + "list(nodes.walk())" + ] + }, + { + "cell_type": "markdown", + "id": "16", + "metadata": {}, + "source": [ + "This returns a flat list of tuples, where the first item corresponds to the number of times the node has been repeated (which is used when printing progress during execution) and the second item is the node itself. " + ] + }, + { + "cell_type": "markdown", + "id": "17", + "metadata": {}, + "source": [ + "## `CalibrationNode` functionality\n", + "\n", + "### Adjustables and measurables settings\n", + "\n", + "A calibration node contains adjustables and measurables. Each adjustable and measurable in turn has its own settings. Each adjustable has:\n", + "\n", + "- `adj_label` (required): Adjustable codename (can be found in the framework)\n", + "- `pop_name`: Population to calibrate (default: all populations)\n", + "- `lower_bound`: Lowest value the y-factor will be allowed to take (default: 0.1)\n", + "- `upper_bound`: Highest value the y-factor will be allowed to take (default: 1)\n", + "- `starting_y_factor`: Y-factor value the autocalibration will start from when running the optimisation algorithm (default: the adjustable’s current `y_factor` in the parset)\n", + "\n", + "\n", + "Each measurable has:\n", + "\n", + "- `meas_label` (required): Measurable codename (can be found in the framework)\n", + "- `pop_name`: Population to use for calibration (default: all populations)\n", + "- `weight`: Weight for a particular population (default: weight = 1. This implies that, by default, all populations are weighted equally regardless of size. See the [section on setting weights](#measurable-weights \"Measurable weights\") for further details)\n", + "- `metric`: Metric to be used by the optimisation algorithm (default: fractional)\n", + "- `cal_start`: Starting year that the calibration will be evaluated for (default: `sim_start`)\n", + "- `cal_end`: End year that the calibration will be evaluated for (default: `sim_end`)\n", + "\n", + "
\n", + "Note that sim_start and sim_end are governed by the project settings and are not set as part of the YAML calibration routine. \n", + "
\n", + "\n", + "When creating a calibration node in the YAML file, it is possible to create the adjustables and measurables using their labels only, using the default values for all other settings. Alternatively, users can specify some or all of the settings. The YAML calibration framework for Atomica supports four ways of setting adjustables and measurables, so as to give users a high level of flexibility. These are: \n", + "\n", + "- String format\n", + "- List format \n", + "- Dictionary format\n", + "- Combined format \n", + "\n", + "In general, we can only use one notation within any particular block of adjustables or measurables (with the exception of **combined format**). However, notation does not necessarily have to be consistent between different calibration blocks, or even between the adjustables and the measurables of the same calibration block. \n", + "\n", + "Below, we will describe each notation and how to use them in a YAML calibration file." + ] + }, + { + "cell_type": "markdown", + "id": "18", + "metadata": {}, + "source": [ + "#### String format\n", + "\n", + "The simplest notation is string format, where only parameter names are passed to the adjustables and measurables, like so: \n", + "\n", + " Calibration: \n", + " match population sizes:\n", + " adjustables: births, mig_rate\n", + " measurables: alive\n", + "\n", + "Multiple parameters can be provided, separated by commas. When we use string notation, the optimisation algorithm will perform an autocalibration run using the default settings for adjustables and measurables. If we want to the optimisation algorithm to use specific settings, rather than just the defaults, it is necessary to use one of the other formats." + ] + }, + { + "cell_type": "markdown", + "id": "19", + "metadata": {}, + "source": [ + "#### Dictionary format\n", + "\n", + "Dictionary format allows us to explicitly set calibration settings for each adjustable and measurable. We do this by writing the setting names and their values under the relevant parameter name. Each adjustable and measurable is placed on a new line, and their respective settings are also specified on separate indented lines, like so: \n", + "\n", + " Calibration: \n", + " Match population sizes:\n", + " adjustables: \n", + " \tb_rate: \n", + " \t\tstarting_y_factor: 1.2 \n", + " \tmig_rate: \n", + " lower_bound: 0.5\n", + " \t\tupper_bound: 20\t\t\n", + " measurables: \n", + " alive:\n", + " \tcal_start: 2000\n", + " \tcal_end: 2040\n", + "\n", + "We can also specify the same settings for multiple adjustables or measurables at once, by placing them together, separated by commas: \n", + "\n", + " Calibration: \n", + " match population sizes:\n", + " adjustables: \n", + " \tbirths, mig_rate: \n", + " \t\tlower_bound: 0.5\n", + " \t\tupper_bound: 20\t\t\n", + " measurables: alive \n", + " " + ] + }, + { + "cell_type": "markdown", + "id": "20", + "metadata": {}, + "source": [ + "#### List format\n", + "\n", + "In list format, as the name suggests, we specify the adjustables and measurables settings in a list. It can be useful as a shorthand of dictionary form, since the labels for each setting don't need to be explicitly written. Instead, we simply write the value of each setting, following the same order as in the [Adjustables and Measurables Settings](#Adjustables-and-measurables-settings) section.\n", + "\n", + "To use list format, place the parameter name and ordered settings values in a list (that is, in square brackets, separated by commas) after the adjustables and/or measurables keyword. The general structure and order to follow are shown below. \n", + "\n", + " adjustables: [adj_label, lower_bound, upper_bound, starting_y_factor]\n", + " measurables: [meas_label, weight, metric, start_year, end_year]\n", + "\n", + "Although this might seem like a lot of information for each adjustable and measurable, it is not necessary to include each item every time we use list format – only up to the point where the last setting we want to change is. For example, if we just want to set the `b_rate` adjustable’s `lower bound` to, say, 0.2, we only need to list the `par_label` and `lower_bound` values in order. Any subsequent settings will retain their default values.\n", + "\n", + " adjustables: [b_rate, 0.2]\n", + " measurables: [alive]" + ] + }, + { + "cell_type": "markdown", + "id": "21", + "metadata": {}, + "source": [ + "However, if we wanted to set values that are at the end of the list order, we need to explicitly specify the default values of all the previous settings. For example, to set the `starting_y_factor` to 1.2 and the `end_year` to 2020, assuming the simulation start year `sim_start` was 2000, we would write:\n", + "\n", + " adjustables: [b_rate, 0.1, 10, 1.2]\n", + " measurables: [alive, 1.0, fractional, 2000, 2020]\n", + "\n", + "We can also specify settings for multiple adjustables/measurables at once, by writing a list for each adjustable or measurable, and placing them together in a list of lists. The first example from the previous section on Dictionary format would be written as\n", + "\n", + " adjustables: [[b_rate, 0.1, 10, 1.2], [mig_rate, 0.5, 20]]\n", + " measurables: [alive]\n", + "\n", + "In this particular case, it might be most practical to use the dictionary format for the `mig_rate`, while the `b_rate` is more concise in list format. List notation may also become convoluted and hard to read if there are parameters to calibrate in the same block. In case like these, we can use the combined format instead, described below." + ] + }, + { + "cell_type": "markdown", + "id": "22", + "metadata": {}, + "source": [ + "#### Combined format\n", + "\n", + "Combined format uses dictionary keys, while the values are in list form. This has two main benefits: Firstly, it separates out the parameters in a clear and organised way, which avoids ending up with a dense list of lists containing long series of numbers. Secondly, it allows us to use both the list and dictionary formats under one same adjustables or measurables block.\n", + "\n", + " calibration: \n", + " match population sizes:\n", + " adjustables: \n", + " b_rate: \t\t\n", + " \t\t\tstarting_y_factor: \t1.2 \t------> dictionary format\n", + " \t\tmig_rate: [0.5, 20]\t ------> combined format\n", + " measurables: alive \n", + "\n", + "In the above example, the `b_rate` adjustable settings are in dictionary format, while the `mig_rate` is now in combined format. When using the combined format, the list of settings is defined in the same order as in the [Adjustables and Measurables Settings](#Adjustables-and-measurables-settings) section. In other words, the order is the same as when using the list format, except we don't specify the first entry (corresponding to the parameter code name) inside the list, as it is already specified before the colon. " + ] + }, + { + "cell_type": "markdown", + "id": "23", + "metadata": {}, + "source": [ + "### Calibrating populations\n", + "\n", + "The YAML calibration framework allows us to indicate specific populations to calibrate. This can be useful if we wish to calibrate some populations separately, or use different calibration settings for different populations. By default, if only the code name of the adjustable or measurable is provided, a separate copy will be created for every population. To specify the population in any format (except for string format, which does not support populations), the `par_name` and `pop_name` must be placed in a tuple, i.e. in round brackets and separated by a comma, like so: `(births, 0-4)`. Calibrating populations with spaces in the `pop_label` is supported, and follows the same syntax: `(births, 0-4 HIV+)`. The following are examples of this feature’s usage in all supported formats: \n", + "\n", + "Dictionary format:\n", + "\n", + " adjustables:\n", + " (births, 0-4), mig_rate: \n", + " lower_bound: 0.5\n", + " upper_bound: 20\n", + " measurables: \n", + " (alive, 0-4):\n", + " weight: 0.1\n", + "\n", + "List format:\n", + "\n", + " adjustables: [ [(births, 0-4), 0.5, 20], [mig_rate, 0.5, 20] ]\n", + " measurables: [(alive, 0-4), 1.0]\n", + "\n", + "Combined format:\n", + "\n", + " adjustables:\n", + " (births, 0-4), mig_rate: [0.5, 20] \n", + " measurables: \n", + " (alive, 0-4): [1.0]" + ] + }, + { + "cell_type": "markdown", + "id": "24", + "metadata": {}, + "source": [ + "#### Meta Y-factors\n", + "\n", + "For each parameter, the meta Y-factor is applied to all populations. To calibrate the meta Y-factor and apply the same changes to every population, set the population name to `all` using the syntax above e.g., `(births, all)` would set the meta Y-factor for the `births` parameter" + ] + }, + { + "cell_type": "markdown", + "id": "25", + "metadata": {}, + "source": [ + "#### Overriding population specific settings\n", + "\n", + "For each adjustable that has been created, the population-specific settings will take precedence over non-population-specific settings. Recall that if no population is specified, this is equivalent to defined adjustables and measurables for each population separately. For example:\n", + "\n", + " adjustables:\n", + " births:\n", + " lower_bound: 0.5\n", + " upper_bound: 20\n", + " (births, 0-4) \n", + " upper_bound: 10\n", + "\n", + "In this case, `births` will be adjusted in every population with a lower bound of 0.5 and upper bound of 20, _except_ for the 0-4 population, in which the lower bound will be 0.5 but the upper bound will be 10." + ] + }, + { + "cell_type": "markdown", + "id": "26", + "metadata": {}, + "source": [ + "### Calibrating transfers and interactions\n", + "\n", + "In the case of transfers and interactions, there are two populations involved: the ‘to’ population, and the ‘from' population. The approach is the same as with regular populations, except that we now have two population names in the tuple instead of one: \n", + "\n", + " adjustables:\n", + " (aging, 5-14, 15-64): \n", + " lower_bound: 0.5\n", + " \tupper_bound: 20\n", + " measurables: alive\n", + "\n", + "And in list form:\n", + "\n", + "\tadjustables: [(aging, 5-14, 15-64), 0.1, 10]\n", + " measurables: alive\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "27", + "metadata": {}, + "source": [ + "### Calibrating to total population data\n", + "\n", + "Usually, our data is structured like below, with each parameter containing several populations, such as age groups. \n", + "\n", + "![](databook_pops.png \"Example of a databook with multiple populations\")\n", + "\n", + "In the YAML file, we could write \n", + "\n", + " calibration\n", + " adjustables: b_rate\n", + " measurables: alive\n", + "\n", + "Since no population has been specified, all populations will be calibrated. \n", + "\n", + "However, for some parameters, our source data might not be broken down into populations or age groups. In that case, the above YAML file will not work, since there is no data available at the individual population level. What we can do in that situation is add an extra row to the databook with a population called `Total` (which is a reserved keyword in Atomica), and explicitly set the population name to `Total` in the YAML file. If it was our 'alive' data that was not broken down by populations, the databook would look like so\n", + "\n", + "![](databook_pops_Total.png \"Example of a databook with a Total population\")\n", + "\n", + "And we would adjust the previous YAML file like so.\n", + "\n", + "\tcalibration\n", + " adjustables: b_rate\n", + " measurables: (alive, Total)" + ] + }, + { + "cell_type": "markdown", + "id": "28", + "metadata": {}, + "source": [ + "## Measurable Weights \n", + "\n", + "In one calibration block, we can include several measurables at the same time, or multiple populations of the same measurable. But say we trusted the data from one measurable’s data source more than another, or wanted to prioritise fitting a particular population – how would we indicate this to the optimisation algorithm? \n", + "\n", + "In the measurable settings, we can set weights for this purpose. The default value for the `weight` setting is 1.0 which is used for all measurables and populations, which corresponds to giving them each an equal weight, regardless of size. That might be desirable if, for example, we have a key population that is smaller than the other populations – if they were weighted proportionally to size, the small key population might be effectively ignored in the optimisation. However, there might be cases where we want to do things differently. For example, we could give a key population a higher weight, or we could weight different age bins according to their size. Another reason to use measurable weights could simply be that we trust one data source more than another. \n", + "\n", + "In the following example, we set the `0-4 HIV+` population of the `alive` measurable to have double the weight than the `0-4` population. \n", + "\n", + " calibration: \n", + " match population sizes:\n", + " adjustables: \n", + " \tb_rate: \n", + " lower_bound: 0.1\n", + " upper_bound: 10\n", + " measurables: \n", + " (alive, 0-4 HIV+): \n", + " \tweight: 2\n", + " (alive, 0-4): \n", + " \t\t\t\tweight: 1\n", + "\n", + "Note that the important factor is the proportion between the different weights, not the weight values themselves. That is to say, if we instead set the above weight values to `4` and `2` respectively, the result would be the same. \n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [conda env:atomica312]", + "language": "python", + "name": "conda-env-atomica312-py" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": { + "height": "calc(100% - 180px)", + "left": "10px", + "top": "150px", + "width": "352px" + }, + "toc_section_display": true, + "toc_window_display": true + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/tutorial/T7/T7_YAML_autocalibration.ipynb b/docs/tutorial/T7/T7_YAML_autocalibration.ipynb new file mode 100644 index 00000000..348fc980 --- /dev/null +++ b/docs/tutorial/T7/T7_YAML_autocalibration.ipynb @@ -0,0 +1,722 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "0", + "metadata": {}, + "source": [ + "# T7 - YAML calibration\n", + "\n", + "As we saw in the earlier calibration tutorial, most autocalibrations involve multiple steps, since the optimization algorithm often gets stuck in local minima if we try to optimize too many parameters at once. We could run each of these steps ourselves through separate calls to `P.calibrate()` – however, there is significant value in being able to explicitly frame the overall calibration process as an algorithm, as this makes it easier to modify the calibration steps and apply the calibration algorithm across a collection of projects. This is implemented in Atomica through the 'YAML calibration' feature, in which the calibration steps are specified in a file which Atomica can then read and use to execute the calibration.\n", + "\n", + "## YAML files\n", + "\n", + "The calibration algorithm files used by Atomica are written in YAML. YAML is a plain-text, human-readable data serialization language used to make configuration files. Essentially, a YAML file can be read into Python variables (dictionaries, lists, strings) which in turn can be used as arguments to Python functions. Here is an example of how variables can be specified in a YAML file:\n", + "\n", + "```\n", + " foo: a string\n", + " bar: 1\n", + " baz: [a,b,c]\n", + " list:\n", + " - i\n", + " - j\n", + " nested:\n", + " x: 1\n", + " y: 2\n", + " ```\n", + "\n", + "When parsed into Python, this becomes\n", + "\n", + "```\n", + "{'foo': 'a string',\n", + " 'bar': 1,\n", + " 'baz': ['a', 'b', 'c'],\n", + " 'list': ['i', 'j'],\n", + " 'nested': {'x': 1, 'y': 2}}\n", + "```\n", + "\n", + "Using YAML files provides a simple way to define a calibration algorithm in a format that is easy to work with and that Atomica can directly execute. This can cut down the time we spend manually calibrating, or even running autocalibrations. It allows us to conduct reproducible calibration runs, and is also highly scalable, since it allows us to apply the same calibration algorithm in multiple countries or settings.\n", + "\n", + "The following tutorial outlines how to use the YAML framework that has been developed for Atomica calibration. Specifically, it will cover how to write a YAML configuration file with calibration instructions for Atomica, and how to use this file to execute a calibration. Bear in mind that YAML calibration is not intended to be a standalone tool that will perfectly calibrate any model – rather, it is one part of the calibration toolbox. It can be used to reduce the time spent on calibration by autocalibrating Atomica models to a reasonable level, but additional tweaking may be required to obtain a consistently high calibration quality across all parameters, populations and/or countries." + ] + }, + { + "cell_type": "markdown", + "id": "1", + "metadata": {}, + "source": [ + "## Basic calibration example\n", + "\n", + "In this tutorial, we will work with a simple version of a typhoid model. This model captures typhoid infections, as well as asymptomatic carriers and vaccination. Firstly, we need to create an Atomica `Project` by loading in the Framework and Databook files, just like we did in [the first atomica tutorial](https://atomica.tools/docs/master/tutorial/T1-Defining-a-model.html). The Framework and Databook for this project can be found in the Atomica repository under `assets/T7`. \n", + "\n", + "_TODO: Update paths when moved to Atomica repository_" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2", + "metadata": {}, + "outputs": [], + "source": [ + "import atomica as at\n", + "F = at.ProjectFramework('T7_framework.xlsx')\n", + "D = at.ProjectData.from_spreadsheet('T7_databook.xlsx', framework=F)\n", + "P = at.Project(framework=F,databook=D, do_run=False)\n", + "P.settings.update_time_vector(start=2000, end=2040, dt=1/52)" + ] + }, + { + "cell_type": "markdown", + "id": "3", + "metadata": {}, + "source": [ + "In the example above, no calibration has been loaded, so all of the calibration Y-factors are equal to 1, and the model is uncalibrated. We can run a simulation and plot it, to see what our model looks like before calibration:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4", + "metadata": {}, + "outputs": [], + "source": [ + "cal = P.make_parset()\n", + "res = P.run_sim(parset=cal, result_name = 'Uncalibrated')\n", + "d = at.PlotData(res, outputs=['alive','deaths', 'typ_prev', 'typ_num_deaths'], project=P)\n", + "fig = at.plot_series(d,axis='pops', data=P.data, n_cols=2, legend_mode='none')[0]\n", + "fig.set_size_inches(10,7)\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "markdown", + "id": "5", + "metadata": {}, + "source": [ + "Two issues with these simulation outputs immediately stand out. First, for the variables and years in which data is available, the model output doesn't match the data very well at all. Second, there is a large sudden change in the values of several variables right at the start of the simulation. In the absence of associated changes in interventions or disease transmission, disease burden is typically much more stable over time, so we would not expect to see such sudden changes at the start of the simulation.\n", + "\n", + "Tutorial 2 covers some of the detail around how to approach calibration. Although the parameters used for calibration vary from model to model, as a general rule, calibration proceeds by\n", + "\n", + "1. Demographic calibration: Adjusting birth and background death rates to match quantities like the total population size.\n", + "2. Epidemiological calibration: Adjusting parameters such as force of infection, diagnosis rate and mortality rate, to match quantities like incidence, prevalence and deaths.\n", + "\n", + "Each of these steps involves calibrating multiple parameters, which may be adjusted sequentially and repeatedly. They may also be interspersed with adjusting the model's initialization, to help minimize sudden transients at the start of the simulation. The purpose of the YAML file is to specify the sequence of steps to follow in carrying out a calibration run, in terms of which parameters to adjust, the order in which to adjust them, and how to assess the quality of the calibration at each step of the process. In this tutorial, we will use a YAML file to specify a sequence of steps to calibrate the simple typhoid model shown above, starting with a minimal example and then introducing key features provided by Atomica's YAML calibration system." + ] + }, + { + "cell_type": "markdown", + "id": "6", + "metadata": { + "jp-MarkdownHeadingCollapsed": true + }, + "source": [ + "## Minimal YAML file\n", + "\n", + "To illustrate how YAML calibration works, let’s start with a simple example of what a YAML file could look like:\n", + "\n", + " calibration:\n", + " \tadjustables: b_rate, mig_rate\n", + " \tmeasurables: alive\n", + "\n", + "The above YAML file represents a single call to the autocalibration optimisation function, where the `b_rate` and `mig_rate` y-factors are adjusted to match `alive`. It is equivalent to running a calibration with the following command:\n", + "\n", + " calibrated_parset = P.calibrate(parset = cal, adjustables = [b_rate, mig_rate], measurables=alive)\n", + "\n", + "Running the YAML calibration is very similar to performing a standalone auto-calibration. After saving the YAML file to disk (e.g. [T7_YAML_1_minimal.yaml](./<`T7_YAML_1_minimal`>.)), the calibration can be run using\n", + "\n", + " calibrated_parset = P.calibrate(parset = cal, yaml='T7_YAML_1_minimal.yaml')\n", + "\n", + "As the YAML calibration framework allows us to specify the adjustables and measurables, it is not necessary to provide them to `Project.calibrate()`, simply providing the YAML file is sufficient. However, the YAML file can contain multiple calibration commands, and therefore a single call to `Project.calibrate()` with a YAML file might be equivalent to multiple explicit calibration steps. The resulting simulation after running this simple calibration is like so: \n", + "\n", + "\"Simple" + ] + }, + { + "cell_type": "markdown", + "id": "7", + "metadata": {}, + "source": [ + "## Sections\n", + "\n", + "At the most basic level, a YAML calibration file defines a sequence of individual steps, where each step incrementally modify the calibration. The YAML file therefore defines an overall _algorithm_ for performing an automatic calibration. This algorithm is defined using two structures in the YAML file\n", + "\n", + "- _actions_ which are associated with particular operations, like running a gradient-descent calibration step with a particular set of parameters and data. A calibration action contains 'adjustables' and 'measurables'. Other examples of actions are detailed below\n", + "- _sections_ which are containers for actions. Sections can contain attributes such as how many times to repeat the contents of the section, or can define settings that are applied to any actions within the section\n", + "\n", + "The original YAML file above consisted of a single calibration action. If we wanted to extend the algorithm by adding a step to calibrate the death rate, we could update our YAML file to the following: \n", + "\n", + "\n", + "```\n", + "calibration:\n", + " Match population sizes:\n", + " adjustables: b_rate, mig_rate\n", + " measurables: alive\n", + " Match deaths:\n", + " adjustables: d_rate\n", + " measurables: deaths\n", + "```\n", + "\n", + "To organize the YAML file further, we could group these into an additional section. Both of these actions affect the overall population calibration, so we could logically group them as follows:\n", + "\n", + "```\n", + "calibration: \n", + " Population calibration:\n", + " Match population sizes:\n", + " adjustables: b_rate, mig_rate\n", + " measurables: alive\n", + " Match deaths:\n", + " adjustables: d_rate\n", + " measurables: deaths\n", + "```\n", + "\n", + "The overall structure of this YAML file is thus:\n", + "\n", + "1. A top-level section titled `calibration` which has one sub-section (`Population calibration`)\n", + "2. A sub-section called `Population calibration` which in turn contains two actions\n", + "3. An action called `Match population sizes` corresponding to the original calibration step for adjusting the birth rate and migration rate\n", + "4. An action called `Match deaths` corresponding to the new step of adjusting the death rate\n", + "\n", + "An action is differentiated from a section in two possible ways:\n", + "\n", + "- By contents e.g., if it contains `adjustables` and `measurables` then it is interpreted as a calibration action rather than a section\n", + "- By the title i.e., if the name corresponds to the name of a supported operation, as described below.\n", + " \n", + "Aside for the names of supported operations, sections can freely named." + ] + }, + { + "cell_type": "markdown", + "id": "8", + "metadata": {}, + "source": [ + "### Repeating a section\n", + "\n", + "The *repeats* keyword can be used to loop over any part of the calibration multiple times. We do this by writing `repeats: n` inside a particular section, where *n* is the number of times we would like to loop over that section. All subsections contained in it will also be looped over *n* times. \n", + "\n", + " calibration: \n", + " repeats: 2\n", + " Population calibration:\n", + " Match population sizes:\n", + " repeats: 2\n", + " adjustables: b_rate, mig_rate\n", + " measurables: alive\n", + " Match deaths:\n", + " adjustables: d_rate\n", + " measurables: deaths\n", + "\n", + "In the above example, we have set `repeats: 2` inside the `calibration` section, so the entire YAML calibration will be repeated twice. Then, the `Match population sizes` section also has `repeats: 2`, so the calibration step defined in that section will also be repeated twice each time. In total, there will be four calls to the optimisation algorithm to match `alive`, and two to match `deaths, so the YAML file above would be equivalent to \n", + "\n", + " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", + " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", + " parset = P.calibrate(parset = parset, adjustables = [d_rate], measurables=deaths)\n", + " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", + " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", + " parset = P.calibrate(parset = parset, adjustables = [d_rate], measurables=deaths)\n", + "\n", + "In this way, it is possible for even a very compact YAML file to correspond to a large number of individual autocalibration steps. " + ] + }, + { + "cell_type": "markdown", + "id": "9", + "metadata": {}, + "source": [ + "## Sections vs Actions\n", + "\n", + "As shown above, sections can help us to structure the calibration in a way that is practical and intuitive. They can be used to group blocks of YAML code that are conceptually related, that we want to repeat together several times, or that we want to apply similar settings to (we will cover which settings are supported in a [later section](#specifying-calibration-settings-in-outer-sections)). \n", + "\n", + "Importantly though, _sections_ do not modify the calibration itself – they are merely wrappers for the innermost blocks that actually correspond to specific actions. It is in these _actions_ that operations are performed on the calibration, such as modifying the calibration or saving it.\n", + "\n", + "
\n", + "We can tell action blocks apart from sections because action blocks contain keywords indicating what kind of block it is, or it contains no sub-sections.\n", + "
\n", + "\n", + "It is possible to load and inspect a YAML file in Atomica without executing it. This can help confirm that the YAML file has been parsed correctly. After loading the calibration, it can be printed to show a summary of the sections and actions that are present, how they are nested, and how many times they are repeated: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "10", + "metadata": {}, + "outputs": [], + "source": [ + "import atomica.yaml_calibration \n", + "calibration_tree = at.yaml_calibration.build('T7_YAML_3_repeats.yaml') \n", + "print(calibration_tree)" + ] + }, + { + "cell_type": "markdown", + "id": "11", + "metadata": {}, + "source": [ + "## Types of Functional Blocks/Actions\n", + "\n", + "YAML calibration files can contain the following types of action blocks: \n", + "\n", + "- Calibration block\n", + "- Initialization block\n", + "- Clear intialization block\n", + "- Saving block" + ] + }, + { + "cell_type": "markdown", + "id": "12", + "metadata": {}, + "source": [ + "### Calibration blocks\n", + "\n", + "In all of the YAML examples shown above, we have worked with 'calibration blocks', which are the main type of action block. Calibration blocks are defined by the fact that they contain two keywords called `adjustables` and `measurables`. Under `adjustables`, we list the parameters for Atomica’s optimisation algorithm to adjust, and under `measurables`, we list the parameters to calibrate to. Each calibration block provides instructions for one optimisation run, and is equivalent to making a call to `P.calibrate()` with the same adjustables and measurables.\n", + "\n", + "#### Adjustable and measurable settings\n", + "\n", + "So far, we have only specified the names of the adjustables and measurables, with no further information – in that case, the optimisation algorithm will use the default settings for adjustables and measurables. For more flexibility, we can specify further settings for the optimisation. The settings for the adjustables and measurables directly map to the options supported by `P.calibrate()`. \n", + "\n", + "Each adjustable has:\n", + "\n", + "- `adj_label` (required): Adjustable codename (can be found in the framework)\n", + "- `pop_name`: Population to calibrate (default: all populations)\n", + "- `lower_bound`: Lowest value the y-factor will be allowed to take (default: 0.1)\n", + "- `upper_bound`: Highest value the y-factor will be allowed to take (default: 1)\n", + "- `starting_y_factor`: Y-factor value the autocalibration will start from when running the optimisation algorithm (default: the adjustable’s current `y_factor` in the parset)\n", + "\n", + "Each measurable has:\n", + "\n", + "- `meas_label` (required): Measurable codename (can be found in the framework)\n", + "- `pop_name`: Population to use for calibration (default: all populations)\n", + "- `weight`: Weight for a particular population (default: 1). By default, all populations are weighted equally regardless of size. See [the documentation on weights]((./YAML_documentation_page.ipynb#measurable-weights \"Measurable weights\") for further details.\n", + "- `metric`: Metric to be used by the optimisation algorithm (default: fractional)\n", + "- `cal_start`: Starting year that the calibration will be evaluated from (default: `sim_start`)\n", + "- `cal_end`: End year until which the calibration will be evaluated (default: `sim_end`)\n", + "\n", + "Note that `sim_start` and `sim_end` are the start and end years that the simulation will run for (the simulation timespan) which are distinct from `cal_start` and `cal_end`, which specify the time period for which we want to calibrate the model, i.e. a subset of the simulation timespan. For more information, see the [section on outer settings](#specifying-calibration-settings-in-outer-sections). The `cal_start` and `cal_end` years can be set per-measurable, so it is possible to prioritize different years for different variables or for different steps of the calibration. \n", + "To specify these adjustables and measurables settings in the YAML file, we simply write the setting names and their values under the relevant parameter name. Each adjustable and measurable is placed on a new line, and their respective settings are also specified on separate indented lines, like so: \n", + "\n", + " calibration: \n", + " Match population sizes:\n", + " adjustables: \n", + " \tb_rate: \n", + " \t\tlower_bound: 0.5\n", + " \t\tupper_bound: 20\t\t\n", + " \tmig_rate: \n", + " \t\tstarting_y_factor: 1.2 \n", + " measurables: \n", + " alive:\n", + " \tcal_start: 2000\n", + " \tcal_end: 2040\n", + " " + ] + }, + { + "cell_type": "markdown", + "id": "13", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "#### Specifying Populations\n", + "\n", + "In some cases, you may want to only set adjustables or evaluation measurables for a specific population, or you may wish to use different settings for one population compared to another. A population can optionally be specified after the parameter name, as the second element of a tuple. Thus, if we only wish to calibrate some populations, we can rewrite our previous YAML file like so: \n", + "\n", + " calibration: \n", + " Match population sizes:\n", + " adjustables: \n", + " \t(b_rate, 0-4): \n", + " \t\tlower_bound: 0.5\n", + " \t\tupper_bound: 20\t\t\n", + " \t(mig_rate, 5-14): \n", + " \t\tstarting_y_factor: 1.2 \n", + " measurables: \n", + " (alive, 0-4), (alive, 5-14):\n", + " \tcal_start: 2000\n", + " \tcal_end: 2040\n", + " \n", + "Note that we can specify the same settings for more than one adjustable/measurable at once by placing several parameter names before the colon, separated by commas – this is applicable to any set of adjustables/measurables, not only different populations of the same parameter. For example, we could write: \n", + "\n", + " calibration: \n", + " Match population sizes:\n", + " adjustables: \n", + " \t(b_rate, 0-4), mig_rate: \n", + " \t\tlower_bound: 0.5\n", + " \t\tupper_bound: 20\n", + " starting_y_factor: 1.2\t\t \n", + " measurables: \n", + " (alive, 0-4), (alive, 5-14):\n", + " \tcal_start: 2000\n", + " \tcal_end: 2040\n", + "\n", + "Finally, this same syntax can be used to calibrate transfers and interactions, but in such cases the tuple should have three elements - the parameter name, the _from_ population and the _to_ population. For more information on calibrating in these cases, see [Calibrating transfers and interactions](./YAML_documentation_page.ipynb#calibrating-transfers-and-interactions \"Calibrating transfern detail by this point> TODO: Update link \n" + ] + }, + { + "cell_type": "markdown", + "id": "14", + "metadata": { + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "### Setting initialisations\n", + "\n", + "In some cases, the model may exhibit an unrealistically large transient at the start of the simulation. This can occur if the initial compartment sizes calculated by Atomica are very different to the equilibrium compartment sizes associated with the model's parameters. Two common reasons for this are:\n", + "\n", + "- The initial conditions are underdetermined, for example, if there are two strains of a disease with different levels of infectiousness, but data is only available on the total prevalence. In the absence of any other information, Atomica will automatically split up the total prevalence equally between the two strains, when in fact maybe one or the other strain may be dominant, which would change the overall transmission\n", + "- The model parameters may not give rise to an equilibrium solution that matches the data, if data sources have been mixed, combined across different years, collected in different ways or different definitions, or because the simplified dynamics in the model don't capture all of the processes in the real world. \n", + "\n", + "Regardless of the cause, there can often be an initial transience period at the beginning of the simulation, where we can observe abrupt spikes in some parameters until the system reaches equilibrium. \n", + "\n", + "\"Pre-initialization\n", + "\n", + "In some models, this can be treated as a 'burn-in' period and the initial part of the simulation can simply be discarded. However, there is a risk that being too far from the correct initialization results in contamination of the estimates of parameters during the calibration period. For example, if the model is initialized with the incorrect prevalence, the calibration applied to the force of infection in order to match the observed incidence would be impacted, which might subsequently affect the model's sensitivity to interventions that change the prevalence later on. Therefore, we wish to minimize the effect of the transient on the calibration. \n", + "\n", + "We can sometimes achieve this by setting the calibration start year `cal_start` to be a few years after the simulation start year `sim_start`, so that the simulation has a few years to reach equilibrium before the calibration process itself begins. However, this extends the duration of the simulation, or might limit the amount of data used for the calibraiton.\n", + "\n", + "An alternative approach is to override the initialisation for our calibration. Initialisations work by running a normal Atomica simulation for a few years (past the initial transient), taking the compartment sizes of that future year, and setting the initial compartment sizes to those stabilized values. In cases where the model parameters are mostly constant, these future compartment sizes will be roughly equivalent to what the initial compartment sizes should be, which will avoid the initial transient in the model. \n", + "\n", + "\n", + "\"Post-initialization\n", + "\n", + "If the model parameters are not roughly constant, the equilibrium that the model converges to in the future might not correspond to the equilibrium solution for the model's initial parameter values. In that case, an initial transient will still occur. To address this, we can remove any time variation in the model's parameter values using the `ParameterSet.make_constant()` method. This will return a copy of the parset in which all parameters are constant over time, thus ensuring that the future compartment sizes are computed based on the same parameter values as the initial simulation year. This often provides a suitable solution, although changes to the total population size due to births and deaths can still take place, so in some cases an initial transient may still be present. In such cases, repeatedly setting initialization based on a shorter simulation can help minimize the discrepancy. For more information on Atomica initializations, see the [documentation](./YAML_documentation_page.ipynb \"Documentation\").\n", + "\n", + "In the YAML file, we indicate that we want to set a new initialization by making a YAML block with the title `set_initialisation`. Under this title, we can specify further settings: \n", + "\n", + "- `init_year` (required): The year to use to take the compartment sizes from. The simulation will be run up to this year\n", + "- `constant_parset` (default: False): Whether to use a constant parset for the initialisation, and which year to use in `parset.make_constant()`. It can be a Boolean (True/False) or numerical value (representing the year from which to draw the constant values for the parset, defaults to the same year as `sim_start`).\n", + "\n", + "There are thus several valid ways to set an initialization. For example, only setting the initialization year:\n", + "\n", + "```\n", + "calibration:\n", + " set_initialisation:\n", + " init_year: 2030\n", + "```\n", + "\n", + "Setting the initialization year with a constant parset, using the parameter values from the `sim_start` year:\n", + "\n", + "```\n", + "calibration:\n", + " set_initialisation:\n", + " init_year: 2030\n", + " constant_parset: True\n", + "```\n", + "\n", + "Setting the initialization year with a constant parset, using the parameter values from a specific year:\n", + "\n", + "\n", + "```\n", + "calibration:\n", + " set_initialisation:\n", + " init_year: 2030\n", + " constant_parset: 2005\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "id": "15", + "metadata": {}, + "source": [ + "### Clearing initialisations\n", + "\n", + "If we have previously set an initialisation in our calibration algorithm, and then set another initialisation later in the YAML file, it uses information from the previous initialisation to calculate the next, since the new simulation will start from the initial compartment sizes calculated in the previous initialization.\n", + "\n", + "Sometimes we might want to calculate a new initialisation from scratch, without using the previous initialisation as a starting point. This could be useful if we have done some calibration steps between the previous initialisation and now, in which case the y-factors will have changed, and we might be better off using a different starting point. \n", + "\n", + "To do this in the YAML file, we can add a section titled `clear_initialisation`, followed by a boolean value. If it is set to `True`, any existing initialization will be cleared; if `False`, nothing will happen. For example:\n", + "\n", + " calibration:\n", + " set_initialisation 1:\n", + " \t\tinit_year: 2030\n", + "\n", + " Match population sizes:\n", + " adjustables: b_rate, mig_rate\n", + " \tmeasurables: alive\n", + " \n", + " \tclear_initialisation: True\n", + " \n", + " set_initialisation 2:\n", + " \t\tinit_year: 2030" + ] + }, + { + "cell_type": "markdown", + "id": "16", + "metadata": {}, + "source": [ + "### Saving calibrations\n", + "\n", + "Throughout a YAML calibration, we might wish to save the calibration state at specific points in the calibration process. For example, if our YAML file has a population section and an epidemiological section, we might want to save the calibration after the population calibration section so we can see the progress made up until that point, or otherwise isolate the effect that different parts of the algorithm are having on the calibration. To save a calibration, we simply make a section titled `save_calibration`. Under the title, we can indicate the filename we wish to save the calibration to, either by providing it directly, or by using the keyword `fname` - both examples are shown below:\n", + "\n", + " calibration:\n", + " \tPopulation section: \n", + " \t\t[…]\n", + " \n", + " \tsave_calibration: \n", + " \t\tfname: pop_calibration.xlsx\n", + " \n", + " \tEpidemiology section: \n", + " \t\t[…]\n", + "\n", + " \tsave_calibration: epi_calibration.xlsx\n", + " \n", + "Note that when we save a calibration, if initial compartment sizes have been explicitly specified by using `set_initialization`, these compartment sizes will be saved along with the y-factors in the same Excel file. Loading the calibration from this file will thus include the initial compartment sizes. \n", + "\n", + "Another option that can be useful for debugging is to save the calibration state at every intermediate step of the YAML file. In that case, you can use the `save_intermediate_calibrations` option when running the calibration e.g.\n", + "\n", + " calibrated_parset = P.calibrate(parset = cal, yaml='T7_YAML_1_minimal.yaml', save_intermediate=True)\n", + "\n", + "For more information on intermediate calibrations, see the relevant [documentation section](./YAML_documentation_page.ipynb#saving-intermediate-calibrations \"Saving intermediate calibrations\")." + ] + }, + { + "cell_type": "markdown", + "id": "17", + "metadata": {}, + "source": [ + "## Specifying settings in outer sections\n", + "\n", + "We saw previously that sections (i.e. YAML blocks that don't correspond to actions) don't directly modify the calibration, and are mainly used to structure the YAML file. However, it is possible to determine calibration settings inside a section, such that they are passed down to any subsections or action blocks contained within. Another way to think of this is that an action block will inherit any settings that are defined in any of its parent sections.\n", + "\n", + "This can simplify the process of writing YAML files where we want to override the default settings in several action blocks, as it allows us to specify those settings once in a parent section, rather than repeatedly in every action block. Additionally, this feature is hierarchical, so settings that are specified further in (e.g. in the action block itself) will always override those set in a section that is further out, allowing for more flexibility.\n", + "\n", + "Some settings that this feature is commonly used for include: \n", + "\n", + "- `max_time`: Maximum amount of time each call to the optimisation algorithm will run for \n", + "- `stepsize`: Initial stepsize, i.e. how much the y-factors will be incremented/decreased by in the optimisation algorithm.\n", + "\n", + "Additionally, any adjustable or measurable setting can also be set outside of its calibration block, although some settings lend themselves more to this feature than others. For example, changing the measurable `weight` for an entire calibration block has no effect, as what matters is the proportion between the weights of different measurables in the same block. The following settings can be useful to set in parent sections:\n", + "\n", + "- `cal_start` and `cal_end`: These can be used to change the calibration timespan for multiple calibration steps at the same time.\n", + "- `metric`: Used for when the measurables should use a different non-standard metric for assessing calibration quality. \n", + "\n", + "We will now provide some examples of how this functionality can be used.\n", + "\n", + "### Inheritance\n", + "\n", + "Settings are automatically inherited by all sub-sections. To set a `max_time` of 120 for every calibration step in the entire calibration, we would write the following. This will result in every calibration step being limited to 120 seconds. \n", + "\n", + " calibration:\n", + " max_time: 120\n", + " Population calibration:\n", + " Match population sizes:\n", + " adjustables: b_rate, mig_rate\n", + " measurables: alive\n", + " Match deaths:\n", + " adjustables: d_rate\n", + " measurables: deaths\n", + " \n", + " Epidemiological calibration\n", + " [...]\n", + "\n", + "### Settings hierarchy\n", + "\n", + "Inherited settings can be overwritten inside sub-sections (in both sections and actions). Say we wanted all calibration blocks to run for a `max_time` of 120 seconds, except for `Match_deaths`, which we want to run for only 60 seconds. In that case, we can override the setting determined in the parent section by specifying the updated value inside `Match_deaths`:\n", + "\n", + " calibration:\n", + " max_time: 120\n", + " Population calibration:\n", + " Match population sizes:\n", + " adjustables: b_rate, mig_rate\n", + " measurables: alive\n", + " Match deaths:\n", + " max_time_ 60\n", + " adjustables: d_rate\n", + " measurables: deaths\n", + " \n", + " Epidemiological calibration\n", + " [...]\n", + "\n", + "### Adjustables/measurables settings\n", + "\n", + "Finally, here is an example of how to use the adjustables and measurables settings outside of a calibration block: \n", + "\n", + " calibration:\n", + " Population calibration:\n", + " upper_bound: 2\n", + " lower_bound: .5\n", + "\n", + " Match population sizes:\n", + " adjustables: b_rate, mig_rate\n", + " measurables alive\n", + "\n", + " Match deaths:\n", + " adjustables: d_rate\n", + " measurab\n", + "\n", + " Epidemiological calibration:\n", + " [...]\n", + "\n", + "In this case, the upper and lower bounds have been updated to 2 and 0.5 respectively, for all the adjustables in the `Population calibration` section (`b_rate`, `mig_rate` and `d_rate`)." + ] + }, + { + "cell_type": "markdown", + "id": "18", + "metadata": {}, + "source": [ + "## Running the YAML calibration\n", + "\n", + "Now that we have finished writing our YAML calibration file, we can proceed to running the calibration. Having loaded a project, `P.calibrate` can then be called directly, passing in the name of the YAML file:\n", + "\n", + " calibrated_parset = P.calibrate(parset = cal, yaml='T7_YAML_1_minimal.yaml')\n", + "\n", + "This function supports several additional optional arguments:\n", + "\n", + "- `savedir` (default: current working directory) - any saved calibrations and logs will be saved into this folder\n", + "- `save_intermediate` (default: `False`) - if `True`, this will save all intermediate calibrations\n", + "- `max_time` (optional) - override the default\n", + "- `log_output` (default: `False`) - if `True`, this will save a text file into the output directory containing all console output (e.g., objective function values)\n", + "\n", + "The YAML file can also be supplied as a dictionary, which would normally be obtained via\n", + "\n", + " import yaml\n", + " calibration_yaml = yaml.load(file, Loader=yaml.FullLoader)\n", + " \n", + "The `calibration_yaml` variable above can be passed to `P.calibrate(..., yaml=calibration_yaml)`. This enables changes to be made to the YAML content programatically prior to running the calibration. " + ] + }, + { + "cell_type": "markdown", + "id": "19", + "metadata": {}, + "source": [ + "## Exercise: worked example\n", + "\n", + "Now that we understand what all of the working parts of a YAML file are, let's put it all together. For each question, write a YAML file to calibrate the model as described. Each question will consist of incremental additions to the previous solution. \n", + "\n", + "_**Question 1.** We want to do a basic population calibration, where we calibrate the death rate and migration rate to match the data corresponding to the total number of people alive. We also want to calibrate the death rate. What should this YAML file look like?_\n", + "\n", + "**Hint**: Open the framework and look at the `Compartments`, `Parameters` and `Characteristics` pages. The `Code Names` and `Display Names` show us how we have to write the parameter names in the YAML file, and what quantities they correspond to. Those with a value in the `Databook Page` column have data values supplied, and can therefore be used as measurables.\n", + "\n", + "**Hint 2**: Some of the parameter `Code Names` and `Display Names` in the databook are as follows: \n", + "\n", + "| Framework Sheet | Code Name | Display Name | Databook Page |\n", + "| :---------------- | :------: | :------: | ----: |\n", + "|COMPARTMENTS | |\n", + "| |birth\t\t|Birth \t\t\t\t\t\t|none|\n", + "| |death \t|Death \t\t\t\t\t\t |none|\n", + "| PARAMETERS | |\n", + "| |b_rate\t\t|Birth rate \t\t\t\t|demographic|\n", + "| |deaths\t\t|All-cause deaths \t\t\t|demographic|\n", + "| |d_rate\t\t|Background mortality rate \t|demographic|\n", + "| |mig_rate\t|Migration Rate \t\t\t\t|demographic|\n", + "| CHARACTERISTICS | |\n", + "| |alive\t|\tTotal population\t\t| demographic" + ] + }, + { + "cell_type": "markdown", + "id": "20", + "metadata": {}, + "source": [ + "_**Question 2.** A single calibration run may not be enough to get good results, so let's loop over our simple population calibration ten times. How would we make that change to the the YAML file?_\n", + "\n", + "**Hint**: Use the `repeats` keyword.\n", + "\n", + "_**Question 3.** Say that, for this particular project, we are only interested in calibrating results from 2005 to 2040. How would we specify this in the YAML file to reduce calibration time?_\n", + "\n", + "**Hint**: Using the `cal_start` and `cal_end` keywords\n", + "\n", + "_**Question 4.** When calibrating the birth rate, it only really makes sense to calibrate the 0-4 population. Modify the YAML file to reflect this._\n", + "\n", + "**Hint**: We place the parameter code name and population name in a tuple.\n", + "\n", + "_**Question 5.** Say we know that our data source underestimates the birth rate. Let’s set its starting y_factor to 1.2 to speed up the optimisation._\n", + "\n", + "**Hint**: Use `starting_y_factor`.\n", + "\n", + "_**Question 6.** We want to avoid the presence of transients in our calibrated simulation. Let’s initialize the calibration in order to eliminate any jumps._\n", + "\n", + "**Hint**: Use `set_initialization` after the calibration blocks, and make sure the initialization gets re-calculated in every loop! \n", + "\n", + "_**Question 7.** We also want to clear the previous initialisation every time we make a new one, instead of using information from the previous initialisation. How can we update the YAML file to reflect this?_\n", + "\n", + "**Hint**: Use `clear_initialisation`, and make sure the initialization gets cleared and re-calculated in every loop!\n", + "\n", + "_**Question 8.** We are almost ready to run the YAML calibration! Now, what instructions do we need to add to automatically save our population calibration once it is done?_\n", + "\n", + "**Hint**: Use `save_calibration` and specify a `fname`.\n", + "\n", + "All solutions to the worked example are in the `Worked_example` folder. _TODO: Update paths when moved to Atomica repository_ The calibration obtained after running the last YAML file in this exercise yields the following simulation result: \n", + "\n", + "\"Worked" + ] + }, + { + "cell_type": "markdown", + "id": "21", + "metadata": {}, + "source": [ + "## Further resources\n", + "\n", + "### Epidemiological calibration\n", + "\n", + "In this tutorial we have demonstrated the key functionality of Atomica's YAML calibration system applied to a population calibration, focussing on adjusting births and deaths to match population size data, without considering disease burden. This same functionality applies to epidemiological calibration, just with different model parameters and data. A complete YAML file of the population and epidemiological calibration can be found at _TODO: Update paths when moved to Atomica repository_\n", + "\n", + "In this YAML file, we have set the `max_time` to 120, to give the calibration a bit more time to reach an optimal solution in each calibration step. \n", + "\n", + "At the beginning of the calibration, we also set the parameters relating to the typhoid disease (`typ_active_inf` and `typ_car`) to zero for the first pass of the population calibration. This essentially \"turns off\" of the typhoid disease until it gets reactivated in the `reset epi y-factors` step, giving the population an opportunity to be reasonably calibrated without interference from the disease components. This can be useful to do since, before calibrating the disease, the magnitude of the disease parameters could be large enough to significantly inmpact the population calibration results. \n", + "\n", + "We then calibrate the population following the same principles as illustrated previously, repeating the population calibration ten times, and setting a new initialization at the end of each loop, with `constant_parset=True` and the `init_year` set to 2030. \n", + "\n", + "After the population calibration, the typhoid y-factors get set t\n", + "#TODO: Deal with issue: epi y-factors get reset to 1 in every pass, which means a) all the epi calibration loops except the first one don't achieve anything, b) if we remove those loops, there's no going back to the pop calibration after the epi calibration to make sure it still fits well after calibrating epi \n", + "\n", + "In the epidemiological calibration section, the typhoid incidence, prevalence, and typhoid deaths are calibrated. Since we don't have a lot of information on the order of magnitude of the susceptibility and infectiousness, the lower and upper bounds are expanded to leave more room for variation. However, we don't want the disease duration `typ_gen_dur` to vary a lot, since we have a pretty clear idea of its magnitude and don't want it to vary too much between calibrations and settings, so we set stricter bounds. \n", + "\n", + "At the end of the typhoid calibration, we set an initialisation in the same way we did for the population calibration. We then repeat the epidemiological calibration ten times, and finally, repeat the whole YAML calibration process (except silencing the epi y-factors) twice. \n", + "\n", + "The resulting calibration from running this YAML file is like so:\n", + "\n", + "\"Complete\n", + "\n", + "### Documentation\n", + "\n", + "For more information on using Atomica's YAML calibration functionality, see [the documentation](./YAML_documentation_page.ipynb#yaml-calibration-documentation-page \"YAML documentation page\").\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": true + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 0de5d3e1a2fe53ad20d9c6477de129d32df9c3b0 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Thu, 13 Feb 2025 21:33:06 +0100 Subject: [PATCH 095/161] Add PNG plots --- .../T7/assets/T7_plot_1_simple_compare.png | Bin 0 -> 39161 bytes docs/tutorial/T7/assets/T7_plot_2_simple.png | Bin 0 -> 266322 bytes .../T7/assets/T7_plot_3_worked_example.png | Bin 0 -> 260718 bytes docs/tutorial/T7/assets/T7_plot_4_complete.png | Bin 0 -> 236545 bytes docs/tutorial/T7/assets/fig_post_init.png | Bin 0 -> 22295 bytes docs/tutorial/T7/assets/fig_pre_init.png | Bin 0 -> 32215 bytes 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/tutorial/T7/assets/T7_plot_1_simple_compare.png create mode 100644 docs/tutorial/T7/assets/T7_plot_2_simple.png create mode 100644 docs/tutorial/T7/assets/T7_plot_3_worked_example.png create mode 100644 docs/tutorial/T7/assets/T7_plot_4_complete.png create mode 100644 docs/tutorial/T7/assets/fig_post_init.png create mode 100644 docs/tutorial/T7/assets/fig_pre_init.png diff --git a/docs/tutorial/T7/assets/T7_plot_1_simple_compare.png b/docs/tutorial/T7/assets/T7_plot_1_simple_compare.png new file mode 100644 index 0000000000000000000000000000000000000000..5d73a052aa33facc09e536d23751b71f469273be GIT binary patch literal 39161 zcmdqJWm{HT_Xi3Fpp+sYAs~u?APCY@N-2u8fOL0AcPJo8DoB^oU2@YQjihvgba(d| z%l(||`k$|GUg#D!+-t45<{a}^V}6#Fe1UtN>^d468m{xCR>8Fwt}0d*VKYzZ={PvZD1NV4^ee>X8giMmy)bjExRnBX>b#rWbeaORmU>cLPS#5N zPADiSNckM{6KUZdU*;1fM)TUQ-}&(2L$+#Jh(WyLr`zfdA2Q_9GArJaI#tCJGbwAD zn6yp0Uj(91sB-`ANLC%C0`03jJUq*(Dr9W>I0Xd-rlZAg#%a86Bz_9Xz!H+T7Q8rR z>+I~rxx@X%htkP6!TtQ*_*IX-KKXcu>1%iH+<9+hrMkg%{6W^5R+>jb9W>GN*qM+Tqpse-({uik$VM8m+~ zcNr6p{&;cE2?L+9{c+7{-C}pr(T4lQYayXaNiTvGb}w@~ZqraawYhum-bbzp2Tv)1 zqbn*ZDxYx4n=;>K1)NQ|U$~~ei4hB?2ic|g%QK^!KYH-OBk8&h(XUUDoTD6 z!#OlEqOGG-e?OQ{NLe|$oEPqro16RZ;-W7+=i|!FIzh5pA|Wi9o!|0Ts51+Meek+d z-;i^fjfmu_SFw=b^kvBTU{bk!DYIT6JIPTk>rsl~w!Ei$t)j~LK!0T*=aFjZ7gn7n zv_Dyjk3&L2xZnRp3l9%RBf-Haw^9M>sPcQ(_sQZLBaFG8T^?Q`KCWVgx~$t z$IZ>n-CY?B#-w!cfMsiR-bAetTr?`gp}~p`L%iMtc-n6o&~h zzThcKFyA(oKQYsE&BfVcEiJ8VrGmO4sk}k*nt`m~x;i00fB&|Ae}DhL16WV#?`Vdu z%e)B-4==P?l7*YEg<_0hJT=rca|bH0g*iJ_q(`gq|gXCWIKSo9z4 zCtYvb+uJwJEPpIYPNqRil}eBl6T`qIW4}v7_F@Hc! z{UPOb1i_s{ z*#ooGO2sDk?L}%bAhED|2&i*H>11)9^cDxE?E7 zbSHXGA3;gzyMrv6RAkXWK~k!AaV%?Y`Fj5y%9!Zr=m@PZM&o`_HeuII3W}Uk zJRF=WzsAO5)vKJ|9_E*naP8Y$T57Eh6`XFjJytD!{{fc6&iToP#zDXw%6y#c7kA23 z=Ha0O+SvFwku54qjwW}*Ku-_uWp{tSX?VCyb$odE-TxT}VYn<(o1S}OZ2b|&4|A?O zoc7l>Fd#2kTplfX+}POYveUuUwD4zTuRTHVqTGOqoMUaGidVyRkLcR9Ykr&_v$MK0 zHEF4-3?r+nt60~sC+6o%%P5jRwV{W_0!!!*w-64=3n%A;b=+sqpQ8^C4>#>+!3_IQ ztNC4{#%-AvN(m}<)$gtd$L>mA&34QE;C!b&<4<@LndV}7gEMn;qCR*OO0cL>Qc`S| z`#!@u-Ws#+>Q0xrKal-SSXP!`YHI3{a#2g^-XIi;#hw&w<(%-XndVz0BrS7o5yL+X z@NYj>pM^T~UXS7V!TPw-csU0%GxHrjhcB@DqHk-seC-lAk=P@8*b&L1zGT)@qDez?&n8zXUBUwp#GWW7ZyI5ouAK)31|u+)nVb{;z~|VhPCfW&BHUixtJ78wz{^4 z8x$1u2?`BKU0ofH2eOy=IqPU^<0Od%K5=k#ByI2Lz^$&X{sixcR3TeQYjvjP3RdIWcd_Dcb%%H+%HZNe!#C_SX*0r*3{HY#o15DjK##q zn>(CtHRHn0hCxnF?g@kX!>Bj)6Rhui**sRKT|?m#^YK1Ccq<%{0kDMqbJVM%kwOM5 zp}Wl5!1gEXzA`z;<`&-4)x~9wY7ASeJKkNYul2+fmynPzLUz;suUAy4jX$TwJNccS zx;(X8eW|5I&8V2G3&ZbnIOT)Xz~yyVjv}c0wF)vykgCiRVKpM{cSv@SyePe;Ys9*Z;He+yByJ`4Sf9-9G;hDI6Y%=T}{Z z*~b0!se;35+P`m>mOxR04-xVud;T%!-?!3l{{QM*mbV*I=C}6-3@6^X$pdO&VGXR+ zWJ&i=v??qtd~ahz!^UYI5HzMZ&7e9Z>Zc8Ox10W^`nd^V^@jd?ZIRO2`X8ptZ9TAURn3Svs2j$q zYZc%XvruElZND&)RiG}s_;Tam6HFwp8+Be}Cr=r2yB;iTc1(5?5=SsB|DO*Ubz(l` zR$(-rv5wZHY)gT!#M4K*C?p&sB+9zJbKUQRa)`i46v_V zJh^lK+ zxM@H(ZT-@-S9a95d$zH1R%OmZJ(w5r-)tEjXgqA28Q|9cm{ua33lXq?Uhh1d23CLP2i@7$WE{BNw~g(PJ0 znjh=Z8(&sF-W)XHAKDd@qBK=}(M=o^+tyubBl-r*(*D2K#xRx4(D!s$d2{|tD)+Fm zriEE2<7Kj`wPZfa)dtZyej(qA*Z&re%r)-^dKFZvb8Cj)Wy2_{B;`O1!Q14b33b~4 zpPyRC3-?=LyEfcFGe?p))4Ov`FfZ2Wd-V&r;%_?*`)9=`1VX+e_w(|-o+p^n<>fah z{Y3S#mWDlkniGzC!5k8$XllyF)mu0pX3jmTOk#rEz`sfA`zpVnkF_W)FELz2sji2A z;ppLN?7hBAyGH9wKNNhOCH}ij@fqhU-M>x-68`kt{?rpn__SPjW19JY0}~RM5_F_9 z(v$Pmr~G%inyX^CnS8B6zC&^_B;n>hGQ@G!thmYpZZN*?g%HRCAAp49lE}z~Z&SJhr_E%_7jB>G^ z-S0Tz#pAExa>?n}s53GC`v_F;wRf>nzu)#vIN$ZUsx!LX-6HMgP#k)1Ec_eUkjuU2 z-5OXj9LU{c$z-WXy#1ui<^1}%WRq1L(`l$X<%5-Tp8wL3p9$RgziBR#qpzQODx;*N z`s%ZKUiw@naX^MX9o(|7@hww>&RFr$VzYvhlIHq)Pp$e-mh%Btm)rpj0A{@eSb1o8 z7{Q)a019=SO-&z>1!AzVu`#R3G84Rf`SMv>?~iUn-#{k8!B?>OItXWt(n>p->8JcV zWWIePVP%s2Vt)vmnArvvWL>rH(FRHrvhipt75&((_^ zFycV2THE$q+c5mp*47pdm4NCN9~x}300Z&;My4D6xAxw~qcg*zo6njte(nFX({JQ) zh0fB2yE~grr`?2_r9`*BNk)>vEh$(!G92=wm&rmxL$@|JHBa`}Y}Q7?+S?@nguN@& zy@t=fdjl;^Dk0T!rfGHfC!m?9H-KJNIqf+t#MvM24QhN22w)e`sQ-jZ%Bp>ZO~3u` zSef;eD_2wxjEO=olfg~s4^f4-dQstJwh=j%8{C*F?^lfQzVX)M_Y2dR>FJ>|YdUgH z)4!Wj^@PO4nH7;D`uenJfN;?6Jhkzip4N8STh?3c1;Di2mr);Z23?e|UcJJ?#jTo>_X2X%xMN^oFte~g_mA57ot*UP5t|0x zlSH8+P~N1%%12wPXSGTyk)$gNa#o*TwWrEk{2FYGrmYSlF!WBxSa)a`7#IkLk1aGE zeu6N4GEP(9sw)1cad`On_)hz)zk$wv_VxWc6D&Ai=Z(FbR>}nM>7M)P7N+~fS&4Q- zUt61hV&c6gPo5B-J=UlWh=_59&Xkl#;eZ(W44thuFj3zJ8 zT~#%;{<-UWD}#A;YS$U+HCZ;N{T~+^_cIimkH3PMPq+powF#IFlS(m(2^0uwX6B$E z3SNd|bq@0}ZW#NfQp=gXH}JlVJv^;A`fsHmhQC4zblIcez%xbIs;TcO(cj z%sA6rPx&K&-dqjc^V1Fdn;^)f9}Ep&R$0Z)6@G$qA8|48GK4wn(2>C z)R&sLq)-OGcj5|a%%@0xmEX5IPPu{lAnv&al>K>)+ZiY#2Gb3nC1Sa60;z$y@$2+x zr+*xHiSHnFAg`nmQiutyoc{n?zwQAQnO*9qNVk*LJ|J;y|=2^)W)g2 z6V3ZhR4$w7RPLv&alH1aAcUc>B^hz1)!RGAjy!di?YS4&5A?cqpeu1FnQ|AH7>INSZ$@f1K zw9(g#U3iKqB#Vhbr4hk}5mOoc2WTrEGuA{_Cd$T|wii56q;#*~dg|T9B^ExKHlUiO z_Y9j#eR2GmB*m>n;xd!k{pH?F#moU31fEW>(=&AMoc!?5e(Lbyr#R1hy);j|JvGwq zAIuaV$4ZZ98Z|xSBA)QLQG3>f$d0Y%EcX1OctL)xNT`n!=8oX$=H-h6_lp-G&7*-H z__tqCW9~CuytIAJ{y!48l%jk4$x^fMoS0S~7cdA5JagssZ>-cJYx+HEHvvi1TX*p{ zd!S!dDmEo;3uj6K1&Z%v^(Ru2|H%d1oPu-$C!0&P+j>YLrUF@%O@- z8;N#oM)|ncuWN%0yZof){Ft$}w)Wp-(fXz)Ez}<7t*uxkkbVuu?R~+|zX<#(LM0^f zpSqM!D`Ux2M6nM^#&8BAY8FgXke6^kbVC+RB&Qh}U|~i3+c0GVw*6oAJ@{C)YT*>8 zA)i?a&ub3#8eib>F5uYuj*h_oEXALo$Bm7R4b`{{;`42Klvluv)tWUlQ#X(BWTLwj zcwx@+Yald&Xf4;yYV+fbX|hme$}BV8tw>~G+5{=|?d1!%l(YI-io&RB)%Q*LqgraM zjr`8@@J!o1*Ouvxf&R56-!DdEWo510>Ez`*UQD8S@BlsE?aWCso-bpa0U5A>MI}Yc zoI!FW+s#W8KLUGW_vOnCP?wu6YR<$YC5P|*Q{Q3Ru(d~2 zpC7KSgI3rL42j*pMulUvbu#3T62}UgIO0RVGkd_sprvJLHX+v)&p%vYpO=^ik1F$Z z5R+qSt8?$q#NU^8&L-CSL5AW7P4UR0U^3|8DYmn-yCdip3n*L5!lDaM;WZo_8UV-O zEy+krf3Hqa1|kWI{G<^3l@gWPXTUQp59w=vH^oZgjxCM1W52d$)2ZsY30%+{WL28Oo31>Bq0%S9B%vuS-fNM zL?<(cE;=+<8|O-vtO^VM22#J#rBT4z3XZa2s6$jt03edu+V_B9RjErUDUryfN<6f0 z&xL|HGS{rOaOj{W;{Aj8?)^MpE_YmmozEsJF4w3V)>w@4&!8e2^`+lDKR<`P_)oI< zt#Z4yS1_*;64Qs&+&%)6aox?owU0EaV}aGMIc#duO2xN3Z&anNBP5ZSg{}8{KZ9VE z|LYDp)dV2cswz=2yUn3D62n=RBb9+8-%1;`bB^w0=MM(Y=?3}lx z_-a31#qQIqK0h|0bY5kJ?Hi_XH(f)Fm_XQxZkDr-l+Y;@tN*<=hozJV&}*qS4-V3V zeG2=tp)A~oHwi|lmbtn4DlcI7mG$g+U51Zv1$ARd>QFa65qa%mP*cplGg1ZOgx$CH zzH#9z?r8>&USG;}BX%+%0h!E-y#E9XaSN9B51A6OPqkNbY!AzZzE_!#HrGwdy79jM zFo~!7S9Sz-RTsB%)iK?b0t2eYx4%29cCeRTf1U<^JQQ~;(?#-=t z%d|-t>ig~F{TK!+*r5IhMFxo94n~|TwOx$M7LWL?dZn=u=w?!L=XqX40U;zSQoo1a*LHBKHqlO;f>!{&9MwvGXISOoa<))sIL9bH~Qs*}8+$ znF63LM;UdGziPE)Z>cveG$M_URtDZjhwZd%>hy8O`tzdPg^yyFf7r%3mK%IYJZliu z`+tA&=FOY4^Wkw@{9xf)Sy}a|L51s+7JcBqe?gbHzQI)uEfb zyu9FB)`9yQ`9$wJ)U0K5v`W|>5G;wPOU4y9FGd@Wz7^KudH~j!aL?yaEXj>4-sWBj zZXzFbjmtSQlU1BS!N~MbV2-jGbRvLUTU(pk<&fn~H2d?k-i!(mYT(QKa@8C}Ozg9p zJf-NcAJryA&D+Krk}tMSSsTp}hXj5k4O<=ONa)C53 zsxqSw42U-W7*xp0J#T)qgV)LR=tfw-aK z`uZOPmmy!o#n^97F5HoLLRuy|q`YjX*5yt4hOgj{+R5L%bdj#`(9f%ZlGKbfB$y`F zBmMSCigHqqIywlu9(vud_k?9(Xh`pRvabhbmftbCMP+SMAh{m0cgnN9nCUs%SPpGS zQ6D|}%Rr}sO?zM>GCBW*fYB?R3|L=Ib~d-$DK`KEKPO#X8t@v^zJGrvledn5A>+c! z26B!^Y4wB=6D}LW4=P+;v9?^Nie zUyb~E&R+0)?u89NHg&)u6oPJiQi5mfpg-s@bjGcYm4$-Mz17av#o~7A@Naj0+o#b? z(8_crYem1UMG_sja(4R49!B^YZyvnnhML-Bxtll`mq7!X3zZU}7N}lLCZ(dHQg_{Z z3%J{3ep!Z{!wV^feezvQe80X9vCr7Hm3OvN^%Aq04WArd(e-NBNZ2GZ zucbJ?Rm!h_|EOLrM7v&J_j0+{r!Jr6pF+*@E}w~+c^)iaItGSU zr5LhTlG6|JC+e*)qWs#S?6cr@6&Ov1N~vDeAX-P*6Z4xJy;I z;Bx)RsFbgBYqGT|om4!cRsGcOkmZW{2FZy2%(pn?ob5{FkeeYTC7lzq%1i4u{HL+5 z{_J`wA<-~Wz8Y8#VHlgmKOach^f!Tm^;S9C@8uAM06_CyW~fR3Mr9YL)BgcmcUFzp z_jy+TpPa9lUAs86zs3iY23K%n-*i&*mtd*9rl>7c%I2$zkM;I%Iet(3>3YzYlI7vc zgH-N_I7O@5W1j-r6!9aaXCTWs%tskG9L+@#1y?}E!_2|K;ZMGnaJ=(6kF1t1r1PXut?1%cE*xClN_mTI>yHb9!o5p1X znim4LQ3V~~0@NJKZii&a-9@q;Sy1Tm%H+SUBr2!B1*A`6%-MpEQ!pt~( zJ8XO8@r#$O41(MAxk-be6^5+h2M3AoHw0`M%gb%wYm{B8Sct!xBkn$XotiMr}k1~yAQR}BmnVkAZBA3aLW z-yAvpxw>k4dU}eWk;D;S-!AP{Mdv;}7d2D3f$yavdFg@!JRT9p?DBmgQ9Y&D$u+0f zy`5X#1<_5LgKD>OxVnd0?&wmlhgEE^=s+3;RQ0=pHLEY1-0$;ZVqi?q&x_gE6qR37 zR8)jKN&^%!ad0tUbQJ9~zWl$!X>2yFSGqay==9R!lAeOisGw8MErIjco;aYoL~HJM z%DmLwHzw<|*gZdtQMu1a$;p*noSzu| z`Hp@W1LrO^HM$2~f=h^^x+Ca|x#bR9_cAgv9GsoAV*a+;c){#qHSVKtZ`X|>13Y-c z^<5d~- c!&SNc&!JT)p3q|s*&>5^qR?2i^TV-`%-x;`vSI>aP2?6@Ep2jKI=su* z_)1Kh3gzfT`33kB3>djLf$J#)3J#@{LiF0wQf|}S6DC`TA)SJA;a6S4NJr7}E6iG`ngOo~)KNr{u`;IVs@t|EO8aPy6 z>4;b78yay$)v&aj;Qq+D%ymI{og;pG6%*6?{M1o&&5i;R9)JEw3keIOBg^j^F78~_ z!9;y~djQlfR^65xWbB5&ke3K)uVFAzAhCkn-HzG#*jPT~SO5u#1kNoa#%`1y{}BcD z_We=CR(+?npB;7_F;|7(u3p0)^a3XV^^im93{oibcHCx<$ENks?aY3U0v^(QB# zHaoYIW{JaHg8`OA0Hhoq9ko8()Iw5sB_#`xO1Xl8VYT`9`SJdm%GAC}f7GfDZ13j# zA}K6KX~KTdPz={R$GBs@2?rQw*8PtNBr2GY;LPSIznSOVNbG8tFVUW#^X{di(&?{? zDgRtwVB~UmBF>!pFpY6FPGKv}7tC^&CEqnzLe2Pss-rH-N!{NESB@Zo0yp4;&|F{V zJl8Lbd;DS88b7!Fhi&+NsHXQDv-9<^K9k8}+ReyF4s?&+ji8k$F*c(-$ES3+czD~` z`ueNLs(r$)$9&Sveb=ei1ww;{;<+t9f`gNwkfU5+yQ1(3hqUf@D4qE0*Y_Vi3ING3 z%OYbyw*ep?MV!>{x#5k2(D*FA*yn5D*N{vMXsG3GT`xAHbM2wo{rzy6ww-Ux^4O45 zp$caBkS%T0uzT#ivX52nIZW*iuF|)TQJXUGmLyt|Yl-i|?%ySN5etbsu;PTFwmE$4 z@?8CfpAzpC3dD+ca!qE&pyg9?62jvAZfmE|$7bb^ASCkOh_x%p#M2uMC-uUcZ#yiA zg(BmBdzzWuLoU}3G=6h$visC+@!pYWYv^tA6Yfoy4U8h(%3?(`Q!D0CDGgeVG%Qfr zl?QB7U0oH6lmn+HqH}4U_!Zq&Pd@B>XnRZf_U%~xjs~Z{Xrkkq9)ZobB7X{eY_HT7 zC07(PO4#W4z#KguEZ<1GaX}o4Il8-RQ+=||d+**oG{c_cYcR7`YV{g z4wl{Moit;IrK&k%^(w+KPw4v;$K`oRac0jCZ$)iL)xRJA9isSdZ}sy|tkj?KiigV) zY}m*vu1E?Y+RGXlw4Vb_Vau)%LCNd)Ksuq|wPOJ~e20PpasJT2-Mk0dD9U882W6tT z$J8GUvbf0G?WUgh#iFVT5pCVZ9FIWX)HW6}OO}$NJDXFaA1W0e_iC!UHpByJ!z~O5bmuQG$EwQ>Hei_N1x`pFWuNwyllYIFS3$CjROtz`F^406tj^{@U z!&S~)&B0WPpyeanL!PMMcNyRI5wqxDiFUrnV0+pg~3hg`r6 zlvPx2L7@Y~mS_+5K7=7`@9YrmElYwjk(e1-^Du=*y`AZmTMPY`83@!N5zy*!R%c9O16VfaD@A?h&z8?2EJef>TXYMl|AA5gh$r{9#$|$r}HhZVZ zy(HL?yc1S8X34hRl7HNTzUwlgz|HvWRwK7q5p`TLwxyZMy&Wto#4$!BXxJ09_ooE64a_T57n|;UfXN*yQRn`a=`X@@s8D6k9_@=vndnfhaJ1{Ow}(`abf< zRw|u)U_7QX0gvQUi4SM}#E9znBd^1Vu`T&4IST$_NmB|^N!^C@OiUM}=C-tmZ~C_J zf-`<tbGnwhL5$+*6{^Hc=lXzKnj~J zOyEZMiJhXeEW^&q8$=hKO89x2%c<bCMWm;xUh`V5uaO=twijJ-9GTM9L4T&N&f4{OOiCieiaKh<#50`$K z*AFR1D%rJoR}3Gn$!FGj%O7gd+$sDQW^8ZHD&#*lHg)F}hG64Q$6q zPB_XS9?Zc@0G1lHum0yV5S?Z5g7D(&Jh!}+Be)Utw*8E~*LZPaD70Yw(zWd(x{B{! zk2ysPnNJBsAGFqbKf~vZ-x&8`#vLQtBdgcEyD+-Z61#<-K44>LYGxVFb$jLfEC2-s zQ9qCW_ki3SKI)I5rfxG@e3c*x_Bch}Pe`iWhuZ-rg6RB6?9dR!aS@0}h|}tS$Z^`0 zt^GKB^45g2^mBW+p)MeRAMM>y)^ev?i<~iTsr{KdccTs zi1_fIykYs+rH21gUWr&%+gxOf5u#LHaURZ!F)r$95Rq*T$a*i3^EOYN8=~LJCxsj0 z856$_Ms*I|oNqqO&%EYS4 z!S#g1q@t4soJY&T?Y0fQQ3#rB@Zb0tQs(=QBQt#faR^dzK?C%Z0EmY3IaAu^iz%ln5w!L5CRP`afZP?G*_>Sj?Sc~ch zwyU9YLOINL(SijB$b`)-KgXB3$LY6*)WdfbvZg?3jyw@D0WqoX227R&m+foNlfe(d z5j0-})?A#A9uAe;W+BFhuL`{k1>xVs>zc*k`g4-MG8f-}AWKU23MiSN-8nPTQxR2d zPIToRyHL_mr3r^s$~L)SuoSLH65RrKs1p6wYN~WK}8oQaW zp*=7XT3J4ewUH;!9G$sgBn7KjG>4YH>iySmKkDhns)fhB>R0ln`0Vk>u(6?(VV5+s zEH!)T&Oc0}j9e+IEsx2R=>vCR(==4+~3keXOi$CG*wU zLOL$o%E88D7kFo2jv!L{zswc5E0)fe#>|#TR#VgU7Hu+!I62g;rK(P)X@;;a}`ky2>kLxWh+{mBq7I8fJkCU9!Kr8b56`+iN}ptmrD ze|!5&N^1c@JK!(*g<&#(an&p61*>Q(Cptv>>p7DP$)6rYwcLU2!Q2OPwHM!|#AW(W zxw)k|N}u+=)S`*d>a)#f@vr(xK$pwnNQ)l3s->H$_+UT0;<@@jLd7vw%i3=9sOhBwMdh#7%eM~~gXM6Jb$K;RgBpehK3c>Z zYnadOGk{gpWSiAhQ6JqO+x@aCK08>DdTn@tm5@OSvzG&_X(kw@RAi3(>yyqkzP%20 z=9C4-VI& zt~@_pIXpShF)|W|EH+SY3f1B0U8pn3(24+&^Ip&|p!dLjobj7t_e(1~J5CS~AfiO9 zp`kI~m5^sRXvmI)UqC-aI-DSkKB-c@53~T80Y{)9bQ`i8f)QXgit)=E`?dpE43<__ zb&ZYQKZJb<$jMDAONxrVMQFH@($UdDn8xVL8t87hd0&jheq9w}MEJjaZ{8n* z_Jf`IjwG0mvAp&{-@Xxw1&}!2!R5}i}#_or4btAUe7cI zLO4navB&wH_u0>Rj4uPm2WRs~+3)wYNKhcxHa z@QgJdbd2cg>1{0}xYvbg@*4Hf2%PQ8=_L4#Eu+xgj+f{J4*y;TMiju4m7b0Tvq>RO z{Y`>^D@6aa0J|bG1=_c7-=rbIs9a*Mmh~}59Fl_3?4Q9dAfp04$p=gW5th>u+?2=F zK(5FsioJKv=Oixk^N-Qet?3R|Tz*1Z4~_lU7kOO6+#+G$N?drv&oI8>qxAK;J0pX7 zv!e`co-(J-ZOw8yGvc7?M~{DMs;XQ=aj1fa7x;tt*XU?Wa&lqgH_+cAqoTSY8n?18 z9WCfCfQ016$0@+NLF~He>FK_4^Gu+1bGi5L-6KRnFB^UCkx!oM?xIX$QW6rd?d-&Z zpN8HidV2c1(6|J0H~|5H;be8y7G<2I;?&BZ4eW4(J|pmWPxM*|kya#Vu3KOSYVLrt zv!zA)kq~smC>EKplkFZCdWvV~SXBS9g8mms&v_#=7$S)Tl$4!A1v(EI%8LbyGN9#; zA@^d*WC0xLa$A$S`g)?^mX?=DgQx9*atBxp=CdGKLQ@{h{+O=&S>}imIGu1j*~E5w z$Ifi38F^V+1DYO~3u|}J%dg4+;6OB$rj_Ws?&Ar%)jN18;&U%FI)Dw%RakUiy`stT z3(0mI4=!2VAC%-IZg)w3@WZwZ&)~)@C(jR$`s1q)qCEp0QzRXn_xcrwOD*q%N%Xew zMIf0dbUcFio4J{E48;PJu}&y=NDC1Q%NKYu1#Y6LlnC`{$ZeVq7d9%b^k?0MUOj*} z!dH9I8KV6VkA0@-vIn#qLGwXIq+dQ*{*41_VUBAs7o(w33{uP{tI(e{xp};j2Q914 z^_4Q+@?O7wJ%i@L2XZ$h%o_cON=r-A!P<~9St@ERnGE2Y^L>*s@vL}Rgf(tB$MdxrN{c!LwJ2WohCxWBtatAOS`lN2lfLDi6>orRw+M^?Z*)7Mj_ zqXq#}u$&Le$;#4$=TXp1iR4pYzbLd`keo>{s`I+0TB*b-GWullaajwWhfvRbivB1D#w+a5(oJ6-`qF;J|eew=#8U5S?Zx~@g2;& zO5C)-lOgr~KNZtoqm4!L=nk5x#Ft0nP6hLrD$8E!SopLlV!w~(zZDop1dv4HeCY-w zzN)l+3fSn?j+w40`-epR!kU_Q!I$|9S+U*aet!t4{Dcs1_+t%8h~xB)TNr|l!MFQI znD63rhuyf(7kbx1V^la@=YT+I9d1qqkg$G)UkZ(mZr$k;%yaWoaheNLBqStx z@m>Q`V~E!P-L`L6eadBTXrhxE*E`(g$yr&s9mm~b+JU=N_4+2f*r>L5LS#RDNT9mhA= zHVSpT9w*PU>iyR0Oru}uy~NjFB`{Myn78}#J4Bu!XOd%v5MuL`QV}U7`6r;^7_v)u zjRyriHwVmlT7JNnko&kMCoEd*azdc7oY{dc2aq!U4YtA>CA0^vOGK(XqU}aayM=NM zxmWu6WgbeLt&zOTlrh1M3(vs!dhgEm7!+gbFPhE<|E?pF$F(V^^ysx+b2xdJZ6WG! zfh0N~cmz^|3HnFX|0^?N4#$kv5DvR8>6`RBR?=^U4G4Q_@?S#>@wXK1fHtN zpn@Zj#B%W;5TQ=R!`IsREaEm|8`RQZD(XD?OtHxpn}+@SF;jJaTFO@*v!{-XZgO1c z-?6cN8SP6vs<2@l2r0ZCS-s7T*_HC}_!4l)ovoytO`C6LM&38L^g}dH0CHu$7IWTT zo%-1&Ae=V{-F4s1bN?wD4BIog*6ovo8L)+GPkstml`oF#AD+F#oHF;L-!Of{NYU)J z=-kB?CaFc0rvS&>@heX$_PYdq&Kj;6X15Aus#|C_o^unMe!f@plBXn+(Z2znpmt<> zyDv$%WhjfBjp}BZ@Am?54^H-qIr4vPjGhKh(^;S~QaC*hJ zR`c#X^|FMLn5qX^boN;{RUDT>t+UQ2mjd>;>)w@ndz>86hM#q-$aG zs!W=9luEoavoZ5b}!md*@qN0^&W6Z4nE2S#Cz$c}jG5X=zzM`*^R> z`h?Ro!QoQwomT}A3=Vdw_D2AQMy<~$q*q{PCk|`NUKTXihBr|(LvGLj4KBhq$a9;J zWzBa!Fo(3001|FW-(sitxy^XpJSDUDXXXRX50#S&A$?VtSKZB|OA>AEn&$kEO5ILy z_2czw1s-O3aD{)`Sq{0c+WDwvJ~20j3A+h3lk?-vzdSHDbpunBZV)i$MrfJc89K1exK*#bWd6Sy*Q*H#o0_>K3V zBfVz-=~Z&hf4Vw5R@z19vz2*_Fr_;n!aT_}xf^Vs>r>WAGs6U3imfyoccDdL8bU}- zjg41dyl5sD04p@LdjUAFX5`7ve{*e2~v6@Y%qCY~KkpZ#A zA@XQDJPX17&Sde>zB%VtXB^Oxg8=)Py{cn%RTTK<>}0s$GcTty)YIHAMuj2Wvb=h? zzvb_5iXtgmP*u^uNMD+)^8uCq=br98YX-|il3(9G1UjaxQP`HXvd+$afmL1h+D(QF zU6bDiOOh=$$(D)SvGXy*T!k6yqv2cr)gLo%1MHAk9{f_>;i_vH$?{54avp3fr0H0- z+JzMQN|cKXYaxsF0-_n{h|fJdO#1ru+~Y5)1Hi_Wi%m1ILJp#jO`tiU2`C!0{gx7# zD&{CR=4;i<+fVT9nOr6$BKjI0{wXbOfvM~9VM$9~Gca><$z}uA?Hx6j;;8`EzDqRv zvp?TE<6In>(m^u>j?r9NY2Lm1k;5&`(M&31e>_T>45>+g5Ca{!5f(MIFtM7Xk!0|T z1)nXsp|b13YhM)HPLE}8AEUlVGk&9V*?bOyP8|?J=zr4fh~}`_n276J*%#U0-Y#GH zQJiUIZ_o8<#67cA$x&i&4Gg(oZEabtpOhtTnkKmJzk`?uu#ZJ(L7D^bk7y`~$`AqT zfn07+I#*c%O;2PK{e?bKWaJqaM*+$p9dv^q-a!r$8Oqm^h~dPAyda$9;Q$u*Lk3y%e)}ruv4F7W z$Gp79#l^)%7L)PtF&PyPb#-+&A%p|R5PS{`BZ47>?w@nCyBr*002-%PR{R44aY4B| z-F|(fL7A5p?}zpU!pP92RRCw901PE!R3I76b#r$++f#)8txxbFaJ(!q;JkSu?E!G~=Q15MRku(|7g$ORqSDk6zIX#7ALXhq#ctu-~FJjYfz_Qzz z=l}%T1??Az@DZS44Z;ufD}IMe4V(t@5oSjWgp<4Tr%?6E5_3VGP;A>Gj$l|2N)K6K z*&=Yidx6l$J1svv-eWw;sZNE{dqmd0M$5H)kt${^UN)XyX<<9S)G;$}!msEoTxmz$ zr1scovj3i;v8TcvQ=)y9)S}Xxy5=-JOLVlDyDP>&*L;}J&)>)q2@(r0^z^BrLl<^C zxp1`XV28pu&HC460@Jc5$6Sz91DDRIKa&V5=gij^lrlKJZwXCnAO;-ovMr8=wDrJY z9FVui2JPbtBCEi$6284@ZS&Q^q->vHJGYvuyE^mYM8oaqL0J6$0mnI_bLk zuCU4jKTv#!b1jOD`~9G4ukP?H3UZ5}C$aBmwB)GAF#0#=;ui<=@00xg{o8cR!Hjju zB(JIoRxEOsj_OhL2JH4A7PMsV>jma=bY({e2BgDs?EAsSQ$nC(+ z#=|)}LJ~7ex9B3UQDkv=;0FCVE16qd9(WEN&MOl;;FGPx4p0>qRPu>a?|i73z*sbe z|M0IT9H|7;o($~&W*~ru@D9KrlC^(ZDsbqeKFq~KLn9*d`qir^>X(ZQyMf1e3#~qj8o#NNzlV76&0Aq4yxQ zc6J7VPG2MvDPzQs&t~7lk6N=I;A|g?vC6tZrA7(y$!!fZXkbpB-x@o>JhVA8y6)d*G1br85R>xQR_i6B zV9_?)voTsmMnNYrU2SjQdSUqp;Q zizF*W_THPw-m-VuTlVHW-hF@P!a29|zi|GS|Chc)`g}g`&ucu#<8gnQbHuGpXR5l( zRaxgyu%FO(k5(z3JyV<;j$m?CVJUy5j*mY&Kjy9h6bPA_6(Lb#f1okxS6eJE0#+q4 zIr(Q#k6JzXNq|()UIJJN&={#JIXO9vU6Ak(z@Yoi_2T9x1);aao)~}=I2^@O#JAlE zQ`L|ZrFUAOOi96+T9K26QuV{e)YB-ZU`^kXL^U%6yNg>OVa)g+D2x#TZyI+oO^17o zR1GsEy0R_DL}v|58j-L0P|~S46_Bo3aC{k}oIHOI<8hjCLU&O1dhB`$7rblXI1pRm3@ zBhHR~)Mt88wIT|>H~?qsMd;X`4Bxj{6?Ayi}KxF(lylKS#lFcL1^_Pu${Xtez$ zawO=taeflDF`H`u0+a9oW}lAy%vhTi)OjPglbCkxfodx3mJ6LJ8Ajt4?=9yGU>Agfe_%b)|H;P0idyXj61#xk}a6c~Snv(35AMf@3WNsJ04>A4!e+zI5;Goo%~5q#I^t?U|() z`@1wI5#vNAgbcj$3yuyU1;>z-yqe}`Y-!9eoV%tL=d<59qrVgN%=UDXT0GOcEpaM( z@NgiMVj(V8ygzxXd`&_h2n{rG-x0-k=(-4om<4wTIt!QaI0#c1bK z*3lmORW}?(mml}v_T$hi#CfVsv%?Nv7UFP%9y=5|S)2&#A+IRGf-1rNtJj^wOE}P= zZ6$@?UD8TAqRK$R_wo*8e)ub1W@p-<%tBht%KRyX!k;a>PG>^gfxilEL&}bg-SHNY`_V{x5Gt!&a zUu5m+IRE8`S-T9!r%z|KDKEiy>0b0nji$s~vVF*w^ZhlZs6cqU-hcRDCgBl6vG@kb z$SM8Yvez+6Zxo+f{F$E99~62Yo|{!()==+UE0P}T`K|fAkH|_<`F9EXOh~<2+y0=r z7NBjnoAQ$(&!-=KYOiIF>O=Ma;ABV&T;NbxEr6JCWxD7vAuethxx~&ceFcdah>(E`#eu^cO@IFEw^$xou6eyPBLb5DUNs%mqli!$ z-V=l$2Te?-9xK^(xs~^9()$7)HSdE6;!CKQV819TuOYfPz8B!8Szt^IYGlzSKXut^Pw zO!x4SZUyQZgkB9M3q7tYkI4Zkk!LB=9;86R8a&O%8UEfV{NpOW4KKqhV{a+NyERm# zwU`o>z?#t8W)VA2BV7_!(Gp}9ro|Jpm@rlvwr2b{`&YqOs>LFxh|2_@U zRB+8MAkHo+3F|zluctR4-y)}jV&dB&eoQ%8ii)E7h0IuCe!;`sM3MV*we4ZGTy zbC>QS8o5M$`JY2JSYIiL|5Ghj04ynw^o-^HNG7(-nxzeno$u(=HiDH}VBy}lz($H5*omouuMiku?%6;^yZnt=E{BhqWNvZ0}E!T3ef6a#v@zg*?dnHiMaK!uL)rfC5-yfgaXRt8ksQBtdFS`yjc<)}i`B#J;@9dvYqB{C^wsg}; zXw~vjKLwlJz#dDHbJ5uvCZT;38r2Z%NE7Rac&0|sNJEzV8>b_>bqAi~w)#CaRg1tB zPJq1s@g>T(EPqrMUNi9tUReH|mJ%tSMjl;2(wEnL^VYLZiFOcg9A4pg1gb*KS#4>l zsM3ydKhT*ry}gR|6&D|w=n^d`5$iW;zcu3MGRiVQ=zcz5+0zmJ<(8bVj(UBz_L zJbVtjz4nzx8Ys#L_m+$({dyJA5+ID`q*N@XklgO46TAm;G9I2LelR+ju7#2}uqQ|1 zL*bwn%bX1)+qsQ!`+-SF^th3y0GW8i4s{;1P(g)c97Vj5k(Cu(uiKht3pDA zg~oh=%UaUV6@Q7dp0MU>t0o3}_{!ZJ8{1D+r~B3Jy??NTw(3E5uE8sv-&m&h8Ktqs?j;UT0w~$x6P$aSbq$dqUyffs836i0MS~!fJUpp;>DeT?sS%4 z`q1mHa76n>xQD9jW#YtHC~ozSpglX$kxqmde|jHJKpPXygh=}#Ye7?Hl<=RW}yLDxX)E1zCzPfrjoOGbUPMha^tyVrk%VO26sdhE)2 zm*9y&x)P{*d>32v@T@;xr!&!P6CB8kfu!-^bcN6(B5`P0kgEt(p7i!KA1YfOHIO>7 zLcXV3$x~3{^s+(A!!nk9vX*(Aeb}aNXLBT``4Y&TT2zI`Mk@%j;>O4&s2py^%iCWV zdZ<&7bH4qra=iKz?WD06K;N+8D1_aSAZ)@w{XN3T(UA?M1TUk-P&i!Bdq=b56;nv6 zpr9bpbVBcN2f^I9A|UV}MfV_>m2ao>th%k8h%yAoGcmE1!i>0)5n9qBhusM{3OD-i z`IAk?_h3k!o@%2s^G)}m4V9tjjME8gy3n2*5Mw>Lq5do&_JQrvA%p!)BG-FBP1?e2 zcO*4C`1|YNn@;6DGF)nDXX%Bz`rcGMvr8OpI6l^$n>gIM#m&(%Q4A5z>K~Ui6V0>M zjup%mB<(x1E>9E;X0)ngi=d%=2&(D*0D=%*JwzTFmyUu?N@(Yi!+nB+A|l(r3gI9s zdxY_!#4jY|48C$5c$A&<&>^NjdGdLWJrlnhaW|q_{kQ0_#Dx{v@BdGdj~Ti0?drZR zic({0{mjdEZF7rUpAjXl>7Gd@Dt%g`s*$GgNm^lu*iSih@%=h4e)^jhlc&?w+chs) znJDy`71N6Tq{>gX<{XT-vo&2&-}$L4i~4440ST1B*1eSii1}d2ZqkJe@#LUDy&_Q- z7lw6g9o`!p27-8FMHLl$k@CPycMqZxh$5t|xP6O?lB8c=5%7+-5fBh?Girg3pN0ro zNsu5u{PBECMs{{|wl_PNGLRU%k%P5rL3OG~03oA-vn)RqPn$wrRqdYGg&@0}jmMiM z^gW|dbG<^3saQ@A)R*4YrM%JJQ0tlA%RM(z!EityF?@{8V#&y+VBuKVsm_+zV*B3h zRmZtmL?h)N4N=XOeh|ea$j!R>gz`SMWE{S#(<`q#QUpVBL@Ig)BRpc<->Y-$8X?2@iz; zRf6No9q4>tK>>KgZ_|AI{KxTU5Y7|{$S6mJ*T%&5Q>k>Ar^&Okh6x^cnJHfB*m#9d z>biEG*35>X^_X=_Tzoit!zHb2hu@^K6|hFx2ndzBA4~6N%uAZk(E4nhp^3J#oSltk zTPUd?lXPgD&ZTQI4=G`?Zbhm7or~|lU>zDc5v*P-Tt(e0J-+;)6D+o?>`Alo=W7Kk z>JyR-bKs3oM%Ei|iB;kz{)L7)ZzFGWZRjde2h+i-W6&~Pv$R}beiiFil}OP$d8d~7 z;lv+N1hr?<6Sh++k@9grIbYQC?n96h!%EzjPT9n)&9T_}XZh>xB5T!SJSZXa5l9Fx zDs~2zraoX%;Ch^x4L5CJ*~?`Vrrtn**Q;WR!uHId+i}gNaBkwW z)#vc)R(c%Ofq?8Py?0kV!?@esQ=CKXtS#J9Jq=&p*&Y8CmlyrdYmx%XEvUqoQMLMk z^A8H62VF6jbZTfUM(8AWbwsfw36;4NO|Ixd5@Xmd(eK`scwb&Nyi5}8hnkd zWEO0Y5xI`Z1tCIw)Q2WV9mUNIuK z<~1Lz!ykhZglPN{#!aH0rJC~@VxDPqhaQi&vJv$~Z`n5ToUvE2XuolCQlPd7G#5If zl0wfCc|CFKNc))RtBcZgpJ?9~EB6z}b%|ZBJX;d)_f$F)GQFsbp|qp>jsywDUYU>f zOc57Xn9rh%?#@jZZKidzTaMkaSspPiOUcJnNncNmw7>e?zVEFm6q8*f_%y44AT%$$u zxhpKWorOv9L532ueB#dSu}7VqFSIAOWSo;92^Ae>;r<@2_V4{nHtcd~j=dHxozhbt zaq)S)3t8aHuHhr&;=0e-)pE*CP!5RVQJ`H0Nn)KKOxwS5of%FF$lkYwDp(IuEEK#2}|w9yCmj! z_eM_6qmD9Ed6n*=giM7+t))4UQ_nxL?Hp%r5)+2c`iNosy^RvLBeXobS7v5yn1U0N ze@2OTBr)t1uqFI0DPv?igAXTb$-vz{c?#t)D9KP*#9;+$62ro4A_7I(IcK`$IO=*# zlhK6VSkfBc!JJhZFpPq~r>u3jJBo{b(BE5-v_~bPPv0PCgZ;{vk!bhh@d7k4rb%q) zFH2@RMAzKAIi=lwZ@A-tj#AT$?V+Js;b=urK`ku(cp)ZfoxW;qy@Jwye#8wBVBIS3 z4qYuICRgbl5yujyYUc1><`Tx!AxY>~4c$9rn5xL^=l`q*woig`0t!f4R-__U&aDCF z&J#c7mEtF4?jK7QdGjl_K2_rRpow#TsY(mwryb~<|4a^qU$9?SdFKwHa~bVQzd~O) z^}c4lX~yQ5U3g(>jCF?F@LG`avZR_z-Tl5#%7bLb8Ta3=8zZ{~a@Bc0M*+$5fUJ+@ z6FDI(nXPrx6%mHfBsv%WdxmfCyqti5gYD?Px$!nHR369>&}jODnQk%GTwFSIA|T)1 z1K)7);~M&bzpYdn=@ctO>(JU(R~m-g#Q8=o!Ii#`52Ff!OZhwcqr}-Z4qRa=7+Cw` zH(jvWETp{%Ntt!`Ep>rVv`S1=V98x~RNvXn%P;mgxUM@&UT! z*?3s-e86u*7_ZCJ`Y4BTO}Vmg%g0fGpNZCJt4idQMyZHHz{7zTq|SNkic1F+ zTYT5qA`N*TYz&W8ER8ISZ?{%eiiwgC4N>o-pJ~|?`r}S})R~c+;z!lb5JQFKI5+iQ^UIYQNa$z}SJz0-4e>cI&|OgSmD@uZtEAbL zPbas&5*#gGtH8=qfB1xtDp&DIM#s}yTY)3X}BDe6iuHw zS_J_a3%Kg=1!3SX^mK9f7ZaTo)B=|v*F4H&`t`qLD}rp_PM#zFB{dCqz7J4p7-^LAO8e2=9xiX(-8(>6-R=&S-YH^OfBrDngPAS@&UFL+S2-tzmS zPr+Z;-8iTU2m2*CysgK6jUo&HwvrwTl#HsM3r%9-mKyFe;ZR{CT3*+snqW_T;8lM2d z@hoBVspFZ?NR^%#jF)NX%O%^)UDKak$Ture#b;Y2RSSfw8mn>boe8x2<2sKr%95fPHR^IGOw zR)Kf4tsXsgbO`g`vyc?t=PlW$y&?YDzdRxasUs(fB|soT9_xy>8U!nqpn?r|X0oH# zOLRZ`2fW>Kh#Nu3!UvjhcRcGyR1dX`h2Q2M{%}nxAkQHN`hSG)3?0Bh$eH;sx3X2mi^Ut>^Smu(u zS+woem$PTHjdQJ-biaFQl`BlNRcS<*s$V$#BzOC+%&xijyHItIB^VNLl@p6$7|iyY zZ}t_Gm%l^TZ>CKrDDh$OUT`oP(`5{Z_v`&hx+q}&prL?8W~ZJ4z{`LjUxIx~OiJ!W z@Pyods*RSk1^%ZjZd6pX_va$tT1W~`)X@FO`)rr;*5jJeyB+E!m-uy0BK-fBnD9gW zd2%`Lxcfcr7AQm1$}&cjyTRL!Q`JxUd6cqg=v^XWp^yTWqg?hfp z3!g&MPl%z;snL~A-u!B(Mq4ZswWz4G=se9kF&)5mEQRR3o*s9Ii!NQZ+-n&QLuNo@ z_(y^OBZs)43DqkeyA=+L(Z+)6YOyZm2^`q6VgRg7UA!u+tRI)P=lQAF^|xX*e-xD8 zWQ~MT!|pjRJ>fQccgTq6C*ZM7UAs-wwKhJdWwbxQ{awg(l};*0?yEmpEw9%5Ji{Gs z;^PHr!_B8;G!1N-t1PG9l>G7p{AWQpG-3V8A&n2^{i@to7vUt`%Ra-_ps$P72i?V!y_S83kN4L;OW#bpaiV1+ z+eYx5kBc5f?JEZebWiA-8&SOy)w90BV-g-*O9X5Hbp?o3uuXFO{^WJnqpWLRb_RL$ zcO|-#uZf8TQ4%JGJIPr{lhMc@Jd!l~1XKpK!QX8h&Y~s)DleGSB(kr`^KqJnOK-Ev zp^2x>JBbybo!O_piXL{fC^rWYaR0lRC%r?=MnD(k(c`6wIb%swjY)C&f@aIT1vYz%JkH5#EQa+ zHvuE`e>^;N*TKUBQtOg8utaGA_xf+>pP(k&p4CwglL1aTq69d(x}KiOzePT5$3ERZ zqVQ4W)8*YZgNd^yv1@epUai3kPEfS$lQ-q&{!~z^5-&OiI*t3Tzb9b#4I)~pDm=C&u1;t5x*| z4l#Cmj@65Axi@UfoB*GS&6*XdW0a&C!Vxuh1CjUP0*=L@_tflOGM_iTysKIL2isNB z#Q>Sn@1+eVM=n--22YE7$S+6IktlMqC)=zQ8_mnkZd z5(!u5CU9e#3H+9Fd?+XY0`?ilC!3a(H3Y76`gWxatq?Pe4y|>{C9x=3sF^i7VBeAsdO~Ge4WizcTV!^WekRCNGjSFEofgvk!0}0K?O3J z+mCDx!eXgYSzdWo{s0*J+9rB5-bS>)AFd@6(|7c7N5Ot8r;JDvUgR3c`Hu?Na1ce6 z6nQHg^+Nl05?=9v)e6?atS=}>j#xOI!PUgKGh0$QO2^?|akvH9zWISJjp`$*8s=$U z3I%V6%yVBJ>rUH$$9K6(B`xSs613y^QXp>ZtL-3bd|3U*1zHX%yGk)Vj=$B?6MBO~+keEdm*0Ev zSfR@e;8?U?bu{Zlt1hZ9h4UvcRu!K=b8sr=?3E;G(@L?Q%;(9lC^{eiN?>7-x$0f6 z*VUOY+C@6HWu3vehNv-Dj^nnfzi)eEv{5>`m~_$ zyQN3;y}sTrYfNpG?AH&YB8G31ZFb?t*vNy0DOFW1@~dj7VX~Q9ozFiK%&KD!=JKkh z6z>z3SScmXWgex5_)PNLn>i6f#^J`4FwSid1jRo;otWZKK8NI%n5#nQzR=@lY$xo# zoD%S_qSJ(9^8!N?_Kgtei9q=$=$1an>pT>iHxRa_Vx+L}%g*^jS)$s+sndd_`*!9e zd+I*r^?RP;@`O{glvj|_?s3JugvRBa*TzQPWyZ5=cdLH3w)wO}K0fJh)cjmz__uS}e=96w`DL&(a)dl zLL(JSrvSR#x@);?9b?gDNSv@*R6DmJ%f7f_dQd#vqki}?hxm@RQKb#GSH8yvH#Ua1 zjy@b55{dNTKDH3opZWCb;=-xwX5Wu%QkUaiH@fDWPKsNbMb0u6YJ0w_I^~J+Z}H7f zg1EnbcHXmOCmfSj*iX$|hYSteO*Y*JQDhpO5o12u;$D|kV>(b2w`*wfqSezEzIm_P z$mU<)qWebF%pRJU*v30QQtB|TFYtOQ!aDP8EzzKpq~lG2a*E}El=vQoHb-O(o_^9Y z#y#!XVj(XmEdoYbI-OSiZ62B!#Z8{ZvEIpPb*}XUzFw#dNYL`W0d7i@3NeYT$pe0g z3>go{nyMwUr7saj=r^C-?wSun68k_PGdg&o+ga1_%9rOx8Z6(aBWgkOX?<}AtKVOCydpccpbj5Sgpu!V?~K1w$*{l(eu~Lri+4~f8s{dWUIob zz-O|L1>GH|9Nadi?KtkZ7FFF}_Lw6L4B#E0zWwnP`H;%9cjgOc>I=5zF7&Jpt425d z)-`fRdDfjvYx7A0TWN9gRx4Z4P82@U)6drZ+|OjrK0kqXUz87&a2l9ds3;~poqkBo zb&;z9NGRZYTvEB#n@qTx~b&d8T)D;`E<6@u2J*ylGJh1Oc&sW zO;eMLifgt~DTxLcR-2`y{U|S?DIF_}?(;TK5@qK-avdDPR3yO$Mn=_8Cjp)#+el8! zR|JNPh-&wQ!&xQoI|;Gv0LWU;_~&wW@~531|hCx0!IN;=A^p%_pezZkdu zfvB<}b3)pCNm<+>oI$vrQ4A!g?$Fi+2Io0!+7rGn_}>13H;kIzfBsNgpRo^b$Sg7W ztC#>4I>~DpV>Gkevi4`anMym2?Pu*Z4>Uqw*;iGpFwuE;*zs^H9HjldEh{2h#t%k>Zt>PDkBRvc7T{80Cu0{lH37DZF7 zQ*ENGxkb?8)IenNU$V8S0vxJuK7+GBeYx|<_GU`$eZ~W&?r$s4s-|1`_;_(1M#a6S z_{~+1lG(~hXR8ZOgTL@f9A&wmVzzBLd+{r?QG%*b?w^=BeR)z0z9Q=fu zX8*t=vFHBG8*yBXX3VSM9?6`l?#&9fO+lSJ#aIm90F zIR89FS%32jfd#ZE|8O_(iA9sVL|TYYVA4b;N!Uf+D%`Qd2&X*{+(8{&&*IPaJl}WD ztH$)*1zzhGN=f;~qQO^2<@F1EVnf~Kwyk@$} zqB$e}5`nGKMG8jjCQ`G4tLJ-*JpfOR25P6&rctmGTIxGOH)K1B{se zkv0jyA9)(4XT_-Iwm-dg6Y{HLmmlrc*5)*kP1~;2unJa#nn`Z1&>H}n;o+ieRTxEX zIN&(7@cRgrnAhvuerJX2mmZ&8a7<4>BNFB<@W)=PO)dT0pSS4z3e<$~1x2s8^e0Nsk|oU0ahmzIM1qD#MCZXm#O3vJPEVp@B;Y<4un@7d&ie zrb+)KII!1bH5Gr&Tz>Wd8ZYrb9Cr1&x~-9Dl1o{ zao-gaBLsUQ(M?IlU3~wYT@~#A^+{|DI6_xuHp}(?aq8aPE0b!RG8q(l8wBL9XB(ZD zVzYdFxaz32U#ZA}#|$qi8QAX2Eb}JGhqm*Wb%wKvtoa|D?D$B-#BV{h1Ct4u$M}wm zXl?77U}VoF=0^P^1I5P1GDEm^j?j}{wVAsBxB~t8@R{QS^1BWhGED{DV|}Z z*cr39Xg~Alii=Ijc(OM;xWiwO#I&v3%}bSxXQ1o3v?^JK;go%)qZ;;EiICbi3zhz_ z$hHmy??s*7!p!Usr1oD46tfM4iZF7=9aMUzBJpy96Mb!1M8pZP}$j2+9Yi}s}g zNa^UZwL+$lO8QKnX7yizG^aHS2dNAr{x=;o-nqlW#doIO1kC7Pdo6z{(lTA}Y(dRk z5nUCkzKEFkWDEzz&5zk92(^ITHG`UgAU*YsXrhs?31xYTahD%dlKRSO9mN*&Z?exx0pzXMHxYCuMlrmN0!5Pm z;zL@KY&oG=Rb9yyz=|>tQ1=i}?-mge`HutDdOWc3<2fe=hS)U+;WK=VS}=~6jG26z zIA!0a&sTIJ*zDn1ZSOUSncxtrQoG~ko!JM^=N|8V?0)e%#tDe6)9jhH3Pz+&ZNsll zf1UWwBM#!kiFbB(hQWKQoA6EOLgBxXvWh&YFPZ>`RDfv3sdN7jTR@yArd>ie^7S8c ztM|V0F$g+0xUDwBdTT zf&n!;?B$hml3D8}7a0>tF7|YKZnIEK3Rg8KT=$duo-AWk0AwoHys~wSISDea%hbe+ z?%v_GQ|W)r)K;1r1g@Kx_2HLN_idBFJzrL!gO4aHpOunWE5j-QrR}!}d8;PQ){@Y{%bHDl+|@2@E)s?KZLGW8OG1wu zU`j_7FgqZ-D%VsEO$>6TOL&sM6zsB9nUV79&pwZny5 zJ05>E7M;0hcw_=^_{l!YKGbFK6gg_@i7?}J2JQdMW5E3boa&Z1nz{p2RHYG;A+EL^ zTL%hFEM#O~5ulxILsECDE?f(5s;et~u~St`t*149(Ueb66zRR#Xv6beRi0&P$!~BJ z2FDkD^ptXYbGX}WcXW@toyE<{3AT>L+7Iyl&gqT{ea#LuEI3DeTz+i~he31OBJu`= zS&+a)RW^yslBOZXx9_xY*IMl@E0cA{wQ2bk(h0QrWE#81nMc|hU6xX=pv(wnef4E~lY$uEPvvW=zNUpl-Ws!%f{^P3G=H zZ9z!A=*}Bd#b1nDd8)FVX`wVSyQdLD3ZX_i341lYL$%_Jz1qzYAj^y?oGqhm&sC+J zYwK=Ouu4k(nwftXk;iaP;V!J+VmsnHJ7DF4v4p0quO>hX!jQPiw6~QXM=Lifh~Xnh z^$KF2S+8WjykUT^iYncCHwkGfOjx;SR zb)`cz0&eppR!S(QeOJ;Xr(WhM>t!XD0Zc-3`W$2`zg4$)UXH2?|!#1S#rs?yO^AV8ju*4G)mCs>yqD{zp1#Yp~cd$kN9>aEr@xHVY|~n zDdq~i-Cz4xw1|F4^?|8Y<&XPnHXPIaL>H|pW4>UQJa4}ayQ1xfjbk5<7_J__Y3ZIN z>gYM4+^Q0Pv8p7aX@}cRV1iYsvl>!A?4o_u>FQENyuzud;Q#k1AItCpqJr4+iDppB zrnsP~y4&-k;lNt!2imdAX-alTXnbdNws)LiIsD%8MYCC{uHB!b1$Tz(q%!k=o#mHb z*zp<%=JC@4TiJ9gD1&|d^{l^HZ9AbazbnwU%7@skx8_Yt3*@3>J3oYDzYvp{G8MDE z)NL6Ag3jl6+bW%Z-n5v|7e2&))BXgy-DPblzDqqVeSWqROC3tQQ{$Bz&+jiZ85Q%& zZzc(3#$9UB8#&%v-5U2|DeHp7uEWIIiWvP@giha^*0$rEq2PyWRRc6&Ms2Wg0jXYs zPt;=1TZm5CsFHEn8GhdnLWy(bJU6em8efQdc2aOca`WzIvUBzIhs^^&Exd@sd2^=j zr~9GYEwJsMl(03_%6jqd*)b4bxNt$5jLGllSjn|4Zg&iuypW3W<|6$ULjm82)`62i zRh07W0=EM&r?;YIU;hl~Dyr~^kCB#6*S^i)&@*OK(ZrNJxZ_=wdwK*6tXMF9QZ)R{8&WLG&mq(9| zMn@2J(HnRnvNREQ8Vy9z{R0CZ{QWULn-pF|OvL{E=g&Xh4jOmzuZ)y$?A=h+3O8AY zt{9fah-|sCq>T4rdvu2VDa4|eymb2*twyP?y(@8TP`$1dl4Rj$US3bis&jm&>+idU-b{+(gWbe&_STP>q=1MS*0kr)MIA!0hN;KSm@AI(mIoHJ zM@U}KmrF&1X?`rfKJyN(u;t$0KYJuRKgxa`ZpnPXFGs08&SPLY1N&Qs4im-D&- zM;$ZsZq+YpUydE;9q)0yxxvgc+Vc8}ivekl-xA+Uacf#qIy$Y;J~HDb2b2fu2odNw z!GL-QStEyW=Vu5ZiD|^*kQQNpO15C@=tU+$yRn81i#_kIiv0?U9kv?(!FNWsYalGR zYxHpu>ucPShx;g>=e<<9Ky1`Njp|2#eEz)%=YQb>?2BTirk9ApK>$+G;S~meuO&)mM3|+;4~6j_F((J8XZhsw8XW zIQd-?j7^>HT7t>M=Pxl@XSW$U*5NMl6KDDP2_y6Sj~|POi~LLm0sg{-KAE1!H}MjJ zU@xho!%*TU9uD-1Sp8HK-c$oPui7;M*M7aqIgsLTIH@Y8QH8`5vuid_kew^q zY`0YT_cVha;w^^F!H7ysBZ3XCNsNLT(=xG5fiI&gQG}dV7bENlZL{*8H28BgVB}oG zpNAy#*mI1xeh&dR=BAXQKy&Ye;cPWC??}^o%{({WUaA{8A?I~DP?7%IFdMi8q0&`% z<qVL_AVdiX4!2s1A6I10< zSxt?c)t0Xc(S5Jwx7q6nd`#b&Uod=rkS%#?do$;lSdN#^^wAEpuF*a;NDr%wPLGMI z?DlVWN{F;mSb0cwVoF(pz+50bHv&ura4n_Go5x7@?%j(aq2XE2qzU10eXtP0?k4zb z@PwEVVD(G)=;`TuiD~xMHa3`*7!k3BVDMeSN<|E#ffQU#sgS@hjB{u{j9Ae zClR2==1YpQz8bdZUlk!a`j>;p3)*?cxb#S?hSSweryZt(m6fWS;MXw|+ReXZO)t-_9M< zV|tw?Edl=7-iS^Pic7TT8q=gdK7M{ZL4Ajz2j$LT-Dq*$Q$H>pkUaTqPtk6@%lGbX z^}cqRV)y&SHM1(daiNI!F@cjY&#tnMd93H<=X&QDlc71Mov-xEV)%?{ndGSA|Uo{>*`aMXT`g_Xv6ARK24u+pqS2k2^77AWe z({*koA^EYzeS1e^qYO$(<+ZgEJ!^y9-hO`iv^WhLSna1tnUyo@Hqw+19Xl4evA#M6 z5BUPa9VtV@81cZFHR=u&AQ-r~nl)qEJRH_EF-+zz2JB@!q48p?AZ21O{daUwapdz z(C~1KmtFls?ht|b2ch4;55wc0B9X3GYrMIrXOt``aKmErhpwBLd%Y2x#&$)xLk zv#mG^Br7WmBVZ6FFU3HYqot!G z>UqMt|KPyjpyE6hvaG#5F`6+-LU8#OHrB5f+jij;iZQ5J*#yTU&d<+ptk6`cv+ev1 zgP^048D$4nkKomFst|O?;?q=r5l{loqoS;=4%iwQNl6XX)w@kiO%*jY%{YMPUeT>x zgSWHMiOxPEBI3fGUue0?NK0!rc~EoSC8UO+aYaL|uZu-$10P|GPHWoP%a^58veVXN zGtwXas@ooG_w0N3XG@QjC+8dS)vulBS)u8Gc1I7yDpbx=zZ}fAno^||e5ODw{`nu< z$Xk1UedD}ZnwFQRitlnk4{tc-jL0h^MMb~M?Ch!N8F&!nJ5`6}N;RZmr#zl{oW*m7bIK!A#a}=PThWn^t++-Vmfu^r4 zbT=kgL`6nQ%E){K*(xqn)Mpfg0?+U8{2FxUSo5l0M`T4_`2@VOIybDGcY&i&$G*V;t{$nA?Kk z69Tm@Ei*$--lDGBPsfw{P#; z+2tZom}tN+>WT!e9PTJ75vINJ^gecZ^XL5he2hYtQBW9`#C{>^X^y;_C}2JFo#_1{ zGGq`C=%Nln{RBZ{EPSW7jcQp>?jVXuQgr}q-r2)L-ohfau(0q7)~D_r1%=NTJ2L*0 zgyvd8uA_Q3#-pr{>s*~Zx{c(w+!`)283X~ukLw~|86hCTNQzW=tub`=K_7y{2)Mb! zarw1`bjJp@W_=^)o;$hnm%(`WI?KpU6ny*yGg!C%{UT0lI6qLWc}Cc^4ikezSxrue z-n-Wr^B|e8x?0nC7=QAu;4|mrHt$7OOmC7umZW>mI@ZYTaYqVMkyRbmEpmasW@KV& zkd_b#byy!$vl&k;9S_B)|Em!w*eVE?$;y1ZLoDG0cHaaR?ltqcdU6{Dw2xjh0{T#fujUk^76u>@vRXs&|qw!yCCn zM|_geZGUA0H>m$@rJLdTN3gR6dEvMMts4V)%x?5-ETmIVQ%4OC>tYm^gnXRxbVOUKfzO-$ zv{7Hbp6s$;ooG+ccvbq$AXT0maCFb0pdJemBcs?-YsJb)L9nJnFr1#aH!)M?gn2do zy8IE8*`-ZQ6R^PMV32PWRSeCwiHM5IGN#2BJ_qnkyQos}J3)90V=#LLjfV^9Jpj|8 znE24Kl()aw?wjTKPk-B=?@oY>7=oG4_YsH6-M{~ySh5Dq7dbgNo(7b*wDfAP{GCtD zXh!`G&yy8CAoMP3G;90~wq*E?^y9RzMvq5KPcM>zg@vnUr8)iH!-v7V4jVbLvycE2 zILKrS4l)N=2s2I>Kch?VU>1*n4e2EPnKM5@c=E-F%O4=fRQBV>U(Z*O7GwmiG+QbmaJ z{(EZOPy5K=8Kp@!Xkn4YjcbqhYpSzDkAK+Faf|(*M zE2{+rh%x35sberwte<-VC3k~Ue0*^#fxy8uG4->)NIVq#x>ZSkRP)&-r1IOXqW9%n$+FUNa@uEofmhOWC5XH)rWY5vLDi6}CV&7qJ*sh$xw4gD zbaoGBc9;2amwZM5(E3PQ+s2i*KuLgO^Oe~Iow|v>7+p(6Wu*bzkvKF2L9*%^tvsrU z`A_P2o4+N8wwuh?(HOcoJC94N);A0K39QdG3?A=UdNZFTu;@7bkZvNAJ781;yiR&S z!ET!_$(F)y5s?Q3#L^$e{?D+_DKD<3Eh>^2{~BQxN{Eh+_c=R1Tz}K^31-KrDSZkrp^L`ntMxU_!>(D}N)(@6DT?DjB8)nmNolZ8s4r+Rys;=t7Uu4p2L>wJgUKX!)L$ z_1TH*8qsn0Y1>%5v!e$Q)YGrN*)x@HQQjp+jzsCaymR8WslQ!Ulil z^4|Nb>c;2RH=n>NBhD2;yOj%9t|;fPPng7Jx~EWX#*wS3xrq9(F!1v$iGI2$i47^D zlDwcy`om~mtSB!}^hqH#S@<(%fD|sezyFb#@8x2_9Y3~g?_h=c zUKCB6FP4*?k+3ToTmcin&CRW)E71l}uHupsMb3q6Rev=HSuul($U7ZU#)*RfzGB~Fp146{Ds3FiJSBt2oytw?%)(XsuT$0wd# z?ttM_c$ICt_BUcSUn*cgxeM(Eh!_(G`6?9GvIP};MGc5?x%h6FE?v5hYXroqfVlw& zx!IYSnAwz4MUuEj`NL_+diwg8acFR0$#MnRuSD9lXB|^V(B0e$9$Bv$`?Xm&d9bFE z^kI0@B(^XfqTBL}_H(ee4Z4qN;@hOnJoYu$Mi(jN8{aF|Np=~s0mFTY+*#96%Y%sq zK_}n)`;V1XYfd!X6eZ}WUY|Z`(-~8QuV5GnC!%C+1hmbqsX3Xf_xKm;4}~whkrrr0 zhSG8SGL}=xldq`>$&2-e)D&G%^zla?G^UVl9Qff8vK*cD_4x&C;^vW86S#)8(6}Tf zs$4liHjCR-ffLEg_dECQaqQT!V-TB}9$^SjX-c!z9u?GA?Q@8;e|dSCo{=%CxYQ1h zs`jI|w=Ym)ybDX8aAspI4F+0uvmv`?KX>k&HbLO;>FGfwvnxuE^!&=DlFw++`347{ zW(O{*0a>=RjLahxE@Hw@f>u*gR8;gCX{{e>#K~BkJ5vB*9mN)oS2A$i~q>amX^Y}&~Toow#+2lV{-*^QZ5AGCe{z`{m-yQ z|2tG)zj@<_uA;x6AGOD-H)A!YI?nTflEsBH zjtlNy;IRd@r+bS}4Cykj*3QY1V=CMw+?wy z3B#Z>Ik)NFyh{_UPTY%c)`!xhp!I}a?iNIo~c~nfyM>b&;i8F8z#iyijh<(0v9i$>@ z#EW6#fl;vASJ{{#B?nqK7KG>d@iyt6XO{L#1 z1j|duG+pfukc=lKCCR9%#ZTEUX0I&QI>ceVfG!G9Hofo8&y}6=7%p@qRZLKS5vQCP zjOTji7f#awe46aZEYYFbpcecX<$}=O-iOPptI<(WcTt>Z@kZ8x`<#)PS&W#O>f(~T z`ILkt?@$5d4>4YZ2tY7>&&uL6>dKNuIi@{X#{+~Q?Isy{d8SjRt`7_hjP~T`m#&^0 z0ZSMA<|7nVA3Z%E?&yFQ%K%$#;V}t`@gASkBpD1iCH&Yl-(V0KPJ~c!mkqEcVI}gn z*hj;2-!rC?3`MmtM2vX+5=iawS9zWd%qWDUk^mo{fojVzE9C|*% zNIL;QqA^B$frt2A=&98_@ju8TWN3DBI-$f{J20(2g!gq^$69vTWv~h>{ATaD5m-i5meG#*bcJnpeq4NZhehbiIkZA0rBg zKT0f+f>*o7fU}l-^yvHA`uf1sR6LknqX2;4y>q7?k2Ct5=%-eRZ6wb%pE44wUipQ@ e|G(7xZ@#RwA)`=w_AmT4$sHl_TX8qkU;ba`g54tk literal 0 HcmV?d00001 diff --git a/docs/tutorial/T7/assets/T7_plot_2_simple.png b/docs/tutorial/T7/assets/T7_plot_2_simple.png new file mode 100644 index 0000000000000000000000000000000000000000..a75ba620d8af6339e8d6a31adc7e8702fecf027c GIT binary patch literal 266322 zcmdSBWmuJK*ENi~1p_hY5)lDu0i{Dwx`aii(v5V3iXe@2gM!qeyFrmo=?3ZU?sqP| z?`J>n@&5XLem`{Yg=;OY>%8VU=NMy-dHTGP7P)nU=mr`Z+AT5BmvU%m{}iI3UBS49 z4nL`L!wrJ}T(XuE5k$-BBw2zN{}>2J3810n2i-hL<2hG)Sd-eW);_q8s)sdFN5_j&%*H>e#YcSH=|15Y~-0r0s*w-2zqZ(}# zp;As;xEdKzelWrD$};KU!!HHw>gyY~cW+KIm98fK8-=*6Pf`uZsmjRF$KY_vpge|2~y zBPnXA+L?W(DTtb!Tp$*85%p%xG0oe}F{0j|B>sF_`(S_E9zFV1X>Tz$Hul!qdZzkd;-@JaUDxDt z=H^mb;`Y%(A|h3iaCLRnaJYc7DTqvIe!L}!|6H`%X)mv^@aOn=d;+ht)zP-zTG2y| zax2gCvy+*X6+gJ@OP4NHZ8Z|>>gip&gOA^|IrTF`HW@uIFpz_r8=Hiry*pW?I1%|d z>G;LicCQS-Y=#`Azc9t#a=*^W{u=T$+dw9Pr^Sz{#yd8axFhD-mES}8I#mz{VRTAZ z$=%+irR-vnQ?bEphoOS$!eyfs9Q_q6c9%K|FFftP}( zI;eQ$!O?3CoBH+j#X;38+SV@u9vsg5^zcl-STA(8$Fc`8>ooq#Ku}9kVZ%~=RVmbW z*>0ge-TZlbq)Da9fw@q>V>-KZLVI_yn}pvjjyl2NLsS&OntXUmD0MHaJgt2CcYi`w zhlP0ip&}z}2Gyd+R&YnB^pz2&r;6+ zke28cL&&QCM7#c);ENYV@Pyz~BQlOM@U}+ojjEp#Ox5-EKG@}!Gw7sTHjlTvE`|*f zDH#|7Xb`EJBPO|*^4|PJulxCPX|$B7(4Z^Tpeuo1qarMjl$+LXdVRcdr|u>b+9m|S z&d=NYa7X;VmzFY)PfP3T>wkR{!yd?1Yl^j~X_;*aZE0>stp~kUjXHOH1|qG%<;cqG zHd*Ilck*zhJrjgWk2E&Kt1qq!c1w&XEG`e4KKVz7YXiAj7HkBV`W`=Cn~#;{A3+4N z=Bkx;#)XHc#2YgrQvJ(i68Tyketfv9|9z~+)!EwIJm;PTyj3NwHyQ(rB)#6s%BtPX z&22t{L5(*5CO%`-rNa35cup1;IiHQu(k{%XN!J4nN;dN`4(lJaL`<4hhVTpLVfpEp z3x`dyZrysOrlNxDYqGaKKAJVS(g9!kD>ckL(%&DmutisHj#0hrbxCpYGnqIJS==k_ zH}U9SX^%|ia#|?pp|@k)zAvvG$*93X93X66YCaw|lx?8pFm;vEPC`{RhE4YzRgPHz40RXR;rlo4@prdZdmJ&9ycQ#@iFD$w&Ie4>;g z*AN#SozZ?a?Z?#qj`QhLd7tZ$LK*_Hd?10CJS0Eo9FC^^=lo(2V>UiwQd@Yj?T`AuYy-gOox+PUk1m< zw)x`HE%s$#3kV2|6m4&4o0#}%CLRptx9Cp8rsUw_l7k&BC@A<;W;_;tfXLP4)l;vq zF{-dxs)OwIBw7+#egy+dKHw5$moO~@UEQ~5$F@YzjQ`mzb(hIh%1ssUKyNK^MH3Mb zLB}Nc4%?d3ar>LG+hmPvety1eV@E9er`U~=8>l4-|944f^skfOk2&63**V#$#U>-` zf|Nwa>-4mxrG;mwoz=6(2tUPUsRxHUX>l-DSHO$KvF(E6iddFi|`2?bk1DDxq8_Vyy85A5A# zAa;`AQH?xNK+4N*Up1pAp zjt2Kgk&*SFFw)+t(p|~f`DB!hqMDMAFF`7njoG;GF;vOtu-^dHKFf_@!6MbNThU1Ige+~ zP7Vq!Ciy;icqr`LSe~fnM)!Ds9h(a0_$;b~5)#8Rs|h23=E8S&Z@e0 zt3$!4-(}EspE4pQrnSm(=doG|y+Wp
  • )K>EUVrcYps0W?$F{cL@lZAz2^7Dn+vz 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


    hxU{ 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�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
    6ABD&JDwd|Y%V_i1I)Pt(m2^W163 za&PYJTok(I9br%V34777+u&$Cd+1_5UBGbeX~AP~&9Wl#3fi^0SYzM%krPey(kv$E zi3?4b4SMvc8E#X?YlauRcnEdkL|r3~b!89}-)>6+dPL62#DP{yW<4W2^J+|~A|Sm; zo_o&i<*YC<(KubQVWhI@)C5W`K*>fNwnbVXn>vqc*u@#NT@LS_O`++fxn`3TQE^E! z(y$3PlVx&#nl5@KQe!*Aj*NH&lH_QNv#tt&40YY;sE+OvP8BGMya;DLEr;3iZDCto zou~T*S@@E%cJ{x!<(63{X7*CZl@1hN3;r!iGXl~LQH;!WJY__NFuK@{>4Dt3BPjx@KP<_H*-R_YvY}+|>odlj{5LbCHAW-yf4d zE}-qNwWWXgdVL`p3f_BvrG^h?d91R?z2i3~gso$G)+dMh!X2@ljC2gQW%nlCVE3bY zVX5CYBSm?awnd@Oi22IcLTwJ12sUKmJ!|!AfZ~UOzISo=cmG8pmw6Z&b@JiE8)NsX zyyyZ3ZCR$V*RM?a4kS?sy}ep49co7G>aP$YUBaZJdsCmKRFZC^WJz6s@X?xcV?WGh z9df3VHomZJiJ;AJ8QRuuC%lncuw~>?+`zHzVVDHdnjhnVA?%tMBfjJg+fg#~Tzyuh z{Jcen;h3_uk=oPtGfAjwa1}w8{Zo-!pNJ914AK(eCuKiKkW`$V9w7C(x3S{o z9V0(}@QlOS=DICUVkgq%06w!$$GSY4t#PeF1{a z0u(m=m4b&5QCOOWpwE~N=3ElA8oMsO76}iTFJ=bz1c z-dVhiDT2e)BZ4bl@+g5uB~&4(&LiDLczbD+FM2-XxrXV=IOP-PAHT9dvmt;@Olna= zc}~IyQf0d?L~y>jQb08kw)7xAdavnziQq;B(b3s`flJhc{u>ggk;1dh-L|jylfr^M z;VibQEN<8}RmLcR-_<00z9_?am!P0i3vyM0mLr$}(w^WY4ME4l#l@W(1t4zhYn?9wCw)D)WRqhK_Sh|qLhH*(B0ZLZ&{ zQK$Z->c{usfuY-+xNbo8jU2&;?INU4Tz(|Sn%K9n+981G_);1OK}JAJNKjIIS_Vy#B*Eor4* zyrsE@E>!%Z>?7&j1Ufj5Q(F~-V?2ZoPNre*s8`1gDCBz{S(#L67s>U|d%$DoYX}@v zSsN4O+fXZ&R2hG^=KERMvTS{r2-P!Qf!F!5xMif8vB_K7MsPqy@C7~`?2-hBaPzO6 zn;6%9prnY1%*m-42zr#-2=7apH{oQVn|;uUF}XJi!k_sP#58U2Q0i(F=<()EJ#4s= zoRaC&S{D^wEU)vv(8tydtn_zLeY^FbLz{f}XBdXxAp=oQe<|JX@_s+>_Q@&8$|isg ztT0@NtwEz0#k?D5-Pni@`@k1>SKzE|%i0@P(;_*LgF@ZnD_=8`$%QP0i4@Z&ytZbs z+@nwF)~ksQ$^hctJL5BzmEHIV)-x^>>w-4qe4a)`#FLAsKmS-x9$MC+Wn1Xhs5b>fpqrIYs6K~NRA~Uio;;e0eoM-Gf{`m6i zYqycW5dK~x9?5cJVMsmG@VuNyo?v$t+uo5N!~U+edx8W_84cIwo6kpOG@E=o$Ms{y z)K>kz*^XX5h1*lSK2L!Cw8t*#~p+;zWi{ zw^Cs1*sI^j85Hh)f9~INE@h}=wa1F?OHE_3?OE}3a?F0*1BZ!F6FO_F#z)=sc=UID z=Gl1@$yCRniH)^2q?rLc1e~cadK>PaQLtU}3HwBHym|umi6i0nJKb212x7+ApU9o- zCrqb-LtgbHBuozz*>Wgx9q=Tr&%{laCYEAF7lEKb0}mDK^i#F}5~zuvD5*3JkKDOH zkG{5RuD@KDGX1T@5>7@pbwz8gb?A7j@`~7N{kK3$XFO}nqg0C#a?a8F_d19kB-|-< z#VBxC^M%`j;uWxDDxLBe1RKaPzr?B_^L!AE><3||WZ|2+*K`pqve~O5UNM6tJfnSb z>%bA#xq9(mpTtVWV|pdDtBj-U^UP)H5f(0#p|{0-tC<~UC4Xbs7Q3f~Tyr|yl@(3g zQ@QsDkvFH2=n^?s6ZnE3K`p*9)V7f{Z~;R~q*zj=vkzCHs|z>%LdQZFU#XSUcEi16 z9ys!KqB;mJagb|EOZ0eAeDDej&g<~%4KxZD7XC-l-KKwe>k^3Zh@=FisfxN!tRm*h z{3G<7zA%vVGA>|8Db=R>_u;hg%=yQia+g5$NAIKEDijYO^g`saKwfD!Tv?bSXQ{cW_o+Y!6tC~WDSl` zAys<}b;LHCQxMtwPt^YT~C6629vA0U<;X3lEHB^3Kd|S;$tl zGSYo`AHF;I6!yAeKj*#f>6L6TNgSUw<7$rJeDcB9lP-Rs^*nQ7wHbfuqO z(muQ)ogz*;r|T4PN-AqiE_9*^&h={zS)zR_qm@~yCUf#@?G(P>n}0vd?w?Fp`zr;J zYVKT#$INCgm7V;3qS}}f2>w?M4Kb6-7LQ06$meG#LcwfoFxz*AKVvv7z;Vh!9oagaQPcOv$Mi)VnX~)|(XJ0)My4el5iejn5wd3nDwUvM3TwCe^e}U3 z|Ir`jW|P zMS!+HITnpVgIa?GI~u zRlc|LuObZVWt=TN61Ca?X+RyQwN5=l=IJVceYr226AKM5!yWO6Pxorr4I33wTt%Mf zS~Pvr(WHLZ8*V>?sb~CmOAgL@46-%PPPC1gjb6kA(A9?>LJ z=7_5QW={1_gW3I~Z*wwtckB1DT;-#D!1sAedIyuF_cLiMCBhp_iK2u)vT+jAS6EbH zD$Y2sW!B1Cu~;cQE%465JhnX(S`9hQY`L<2N_@JcX^8r$VTK*5AwsHV04p@2@(*y% z7OfKc3_fFYr}jzNbiEY}zm3Jqj>kA~R$?5NW{DYI^nJR6+4$-+*}9~`1H+o4!b`ze z1LN(_Rf^5$~8k9}LFjdBmB;0QmQ z*L1#(Lg1vK6E@V{Lx_-7iI&qSW{)4t@$Hz@JBOGNI;yIwOHdaCOx+*yp9tLq8M7Wq zw7`FFJo&Ef+{TfX6&%FQi|w1Tdgb9Aw%LH?uh4Z_{sgnnXFKaQSgq%AgkqI)(NG5q zpKZ-f_v!PM!aN~6F4yWaj`sy08u}{~1`?L^>`@~cRs-()4w7BQom(gxl6e|{^OeXeB=&0Y*;ZOBzz(A;>|}od8hYV zm_KPB+AP0ldib2KpfT;(1fqj_@s7-+AK%i=HiEu6RBh((ex16DmCX0sW`COL*vT3P zdfV79CR9v!sId_Se)}%xI|TjY3L`#S(^5YYcE-yyfD$j5S1Szgk02 zqi8=cjQZe}=25FZeBedvXv6(-Fn6a}M)mJ9QL_($w-20>fER$`yZd{UFrwG;3mBxj z7*yv9L#Yp>sPUkK;#1@_Gyyd=cb*#?2R?9|uP~eaT)_D-O|s~!P*Q}bRO_F!YyTHp zZy8nP8np}4(hZC52I=nZkPhiqkdSVryHgrOBqWs%=@d{&>F)0S?zP|dJLk_~4ENX$ z_t>uWJa^1_)tuPjUE8AX*0Vt4Am#A>=UrHy%i({hCdHtwV%&u6p+{pT9q~|?^%EJ$R^;sM zrCQ(C9bBkOGwUCio0SCoAIR>K8#x9SP}><$pSqrHC_xo?aOyz0A^D%b@qXFs(Ra?Y z&-M4n7oI)r;;62a*n!9~@9r0=6n3IgZ`Grle4<{BOrCr{4K0n!*fn#|{xI~nKLyt( z#S*Zdj-$km?e)ah+D9=JK3B?q7gs?Tptb3WKJ&&o8-@n0`{};W0|7pTw>DyRo=3s| zTRlDA)ldi{l*g09L?M7=mflHcUDkt&JNAlMES1uh`5w$N;nq zS$KO+7PW$|&~bNdZg z(5D;2@e-!Z0P{3(5DgmCN*g=IuY(K;tgQKlQ#mk1Z?(-SuD}qC0R+>%x+&*7Bq)ek zL9((9%D=265DhgV{Po{=!Wn3@QXL9fc3L1@iRD^o^}>SkJAnLLSz8MRBty@yUuw`3 zsx2WVk6tF@BjawuDV;$6pOlM*mEKUjZ4Z0KoVEqb6iqMI<5%lynt;&>qC?Oxs z;I8o#&TW}Dkuvi>OUQrXS6g_H09fGBTdywk66NM+FWuHZdKaHZo724UULQMkh0UI? zvE*r$%R-i&cGj0)#Iule;+>UyGsBjGcE8x7Cmc{C)G&a30Qes%czXkk`TjIc@lf2o z__sMwG5H$;yBic72eN=*E+n8h2Z%Z`RB#DH1>_aL$Nfl88^lM@?wjAa00 z4+8@vjj36EQki<3_f zaWm@OYtz5^B!T(+(+;EoVN7!qS;K+Dd(OLSq@j-4webf;v{Hkn1pNwAHZvdg#qeq!>z|NRg?rE3pcCx=9YH3qc(9K{}-5)(jSbI@3qHNq=&OX zMGAeQjCl_jNF&ED!*o8@l$%Uc`$~K|l~p8Wz=5>c1Iq{}5xR?)7bLZ{wUw3u)Jy4% z3=CfeuY8`xE8@JH^Hdo^Qd01i`}_Z2)>8qf=nwjQAW$J0pxaLyFKB`(HZd4eq=2ri z(u@+_1L)|x7+_p(?pR&=3<#-QT|Tf>rWB}dt*1~r1~WUS04G_nnt5bkbSMsOG&(=5 zB#2!fG-%fP56^Dn1>QcWy@K7i=>yRJ7XY>g%92CXLBJ~O>UKs(WTiN!-oLofDtNnr z04=`K%}k=5$Na-k6#CaM7vZ_g^(A6Oc#-~UX!Inr#?(9>>5=*Q<3qu3YSt%-7ulb4 z@J;zm?E%Kv{%F=SJ8^o`(5G6t`+(Nqz8s$aZ*(9PiPFmDC-(QM1*9j;Ddt((;U6rX zx?Clz0|pBg%>R5EBSLwe2g~{FYk3~9+C0qh^^9M~Z#b@Q0c%WM;iR3Q9H^>CM$n+= zCZNJ@&;D;Pg&oi=NEW_=o|RD1kXZv@$5r#i$$_I3S_nZeA|TP!0Rn1g9v}w%AG^{D zkaqL{eh`|K&_MySu&}@xaOVyc%?6)|0*!^j|EjPGh{oj(fVZL-kc)kNHh0-=f70FV z(36*ZN&DgI$5H-`-3qX+uIRP*0!Sh?3|p&%k~mT zRd7trOK0?_Vsch{e} zH6(M0$^7yo?dMlqpNI~c8Zll_QiK*JUbFu4rupp1atV|yrdoDGK(c-Ud;cH?aJ|y?{A@b8M!<6a)GWq3&re^T{CO#_XyC-&z;jLe*H;-hB3&w>YhQDmt zpVj^t{2oNy1cP9`&jBLvLZx92gF>XF23QmbtwSkc^-#55A})wgaJ}5qy}8fsFc@+> zUJ?Tr;ft)Stl%^K-{(jO;~a{2K-r1giNllc(d+bko0RO$^gKp6F0wZ3*;S%pOv#W{;+y8M9mJ|$cL zXxY#R*7vP>m-@r5n%V#t>JReYq zz?tv@2CBQr74h0i34eVy{n{BQo6(>f?p5se8QZu>4Glw?nYu!M^xDe+Z4l*ncnjBR z;zB0MZu(*JR~m=1cL4JHc=GLpsgM_4APSJK{hU2>>5P&a1|&Cj+sqRxl92%n0Z>6v zP?_-E^>IQHE!yZ2A`}9EnyCPXjhEUP%@!9!L{#UV6$wF1JbQM&6BtN*4l{iNz}KFs z;W#Xo=CZ|=BF~WQG*aWKsv6zdVED~ox(&JFpLo>O@fo--|LSbefC~R30PhQdRxVS- ziyinuqJg%xXK|4nY>|kJ42bP$CM*neml-uW#bxo>6@hbiw#|p9M-W^e7lE1fN>lgY+Mf0Y(PQ^v=7w4iwISkbOt`&+=Fedq6va{mWlE3k}i&j zHgbgNtKh&?zqeo*(0k5Y3Q%XF?d1fSqJWes7?{8I*z-m7=&q;!?O^;z3sl|>3j)BX zF0c60VwTvQ{H`UT374FrzUaTgF$RTPapl#JKC7$0^4Nj7Eclox2!zVeaGN|i8ZM1g z2b2L#CP@Kc0*vC8nrh*rN`s4~Zcr21IbPn@Shwc> z`r-nbVwg4G*mJT|yW%92hRP5s8_z*cpbPKOgxU zw+@B7Zn+P?2WK`{D=Sw{e$4>LhpFm6V*PtEvY=2o*{bCxDkP1^c(Urt^XulHayF<8 zLd@jM%mUN|KReMxFC&VhJFpqRRstO(__h0|(kvl0L4pACnhpyy{OHa@Dr=y*K9SI% zF7av+{WFKrC?zWZwMAh%9*2P^nU(f#fmW3d}#$^>?j zf~Jq9M^nBlKlUEYOAE%WL)$<`28#{!7ZNC zB80;v)B&siXM1ct0gOJMFlp_lgn(p15NyUvSM}wdM^-@w@B;r$V5UdR$rS_Ex^CZ{ zSBe2`eWg&j=%)Ho(@q4Q+sffyE~(=Cu!=Oa9G$ULfhg>=g=jo)t)a?^ztxPs_nkN`RbNqh*(mSaDZaD2j0VnqK+F56Lmw1xjjsgS1HuQq8 z2nQ;-#6P$h#4#_u_}3?TLO8k4ISOHa>RH5yKLz|=tbU=R^;dm6G;tfs3d_S+)Tx0f znrkiY@X@vN2}P!2_P}VA+Ds`12c~p93GOFI0QCS{5F5y0r)D2pQ)N|Iz&r>6n-v7T z?VdxRL=P0($FSx$@Hj$m)esLJooQSt1E0mz0?0N&<0%XD(?FrsH?{en>bK;ujDaNE z*}41ofWoU;1q;6tF(`6X)v;**hJ*SU_V8I*5%#QrN^msibhN}#>v-73s16zXo#8hE zdU6OQ&$nr|+0S64FA%49`_6LK-~X*Ng}2heUGwVg<@cY8 zv?dam#7`;Fx-4)sG#Lmol-^tI5*T_o^rA}`8K1jg%ZbAnGY${0 zh;la~UWb`eo3Pc&Z>yf>5`YQ%$<32=cjz^^@O_Srs|CED20VtJzBe^??0j_KR)0@d zWHSx((-kx~K#3Y|xk1Xd4}3Dn%nnC%i~ZsA`>sMq$xYGQHtS(hu+_yS`mBnA=gU9@ zgXimoeP*Uu;$nKq17a+r9S|l1%t9Uo%%tWj%L+sTp5W~Dsy~X0l0heEUOi$3`;HAO zyEyXr;)BmE>2xyWw5KE04zj$#C=j$^7)daHLosZ*8xT*#F&Q7;@G9;|U_+-Y1*^fB zN5+7F!F*beJN*w#;=h1E@y9mDXAXnNi?Eo)cIVEyN@%j^I3o>B_rVp26?vR zx%`MBV3cw6;bHQuMZ2)Jw^tr})?HZctP6(*P|9}f!@-T^d^XGsQj|NNF@JsXm@plF z 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
    DG%FbH}zWXisCo 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

    x z7Lzwa21goVXJ^1bZ_RlG>G>SB{VmqDPqAXcf&XpOXM{<0~i z$f3b+LHCLZ7qh`;)}ZKD!8{GS^bm>;Bh6#6x^trn5?-|tY&yA1=Ri`JVVxqT1=fO- zvu5uj%iG!kUF;7Nw4o2Ixd@y&=i^LHD<9Gy9+~0kPQon9R@{TbmV&$n%geX(bG6*; z7aeDW&|hA>L>Rh}uvRb}!~H~{D=DR4bo9Ko-L3WSsk=UU$6>Z%a)2|q<~)X;#oGh^ z(nv3gO~y*4+YCMc`C~H;B!F5#;Xt7rI}S(Ez}s(SMbAoD%&T$kN`feXETUw*

    qOiLk#A+p6-csJo&l=vG;xY#sPXE7% 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

    M1_veHzaPOFok3KCq=CS- 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 #SR%%6G}76>%UR2@A@FI+ry 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 L{an^LB{Ts5rS9J$ literal 0 HcmV?d00001 diff --git a/docs/tutorial/T7/assets/T7_plot_4_complete.png b/docs/tutorial/T7/assets/T7_plot_4_complete.png new file mode 100644 index 0000000000000000000000000000000000000000..3fe308bd6d9e0af99b073b0298feca07be1bc2c0 GIT binary patch literal 236545 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%0AEoq5`1e(YwJEwQ9Mer|{)+-N{r-bV zinI-)A|=e-H~+=dfUbuqZ+}<)pD6pke-{R~R{an3PEpDF-+$L799`?bf7b%#+7bU} z&|cCgDg!_zE(X;DzDYXk&Fv9A8e@Lpb!k&!{JqLw-N`yePN$WJiD z9|Px|`}V>|^(=hda%;S|syO%V-TS*XPCq?8ef$NWs~lK;@WYr|T3V%6{n&f!lZ(qt zGG4ebv!B6XidgodxL)If=fHjNT=V1amL6v7fxa`M0!MyZ+V^}6Pr z<-z-PUhV{RBDmg%f92HG$z;xsooJ$!7{C;xK07aK+B1aSe$B-qBXe=mYnu>|Y1o|v zJ~`GGQ{YB8H1lX8sCXj~KmPEOhX3s>`3(8s7FpotaamgUdK1G)UTU33O8hK5JOuMy z2{#`0~@gk9{tE+yk2PGw!#uSbf zoSL?e_cL3%|9L5*^Op*a$0w8jdS_!}qXBWn<<>d?AZ7t@BcAQqRmL;K+n_ccOs-GV zMk4XfM586fTX z0M8eBi|&(Ve#G)%VWwr@JC6JBf~GPCo{*A~`j1xF&E^)?$%C6ygRuh`3{ML|CXU@O zQ;?Kp4(j$`f7gT2S5WW`OSbur+~SMndt}xHxuO17>OOLkid&P2hA} z9u`{v`I!SvWPrdZwb0;l$|qPiZ{CED#PN^TdWuWLAnW_hyd>Sb3WBtNSqTxF5e
    AFyE-rMvK+dl8~`6e0-;>vdk46)X*jsJ5K3qn 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� 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 ZSU!kM%$ljY)NO%3>MA;yGL^31{VzuQk|6*9 literal 0 HcmV?d00001 diff --git a/docs/tutorial/T7/assets/fig_post_init.png b/docs/tutorial/T7/assets/fig_post_init.png new file mode 100644 index 0000000000000000000000000000000000000000..5cc4a4e7b43850198754fc4114f4aa92831a78c7 GIT binary patch literal 22295 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 literal 0 HcmV?d00001 From 99f83245f4ba9d5d9ab73ebe0e55c25c95b26ffd Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Thu, 13 Feb 2025 21:34:08 +0100 Subject: [PATCH 096/161] Add framework and databook --- docs/tutorial/T7/assets/T7_databook.xlsx | Bin 0 -> 84343 bytes docs/tutorial/T7/assets/T7_framework.xlsx | Bin 0 -> 36452 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/tutorial/T7/assets/T7_databook.xlsx create mode 100644 docs/tutorial/T7/assets/T7_framework.xlsx diff --git a/docs/tutorial/T7/assets/T7_databook.xlsx b/docs/tutorial/T7/assets/T7_databook.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5110e7feb568e5cd5db1b6abac9c1fd883831a07 GIT binary patch literal 84343 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�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 literal 0 HcmV?d00001 diff --git a/docs/tutorial/T7/assets/T7_framework.xlsx b/docs/tutorial/T7/assets/T7_framework.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..4d8197636c9b1b53ff7dd5189be98b057b011013 GIT binary patch literal 36452 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 YD@cO_1SUX0WPl$!7(lof^vB)*0?@SH=l}o! literal 0 HcmV?d00001 From 3c7f70e9727d3d75f2fa0f86b88ad1a7bed623ac Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Thu, 13 Feb 2025 21:36:01 +0100 Subject: [PATCH 097/161] Add calibration scripts --- .../T7/calibrations/run_model_autocals.py | 80 +++++++++++++++++++ .../T7/calibrations/run_tutorial_autocals.py | 80 +++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 docs/tutorial/T7/calibrations/run_model_autocals.py create mode 100644 docs/tutorial/T7/calibrations/run_tutorial_autocals.py diff --git a/docs/tutorial/T7/calibrations/run_model_autocals.py b/docs/tutorial/T7/calibrations/run_model_autocals.py new file mode 100644 index 00000000..f4baac2c --- /dev/null +++ b/docs/tutorial/T7/calibrations/run_model_autocals.py @@ -0,0 +1,80 @@ +# This file produces a calibrations of the whole typhoid model. +# Output files will be saved locally in the outputs folder. +# Desirable results must be manually moved to the calibrations folder so that they can be plotted by the +# Plot_final_typhoid_calibration.ipynb notebook. This is to avoid crowding the final results folder (calibrations) when +# trying out new ways of calibrating the model. + + +import atomica as at +import atomica.yaml_calibration +import os +import time +import shutil +import winsound + +print(os.getcwd()) +#run settings +yaml_dir = '../calibrations' +yaml_fname = 'typ_calibration_instructions' +yaml_path = f'{yaml_dir}/{yaml_fname}.yaml' +testing = False #<------------ +savecals = True +dis_model = 'typh' +out_path = 'outputs' + +#make project ------------------------------------------------ +print(os.getcwd()) +inputs = '../assets' +F = at.ProjectFramework(f'{inputs}/T7_framework.xlsx') +D = at.ProjectData.from_spreadsheet(f'{inputs}/T7_databook.xlsx', framework=F) + +P = at.Project(framework=F, databook=D, do_run=False) +P.settings.update_time_vector(start=2000, end=2050, dt=1 / 52) +cal = P.make_parset() +# starting calibration (if needed) +# cal.load_calibration(out_path + "/PAK_typh_YAML_autocalibrations_2024-04-25_1941_reinitialising/PAK_typh_YAML-autocalibration_2024-04-25_1959.xlsx") +# print('Existing calibration loaded') + +# new folder to put calibrations in +date = time.strftime("%Y-%m-%d_%H%M") +calspath = f'{out_path}/cal_{yaml_fname}' +if testing: + calspath += '_TESTING' + savecals = False +if savecals: + #save everything in folder + try: + os.makedirs(calspath) + except FileExistsError: + calspath += f'_{date}' + os.makedirs(f'{calspath}') + + # save yaml file for reference + new_fname = f'{yaml_fname}_{date}.yaml' + shutil.copy(yaml_path, calspath) + shutil.move(f'{calspath}/{yaml_fname}.yaml', f'{calspath}/{new_fname}.yaml') #renaming file + + #save logfile + at.start_logging(f'{calspath}/logfile_{date}.txt') + + # save current runfile for reference + runfile_name = f'{os.path.basename(__file__)}_{date}' + shutil.copy(__file__, f'{calspath}/{runfile_name}') + +# display tree +cal_tree = at.yaml_calibration.build(yaml_path) +print(cal_tree) + +#run calibration w yaml instructions # <-------------------------- +newcal = P.calibrate(parset = cal, yaml=yaml_path, quiet=False, savedir=calspath, save_intermediate=False, verbose=0) + +#save final calibration +date = time.strftime("%Y-%m-%d_%H%M") +newcal.save_calibration(f'{calspath}/typ_calibration.xlsx') +at.stop_logging() + + +#Notification - calibration finished +winsound.Beep(frequency = 2500, duration = 200) +winsound.Beep(frequency = 2750, duration = 200) +winsound.Beep(frequency = 3050, duration = 200) diff --git a/docs/tutorial/T7/calibrations/run_tutorial_autocals.py b/docs/tutorial/T7/calibrations/run_tutorial_autocals.py new file mode 100644 index 00000000..8a8bd7c7 --- /dev/null +++ b/docs/tutorial/T7/calibrations/run_tutorial_autocals.py @@ -0,0 +1,80 @@ +# This file produces calibrations of each YAML file shown in T7: YAML autocalibration tutorial. +# Output files will be saved locally in the outputs folder. +# Desirable results must be manually moved to the calibrations folder so that they can be plotted by the +# YAML_tutorial_plots_final.ipynb notebook. This is to avoid crowding the final results folder (calibrations) when +# re-running the calibrations or trying out new versions of the model. + +import sys +in_path = '../inputs' +sys.path.append(in_path) +import atomica as at +import atomica.yaml_calibration +import os +from os.path import isfile +import time +import shutil +import winsound + +yaml_dir = os.getcwd() +fnames = [f for f in os.listdir(yaml_dir) if isfile(f"{yaml_dir}/{f}")] +yaml_files = [f for f in fnames if ".yaml" in f and "T7_YAML" in f] +yaml_files += 'WE_8' + +testing = False #<------------ +savecals = True +out_path = 'outputs' + +#make project ------------------------------------------------ +inputs = '../assets' +F = at.ProjectFramework(f'{inputs}/T7_framework.xlsx') +D = at.ProjectData.from_spreadsheet(f'{inputs}/T7_databook.xlsx', framework=F) + +P = at.Project(framework=F, databook=D, do_run=False) +P.settings.update_time_vector(start=2000, end=2050, dt=1 / 52) +cal = P.make_parset() +# starting calibration (if needed) +# cal.load_calibration(out_path + "/PAK_typh_YAML_autocalibrations_2024-04-25_1941_reinitialising/PAK_typh_YAML-autocalibration_2024-04-25_1959.xlsx") +# print('Existing calibration loaded') + +for yaml_fname in yaml_files: + yaml_path = f'{yaml_dir}/{yaml_fname}' + + # new folder to put calibrations in + date = time.strftime("%Y-%m-%d_%H%M") + calspath = f'{out_path}/cals_{yaml_fname[8]}' + if savecals: + #save everything in folder + try: + os.makedirs(calspath) + except FileExistsError: + calspath += f'_{date}' + os.makedirs(f'{calspath}') + + # save yaml file for reference + new_fname = f'{yaml_fname}_{date}.yaml' + shutil.copy(yaml_path, calspath) + shutil.move(f'{calspath}/{yaml_fname}', f'{calspath}/{new_fname}') #renaming file + + #save logfile + at.start_logging(f'{calspath}/logfile_{date}.txt') + + # save current runfile for reference + runfile_name = f'{os.path.basename(__file__)}_{date}' + shutil.copy(__file__, f'{calspath}/{runfile_name}') + + # display tree + cal_tree = at.yaml_calibration.build(yaml_path) + print(cal_tree) + + #run calibration w yaml instructions # <-------------------------- + newcal = P.calibrate(parset = cal, yaml=yaml_path, quiet=False, savedir=calspath, save_intermediate=False, verbose=0) + + #save final calibration + newcal.save_calibration(f'{calspath}/cal_{yaml_fname[8]}') #newcal.save_calibration(f'{calspath}/cal_{yaml_fname}') + at.stop_logging() + + +#Notification - calibration finished +winsound.Beep(frequency = 2500, duration = 200) +winsound.Beep(frequency = 2750, duration = 200) +winsound.Beep(frequency = 3050, duration = 200) From 63220e9c1fae97f73b2635c4704ba05aa4ebb12d Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Thu, 13 Feb 2025 21:38:25 +0100 Subject: [PATCH 098/161] Add YAML files shown in tutorial --- .../T7/calibrations/T7_YAML_1_minimal.yaml | 7 +++++++ .../T7/calibrations/T7_YAML_2_sections.yaml | 12 ++++++++++++ .../T7/calibrations/T7_YAML_3_repeats.yaml | 11 +++++++++++ .../tutorial/T7/calibrations/T7_YAML_4_cal.yaml | 16 ++++++++++++++++ .../T7/calibrations/T7_YAML_5_cal_pop.yaml | 17 +++++++++++++++++ .../T7_YAML_6_cal_multiple_params.yaml | 17 +++++++++++++++++ .../T7_YAML_7_transience_initialisation.yaml | 14 ++++++++++++++ .../calibrations/T7_YAML_8_clearing_init.yaml | 14 ++++++++++++++ .../calibrations/T7_YAML_9_outer_settings.yaml | 15 +++++++++++++++ .../T7_YAML_9_outer_settings_maxtime.yaml | 12 ++++++++++++ 10 files changed, 135 insertions(+) create mode 100644 docs/tutorial/T7/calibrations/T7_YAML_1_minimal.yaml create mode 100644 docs/tutorial/T7/calibrations/T7_YAML_2_sections.yaml create mode 100644 docs/tutorial/T7/calibrations/T7_YAML_3_repeats.yaml create mode 100644 docs/tutorial/T7/calibrations/T7_YAML_4_cal.yaml create mode 100644 docs/tutorial/T7/calibrations/T7_YAML_5_cal_pop.yaml create mode 100644 docs/tutorial/T7/calibrations/T7_YAML_6_cal_multiple_params.yaml create mode 100644 docs/tutorial/T7/calibrations/T7_YAML_7_transience_initialisation.yaml create mode 100644 docs/tutorial/T7/calibrations/T7_YAML_8_clearing_init.yaml create mode 100644 docs/tutorial/T7/calibrations/T7_YAML_9_outer_settings.yaml create mode 100644 docs/tutorial/T7/calibrations/T7_YAML_9_outer_settings_maxtime.yaml diff --git a/docs/tutorial/T7/calibrations/T7_YAML_1_minimal.yaml b/docs/tutorial/T7/calibrations/T7_YAML_1_minimal.yaml new file mode 100644 index 00000000..dac077d3 --- /dev/null +++ b/docs/tutorial/T7/calibrations/T7_YAML_1_minimal.yaml @@ -0,0 +1,7 @@ + +calibration: + adjustables: b_rate, mig_rate + measurables: alive + + + diff --git a/docs/tutorial/T7/calibrations/T7_YAML_2_sections.yaml b/docs/tutorial/T7/calibrations/T7_YAML_2_sections.yaml new file mode 100644 index 00000000..227d32d5 --- /dev/null +++ b/docs/tutorial/T7/calibrations/T7_YAML_2_sections.yaml @@ -0,0 +1,12 @@ + +calibration: + + Population calibration: + + Match population sizes: + adjustables: b_rate, mig_rate + measurables: alive + + Match deaths: + adjustables: d_rate + measurables: deaths \ No newline at end of file diff --git a/docs/tutorial/T7/calibrations/T7_YAML_3_repeats.yaml b/docs/tutorial/T7/calibrations/T7_YAML_3_repeats.yaml new file mode 100644 index 00000000..f5b526f0 --- /dev/null +++ b/docs/tutorial/T7/calibrations/T7_YAML_3_repeats.yaml @@ -0,0 +1,11 @@ + +calibration: + repeats: 2 + Population calibration: + Match population sizes: + repeats: 5 + adjustables: b_rate, mig_rate + measurables: alive + Match deaths: + adjustables: d_rate + measurables: deaths diff --git a/docs/tutorial/T7/calibrations/T7_YAML_4_cal.yaml b/docs/tutorial/T7/calibrations/T7_YAML_4_cal.yaml new file mode 100644 index 00000000..5fca7b66 --- /dev/null +++ b/docs/tutorial/T7/calibrations/T7_YAML_4_cal.yaml @@ -0,0 +1,16 @@ + +calibration: + Match population sizes: + adjustables: + b_rate: + lower_bound: 0.5 + upper_bound: 20 + mig_rate: + starting_y_factor: 1.2 + measurables: + alive: + cal_start: 2000 + cal_end: 2040 + + + diff --git a/docs/tutorial/T7/calibrations/T7_YAML_5_cal_pop.yaml b/docs/tutorial/T7/calibrations/T7_YAML_5_cal_pop.yaml new file mode 100644 index 00000000..caef4bbc --- /dev/null +++ b/docs/tutorial/T7/calibrations/T7_YAML_5_cal_pop.yaml @@ -0,0 +1,17 @@ + +calibration: + Match population sizes: + adjustables: + (b_rate, 0-4): + lower_bound: 0.5 + upper_bound: 20 + (mig_rate, 5-14): + starting_y_factor: 1.2 + measurables: + (alive, 0-4), (alive, 5-14): + cal_start: 2000 + cal_end: 2040 + + + + diff --git a/docs/tutorial/T7/calibrations/T7_YAML_6_cal_multiple_params.yaml b/docs/tutorial/T7/calibrations/T7_YAML_6_cal_multiple_params.yaml new file mode 100644 index 00000000..c97d9248 --- /dev/null +++ b/docs/tutorial/T7/calibrations/T7_YAML_6_cal_multiple_params.yaml @@ -0,0 +1,17 @@ + +calibration: + Match population sizes: + adjustables: + b_rate, mig_rate: + lower_bound: 0.5 + upper_bound: 20 + starting_y_factor: 1.2 + measurables: + alive: + cal_start: 2000 + cal_end: 2040 + + + + + diff --git a/docs/tutorial/T7/calibrations/T7_YAML_7_transience_initialisation.yaml b/docs/tutorial/T7/calibrations/T7_YAML_7_transience_initialisation.yaml new file mode 100644 index 00000000..d0d4e37e --- /dev/null +++ b/docs/tutorial/T7/calibrations/T7_YAML_7_transience_initialisation.yaml @@ -0,0 +1,14 @@ + + + + + + set_initialisation: + init_year: 2010 + constant_parset: True + + + + + + diff --git a/docs/tutorial/T7/calibrations/T7_YAML_8_clearing_init.yaml b/docs/tutorial/T7/calibrations/T7_YAML_8_clearing_init.yaml new file mode 100644 index 00000000..6dd34940 --- /dev/null +++ b/docs/tutorial/T7/calibrations/T7_YAML_8_clearing_init.yaml @@ -0,0 +1,14 @@ + +calibration: + clear_initialisation: True + + + + + + save_calibration: + fname: Pop_calibration.xlsx + + + + diff --git a/docs/tutorial/T7/calibrations/T7_YAML_9_outer_settings.yaml b/docs/tutorial/T7/calibrations/T7_YAML_9_outer_settings.yaml new file mode 100644 index 00000000..b6e3622c --- /dev/null +++ b/docs/tutorial/T7/calibrations/T7_YAML_9_outer_settings.yaml @@ -0,0 +1,15 @@ + + +calibration: + Population calibration: + upper_bound: 2 + lower_bound: 0.5 + + Match population sizes: + adjustables: b_rate, mig_rate + measurables: alive + + Match deaths: + adjustables: d_rate + measurables: deaths + diff --git a/docs/tutorial/T7/calibrations/T7_YAML_9_outer_settings_maxtime.yaml b/docs/tutorial/T7/calibrations/T7_YAML_9_outer_settings_maxtime.yaml new file mode 100644 index 00000000..f742fedc --- /dev/null +++ b/docs/tutorial/T7/calibrations/T7_YAML_9_outer_settings_maxtime.yaml @@ -0,0 +1,12 @@ + +calibration: + Population calibration: + max_time: 120 + Match population sizes: + adjustables: b_rate, mig_rate + measurables: alive + Match deaths: + adjustables: d_rate + measurables: deaths + + From f2d4ea750e5f1b60de703597f6e013d9bf2c2b24 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Thu, 13 Feb 2025 21:39:28 +0100 Subject: [PATCH 099/161] Add typhoid YAML file and calibration output --- .../T7/calibrations/typ_calibration.xlsx | Bin 0 -> 10520 bytes .../typ_calibration_instructions.yaml | 55 ++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 docs/tutorial/T7/calibrations/typ_calibration.xlsx create mode 100644 docs/tutorial/T7/calibrations/typ_calibration_instructions.yaml diff --git a/docs/tutorial/T7/calibrations/typ_calibration.xlsx b/docs/tutorial/T7/calibrations/typ_calibration.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..db1b00f89211f171d7f9df5fb3dc72ffe0d063d5 GIT binary patch literal 10520 zcmbVS1zeQdwjWwR=?+m5L>d7JX%GoPx`q&u?i{)ikWgAmzyRrP7(fPw4gu*QMsk3m zJKo?4@8RC}-Z>Y3GdpIj|F^%j|KIx7-g~JiVqlU10Dx<#k2pZZwqQgH4FI6R0su%+ zJwR!DI~P+s7b6W12UBMQPIp_Iw)k$luiQkB4-$?EW2!Y@JXh5u4|vSbO_95cq3;!| zBUrUS&2s9Kj;R7vy@{Tis7CqtE z0yluqh8Jn7NIC0rxEPtT!5FUC8l#21xu!aZLxjf$$W!{BeDjui!?OXO6Z0KlDn|1& zN;8JOUQSV)atAN2n?dVr2+q>ozeQ8i|zxJ+Geuk9n9i87x(vL7-LM${pZxr{vA&yLfF4!??MVc{KD zbgw!kH7yOl$E3%z>JF#iNm#urJ&vf3HaXGxdc+G)8|d}p3^mJ|?MT=DO4Ss(J9vYS z;jbon?Eho7~5;r%1soE3;_p?d2vjh zWd(QC#!D619s{Hdfy`BRD<&D5d>%`w;{>j>?A|qN>+@zWhk4&NeI`jzG#=ZYIr5?kCwR*Tp<`#4_Rd#M?tqQC%73 zY~iX7JY~k%(43A~wvKM@1@YE+XYOjnuMQJ!MsI^e2+Rqcs_$ZKjpcZz--`C+Jog=R z&u9EzOs9U3LpHQU7%7tPw|C>OmI~a4$r<7R0GsTn=lC~EUE0Xm!qn8ond@i4b7`!o z6a)J^0#qSLwmtD%8~EpRZ?xs}%B<@fzi8|s-YYTVT78v~08RQC#Q_RuoXtiW6>j!y z-bB9L;qDo!_7fHF6}wS?W;SKmzbDme-n#GBFlob3wA6H#(zLQverDX*2o#T+obxt)YGOa4*X`Ub7*v1Z9JzJw>-@-@%KpOpW>si)(Auk`hT!QfQ`VEQGe4A@-=8@p?3tKcmbvsLtgCctd*P}c5m`c-F#JFhp{uxGY)k; zg&)omlIOzJlQySLg-4#%k54-^o$st{?i?PS81HPlf5F*G(mp8>E3hwegD;J5?9HAe z?Kzh3)~nz&ihe~#@9vcz_rMP`>`q6v)qOfAhhCExEl-dm9Yd_Ny_?DF3}PHYEVWor%1-M+1ZO%gRGkqmK})EAArHALEwb9?7TTK5#o@&%$)Ihk}#| zu`$oM8V9oQMa(jJFxtsN4Y8`b06V_5Dhw+|3W z?@*E5i{^!5InV}aH??n!mYwofG%fD+JI)I_>jSEJYA`I~0UR6>LD&`>Xmo#w;`_^D z45*>;3HmRRH2*1zYoUS0s3{SIZ^4Q2r|4*HyO=;(KR;RBVpQKBqV5LPYu1b>deX+$ zu(4mFRqe2cW!3y-)r-Boe~S88uh}!60Hp)0VYB89Dn8~?Z#~^TbvRy-ThitofzQex z%y<|WiSNs}9^DJsnt@}@ge-f)BR7Joy>YHn0)o(QiCYw2zve%O?(o$rOUgcPE`NY} zA-?=W#E@y0szHu4L;Z7`wMdI_Z`~!6vzkoKRBQ%~enbIpmhZ#d6D@H;K~cwtRCdI# zypNM8jGOOVuMQ)9h(A+1drW1eG3hlHUTx~8%HX0^%jsF%kf2Sk+`TG4_XuGkswKGb zDkQ3=AU`K?ut-~YqRy4{gxe7dogdQ7f34vfk0beu`3De)YgjlwvC%M5D?cRjRR^h! zsf6_PQKD#4XfhnVCaUGKmn!!*HXp>{#+;yInh>Y|B$dAOb*r!hniu~r+95F4<^PJR z==PshwGNZK5##5q^>-0;u3Sv9X^M%xE;xbHxP^%wg!^k?&9RE7Y8dPm{tGmJa=<+T zXyeERoRW$F!sh=Ng2_BSmW?C6(fwHv9;p%QSh;N*>}dAs@F0-kCA*iC!1{}8%!gJZ zXg_vOX(Fs(towC!IqL=Z5B5C9x8_!NMqatjKz(0O)?n(y1K60F12J_te^F7<|1qwE z8alh2|H8je@lrI$^!i&sHxLp5|dIe+-S4nZ&;psT`$Lo!=~ z>5wMaM@QLgd;JojSsvHnF97dqJ_CSLElODK+AR=UEYbt=r&BuIj^-_tz^N??(Ad0T zRZS2DsG&{hk3rizhH`9}Mm(}`gaXt4xWCQ+OEivuzH;V~A>#KrNsSn-Yt@75|FFK6 z9C0A>`>nu?AYL$&ere7!S#}Sk$CmT&!{#(ReLwa3S}oWmV&*=j0NU>y=xtMK{)p?I zoAffu+s|VI;6EATp6_MjN*AsVNn+fZ$DWFY&`y|0!{vUI*U*JmbIex9Bwo}i?wg)* zpVq)cZK_Vjha8NIBso?YkkgY&mBr!=?Mb5tZCeNUYas4Z-vw%?BFWf5 zLiq*XrloY+?(o4eJR5=Wvwb$8<-^MLhBQ_dPk#zXf8JIA5GlVU^83;uPaf&R_+^z^=l8HIN17v`>|7nAFL=kUeqy(0$7 z46Xd`#$Mt+PP=u#x`tCH`0VU_YtG2ZT-%E?Q`f4auC3$K-A$*Rl_O|S1lLl2>qmsR z%kfb&f3Jgsr@K>Cljzr|or@(Z1RNemm|t*DU=ezJ(_ge{&}3J}7QTJxXeG!E_$ znb|WG%{wF*`MK_x7rUMAxy{Uo9M#7n_V$^uFPuvxz>24-gQnuSyfPWli@R zrR~m%(!oYU86sLw5H-4d>ucV;1mfrU+N;K&!G@NcT6s?!pMmXuR+-P0z$OE$5E~nj9mL2QVL4MMKuEsdsGufij&ymm8%~ni?#jF@4!{Sza zlEvPxNGFTMu9zf?#jL0&i^Z)tCxhRvC?7v(XpvXuebIbe_z$`i^fbTaku>;!%Zt@YsL1=I$yCT{ zsVSfTv;Y6?>eAEvo>!)oFy~sUl~9>iplMpjYOSf8|40A--KA%x*{v|bH5x~%|4eyr z?-Sek6VwEa#tpfyrXeX(@%2Xgr-v(GE9pHYakYloYs3(_(zqkx_4-`kQ}t2)voWRj zp0BF19%Sb-kQ=Q%?ukzwk6b&XwJgQUtIu>})u!ZKSY7WM$>p#@)P3OqQt+!6ZMYRF zo2mh;<)yWY4Er_mPtx;26`tDk;|W}fZBHvbtD`2}QYh@+r~2*;zni@2Che*XOwyGe z!9Dkx8?mG164>|M-FX2M;SbHGwGhw-$S@q0nqFz?9f6h!+ILS(7K3&Lom18qURK1;iK5nV-{cTo zf^!ikEN@<|H$LCKyVk?XyxQW}@_lF(t!&NXUeuT%N>-+h_s#OAZMtjwqLgO1+C6rC z>W@O*q){U>HE_Lv&m_6p9s7dEM0hBN2A&m7iij|ZO6L|hyAo@YC%tG-svq~**mc?1 zouASbCPwk!*J~r~Y|KtMW#|JkC7W9KkS8L?Ij6WkLi6W!;>DN8z~_UG-?!ADAQx|K z)Y8P;2ukR3sscr=0(79yTuwEh{Vu2aP%f8KHE6NRsUFncE3^WvW(o-)zz*%d^KHDF6fHnZ zd*X)2|3&4eH(L&&`Hgo!ecdGi|4!vP?16jtEXPm++GP<`{d@awRBUl!iIvqxT%g=E z1j@TnB)!P4o0?8^E;@+t*aXw2f>Q-9zFy9qjPB1LCwi+2XzR>)+@|^Xi?+%?dQA(n zB89iCOMfH98awi5+tB`JdjymSqE7&&yPNyxk>r`@jpU@~U+8~7x+vtxt1GKQ5pv=Y z@*{$_){Sd}lhX+CI@xL67uciZYqRut=-6yWRbYS?eZLSEQ4?BJz>e~WNwyqIsioBQ zZalT%WOH^EubhKB3Uy^AC?rGhg?}q3jy5HPHYYnhbybOuz}M5cmn)P(`wc@2 zH6KHIdxAy}EhIACekNk)7~Z{?gn0AN{MF28QW9dQN$jLTSVS+~$Y=53AbJ$h-6U4) z+1<~8wDde_`fJpWcAQ}M0=1j|9JP&0_-iNbkKM{B)ox|fMr8xz7GWaN_NKxeJ^oyX zqJ~s+R>i!16iAP}x{6ZY_(1AqyHc^t@sHF9ymp zqi^D96$(sV^X8KO*u9p>8G*=uT-0*Q7DQ*K?b% zzPSpUs+!;5`Xy1QF$LdK7Eh;lsTc0cc_d6zh%#%5+PHAEPP!s{>p?v|cGla*&I&R* zli(8U12H*;yX6}J_&6dtxKh)t3}0Q=ZSQ@;v3&O}Q!vz?NQ z`DedM;(G(RH?1f&MZ=h_hOX0aQ`_*UJ zUL>66tItzbEn!>sbGB#2+)}|Fi|AZtZH)F#_jT^iVaCmSv1~|@8-1BK-W4o}+A|WcpIw z#mUmn-1%|=7Lw2soytx03YlOQwd5mn5z7ptB%#_s*REwnJ&^@VbiH?yD_gPWr(0(Z%A}$Cgx(KnI9G1yA5Zz5 z4-1Eei|0=>r4x-7>n=ht@j=hbu-3^f*S-#3RG2Jk;d?uf0yv%BdUk|?HQy}n^kff0 z3sd>VD~=mmss-jHM}8R4L0=|zVJ*n8f z_0{V86NtHM$dfVNZk|jGhctbOPJ2rJSZ^&7ss?OJ{aPZ06AX;3w*u?lV}T@~$m)cE z_&4982k)fz(8(O-(=(-~gDs1zeH5Q^4BjYX6>~a`vn^0V@ur}3}{H?5ec;hYG7?q$I zw3m{eKq}F1^}-Er`K;a`WeZflv6wx4Aj#FH%tB9VtJj#53%rY`4 z$x9~d*_^k&3+V4E0!xp$^Gz{LUj64;#~;1Zvcn ziAdun^5xp~yXJwc#S@+QaI-NeL<)#k9Rik(qUj)%Z-0y|M&5NC33)_uJV43Id$gFE z%*Aum`suEaGa`5pO9@F3?_iKByIhpn^bAUv!Q$BL()wwzA(I!ho8^7M3F1~fpK>O^ zykEg)LCEbbPojOG&jT{YE^^G_*W!^Fbql9uH;>wpS708WbI4#}=HuA;ZsG9h;m22j zW{R0T)A&NX;Xa@F?(a;u;W5}GlQ>1s_25W7!B@t$Eg)nr zl{(exy!b*+5h^d$g)rt(S;WAY)nXXD9pRIL!(OaUZ6pV$?YJced z?WBuGV==bcA6Ltz(WvEm_zWgDUX*M}p9Qn%0+UIG{8v*Jmfbn-k8U=Y<#I{x17Cef zX;rd9QdJ=Obq(QBC8OrL*W1Ji?8RYzxGyF-2D=b2j<6W^MhpkXp?cIC;CEEpXe1&#=B~fXNyW_}W-h0sNdUNju>*E~qCb?!#&Xp)~u6L_Q z_b4>GTt6v^VX?qal2;iMj{{r}Z?z>9SjQhWxThrgZf1bgt>ngpOl%WDMZZXJ$tD{LD^%kWRJ{(HO?762flm=oY+i++16V2ldCDBm5>vz zL>?PIpW;8GB#uSDW*aoB#i_^S4>5{sx zh$S$g#c`su|J~F}5~6`sC_CCOhGihhoifZTOnjX(Sb1i;rlNe-sQ;*V-m}rLdWrqe z6tH&kJhwd1^@JmbcPTeuyIT`BoucjB?H=W4g4Hy*;?fXB0xpHrvmI&`uGoz#x`VHP+45O|+;m8G%mXi6!DOGa`vs^EPBbL_;K4 z1Zb9keGMISSemifS68`l4-h6FfOKb6955CVM#@D&={+g|QiUhMdX}6u6g4G63*h2!jr(_DqE!^AKW%coir*(=xEldn- zE=eBTxww^-k^(oyrb z6A#4*l;A0$P6vaHoN6?PR{Xi6JsIzO4qr@smoVHIokdFB3hp*jrM^#={_d>+_mZ$v z=(D=p(Ig-H_y}Cro;ac3e?53pTb9YaR_Yr+1Pz)n2bK;O2I|gaOIj$u-R;vLGpHZ- zW2DLW9!VWycM7KNpPSsYc#r_;q|gsJVR#6m7l}H!_T%^jd;&&-BYdj!5=Ymoy0NVh z&W`O|d33SR_)-jhlOL~o^vW?mKk*ssp`ado!Te0Bh8>dN5YRl%PonQ5rRh#Ij|mY> z4wj%Ozz8SdoV)v6bGt7(jx4f&zu}0QXh3IuTNOM#(Ekem;W+Etx=h)w=LW`6iuTMs zodMPg&LZV}NDa%XMWrv;!9#IPLj_A8Zkup3ejG*$1$pT7iOM{HFsea1cxdMNzPkVs zBZfntZ24eMCxj)xwbhc(H#mo>*)l2YTM3obG)O(kOwc}H{{jDG8)Y0D*v*3G`@mM> z9hT$dwx)3xTg1_)mcW?9kg2GbL56MrccHMT?XjF0gBagjrXG%@q+3HF#(rD?_ z=6me=JTbUtS)PMqUr40haQST^-`*PDw9!y}yHLt}V}16gWPB5AlX&_s�veHNOi zs!_Qe${8O#jKrs+d!U<18CWK#DaGzHm$s@vkmSR*6eCc3OXGx3B2X$vJ?qxXXXI|+ zz-0B&jACcm#~Hd`*y2t>as;@vpGGF1u2-uFBAG)NA53*-j%TmZV4qdHZ#%LvXAD7u zKHoZEFAvM-_gPmh*)n5I+foGz0QC>P`wlZZ97?QE^4YO^SEbqGcr$!>LqW& z+GSrVgqaRZalD`J2a42tm8nUL+@TZWHy2<{^Qo&D1yz}ER)XsC*GEVyD}$a^=^eqt z36TM7^nxr($+1V1pH3Wx*ZM9V0L1oVT@Y77fjZXR)O)Bhd>Uri zs*?*ct(Nyoik(K%Y2ePcWttfFC%6`N!NayuVie`OXiQ?<96IKF!xs2Al~N~DUjw_M zf&|RjYi_mNi}@tFP$i2XVs9JU;b&PaUmj4^r_Rv{`;1z2ou*d$M~F1F;-QnWb2ngQ zyWRbOp|(kE>8CFMz=RG2pwo*mQ@7l+2jrZNypj}hW~Hv8DAIc~zYKF1qB#NgA3K$_ zpJMv;8O?-hs^@~L=lxR@9J=UBp6jd6?cBLpWFpoBkJ2WA3_V=ch7m-pok-l}0Zcs?K3!M43RL>TH{FKmkF_M6(yw--x9@OKb+ZF6=gyE z@)yUQ1di!@S={12bti|1D=u2vC+(*6vSlrl^G@$0t~cU--m8}qvGMBxM?_M2<8r#Q zL(t^)S0cEq=%piKIMfpFh>(9UvrAHo%`HVs$*Fpl&I-X6q=zfN$}7XR5A?7dDA)gS zBoOW;YxF|M8Ya6kZ4{MT4+950h>dx0+@1`UP`=ze@sr#wP9_*A&h#wny)IP;~Zf8Mm>z+ z16KdM#iN_p>w5EFGNin-Xkz3$O9eY}L3!)ija1j=(`Xm2#qJ8te=n0hHYmKkZ4SW* zddDr+&$`@e9`>>BAdy4xIawK$BiXOQ zOg(e9RNDjV6n6*r&NXlNhAwpOlnxemz_-K)k|I3bgN=EW`I%+}3@@-$6w%PhelDf{ zbM_c&>VE!J1zZ;YA(!mm0IuXc{iY58R0V{h=?K@PzPi@^ zr96$w2|^9w-&Vd?5w5OsejzZS;@L}tKi520Rj&rVzf_gzf2v*$gRcTyb*sMsxEcS0 llf9~b)qng_e|7g?)PMITDvDUxmlF7>|8^8xM3^sI{{ycxZf^hp literal 0 HcmV?d00001 diff --git a/docs/tutorial/T7/calibrations/typ_calibration_instructions.yaml b/docs/tutorial/T7/calibrations/typ_calibration_instructions.yaml new file mode 100644 index 00000000..9fc49bdc --- /dev/null +++ b/docs/tutorial/T7/calibrations/typ_calibration_instructions.yaml @@ -0,0 +1,55 @@ +--- +#Timestep for the model +#sim_dt: 0.019 + +#Ordered instructions for how to calibrate the model + #adj order: (adjustable var_label, populations to adjust for (default all), minimum value (default 0.1), maximum value (default 10), initial y_factor value (optional, default is parset value)) + #meas order: #(measurable var_label, populations to measure for (default all), weight (default 1.0), metric (default "fractional"), start_year (optional), end_year (optional)) +calibration: + repeats: 3 + max_time: 120 + + Population calibration: #-------------------------------------------------- + repeats: 5 + + match population sizes: + adjustables: + (b_rate, 0-4), mig_rate: [ 0.1, 10 ] + (b_rate, 0-4): + initial_value: 1.2 + measurables: alive + + match all-cause deaths: + adjustables: d_rate + measurables: deaths + + pop initialization: + clear_initialization: True + set_initialization: + init_year: 2010 + constant_parset: True + + + Epidemiology calibration: # ----------------------------------------------------- + repeats: 10 + + Typhoid calibration: + + match typhoid incidence: + adjustables: + typ_susceptibility: [0.01, 100 ] + measurables: [ typ_incidence ] + + match typhoid prevalence: + adjustables: [ [ typ_gen_dur, 0.5, 2 ], [ typ_infx, 0.01, 100 ] ] + measurables: [ typ_prev ] + + match typhoid deaths: + adjustables: [ typ_d_rate ] + measurables: [ typ_num_deaths ] + + reinitialization typhoid: + clear_initialization: True + set_initialization: + init_year: 2010 + constant_parset: True From eda9576049fea7428924099363ab315c5d2ba6e4 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Thu, 13 Feb 2025 21:39:56 +0100 Subject: [PATCH 100/161] Add worked example solutions --- docs/tutorial/T7/calibrations/WE_1.yaml | 13 +++++++++++ docs/tutorial/T7/calibrations/WE_2.yaml | 9 ++++++++ docs/tutorial/T7/calibrations/WE_3.yaml | 9 ++++++++ docs/tutorial/T7/calibrations/WE_4.yaml | 9 ++++++++ docs/tutorial/T7/calibrations/WE_5.yaml | 13 +++++++++++ docs/tutorial/T7/calibrations/WE_6.yaml | 16 ++++++++++++++ docs/tutorial/T7/calibrations/WE_7.yaml | 18 +++++++++++++++ docs/tutorial/T7/calibrations/WE_8.yaml | 29 +++++++++++++++++++++++++ 8 files changed, 116 insertions(+) create mode 100644 docs/tutorial/T7/calibrations/WE_1.yaml create mode 100644 docs/tutorial/T7/calibrations/WE_2.yaml create mode 100644 docs/tutorial/T7/calibrations/WE_3.yaml create mode 100644 docs/tutorial/T7/calibrations/WE_4.yaml create mode 100644 docs/tutorial/T7/calibrations/WE_5.yaml create mode 100644 docs/tutorial/T7/calibrations/WE_6.yaml create mode 100644 docs/tutorial/T7/calibrations/WE_7.yaml create mode 100644 docs/tutorial/T7/calibrations/WE_8.yaml diff --git a/docs/tutorial/T7/calibrations/WE_1.yaml b/docs/tutorial/T7/calibrations/WE_1.yaml new file mode 100644 index 00000000..d99f3331 --- /dev/null +++ b/docs/tutorial/T7/calibrations/WE_1.yaml @@ -0,0 +1,13 @@ + + +calibration: + Population calibration: + Match population sizes: + adjustables: b_rate, mig_rate + measurables: alive + + Match deaths: + adjustables: d_rate + measurables: deaths + + \ No newline at end of file diff --git a/docs/tutorial/T7/calibrations/WE_2.yaml b/docs/tutorial/T7/calibrations/WE_2.yaml new file mode 100644 index 00000000..d2aa7e29 --- /dev/null +++ b/docs/tutorial/T7/calibrations/WE_2.yaml @@ -0,0 +1,9 @@ +calibration: + Population calibration: + repeats: 10 + Match population sizes: + adjustables: + b_rate, mig_rate: + lower_bound: 0.1 + upper_bound: 10 + measurables: alive diff --git a/docs/tutorial/T7/calibrations/WE_3.yaml b/docs/tutorial/T7/calibrations/WE_3.yaml new file mode 100644 index 00000000..fa87a1c3 --- /dev/null +++ b/docs/tutorial/T7/calibrations/WE_3.yaml @@ -0,0 +1,9 @@ +calibration: + cal_start: 2005 + cal_end: 2040 + + Population calibration: + repeats: 10 + Match population sizes: + adjustables: b_rate, mig_rate + measurables: alive \ No newline at end of file diff --git a/docs/tutorial/T7/calibrations/WE_4.yaml b/docs/tutorial/T7/calibrations/WE_4.yaml new file mode 100644 index 00000000..77560b42 --- /dev/null +++ b/docs/tutorial/T7/calibrations/WE_4.yaml @@ -0,0 +1,9 @@ +calibration: + cal_start: 2005 + cal_end: 2040 + + Population calibration: + repeats: 10 + Match population sizes: + adjustables: (b_rate, 0-4), mig_rate + measurables: alive \ No newline at end of file diff --git a/docs/tutorial/T7/calibrations/WE_5.yaml b/docs/tutorial/T7/calibrations/WE_5.yaml new file mode 100644 index 00000000..3cdce1e6 --- /dev/null +++ b/docs/tutorial/T7/calibrations/WE_5.yaml @@ -0,0 +1,13 @@ +calibration: + cal_start: 2005 + cal_end: 2040 + + Population calibration: + repeats: 10 + Match population sizes: + adjustables: + (b_rate, 0-4): + starting_y_factor: 1.2 + mig_rate: + lower_bound: 0.1 + measurables: alive diff --git a/docs/tutorial/T7/calibrations/WE_6.yaml b/docs/tutorial/T7/calibrations/WE_6.yaml new file mode 100644 index 00000000..70669139 --- /dev/null +++ b/docs/tutorial/T7/calibrations/WE_6.yaml @@ -0,0 +1,16 @@ +calibration: + cal_start: 2005 + cal_end: 2040 + + Population calibration: + repeats: 10 + Match population sizes: + adjustables: + (b_rate, 0-4): + starting_y_factor: 1.2 + mig_rate: + lower_bound: 0.1 + measurables: alive + + set_initialization: + init_year: 2025 \ No newline at end of file diff --git a/docs/tutorial/T7/calibrations/WE_7.yaml b/docs/tutorial/T7/calibrations/WE_7.yaml new file mode 100644 index 00000000..1a3c6dc2 --- /dev/null +++ b/docs/tutorial/T7/calibrations/WE_7.yaml @@ -0,0 +1,18 @@ +calibration: + cal_start: 2005 + cal_end: 2040 + + Population calibration: + repeats: 10 + Match population sizes: + adjustables: + (b_rate, 0-4): + starting_y_factor: 1.2 + mig_rate: + lower_bound: 0.1 + measurables: alive + + clear_initialization: True + + set_initialization: + init_year: 2025 \ No newline at end of file diff --git a/docs/tutorial/T7/calibrations/WE_8.yaml b/docs/tutorial/T7/calibrations/WE_8.yaml new file mode 100644 index 00000000..4256b51b --- /dev/null +++ b/docs/tutorial/T7/calibrations/WE_8.yaml @@ -0,0 +1,29 @@ + + +calibration: + cal_start: 2005 + cal_end: 2040 + + Population calibration: + repeats: 10 + + Match population sizes: + adjustables: + (b_rate, 0-4): + starting_y_factor: 1.2 + mig_rate: + lower_bound: 0.1 + measurables: alive + + Match deaths: + adjustables: d_rate + measurables: deaths + + + clear_initialization: True + + set_initialization: + init_year: 2010 + + save_calibration: + fname: Pop_calibration.xlsx \ No newline at end of file From cc7ab6f04ecf3bd93210bb24c53821c94605d837 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Thu, 13 Feb 2025 21:40:58 +0100 Subject: [PATCH 101/161] Add calibration outputs of YAML files shown in the tutorial And also of the final worked example solution --- docs/tutorial/T7/calibrations/cal_1.xlsx | Bin 0 -> 6921 bytes docs/tutorial/T7/calibrations/cal_3.xlsx | Bin 0 -> 6982 bytes docs/tutorial/T7/calibrations/cal_4.xlsx | Bin 0 -> 6936 bytes docs/tutorial/T7/calibrations/cal_5.xlsx | Bin 0 -> 6926 bytes docs/tutorial/T7/calibrations/cal_6.xlsx | Bin 0 -> 6937 bytes docs/tutorial/T7/calibrations/cal_7.xlsx | Bin 0 -> 6917 bytes docs/tutorial/T7/calibrations/cal_8.xlsx | Bin 0 -> 6917 bytes docs/tutorial/T7/calibrations/cal_9.xlsx | Bin 0 -> 6938 bytes docs/tutorial/T7/calibrations/cal_WE8.xlsx | Bin 0 -> 13828 bytes 9 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/tutorial/T7/calibrations/cal_1.xlsx create mode 100644 docs/tutorial/T7/calibrations/cal_3.xlsx create mode 100644 docs/tutorial/T7/calibrations/cal_4.xlsx create mode 100644 docs/tutorial/T7/calibrations/cal_5.xlsx create mode 100644 docs/tutorial/T7/calibrations/cal_6.xlsx create mode 100644 docs/tutorial/T7/calibrations/cal_7.xlsx create mode 100644 docs/tutorial/T7/calibrations/cal_8.xlsx create mode 100644 docs/tutorial/T7/calibrations/cal_9.xlsx create mode 100644 docs/tutorial/T7/calibrations/cal_WE8.xlsx diff --git a/docs/tutorial/T7/calibrations/cal_1.xlsx b/docs/tutorial/T7/calibrations/cal_1.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..90de0236f223685f9fc194283101f58942fd058d GIT binary patch literal 6921 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 HI^h2S&um-2 literal 0 HcmV?d00001 diff --git a/docs/tutorial/T7/calibrations/cal_5.xlsx b/docs/tutorial/T7/calibrations/cal_5.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..6f8723faef8b5fe488cecf26044bb0ce97c75432 GIT binary patch literal 6926 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 OfFI9q{Crb42mB8xuwsk= literal 0 HcmV?d00001 diff --git a/docs/tutorial/T7/calibrations/cal_6.xlsx b/docs/tutorial/T7/calibrations/cal_6.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5362c5a515b50bfe8d8e3a06a2b0e5942c452da2 GIT binary patch literal 6937 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 literal 0 HcmV?d00001 diff --git a/docs/tutorial/T7/calibrations/cal_8.xlsx b/docs/tutorial/T7/calibrations/cal_8.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..6a9a4b1e9155cbab32beb9f0c705e2d8f1fb08d2 GIT binary patch literal 6917 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 literal 0 HcmV?d00001 diff --git a/docs/tutorial/T7/calibrations/cal_9.xlsx b/docs/tutorial/T7/calibrations/cal_9.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b28f538dda3763b1a866d761b2515495fbcbf5f5 GIT binary patch literal 6938 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 Date: Thu, 13 Feb 2025 21:42:12 +0100 Subject: [PATCH 102/161] Add stripped plotting notebooks --- .../Plot_YAML_tutorial_plots.ipynb | 516 ++++++++++++++++++ .../Plot_final_typhoid_calibration.ipynb | 202 +++++++ 2 files changed, 718 insertions(+) create mode 100644 docs/tutorial/T7/calibrations/Plot_YAML_tutorial_plots.ipynb create mode 100644 docs/tutorial/T7/calibrations/Plot_final_typhoid_calibration.ipynb diff --git a/docs/tutorial/T7/calibrations/Plot_YAML_tutorial_plots.ipynb b/docs/tutorial/T7/calibrations/Plot_YAML_tutorial_plots.ipynb new file mode 100644 index 00000000..b8995e53 --- /dev/null +++ b/docs/tutorial/T7/calibrations/Plot_YAML_tutorial_plots.ipynb @@ -0,0 +1,516 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "0", + "metadata": {}, + "source": [ + "# Calibration plots for the YAML files shown in the YAML tutorial\n", + "\n", + "This plots the calibration reslts from `run_tutorial_autocals` (which includes the final worked example as well as the YAML examples in the tutorial)" + ] + }, + { + "cell_type": "markdown", + "id": "1", + "metadata": {}, + "source": [ + "# Make project" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2", + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3", + "metadata": {}, + "outputs": [], + "source": [ + "import atomica as at\n", + "import os\n", + "from os.path import isfile\n", + "import re\n", + "import sciris as sc" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4", + "metadata": {}, + "outputs": [], + "source": [ + "inputs = '../assets'\n", + "F = at.ProjectFramework(f'{inputs}/T7_framework.xlsx')\n", + "D = at.ProjectData.from_spreadsheet(f'{inputs}/T7_databook.xlsx', framework=F)\n", + "P = at.Project(framework=F,databook=D)\n", + "P.settings.update_time_vector(start=2000, end=2040, dt=1/52)" + ] + }, + { + "cell_type": "markdown", + "id": "5", + "metadata": { + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "# Pre-calibraton" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6", + "metadata": {}, + "outputs": [], + "source": [ + "cal0 = P.make_parset()\n", + "res0 = P.run_sim(parset=cal0, result_name = 'Uncalibrated')\n", + "d = at.PlotData(res0, outputs=['alive','deaths'], project=P)\n", + "fig = at.plot_series(d,axis='pops', data=P.data, n_cols=2, legend_mode='none')[0]\n", + "fig.set_size_inches(8,4)\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7", + "metadata": {}, + "outputs": [], + "source": [ + "cal0 = P.make_parset()\n", + "res0 = P.run_sim(parset=cal0, result_name = 'Uncalibrated')\n", + "d = at.PlotData(res0, outputs=['alive', 'typ_incidence', 'typ_prev', 'typ_num_deaths'], project=P)\n", + "fig = at.plot_series(d,axis='pops', data=P.data, n_cols=2, legend_mode='none')[0]\n", + "fig.set_size_inches(8,6)\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "markdown", + "id": "8", + "metadata": {}, + "source": [ + "# Import calibrations" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9", + "metadata": {}, + "outputs": [], + "source": [ + "#calibration files to import\n", + "calpaths = ['cal_1', '', 'cal_3', 'cal_4', 'cal_5', 'cal_6', 'cal_7', 'cal_8', 'cal_9', 'cal_WE8']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "10", + "metadata": {}, + "outputs": [], + "source": [ + "resdict = sc.odict()\n", + "for i, file in enumerate(calpaths):\n", + " print(i+1)\n", + " print(file)\n", + " print(f'res_{i+1}')\n", + " if file == '':\n", + " continue\n", + " cal = P.make_parset() \n", + " cal = cal.load_calibration(f'{file}.xlsx')\n", + " resdict[f'res_{i+1}'] = P.run_sim(parset=cal, result_name = file)" + ] + }, + { + "cell_type": "markdown", + "id": "11", + "metadata": {}, + "source": [ + "# Plot calibrations" + ] + }, + { + "cell_type": "markdown", + "id": "12", + "metadata": {}, + "source": [ + "## 1 - Minimal yaml file (shown in tutorial)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13", + "metadata": {}, + "outputs": [], + "source": [ + "# specific calibration\n", + "file = 'cal_1.xlsx'\n", + "cal1 = P.make_parset() \n", + "cal1 = cal1.load_calibration(file)\n", + "res1 = P.run_sim(parset=cal1, result_name = 'Simple calibration')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "14", + "metadata": { + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "d = at.PlotData([res0, res1], outputs='alive', project=P, pops='65+')\n", + "at.plot_series(d, axis='results', data=P.data);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "15", + "metadata": {}, + "outputs": [], + "source": [ + "d = at.PlotData(res1, outputs=['alive','typ_incidence', 'typ_prev', 'typ_num_deaths'], project=P)\n", + "fig = at.plot_series(d,axis='pops', data=P.data, n_cols=2, legend_mode='none')[0]\n", + "fig.set_size_inches(12,8)\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "16", + "metadata": {}, + "outputs": [], + "source": [ + "d = at.PlotData(res1, outputs=['alive', 'deaths', 'typ_prev', 'typ_num_deaths'], project=P)\n", + "fig = at.plot_series(d,axis='pops', data=P.data, n_cols=2, legend_mode='none')[0]\n", + "fig.set_size_inches(12,8)\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "markdown", + "id": "17", + "metadata": { + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "## 3 - Repeats (not shown at the moment)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "18", + "metadata": { + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "d = at.PlotData(resdict['res_3'], outputs=['alive','deaths', 'typ_incidence', 'typ_prev', 'typ_num_deaths'], project=P)\n", + "fig = at.plot_series(d,axis='pops', data=P.data, n_cols=2, legend_mode='none')[0]\n", + "fig.set_size_inches(10,8)\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "19", + "metadata": {}, + "outputs": [], + "source": [ + "d = at.PlotData(resdict['res_3'], outputs=['alive','typ_incidence', 'typ_prev', 'typ_num_deaths', ], project=P)\n", + "fig = at.plot_series(d,axis='pops', data=P.data, n_cols=2, legend_mode='none')[0]\n", + "fig.set_size_inches(10,8)\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "20", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "21", + "metadata": { + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "## 4 - cal dict format (not shown)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "22", + "metadata": { + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "#plot total pop: cals vs no calibration\n", + "d = at.PlotData(resdict['res_4'], outputs='alive', project=P)\n", + "at.plot_series(d, axis='pops', data=P.data);" + ] + }, + { + "cell_type": "markdown", + "id": "23", + "metadata": { + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "## 5 - calibrate specific pops (not shown)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "24", + "metadata": { + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "#plot total pop: cals vs no calibration\n", + "d = at.PlotData(resdict['res_5'], outputs='alive', project=P)\n", + "at.plot_series(d, axis='pops', data=P.data);" + ] + }, + { + "cell_type": "markdown", + "id": "25", + "metadata": { + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "## 6 - cal with mult params (not shown)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "26", + "metadata": { + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "#plot total pop: cals vs no calibration\n", + "d = at.PlotData(resdict['res_6'], outputs='alive', project=P)\n", + "at.plot_series(d, axis='pops', data=P.data);" + ] + }, + { + "cell_type": "markdown", + "id": "27", + "metadata": { + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "## 7 - init (showing a different example)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "28", + "metadata": { + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "#plot total pop: cals vs no calibration\n", + "d = at.PlotData(resdict['res_7'], outputs='alive', project=P)\n", + "at.plot_series(d, axis='pops', data=P.data);" + ] + }, + { + "cell_type": "markdown", + "id": "29", + "metadata": { + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "## 8 - clear init (showing a different example)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "30", + "metadata": { + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "#plot total pop: cals vs no calibration\n", + "d = at.PlotData(resdict['res_8'], outputs='alive', project=P)\n", + "at.plot_series(d, axis='pops', data=P.data);" + ] + }, + { + "cell_type": "markdown", + "id": "31", + "metadata": {}, + "source": [ + "# cal 9 - outer settings (not shown)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "32", + "metadata": {}, + "outputs": [], + "source": [ + "#plot total pop: cals vs no calibration\n", + "d = at.PlotData(resdict['res_9'], outputs='alive', project=P)\n", + "at.plot_series(d, axis='pops', data=P.data);" + ] + }, + { + "cell_type": "markdown", + "id": "33", + "metadata": { + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "### add -cal with outer params (not shown)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "34", + "metadata": {}, + "outputs": [], + "source": [ + "# #plot total pop: cals vs no calibration\n", + "# d = at.PlotData(resdict['res_9'], outputs='alive', project=P)\n", + "# at.plot_series(d, axis='pops', data=P.data);" + ] + }, + { + "cell_type": "markdown", + "id": "35", + "metadata": {}, + "source": [ + "# WE_8: Worked example calibration (shown in tutorial)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "36", + "metadata": {}, + "outputs": [], + "source": [ + "d = at.PlotData(resdict['res_10'], outputs=['alive', 'deaths', 'typ_prev', 'typ_num_deaths'], project=P)\n", + "fig = at.plot_series(d,axis='pops', data=P.data, n_cols=2, legend_mode='none')[0]\n", + "fig.set_size_inches(12,8)\n", + "fig.tight_layout()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "AtomicaTest", + "language": "python", + "name": "atomicatest" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": true + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/tutorial/T7/calibrations/Plot_final_typhoid_calibration.ipynb b/docs/tutorial/T7/calibrations/Plot_final_typhoid_calibration.ipynb new file mode 100644 index 00000000..6c4ca419 --- /dev/null +++ b/docs/tutorial/T7/calibrations/Plot_final_typhoid_calibration.ipynb @@ -0,0 +1,202 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "0", + "metadata": {}, + "source": [ + "# Calibration plots for the pop + epi calibration\n", + "\n", + "This plots the results from `run_model_autocals.py` (whole calibration)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1", + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2", + "metadata": {}, + "outputs": [], + "source": [ + "import atomica as at\n", + "import os\n", + "from os.path import isfile\n", + "import re\n", + "import sciris as sc" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3", + "metadata": {}, + "outputs": [], + "source": [ + "#load typhoid project\n", + "inputs = '../assets'\n", + "F = at.ProjectFramework(f'{inputs}/T7_framework.xlsx')\n", + "D = at.ProjectData.from_spreadsheet(f'{inputs}/T7_databook.xlsx', framework=F)\n", + "P = at.Project(framework=F, databook=D, do_run=False)\n", + "P.settings.update_time_vector(start=2000, end=2040, dt=1/52)" + ] + }, + { + "cell_type": "markdown", + "id": "4", + "metadata": {}, + "source": [ + "# Plot uncalibrated" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5", + "metadata": {}, + "outputs": [], + "source": [ + "cal0 = P.make_parset()\n", + "res0 = P.run_sim(parset=cal0, result_name = 'Uncalibrated')\n", + "d = at.PlotData(res0, outputs=['alive', 'deaths'], project=P)\n", + "at.plot_series(d, axis='pops', data=P.data, n_cols=2, legend_mode='none');" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6", + "metadata": {}, + "outputs": [], + "source": [ + "d = at.PlotData(res0, outputs=['alive','typ_incidence', 'typ_prev', 'typ_num_deaths'], project=P)\n", + "fig = at.plot_series(d,axis='pops', data=P.data, n_cols=2, legend_mode='none')[0]\n", + "fig.set_size_inches(12,8)\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "markdown", + "id": "7", + "metadata": {}, + "source": [ + "# Load in calibrations" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8", + "metadata": {}, + "outputs": [], + "source": [ + "calfile= \"typ_calibration.xlsx\"\n", + "print(calfile)\n", + "cal = P.make_parset() \n", + "cal = cal.load_calibration(f'{calfile}')\n", + "res1 = P.run_sim(parset=cal, result_name = 'Complete YAML calibration')" + ] + }, + { + "cell_type": "markdown", + "id": "9", + "metadata": {}, + "source": [ + "# Plot calibrations" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "10", + "metadata": {}, + "outputs": [], + "source": [ + "d = at.PlotData(res1, outputs=['alive', 'deaths'], project=P)\n", + "at.plot_series(d, axis='pops', data=P.data, n_cols=2, legend_mode='none');" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11", + "metadata": {}, + "outputs": [], + "source": [ + "d = at.PlotData(res1, outputs=['alive','deaths', 'typ_prev', 'typ_num_deaths'], project=P)\n", + "fig = at.plot_series(d,axis='pops', data=P.data, n_cols=2, legend_mode='none')[0]\n", + "fig.set_size_inches(12,8)\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "12", + "metadata": {}, + "outputs": [], + "source": [ + "#display deaths\n", + "d = at.PlotData(res1, outputs='d_rate:flow', project=P) \n", + "for s in d.series:\n", + " s.data_label = 'deaths'\n", + "at.plot_series(d,axis='pops',data=P.data);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13", + "metadata": {}, + "outputs": [], + "source": [ + "#display other typh vars\n", + "d = at.PlotData(res1, outputs=['life_exp'], project=P)\n", + "at.plot_series(d,axis='pops',data=P.data);" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "AtomicaTest", + "language": "python", + "name": "atomicatest" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": true + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 17fbfc73be3bc4f17caaf2f71bd337c147c37c6b Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Thu, 13 Feb 2025 21:42:28 +0100 Subject: [PATCH 103/161] Add README --- docs/tutorial/T7/calibrations/README.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 docs/tutorial/T7/calibrations/README.txt diff --git a/docs/tutorial/T7/calibrations/README.txt b/docs/tutorial/T7/calibrations/README.txt new file mode 100644 index 00000000..db78fa2e --- /dev/null +++ b/docs/tutorial/T7/calibrations/README.txt @@ -0,0 +1,10 @@ +Contains example YAML files and scripts to run calibrations with them + +- `T7_YAML_*` files correspond to the examples of YAML calibrations used in Tutorial 7 +- `WE_*.yaml` are the solutions to the 'worked example' section in Tutorial 7 +- `typ_calibration_instructions.yaml` corresponds to a full finished YAML calibration for the model + +This folder also contains + +- `*.py` files to run the YAML files and produce `*.xlsx` calibration outputs +- `*.ipynb` notebooks to generate plots using those calibration outputs \ No newline at end of file From 764b7d9df270e3e025ad646cd8e744d3e0fbc5bc Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Fri, 14 Feb 2025 00:11:39 +0100 Subject: [PATCH 104/161] Update tutorial text --- .../tutorial/T7/T7_YAML_autocalibration.ipynb | 56 ++++++++++--------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/docs/tutorial/T7/T7_YAML_autocalibration.ipynb b/docs/tutorial/T7/T7_YAML_autocalibration.ipynb index 348fc980..0f2fbf22 100644 --- a/docs/tutorial/T7/T7_YAML_autocalibration.ipynb +++ b/docs/tutorial/T7/T7_YAML_autocalibration.ipynb @@ -101,7 +101,7 @@ "1. Demographic calibration: Adjusting birth and background death rates to match quantities like the total population size.\n", "2. Epidemiological calibration: Adjusting parameters such as force of infection, diagnosis rate and mortality rate, to match quantities like incidence, prevalence and deaths.\n", "\n", - "Each of these steps involves calibrating multiple parameters, which may be adjusted sequentially and repeatedly. They may also be interspersed with adjusting the model's initialization, to help minimize sudden transients at the start of the simulation. The purpose of the YAML file is to specify the sequence of steps to follow in carrying out a calibration run, in terms of which parameters to adjust, the order in which to adjust them, and how to assess the quality of the calibration at each step of the process. In this tutorial, we will use a YAML file to specify a sequence of steps to calibrate the simple typhoid model shown above, starting with a minimal example and then introducing key features provided by Atomica's YAML calibration system." + "Each of these steps involves calibrating multiple parameters, which may be adjusted sequentially and repeatedly. They may also be interspersed with adjusting the model's initialization, to help minimize sudden transients at the start of the simulation. The purpose of the YAML file is to specify the sequence of steps to follow in carrying out a calibration run, in terms of which parameters to adjust, the order in which to adjust them (or whether some should be adjusted simultaneously), and how to assess the quality of the calibration at each step of the process. In this tutorial, we will use YAML files to specify a sequence of steps to calibrate the simple typhoid model shown above, starting with a minimal example and then introducing key features provided by Atomica's YAML calibration system." ] }, { @@ -121,15 +121,18 @@ "\n", "The above YAML file represents a single call to the autocalibration optimisation function, where the `b_rate` and `mig_rate` y-factors are adjusted to match `alive`. It is equivalent to running a calibration with the following command:\n", "\n", - " calibrated_parset = P.calibrate(parset = cal, adjustables = [b_rate, mig_rate], measurables=alive)\n", + " calibrated_parset = P.calibrate(parset = cal, adjustables = ['b_rate', 'mig_rate'], measurables = 'alive')\n", "\n", "Running the YAML calibration is very similar to performing a standalone auto-calibration. After saving the YAML file to disk (e.g. [T7_YAML_1_minimal.yaml](./<`T7_YAML_1_minimal`>.)), the calibration can be run using\n", "\n", " calibrated_parset = P.calibrate(parset = cal, yaml='T7_YAML_1_minimal.yaml')\n", "\n", - "As the YAML calibration framework allows us to specify the adjustables and measurables, it is not necessary to provide them to `Project.calibrate()`, simply providing the YAML file is sufficient. However, the YAML file can contain multiple calibration commands, and therefore a single call to `Project.calibrate()` with a YAML file might be equivalent to multiple explicit calibration steps. The resulting simulation after running this simple calibration is like so: \n", + "As the YAML calibration framework allows us to specify the adjustables and measurables, it is not necessary to provide them to `Project.calibrate()` – simply providing the YAML file is sufficient. However, the YAML file can contain multiple calibration commands, and therefore a single call to `Project.calibrate()` with a YAML file might be equivalent to multiple explicit calibration steps. The resulting simulation after running this simple calibration is like so: \n", "\n", - "\"Simple" + "\"Simple\n", + "\"Simple\n", + "\n", + "As you can see, these plots don't look very different to the uncalibrated simulation results. If we plot the uncalibrated simulation in the same plot as our simple calibration, we can see that there has been a slight change, but not nearly enough to be able to consider this a good calibration. Next, we will illustrate the YAML calibration features that we can use to improve on this initial result. " ] }, { @@ -139,10 +142,10 @@ "source": [ "## Sections\n", "\n", - "At the most basic level, a YAML calibration file defines a sequence of individual steps, where each step incrementally modify the calibration. The YAML file therefore defines an overall _algorithm_ for performing an automatic calibration. This algorithm is defined using two structures in the YAML file\n", + "At the most basic level, a YAML calibration file defines a sequence of individual steps, where each step incrementally modifies the calibration. The YAML file therefore defines an overall _algorithm_ for performing an automatic calibration. This algorithm is defined using two structures in the YAML file:\n", "\n", - "- _actions_ which are associated with particular operations, like running a gradient-descent calibration step with a particular set of parameters and data. A calibration action contains 'adjustables' and 'measurables'. Other examples of actions are detailed below\n", - "- _sections_ which are containers for actions. Sections can contain attributes such as how many times to repeat the contents of the section, or can define settings that are applied to any actions within the section\n", + "- _actions_, which are associated with particular operations, like running a gradient-descent calibration step with a particular set of parameters and data. A calibration action contains `adjustables` and `measurables`. Other examples of actions are detailed below.\n", + "- _sections_, which are containers for actions. Sections can contain attributes, such as how many times to repeat the contents of the section, or they can define settings that are applied to any relevant actions within that section.\n", "\n", "The original YAML file above consisted of a single calibration action. If we wanted to extend the algorithm by adding a step to calibrate the death rate, we could update our YAML file to the following: \n", "\n", @@ -172,17 +175,18 @@ "\n", "The overall structure of this YAML file is thus:\n", "\n", - "1. A top-level section titled `calibration` which has one sub-section (`Population calibration`)\n", - "2. A sub-section called `Population calibration` which in turn contains two actions\n", - "3. An action called `Match population sizes` corresponding to the original calibration step for adjusting the birth rate and migration rate\n", - "4. An action called `Match deaths` corresponding to the new step of adjusting the death rate\n", + "1. A top-level section titled `calibration`, which has one sub-section (`Population calibration`)\n", + "2. A sub-section called `Population calibration`, which in turn contains two actions\n", + "3. An action called `Match population sizes`, corresponding to the original calibration step we used to adjust the birth rate and migration rate\n", + "4. An action called `Match deaths`, corresponding to the new step of adjusting the death rate\n", "\n", "An action is differentiated from a section in two possible ways:\n", "\n", - "- By contents e.g., if it contains `adjustables` and `measurables` then it is interpreted as a calibration action rather than a section\n", - "- By the title i.e., if the name corresponds to the name of a supported operation, as described below.\n", - " \n", - "Aside for the names of supported operations, sections can freely named." + "- By its contents (e.g. if it contains `adjustables` and `measurables`, then it will be interpreted as a calibration action rather than a section)\n", + "- By the title (if the name corresponds to the name of a supported operation, as described below)\n", + "\n", + "Additionally, actions can never contain any sub-sections, whereas sections do. \n", + "Apart from the names of supported operations, sections can be freely named." ] }, { @@ -224,15 +228,15 @@ "source": [ "## Sections vs Actions\n", "\n", - "As shown above, sections can help us to structure the calibration in a way that is practical and intuitive. They can be used to group blocks of YAML code that are conceptually related, that we want to repeat together several times, or that we want to apply similar settings to (we will cover which settings are supported in a [later section](#specifying-calibration-settings-in-outer-sections)). \n", + "As shown above, sections can help us to structure the calibration in a way that is practical and intuitive. They can be used to group blocks of YAML code that are conceptually related, that we want to repeat together several times, or that we want to apply similar settings to (we will cover which settings are supported in [the corresponding section](#specifying-calibration-settings-in-outer-sections)). \n", "\n", "Importantly though, _sections_ do not modify the calibration itself – they are merely wrappers for the innermost blocks that actually correspond to specific actions. It is in these _actions_ that operations are performed on the calibration, such as modifying the calibration or saving it.\n", "\n", "

    \n", "\n", - "It is possible to load and inspect a YAML file in Atomica without executing it. This can help confirm that the YAML file has been parsed correctly. After loading the calibration, it can be printed to show a summary of the sections and actions that are present, how they are nested, and how many times they are repeated: " + "It is possible to load and inspect a YAML file in Atomica without executing it. This can help confirm that the YAML file has been parsed correctly. After loading in the YAML file, it can be printed to show a summary of the sections and actions that are present, how they are nested, and how many times they are repeated: " ] }, { @@ -252,9 +256,9 @@ "id": "11", "metadata": {}, "source": [ - "## Types of Functional Blocks/Actions\n", + "## Types of Action Blocks\n", "\n", - "YAML calibration files can contain the following types of action blocks: \n", + "YAML calibration files can contain the following types of actions, or action blocks: \n", "\n", "- Calibration block\n", "- Initialization block\n", @@ -269,30 +273,30 @@ "source": [ "### Calibration blocks\n", "\n", - "In all of the YAML examples shown above, we have worked with 'calibration blocks', which are the main type of action block. Calibration blocks are defined by the fact that they contain two keywords called `adjustables` and `measurables`. Under `adjustables`, we list the parameters for Atomica’s optimisation algorithm to adjust, and under `measurables`, we list the parameters to calibrate to. Each calibration block provides instructions for one optimisation run, and is equivalent to making a call to `P.calibrate()` with the same adjustables and measurables.\n", + "In all of the YAML examples shown above, we have worked with 'calibration blocks', which are the main type of action. Calibration blocks are defined by the fact that they contain the keywords `adjustables` and `measurables`. Under `adjustables`, we list the parameters for Atomica’s optimisation algorithm to adjust, and under `measurables`, we list the parameters to calibrate to. Each calibration block provides instructions for one optimisation run, and is equivalent to making a call to `P.calibrate()` with the same adjustables and measurables.\n", "\n", "#### Adjustable and measurable settings\n", "\n", - "So far, we have only specified the names of the adjustables and measurables, with no further information – in that case, the optimisation algorithm will use the default settings for adjustables and measurables. For more flexibility, we can specify further settings for the optimisation. The settings for the adjustables and measurables directly map to the options supported by `P.calibrate()`. \n", + "So far, we have only specified the names of the adjustables and measurables, with no further information – in that case, the optimisation algorithm will use the default settings for adjustables and measurables. For more flexibility, we can customise the settings to be used for the optimisation. The settings for the adjustables and measurables directly map to the options supported by `P.calibrate()`. \n", "\n", "Each adjustable has:\n", "\n", - "- `adj_label` (required): Adjustable codename (can be found in the framework)\n", + "- `adj_label` (required): Adjustable parameter codename (can be found in the framework)\n", "- `pop_name`: Population to calibrate (default: all populations)\n", "- `lower_bound`: Lowest value the y-factor will be allowed to take (default: 0.1)\n", - "- `upper_bound`: Highest value the y-factor will be allowed to take (default: 1)\n", + "- `upper_bound`: Highest value the y-factor will be allowed to take (default: 10)\n", "- `starting_y_factor`: Y-factor value the autocalibration will start from when running the optimisation algorithm (default: the adjustable’s current `y_factor` in the parset)\n", "\n", "Each measurable has:\n", "\n", - "- `meas_label` (required): Measurable codename (can be found in the framework)\n", + "- `meas_label` (required): Measurable parameter codename (can be found in the framework)\n", "- `pop_name`: Population to use for calibration (default: all populations)\n", "- `weight`: Weight for a particular population (default: 1). By default, all populations are weighted equally regardless of size. See [the documentation on weights]((./YAML_documentation_page.ipynb#measurable-weights \"Measurable weights\") for further details.\n", "- `metric`: Metric to be used by the optimisation algorithm (default: fractional)\n", "- `cal_start`: Starting year that the calibration will be evaluated from (default: `sim_start`)\n", "- `cal_end`: End year until which the calibration will be evaluated (default: `sim_end`)\n", "\n", - "Note that `sim_start` and `sim_end` are the start and end years that the simulation will run for (the simulation timespan) which are distinct from `cal_start` and `cal_end`, which specify the time period for which we want to calibrate the model, i.e. a subset of the simulation timespan. For more information, see the [section on outer settings](#specifying-calibration-settings-in-outer-sections). The `cal_start` and `cal_end` years can be set per-measurable, so it is possible to prioritize different years for different variables or for different steps of the calibration. \n", + "Note that `sim_start` and `sim_end` are the start and end years that the simulation will run for (the simulation timespan). These are distinct from `cal_start` and `cal_end`, which specify the time period for which we want to calibrate the model, i.e. a subset of the simulation timespan. For more information, see the [section on outer settings](#specifying-calibration-settings-in-outer-sections). The `cal_start` and `cal_end` years can be set per measurable, so it is possible to prioritize different years for different variables or for different steps of the calibration. \n", "To specify these adjustables and measurables settings in the YAML file, we simply write the setting names and their values under the relevant parameter name. Each adjustable and measurable is placed on a new line, and their respective settings are also specified on separate indented lines, like so: \n", "\n", " calibration: \n", From 95666ff8993ddb2ccb39b5910ffb739798a7158b Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 17 Feb 2025 13:01:20 +1000 Subject: [PATCH 105/161] Remove extra calculations --- docs/tutorial/T7/assets/T7_databook.xlsx | Bin 84343 -> 75643 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/tutorial/T7/assets/T7_databook.xlsx b/docs/tutorial/T7/assets/T7_databook.xlsx index 5110e7feb568e5cd5db1b6abac9c1fd883831a07..e41e519a4915bc3bed2fb0b6cf59e9c9c7482a34 100644 GIT binary patch delta 63577 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\n", - "\n", - "It is possible to load and inspect a YAML file in Atomica without executing it. This can help confirm that the YAML file has been parsed correctly. After loading in the YAML file, it can be printed to show a summary of the sections and actions that are present, how they are nested, and how many times they are repeated: " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "10", - "metadata": {}, - "outputs": [], - "source": [ - "import atomica.yaml_calibration \n", - "calibration_tree = at.yaml_calibration.build('calibrations/T7_YAML_3_repeats.yaml') \n", - "print(calibration_tree)" - ] - }, - { - "cell_type": "markdown", - "id": "11", - "metadata": {}, - "source": [ - "## Types of Action Blocks\n", - "\n", - "YAML calibration files can contain the following types of actions, or action blocks: \n", - "\n", - "- Calibration block\n", - "- Initialization block\n", - "- Intialization clearing block\n", - "- Saving block" - ] - }, - { - "cell_type": "markdown", - "id": "12", - "metadata": {}, - "source": [ - "### Calibration blocks\n", - "\n", - "In all of the YAML examples shown above, we have worked with 'calibration blocks', which are the main type of action. Calibration blocks are defined by the fact that they contain the keywords `adjustables` and `measurables`. Under `adjustables`, we list the parameters for Atomica’s optimisation algorithm to adjust, and under `measurables`, we list the parameters to calibrate to. Each calibration block provides instructions for one optimisation run, and is equivalent to making one call to `P.calibrate()` with the same adjustables and measurables.\n", - "\n", - "#### Adjustable and measurable settings\n", - "\n", - "So far, we have only specified the names of the adjustables and measurables, with no further information – in that case, the optimisation algorithm will use the default calibration settings for adjustables and measurables. For more flexibility, we can customise the settings that will be used for the optimisation, which directly map to the options supported by `P.calibrate()`.\n", - "\n", - "Each adjustable has:\n", - "\n", - "- `adj_label` (required): Adjustable parameter codename (can be found in the framework)\n", - "- `pop_name`: Population to calibrate (default: all populations)\n", - "- `lower_bound`: Lowest value the y-factor will be allowed to take (default: 0.1)\n", - "- `upper_bound`: Highest value the y-factor will be allowed to take (default: 10)\n", - "- `starting_y_factor`: Y-factor value the optimisation algorithm will start from (default: the adjustable's current `y_factor` in the parset)\n", - "\n", - "Each measurable has:\n", - "\n", - "- `meas_label` (required): Measurable parameter codename (can be found in the framework)\n", - "- `pop_name`: Population to use for calibration (default: all populations)\n", - "- `weight`: Weight for a particular population (default: 1). By default, all populations are weighted equally regardless of size. See [the documentation on weights](https://atomica.tools/docs/master/general/YAML_calibration.html#Measurable-Weights \"Measurable weights\") for further details.\n", - "- `metric`: Metric to be used by the optimisation algorithm (default: fractional)\n", - "- `cal_start`: Starting year that the calibration will be evaluated from (default: `sim_start`)\n", - "- `cal_end`: End year until which the calibration will be evaluated (default: `sim_end`)\n", - "\n", - "Note that `sim_start` and `sim_end` are the start and end years that the simulation will run for (the simulation timespan). These are distinct from `cal_start` and `cal_end`, which specify the time period for which we want to calibrate the model, i.e. a subset of the simulation timespan. For more information, see the [section on outer settings](#specifying-settings-in-outer-sections \"Specifying settings in outer sections\"). The `cal_start` and `cal_end` years can be set independently for each measurable, so it is possible to prioritize different years for different variables or for different steps of the calibration.\n", - "To specify these adjustables and measurables settings in the YAML file, we simply write the setting names and their values under the relevant parameter name. Each adjustable and measurable is placed on a new line, and their respective settings are also specified on separate indented lines, like so:\n", - "\n", - " calibration:\n", - " Match population sizes:\n", - " adjustables: \n", - " \tb_rate: \n", - " \t\tlower_bound: 0.5\n", - " \t\tupper_bound: 20\t\t\n", - " \tmig_rate: \n", - " \t\tstarting_y_factor: 1.2 \n", - " measurables: \n", - " alive:\n", - " \tcal_start: 2000\n", - " \tcal_end: 2040\n", - " " - ] - }, - { - "cell_type": "markdown", - "id": "13", - "metadata": { - "editable": true, - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, - "source": [ - "#### Specifying Populations\n", - "\n", - "In some cases, you may want to only set adjustables or measurables for a specific population, or you may wish to use different settings for one population compared to another. A population can optionally be specified after the parameter name, as the second element of a tuple. Thus, if we only wish to calibrate some populations, we can rewrite our previous YAML file like so:\n", - "\n", - " calibration: \n", - " Match population sizes:\n", - " adjustables: \n", - " \t(b_rate, 0-4): \n", - " \t\tlower_bound: 0.5\n", - " \t\tupper_bound: 20\t\t\n", - " \t(mig_rate, 5-14): \n", - " \t\tstarting_y_factor: 1.2 \n", - " measurables: \n", - " (alive, 0-4), (alive, 5-14):\n", - " \tcal_start: 2000\n", - " \tcal_end: 2040\n", - " \n", - "Note that we can specify the same settings for more than one adjustable/measurable at once by placing several parameter names before the colon, separated by commas – this is applicable to any set of adjustables/measurables, not only different populations of the same parameter. For example, we could write: \n", - "\n", - " calibration: \n", - " Match population sizes:\n", - " adjustables: \n", - " \t(b_rate, 0-4), mig_rate: \n", - " \t\tlower_bound: 0.5\n", - " \t\tupper_bound: 20\n", - " starting_y_factor: 1.2\t\t \n", - " measurables: \n", - " (alive, 0-4), (alive, 5-14):\n", - " \tcal_start: 2000\n", - " \tcal_end: 2040\n", - "\n", - "Finally, the same syntax we use to calibrate populations can be used to calibrate transfers and interactions, but in such cases the tuple should have three elements - the parameter name, the _from_ population and the _to_ population. For more information on how to calibrate in these cases, see the documentation on [Calibrating transfers and interactions](https://atomica.tools/docs/master/general/YAML_calibration.html#Calibrating-transfers-and-interactions \"Calibrating transfers and interactions\")." - ] - }, - { - "cell_type": "markdown", - "id": "14", - "metadata": { - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, - "source": [ - "### Setting initializations\n", - "\n", - "In some cases, the model may exhibit an unrealistically large transient at the start of the simulation. This can occur if the initial compartment sizes calculated by Atomica are very different to the equilibrium compartment sizes associated with the model's parameters. Two common reasons for this are:\n", - "\n", - "- The initial conditions are underdetermined, for example, if there are two strains of a disease with different levels of infectiousness, but data is only available on the total prevalence. In the absence of any other information, Atomica will automatically split up the total prevalence equally between the two strains, when in fact maybe one or the other strain may be dominant, which would change the overall transmission\n", - "- The model parameters may not give rise to an equilibrium solution that matches the data, if data sources have been mixed, combined across different years, collected in different ways or different definitions, or because the simplified dynamics in the model don't capture all of the processes in the real world. \n", - "\n", - "Regardless of the cause, there can often be an initial transience period at the beginning of the simulation, where we can observe abrupt spikes in some parameters until the system reaches equilibrium. \n", - "\n", - "\"Pre-initialization\n", - "\n", - "In some models, this can be treated as a 'burn-in' period and the initial part of the simulation can simply be discarded. However, there is a risk that being too far from the correct initialization results in contamination of the estimates of parameters during the calibration period. For example, if the model is initialized with the incorrect prevalence, the calibration applied to the force of infection in order to match the observed incidence would be impacted, which might subsequently affect the model's sensitivity to interventions that change the prevalence later on. Therefore, we wish to minimize the effect of the transient on the calibration. \n", - "\n", - "We can sometimes achieve this by setting the calibration start year `cal_start` to be a few years after the simulation start year `sim_start`, so that the simulation has a few years to reach equilibrium before the calibration process itself begins. However, this extends the duration of the simulation, or might limit the amount of data used for the calibration.\n", - "\n", - "An alternative approach is to override the initialization for our calibration. initializations work by running a normal Atomica simulation for a few years (past the initial transient), taking the compartment sizes of that future year, and setting the initial compartment sizes to those stabilized values. In cases where the model parameters are mostly constant, these future compartment sizes will be roughly equivalent to what the initial compartment sizes should be, which will avoid the initial transient in the model.\n", - "\n", - "\n", - "\"Post-initialization\n", - "\n", - "If the model parameters are not roughly constant, the equilibrium that the model converges to in the future might not correspond to the equilibrium solution for the model's initial parameter values. In that case, an initial transient will still occur. To address this, we can remove any time variation in the model's parameter values using the `ParameterSet.make_constant()` method. This will return a copy of the parset in which all parameters are constant over time, thus ensuring that the future compartment sizes are computed based on the same parameter values as the initial simulation year. This often provides a suitable solution, although changes to the total population size due to births and deaths can still take place, so in some cases an initial transient may still be present. In such cases, repeatedly setting initialization based on a shorter simulation can help minimize the discrepancy. For more information on Atomica initializations, see the [documentation](https://atomica.tools/docs/master/general/YAML_calibration.html \"Documentation\").\n", - "\n", - "In the YAML file, we indicate that we want to set a new initialization by making a YAML block with the title `set_initialization`. Under this title, we can specify further settings:\n", - "\n", - "- `init_year` (required): The year to use to take the compartment sizes from. The simulation will be run up to this year\n", - "- `constant_parset` (default: False): Whether to use a constant parset for the initialization, and which year to use in `parset.make_constant()`. It can be a Boolean (True/False) or numerical value (representing the year from which to draw the constant values for the parset, defaults to the same year as `sim_start`).\n", - "\n", - "There are thus several valid ways to set an initialization. For example, only setting the initialization year:\n", - "\n", - "```\n", - "calibration:\n", - " set_initialization:\n", - " init_year: 2030\n", - "```\n", - "\n", - "Setting the initialization year with a constant parset, using the parameter values from the `sim_start` year:\n", - "\n", - "```\n", - "calibration:\n", - " set_initialization:\n", - " init_year: 2030\n", - " constant_parset: True\n", - "```\n", - "\n", - "Setting the initialization year with a constant parset, using the parameter values from a specific year:\n", - "\n", - "\n", - "```\n", - "calibration:\n", - " set_initialization:\n", - " init_year: 2030\n", - " constant_parset: 2005\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "id": "15", - "metadata": {}, - "source": [ - "### Clearing initializations\n", - "\n", - "If we have previously set an initialization in our calibration algorithm, and then set another initialization later in the YAML file, it uses information from the previous initialization to calculate the next, since the new simulation will start from the initial compartment sizes calculated in the previous initialization.\n", - "\n", - "Sometimes we might want to calculate a new initialization from scratch, without using the previous initialization as a starting point. This could be useful if we have done some calibration steps between the previous initialization and now, in which case the y-factors will have changed, and we might be better off using a different starting point.\n", - "\n", - "To do this in the YAML file, we can add a section titled `clear_initialization`, followed by a boolean value. If it is set to `True`, any existing initialization will be cleared; if `False`, nothing will happen. For example:\n", - "\n", - " calibration:\n", - " set_initialization 1:\n", - " \t\tinit_year: 2030\n", - "\n", - " Match population sizes:\n", - " adjustables: b_rate, mig_rate\n", - " \tmeasurables: alive\n", - " \n", - " \tclear_initialization: True\n", - " \n", - " set_initialization 2:\n", - " \t\tinit_year: 2030" - ] - }, - { - "cell_type": "markdown", - "id": "16", - "metadata": {}, - "source": [ - "### Saving calibrations\n", - "\n", - "Throughout a YAML calibration, we might wish to save the calibration state at specific points in the calibration process. For example, if our YAML file has a population section and an epidemiological section, we might want to save the calibration after the population calibration section so we can see the progress made up until that point, or otherwise isolate the effect that different parts of the algorithm are having on the calibration. To save a calibration, we simply make a section titled `save_calibration`. Under the title, we can indicate the filename we wish to save the calibration to, either by providing it directly, or by using the keyword `fname` - both examples are shown below:\n", - "\n", - " calibration:\n", - " \tPopulation section: \n", - " \t\t[…]\n", - " \n", - " \tsave_calibration: \n", - " \t\tfname: pop_calibration.xlsx\n", - " \n", - " \tEpidemiology section: \n", - " \t\t[…]\n", - "\n", - " \tsave_calibration: epi_calibration.xlsx\n", - " \n", - "Note that when we save a calibration, if initial compartment sizes have been explicitly specified by using `set_initialization`, these compartment sizes will be saved along with the y-factors in the same Excel file. Loading the calibration from this file will thus include the initial compartment sizes.\n", - "\n", - "Another option that can be useful for debugging is to save the calibration state at every intermediate step of the YAML file. In that case, you can use the `save_intermediate_calibrations` option when running the calibration e.g.\n", - "\n", - " calibrated_parset = P.calibrate(parset = cal, yaml='T7_YAML_1_minimal.yaml', save_intermediate=True)" - ] - }, - { - "cell_type": "markdown", - "id": "17", - "metadata": {}, - "source": [ - "## Specifying settings in outer sections\n", - "\n", - "We saw previously that sections (i.e. YAML blocks that don't correspond to actions) don't directly modify the calibration, and are mainly used to structure the YAML file. However, it is possible to determine calibration settings inside a section, such that they are passed down to any subsections or action blocks contained within. Another way to think of this is that an action block will inherit any settings that are defined in any of its parent sections.\n", - "\n", - "This can simplify the process of writing YAML files where we want to override the default settings in several action blocks, as it allows us to specify those settings once in a parent section, rather than repeatedly in every action block. Additionally, this feature is hierarchical, so settings that are specified further in (e.g. in the action block itself) will always override those set in a section that is further out, allowing for more flexibility.\n", - "\n", - "Some settings that this feature is commonly used for include: \n", - "\n", - "- `max_time`: Maximum amount of time each call to the optimisation algorithm will run for \n", - "- `stepsize`: Initial step size, i.e. how much the y-factors will be increased/decreased by in the optimisation algorithm.\n", - "\n", - "Additionally, any adjustable or measurable setting can also be set outside of its calibration block, although some settings lend themselves more to this feature than others. For example, changing the measurable `weight` for an entire calibration block has no effect, as what matters is the proportion between the weights of different measurables in the same block. The following settings can be useful to set in parent sections:\n", - "\n", - "- `cal_start` and `cal_end`: These can be used to change the calibration timespan for multiple calibration steps at the same time.\n", - "- `metric`: Used for when the measurables should use a different non-standard metric for assessing calibration quality. \n", - "\n", - "We will now provide some examples of how this functionality can be used.\n", - "\n", - "### Inheritance\n", - "\n", - "Settings are automatically inherited by all sub-sections. To set a `max_time` of 120 for every calibration step in the entire calibration, we would write the following. This will result in every calibration step being limited to 120 seconds. \n", - "\n", - " calibration:\n", - " max_time: 120\n", - " Population calibration:\n", - " Match population sizes:\n", - " adjustables: b_rate, mig_rate\n", - " measurables: alive\n", - " Match deaths:\n", - " adjustables: d_rate\n", - " measurables: deaths\n", - " \n", - " Epidemiological calibration\n", - " [...]\n", - "\n", - "### Settings hierarchy\n", - "\n", - "Inherited settings can be overwritten inside sub-sections (in both sections and actions). Say we wanted all calibration blocks to run for a `max_time` of 120 seconds, except for `Match_deaths`, which we want to run for only 60 seconds. In that case, we can override the setting determined in the parent section by specifying the updated value inside `Match_deaths`:\n", - "\n", - " calibration:\n", - " max_time: 120\n", - " Population calibration:\n", - " Match population sizes:\n", - " adjustables: b_rate, mig_rate\n", - " measurables: alive\n", - " Match deaths:\n", - " max_time_ 60\n", - " adjustables: d_rate\n", - " measurables: deaths\n", - " \n", - " Epidemiological calibration\n", - " [...]\n", - "\n", - "### Adjustables/measurables settings\n", - "\n", - "Finally, here is an example of how to use the adjustables and measurables settings outside of a calibration block:\n", - "\n", - " calibration:\n", - " Population calibration:\n", - " upper_bound: 2\n", - " lower_bound: .5\n", - "\n", - " Match population sizes:\n", - " adjustables: b_rate, mig_rate\n", - " measurables alive\n", - "\n", - " Match deaths:\n", - " adjustables: d_rate\n", - " measurab\n", - "\n", - " Epidemiological calibration:\n", - " [...]\n", - "\n", - "In this case, the upper and lower bounds have been updated to 2 and 0.5 respectively, for all the adjustables in the `Population calibration` section (`b_rate`, `mig_rate` and `d_rate`)." - ] - }, - { - "cell_type": "markdown", - "id": "18", - "metadata": {}, - "source": [ - "## Running the YAML calibration\n", - "\n", - "Now that we have finished writing our YAML calibration file, we can proceed to running the calibration. Having loaded a project, `P.calibrate` can then be called directly, passing in the name of the YAML file:\n", - "\n", - " calibrated_parset = P.calibrate(parset = cal, yaml='T7_YAML_1_minimal.yaml')\n", - "\n", - "This function supports several additional optional arguments:\n", - "\n", - "- `savedir` (default: current working directory) - any saved calibrations and logs will be saved into this folder\n", - "- `save_intermediate` (default: `False`) - if `True`, this will save all intermediate calibrations\n", - "- `max_time` (optional) - override the default\n", - "- `log_output` (default: `False`) - if `True`, this will save a text file into the output directory containing all console output (e.g., objective function values)\n", - "\n", - "The YAML file can also be supplied as a dictionary, which would normally be obtained via\n", - "\n", - " import yaml\n", - " calibration_yaml = yaml.load(file, Loader=yaml.FullLoader)\n", - " \n", - "The `calibration_yaml` variable above can be passed to `P.calibrate(..., yaml=calibration_yaml)`. This enables changes to be made to the YAML content programmatically prior to running the calibration." - ] - }, - { - "cell_type": "markdown", - "id": "19", - "metadata": {}, - "source": [ - "## Exercise: worked example\n", - "\n", - "Now that we understand what all the working parts of a YAML file are, let's put it all together. For each question, write a YAML file to calibrate the model as described. Each question will consist of incremental additions to the previous solution.\n", - "\n", - "_**Question 1.** We want to do a basic population calibration, where we calibrate the death rate and migration rate to match the data corresponding to the total number of people alive. We also want to calibrate the death rate. What should this YAML file look like?_\n", - "\n", - "**Hint**: Open the framework and look at the `Compartments`, `Parameters` and `Characteristics` pages. The `Code Names` and `Display Names` show us how we have to write the parameter names in the YAML file, and what quantities they correspond to. Those with a value in the `Databook Page` column have data values supplied, and can therefore be used as measurables.\n", - "\n", - "**Hint 2**: Some of the parameter `Code Names` and `Display Names` in the databook are as follows: \n", - "\n", - "| Framework Sheet | Code Name | Display Name | Databook Page |\n", - "|:----------------|:--------------:|:------------------------------:|--------------:|\n", - "| COMPARTMENTS | |\n", - "| | birth\t\t | Birth \t\t\t\t\t\t | none |\n", - "| | death \t | Death \t\t\t\t\t\t | none |\n", - "| PARAMETERS | |\n", - "| | b_rate\t\t | Birth rate \t\t\t\t | demographic |\n", - "| | deaths\t\t | All-cause deaths \t\t\t | demographic |\n", - "| | d_rate\t\t | Background mortality rate \t | demographic |\n", - "| | mig_rate\t | Migration Rate \t\t\t\t | demographic |\n", - "| CHARACTERISTICS | |\n", - "| | alive\t | \tTotal population\t\t | demographic |" - ] - }, - { - "cell_type": "markdown", - "id": "20", - "metadata": {}, - "source": [ - "_**Question 2.** A single calibration run may not be enough to get good results, so let's loop over our simple population calibration ten times. How would we make that change to the YAML file?_\n", - "\n", - "**Hint**: Use the `repeats` keyword.\n", - "\n", - "_**Question 3.** Say that, for this particular project, we are only interested in calibrating results from 2005 to 2040. How would we specify this in the YAML file to reduce calibration time?_\n", - "\n", - "**Hint**: Using the `cal_start` and `cal_end` keywords\n", - "\n", - "_**Question 4.** When calibrating the birth rate, it only really makes sense to calibrate the 0-4 population. Modify the YAML file to reflect this._\n", - "\n", - "**Hint**: We place the parameter code name and population name in a tuple.\n", - "\n", - "_**Question 5.** Say we know that our data source underestimates the birth rate. Let’s set its starting y_factor to 1.2 to speed up the optimisation._\n", - "\n", - "**Hint**: Use `starting_y_factor`.\n", - "\n", - "_**Question 6.** We want to avoid the presence of transients in our calibrated simulation. Let’s initialize the calibration in order to eliminate any jumps._\n", - "\n", - "**Hint**: Use `set_initialization` after the calibration blocks, and make sure the initialization gets re-calculated in every loop! \n", - "\n", - "_**Question 7.** We also want to clear the previous initialization every time we make a new one, instead of using information from the previous initialization. How can we update the YAML file to reflect this?_\n", - "\n", - "**Hint**: Use `clear_initialization`, and make sure the initialization gets cleared and re-calculated in every loop!\n", - "\n", - "_**Question 8.** We are almost ready to run the YAML calibration! Now, what instructions do we need to add to automatically save our population calibration once it is done?_\n", - "\n", - "**Hint**: Use `save_calibration` and specify a `fname`.\n", - "\n", - "All solutions to the worked example are in the `docs/tutorial/T7/calibrations` folder of the Atomica repository. The calibration obtained after running the last YAML file in this exercise yields the following simulation result:\n", - "\n", - "\"Worked" - ] - }, - { - "cell_type": "markdown", - "id": "21", - "metadata": {}, - "source": [ - "## Further resources\n", - "\n", - "### Epidemiological calibration\n", - "\n", - "In this tutorial we have demonstrated the key functionality of Atomica's YAML calibration system applied to a population calibration, focussing on adjusting births and deaths to match population size data, without considering disease burden. This same functionality applies to epidemiological calibration, just with different model parameters and data. A complete YAML file of the population and epidemiological calibration instructions (`typ_calibration_instructions.yaml`) can be found in the Atomica code repository, at `docs/tutorial/T7/calibrations`.\n", - "\n", - "In this YAML file, we have set the `max_time` to 120, to give the calibration a bit more time to reach an optimal solution in each calibration step. \n", - "\n", - "At the beginning of the calibration, we also set the parameters relating to the typhoid disease (`typ_active_inf` and `typ_car`) to zero for the first pass of the population calibration. This essentially \"turns off\" of the typhoid disease until it gets reactivated in the `reset epi y-factors` step, giving the population an opportunity to be reasonably calibrated without interference from the disease components. This can be useful to do since, before calibrating the disease, the magnitude of the disease parameters could be large enough to significantly impact the population calibration results.\n", - "\n", - "We then calibrate the population following the same principles as illustrated previously, repeating the population calibration ten times, and setting a new initialization at the end of each loop, with `constant_parset=True` and the `init_year` set to 2030.\n", - "\n", - "In the epidemiological calibration section, the typhoid incidence, prevalence, and typhoid deaths are calibrated. Since we don't have a lot of information on the order of magnitude of the susceptibility and infectiousness, the lower and upper bounds are expanded to leave more room for variation. However, we don't want the disease duration `typ_gen_dur` to vary a lot, since we have a pretty clear idea of its magnitude and don't want it to vary too much between calibrations and settings, so we set stricter bounds. \n", - "\n", - "At the end of the typhoid calibration, we set an initialization in the same way we did for the population calibration. We then repeat the epidemiological calibration ten times, and finally, repeat the whole YAML calibration process (except silencing the epi y-factors) twice.\n", - "\n", - "The resulting calibration from running this YAML file is like so:\n", - "\n", - "\"Complete\n", - "\n", - "### Documentation\n", - "\n", - "For more information on using Atomica's YAML calibration functionality, see [the documentation](https://atomica.tools/docs/master/general/YAML_calibration.html \"YAML documentation page\").\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.13" - }, - "toc": { - "base_numbering": 1, - "nav_menu": {}, - "number_sections": true, - "sideBar": true, - "skip_h1_title": false, - "title_cell": "Table of Contents", - "title_sidebar": "Contents", - "toc_cell": false, - "toc_position": {}, - "toc_section_display": true, - "toc_window_display": true - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} +{ + "cells": [ + { + "cell_type": "markdown", + "id": "0", + "metadata": {}, + "source": [ + "# T7 - YAML calibration\n", + "\n", + "As we saw in the earlier calibration tutorial, most autocalibrations involve multiple steps, since the optimization algorithm often gets stuck in local minima if we try to optimize too many parameters at once. We could run each of these steps ourselves through separate calls to `P.calibrate()` – however, there is significant value in being able to explicitly frame the overall calibration process as an algorithm, as this makes it easier to modify the calibration steps and apply the calibration algorithm across a collection of projects. This is implemented in Atomica through the 'YAML calibration' feature, in which the calibration steps are specified in a file which Atomica can then read and use to execute the calibration.\n", + "\n", + "## YAML files\n", + "\n", + "The calibration algorithm files used by Atomica are written in YAML. YAML is a plain-text, human-readable data serialization language used to make configuration files. Essentially, a YAML file can be read into Python variables (dictionaries, lists, strings) which in turn can be used as arguments to Python functions. Here is an example of how variables can be specified in a YAML file:\n", + "\n", + "```\n", + " foo: a string\n", + " bar: 1\n", + " baz: [a,b,c]\n", + " list:\n", + " - i\n", + " - j\n", + " nested:\n", + " x: 1\n", + " y: 2\n", + " ```\n", + "\n", + "When parsed into Python, this becomes\n", + "\n", + "```\n", + "{'foo': 'a string',\n", + " 'bar': 1,\n", + " 'baz': ['a', 'b', 'c'],\n", + " 'list': ['i', 'j'],\n", + " 'nested': {'x': 1, 'y': 2}}\n", + "```\n", + "\n", + "Using YAML files provides a simple way to define a calibration algorithm in a format that is easy to work with and that Atomica can directly execute. This can cut down the time we spend manually calibrating, or even running autocalibrations. It allows us to conduct reproducible calibration runs, and is also highly scalable, since it allows us to apply the same calibration algorithm in multiple countries or settings.\n", + "\n", + "The following tutorial outlines how to use the YAML framework that has been developed for Atomica calibration. Specifically, it will cover how to write a YAML configuration file with calibration instructions for Atomica, and how to use this file to execute a calibration. Bear in mind that YAML calibration is not intended to be a standalone tool that will perfectly calibrate any model – rather, it is one part of the calibration toolbox. It can be used to reduce the time spent on calibration by autocalibrating Atomica models to a reasonable level, but additional tweaking may be required to obtain a consistently high calibration quality across all parameters, populations and/or countries." + ] + }, + { + "cell_type": "markdown", + "id": "1", + "metadata": {}, + "source": [ + "## Basic calibration example\n", + "\n", + "In this tutorial, we will work with a simple version of a typhoid model. This model captures typhoid infections, as well as asymptomatic carriers and vaccination. Firstly, we need to create an Atomica `Project` by loading in the Framework and Databook files, just like we did in [the first Atomica tutorial](https://atomica.tools/docs/master/tutorial/T1-Defining-a-model.html). The Framework and Databook for this project can be found in the Atomica repository under `T7/assets`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2", + "metadata": {}, + "outputs": [], + "source": [ + "import atomica as at\n", + "F = at.ProjectFramework('assets/T7_framework.xlsx')\n", + "D = at.ProjectData.from_spreadsheet('assets/T7_databook.xlsx', framework=F)\n", + "P = at.Project(framework=F,databook=D, do_run=False)\n", + "P.settings.update_time_vector(start=2000, end=2040, dt=1/52)" + ] + }, + { + "cell_type": "markdown", + "id": "3", + "metadata": {}, + "source": [ + "In the example above, no calibration has been loaded, so all of the calibration Y-factors are equal to 1, and the model is uncalibrated. We can run a simulation and plot it, to see what our model looks like before calibration:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4", + "metadata": {}, + "outputs": [], + "source": [ + "cal = P.make_parset()\n", + "res = P.run_sim(parset=cal, result_name = 'Uncalibrated')\n", + "d = at.PlotData(res, outputs=['alive','deaths', 'typ_prev', 'typ_num_deaths'], project=P)\n", + "fig = at.plot_series(d,axis='pops', data=P.data, n_cols=2, legend_mode='none')[0]\n", + "fig.set_size_inches(10,7)\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "markdown", + "id": "5", + "metadata": {}, + "source": [ + "Two issues with these simulation outputs immediately stand out. First, for the variables and years in which data is available, the model output doesn't match the data very well at all. Second, there is a large sudden change in the values of several variables right at the start of the simulation. In the absence of associated changes in interventions or disease transmission, disease burden is typically much more stable over time, so we would not expect to see such sudden changes at the start of the simulation.\n", + "\n", + "Tutorial 2 covers some of the detail around how to approach calibration. Although the parameters used for calibration vary from model to model, as a general rule, calibration proceeds by\n", + "\n", + "1. Demographic calibration: Adjusting birth and background death rates to match quantities like the total population size.\n", + "2. Epidemiological calibration: Adjusting parameters such as force of infection, diagnosis rate and mortality rate, to match quantities like incidence, prevalence and deaths.\n", + "\n", + "Each of these steps involves calibrating multiple parameters, which may be adjusted sequentially and repeatedly. They may also be interspersed with adjusting the model's initialization, to help minimize sudden transients at the start of the simulation. The purpose of the YAML file is to specify the sequence of steps to follow in carrying out a calibration run, in terms of which parameters to adjust, the order in which to adjust them (or whether some should be adjusted simultaneously), and how to assess the quality of the calibration at each step of the process. In this tutorial, we will use YAML files to specify a sequence of steps to calibrate the simple typhoid model shown above, starting with a minimal example and then introducing key features provided by Atomica's YAML calibration system." + ] + }, + { + "cell_type": "markdown", + "id": "6", + "metadata": { + "jp-MarkdownHeadingCollapsed": true + }, + "source": [ + "## Minimal YAML file\n", + "\n", + "To illustrate how YAML calibration works, let’s start with a simple example of what a YAML file could look like:\n", + "\n", + " calibration:\n", + " \tadjustables: b_rate, mig_rate\n", + " \tmeasurables: alive\n", + "\n", + "The above YAML file represents a single call to the autocalibration optimisation function, where the `b_rate` and `mig_rate` y-factors are adjusted to match `alive`. It is equivalent to running a calibration with the following command:\n", + "\n", + " calibrated_parset = P.calibrate(parset = cal, adjustables = ['b_rate', 'mig_rate'], measurables = 'alive')\n", + "\n", + "Running the YAML calibration is very similar to performing a standalone auto-calibration. After saving the YAML file to disk (e.g., `T7_YAML_1_minimal.yaml`), the calibration can be run using\n", + "\n", + " calibrated_parset = P.calibrate(parset = cal, yaml='T7_YAML_1_minimal.yaml')\n", + "\n", + "As the YAML calibration framework allows us to specify the adjustables and measurables, it is not necessary to provide them to `Project.calibrate()` – simply providing the YAML file is sufficient. However, the YAML file can contain multiple calibration commands, and therefore a single call to `Project.calibrate()` with a YAML file might be equivalent to multiple explicit calibration steps. The resulting simulation after running this simple calibration is like so: \n", + "\n", + "\"Simple\n", + "\"Simple\n", + "\n", + "As you can see, these plots don't look very different to the uncalibrated simulation results. If we plot the uncalibrated simulation in the same plot as our simple calibration, we can see that there has been a slight change, but not nearly enough to be able to consider this a good calibration. Next, we will illustrate the YAML calibration features that we can use to improve on this initial result. " + ] + }, + { + "cell_type": "markdown", + "id": "7", + "metadata": {}, + "source": [ + "## Sections\n", + "\n", + "At the most basic level, a YAML calibration file defines a sequence of individual steps, where each step incrementally modifies the calibration. The YAML file therefore defines an overall _algorithm_ for performing an automatic calibration. This algorithm is defined using two structures in the YAML file:\n", + "\n", + "- _actions_, which are associated with particular operations, like running a gradient-descent calibration step with a particular set of parameters and data. A calibration action contains `adjustables` and `measurables`. Other examples of actions are detailed below.\n", + "- _sections_, which are containers for actions. Sections can contain attributes, such as how many times to repeat the contents of the section, or they can define settings that are applied to any relevant actions within that section.\n", + "\n", + "The original YAML file above consisted of a single calibration action. If we wanted to extend the algorithm by adding a step to calibrate the death rate, we could update our YAML file to the following: \n", + "\n", + "\n", + "```\n", + "calibration:\n", + " Match population sizes:\n", + " adjustables: b_rate, mig_rate\n", + " measurables: alive\n", + " Match deaths:\n", + " adjustables: d_rate\n", + " measurables: deaths\n", + "```\n", + "\n", + "To organize the YAML file further, we could group these into an additional section. Both of these actions affect the overall population calibration, so we could logically group them as follows:\n", + "\n", + "```\n", + "calibration: \n", + " Population calibration:\n", + " Match population sizes:\n", + " adjustables: b_rate, mig_rate\n", + " measurables: alive\n", + " Match deaths:\n", + " adjustables: d_rate\n", + " measurables: deaths\n", + "```\n", + "\n", + "The overall structure of this YAML file is thus:\n", + "\n", + "1. A top-level section titled `calibration`, which has one sub-section (`Population calibration`)\n", + "2. A sub-section called `Population calibration`, which in turn contains two actions\n", + "3. An action called `Match population sizes`, corresponding to the original calibration step we used to adjust the birth rate and migration rate\n", + "4. An action called `Match deaths`, corresponding to the new step of adjusting the death rate\n", + "\n", + "An action is differentiated from a section in two possible ways:\n", + "\n", + "- By its contents (e.g. if it contains `adjustables` and `measurables`, then it will be interpreted as a calibration action rather than a section)\n", + "- By the title (if the name corresponds to the name of a supported operation, as described below)\n", + "\n", + "Additionally, actions can never contain any sub-sections, whereas sections do. \n", + "Apart from the names of supported operations, sections can be freely named." + ] + }, + { + "cell_type": "markdown", + "id": "8", + "metadata": {}, + "source": [ + "### Repeating a section\n", + "\n", + "The *repeats* keyword can be used to loop over any part of the calibration multiple times. We do this by writing `repeats: n` inside a particular section, where *n* is the number of times we would like to loop over that section. All subsections contained in it will also be looped over *n* times. \n", + "\n", + " calibration: \n", + " repeats: 2\n", + " Population calibration:\n", + " Match population sizes:\n", + " repeats: 2\n", + " adjustables: b_rate, mig_rate\n", + " measurables: alive\n", + " Match deaths:\n", + " adjustables: d_rate\n", + " measurables: deaths\n", + "\n", + "In the above example, we have set `repeats: 2` inside the `calibration` section, so the entire YAML calibration will be repeated twice. Then, the `Match population sizes` section also has `repeats: 2`, so the calibration step defined in that section will also be repeated twice each time. In total, there will be four calls to the optimisation algorithm to match `alive`, and two to match `deaths, so the YAML file above would be equivalent to \n", + "\n", + " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", + " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", + " parset = P.calibrate(parset = parset, adjustables = [d_rate], measurables=deaths)\n", + " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", + " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", + " parset = P.calibrate(parset = parset, adjustables = [d_rate], measurables=deaths)\n", + "\n", + "In this way, it is possible for even a very compact YAML file to correspond to a large number of individual autocalibration steps. " + ] + }, + { + "cell_type": "markdown", + "id": "9", + "metadata": {}, + "source": [ + "## Sections vs Actions\n", + "\n", + "As shown above, sections can help us to structure the calibration in a way that is practical and intuitive. They can be used to group blocks of YAML code that are conceptually related, that we want to repeat together several times, or that we want to apply similar settings to (we will cover which settings are supported in [the corresponding section](#specifying-settings-in-outer-sections). \n", + "\n", + "Importantly though, _sections_ do not modify the calibration itself – they are merely wrappers for the innermost blocks that actually correspond to specific actions. It is in these _actions_ that operations are performed on the calibration, such as modifying the calibration or saving it.\n", + "\n", + "
    \n", + "We can tell action blocks apart from sections because action blocks contain keywords indicating what kind of block they are, and they don't contain any sub-sections.\n", + "
    \n", + "\n", + "It is possible to load and inspect a YAML file in Atomica without executing it. This can help confirm that the YAML file has been parsed correctly. After loading in the YAML file, it can be printed to show a summary of the sections and actions that are present, how they are nested, and how many times they are repeated: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "10", + "metadata": {}, + "outputs": [], + "source": [ + "import atomica.yaml_calibration \n", + "calibration_tree = at.yaml_calibration.build('calibrations/T7_YAML_3_repeats.yaml') \n", + "print(calibration_tree)" + ] + }, + { + "cell_type": "markdown", + "id": "11", + "metadata": {}, + "source": [ + "## Types of Action Blocks\n", + "\n", + "YAML calibration files can contain the following types of actions, or action blocks: \n", + "\n", + "- Calibration block\n", + "- Initialization block\n", + "- Intialization clearing block\n", + "- Saving block" + ] + }, + { + "cell_type": "markdown", + "id": "12", + "metadata": {}, + "source": [ + "### Calibration blocks\n", + "\n", + "In all of the YAML examples shown above, we have worked with 'calibration blocks', which are the main type of action. Calibration blocks are defined by the fact that they contain the keywords `adjustables` and `measurables`. Under `adjustables`, we list the parameters for Atomica’s optimisation algorithm to adjust, and under `measurables`, we list the parameters to calibrate to. Each calibration block provides instructions for one optimisation run, and is equivalent to making one call to `P.calibrate()` with the same adjustables and measurables.\n", + "\n", + "#### Adjustable and measurable settings\n", + "\n", + "So far, we have only specified the names of the adjustables and measurables, with no further information – in that case, the optimisation algorithm will use the default calibration settings for adjustables and measurables. For more flexibility, we can customise the settings that will be used for the optimisation, which directly map to the options supported by `P.calibrate()`.\n", + "\n", + "Each adjustable has:\n", + "\n", + "- `adj_label` (required): Adjustable parameter codename (can be found in the framework)\n", + "- `pop_name`: Population to calibrate (default: all populations)\n", + "- `lower_bound`: Lowest value the y-factor will be allowed to take (default: 0.1)\n", + "- `upper_bound`: Highest value the y-factor will be allowed to take (default: 10)\n", + "- `starting_y_factor`: Y-factor value the optimisation algorithm will start from (default: the adjustable's current `y_factor` in the parset)\n", + "\n", + "Each measurable has:\n", + "\n", + "- `meas_label` (required): Measurable parameter codename (can be found in the framework)\n", + "- `pop_name`: Population to use for calibration (default: all populations)\n", + "- `weight`: Weight for a particular population (default: 1). By default, all populations are weighted equally regardless of size. See [the documentation on weights](https://atomica.tools/docs/master/general/YAML_calibration.html#Measurable-Weights \"Measurable weights\") for further details.\n", + "- `metric`: Metric to be used by the optimisation algorithm (default: fractional)\n", + "- `cal_start`: Starting year that the calibration will be evaluated from (default: `sim_start`)\n", + "- `cal_end`: End year until which the calibration will be evaluated (default: `sim_end`)\n", + "\n", + "Note that `sim_start` and `sim_end` are the start and end years that the simulation will run for (the simulation timespan). These are distinct from `cal_start` and `cal_end`, which specify the time period for which we want to calibrate the model, i.e. a subset of the simulation timespan. For more information, see the [section on outer settings](#specifying-settings-in-outer-sections \"Specifying settings in outer sections\"). The `cal_start` and `cal_end` years can be set independently for each measurable, so it is possible to prioritize different years for different variables or for different steps of the calibration.\n", + "To specify these adjustables and measurables settings in the YAML file, we simply write the setting names and their values under the relevant parameter name. Each adjustable and measurable is placed on a new line, and their respective settings are also specified on separate indented lines, like so:\n", + "\n", + " calibration:\n", + " Match population sizes:\n", + " adjustables: \n", + " \tb_rate: \n", + " \t\tlower_bound: 0.5\n", + " \t\tupper_bound: 20\t\t\n", + " \tmig_rate: \n", + " \t\tstarting_y_factor: 1.2 \n", + " measurables: \n", + " alive:\n", + " \tcal_start: 2000\n", + " \tcal_end: 2040\n", + " " + ] + }, + { + "cell_type": "markdown", + "id": "13", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "#### Specifying Populations\n", + "\n", + "In some cases, we may only want to set adjustables or measurables for a specific population, or we may wish to use different settings for one population compared to another. A population can optionally be specified after the parameter name, as the second element of a tuple. Thus, if we only wish to calibrate some populations, we can rewrite our previous YAML file like so:\n", + "\n", + " calibration: \n", + " Match population sizes:\n", + " adjustables: \n", + " \t(b_rate, 0-4): \n", + " \t\tlower_bound: 0.5\n", + " \t\tupper_bound: 20\t\t\n", + " \t(mig_rate, 5-14): \n", + " \t\tstarting_y_factor: 1.2 \n", + " measurables: \n", + " (alive, 0-4), (alive, 5-14):\n", + " \tcal_start: 2000\n", + " \tcal_end: 2040\n", + " \n", + "Note that we can specify the same settings for more than one adjustable/measurable at once by placing several parameter names before the colon, separated by commas – this is applicable to any set of adjustables/measurables, not only different populations of the same parameter. For example, we could write: \n", + "\n", + " calibration: \n", + " Match population sizes:\n", + " adjustables: \n", + " \t(b_rate, 0-4), mig_rate: \n", + " \t\tlower_bound: 0.5\n", + " \t\tupper_bound: 20\n", + " starting_y_factor: 1.2\t\t \n", + " measurables: \n", + " (alive, 0-4), (alive, 5-14):\n", + " \tcal_start: 2000\n", + " \tcal_end: 2040\n", + "\n", + "Finally, the same syntax we use to calibrate populations can be used to calibrate transfers and interactions, but in such cases the tuple should have three elements - the parameter name, the _from_ population and the _to_ population. For more information on how to calibrate in these cases, see the documentation on [Calibrating transfers and interactions](https://atomica.tools/docs/master/general/YAML_calibration.html#Calibrating-transfers-and-interactions \"Calibrating transfers and interactions\")." + ] + }, + { + "cell_type": "markdown", + "id": "14", + "metadata": { + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "### Setting initializations\n", + "\n", + "In some cases, the model may exhibit an unrealistically large transient at the start of the simulation. This can occur if the initial compartment sizes calculated by Atomica are very different to the equilibrium compartment sizes associated with the model's parameters. Two common reasons for this are:\n", + "\n", + "- The initial conditions are underdetermined, for example, if there are two strains of a disease with different levels of infectiousness, but data is only available on the total prevalence. In the absence of any other information, Atomica will automatically split up the total prevalence equally between the two strains, when in fact maybe one or the other strain may be dominant, which would change the overall transmission.\n", + "- The model parameters may not give rise to an equilibrium solution that matches the data. This could be due to data sources being mixed, combined across different years, collected in different ways or with different definitions, or because the simplified dynamics in the model simply don't capture all the processes in the real world.\n", + "\n", + "Regardless of the cause, there can often be an initial transience period at the beginning of the simulation, where we can observe abrupt spikes in some parameters until the system reaches equilibrium. \n", + "\n", + "\"Pre-initialization\n", + "\n", + "In some models, this can be treated as a 'burn-in' period, and the initial part of the simulation is simply discarded. However, there is a risk that being too far from the correct initialization can contaminate the parameter estimates during the calibration period. For example, if the model is initialized with the incorrect prevalence, the calibration applied to the force of infection in order to match the observed incidence would be impacted, which might subsequently affect the model's sensitivity to interventions that change the prevalence later on. Therefore, we wish to minimize the effect of transients on the calibration.\n", + "\n", + "We can sometimes achieve this by setting the calibration start year `cal_start` to be a few years after the simulation start year `sim_start`, so that the simulation has a few years to reach equilibrium before the calibration process itself begins. However, this extends the duration of the simulation, and it might limit the amount of data that can be used for calibration.\n", + "\n", + "An alternative approach is to override the initial values of our simulation and replace them with new initialization values. Setting an initialization works by running a normal Atomica simulation for a few years (past the initial transient), taking the compartment sizes of that future year, and setting the initial compartment sizes to those stabilized values. In cases where the model parameters are approximately constant, these future compartment sizes will be roughly equivalent to what the initial compartment sizes should be, which will prevent the appearance of an initial transient in the model.\n", + "\n", + "\"Post-initialization\n", + "\n", + "If the model parameters are not roughly constant, the equilibrium that the model converges to in the future might not correspond to the equilibrium solution for the model's initial parameter values. In that case, an initial transient can still occur. To address this, we can remove any time variation in the model's parameter values using the `ParameterSet.make_constant()` method. This will return a copy of the parset in which all parameters are constant over time, thus ensuring that the future compartment sizes are computed based on the same parameter values as the initial simulation year. This often provides a suitable solution, although changes to the total population size due to births and deaths can still take place, so in some cases a small initial transient may still be present. In such cases, repeatedly setting initialization based on a shorter simulation can help minimize the discrepancy. For more information on Atomica initializations, see the [documentation on this topic](https://atomica.tools/docs/master/general/Compartment-Initialization.html \"Initializing compartments\").\n", + "\n", + "In the YAML file, we indicate that we want to set a new initialization by making a YAML block with the title `set_initialization`. Under this title, we can specify further settings:\n", + "\n", + "- `init_year` (required): The future year to take the compartment sizes from. The simulation will be run up to this year.\n", + "- `constant_parset` (default: False): Whether to make the parameters constant while the initialization is being calculated, and which year to extract these constant parameter values from, i.e. which year to use in `parset.make_constant()`. It can be a numerical value (representing the year from which to draw the constant values for the parset) or Boolean (if `True`, the default year `sim_start` will be used).\n", + "\n", + "There are thus several valid ways to set an initialization. For example, only setting the initialization year:\n", + "\n", + "```\n", + "calibration:\n", + " set_initialization:\n", + " init_year: 2030\n", + "```\n", + "\n", + "Setting the initialization year with a constant parset, using the parameter values from the default `sim_start` year:\n", + "\n", + "```\n", + "calibration:\n", + " set_initialization:\n", + " init_year: 2030\n", + " constant_parset: True\n", + "```\n", + "\n", + "Setting the initialization year with a constant parset, using constant parameter values from a specific year:\n", + "\n", + "\n", + "```\n", + "calibration:\n", + " set_initialization:\n", + " init_year: 2030\n", + " constant_parset: 2005\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "id": "15", + "metadata": {}, + "source": [ + "### Clearing initializations\n", + "\n", + "If we have previously set an initialization in our YAML calibration algorithm, and we then set another initialization later in the YAML file, it uses information from the previous initialization to calculate the next, since the new simulation will start from the initial compartment sizes calculated in that previous initialization.\n", + "\n", + "Sometimes we might wish to calculate a new initialization from scratch, without using our previous initializations as a starting point. This could be useful if we have done some calibration steps between the previous initialization and now, in which case the y-factors will have changed, which in turn could have caused the equilibrium values to vary.\n", + "\n", + "To do this in the YAML file, we can make a section titled `clear_initialization`, followed by a Boolean value. If it is set to `True`, any existing initialization will be cleared; if `False`, nothing will happen. The most simple example is as follows:\n", + "\n", + "```\n", + "calibration:\n", + " clear_initialization: True\n", + "```\n", + "\n", + "Below is a more practical example of how we would use the `clear_initialization` feature in a real YAML file, where we first set an initialization, perform some calibration steps, and then clear our previous initialization before making a new one.\n", + "\n", + " calibration:\n", + " First initialization:\n", + " set_initialization:\n", + " init_year: 2030\n", + "\n", + " Match population sizes:\n", + " adjustables: b_rate, mig_rate\n", + " \tmeasurables: alive\n", + " \n", + " \tclear_initialization: True\n", + "\n", + " Second initialization:\n", + " set_initialization:\n", + " init_year: 2030\n", + "\n", + "\n", + "Note that we need to wrap `set_initialization` in an outer section, since YAML does not allow duplicate keys (i.e. identical section/action titles at the same level)." + ] + }, + { + "cell_type": "markdown", + "id": "16", + "metadata": {}, + "source": [ + "### Saving calibrations\n", + "\n", + "Throughout a YAML calibration, we might wish to save the calibration state at specific points in the process. For example, if our YAML file has a population section and an epidemiological section, we might want to save the calibration after the population calibration section so we can see the progress made up to that point, or otherwise identify the effect that different parts of the algorithm are having on the calibration. To save a calibration, we simply make a section titled `save_calibration`. Under the title, we indicate the filename we wish to save the calibration to, either by providing it directly, or by using the keyword `fname` - both examples are shown below:\n", + "\n", + " calibration:\n", + " \tPopulation section: \n", + " \t\t[…]\n", + " \n", + " \tsave_calibration: \n", + " \t\tfname: pop_calibration.xlsx\n", + " \n", + " \tEpidemiology section: \n", + " \t\t[…]\n", + "\n", + " \tsave_calibration: epi_calibration.xlsx\n", + " \n", + "Note that when we save a calibration, if the initial compartment sizes have been explicitly specified using `set_initialization`, these compartment sizes will be saved along with the y-factors in the same Excel file. Loading the calibration from this file will thus also set the initial compartment sizes to those values.\n", + "\n", + "Another option that can be useful for debugging is to save the calibration state at every intermediate step of the YAML file. In that case, we can use the `save_intermediate_calibrations` option when loading in and running the calibration, e.g.\n", + "\n", + " calibrated_parset = P.calibrate(parset = cal, yaml='T7_YAML_1_minimal.yaml', save_intermediate=True)\n", + "\n", + "More options for running the calibration can be found [here](#running-the-yaml-calibration \"Running the YAML calibration\")." + ] + }, + { + "cell_type": "markdown", + "id": "17", + "metadata": {}, + "source": [ + "## Specifying settings in outer sections\n", + "\n", + "We saw previously that sections (i.e. YAML blocks that don't correspond to actions) don't directly modify the calibration, and are mainly used to structure the YAML file. However, it is possible to determine calibration settings inside a section, such that they are passed down to any subsections or action blocks contained within. Another way to think of this is that an action block will inherit any settings that are defined in any of its parent sections.\n", + "\n", + "This can simplify the process of writing YAML files where we want to override the default settings in several action blocks, as it allows us to specify those settings once in a parent section, rather than repeatedly in every action block. Additionally, this feature is hierarchical, so settings that are specified further in (e.g. in the action block itself) will always override those set in a section that is further out, allowing for more flexibility.\n", + "\n", + "Some settings that this feature is commonly used for include: \n", + "\n", + "- `max_time`: Maximum amount of time each call to the optimisation algorithm will run for (default: 60 seconds)\n", + "- `stepsize`: Initial step size, i.e. how much the y-factors will be increased/decreased by the optimisation algorithm (default: 0.1)\n", + "\n", + "Additionally, any adjustable or measurable setting can also be set outside of its calibration block, although some settings lend themselves more to this feature than others. For example, changing the measurable `weight` for an entire calibration block has no effect, as what matters is the proportion between the weights of different measurables in the same block. The following settings can be useful to set in parent sections:\n", + "\n", + "- `cal_start` and `cal_end`: These can be used to change the calibration timespan for multiple calibration steps at the same time.\n", + "- `metric`: To change the metric used to assess calibration quality, i.e. how well the simulation fits the measurables data.\n", + "\n", + "We will now provide some examples of how this functionality can be used.\n", + "\n", + "### Inheritance\n", + "\n", + "Settings are automatically inherited by all subsections. To set a `max_time` of 120 for every calibration step in the entire calibration, we would write the following. This will result in every calibration step running for at most 120 seconds, rather than the default 60 seconds.\n", + "\n", + " calibration:\n", + " max_time: 120\n", + " Population calibration:\n", + " Match population sizes:\n", + " adjustables: b_rate, mig_rate\n", + " measurables: alive\n", + " Match deaths:\n", + " adjustables: d_rate\n", + " measurables: deaths\n", + " \n", + " Epidemiological calibration\n", + " [...]\n", + "\n", + "### Settings hierarchy\n", + "\n", + "Inherited settings can be overwritten inside sub-sections (in both sections and actions). Say we wanted all calibration blocks to run for a `max_time` of 120 seconds, except for `Match_deaths`, which we want to run for only 60 seconds. In that case, we can override the setting determined in the parent section by specifying the updated value inside `Match_deaths`:\n", + "\n", + " calibration:\n", + " max_time: 120\n", + " Population calibration:\n", + " Match population sizes:\n", + " adjustables: b_rate, mig_rate\n", + " measurables: alive\n", + " Match deaths:\n", + " max_time_ 60\n", + " adjustables: d_rate\n", + " measurables: deaths\n", + " \n", + " Epidemiological calibration\n", + " [...]\n", + "\n", + "### Adjustables/measurables settings\n", + "\n", + "Finally, here is an example of how to use the adjustables and measurables settings outside a calibration block:\n", + "\n", + " calibration:\n", + " Population calibration:\n", + " upper_bound: 2\n", + " lower_bound: .5\n", + "\n", + " Match population sizes:\n", + " adjustables: b_rate, mig_rate\n", + " measurables alive\n", + "\n", + " Match deaths:\n", + " adjustables: d_rate\n", + " measurab\n", + "\n", + " Epidemiological calibration:\n", + " [...]\n", + "\n", + "In this case, the upper and lower bounds have been updated to 2 and 0.5 respectively, for all the adjustables in the `Population calibration` section (`b_rate`, `mig_rate` and `d_rate`)." + ] + }, + { + "cell_type": "markdown", + "id": "18", + "metadata": {}, + "source": [ + "## Running the YAML calibration\n", + "\n", + "Now that we have finished writing our YAML calibration file, we can proceed to running the calibration. Having loaded a project, `P.calibrate` can then be called directly, passing in the name of the YAML file:\n", + "\n", + " calibrated_parset = P.calibrate(parset = cal, yaml='T7_YAML_1_minimal.yaml')\n", + "\n", + "This function supports several additional optional arguments:\n", + "\n", + "- `savedir` (default: current working directory) - any saved calibrations and logs will be saved into this folder\n", + "- `save_intermediate` (default: `False`) - if `True`, this will save all intermediate calibrations\n", + "- `max_time` (optional) - override the default\n", + "- `log_output` (default: `False`) - if `True`, this will save a text file into the output directory containing all console output (e.g., objective function values)\n", + "\n", + "The YAML file can also be supplied as a dictionary, which would normally be obtained via\n", + "\n", + " import yaml\n", + " calibration_yaml = yaml.load(file, Loader=yaml.FullLoader)\n", + " \n", + "The `calibration_yaml` variable above can be passed to `P.calibrate(..., yaml=calibration_yaml)`. This enables changes to be made to the YAML content programmatically prior to running the calibration." + ] + }, + { + "cell_type": "markdown", + "id": "19", + "metadata": {}, + "source": [ + "## Exercise: worked example\n", + "\n", + "Now that we understand what all the working parts of a YAML file are, let's put it all together. For each question, write a YAML file to calibrate the model as described. Each question will consist of incremental additions to the previous solution.\n", + "\n", + "_**Question 1.** We want to do a basic population calibration, where we calibrate the death rate and migration rate to match the data corresponding to the total number of people alive. We also want to calibrate the death rate. What should this YAML file look like?_\n", + "\n", + "**Hint**: Open the framework and look at the `Compartments`, `Parameters` and `Characteristics` pages. The `Code Names` and `Display Names` show us how we have to write the parameter names in the YAML file, and what quantities they correspond to. Those with a value in the `Databook Page` column have data values supplied, and can therefore be used as measurables.\n", + "\n", + "**Hint 2**: Some of the parameter `Code Names` and `Display Names` in the databook are as follows: \n", + "\n", + "| Framework Sheet | Code Name | Display Name | Databook Page |\n", + "|:----------------|:--------------:|:------------------------------:|--------------:|\n", + "| COMPARTMENTS | |\n", + "| | birth\t\t | Birth \t\t\t\t\t\t | none |\n", + "| | death \t | Death \t\t\t\t\t\t | none |\n", + "| PARAMETERS | |\n", + "| | b_rate\t\t | Birth rate \t\t\t\t | demographic |\n", + "| | deaths\t\t | All-cause deaths \t\t\t | demographic |\n", + "| | d_rate\t\t | Background mortality rate \t | demographic |\n", + "| | mig_rate\t | Migration Rate \t\t\t\t | demographic |\n", + "| CHARACTERISTICS | |\n", + "| | alive\t | \tTotal population\t\t | demographic |" + ] + }, + { + "cell_type": "markdown", + "id": "20", + "metadata": {}, + "source": [ + "_**Question 2.** A single calibration run may not be enough to get good results, so let's loop over our simple population calibration ten times. How would we make that change to the YAML file?_\n", + "\n", + "**Hint**: Use the `repeats` keyword.\n", + "\n", + "_**Question 3.** Say that, for this particular project, we are only interested in calibrating results from 2005 to 2040. How would we specify this in the YAML file to reduce calibration time?_\n", + "\n", + "**Hint**: Using the `cal_start` and `cal_end` keywords\n", + "\n", + "_**Question 4.** When calibrating the birth rate, it only really makes sense to calibrate the 0-4 population. Modify the YAML file to reflect this._\n", + "\n", + "**Hint**: We place the parameter code name and population name in a tuple.\n", + "\n", + "_**Question 5.** Say we know that our data source underestimates the birth rate. Let’s set its starting y_factor to 1.2 to speed up the optimisation._\n", + "\n", + "**Hint**: Use `starting_y_factor`.\n", + "\n", + "_**Question 6.** We want to avoid the presence of transients in our calibrated simulation. Let’s initialize the calibration in order to eliminate any jumps._\n", + "\n", + "**Hint**: Use `set_initialization` after the calibration blocks, and make sure the initialization gets re-calculated in every loop! \n", + "\n", + "_**Question 7.** We also want to clear the previous initialization every time we make a new one, instead of using information from the previous initialization. How can we update the YAML file to reflect this?_\n", + "\n", + "**Hint**: Use `clear_initialization`, and make sure the initialization gets cleared and re-calculated in every loop!\n", + "\n", + "_**Question 8.** We are almost ready to run the YAML calibration! Now, what instructions do we need to add to automatically save our population calibration once it is done?_\n", + "\n", + "**Hint**: Use `save_calibration` and specify a `fname`.\n", + "\n", + "All solutions to the worked example are in the `docs/tutorial/T7/calibrations` folder of the Atomica repository. The calibration obtained after running the last YAML file in this exercise yields the following simulation result:\n", + "\n", + "\"Worked" + ] + }, + { + "cell_type": "markdown", + "id": "21", + "metadata": {}, + "source": [ + "## Further resources\n", + "\n", + "### Epidemiological calibration\n", + "\n", + "In this tutorial we have demonstrated the key functionality of Atomica's YAML calibration system applied to a population calibration, focussing on adjusting births and deaths to match population size data, without considering disease burden. This same functionality applies to epidemiological calibration, just with different model parameters and data. A complete YAML file of the population and epidemiological calibration instructions (`typ_calibration_instructions.yaml`) can be found in the Atomica code repository, at `docs/tutorial/T7/calibrations`.\n", + "\n", + "In this YAML file, we have set the `max_time` to 120, to give the calibration a bit more time to reach an optimal solution in each calibration step. \n", + "\n", + "At the beginning of the calibration, we also set the parameters relating to the typhoid disease (`typ_active_inf` and `typ_car`) to zero for the first pass of the population calibration. This essentially \"turns off\" of the typhoid disease until it gets reactivated in the `reset epi y-factors` step, giving the population an opportunity to be reasonably calibrated without interference from the disease components. This can be useful to do since, before calibrating the disease, the magnitude of the disease parameters could be large enough to significantly impact the population calibration results.\n", + "\n", + "We then calibrate the population following the same principles as illustrated previously, repeating the population calibration ten times, and setting a new initialization at the end of each loop, with `constant_parset=True` and the `init_year` set to 2030.\n", + "\n", + "In the epidemiological calibration section, the typhoid incidence, prevalence, and typhoid deaths are calibrated. Since we don't have a lot of information on the order of magnitude of the susceptibility and infectiousness, the lower and upper bounds are expanded to leave more room for variation. However, we don't want the disease duration `typ_gen_dur` to vary a lot, since we have a pretty clear idea of its magnitude and don't want it to vary too much between calibrations and settings, so we set stricter bounds. \n", + "\n", + "At the end of the typhoid calibration, we set an initialization in the same way we did for the population calibration. We then repeat the epidemiological calibration ten times, and finally, repeat the whole YAML calibration process (except silencing the epi y-factors) twice.\n", + "\n", + "The resulting calibration from running this YAML file is like so:\n", + "\n", + "\"Complete\n", + "\n", + "### Documentation\n", + "\n", + "For more information on using Atomica's YAML calibration functionality, see [the documentation](https://atomica.tools/docs/master/general/YAML_calibration.html \"YAML documentation page\").\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": true + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 966a7d39212d67f41e90ceb37853e2622bb37e3b Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Thu, 6 Mar 2025 20:09:46 +0100 Subject: [PATCH 124/161] YAML tutorial edits -Added description of plots and how to "turn off" disease components in the YAML file -Formatting, spelling edits --- .../tutorial/T7/T7_YAML_autocalibration.ipynb | 1470 +++++++++-------- 1 file changed, 738 insertions(+), 732 deletions(-) diff --git a/docs/tutorial/T7/T7_YAML_autocalibration.ipynb b/docs/tutorial/T7/T7_YAML_autocalibration.ipynb index d6d3d2d0..e142307a 100644 --- a/docs/tutorial/T7/T7_YAML_autocalibration.ipynb +++ b/docs/tutorial/T7/T7_YAML_autocalibration.ipynb @@ -1,732 +1,738 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "0", - "metadata": {}, - "source": [ - "# T7 - YAML calibration\n", - "\n", - "As we saw in the earlier calibration tutorial, most autocalibrations involve multiple steps, since the optimization algorithm often gets stuck in local minima if we try to optimize too many parameters at once. We could run each of these steps ourselves through separate calls to `P.calibrate()` – however, there is significant value in being able to explicitly frame the overall calibration process as an algorithm, as this makes it easier to modify the calibration steps and apply the calibration algorithm across a collection of projects. This is implemented in Atomica through the 'YAML calibration' feature, in which the calibration steps are specified in a file which Atomica can then read and use to execute the calibration.\n", - "\n", - "## YAML files\n", - "\n", - "The calibration algorithm files used by Atomica are written in YAML. YAML is a plain-text, human-readable data serialization language used to make configuration files. Essentially, a YAML file can be read into Python variables (dictionaries, lists, strings) which in turn can be used as arguments to Python functions. Here is an example of how variables can be specified in a YAML file:\n", - "\n", - "```\n", - " foo: a string\n", - " bar: 1\n", - " baz: [a,b,c]\n", - " list:\n", - " - i\n", - " - j\n", - " nested:\n", - " x: 1\n", - " y: 2\n", - " ```\n", - "\n", - "When parsed into Python, this becomes\n", - "\n", - "```\n", - "{'foo': 'a string',\n", - " 'bar': 1,\n", - " 'baz': ['a', 'b', 'c'],\n", - " 'list': ['i', 'j'],\n", - " 'nested': {'x': 1, 'y': 2}}\n", - "```\n", - "\n", - "Using YAML files provides a simple way to define a calibration algorithm in a format that is easy to work with and that Atomica can directly execute. This can cut down the time we spend manually calibrating, or even running autocalibrations. It allows us to conduct reproducible calibration runs, and is also highly scalable, since it allows us to apply the same calibration algorithm in multiple countries or settings.\n", - "\n", - "The following tutorial outlines how to use the YAML framework that has been developed for Atomica calibration. Specifically, it will cover how to write a YAML configuration file with calibration instructions for Atomica, and how to use this file to execute a calibration. Bear in mind that YAML calibration is not intended to be a standalone tool that will perfectly calibrate any model – rather, it is one part of the calibration toolbox. It can be used to reduce the time spent on calibration by autocalibrating Atomica models to a reasonable level, but additional tweaking may be required to obtain a consistently high calibration quality across all parameters, populations and/or countries." - ] - }, - { - "cell_type": "markdown", - "id": "1", - "metadata": {}, - "source": [ - "## Basic calibration example\n", - "\n", - "In this tutorial, we will work with a simple version of a typhoid model. This model captures typhoid infections, as well as asymptomatic carriers and vaccination. Firstly, we need to create an Atomica `Project` by loading in the Framework and Databook files, just like we did in [the first Atomica tutorial](https://atomica.tools/docs/master/tutorial/T1-Defining-a-model.html). The Framework and Databook for this project can be found in the Atomica repository under `T7/assets`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2", - "metadata": {}, - "outputs": [], - "source": [ - "import atomica as at\n", - "F = at.ProjectFramework('assets/T7_framework.xlsx')\n", - "D = at.ProjectData.from_spreadsheet('assets/T7_databook.xlsx', framework=F)\n", - "P = at.Project(framework=F,databook=D, do_run=False)\n", - "P.settings.update_time_vector(start=2000, end=2040, dt=1/52)" - ] - }, - { - "cell_type": "markdown", - "id": "3", - "metadata": {}, - "source": [ - "In the example above, no calibration has been loaded, so all of the calibration Y-factors are equal to 1, and the model is uncalibrated. We can run a simulation and plot it, to see what our model looks like before calibration:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4", - "metadata": {}, - "outputs": [], - "source": [ - "cal = P.make_parset()\n", - "res = P.run_sim(parset=cal, result_name = 'Uncalibrated')\n", - "d = at.PlotData(res, outputs=['alive','deaths', 'typ_prev', 'typ_num_deaths'], project=P)\n", - "fig = at.plot_series(d,axis='pops', data=P.data, n_cols=2, legend_mode='none')[0]\n", - "fig.set_size_inches(10,7)\n", - "fig.tight_layout()" - ] - }, - { - "cell_type": "markdown", - "id": "5", - "metadata": {}, - "source": [ - "Two issues with these simulation outputs immediately stand out. First, for the variables and years in which data is available, the model output doesn't match the data very well at all. Second, there is a large sudden change in the values of several variables right at the start of the simulation. In the absence of associated changes in interventions or disease transmission, disease burden is typically much more stable over time, so we would not expect to see such sudden changes at the start of the simulation.\n", - "\n", - "Tutorial 2 covers some of the detail around how to approach calibration. Although the parameters used for calibration vary from model to model, as a general rule, calibration proceeds by\n", - "\n", - "1. Demographic calibration: Adjusting birth and background death rates to match quantities like the total population size.\n", - "2. Epidemiological calibration: Adjusting parameters such as force of infection, diagnosis rate and mortality rate, to match quantities like incidence, prevalence and deaths.\n", - "\n", - "Each of these steps involves calibrating multiple parameters, which may be adjusted sequentially and repeatedly. They may also be interspersed with adjusting the model's initialization, to help minimize sudden transients at the start of the simulation. The purpose of the YAML file is to specify the sequence of steps to follow in carrying out a calibration run, in terms of which parameters to adjust, the order in which to adjust them (or whether some should be adjusted simultaneously), and how to assess the quality of the calibration at each step of the process. In this tutorial, we will use YAML files to specify a sequence of steps to calibrate the simple typhoid model shown above, starting with a minimal example and then introducing key features provided by Atomica's YAML calibration system." - ] - }, - { - "cell_type": "markdown", - "id": "6", - "metadata": { - "jp-MarkdownHeadingCollapsed": true - }, - "source": [ - "## Minimal YAML file\n", - "\n", - "To illustrate how YAML calibration works, let’s start with a simple example of what a YAML file could look like:\n", - "\n", - " calibration:\n", - " \tadjustables: b_rate, mig_rate\n", - " \tmeasurables: alive\n", - "\n", - "The above YAML file represents a single call to the autocalibration optimisation function, where the `b_rate` and `mig_rate` y-factors are adjusted to match `alive`. It is equivalent to running a calibration with the following command:\n", - "\n", - " calibrated_parset = P.calibrate(parset = cal, adjustables = ['b_rate', 'mig_rate'], measurables = 'alive')\n", - "\n", - "Running the YAML calibration is very similar to performing a standalone auto-calibration. After saving the YAML file to disk (e.g., `T7_YAML_1_minimal.yaml`), the calibration can be run using\n", - "\n", - " calibrated_parset = P.calibrate(parset = cal, yaml='T7_YAML_1_minimal.yaml')\n", - "\n", - "As the YAML calibration framework allows us to specify the adjustables and measurables, it is not necessary to provide them to `Project.calibrate()` – simply providing the YAML file is sufficient. However, the YAML file can contain multiple calibration commands, and therefore a single call to `Project.calibrate()` with a YAML file might be equivalent to multiple explicit calibration steps. The resulting simulation after running this simple calibration is like so: \n", - "\n", - "\"Simple\n", - "\"Simple\n", - "\n", - "As you can see, these plots don't look very different to the uncalibrated simulation results. If we plot the uncalibrated simulation in the same plot as our simple calibration, we can see that there has been a slight change, but not nearly enough to be able to consider this a good calibration. Next, we will illustrate the YAML calibration features that we can use to improve on this initial result. " - ] - }, - { - "cell_type": "markdown", - "id": "7", - "metadata": {}, - "source": [ - "## Sections\n", - "\n", - "At the most basic level, a YAML calibration file defines a sequence of individual steps, where each step incrementally modifies the calibration. The YAML file therefore defines an overall _algorithm_ for performing an automatic calibration. This algorithm is defined using two structures in the YAML file:\n", - "\n", - "- _actions_, which are associated with particular operations, like running a gradient-descent calibration step with a particular set of parameters and data. A calibration action contains `adjustables` and `measurables`. Other examples of actions are detailed below.\n", - "- _sections_, which are containers for actions. Sections can contain attributes, such as how many times to repeat the contents of the section, or they can define settings that are applied to any relevant actions within that section.\n", - "\n", - "The original YAML file above consisted of a single calibration action. If we wanted to extend the algorithm by adding a step to calibrate the death rate, we could update our YAML file to the following: \n", - "\n", - "\n", - "```\n", - "calibration:\n", - " Match population sizes:\n", - " adjustables: b_rate, mig_rate\n", - " measurables: alive\n", - " Match deaths:\n", - " adjustables: d_rate\n", - " measurables: deaths\n", - "```\n", - "\n", - "To organize the YAML file further, we could group these into an additional section. Both of these actions affect the overall population calibration, so we could logically group them as follows:\n", - "\n", - "```\n", - "calibration: \n", - " Population calibration:\n", - " Match population sizes:\n", - " adjustables: b_rate, mig_rate\n", - " measurables: alive\n", - " Match deaths:\n", - " adjustables: d_rate\n", - " measurables: deaths\n", - "```\n", - "\n", - "The overall structure of this YAML file is thus:\n", - "\n", - "1. A top-level section titled `calibration`, which has one sub-section (`Population calibration`)\n", - "2. A sub-section called `Population calibration`, which in turn contains two actions\n", - "3. An action called `Match population sizes`, corresponding to the original calibration step we used to adjust the birth rate and migration rate\n", - "4. An action called `Match deaths`, corresponding to the new step of adjusting the death rate\n", - "\n", - "An action is differentiated from a section in two possible ways:\n", - "\n", - "- By its contents (e.g. if it contains `adjustables` and `measurables`, then it will be interpreted as a calibration action rather than a section)\n", - "- By the title (if the name corresponds to the name of a supported operation, as described below)\n", - "\n", - "Additionally, actions can never contain any sub-sections, whereas sections do. \n", - "Apart from the names of supported operations, sections can be freely named." - ] - }, - { - "cell_type": "markdown", - "id": "8", - "metadata": {}, - "source": [ - "### Repeating a section\n", - "\n", - "The *repeats* keyword can be used to loop over any part of the calibration multiple times. We do this by writing `repeats: n` inside a particular section, where *n* is the number of times we would like to loop over that section. All subsections contained in it will also be looped over *n* times. \n", - "\n", - " calibration: \n", - " repeats: 2\n", - " Population calibration:\n", - " Match population sizes:\n", - " repeats: 2\n", - " adjustables: b_rate, mig_rate\n", - " measurables: alive\n", - " Match deaths:\n", - " adjustables: d_rate\n", - " measurables: deaths\n", - "\n", - "In the above example, we have set `repeats: 2` inside the `calibration` section, so the entire YAML calibration will be repeated twice. Then, the `Match population sizes` section also has `repeats: 2`, so the calibration step defined in that section will also be repeated twice each time. In total, there will be four calls to the optimisation algorithm to match `alive`, and two to match `deaths, so the YAML file above would be equivalent to \n", - "\n", - " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", - " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", - " parset = P.calibrate(parset = parset, adjustables = [d_rate], measurables=deaths)\n", - " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", - " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", - " parset = P.calibrate(parset = parset, adjustables = [d_rate], measurables=deaths)\n", - "\n", - "In this way, it is possible for even a very compact YAML file to correspond to a large number of individual autocalibration steps. " - ] - }, - { - "cell_type": "markdown", - "id": "9", - "metadata": {}, - "source": [ - "## Sections vs Actions\n", - "\n", - "As shown above, sections can help us to structure the calibration in a way that is practical and intuitive. They can be used to group blocks of YAML code that are conceptually related, that we want to repeat together several times, or that we want to apply similar settings to (we will cover which settings are supported in [the corresponding section](#specifying-settings-in-outer-sections). \n", - "\n", - "Importantly though, _sections_ do not modify the calibration itself – they are merely wrappers for the innermost blocks that actually correspond to specific actions. It is in these _actions_ that operations are performed on the calibration, such as modifying the calibration or saving it.\n", - "\n", - "
    \n", - "We can tell action blocks apart from sections because action blocks contain keywords indicating what kind of block they are, and they don't contain any sub-sections.\n", - "
    \n", - "\n", - "It is possible to load and inspect a YAML file in Atomica without executing it. This can help confirm that the YAML file has been parsed correctly. After loading in the YAML file, it can be printed to show a summary of the sections and actions that are present, how they are nested, and how many times they are repeated: " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "10", - "metadata": {}, - "outputs": [], - "source": [ - "import atomica.yaml_calibration \n", - "calibration_tree = at.yaml_calibration.build('calibrations/T7_YAML_3_repeats.yaml') \n", - "print(calibration_tree)" - ] - }, - { - "cell_type": "markdown", - "id": "11", - "metadata": {}, - "source": [ - "## Types of Action Blocks\n", - "\n", - "YAML calibration files can contain the following types of actions, or action blocks: \n", - "\n", - "- Calibration block\n", - "- Initialization block\n", - "- Intialization clearing block\n", - "- Saving block" - ] - }, - { - "cell_type": "markdown", - "id": "12", - "metadata": {}, - "source": [ - "### Calibration blocks\n", - "\n", - "In all of the YAML examples shown above, we have worked with 'calibration blocks', which are the main type of action. Calibration blocks are defined by the fact that they contain the keywords `adjustables` and `measurables`. Under `adjustables`, we list the parameters for Atomica’s optimisation algorithm to adjust, and under `measurables`, we list the parameters to calibrate to. Each calibration block provides instructions for one optimisation run, and is equivalent to making one call to `P.calibrate()` with the same adjustables and measurables.\n", - "\n", - "#### Adjustable and measurable settings\n", - "\n", - "So far, we have only specified the names of the adjustables and measurables, with no further information – in that case, the optimisation algorithm will use the default calibration settings for adjustables and measurables. For more flexibility, we can customise the settings that will be used for the optimisation, which directly map to the options supported by `P.calibrate()`.\n", - "\n", - "Each adjustable has:\n", - "\n", - "- `adj_label` (required): Adjustable parameter codename (can be found in the framework)\n", - "- `pop_name`: Population to calibrate (default: all populations)\n", - "- `lower_bound`: Lowest value the y-factor will be allowed to take (default: 0.1)\n", - "- `upper_bound`: Highest value the y-factor will be allowed to take (default: 10)\n", - "- `starting_y_factor`: Y-factor value the optimisation algorithm will start from (default: the adjustable's current `y_factor` in the parset)\n", - "\n", - "Each measurable has:\n", - "\n", - "- `meas_label` (required): Measurable parameter codename (can be found in the framework)\n", - "- `pop_name`: Population to use for calibration (default: all populations)\n", - "- `weight`: Weight for a particular population (default: 1). By default, all populations are weighted equally regardless of size. See [the documentation on weights](https://atomica.tools/docs/master/general/YAML_calibration.html#Measurable-Weights \"Measurable weights\") for further details.\n", - "- `metric`: Metric to be used by the optimisation algorithm (default: fractional)\n", - "- `cal_start`: Starting year that the calibration will be evaluated from (default: `sim_start`)\n", - "- `cal_end`: End year until which the calibration will be evaluated (default: `sim_end`)\n", - "\n", - "Note that `sim_start` and `sim_end` are the start and end years that the simulation will run for (the simulation timespan). These are distinct from `cal_start` and `cal_end`, which specify the time period for which we want to calibrate the model, i.e. a subset of the simulation timespan. For more information, see the [section on outer settings](#specifying-settings-in-outer-sections \"Specifying settings in outer sections\"). The `cal_start` and `cal_end` years can be set independently for each measurable, so it is possible to prioritize different years for different variables or for different steps of the calibration.\n", - "To specify these adjustables and measurables settings in the YAML file, we simply write the setting names and their values under the relevant parameter name. Each adjustable and measurable is placed on a new line, and their respective settings are also specified on separate indented lines, like so:\n", - "\n", - " calibration:\n", - " Match population sizes:\n", - " adjustables: \n", - " \tb_rate: \n", - " \t\tlower_bound: 0.5\n", - " \t\tupper_bound: 20\t\t\n", - " \tmig_rate: \n", - " \t\tstarting_y_factor: 1.2 \n", - " measurables: \n", - " alive:\n", - " \tcal_start: 2000\n", - " \tcal_end: 2040\n", - " " - ] - }, - { - "cell_type": "markdown", - "id": "13", - "metadata": { - "editable": true, - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, - "source": [ - "#### Specifying Populations\n", - "\n", - "In some cases, we may only want to set adjustables or measurables for a specific population, or we may wish to use different settings for one population compared to another. A population can optionally be specified after the parameter name, as the second element of a tuple. Thus, if we only wish to calibrate some populations, we can rewrite our previous YAML file like so:\n", - "\n", - " calibration: \n", - " Match population sizes:\n", - " adjustables: \n", - " \t(b_rate, 0-4): \n", - " \t\tlower_bound: 0.5\n", - " \t\tupper_bound: 20\t\t\n", - " \t(mig_rate, 5-14): \n", - " \t\tstarting_y_factor: 1.2 \n", - " measurables: \n", - " (alive, 0-4), (alive, 5-14):\n", - " \tcal_start: 2000\n", - " \tcal_end: 2040\n", - " \n", - "Note that we can specify the same settings for more than one adjustable/measurable at once by placing several parameter names before the colon, separated by commas – this is applicable to any set of adjustables/measurables, not only different populations of the same parameter. For example, we could write: \n", - "\n", - " calibration: \n", - " Match population sizes:\n", - " adjustables: \n", - " \t(b_rate, 0-4), mig_rate: \n", - " \t\tlower_bound: 0.5\n", - " \t\tupper_bound: 20\n", - " starting_y_factor: 1.2\t\t \n", - " measurables: \n", - " (alive, 0-4), (alive, 5-14):\n", - " \tcal_start: 2000\n", - " \tcal_end: 2040\n", - "\n", - "Finally, the same syntax we use to calibrate populations can be used to calibrate transfers and interactions, but in such cases the tuple should have three elements - the parameter name, the _from_ population and the _to_ population. For more information on how to calibrate in these cases, see the documentation on [Calibrating transfers and interactions](https://atomica.tools/docs/master/general/YAML_calibration.html#Calibrating-transfers-and-interactions \"Calibrating transfers and interactions\")." - ] - }, - { - "cell_type": "markdown", - "id": "14", - "metadata": { - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, - "source": [ - "### Setting initializations\n", - "\n", - "In some cases, the model may exhibit an unrealistically large transient at the start of the simulation. This can occur if the initial compartment sizes calculated by Atomica are very different to the equilibrium compartment sizes associated with the model's parameters. Two common reasons for this are:\n", - "\n", - "- The initial conditions are underdetermined, for example, if there are two strains of a disease with different levels of infectiousness, but data is only available on the total prevalence. In the absence of any other information, Atomica will automatically split up the total prevalence equally between the two strains, when in fact maybe one or the other strain may be dominant, which would change the overall transmission.\n", - "- The model parameters may not give rise to an equilibrium solution that matches the data. This could be due to data sources being mixed, combined across different years, collected in different ways or with different definitions, or because the simplified dynamics in the model simply don't capture all the processes in the real world.\n", - "\n", - "Regardless of the cause, there can often be an initial transience period at the beginning of the simulation, where we can observe abrupt spikes in some parameters until the system reaches equilibrium. \n", - "\n", - "\"Pre-initialization\n", - "\n", - "In some models, this can be treated as a 'burn-in' period, and the initial part of the simulation is simply discarded. However, there is a risk that being too far from the correct initialization can contaminate the parameter estimates during the calibration period. For example, if the model is initialized with the incorrect prevalence, the calibration applied to the force of infection in order to match the observed incidence would be impacted, which might subsequently affect the model's sensitivity to interventions that change the prevalence later on. Therefore, we wish to minimize the effect of transients on the calibration.\n", - "\n", - "We can sometimes achieve this by setting the calibration start year `cal_start` to be a few years after the simulation start year `sim_start`, so that the simulation has a few years to reach equilibrium before the calibration process itself begins. However, this extends the duration of the simulation, and it might limit the amount of data that can be used for calibration.\n", - "\n", - "An alternative approach is to override the initial values of our simulation and replace them with new initialization values. Setting an initialization works by running a normal Atomica simulation for a few years (past the initial transient), taking the compartment sizes of that future year, and setting the initial compartment sizes to those stabilized values. In cases where the model parameters are approximately constant, these future compartment sizes will be roughly equivalent to what the initial compartment sizes should be, which will prevent the appearance of an initial transient in the model.\n", - "\n", - "\"Post-initialization\n", - "\n", - "If the model parameters are not roughly constant, the equilibrium that the model converges to in the future might not correspond to the equilibrium solution for the model's initial parameter values. In that case, an initial transient can still occur. To address this, we can remove any time variation in the model's parameter values using the `ParameterSet.make_constant()` method. This will return a copy of the parset in which all parameters are constant over time, thus ensuring that the future compartment sizes are computed based on the same parameter values as the initial simulation year. This often provides a suitable solution, although changes to the total population size due to births and deaths can still take place, so in some cases a small initial transient may still be present. In such cases, repeatedly setting initialization based on a shorter simulation can help minimize the discrepancy. For more information on Atomica initializations, see the [documentation on this topic](https://atomica.tools/docs/master/general/Compartment-Initialization.html \"Initializing compartments\").\n", - "\n", - "In the YAML file, we indicate that we want to set a new initialization by making a YAML block with the title `set_initialization`. Under this title, we can specify further settings:\n", - "\n", - "- `init_year` (required): The future year to take the compartment sizes from. The simulation will be run up to this year.\n", - "- `constant_parset` (default: False): Whether to make the parameters constant while the initialization is being calculated, and which year to extract these constant parameter values from, i.e. which year to use in `parset.make_constant()`. It can be a numerical value (representing the year from which to draw the constant values for the parset) or Boolean (if `True`, the default year `sim_start` will be used).\n", - "\n", - "There are thus several valid ways to set an initialization. For example, only setting the initialization year:\n", - "\n", - "```\n", - "calibration:\n", - " set_initialization:\n", - " init_year: 2030\n", - "```\n", - "\n", - "Setting the initialization year with a constant parset, using the parameter values from the default `sim_start` year:\n", - "\n", - "```\n", - "calibration:\n", - " set_initialization:\n", - " init_year: 2030\n", - " constant_parset: True\n", - "```\n", - "\n", - "Setting the initialization year with a constant parset, using constant parameter values from a specific year:\n", - "\n", - "\n", - "```\n", - "calibration:\n", - " set_initialization:\n", - " init_year: 2030\n", - " constant_parset: 2005\n", - "```\n" - ] - }, - { - "cell_type": "markdown", - "id": "15", - "metadata": {}, - "source": [ - "### Clearing initializations\n", - "\n", - "If we have previously set an initialization in our YAML calibration algorithm, and we then set another initialization later in the YAML file, it uses information from the previous initialization to calculate the next, since the new simulation will start from the initial compartment sizes calculated in that previous initialization.\n", - "\n", - "Sometimes we might wish to calculate a new initialization from scratch, without using our previous initializations as a starting point. This could be useful if we have done some calibration steps between the previous initialization and now, in which case the y-factors will have changed, which in turn could have caused the equilibrium values to vary.\n", - "\n", - "To do this in the YAML file, we can make a section titled `clear_initialization`, followed by a Boolean value. If it is set to `True`, any existing initialization will be cleared; if `False`, nothing will happen. The most simple example is as follows:\n", - "\n", - "```\n", - "calibration:\n", - " clear_initialization: True\n", - "```\n", - "\n", - "Below is a more practical example of how we would use the `clear_initialization` feature in a real YAML file, where we first set an initialization, perform some calibration steps, and then clear our previous initialization before making a new one.\n", - "\n", - " calibration:\n", - " First initialization:\n", - " set_initialization:\n", - " init_year: 2030\n", - "\n", - " Match population sizes:\n", - " adjustables: b_rate, mig_rate\n", - " \tmeasurables: alive\n", - " \n", - " \tclear_initialization: True\n", - "\n", - " Second initialization:\n", - " set_initialization:\n", - " init_year: 2030\n", - "\n", - "\n", - "Note that we need to wrap `set_initialization` in an outer section, since YAML does not allow duplicate keys (i.e. identical section/action titles at the same level)." - ] - }, - { - "cell_type": "markdown", - "id": "16", - "metadata": {}, - "source": [ - "### Saving calibrations\n", - "\n", - "Throughout a YAML calibration, we might wish to save the calibration state at specific points in the process. For example, if our YAML file has a population section and an epidemiological section, we might want to save the calibration after the population calibration section so we can see the progress made up to that point, or otherwise identify the effect that different parts of the algorithm are having on the calibration. To save a calibration, we simply make a section titled `save_calibration`. Under the title, we indicate the filename we wish to save the calibration to, either by providing it directly, or by using the keyword `fname` - both examples are shown below:\n", - "\n", - " calibration:\n", - " \tPopulation section: \n", - " \t\t[…]\n", - " \n", - " \tsave_calibration: \n", - " \t\tfname: pop_calibration.xlsx\n", - " \n", - " \tEpidemiology section: \n", - " \t\t[…]\n", - "\n", - " \tsave_calibration: epi_calibration.xlsx\n", - " \n", - "Note that when we save a calibration, if the initial compartment sizes have been explicitly specified using `set_initialization`, these compartment sizes will be saved along with the y-factors in the same Excel file. Loading the calibration from this file will thus also set the initial compartment sizes to those values.\n", - "\n", - "Another option that can be useful for debugging is to save the calibration state at every intermediate step of the YAML file. In that case, we can use the `save_intermediate_calibrations` option when loading in and running the calibration, e.g.\n", - "\n", - " calibrated_parset = P.calibrate(parset = cal, yaml='T7_YAML_1_minimal.yaml', save_intermediate=True)\n", - "\n", - "More options for running the calibration can be found [here](#running-the-yaml-calibration \"Running the YAML calibration\")." - ] - }, - { - "cell_type": "markdown", - "id": "17", - "metadata": {}, - "source": [ - "## Specifying settings in outer sections\n", - "\n", - "We saw previously that sections (i.e. YAML blocks that don't correspond to actions) don't directly modify the calibration, and are mainly used to structure the YAML file. However, it is possible to determine calibration settings inside a section, such that they are passed down to any subsections or action blocks contained within. Another way to think of this is that an action block will inherit any settings that are defined in any of its parent sections.\n", - "\n", - "This can simplify the process of writing YAML files where we want to override the default settings in several action blocks, as it allows us to specify those settings once in a parent section, rather than repeatedly in every action block. Additionally, this feature is hierarchical, so settings that are specified further in (e.g. in the action block itself) will always override those set in a section that is further out, allowing for more flexibility.\n", - "\n", - "Some settings that this feature is commonly used for include: \n", - "\n", - "- `max_time`: Maximum amount of time each call to the optimisation algorithm will run for (default: 60 seconds)\n", - "- `stepsize`: Initial step size, i.e. how much the y-factors will be increased/decreased by the optimisation algorithm (default: 0.1)\n", - "\n", - "Additionally, any adjustable or measurable setting can also be set outside of its calibration block, although some settings lend themselves more to this feature than others. For example, changing the measurable `weight` for an entire calibration block has no effect, as what matters is the proportion between the weights of different measurables in the same block. The following settings can be useful to set in parent sections:\n", - "\n", - "- `cal_start` and `cal_end`: These can be used to change the calibration timespan for multiple calibration steps at the same time.\n", - "- `metric`: To change the metric used to assess calibration quality, i.e. how well the simulation fits the measurables data.\n", - "\n", - "We will now provide some examples of how this functionality can be used.\n", - "\n", - "### Inheritance\n", - "\n", - "Settings are automatically inherited by all subsections. To set a `max_time` of 120 for every calibration step in the entire calibration, we would write the following. This will result in every calibration step running for at most 120 seconds, rather than the default 60 seconds.\n", - "\n", - " calibration:\n", - " max_time: 120\n", - " Population calibration:\n", - " Match population sizes:\n", - " adjustables: b_rate, mig_rate\n", - " measurables: alive\n", - " Match deaths:\n", - " adjustables: d_rate\n", - " measurables: deaths\n", - " \n", - " Epidemiological calibration\n", - " [...]\n", - "\n", - "### Settings hierarchy\n", - "\n", - "Inherited settings can be overwritten inside sub-sections (in both sections and actions). Say we wanted all calibration blocks to run for a `max_time` of 120 seconds, except for `Match_deaths`, which we want to run for only 60 seconds. In that case, we can override the setting determined in the parent section by specifying the updated value inside `Match_deaths`:\n", - "\n", - " calibration:\n", - " max_time: 120\n", - " Population calibration:\n", - " Match population sizes:\n", - " adjustables: b_rate, mig_rate\n", - " measurables: alive\n", - " Match deaths:\n", - " max_time_ 60\n", - " adjustables: d_rate\n", - " measurables: deaths\n", - " \n", - " Epidemiological calibration\n", - " [...]\n", - "\n", - "### Adjustables/measurables settings\n", - "\n", - "Finally, here is an example of how to use the adjustables and measurables settings outside a calibration block:\n", - "\n", - " calibration:\n", - " Population calibration:\n", - " upper_bound: 2\n", - " lower_bound: .5\n", - "\n", - " Match population sizes:\n", - " adjustables: b_rate, mig_rate\n", - " measurables alive\n", - "\n", - " Match deaths:\n", - " adjustables: d_rate\n", - " measurab\n", - "\n", - " Epidemiological calibration:\n", - " [...]\n", - "\n", - "In this case, the upper and lower bounds have been updated to 2 and 0.5 respectively, for all the adjustables in the `Population calibration` section (`b_rate`, `mig_rate` and `d_rate`)." - ] - }, - { - "cell_type": "markdown", - "id": "18", - "metadata": {}, - "source": [ - "## Running the YAML calibration\n", - "\n", - "Now that we have finished writing our YAML calibration file, we can proceed to running the calibration. Having loaded a project, `P.calibrate` can then be called directly, passing in the name of the YAML file:\n", - "\n", - " calibrated_parset = P.calibrate(parset = cal, yaml='T7_YAML_1_minimal.yaml')\n", - "\n", - "This function supports several additional optional arguments:\n", - "\n", - "- `savedir` (default: current working directory) - any saved calibrations and logs will be saved into this folder\n", - "- `save_intermediate` (default: `False`) - if `True`, this will save all intermediate calibrations\n", - "- `max_time` (optional) - override the default\n", - "- `log_output` (default: `False`) - if `True`, this will save a text file into the output directory containing all console output (e.g., objective function values)\n", - "\n", - "The YAML file can also be supplied as a dictionary, which would normally be obtained via\n", - "\n", - " import yaml\n", - " calibration_yaml = yaml.load(file, Loader=yaml.FullLoader)\n", - " \n", - "The `calibration_yaml` variable above can be passed to `P.calibrate(..., yaml=calibration_yaml)`. This enables changes to be made to the YAML content programmatically prior to running the calibration." - ] - }, - { - "cell_type": "markdown", - "id": "19", - "metadata": {}, - "source": [ - "## Exercise: worked example\n", - "\n", - "Now that we understand what all the working parts of a YAML file are, let's put it all together. For each question, write a YAML file to calibrate the model as described. Each question will consist of incremental additions to the previous solution.\n", - "\n", - "_**Question 1.** We want to do a basic population calibration, where we calibrate the death rate and migration rate to match the data corresponding to the total number of people alive. We also want to calibrate the death rate. What should this YAML file look like?_\n", - "\n", - "**Hint**: Open the framework and look at the `Compartments`, `Parameters` and `Characteristics` pages. The `Code Names` and `Display Names` show us how we have to write the parameter names in the YAML file, and what quantities they correspond to. Those with a value in the `Databook Page` column have data values supplied, and can therefore be used as measurables.\n", - "\n", - "**Hint 2**: Some of the parameter `Code Names` and `Display Names` in the databook are as follows: \n", - "\n", - "| Framework Sheet | Code Name | Display Name | Databook Page |\n", - "|:----------------|:--------------:|:------------------------------:|--------------:|\n", - "| COMPARTMENTS | |\n", - "| | birth\t\t | Birth \t\t\t\t\t\t | none |\n", - "| | death \t | Death \t\t\t\t\t\t | none |\n", - "| PARAMETERS | |\n", - "| | b_rate\t\t | Birth rate \t\t\t\t | demographic |\n", - "| | deaths\t\t | All-cause deaths \t\t\t | demographic |\n", - "| | d_rate\t\t | Background mortality rate \t | demographic |\n", - "| | mig_rate\t | Migration Rate \t\t\t\t | demographic |\n", - "| CHARACTERISTICS | |\n", - "| | alive\t | \tTotal population\t\t | demographic |" - ] - }, - { - "cell_type": "markdown", - "id": "20", - "metadata": {}, - "source": [ - "_**Question 2.** A single calibration run may not be enough to get good results, so let's loop over our simple population calibration ten times. How would we make that change to the YAML file?_\n", - "\n", - "**Hint**: Use the `repeats` keyword.\n", - "\n", - "_**Question 3.** Say that, for this particular project, we are only interested in calibrating results from 2005 to 2040. How would we specify this in the YAML file to reduce calibration time?_\n", - "\n", - "**Hint**: Using the `cal_start` and `cal_end` keywords\n", - "\n", - "_**Question 4.** When calibrating the birth rate, it only really makes sense to calibrate the 0-4 population. Modify the YAML file to reflect this._\n", - "\n", - "**Hint**: We place the parameter code name and population name in a tuple.\n", - "\n", - "_**Question 5.** Say we know that our data source underestimates the birth rate. Let’s set its starting y_factor to 1.2 to speed up the optimisation._\n", - "\n", - "**Hint**: Use `starting_y_factor`.\n", - "\n", - "_**Question 6.** We want to avoid the presence of transients in our calibrated simulation. Let’s initialize the calibration in order to eliminate any jumps._\n", - "\n", - "**Hint**: Use `set_initialization` after the calibration blocks, and make sure the initialization gets re-calculated in every loop! \n", - "\n", - "_**Question 7.** We also want to clear the previous initialization every time we make a new one, instead of using information from the previous initialization. How can we update the YAML file to reflect this?_\n", - "\n", - "**Hint**: Use `clear_initialization`, and make sure the initialization gets cleared and re-calculated in every loop!\n", - "\n", - "_**Question 8.** We are almost ready to run the YAML calibration! Now, what instructions do we need to add to automatically save our population calibration once it is done?_\n", - "\n", - "**Hint**: Use `save_calibration` and specify a `fname`.\n", - "\n", - "All solutions to the worked example are in the `docs/tutorial/T7/calibrations` folder of the Atomica repository. The calibration obtained after running the last YAML file in this exercise yields the following simulation result:\n", - "\n", - "\"Worked" - ] - }, - { - "cell_type": "markdown", - "id": "21", - "metadata": {}, - "source": [ - "## Further resources\n", - "\n", - "### Epidemiological calibration\n", - "\n", - "In this tutorial we have demonstrated the key functionality of Atomica's YAML calibration system applied to a population calibration, focussing on adjusting births and deaths to match population size data, without considering disease burden. This same functionality applies to epidemiological calibration, just with different model parameters and data. A complete YAML file of the population and epidemiological calibration instructions (`typ_calibration_instructions.yaml`) can be found in the Atomica code repository, at `docs/tutorial/T7/calibrations`.\n", - "\n", - "In this YAML file, we have set the `max_time` to 120, to give the calibration a bit more time to reach an optimal solution in each calibration step. \n", - "\n", - "At the beginning of the calibration, we also set the parameters relating to the typhoid disease (`typ_active_inf` and `typ_car`) to zero for the first pass of the population calibration. This essentially \"turns off\" of the typhoid disease until it gets reactivated in the `reset epi y-factors` step, giving the population an opportunity to be reasonably calibrated without interference from the disease components. This can be useful to do since, before calibrating the disease, the magnitude of the disease parameters could be large enough to significantly impact the population calibration results.\n", - "\n", - "We then calibrate the population following the same principles as illustrated previously, repeating the population calibration ten times, and setting a new initialization at the end of each loop, with `constant_parset=True` and the `init_year` set to 2030.\n", - "\n", - "In the epidemiological calibration section, the typhoid incidence, prevalence, and typhoid deaths are calibrated. Since we don't have a lot of information on the order of magnitude of the susceptibility and infectiousness, the lower and upper bounds are expanded to leave more room for variation. However, we don't want the disease duration `typ_gen_dur` to vary a lot, since we have a pretty clear idea of its magnitude and don't want it to vary too much between calibrations and settings, so we set stricter bounds. \n", - "\n", - "At the end of the typhoid calibration, we set an initialization in the same way we did for the population calibration. We then repeat the epidemiological calibration ten times, and finally, repeat the whole YAML calibration process (except silencing the epi y-factors) twice.\n", - "\n", - "The resulting calibration from running this YAML file is like so:\n", - "\n", - "\"Complete\n", - "\n", - "### Documentation\n", - "\n", - "For more information on using Atomica's YAML calibration functionality, see [the documentation](https://atomica.tools/docs/master/general/YAML_calibration.html \"YAML documentation page\").\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.13" - }, - "toc": { - "base_numbering": 1, - "nav_menu": {}, - "number_sections": true, - "sideBar": true, - "skip_h1_title": false, - "title_cell": "Table of Contents", - "title_sidebar": "Contents", - "toc_cell": false, - "toc_position": {}, - "toc_section_display": true, - "toc_window_display": true - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} +{ + "cells": [ + { + "cell_type": "markdown", + "id": "0", + "metadata": {}, + "source": [ + "# T7 - YAML calibration\n", + "\n", + "As we saw in the earlier calibration tutorial, most autocalibrations involve multiple steps, since the optimization algorithm often gets stuck in local minima if we try to optimize too many parameters at once. We could run each of these steps ourselves through separate calls to `P.calibrate()` – however, there is significant value in being able to explicitly frame the overall calibration process as an algorithm, as this makes it easier to modify the calibration steps and apply the calibration algorithm across a collection of projects. This is implemented in Atomica through the 'YAML calibration' feature, in which the calibration steps are specified in a file which Atomica can then read and use to execute the calibration.\n", + "\n", + "## YAML files\n", + "\n", + "The calibration algorithm files used by Atomica are written in YAML. YAML is a plain-text, human-readable data serialization language used to make configuration files. Essentially, a YAML file can be read into Python variables (dictionaries, lists, strings) which in turn can be used as arguments to Python functions. Here is an example of how variables can be specified in a YAML file:\n", + "\n", + "```\n", + " foo: a string\n", + " bar: 1\n", + " baz: [a,b,c]\n", + " list:\n", + " - i\n", + " - j\n", + " nested:\n", + " x: 1\n", + " y: 2\n", + " ```\n", + "\n", + "When parsed into Python, this becomes\n", + "\n", + "```\n", + "{'foo': 'a string',\n", + " 'bar': 1,\n", + " 'baz': ['a', 'b', 'c'],\n", + " 'list': ['i', 'j'],\n", + " 'nested': {'x': 1, 'y': 2}}\n", + "```\n", + "\n", + "Using YAML files provides a simple way to define a calibration algorithm in a format that is easy to work with and that Atomica can directly execute. This can cut down the time we spend manually calibrating, or even running autocalibrations. It allows us to conduct reproducible calibration runs, and is also highly scalable, since it allows us to apply the same calibration algorithm in multiple countries or settings.\n", + "\n", + "The following tutorial outlines how to use the YAML framework that has been developed for Atomica calibration. Specifically, it will cover how to write a YAML configuration file with calibration instructions for Atomica, and how to use this file to execute a calibration. Bear in mind that YAML calibration is not intended to be a standalone tool that will perfectly calibrate any model – rather, it is one part of the calibration toolbox. It can be used to reduce the time spent on calibration by autocalibrating Atomica models to a reasonable level, but additional tweaking may be required to obtain a consistently high calibration quality across all parameters, populations and/or countries." + ] + }, + { + "cell_type": "markdown", + "id": "1", + "metadata": {}, + "source": [ + "## Basic calibration example\n", + "\n", + "In this tutorial, we will work with a simple version of a typhoid model. This model captures typhoid infections, as well as asymptomatic carriers and vaccination. Firstly, we need to create an Atomica `Project` by loading in the Framework and Databook files, just like we did in [the first Atomica tutorial](https://atomica.tools/docs/master/tutorial/T1-Defining-a-model.html). The Framework and Databook for this project can be found in the Atomica repository under `T7/assets`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2", + "metadata": {}, + "outputs": [], + "source": [ + "import atomica as at\n", + "F = at.ProjectFramework('assets/T7_framework.xlsx')\n", + "D = at.ProjectData.from_spreadsheet('assets/T7_databook.xlsx', framework=F)\n", + "P = at.Project(framework=F, databook=D, do_run=False)\n", + "P.settings.update_time_vector(start=2000, end=2040, dt=1/52)" + ] + }, + { + "cell_type": "markdown", + "id": "3", + "metadata": {}, + "source": [ + "In the example above, no calibration has been loaded, so all the calibration Y-factors are equal to 1, and the model is uncalibrated. We can run a simulation and plot it, to see what our model looks like before calibration:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4", + "metadata": {}, + "outputs": [], + "source": [ + "uncal = P.make_parset()\n", + "res = P.run_sim(parset=uncal, result_name='Uncalibrated')\n", + "d = at.PlotData(res, outputs=['alive','deaths', 'typ_prev', 'typ_num_deaths'], project=P)\n", + "fig = at.plot_series(d, axis='pops', data=P.data, n_cols=2, legend_mode='none')[0]\n", + "fig.set_size_inches(10,7)\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "markdown", + "id": "5", + "metadata": {}, + "source": [ + "Two issues with these simulation outputs immediately stand out. First, for the variables and years in which data is available, the model output doesn't match the data very well at all. Second, there is a large sudden change in the values of several variables right at the start of the simulation. In the absence of associated changes in interventions or disease transmission, disease burden is typically much more stable over time, so we would not expect to see such sudden changes at the start of the simulation.\n", + "\n", + "Tutorial 2 covers some of the detail around how to approach calibration. Although the parameters used for calibration vary from model to model, as a general rule, calibration proceeds by\n", + "\n", + "1. Demographic calibration: Adjusting birth and background death rates to match quantities like the total population size.\n", + "2. Epidemiological calibration: Adjusting parameters such as force of infection, diagnosis rate and mortality rate, to match quantities like incidence, prevalence and deaths.\n", + "\n", + "Each of these steps involves calibrating multiple parameters, which may be adjusted sequentially and repeatedly. They may also be interspersed with adjusting the model's initialization, to help minimize sudden transients at the start of the simulation. The purpose of the YAML file is to specify the sequence of steps to follow in carrying out a calibration run, in terms of which parameters to adjust, the order in which to adjust them (or whether some should be adjusted simultaneously), and how to assess the quality of the calibration at each step of the process. In this tutorial, we will use YAML files to specify a sequence of steps to calibrate the simple typhoid model shown above, starting with a minimal example and then introducing key features provided by Atomica's YAML calibration system." + ] + }, + { + "cell_type": "markdown", + "id": "6", + "metadata": { + "jp-MarkdownHeadingCollapsed": true + }, + "source": [ + "## Minimal YAML file\n", + "\n", + "To illustrate how YAML calibration works, let’s start with a simple example of what a YAML file could look like:\n", + "\n", + " calibration:\n", + " \tadjustables: b_rate, mig_rate\n", + " \tmeasurables: alive\n", + "\n", + "The above YAML file represents a single call to the autocalibration optimisation function, where the `b_rate` and `mig_rate` y-factors are adjusted to match `alive`. It is equivalent to running a calibration with the following command:\n", + "\n", + " calibrated_parset = P.calibrate(parset = uncal, adjustables = ['b_rate', 'mig_rate'], measurables = 'alive')\n", + "\n", + "Running the YAML calibration is very similar to performing a standalone auto-calibration. After saving the YAML file to disk (e.g., `T7_YAML_1_minimal.yaml`), the calibration can be run using\n", + "\n", + " calibrated_parset = P.calibrate(parset = uncal, yaml='T7_YAML_1_minimal.yaml')\n", + "\n", + "As the YAML calibration framework allows us to specify the adjustables and measurables, it is not necessary to provide them to `Project.calibrate()` – simply providing the YAML file is sufficient. However, the YAML file can contain multiple calibration commands, and therefore a single call to `Project.calibrate()` with a YAML file might be equivalent to multiple explicit calibration steps. The resulting simulation after running this simple calibration is like so: \n", + "\n", + "\"Simple\n", + "\"Simple\n", + "\n", + "As you can see, these plots don't look very different to the uncalibrated simulation results. If we plot the uncalibrated simulation in the same plot as our simple calibration, we can see that there has been a slight change, but not nearly enough to be able to consider this a good calibration. Next, we will illustrate the YAML calibration features that we can use to improve on this initial result. " + ] + }, + { + "cell_type": "markdown", + "id": "7", + "metadata": {}, + "source": [ + "## Sections\n", + "\n", + "At the most basic level, a YAML calibration file defines a sequence of individual steps, where each step incrementally modifies the calibration. The YAML file therefore defines an overall _algorithm_ for performing an automatic calibration. This algorithm is defined using two structures in the YAML file:\n", + "\n", + "- _actions_, which are associated with particular operations, like running a gradient-descent calibration step with a particular set of parameters and data. A calibration action contains `adjustables` and `measurables`. Other examples of actions are detailed below.\n", + "- _sections_, which are containers for actions. Sections can contain attributes, such as how many times to repeat the contents of the section, or they can define settings that are applied to any relevant actions within that section.\n", + "\n", + "The original YAML file above consisted of a single calibration action. If we wanted to extend the algorithm by adding a step to calibrate the death rate, we could update our YAML file to the following: \n", + "\n", + "\n", + "```\n", + "calibration:\n", + " Match population sizes:\n", + " adjustables: b_rate, mig_rate\n", + " measurables: alive\n", + " Match deaths:\n", + " adjustables: d_rate\n", + " measurables: deaths\n", + "```\n", + "\n", + "To organize the YAML file further, we could group these into an additional section. Both of these actions affect the overall population calibration, so we could logically group them as follows:\n", + "\n", + "```\n", + "calibration: \n", + " Population calibration:\n", + " Match population sizes:\n", + " adjustables: b_rate, mig_rate\n", + " measurables: alive\n", + " Match deaths:\n", + " adjustables: d_rate\n", + " measurables: deaths\n", + "```\n", + "\n", + "The overall structure of this YAML file is thus:\n", + "\n", + "1. A top-level section titled `calibration`, which has one sub-section (`Population calibration`)\n", + "2. A sub-section called `Population calibration`, which in turn contains two actions\n", + "3. An action called `Match population sizes`, corresponding to the original calibration step we used to adjust the birth rate and migration rate\n", + "4. An action called `Match deaths`, corresponding to the new step of adjusting the death rate\n", + "\n", + "An action is differentiated from a section in two possible ways:\n", + "\n", + "- By its contents (e.g. if it contains `adjustables` and `measurables`, then it will be interpreted as a calibration action rather than a section)\n", + "- By the title (if the name corresponds to the name of a supported operation, as described below)\n", + "\n", + "Additionally, actions can never contain any sub-sections, whereas sections always do.\n", + "Apart from the names of supported operations, sections can be freely named." + ] + }, + { + "cell_type": "markdown", + "id": "8", + "metadata": {}, + "source": [ + "### Repeating a section\n", + "\n", + "The *repeats* keyword can be used to loop over any part of the calibration multiple times. We do this by writing `repeats: n` inside a particular section, where *n* is the number of times we would like to loop over that section. All subsections contained in it will also be looped over *n* times. \n", + "\n", + " calibration: \n", + " repeats: 2\n", + " Population calibration:\n", + " Match population sizes:\n", + " repeats: 2\n", + " adjustables: b_rate, mig_rate\n", + " measurables: alive\n", + " Match deaths:\n", + " adjustables: d_rate\n", + " measurables: deaths\n", + "\n", + "In the above example, we have set `repeats: 2` inside the `calibration` section, so the entire YAML calibration will be repeated twice. Then, the `Match population sizes` section also has `repeats: 2`, so the calibration step defined in that section will also be repeated twice each time. In total, there will be four calls to the optimisation algorithm to match `alive`, and two to match `deaths, so the YAML file above would be equivalent to \n", + "\n", + " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", + " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", + " parset = P.calibrate(parset = parset, adjustables = [d_rate], measurables=deaths)\n", + " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", + " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", + " parset = P.calibrate(parset = parset, adjustables = [d_rate], measurables=deaths)\n", + "\n", + "In this way, it is possible for even a very compact YAML file to correspond to a large number of individual autocalibration steps. " + ] + }, + { + "cell_type": "markdown", + "id": "9", + "metadata": {}, + "source": [ + "## Sections vs Actions\n", + "\n", + "As shown above, sections can help us to structure the calibration in a way that is practical and intuitive. They can be used to group blocks of YAML code that are conceptually related, that we want to repeat together several times, or that we want to apply similar settings to (we will cover which settings are supported in [the corresponding section](#specifying-settings-in-outer-sections)).\n", + "\n", + "Importantly though, _sections_ do not modify the calibration itself – they are merely wrappers for the innermost blocks that actually correspond to specific actions. It is in these _actions_ that operations are performed on the calibration, such as modifying the calibration or saving it.\n", + "\n", + "
    \n", + "We can tell action blocks apart from sections because action blocks contain keywords indicating what kind of block they are, and they don't contain any sub-sections.\n", + "
    \n", + "\n", + "It is possible to load and inspect a YAML file in Atomica without executing it. This can help confirm that the YAML file has been parsed correctly. After loading in the YAML file, it can be printed to show a summary of the sections and actions that are present, how they are nested, and how many times they are repeated: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "10", + "metadata": {}, + "outputs": [], + "source": [ + "import atomica.yaml_calibration \n", + "calibration_tree = at.yaml_calibration.build('calibrations/T7_YAML_3_repeats.yaml') \n", + "print(calibration_tree)" + ] + }, + { + "cell_type": "markdown", + "id": "11", + "metadata": {}, + "source": [ + "## Types of Action Blocks\n", + "\n", + "YAML calibration files can contain the following types of actions, or action blocks: \n", + "\n", + "- Calibration block\n", + "- Initialization block\n", + "- Intialization clearing block\n", + "- Saving block" + ] + }, + { + "cell_type": "markdown", + "id": "12", + "metadata": {}, + "source": [ + "### Calibration blocks\n", + "\n", + "In all of the YAML examples shown above, we have worked with 'calibration blocks', which are the main type of action. Calibration blocks are defined by the fact that they contain the keywords `adjustables` and `measurables`. Under `adjustables`, we list the parameters for Atomica’s optimisation algorithm to adjust, and under `measurables`, we list the parameters to calibrate to. Each calibration block provides instructions for one optimisation run, and is equivalent to making one call to `P.calibrate()` with the same adjustables and measurables.\n", + "\n", + "#### Adjustable and measurable settings\n", + "\n", + "So far, we have only specified the names of the adjustables and measurables, with no further information – in that case, the optimisation algorithm will use the default calibration settings for adjustables and measurables. For more flexibility, we can customise the settings that will be used for the optimisation, which directly map to the options supported by `P.calibrate()`.\n", + "\n", + "Each adjustable has:\n", + "\n", + "- `adj_label` (required): Adjustable parameter codename (can be found in the framework)\n", + "- `pop_name`: Population to calibrate (default: all populations)\n", + "- `lower_bound`: Lowest value the y-factor will be allowed to take (default: 0.1)\n", + "- `upper_bound`: Highest value the y-factor will be allowed to take (default: 10)\n", + "- `starting_y_factor`: Y-factor value the optimisation algorithm will start from (default: the adjustable's current `y_factor` in the parset)\n", + "\n", + "Each measurable has:\n", + "\n", + "- `meas_label` (required): Measurable parameter codename (can be found in the framework)\n", + "- `pop_name`: Population to use for calibration (default: all populations)\n", + "- `weight`: Weight for a particular population (default: 1). By default, all populations are weighted equally regardless of size. See [the documentation on weights](https://atomica.tools/docs/master/general/YAML_calibration.html#Measurable-Weights \"Measurable weights\") for further details.\n", + "- `metric`: Metric to be used by the optimisation algorithm (default: fractional)\n", + "- `cal_start`: Starting year that the calibration will be evaluated from (default: `sim_start`)\n", + "- `cal_end`: End year until which the calibration will be evaluated (default: `sim_end`)\n", + "\n", + "Note that `sim_start` and `sim_end` are the start and end years that the simulation will run for (the simulation timespan). These are distinct from `cal_start` and `cal_end`, which specify the time period for which we want to calibrate the model, i.e. a subset of the simulation timespan. For more information, see the [section on outer settings](#specifying-settings-in-outer-sections \"Specifying settings in outer sections\"). The `cal_start` and `cal_end` years can be set independently for each measurable, so it is possible to prioritize different years for different variables or for different steps of the calibration.\n", + "To specify these adjustables and measurables settings in the YAML file, we simply write the setting names and their values under the relevant parameter name. Each adjustable and measurable is placed on a new line, and their respective settings are also specified on separate indented lines, like so:\n", + "\n", + " calibration:\n", + " Match population sizes:\n", + " adjustables: \n", + " \tb_rate: \n", + " \t\tlower_bound: 0.5\n", + " \t\tupper_bound: 20\t\t\n", + " \tmig_rate: \n", + " \t\tstarting_y_factor: 1.2 \n", + " measurables: \n", + " alive:\n", + " \tcal_start: 2000\n", + " \tcal_end: 2040\n", + " " + ] + }, + { + "cell_type": "markdown", + "id": "13", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "#### Specifying Populations\n", + "\n", + "In some cases, we may only want to set adjustables or measurables for a specific population, or we may wish to use different settings for one population compared to another. A population can optionally be specified after the parameter name, as the second element of a tuple. Thus, if we only wish to calibrate some populations, we can rewrite our previous YAML file like so:\n", + "\n", + " calibration: \n", + " Match population sizes:\n", + " adjustables: \n", + " \t(b_rate, 0-4): \n", + " \t\tlower_bound: 0.5\n", + " \t\tupper_bound: 20\t\t\n", + " \t(mig_rate, 5-14): \n", + " \t\tstarting_y_factor: 1.2 \n", + " measurables: \n", + " (alive, 0-4), (alive, 5-14):\n", + " \tcal_start: 2000\n", + " \tcal_end: 2040\n", + " \n", + "Note that we can specify the same settings for more than one adjustable/measurable at once by placing several parameter names before the colon, separated by commas – this is applicable to any set of adjustables/measurables, not only different populations of the same parameter. For example, we could write: \n", + "\n", + " calibration: \n", + " Match population sizes:\n", + " adjustables: \n", + " \t(b_rate, 0-4), mig_rate: \n", + " \t\tlower_bound: 0.5\n", + " \t\tupper_bound: 20\n", + " starting_y_factor: 1.2\t\t \n", + " measurables: \n", + " (alive, 0-4), (alive, 5-14):\n", + " \tcal_start: 2000\n", + " \tcal_end: 2040\n", + "\n", + "Finally, the same syntax we use to calibrate populations can be used to calibrate transfers and interactions, but in such cases the tuple should have three elements - the parameter name, the _from_ population and the _to_ population. For more information on how to calibrate in these cases, see the documentation on [Calibrating transfers and interactions](https://atomica.tools/docs/master/general/YAML_calibration.html#Calibrating-transfers-and-interactions \"Calibrating transfers and interactions\")." + ] + }, + { + "cell_type": "markdown", + "id": "14", + "metadata": { + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "### Setting initializations\n", + "\n", + "In some cases, the model may exhibit an unrealistically large transient at the start of the simulation. This can occur if the initial compartment sizes calculated by Atomica are very different to the equilibrium compartment sizes associated with the model's parameters. Two common reasons for this are:\n", + "\n", + "- The initial conditions are underdetermined, for example, if there are two strains of a disease with different levels of infectiousness, but data is only available on the total prevalence. In the absence of any other information, Atomica will automatically split up the total prevalence equally between the two strains, when in fact maybe one or the other strain may be dominant, which would change the overall transmission.\n", + "- The model parameters may not give rise to an equilibrium solution that matches the data. This could be due to data sources being mixed, combined across different years, collected in different ways or with different definitions, or because the simplified dynamics in the model simply don't capture all the processes in the real world.\n", + "\n", + "Regardless of the cause, there can often be an initial transience period at the beginning of the simulation, where we can observe abrupt spikes in some parameters until the system reaches equilibrium. \n", + "\n", + "\"Pre-initialization\n", + "\n", + "In some models, this can be treated as a 'burn-in' period, and the initial part of the simulation is simply discarded. However, there is a risk that being too far from the correct initialization can contaminate the parameter estimates during the calibration period. For example, if the model is initialized with the incorrect prevalence, the calibration applied to the force of infection in order to match the observed incidence would be impacted, which might subsequently affect the model's sensitivity to interventions that change the prevalence later on. Therefore, we wish to minimize the effect of transients on the calibration.\n", + "\n", + "We can sometimes achieve this by setting the calibration start year `cal_start` to be a few years after the simulation start year `sim_start`, so that the simulation has a few years to reach equilibrium before the calibration process itself begins. However, this extends the duration of the simulation, and it might limit the amount of data that can be used for calibration.\n", + "\n", + "An alternative approach is to override the initial values of our simulation and replace them with new initialization values. Setting an initialization works by running a normal Atomica simulation for a few years (past the initial transient), taking the compartment sizes of that future year, and setting the initial compartment sizes to those stabilized values. In cases where the model parameters are approximately constant, these future compartment sizes will be roughly equivalent to what the initial compartment sizes should be, which will prevent the appearance of an initial transient in the model.\n", + "\n", + "\"Post-initialization\n", + "\n", + "If the model parameters are not roughly constant, the equilibrium that the model converges to in the future might not correspond to the equilibrium solution for the model's initial parameter values. In that case, an initial transient can still occur. To address this, we can remove any time variation in the model's parameter values using the `ParameterSet.make_constant()` method. This will return a copy of the parset in which all parameters are constant over time, thus ensuring that the future compartment sizes are computed based on the same parameter values as the initial simulation year. This often provides a suitable solution, although changes to the total population size due to births and deaths can still take place, so in some cases a small initial transient may still be present. In such cases, repeatedly setting initialization based on a shorter simulation can help minimize the discrepancy. For more information on Atomica initializations, see the [documentation on this topic](https://atomica.tools/docs/master/general/Compartment-Initialization.html \"Initializing compartments\").\n", + "\n", + "In the YAML file, we indicate that we want to set a new initialization by making a YAML block with the title `set_initialization`. Under this title, we can specify further settings:\n", + "\n", + "- `init_year` (required): The future year to take the compartment sizes from. The simulation will be run up to this year.\n", + "- `constant_parset` (default: False): Whether to make the parameters constant while the initialization is being calculated, and which year to extract these constant parameter values from, i.e. which year to use in `parset.make_constant()`. It can be a numerical value (representing the year from which to draw the constant values for the parset) or Boolean (if `True`, the default year `sim_start` will be used).\n", + "\n", + "There are thus several valid ways to set an initialization. For example, only setting the initialization year:\n", + "\n", + "```\n", + "calibration:\n", + " set_initialization:\n", + " init_year: 2030\n", + "```\n", + "\n", + "Setting the initialization year with a constant parset, using the parameter values from the default `sim_start` year:\n", + "\n", + "```\n", + "calibration:\n", + " set_initialization:\n", + " init_year: 2030\n", + " constant_parset: True\n", + "```\n", + "\n", + "Setting the initialization year with a constant parset, using constant parameter values from a specific year:\n", + "\n", + "\n", + "```\n", + "calibration:\n", + " set_initialization:\n", + " init_year: 2030\n", + " constant_parset: 2005\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "id": "15", + "metadata": {}, + "source": [ + "### Clearing initializations\n", + "\n", + "If we have previously set an initialization in our YAML calibration algorithm, and we then set another initialization later in the YAML file, it uses information from the previous initialization to calculate the next, since the new simulation will start from the initial compartment sizes calculated in that previous initialization.\n", + "\n", + "Sometimes we might wish to calculate a new initialization from scratch, without using our previous initializations as a starting point. This could be useful if we have done some calibration steps between the previous initialization and now, in which case the y-factors will have changed, which in turn could have caused the equilibrium values to vary.\n", + "\n", + "To do this in the YAML file, we can make a section titled `clear_initialization`, followed by a Boolean value. If it is set to `True`, any existing initialization will be cleared; if `False`, nothing will happen. The most simple example is as follows:\n", + "\n", + "```\n", + "calibration:\n", + " clear_initialization: True\n", + "```\n", + "\n", + "Below is a more practical example of how we would use the `clear_initialization` feature in a real YAML file, where we first set an initialization, perform some calibration steps, and then clear our previous initialization before making a new one.\n", + "\n", + " calibration:\n", + " First initialization:\n", + " set_initialization:\n", + " init_year: 2030\n", + "\n", + " Match population sizes:\n", + " adjustables: b_rate, mig_rate\n", + " \tmeasurables: alive\n", + " \n", + " \tclear_initialization: True\n", + "\n", + " Second initialization:\n", + " set_initialization:\n", + " init_year: 2030\n", + "\n", + "\n", + "Note that we need to wrap `set_initialization` in an outer section, since YAML does not allow duplicate keys (i.e. identical section/action titles at the same level)." + ] + }, + { + "cell_type": "markdown", + "id": "16", + "metadata": {}, + "source": [ + "### Saving calibrations\n", + "\n", + "Throughout a YAML calibration, we might wish to save the calibration state at specific points in the process. For example, if our YAML file has a population section and an epidemiological section, we might want to save the calibration after the population calibration section so we can see the progress made up to that point, or otherwise identify the effect that different parts of the algorithm are having on the calibration. To save a calibration, we simply make a section titled `save_calibration`. Under the title, we indicate the filename we wish to save the calibration to, either by providing it directly, or by using the keyword `fname` - both examples are shown below:\n", + "\n", + " calibration:\n", + " \tPopulation section: \n", + " \t\t[…]\n", + " \n", + " \tsave_calibration: \n", + " \t\tfname: pop_calibration.xlsx\n", + " \n", + " \tEpidemiology section: \n", + " \t\t[…]\n", + "\n", + " \tsave_calibration: epi_calibration.xlsx\n", + " \n", + "Note that when we save a calibration, if the initial compartment sizes have been explicitly specified using `set_initialization`, these compartment sizes will be saved along with the y-factors in the same Excel file. Loading the calibration from this file will thus also set the initial compartment sizes to those values.\n", + "\n", + "Another option that can be useful for debugging is to save the calibration state at every intermediate step of the YAML file. In that case, we can use the `save_intermediate_calibrations` option when loading in and running the calibration, e.g.\n", + "\n", + " calibrated_parset = P.calibrate(parset = cal, yaml='T7_YAML_1_minimal.yaml', save_intermediate=True)\n", + "\n", + "More options for running the calibration can be found [here](#running-the-yaml-calibration \"Running the YAML calibration\")." + ] + }, + { + "cell_type": "markdown", + "id": "17", + "metadata": {}, + "source": [ + "## Specifying settings in outer sections\n", + "\n", + "We saw previously that sections (i.e. YAML blocks that don't correspond to actions) don't directly modify the calibration, and are mainly used to structure the YAML file. However, it is possible to determine calibration settings inside a section, such that they are passed down to any subsections or action blocks contained within. Another way to think of this is that an action block will inherit any settings that are defined in any of its parent sections.\n", + "\n", + "This can simplify the process of writing YAML files where we want to override the default settings in several action blocks, as it allows us to specify those settings once in a parent section, rather than repeatedly in every action block. Additionally, this feature is hierarchical, so settings that are specified further in (e.g. in the action block itself) will always override those set in a section that is further out, allowing for more flexibility.\n", + "\n", + "Some settings that this feature is commonly used for include: \n", + "\n", + "- `max_time`: Maximum amount of time each call to the optimisation algorithm will run for (default: 60 seconds)\n", + "- `stepsize`: Initial step size, i.e. how much the y-factors will be increased/decreased by the optimisation algorithm (default: 0.1)\n", + "\n", + "Additionally, any adjustable or measurable setting can also be set outside of its calibration block, although some settings lend themselves more to this feature than others. For example, changing the measurable `weight` for an entire calibration block has no effect, as what matters is the proportion between the weights of different measurables in the same block. The following settings can be useful to set in parent sections:\n", + "\n", + "- `cal_start` and `cal_end`: These can be used to change the calibration timespan for multiple calibration steps at the same time.\n", + "- `metric`: To change the metric used to assess calibration quality, i.e. how well the simulation fits the measurables data.\n", + "\n", + "We will now provide some examples of how this functionality can be used.\n", + "\n", + "### Inheritance\n", + "\n", + "Settings are automatically inherited by all subsections. To set a `max_time` of 120 for every calibration step in the entire calibration, we would write the following. This will result in every calibration step running for at most 120 seconds, rather than the default 60 seconds.\n", + "\n", + " calibration:\n", + " max_time: 120\n", + " Population calibration:\n", + " Match population sizes:\n", + " adjustables: b_rate, mig_rate\n", + " measurables: alive\n", + " Match deaths:\n", + " adjustables: d_rate\n", + " measurables: deaths\n", + " \n", + " Epidemiological calibration\n", + " [...]\n", + "\n", + "### Settings hierarchy\n", + "\n", + "Inherited settings can be overwritten inside subsections (in both sections and actions). Say we wanted all calibration blocks to run for a `max_time` of 120 seconds, except for `Match_deaths`, which we want to run for only 60 seconds. In that case, we can override the setting determined in the parent section by specifying the updated value inside `Match_deaths` subsection (which happens to be an action block):\n", + "\n", + " calibration:\n", + " max_time: 120\n", + " Population calibration:\n", + " Match population sizes:\n", + " adjustables: b_rate, mig_rate\n", + " measurables: alive\n", + " Match deaths:\n", + " max_time: 60\n", + " adjustables: d_rate\n", + " measurables: deaths\n", + " \n", + " Epidemiological calibration\n", + " [...]\n", + "\n", + "### Outer adjustables/measurables settings\n", + "\n", + "Finally, here is an example of how to use the adjustables and measurables settings outside a calibration block:\n", + "\n", + " calibration:\n", + " Population calibration:\n", + " upper_bound: 2\n", + " lower_bound: 0.5\n", + "\n", + " Match population sizes:\n", + " adjustables: b_rate, mig_rate\n", + " measurables: alive\n", + "\n", + " Match deaths:\n", + " adjustables: d_rate\n", + " measurables: deaths\n", + "\n", + " Epidemiological calibration:\n", + " [...]\n", + "\n", + "In this case, the upper and lower bounds have been updated to 2 and 0.5 respectively, for all the adjustables in the `Population calibration` section (that is, `b_rate`, `mig_rate` and `d_rate`). The upper and lower bounds in the Epidemiological section will remain unchanged, using the default values of 0.1 and 10." + ] + }, + { + "cell_type": "markdown", + "id": "18", + "metadata": {}, + "source": [ + "## Running the YAML calibration\n", + "\n", + "Now that we have finished writing our YAML calibration file, we can proceed to running the calibration. Having loaded a project, `P.calibrate()` can then be called directly, passing in the uncalibrated parset and the name of the YAML file:\n", + "\n", + " calibrated_parset = P.calibrate(parset=uncal, yaml='T7_YAML_1_minimal.yaml')\n", + "\n", + "This function also supports several optional arguments:\n", + "\n", + "- `savedir`: Any saved calibrations and logs will be saved into this folder (default: current working directory).\n", + "- `save_intermediate`: If `True`, this will save a calibration file at every step (default: `False`).\n", + "- `max_time`: Maximum amount of time each calibration step will run for (default: 60 seconds).\n", + "- `log_output`: If `True`, this will save a text file into the output directory containing all console output, e.g. objective function values (default: `False`).\n", + "\n", + "The YAML file can also be supplied as a dictionary, which would normally be obtained via\n", + "\n", + " import yaml\n", + " yaml_instructions = yaml.load(file, Loader=yaml.FullLoader)\n", + " \n", + "The `yaml_instructions` variable above can be passed to `P.calibrate(..., yaml=yaml_instructions)`. This enables changes to be made to the YAML content programmatically prior to running the calibration." + ] + }, + { + "cell_type": "markdown", + "id": "19", + "metadata": {}, + "source": [ + "## Exercise: Worked Example\n", + "\n", + "Now that we understand what all the working parts of a YAML file are, let's put it all together. For each question, write a YAML file to calibrate the model as described. Each question will consist of incremental additions to the previous solution.\n", + "\n", + "_**Question 1.** We want to do a basic population calibration, where we calibrate the birth rate and migration rate to match the data corresponding to the total number of people alive. We also want to calibrate the death rate. What should this YAML file look like?_\n", + "\n", + "**Hint**: Open the framework and look at the `Compartments`, `Parameters` and `Characteristics` pages. The `Code Names` and `Display Names` show us how we have to write the parameter names in the YAML file, and what quantities they correspond to. Those with a value in the `Databook Page` column have data values supplied, and can therefore be used as measurables.\n", + "\n", + "**Hint 2**: Some of the parameter `Code Names` and `Display Names` in the databook are as follows: \n", + "\n", + "| Framework Sheet | Code Name | Display Name | Databook Page |\n", + "|:----------------|:--------------:|:------------------------------:|--------------:|\n", + "| COMPARTMENTS | |\n", + "| | birth\t\t | Birth \t\t\t\t\t\t | none |\n", + "| | death \t | Death \t\t\t\t\t\t | none |\n", + "| PARAMETERS | |\n", + "| | b_rate\t\t | Birth rate \t\t\t\t | demographic |\n", + "| | deaths\t\t | All-cause deaths \t\t\t | demographic |\n", + "| | d_rate\t\t | Background mortality rate \t | demographic |\n", + "| | mig_rate\t | Migration Rate \t\t\t\t | demographic |\n", + "| CHARACTERISTICS | |\n", + "| | alive\t | \tTotal population\t\t | demographic |" + ] + }, + { + "cell_type": "markdown", + "id": "20", + "metadata": {}, + "source": [ + "_**Question 2.** A single calibration run may not be enough to get good results, so let's loop over our simple population calibration ten times. How would we make that change to the YAML file?_\n", + "\n", + "**Hint**: Use the `repeats` keyword.\n", + "\n", + "_**Question 3.** Say that, for this particular project, we are only interested in calibrating results from 2005 to 2040. How would we specify this in the YAML file to reduce calibration time?_\n", + "\n", + "**Hint**: Using the `cal_start` and `cal_end` keywords.\n", + "\n", + "_**Question 4.** When calibrating the birth rate, it only really makes sense to calibrate the 0-4 population. Modify the YAML file to reflect this._\n", + "\n", + "**Hint**: We place the parameter code name and population name in a tuple.\n", + "\n", + "_**Question 5.** Say we know that our data source underestimates the birth rate. Let’s set the starting y_factor for this parameter to 1.2 to speed up the optimisation._\n", + "\n", + "**Hint**: Use `starting_y_factor`.\n", + "\n", + "_**Question 6.** We want to avoid the presence of transients in our calibrated simulation. Let’s initialize the calibration in order to eliminate any jumps._\n", + "\n", + "**Hint**: Use `set_initialization` after the calibration blocks, and make sure the initialization gets re-calculated in every loop! \n", + "\n", + "_**Question 7.** We also want to clear the previous initialization every time we make a new one, instead of using information from the previous initialization. How can we update the YAML file to reflect this?_\n", + "\n", + "**Hint**: Use `clear_initialization`, and make sure the initialization gets cleared and re-calculated in every loop!\n", + "\n", + "_**Question 8.** We are almost ready to run the YAML calibration! Now, what instructions do we need to add to automatically save our population calibration once it is done?_\n", + "\n", + "**Hint**: Use `save_calibration` and specify a `fname`.\n", + "\n", + "All solutions to the worked example can be found in the `docs/tutorial/T7/calibrations` folder of the Atomica repository. The calibration obtained after running the last YAML file in this exercise yields the following simulation result:\n", + "\n", + "\"Worked\n", + "\n", + "The above calibration result is an improvement on the simple example shown earlier in the tutorial - while the simulation result for the 15-64 age group (in green) may not look as close to the data, the remaining populations have an excellent fit, leading to a very good overall population calibration. Additionally, all-cause deaths are now calibrated. Note that we do not expect the calibrated simulation to match the data points exactly, but to follow the same overall trends." + ] + }, + { + "cell_type": "markdown", + "id": "21", + "metadata": {}, + "source": [ + "## Further resources\n", + "\n", + "### Epidemiological calibration\n", + "\n", + "In this tutorial we have demonstrated the key functionality of Atomica's YAML calibration system applied to a population calibration, focussing on adjusting births, migration and deaths to match population size data, without considering disease burden. The same functionality can be used for epidemiological calibration, just with different model parameters and data. A complete YAML file of the population and epidemiological calibration instructions can be found in the Atomica code repository, at `docs/tutorial/T7/calibrations/typ_calibration_instructions.yaml`.\n", + "\n", + "In this YAML file, we have set the `max_time` to 120, to give the calibration a bit more time to reach an optimal solution in each calibration step. We then calibrate the population following the same principles illustrated previously, repeating the population calibration ten times, and setting a new initialization at the end of each loop, with `constant_parset=True` and the `init_year` set to 2030.\n", + "\n", + "In the epidemiological calibration section, the typhoid incidence, prevalence, and typhoid deaths are calibrated. Since we don't have a lot of information on the order of magnitude of the susceptibility and infectiousness, the lower and upper bounds are expanded to leave more room for variation. However, we don't want the disease duration `typ_gen_dur` to vary a lot, since we have a pretty clear idea of its magnitude and don't want it to vary too much between calibrations and settings, so we set stricter bounds. \n", + "\n", + "At the end of the typhoid calibration, we set an initialization in the same way we did for the population calibration. We then repeat the epidemiological calibration ten times, and finally, repeat the whole YAML calibration process (except silencing the epi y-factors) twice.\n", + "\n", + "The resulting calibration from running this YAML file is like so:\n", + "\n", + "\"Complete\n", + "\n", + "As you can see, this is an improvement on the previous calibrations shown, since the epidemiological parameters (like typhoid prevalence and typhoid deaths) are now also calibrated to match the data.\n", + "\n", + "__Alternative approach__\n", + "\n", + "If the epidemiological parameters have a very large impact on the population parameters (for example, if the uncalibrated disease prevalence or disease mortality is much larger than the data would indicate), this can make it hard to properly calibrate the population in the first instance. We might observe that the population y-factors relating to births and migration increase (or, in the case of deaths, decrease) by a lot, to compensate for the large amount of people dying from disease.\n", + "\n", + "To prevent this behaviour, we can do the following: At the beginning of the YAML file, we set the parameters relating to the typhoid disease (`typ_active_inf` and `typ_car`) to zero. This essentially \"turns off\" of the typhoid disease, giving us the opportunity to reasonably calibrate the population without interference from the disease components. Then, just after the population calibration section, we \"reactivate\" the disease by setting the `typ_active_inf` and `typ_car` y-factors back to 1, before proceeding to the epidemiological calibration. Looping over this whole algorithm a couple of times (except for the first step where we \"turn off\" the disease) allows the population to be fine-tuned while taking the epidemiological parameters into account.\n", + "\n", + "### Documentation\n", + "\n", + "For more information on using Atomica's YAML calibration functionality, see [the documentation](https://atomica.tools/docs/master/general/YAML_calibration.html \"YAML documentation page\").\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": true + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 87a0d75448c46d72e12cb3aa810e48b33e03594a Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Thu, 6 Mar 2025 20:17:40 +0100 Subject: [PATCH 125/161] Update YAML documentation -Add png files of databook screenshots -Update links -Formatting and spelling --- docs/general/YAML_calibration.ipynb | 14 +++++++------- docs/general/databook_pops.png | Bin 0 -> 45849 bytes docs/general/databook_pops_Total.png | Bin 0 -> 33878 bytes 3 files changed, 7 insertions(+), 7 deletions(-) create mode 100644 docs/general/databook_pops.png create mode 100644 docs/general/databook_pops_Total.png diff --git a/docs/general/YAML_calibration.ipynb b/docs/general/YAML_calibration.ipynb index adf79647..0029dfa3 100644 --- a/docs/general/YAML_calibration.ipynb +++ b/docs/general/YAML_calibration.ipynb @@ -172,7 +172,7 @@ "- `pop_name`: Population to calibrate (default: all populations)\n", "- `lower_bound`: Lowest value the y-factor will be allowed to take (default: 0.1)\n", "- `upper_bound`: Highest value the y-factor will be allowed to take (default: 1)\n", - "- `starting_y_factor`: Y-factor value the autocalibration will start from when running the optimisation algorithm (default: the adjustable’s current `y_factor` in the parset)\n", + "- `starting_y_factor`: Y-factor value the autocalibration will start from when running the optimisation algorithm (default: the adjustable's current `y_factor` in the parset)\n", "\n", "\n", "Each measurable has:\n", @@ -265,7 +265,7 @@ " adjustables: [adj_label, lower_bound, upper_bound, starting_y_factor]\n", " measurables: [meas_label, weight, metric, start_year, end_year]\n", "\n", - "Although this might seem like a lot of information for each adjustable and measurable, it is not necessary to include each item every time we use list format – only up to the point where the last setting we want to change is. For example, if we just want to set the `b_rate` adjustable’s `lower bound` to, say, 0.2, we only need to list the `par_label` and `lower_bound` values in order. Any subsequent settings will retain their default values.\n", + "Although this might seem like a lot of information for each adjustable and measurable, it is not necessary to include each item every time we use list format – only up to the point where the last setting we want to change is. For example, if we just want to set the `b_rate` adjustable's `lower bound` to, say, 0.2, we only need to list the `par_label` and `lower_bound` values in order. Any subsequent settings will retain their default values.\n", "\n", " adjustables: [b_rate, 0.2]\n", " measurables: [alive]" @@ -377,7 +377,7 @@ "source": [ "### Calibrating transfers and interactions\n", "\n", - "In the case of transfers and interactions, there are two populations involved: the ‘to’ population, and the ‘from' population. The approach is the same as with regular populations, except that we now have two population names in the tuple instead of one: \n", + "In the case of transfers and interactions, there are two populations involved: the _to_ population, and the _from_ population. The approach is the same as with regular populations, except that we now have two population names in the tuple instead of one:\n", "\n", " adjustables:\n", " (aging, 5-14, 15-64): \n", @@ -401,7 +401,7 @@ "\n", "Usually, our data is structured like below, with each parameter containing several populations, such as age groups. \n", "\n", - "![](databook_pops.png \"Example of a databook with multiple populations\")\n", + "\"Example\n", "\n", "In the YAML file, we could write \n", "\n", @@ -411,9 +411,9 @@ "\n", "Since no population has been specified, all populations will be calibrated. \n", "\n", - "However, for some parameters, our source data might not be broken down into populations or age groups. In that case, the above YAML file will not work, since there is no data available at the individual population level. What we can do in that situation is add an extra row to the databook with a population called `Total` (which is a reserved keyword in Atomica), and explicitly set the population name to `Total` in the YAML file. If it was our 'alive' data that was not broken down by populations, the databook would look like so\n", + "However, for some parameters, our source data might not be broken down into populations or age groups. In that case, the above YAML file will not work, since there is no data available at the individual population level. What we can do in that situation is to add an extra row to the databook with a population called `Total` (which is a reserved keyword in Atomica), and explicitly set the population name to `Total` in the YAML file. If it was our 'alive' data that was not broken down by populations, the databook would look like so\n", "\n", - "![](databook_pops_Total.png \"Example of a databook with a Total population\")\n", + "\"Example\n", "\n", "And we would adjust the previous YAML file like so.\n", "\n", @@ -429,7 +429,7 @@ "source": [ "## Measurable Weights \n", "\n", - "In one calibration block, we can include several measurables at the same time, or multiple populations of the same measurable. But say we trusted the data from one measurable’s data source more than another, or wanted to prioritise fitting a particular population – how would we indicate this to the optimisation algorithm? \n", + "In one calibration block, we can include several measurables at the same time, or multiple populations of the same measurable. But say we trusted the data from one measurable's data source more than another, or wanted to prioritise fitting a particular population – how would we indicate this to the optimisation algorithm?\n", "\n", "In the measurable settings, we can set weights for this purpose. The default value for the `weight` setting is 1.0 which is used for all measurables and populations, which corresponds to giving them each an equal weight, regardless of size. That might be desirable if, for example, we have a key population that is smaller than the other populations – if they were weighted proportionally to size, the small key population might be effectively ignored in the optimisation. However, there might be cases where we want to do things differently. For example, we could give a key population a higher weight, or we could weight different age bins according to their size. Another reason to use measurable weights could simply be that we trust one data source more than another. \n", "\n", diff --git a/docs/general/databook_pops.png b/docs/general/databook_pops.png new file mode 100644 index 0000000000000000000000000000000000000000..be026587cb66082785c2452030ecc1f318199f16 GIT binary patch literal 45849 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%0A$sN0@1HO7Yqb1(we7uZCm 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 ToW#GS0DIDB~ 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%0DG{~r!1{~<7`>dttS6cpajDu0H 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 Date: Thu, 6 Mar 2025 20:24:12 +0100 Subject: [PATCH 126/161] Consistent spelling in T7 Update spelling of 'optimization' for consistency --- docs/tutorial/T7/T7_YAML_autocalibration.ipynb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/tutorial/T7/T7_YAML_autocalibration.ipynb b/docs/tutorial/T7/T7_YAML_autocalibration.ipynb index e142307a..2a3f3610 100644 --- a/docs/tutorial/T7/T7_YAML_autocalibration.ipynb +++ b/docs/tutorial/T7/T7_YAML_autocalibration.ipynb @@ -117,7 +117,7 @@ " \tadjustables: b_rate, mig_rate\n", " \tmeasurables: alive\n", "\n", - "The above YAML file represents a single call to the autocalibration optimisation function, where the `b_rate` and `mig_rate` y-factors are adjusted to match `alive`. It is equivalent to running a calibration with the following command:\n", + "The above YAML file represents a single call to the autocalibration optimization function, where the `b_rate` and `mig_rate` y-factors are adjusted to match `alive`. It is equivalent to running a calibration with the following command:\n", "\n", " calibrated_parset = P.calibrate(parset = uncal, adjustables = ['b_rate', 'mig_rate'], measurables = 'alive')\n", "\n", @@ -207,7 +207,7 @@ " adjustables: d_rate\n", " measurables: deaths\n", "\n", - "In the above example, we have set `repeats: 2` inside the `calibration` section, so the entire YAML calibration will be repeated twice. Then, the `Match population sizes` section also has `repeats: 2`, so the calibration step defined in that section will also be repeated twice each time. In total, there will be four calls to the optimisation algorithm to match `alive`, and two to match `deaths, so the YAML file above would be equivalent to \n", + "In the above example, we have set `repeats: 2` inside the `calibration` section, so the entire YAML calibration will be repeated twice. Then, the `Match population sizes` section also has `repeats: 2`, so the calibration step defined in that section will also be repeated twice each time. In total, there will be four calls to the optimization algorithm to match `alive`, and two to match `deaths, so the YAML file above would be equivalent to\n", "\n", " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", @@ -271,11 +271,11 @@ "source": [ "### Calibration blocks\n", "\n", - "In all of the YAML examples shown above, we have worked with 'calibration blocks', which are the main type of action. Calibration blocks are defined by the fact that they contain the keywords `adjustables` and `measurables`. Under `adjustables`, we list the parameters for Atomica’s optimisation algorithm to adjust, and under `measurables`, we list the parameters to calibrate to. Each calibration block provides instructions for one optimisation run, and is equivalent to making one call to `P.calibrate()` with the same adjustables and measurables.\n", + "In all of the YAML examples shown above, we have worked with 'calibration blocks', which are the main type of action. Calibration blocks are defined by the fact that they contain the keywords `adjustables` and `measurables`. Under `adjustables`, we list the parameters for Atomica’s optimization algorithm to adjust, and under `measurables`, we list the parameters to calibrate to. Each calibration block provides instructions for one optimization run, and is equivalent to making one call to `P.calibrate()` with the same adjustables and measurables.\n", "\n", "#### Adjustable and measurable settings\n", "\n", - "So far, we have only specified the names of the adjustables and measurables, with no further information – in that case, the optimisation algorithm will use the default calibration settings for adjustables and measurables. For more flexibility, we can customise the settings that will be used for the optimisation, which directly map to the options supported by `P.calibrate()`.\n", + "So far, we have only specified the names of the adjustables and measurables, with no further information – in that case, the optimization algorithm will use the default calibration settings for adjustables and measurables. For more flexibility, we can customise the settings that will be used for the optimization, which directly map to the options supported by `P.calibrate()`.\n", "\n", "Each adjustable has:\n", "\n", @@ -283,14 +283,14 @@ "- `pop_name`: Population to calibrate (default: all populations)\n", "- `lower_bound`: Lowest value the y-factor will be allowed to take (default: 0.1)\n", "- `upper_bound`: Highest value the y-factor will be allowed to take (default: 10)\n", - "- `starting_y_factor`: Y-factor value the optimisation algorithm will start from (default: the adjustable's current `y_factor` in the parset)\n", + "- `starting_y_factor`: Y-factor value the optimization algorithm will start from (default: the adjustable's current `y_factor` in the parset)\n", "\n", "Each measurable has:\n", "\n", "- `meas_label` (required): Measurable parameter codename (can be found in the framework)\n", "- `pop_name`: Population to use for calibration (default: all populations)\n", "- `weight`: Weight for a particular population (default: 1). By default, all populations are weighted equally regardless of size. See [the documentation on weights](https://atomica.tools/docs/master/general/YAML_calibration.html#Measurable-Weights \"Measurable weights\") for further details.\n", - "- `metric`: Metric to be used by the optimisation algorithm (default: fractional)\n", + "- `metric`: Metric to be used by the optimization algorithm (default: fractional)\n", "- `cal_start`: Starting year that the calibration will be evaluated from (default: `sim_start`)\n", "- `cal_end`: End year until which the calibration will be evaluated (default: `sim_end`)\n", "\n", @@ -503,8 +503,8 @@ "\n", "Some settings that this feature is commonly used for include: \n", "\n", - "- `max_time`: Maximum amount of time each call to the optimisation algorithm will run for (default: 60 seconds)\n", - "- `stepsize`: Initial step size, i.e. how much the y-factors will be increased/decreased by the optimisation algorithm (default: 0.1)\n", + "- `max_time`: Maximum amount of time each call to the optimization algorithm will run for (default: 60 seconds)\n", + "- `stepsize`: Initial step size, i.e. how much the y-factors will be increased/decreased by the optimization algorithm (default: 0.1)\n", "\n", "Additionally, any adjustable or measurable setting can also be set outside of its calibration block, although some settings lend themselves more to this feature than others. For example, changing the measurable `weight` for an entire calibration block has no effect, as what matters is the proportion between the weights of different measurables in the same block. The following settings can be useful to set in parent sections:\n", "\n", @@ -643,7 +643,7 @@ "\n", "**Hint**: We place the parameter code name and population name in a tuple.\n", "\n", - "_**Question 5.** Say we know that our data source underestimates the birth rate. Let’s set the starting y_factor for this parameter to 1.2 to speed up the optimisation._\n", + "_**Question 5.** Say we know that our data source underestimates the birth rate. Let’s set the starting y_factor for this parameter to 1.2 to speed up the optimization._\n", "\n", "**Hint**: Use `starting_y_factor`.\n", "\n", From 616dcd07005d3641b5879363c8c71ce31789e7f9 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 10 Mar 2025 10:58:28 +1000 Subject: [PATCH 127/161] Fix table --- .../tutorial/T7/T7_YAML_autocalibration.ipynb | 71 +++++++++++++++---- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/docs/tutorial/T7/T7_YAML_autocalibration.ipynb b/docs/tutorial/T7/T7_YAML_autocalibration.ipynb index 2a3f3610..f557fd60 100644 --- a/docs/tutorial/T7/T7_YAML_autocalibration.ipynb +++ b/docs/tutorial/T7/T7_YAML_autocalibration.ipynb @@ -316,7 +316,6 @@ "cell_type": "markdown", "id": "13", "metadata": { - "editable": true, "slideshow": { "slide_type": "" }, @@ -612,18 +611,55 @@ "\n", "**Hint 2**: Some of the parameter `Code Names` and `Display Names` in the databook are as follows: \n", "\n", - "| Framework Sheet | Code Name | Display Name | Databook Page |\n", - "|:----------------|:--------------:|:------------------------------:|--------------:|\n", - "| COMPARTMENTS | |\n", - "| | birth\t\t | Birth \t\t\t\t\t\t | none |\n", - "| | death \t | Death \t\t\t\t\t\t | none |\n", - "| PARAMETERS | |\n", - "| | b_rate\t\t | Birth rate \t\t\t\t | demographic |\n", - "| | deaths\t\t | All-cause deaths \t\t\t | demographic |\n", - "| | d_rate\t\t | Background mortality rate \t | demographic |\n", - "| | mig_rate\t | Migration Rate \t\t\t\t | demographic |\n", - "| CHARACTERISTICS | |\n", - "| | alive\t | \tTotal population\t\t | demographic |" + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    Framework SheetCode NameDisplay NameDatabook Page
    CompartmentsbirthBirthnone
    deathDeathnone
    Parametersb_rateBirth ratedemographic
    deathsAll-cause deathsdemographic
    d_rateBackground mortality ratedemographic
    mig_rateMigration Ratedemographic
    CharacteristicsaliveTotal populationdemographic
    " ] }, { @@ -717,7 +753,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.10.11" }, "toc": { "base_numbering": 1, @@ -728,7 +764,12 @@ "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, - "toc_position": {}, + "toc_position": { + "height": "calc(100% - 180px)", + "left": "10px", + "top": "150px", + "width": "343.4px" + }, "toc_section_display": true, "toc_window_display": true } From 9483b7b867525fbb71e6c9e685b2575c0e39a89a Mon Sep 17 00:00:00 2001 From: Cliff Kerr Date: Fri, 30 May 2025 15:44:05 -0400 Subject: [PATCH 128/161] replace setup.py with pyproject.toml --- docs/index.rst | 20 ++++++++++++++++- pyproject.toml | 56 ++++++++++++++++++++++++++++++++++++++++++++++ setup.py | 59 ------------------------------------------------- tests/simple.py | 10 +++++++++ 4 files changed, 85 insertions(+), 60 deletions(-) create mode 100644 pyproject.toml delete mode 100644 setup.py create mode 100644 tests/simple.py diff --git a/docs/index.rst b/docs/index.rst index 16beee87..4cadb6a6 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -5,7 +5,25 @@ :align: center -Atomica is a simulation engine for compartmental models. It can be used to simulate disease epidemics, health care cascades, and many other things. +[Atomica](https://https://github.com/atomicateam/atomica) is a simulation engine for compartmental models. It can be used to simulate disease epidemics, health care cascades, and many other things. + +To install via PyPI: + +.. code-block:: python + + pip install atomica + +You can run a plot an Atomica demo with: + +.. code-block:: python + + import atomica as at + import matplotlib.pyplot as plt + + P = at.demo("sir") + d = at.PlotData(P.results[0], project=P) + figs = at.plot_series(d) + plt.show() .. toctree:: :maxdepth: 1 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..d6aaafd7 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,56 @@ +[build-system] +requires = ["setuptools>=61.0", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "atomica" +dynamic = ["version"] +description = "Toolbox for compartment-based dynamic systems with costing and optimization" +readme = "README.md" +authors = [ + { name="Atomica Team", email="info@atomica.tools" }, +] +license = { text="MIT" } +keywords = ["dynamic", "compartment", "optimization", "disease"] +classifiers = [ + "Environment :: Console", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Topic :: Software Development :: Libraries :: Python Modules", + "Development Status :: 5 - Production/Stable", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13" +] +requires-python = ">=3.7" + +dependencies = [ + "matplotlib", + "numpy>=1.10.1,<2", + "scipy>=1.6", + "pandas", + "xlsxwriter", + "openpyxl", + "pyswarm", + "hyperopt", + "sciris", + "tqdm", +] + +[project.urls] +Homepage = "https://atomica.tools" + +[tool.setuptools] +include-package-data = true + +[tool.setuptools.packages.find] +where = ["."] + +[tool.setuptools.dynamic] +version = {attr = "atomica.version.__version__"} \ No newline at end of file diff --git a/setup.py b/setup.py deleted file mode 100644 index 53a5d85c..00000000 --- a/setup.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from setuptools import setup, find_packages -import os - -cwd = os.path.abspath(os.path.dirname(__file__)) - -# Read version -with open(os.path.join(cwd, "atomica", "version.py"), "r") as f: - version = [x.split("=")[1].replace('"', "").strip() for x in f if x.startswith("version =")][0] - -# Read README.md for description -with open(os.path.join(cwd, "README.md"), "r") as f: - long_description = f.read() - -CLASSIFIERS = [ - "Environment :: Console", - "Intended Audience :: Science/Research", - "License :: OSI Approved :: MIT License", - "Operating System :: OS Independent", - "Programming Language :: Python", - "Topic :: Software Development :: Libraries :: Python Modules", - "Development Status :: 5 - Production/Stable", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", -] - -setup( - name="atomica", - version=version, - author="Atomica Team", - author_email="info@atomica.tools", - description="Toolbox for compartment-based dynamic systems with costing and optimization", - long_description=long_description, - long_description_content_type="text/markdown", - url="https://atomica.tools", - keywords=["dynamic", "compartment", "optimization", "disease"], - platforms=["OS Independent"], - classifiers=CLASSIFIERS, - packages=find_packages(), - include_package_data=True, - install_requires=[ - "matplotlib", - "numpy>=1.10.1,<2", - "scipy>=1.6", - "pandas", - "xlsxwriter", - "openpyxl", - "pyswarm", - "hyperopt", - "sciris", - "tqdm", - ], -) diff --git a/tests/simple.py b/tests/simple.py new file mode 100644 index 00000000..26d6a963 --- /dev/null +++ b/tests/simple.py @@ -0,0 +1,10 @@ +""" +Minimal example of running Atomica. +""" +import atomica as at +import matplotlib.pyplot as plt + +P = at.demo("sir") +d = at.PlotData(P.results[0], project=P) +figs = at.plot_series(d) +plt.show() \ No newline at end of file From 8b6fc9fa612d164d8c22a303bd7c9128906d2700 Mon Sep 17 00:00:00 2001 From: Cliff Kerr Date: Fri, 30 May 2025 15:50:02 -0400 Subject: [PATCH 129/161] update version --- CHANGELOG.md | 4 ++++ atomica/__init__.py | 9 ++++++--- atomica/version.py | 8 ++------ pyproject.toml | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1f60ebb..5c07437c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ This file records changes to the codebase grouped by version release. Unreleased changes are generally only present during development (relevant parts of the changelog can be written and saved in that section before a version number has been assigned) +## [1.31.1] - 2025-05-30 + +- Switched from `setup.py` to `pyproject.toml`-based installation. + ## [1.31.0] - 2025-02-18 - Framework definitions of compartments, characteristics, and parameters support a new column 'databook default all'. If set to 'y', then when a databook is produced, the data entry table will only contain a record for 'All' instead of having population-specific rows. Further manual editing of the tables is supported as normal. diff --git a/atomica/__init__.py b/atomica/__init__.py index 0ba03568..55484117 100644 --- a/atomica/__init__.py +++ b/atomica/__init__.py @@ -56,12 +56,15 @@ logger.addHandler(warning_handler) logger.setLevel("INFO") # Set the overall log level -from .version import version as __version__, versiondate as __versiondate__, gitinfo as __gitinfo__ -# Check scipy version -import scipy +# Get version information import sciris as sc +__gitinfo__ = sc.gitinfo(__file__) +from .version import version as __version__, versiondate as __versiondate__ + +# Check scipy version +import scipy if sc.compareversions(scipy.__version__, "1.2.1") < 0: raise Exception(f"Atomica requires Scipy 1.2.1 or later - installed version is {scipy.__version__}") diff --git a/atomica/version.py b/atomica/version.py index 6d57766a..751f4d57 100644 --- a/atomica/version.py +++ b/atomica/version.py @@ -3,9 +3,5 @@ Standard location for module version number and date. """ - -import sciris as sc - -version = "1.31.0" -versiondate = "2025-02-17" -gitinfo = sc.gitinfo(__file__) +version = "1.31.1" +versiondate = "2025-05-30" diff --git a/pyproject.toml b/pyproject.toml index d6aaafd7..70aed4f0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,4 +53,4 @@ include-package-data = true where = ["."] [tool.setuptools.dynamic] -version = {attr = "atomica.version.__version__"} \ No newline at end of file +version = {attr = "atomica.version.version"} \ No newline at end of file From 2e9ed306816850166e9e5256ca95e953838bd407 Mon Sep 17 00:00:00 2001 From: Cliff Kerr Date: Fri, 30 May 2025 15:52:31 -0400 Subject: [PATCH 130/161] update order --- atomica/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/__init__.py b/atomica/__init__.py index 55484117..e751eb87 100644 --- a/atomica/__init__.py +++ b/atomica/__init__.py @@ -58,9 +58,9 @@ # Get version information +from .version import version as __version__, versiondate as __versiondate__ import sciris as sc __gitinfo__ = sc.gitinfo(__file__) -from .version import version as __version__, versiondate as __versiondate__ # Check scipy version From 708dc0e7721fed17e4b9f4da9a13dec425d20d41 Mon Sep 17 00:00:00 2001 From: Cliff Kerr Date: Fri, 30 May 2025 15:56:32 -0400 Subject: [PATCH 131/161] add gitinfo back to version module --- atomica/__init__.py | 1 + docs/index.rst | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/atomica/__init__.py b/atomica/__init__.py index e751eb87..a1f7b482 100644 --- a/atomica/__init__.py +++ b/atomica/__init__.py @@ -61,6 +61,7 @@ from .version import version as __version__, versiondate as __versiondate__ import sciris as sc __gitinfo__ = sc.gitinfo(__file__) +version.gitinfo = __gitinfo__ # Add back (so version.py does not require imports) # Check scipy version diff --git a/docs/index.rst b/docs/index.rst index 4cadb6a6..8fb55856 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -13,7 +13,7 @@ To install via PyPI: pip install atomica -You can run a plot an Atomica demo with: +You can run and plot an Atomica demo with: .. code-block:: python From 784a1c94a809f1ac95c4da3b29b23d4748a0da2c Mon Sep 17 00:00:00 2001 From: Cliff Kerr Date: Fri, 30 May 2025 16:00:46 -0400 Subject: [PATCH 132/161] update license date --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 43382f75..c75ac9ae 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Atomica Development Team +Copyright (c) 2017 - 2025 Atomica Development Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 256fde2aa9c2fc7af8f816c20ec86462684a3e1f Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 2 Jun 2025 10:21:49 +1000 Subject: [PATCH 133/161] Lift numpy version restriction --- atomica/programs.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atomica/programs.py b/atomica/programs.py index f3f60f1f..02640a22 100644 --- a/atomica/programs.py +++ b/atomica/programs.py @@ -1552,7 +1552,7 @@ def get_outcome(self, prop_covered): # RANDOM CALCULATION elif self.cov_interaction == "random": # Outcome += c1(1-c2)* delta_out1 + c2(1-c1)*delta_out2 + c1c2* max(delta_out1,delta_out2) - combination_coverage = np.product(self.combinations * cov + (self.combinations ^ 1) * (1 - cov), axis=1) + combination_coverage = np.prod(self.combinations * cov + (self.combinations ^ 1) * (1 - cov), axis=1) outcome += np.sum(combination_coverage.ravel() * self._combination_outcomes.ravel()) else: raise Exception('Unknown reachability type "%s"', self.cov_interaction) diff --git a/pyproject.toml b/pyproject.toml index 70aed4f0..af0cf1e5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,7 @@ requires-python = ">=3.7" dependencies = [ "matplotlib", - "numpy>=1.10.1,<2", + "numpy>=1.10.1", "scipy>=1.6", "pandas", "xlsxwriter", From 46a40d95359e2d325222cb0f7c077c91b6fa6469 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 2 Jun 2025 10:26:21 +1000 Subject: [PATCH 134/161] Fix RST link syntax --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index 8fb55856..3397fb48 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -5,7 +5,7 @@ :align: center -[Atomica](https://https://github.com/atomicateam/atomica) is a simulation engine for compartmental models. It can be used to simulate disease epidemics, health care cascades, and many other things. +`Atomica `_ is a simulation engine for compartmental models. It can be used to simulate disease epidemics, health care cascades, and many other things. To install via PyPI: From 5146fe62483e7343cd257bb384f767d6946de2d6 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 18 Jun 2025 10:02:06 +1000 Subject: [PATCH 135/161] Fix comment --- atomica/excel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/excel.py b/atomica/excel.py index 304490ab..c40f46dc 100644 --- a/atomica/excel.py +++ b/atomica/excel.py @@ -403,7 +403,7 @@ def __init__(self, code_name: str, full_name: str, tvec: np.array, from_pops: li self.ts = ts if ts is not None else sc.odict() self.attributes = {} #: Attributes associated with the table - self.ts_attributes = {} #: Attributes associated with each TimeSeries row. This is a dict-of-dicts with `ts_attributes[attribute]={pop:value}` e.g., ts_attributes["Provenance"] = {'popA': 'value', 'popB': 'value'} + self.ts_attributes = {} #: Attributes associated with each TimeSeries row. This is a dict-of-dicts with `ts_attributes[attribute]={(from_pop, to_pop):value}` e.g., `ts_attributes["Provenance"] = {('0-4', '5-14'): 'value'}` self.ts_attributes["Provenance"] = {} # Include provenance attribute by default self.assumption_heading = "Constant" #: Heading to use for assumption column From 9192dc10ff3864c0dda228c6c75f091421c0d1c4 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 18 Jun 2025 10:02:30 +1000 Subject: [PATCH 136/161] Adjust precision --- tests/test_tox_timed_compartments.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_tox_timed_compartments.py b/tests/test_tox_timed_compartments.py index c8db579f..1cd6e68a 100644 --- a/tests/test_tox_timed_compartments.py +++ b/tests/test_tox_timed_compartments.py @@ -55,6 +55,7 @@ def test_zero_duration(): P = get_project() ps = P.parsets[0].copy() ps.pars["nat_rec"].ts[0].insert(None, 0) # Sub-timestep size + P.settings.sim_dt = 1/24 # One of the tests had a numerical precision issue on just one platform, hard to reproduce but seeing if this avoids it res2 = P.run_sim(ps) d = at.PlotData(res2, [":inf", "inf:", "inf"]) at.plot_series(d) From ca9a4fdfd4de3be000beb3323de2d16abb17465a Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 18 Jun 2025 15:01:14 +1000 Subject: [PATCH 137/161] Update build/deploy commands --- azure-pipelines.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e2bf892e..c9cbc47a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -93,12 +93,9 @@ jobs: inputs: versionSpec: '3.12' - script: | - python -m pip install setuptools - python -m pip install wheel + python -m pip install build python -m pip install twine - python setup.py build - python setup.py sdist - python setup.py bdist_wheel + python -m build displayName: 'Build Atomica' - task: TwineAuthenticate@1 displayName: 'Twine Authenticate' @@ -106,4 +103,5 @@ jobs: pythonUploadServiceConnection: pypi_atomica - script: | python -m twine upload -r "pypi_atomica" --config-file $(PYPIRC_PATH) dist/* - displayName: 'Upload to PyPI' \ No newline at end of file + displayName: 'Upload to PyPI' + From 51545defb8452692f4d0485bb66148147126285c Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Thu, 26 Jun 2025 09:13:24 +1000 Subject: [PATCH 138/161] Fix issue with duplicate databook sheet names --- CHANGELOG.md | 4 ++++ atomica/data.py | 18 +++++++----------- atomica/version.py | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c07437c..70fd0a4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ This file records changes to the codebase grouped by version release. Unreleased changes are generally only present during development (relevant parts of the changelog can be written and saved in that section before a version number has been assigned) +## [1.31.2] - 2025-06-26 + +- Fix bug in creating databook if framework 'Databook pages' sheet contains multiple code names mapping to the same full name. + ## [1.31.1] - 2025-05-30 - Switched from `setup.py` to `pyproject.toml`-based installation. diff --git a/atomica/data.py b/atomica/data.py index 60763755..8b1f28c5 100644 --- a/atomica/data.py +++ b/atomica/data.py @@ -56,7 +56,7 @@ def __init__(self, framework): self.interpops = list() #: This stores a list of :class:`TimeDependentConnections` instances for interactions self.tvec = None #: This is the data's tvec used when instantiating new tables. Not _guaranteed_ to be the same for every TDVE/TDC table self.tdve = sc.odict() #: This is an odict storing :class:`TimeDependentValuesEntry` instances keyed by the code name of the TDVE - self.tdve_pages = sc.odict() #: This is an odict mapping worksheet name to an (ordered) list of TDVE code names appearing on that sheet + self.tdve_pages = sc.odict(defaultdict=list) #: This is an odict mapping worksheet name to an (ordered) list of TDVE code names appearing on that sheet # Internal storage used with methods while writing self._pop_types = list(framework.pop_types.keys()) #: Store set of valid population types from framework @@ -264,7 +264,7 @@ class instance (e.g. if creating a new databook). data = ProjectData(framework=framework) data.tvec = sc.promotetoarray(tvec) pages = defaultdict(list) # This will store {sheet_name:(code_name,databook_order)} which will then get sorted further - + page_names = framework.sheets["databook pages"][0].set_index('datasheet code name')['datasheet title'].to_dict() for obj_type, df in zip(["comps", "characs", "pars"], [framework.comps, framework.characs, framework.pars]): for _, spec in df.iterrows(): databook_page = spec.get("databook page") @@ -279,7 +279,7 @@ class instance (e.g. if creating a new databook). order = np.inf else: order = databook_order - pages[databook_page].append((spec.name, order)) + pages[page_names[databook_page]].append((spec.name, order)) data.tdve[spec.name] = TimeDependentValuesEntry(full_name, data.tvec, allowed_units=allowed_units, comment=spec["guidance"], pop_type=pop_type, default_all=default_all) data.tdve[spec.name].write_units = True data.tdve[spec.name].write_uncertainty = True @@ -294,14 +294,10 @@ class instance (e.g. if creating a new databook). # add_pop normally adds TDVE rows, but it won't operate on any TDVEs that default to 'All' so we need to add the 'All' rows here data.tdve[spec.name].ts["All"] = TimeSeries(units=allowed_units[0]) - # Now convert pages to full names and sort them into the correct order - for _, spec in framework.sheets["databook pages"][0].iterrows(): - - if spec["datasheet code name"] in pages: - pages[spec["datasheet code name"]].sort(key=lambda x: x[1]) - data.tdve_pages[spec["datasheet title"]] = [x[0] for x in pages[spec["datasheet code name"]]] - else: - data.tdve_pages[spec["datasheet title"]] = list() + # Now sort them into the correct order + for page, tables in pages.items(): + tables.sort(key=lambda x: x[1]) + data.tdve_pages[page] = [x[0] for x in tables] # Now, proceed to add pops, transfers, and interactions for code_name, spec in new_pops.items(): diff --git a/atomica/version.py b/atomica/version.py index 751f4d57..26dfd0e0 100644 --- a/atomica/version.py +++ b/atomica/version.py @@ -3,5 +3,5 @@ Standard location for module version number and date. """ -version = "1.31.1" -versiondate = "2025-05-30" +version = "1.31.2" +versiondate = "2025-06-26" From 8fe80dd2645a84f30684f6531172ebacce6dac65 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Fri, 27 Jun 2025 17:21:39 +1000 Subject: [PATCH 139/161] Proposed solution --- atomica/model.py | 52 +++++++++++++++++------- tests/framework_init_zero.xlsx | Bin 0 -> 31751 bytes tests/test_tox_zero_init.py | 70 +++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 15 deletions(-) create mode 100644 tests/framework_init_zero.xlsx create mode 100644 tests/test_tox_zero_init.py diff --git a/atomica/model.py b/atomica/model.py index 2e67badf..3f3e05d4 100644 --- a/atomica/model.py +++ b/atomica/model.py @@ -1861,27 +1861,48 @@ def initialize_compartments(self, parset: ParameterSet, framework, t_init: float # values for the compartments by solving the set of characteristics simultaneously # Build up the comps and characs containing the setup values in the databook - the `b` in `x=A*b` - characs_to_use = framework.characs.index[(framework.characs["setup weight"] > 0) & (framework.characs["population type"] == self.type)] - comps_to_use = framework.comps.index[(framework.comps["setup weight"] > 0) & (framework.comps["population type"] == self.type)] - b_objs = [self.charac_lookup[x] for x in characs_to_use] + [self.comp_lookup[x] for x in comps_to_use] + characs_to_use = set(framework.characs.index[(framework.characs["setup weight"] > 0) & (framework.characs["population type"] == self.type)]) + comps_to_use = set(framework.comps.index[(framework.comps["setup weight"] > 0) & (framework.comps["population type"] == self.type)]) + + b_vals = {} + b_objs = {} + + # First add all of the compartments that will be used from the databook + for comp in comps_to_use: + b_objs[comp] = self.comp_lookup[comp] + par = parset.pars[comp] + b_vals[comp] = par.interpolate(t_init, pop_name=self.name)[0] * par.y_factor[self.name] * par.meta_y_factor + + # Then add all of the characteristics, and additional zero compartments + for charac in characs_to_use: + obj = self.charac_lookup[charac] + b_objs[charac] = obj + par = parset.pars[charac] + b_vals[charac] = par.interpolate(t_init, pop_name=self.name)[0] * par.y_factor[self.name] * par.meta_y_factor + if b_vals[charac] == 0: + for comp in obj.get_included_comps(): + if comp.name in b_vals and b_vals[comp.name] != 0: + raise BadInitialization(f'Compartment {comp.name} was explicitly specified as having a non-zero value, but characteristic {charac} has a zero value - input data not consistent') + else: + b_vals[comp.name] = 0 + b_objs[comp.name] = comp + else: + if obj.denominator is not None: + denom_par = parset.pars[obj.denominator.name] + b_vals[charac] *= denom_par.interpolate(t_init, pop_name=self.name)[0] * denom_par.y_factor[self.name] * denom_par.meta_y_factor + # Build up the comps corresponding to the `x` values in `x=A*b` i.e. the compartments being solved for comps = [c for c in self.comps if not (isinstance(c, SourceCompartment) or isinstance(c, SinkCompartment))] - charac_indices = {c.name: i for i, c in enumerate(b_objs)} # Make lookup dict for characteristic indices + b_indices = {c.name: i for i, c in enumerate(b_objs.values())} # Make lookup dict for characteristic indices comp_indices = {c.name: i for i, c in enumerate(comps)} # Make lookup dict for compartment indices - b = np.zeros((len(b_objs), 1)) + b = np.fromiter(b_vals.values(),dtype=float).reshape(-1,1) A = np.zeros((len(b_objs), len(comps))) - # Construct the characteristic value vector (b) and the includes matrix (A) - for i, obj in enumerate(b_objs): - # Look up the characteristic value - par = parset.pars[obj.name] - b[i] = par.interpolate(t_init, pop_name=self.name)[0] * par.y_factor[self.name] * par.meta_y_factor + # Fill out the includes matrix (A) + for i, obj in enumerate(b_objs.values()): if isinstance(obj, Characteristic): - if obj.denominator is not None: - denom_par = parset.pars[obj.denominator.name] - b[i] *= denom_par.interpolate(t_init, pop_name=self.name)[0] * denom_par.y_factor[self.name] * denom_par.meta_y_factor for inc in obj.get_included_comps(): A[i, comp_indices[inc.name]] = 1.0 else: @@ -1889,6 +1910,7 @@ def initialize_compartments(self, parset: ParameterSet, framework, t_init: float # Solve the linear system (nb. lstsq returns the minimum norm solution x = np.linalg.lstsq(A, b.ravel(), rcond=None)[0].reshape(-1, 1) + proposed = np.matmul(A, x) residual = np.sum((proposed.ravel() - b.ravel()) ** 2) @@ -1922,8 +1944,8 @@ def report_characteristic(charac, n_indent=0): """ msg = "" - if charac.name in charac_indices: - msg += n_indent * "\t" + "Characteristic '{0}': Target value = {1}\n".format(charac.name, b[charac_indices[charac.name]]) + if charac.name in b_indices: + msg += n_indent * "\t" + "Characteristic '{0}': Target value = {1}\n".format(charac.name, b[b_indices[charac.name]]) else: msg += n_indent * "\t" + "Characteristic '{0}' not in databook: Target value = N/A (0.0)\n".format(charac.name) diff --git a/tests/framework_init_zero.xlsx b/tests/framework_init_zero.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5521fa1ea5281d593bf47416b256f210a8d3e927 GIT binary patch literal 31751 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 KX*m7*?SBCrRy@T3 literal 0 HcmV?d00001 diff --git a/tests/test_tox_zero_init.py b/tests/test_tox_zero_init.py new file mode 100644 index 00000000..8ded6b58 --- /dev/null +++ b/tests/test_tox_zero_init.py @@ -0,0 +1,70 @@ +# Test frameworks with no compartments/characteristics to ensure that +# they are initialized as 0 correctly + +import atomica as at +import numpy as np +from numpy.testing import assert_allclose +import pytest + +testdir = at.parent_dir() +tmpdir = testdir / "temp" + + +def _run_framework(fname): + F = at.ProjectFramework(testdir / fname) + D = at.ProjectData.new(F, [2020], 1, 0) + P = at.Project(framework=F, databook=D, do_run=False) + P.settings.update_time_vector(dt=1) + res = P.run_sim() + return res + + +def test_shortcut_init_1(): + res = _run_framework("test_shortcut_init_framework_1.xlsx") + print(res) + + # With no shortcut initialization for infected, 40 people get assigned to it, which flow downstream to R and D + assert_allclose(res.get_variable("s")[0].vals[0], 40) + assert_allclose(res.get_variable("i")[0].vals[0], 0) + assert_allclose(res.get_variable("r")[0].vals[0], 60) + assert_allclose(res.get_variable("d")[0].vals[0], 20) + + +def test_shortcut_init_2(): + res = _run_framework("test_shortcut_init_framework_2.xlsx") + + # With 0 shortcut initialization for infected, 0 people get assigned to it, so we have an even split + assert_allclose(res.get_variable("s")[0].vals[0], 60) + assert_allclose(res.get_variable("i")[0].vals[0], 0) + assert_allclose(res.get_variable("r")[0].vals[0], 60) + assert_allclose(res.get_variable("d")[0].vals[0], 0) + + +def test_shortcut_init_3(): + # With a nonzero shortcut initialization, an error should occur + with pytest.raises(at.InvalidFramework): + _run_framework("test_shortcut_init_framework_3.xlsx") + + +def test_shortcut_init_4(): + res = _run_framework("test_shortcut_init_framework_4.xlsx") + + # With 0 shortcut initialization for infected, 0 people get assigned to it, so we have an even split + assert_allclose(res.get_variable("s")[0].vals[0], 60) + assert_allclose(res.get_variable("i")[0].vals[0], 0) + assert_allclose(res.get_variable("r")[0].vals[0], 60) + assert_allclose(res.get_variable("d")[0].vals[0], 0) + + +def test_shortcut_init_5(): + # With a nonzero shortcut initialization, an error should occur + with pytest.raises(at.InvalidFramework): + _run_framework("test_shortcut_init_framework_5.xlsx") + + +if __name__ == "__main__": + test_shortcut_init_1() + test_shortcut_init_2() + test_shortcut_init_3() + test_shortcut_init_4() + test_shortcut_init_5() From 865a5e18b2bb05c63bbafff3b0b24a7e58f60ceb Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Fri, 27 Jun 2025 17:22:02 +1000 Subject: [PATCH 140/161] Add a test (although overall suite doesn't pass yet) --- tests/framework_init_zero.xlsx | Bin 31751 -> 31855 bytes tests/test_tox_zero_init.py | 57 +++------------------------------ 2 files changed, 5 insertions(+), 52 deletions(-) diff --git a/tests/framework_init_zero.xlsx b/tests/framework_init_zero.xlsx index 5521fa1ea5281d593bf47416b256f210a8d3e927..b7409836d6f3b795a09450883a8f9649009201b9 100644 GIT binary patch delta 14961 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

    yl)jKC&O;(I43l+_6;Hn{_Hv#*y{ygu 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 CkeYu0 diff --git a/tests/test_tox_zero_init.py b/tests/test_tox_zero_init.py index 8ded6b58..c9ca9956 100644 --- a/tests/test_tox_zero_init.py +++ b/tests/test_tox_zero_init.py @@ -1,5 +1,4 @@ -# Test frameworks with no compartments/characteristics to ensure that -# they are initialized as 0 correctly +# Test frameworks where characteristics with zero values get extra initialization conditions for constituent compartments import atomica as at import numpy as np @@ -10,61 +9,15 @@ tmpdir = testdir / "temp" -def _run_framework(fname): - F = at.ProjectFramework(testdir / fname) +def test_zero_initialization(): + F = at.ProjectFramework(testdir / "framework_init_zero.xlsx") D = at.ProjectData.new(F, [2020], 1, 0) P = at.Project(framework=F, databook=D, do_run=False) - P.settings.update_time_vector(dt=1) + P.settings.update_time_vector(start=2020 ,end=2021, dt=1) res = P.run_sim() return res -def test_shortcut_init_1(): - res = _run_framework("test_shortcut_init_framework_1.xlsx") - print(res) - - # With no shortcut initialization for infected, 40 people get assigned to it, which flow downstream to R and D - assert_allclose(res.get_variable("s")[0].vals[0], 40) - assert_allclose(res.get_variable("i")[0].vals[0], 0) - assert_allclose(res.get_variable("r")[0].vals[0], 60) - assert_allclose(res.get_variable("d")[0].vals[0], 20) - - -def test_shortcut_init_2(): - res = _run_framework("test_shortcut_init_framework_2.xlsx") - - # With 0 shortcut initialization for infected, 0 people get assigned to it, so we have an even split - assert_allclose(res.get_variable("s")[0].vals[0], 60) - assert_allclose(res.get_variable("i")[0].vals[0], 0) - assert_allclose(res.get_variable("r")[0].vals[0], 60) - assert_allclose(res.get_variable("d")[0].vals[0], 0) - - -def test_shortcut_init_3(): - # With a nonzero shortcut initialization, an error should occur - with pytest.raises(at.InvalidFramework): - _run_framework("test_shortcut_init_framework_3.xlsx") - - -def test_shortcut_init_4(): - res = _run_framework("test_shortcut_init_framework_4.xlsx") - - # With 0 shortcut initialization for infected, 0 people get assigned to it, so we have an even split - assert_allclose(res.get_variable("s")[0].vals[0], 60) - assert_allclose(res.get_variable("i")[0].vals[0], 0) - assert_allclose(res.get_variable("r")[0].vals[0], 60) - assert_allclose(res.get_variable("d")[0].vals[0], 0) - - -def test_shortcut_init_5(): - # With a nonzero shortcut initialization, an error should occur - with pytest.raises(at.InvalidFramework): - _run_framework("test_shortcut_init_framework_5.xlsx") - if __name__ == "__main__": - test_shortcut_init_1() - test_shortcut_init_2() - test_shortcut_init_3() - test_shortcut_init_4() - test_shortcut_init_5() + test_zero_initialization() From f634cc1c1bbea1bc3339179b2a232372aee72ba3 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Sat, 28 Jun 2025 01:58:22 +1000 Subject: [PATCH 141/161] Fix error message --- atomica/model.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atomica/model.py b/atomica/model.py index 3f3e05d4..78edddca 100644 --- a/atomica/model.py +++ b/atomica/model.py @@ -1920,10 +1920,10 @@ def initialize_compartments(self, parset: ParameterSet, framework, t_init: float characteristic_tolerence_failed = False # Print warning for characteristics that are not well matched by the compartment size solution - for i in range(0, len(b_objs)): + for i, obj in enumerate(b_objs.values()): if abs(proposed[i] - b[i]) > model_settings["tolerance"]: characteristic_tolerence_failed = True - error_msg += "Characteristic '{0}' '{1}' - Requested {2}, Calculated {3}\n".format(self.name, b_objs[i].name, b[i], proposed[i]) + error_msg += "Characteristic '{0}' '{1}' - Requested {2}, Calculated {3}\n".format(self.name, obj.name, b[i], proposed[i]) # Print expanded diagnostic for negative compartments showing parent characteristics def report_characteristic(charac, n_indent=0): From d23d05a847b3b61d8d46f3b07ad98bee8f4b53bb Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Sat, 28 Jun 2025 03:35:58 +1000 Subject: [PATCH 142/161] Improve message --- atomica/model.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atomica/model.py b/atomica/model.py index 78edddca..aadab773 100644 --- a/atomica/model.py +++ b/atomica/model.py @@ -1880,6 +1880,7 @@ def initialize_compartments(self, parset: ParameterSet, framework, t_init: float par = parset.pars[charac] b_vals[charac] = par.interpolate(t_init, pop_name=self.name)[0] * par.y_factor[self.name] * par.meta_y_factor if b_vals[charac] == 0: + logger.debug(f'Characteristic {charac} has a zero value, adding extra zero compartments') for comp in obj.get_included_comps(): if comp.name in b_vals and b_vals[comp.name] != 0: raise BadInitialization(f'Compartment {comp.name} was explicitly specified as having a non-zero value, but characteristic {charac} has a zero value - input data not consistent') @@ -1923,7 +1924,7 @@ def initialize_compartments(self, parset: ParameterSet, framework, t_init: float for i, obj in enumerate(b_objs.values()): if abs(proposed[i] - b[i]) > model_settings["tolerance"]: characteristic_tolerence_failed = True - error_msg += "Characteristic '{0}' '{1}' - Requested {2}, Calculated {3}\n".format(self.name, obj.name, b[i], proposed[i]) + error_msg += f"{obj.__class__.__name__} '{obj.name}' ({self.name})- Requested {b[i]}, Calculated {proposed[i]}\n" # Print expanded diagnostic for negative compartments showing parent characteristics def report_characteristic(charac, n_indent=0): From e083bdcf14e4f7857de0a4a61f9b34dc0da13276 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 30 Jun 2025 15:49:38 +1000 Subject: [PATCH 143/161] Improve comment --- atomica/data.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/atomica/data.py b/atomica/data.py index 8b1f28c5..2ecf0713 100644 --- a/atomica/data.py +++ b/atomica/data.py @@ -170,7 +170,12 @@ def get_ts(self, name: str, key=None): is therefore encountered on the :class:`Result` and plotting side. If retrieving values for a comp/charac/par and the databook contains an entry for 'all' rather - than specific populations, then the 'all' time series will be returned regardless of the key + than specific populations, then the 'all' time series will be returned if the key does not match + any population names. + + Note that the TDVE can contain time series for population names that don't correspond to actual populations. + For example, users could add an extra row for 'Total', or anything else. `get_ts()` will retrieve these + rows without an error, so population names are not validated against the populations in the databook. """ # Exit immediately if the name is not specified From c7d96f2cda5e51f72d3e3b05fd9b08aeed821412 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Tue, 8 Jul 2025 07:39:06 +1000 Subject: [PATCH 144/161] Resolve numpy deprecation warning (plus it's a fraction faster too) --- atomica/model.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/atomica/model.py b/atomica/model.py index aadab773..2c4f66b4 100644 --- a/atomica/model.py +++ b/atomica/model.py @@ -602,7 +602,7 @@ def balance(self, ti: int) -> None: if self.duration_group: link._vals[:, ti] = flow else: - link.vals[ti] = flow + link.vals[ti] = flow[0] def initial_flush(self) -> None: """ @@ -1986,7 +1986,7 @@ def report_characteristic(charac, n_indent=0): # Otherwise, insert the values for i, c in enumerate(comps): - c[0] = max(0.0, x[i]) + c[0] = max(0.0, x[i,0]) class Model: @@ -2662,7 +2662,7 @@ def update_pars(self) -> None: for par, val in zip(pars, par_vals): if par.skip_function is None or (self.t[ti] < par.skip_function[0]) or (self.t[ti] > par.skip_function[1]): # Careful - note how the < here matches >= in Parameter.update() - par[ti] = par.scale_factor * val + par[ti] = par.scale_factor * val[0] # Restrict the parameter's value if a limiting range was defined for par in pars: From 3a177cb19985dab7f4b2b49681078028f791d3ab Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 9 Jul 2025 06:27:19 +1000 Subject: [PATCH 145/161] Add function to clear TimeSeries objects --- atomica/utils.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/atomica/utils.py b/atomica/utils.py index eb7bb3d8..eb1db16b 100644 --- a/atomica/utils.py +++ b/atomica/utils.py @@ -624,6 +624,22 @@ def sample(self, constant=True): return new + def clear(self) -> None: + """ + Clear the TimeSeries + + This method resets TimeSeries but keeps the units present, so it is useful when + wanting to replace the values associated with a particular TimeSeries instance. + + :return: None + """ + + self.t = [] + self.vals = [] + self.assumption = None + self.sigma = None + self._sampled = False + return None def evaluate_plot_string(plot_string: str): """ From 62207d5c4abdba39a5ac2fc21d8231d84b75ed23 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 14 Jul 2025 15:47:20 +1000 Subject: [PATCH 146/161] Add separate initialization tolerance --- CHANGELOG.md | 11 +++++++++++ atomica/model.py | 11 ++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 70fd0a4c..9cec3373 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ This file records changes to the codebase grouped by version release. Unreleased changes are generally only present during development (relevant parts of the changelog can be written and saved in that section before a version number has been assigned) +## [1.31.3] - 2025-XX-XX + +- Changed initialization method to increase prioritization for characteristics with zero value. If a characteristic has a zero value, this will now automatically add extra constraints that all constitutent compartments should also be zero. In practice, this means that it is less likely that frameworks will cause negative initial popsizes, so some frameworks that previously did not work will now initialize correctly. +- Added `at.TimeSeries.clear()` to reset a time series while preserving the units. This function can be useful when updating the value of databook quantities programatically. +- Added a separate numerical tolerance used for initialization (`at.model.model_settings['initialization_tolerance']`) which permits more approximate initializations while still maintaining the same numerical tolerance for the rest of the integration. + +- *Backwards-compatibility notes* + +- Some initializations might show numerical (e.g., `1e-10`) differences in their values due to the new algorithm. In a small number of cases (depending on the framework), it is possible that the updated initialization method could result in a slightly different initialization. +- The default initialization tolerance is now `1e-3` instead of `1e-6`, some models that previously raised a `BadInitialization` error will now run without error. Users should note that if it's necessary to guarantee an exact initialization, this tolerance should be reduced. + ## [1.31.2] - 2025-06-26 - Fix bug in creating databook if framework 'Databook pages' sheet contains multiple code names mapping to the same full name. diff --git a/atomica/model.py b/atomica/model.py index 2c4f66b4..2bad544b 100644 --- a/atomica/model.py +++ b/atomica/model.py @@ -26,6 +26,7 @@ model_settings = dict() model_settings["tolerance"] = 1e-6 +model_settings["initialization_tolerance"] = 1e-3 __all__ = [ "BadInitialization", @@ -1922,7 +1923,7 @@ def initialize_compartments(self, parset: ParameterSet, framework, t_init: float # Print warning for characteristics that are not well matched by the compartment size solution for i, obj in enumerate(b_objs.values()): - if abs(proposed[i] - b[i]) > model_settings["tolerance"]: + if abs(proposed[i] - b[i]) > model_settings["initialization_tolerance"]: characteristic_tolerence_failed = True error_msg += f"{obj.__class__.__name__} '{obj.name}' ({self.name})- Requested {b[i]}, Calculated {proposed[i]}\n" @@ -1960,7 +1961,7 @@ def report_characteristic(charac, n_indent=0): return msg for i in range(0, len(comps)): - if x[i] < -model_settings["tolerance"]: + if x[i] < -model_settings["initialization_tolerance"]: error_msg += "Compartment %s %s - Calculated %f\n" % (self.name, comps[i].name, x[i]) for charac in b_objs: try: @@ -1970,10 +1971,10 @@ def report_characteristic(charac, n_indent=0): if comps[i] == charac: error_msg += report_characteristic(charac) - if residual > model_settings["tolerance"]: + if residual > model_settings["initialization_tolerance"]: # Halt for an unsatisfactory overall solution - raise BadInitialization("Global residual was %g which is unacceptably large (should be < %g)\n%s" % (residual, model_settings["tolerance"], error_msg)) - elif np.any(np.less(x, -model_settings["tolerance"])): + raise BadInitialization("Global residual was %g which is unacceptably large (should be < %g)\n%s" % (residual, model_settings["initialization_tolerance"], error_msg)) + elif np.any(np.less(x, -model_settings["initialization_tolerance"])): # Halt for any negative popsizes raise BadInitialization(f"Negative initial popsizes:\n{error_msg}") elif characteristic_tolerence_failed: From fa31a9df96bec097c7dd097e3ff38b77f4919f17 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 14 Jul 2025 15:47:33 +1000 Subject: [PATCH 147/161] Improve error message --- atomica/plotting.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/atomica/plotting.py b/atomica/plotting.py index 1931b996..49b4563e 100644 --- a/atomica/plotting.py +++ b/atomica/plotting.py @@ -288,7 +288,10 @@ def __init__(self, results, outputs=None, pops=None, output_aggregation=None, po vars = pop.get_variable(output_label) except NotFoundError as e: in_pops = [x.name for x in result.model.pops if output_label in x] - message = f'Variable "{output_label}" was requested in population "{pop.name}" but it is only defined in these populations: {in_pops}' + if not in_pops: + message = f'Variable "{output_label}" was requested in population "{pop.name}" but it is not defined in any populations' + else: + message = f'Variable "{output_label}" was requested in population "{pop.name}" but it is only defined in these populations: {in_pops}' raise NotFoundError(message) from e if vars[0].vals is None: From 450375724370240842baa5ed3a9ba4b38520c773 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 14 Jul 2025 15:47:46 +1000 Subject: [PATCH 148/161] Switch to more recent numpy function --- atomica/plotting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/plotting.py b/atomica/plotting.py index 49b4563e..5749feab 100644 --- a/atomica/plotting.py +++ b/atomica/plotting.py @@ -698,7 +698,7 @@ def time_aggregate(self, t_bins, time_aggregation=None, interpolation_method=Non v2 = np.interp(t2, s.tvec, s.vals, left=np.nan, right=np.nan) # Return NaN outside bounds - it should never be valid to use extrapolated output values in time aggregation else: v2 = s.vals[idx] - vals[i] = np.trapz(y=v2 / scale, x=t2) # Note division by timescale here, which annualizes it + vals[i] = np.trapezoid(y=v2 / scale, x=t2) # Note division by timescale here, which annualizes it elif interpolation_method == "previous": if interpolate: v2 = scipy.interpolate.interp1d(s.tvec, s.vals, kind="previous", copy=False, assume_sorted=True, bounds_error=False, fill_value=(np.nan, np.nan))(t2) From 5a85b7f6d17a85888626498412dc361d6024f463 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 21 Jul 2025 16:57:11 +1000 Subject: [PATCH 149/161] Add additional logging level --- CHANGELOG.md | 1 + atomica/__init__.py | 15 +++++++++------ atomica/utils.py | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cec3373..78d6e3fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This file records changes to the codebase grouped by version release. Unreleased - Changed initialization method to increase prioritization for characteristics with zero value. If a characteristic has a zero value, this will now automatically add extra constraints that all constitutent compartments should also be zero. In practice, this means that it is less likely that frameworks will cause negative initial popsizes, so some frameworks that previously did not work will now initialize correctly. - Added `at.TimeSeries.clear()` to reset a time series while preserving the units. This function can be useful when updating the value of databook quantities programatically. - Added a separate numerical tolerance used for initialization (`at.model.model_settings['initialization_tolerance']`) which permits more approximate initializations while still maintaining the same numerical tolerance for the rest of the integration. +- Added another logging level (`at.VERBOSE`) which enables more targeted additional output - *Backwards-compatibility notes* diff --git a/atomica/__init__.py b/atomica/__init__.py index a1f7b482..efcf58d0 100644 --- a/atomica/__init__.py +++ b/atomica/__init__.py @@ -26,7 +26,10 @@ import sys import logging +VERBOSE = 15 +logging.addLevelName(VERBOSE, "VERBOSE") logger = logging.getLogger("atomica") +logging.Logger.verbose = lambda self, msg, *args, **kwargs: self.log(VERBOSE, msg, *args, **kwargs) if not logger.handlers: # Only add handlers if they don't already exist in the module-level logger @@ -34,16 +37,16 @@ # prior to importing Atomica, and the user's custom logger won't be overwritten as long as it has # at least one handler already added. The use case was originally to suppress messages on import, but since # importing is silent now, it doesn't matter so much. - debug_handler = logging.StreamHandler(sys.stdout) # info_handler will handle all messages below WARNING sending them to STDOUT - info_handler = logging.StreamHandler(sys.stdout) # info_handler will handle all messages below WARNING sending them to STDOUT + debug_handler = logging.StreamHandler(sys.stdout) # handle all messages below WARNING sending them to STDOUT + info_handler = logging.StreamHandler(sys.stdout) # handle all messages below WARNING sending them to STDOUT warning_handler = logging.StreamHandler(sys.stderr) # warning_handler will send all messages at or above WARNING to STDERR - debug_handler.setLevel(0) # Handle all lower levels - the output should be filtered further by setting the logger level, not the handler level - info_handler.setLevel(logging.INFO) # Handle all lower levels - the output should be filtered further by setting the logger level, not the handler level + debug_handler.setLevel(0) # Handle all levels - the output is then filtered further by setting the logger level, not the handler level + info_handler.setLevel(logging.INFO) # Handle levels INFO or higher warning_handler.setLevel(logging.WARNING) - debug_handler.addFilter(type("ThresholdFilter", (object,), {"filter": lambda x, logRecord: logRecord.levelno < logging.INFO})()) # Display anything INFO or higher - info_handler.addFilter(type("ThresholdFilter", (object,), {"filter": lambda x, logRecord: logRecord.levelno < logging.WARNING})()) # Don't display WARNING or higher + debug_handler.addFilter(type("ThresholdFilter", (object,), {"filter": lambda x, logRecord: logRecord.levelno < logging.INFO})()) # Display only messages below the INFO level + info_handler.addFilter(type("ThresholdFilter", (object,), {"filter": lambda x, logRecord: logRecord.levelno < logging.WARNING})()) # Display only messages below WARNING (the info_handler level already rejects anything below INFO) warning_formatter = logging.Formatter("%(levelname)s {%(filename)s:%(lineno)d} - %(message)s") warning_handler.setFormatter(warning_formatter) diff --git a/atomica/utils.py b/atomica/utils.py index eb1db16b..21a1a345 100644 --- a/atomica/utils.py +++ b/atomica/utils.py @@ -1003,7 +1003,7 @@ def stop_logging() -> None: def get_sigfigs_necessary(x, y, min_sigfigs: int = 2) -> int: """ - Get how many significant figures are necessary to tell the difference berween two numbers + Get how many significant figures are necessary to tell the difference between two numbers :param x, y: numbers to compare :param min_sigfigs: minimum number of sigfigs to use if no difference From 16efa1eb6e245b8023ebd8a51fd572c97c4d607b Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 11 Aug 2025 11:33:06 +1000 Subject: [PATCH 150/161] Update initialization method to enforce zero compartments by omitting them from the initialization --- CHANGELOG.md | 4 +-- atomica/model.py | 43 +++++++++++++++++++--------- atomica/version.py | 4 +-- tests/test_tox_timed_compartments.py | 21 ++++---------- 4 files changed, 38 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78d6e3fe..f73acaec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,9 @@ This file records changes to the codebase grouped by version release. Unreleased changes are generally only present during development (relevant parts of the changelog can be written and saved in that section before a version number has been assigned) -## [1.31.3] - 2025-XX-XX +## [1.31.3] - 2025-08-11 -- Changed initialization method to increase prioritization for characteristics with zero value. If a characteristic has a zero value, this will now automatically add extra constraints that all constitutent compartments should also be zero. In practice, this means that it is less likely that frameworks will cause negative initial popsizes, so some frameworks that previously did not work will now initialize correctly. +- Changed initialization method to increase prioritization for characteristics with zero value. If a characteristic has a zero value, this will now automatically force included compartments to have a zero value. In practice, this means that it is less likely that frameworks will cause negative initial popsizes, so some frameworks that previously did not work will now initialize correctly. - Added `at.TimeSeries.clear()` to reset a time series while preserving the units. This function can be useful when updating the value of databook quantities programatically. - Added a separate numerical tolerance used for initialization (`at.model.model_settings['initialization_tolerance']`) which permits more approximate initializations while still maintaining the same numerical tolerance for the rest of the integration. - Added another logging level (`at.VERBOSE`) which enables more targeted additional output diff --git a/atomica/model.py b/atomica/model.py index 2bad544b..3a354ff9 100644 --- a/atomica/model.py +++ b/atomica/model.py @@ -1869,33 +1869,41 @@ def initialize_compartments(self, parset: ParameterSet, framework, t_init: float b_objs = {} # First add all of the compartments that will be used from the databook + zero_compartments = set() # Keep track of compartments that will be initialized as zero for comp in comps_to_use: - b_objs[comp] = self.comp_lookup[comp] par = parset.pars[comp] - b_vals[comp] = par.interpolate(t_init, pop_name=self.name)[0] * par.y_factor[self.name] * par.meta_y_factor + val = par.interpolate(t_init, pop_name=self.name)[0] * par.y_factor[self.name] * par.meta_y_factor + obj = self.comp_lookup[comp] + if val == 0: + zero_compartments.add(obj) + else: + b_objs[comp] = obj + b_vals[comp] = val - # Then add all of the characteristics, and additional zero compartments + # Then add all of the characteristics for charac in characs_to_use: - obj = self.charac_lookup[charac] - b_objs[charac] = obj par = parset.pars[charac] - b_vals[charac] = par.interpolate(t_init, pop_name=self.name)[0] * par.y_factor[self.name] * par.meta_y_factor - if b_vals[charac] == 0: - logger.debug(f'Characteristic {charac} has a zero value, adding extra zero compartments') + val = par.interpolate(t_init, pop_name=self.name)[0] * par.y_factor[self.name] * par.meta_y_factor + obj = self.charac_lookup[charac] + if val == 0: + # If the characteristic is zero, then all of the compartments included in it must also be zero for comp in obj.get_included_comps(): - if comp.name in b_vals and b_vals[comp.name] != 0: + if comp.name in b_vals: + # If a separate databook entry just for this compartment says the compartment should be non-zero, then we have two essentially equally + # direct specifications for the compartment. In that case, we should raise an error as the user has explicitly specified contradictory values raise BadInitialization(f'Compartment {comp.name} was explicitly specified as having a non-zero value, but characteristic {charac} has a zero value - input data not consistent') else: - b_vals[comp.name] = 0 - b_objs[comp.name] = comp + zero_compartments.add(comp) else: + b_objs[charac] = obj + b_vals[charac] = val if obj.denominator is not None: denom_par = parset.pars[obj.denominator.name] b_vals[charac] *= denom_par.interpolate(t_init, pop_name=self.name)[0] * denom_par.y_factor[self.name] * denom_par.meta_y_factor # Build up the comps corresponding to the `x` values in `x=A*b` i.e. the compartments being solved for - comps = [c for c in self.comps if not (isinstance(c, SourceCompartment) or isinstance(c, SinkCompartment))] + comps = [c for c in self.comps if not (isinstance(c, SourceCompartment) or isinstance(c, SinkCompartment) or c in zero_compartments)] b_indices = {c.name: i for i, c in enumerate(b_objs.values())} # Make lookup dict for characteristic indices comp_indices = {c.name: i for i, c in enumerate(comps)} # Make lookup dict for compartment indices @@ -1906,7 +1914,8 @@ def initialize_compartments(self, parset: ParameterSet, framework, t_init: float for i, obj in enumerate(b_objs.values()): if isinstance(obj, Characteristic): for inc in obj.get_included_comps(): - A[i, comp_indices[inc.name]] = 1.0 + if inc not in zero_compartments: + A[i, comp_indices[inc.name]] = 1.0 else: A[i, comp_indices[obj.name]] = 1.0 @@ -1956,6 +1965,8 @@ def report_characteristic(charac, n_indent=0): for inc in charac.includes: if isinstance(inc, Characteristic): msg += report_characteristic(inc, n_indent) + elif inc in zero_compartments: + msg += n_indent * "\t" + "Compartment %s: Preassigned value = 0.0\n" % (inc.name) else: msg += n_indent * "\t" + "Compartment %s: Computed value = %f\n" % (inc.name, x[comp_indices[inc.name]]) return msg @@ -1985,7 +1996,11 @@ def report_characteristic(charac, n_indent=0): # (but it exists as a fallback to ensure that any inconsistencies result in the error being raised) raise BadInitialization(f"Initialization error\n{error_msg}") - # Otherwise, insert the values + # Initialize any compartments that were specified as zero + for c in zero_compartments: + c[0] = 0.0 + + # Insert the calculated initial values for i, c in enumerate(comps): c[0] = max(0.0, x[i,0]) diff --git a/atomica/version.py b/atomica/version.py index 26dfd0e0..560edd03 100644 --- a/atomica/version.py +++ b/atomica/version.py @@ -3,5 +3,5 @@ Standard location for module version number and date. """ -version = "1.31.2" -versiondate = "2025-06-26" +version = "1.31.3" +versiondate = "2025-08-11" diff --git a/tests/test_tox_timed_compartments.py b/tests/test_tox_timed_compartments.py index 1cd6e68a..cf306ba1 100644 --- a/tests/test_tox_timed_compartments.py +++ b/tests/test_tox_timed_compartments.py @@ -2,19 +2,8 @@ import sciris as sc import os import pytest -import sys - -# # P = at.Project(framework='dummy_framework.xlsx',databook='dummy_databook.xlsx') -# # # P.run_sim() -# # P = at.demo('tb',do_run=True) -# # P.results[0].plot() -# # P = at.Project.load('asdf2.prj') -# -# # P = at.Project(framework=at.LIBRARY_PATH+'tb_framework.xlsx') -# # P.load_databook(at.LIBRARY_PATH+'tb_databook.xlsx') -# P = at.demo('tb',do_run=True) -# -# +import numpy as np + testdir = at.parent_dir() tmpdir = testdir / "temp" @@ -61,9 +50,9 @@ def test_zero_duration(): at.plot_series(d) pop = res2.model.pops[0] - assert pop.get_variable("foi")[0].vals[0] == 24 # Flow into the compartment - assert pop.get_variable("inf")[0].vals[1] == 24 * res2.dt # Compartment contents should now equal the inflow - assert pop.get_variable("inf")[0].vals[2] == 24 * res2.dt # Same again, contents equals the inflow because it was flushed entirely + assert np.isclose(pop.get_variable("foi")[0].vals[0], 24) # Flow into the compartment + assert np.isclose(pop.get_variable("inf")[0].vals[1], 24 * res2.dt) # Compartment contents should now equal the inflow + assert np.isclose(pop.get_variable("inf")[0].vals[2], 24 * res2.dt) # Same again, contents equals the inflow because it was flushed entirely # Check formally that total inflows equal total outflows assert pop.get_variable("inf")[0].vals[0] == sum(link.vals[0] for link in pop.get_variable("inf")[0].outlinks) From 41297ebd0dfbc3d1780127f6fdf01da31f050e51 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 11 Aug 2025 13:57:50 +1000 Subject: [PATCH 151/161] Switch pipeline to main --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c9cbc47a..5a918b58 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -3,7 +3,7 @@ schedules: displayName: Nightly build branches: include: - - master + - main - develop jobs: @@ -84,7 +84,7 @@ jobs: - job: 'deploy' dependsOn: 'tox' - condition: and(ne(variables['Build.Reason'], 'Schedule'),and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))) + condition: and(ne(variables['Build.Reason'], 'Schedule'),and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))) pool: vmImage: 'ubuntu-latest' steps: From 9af6d365b0c02ba9ccf837a826cbf5b7849a59f4 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 11 Aug 2025 14:37:28 +1000 Subject: [PATCH 152/161] Allow numerical differences --- tests/test_tox_frameworks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tox_frameworks.py b/tests/test_tox_frameworks.py index 303ee535..ccded5d8 100644 --- a/tests/test_tox_frameworks.py +++ b/tests/test_tox_frameworks.py @@ -56,7 +56,7 @@ def test_framework_single_char(): P.settings = P1.settings r2 = P.run_sim() - test_equal = lambda var1, var2: np.testing.assert_array_equal(r1.get_variable(var1)[0].vals, r2.get_variable(var2)[0].vals) + test_equal = lambda var1, var2: np.testing.assert_allclose(r1.get_variable(var1)[0].vals, r2.get_variable(var2)[0].vals) test_equal("sus", "s") test_equal("inf", "i") From 623feb8735b92e5786257346a5f6c6e03f8a95ad Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 28 Jan 2026 10:08:44 +1100 Subject: [PATCH 153/161] Changes for tests to pass with Pandas 3 --- atomica/framework.py | 6 +++--- atomica/model.py | 2 +- atomica/optimization.py | 2 +- atomica/reconciliation.py | 14 +++++++++----- atomica/utils.py | 9 ++++++++- azure-pipelines.yml | 4 ++-- tox.ini | 2 +- 7 files changed, 25 insertions(+), 14 deletions(-) diff --git a/atomica/framework.py b/atomica/framework.py index 76d13de1..cd378003 100644 --- a/atomica/framework.py +++ b/atomica/framework.py @@ -667,9 +667,9 @@ def _sanitize_compartments(self) -> None: self.comps["setup weight"] = ((~self.comps["databook page"].isna() | ~self.comps["default value"].isna()) & (self.comps["is source"] == "n") & (self.comps["is sink"] == "n")).astype(float) else: fill_ones = self.comps["setup weight"].isna() & (~self.comps["databook page"].isna() | ~self.comps["default value"].isna()) & (self.comps["is source"] == "n") & (self.comps["is sink"] == "n") + self.comps["setup weight"] = self.comps["setup weight"].astype(float) self.comps.loc[fill_ones, "setup weight"] = 1 self.comps.loc[self.comps["setup weight"].isna(), "setup weight"] = 0 - self.comps["setup weight"] = self.comps["setup weight"].astype(float) if "calibrate" not in self.comps: # If calibration column is not present, then it calibrate if in the databook @@ -750,9 +750,9 @@ def _sanitize_characteristics(self) -> None: self.characs["setup weight"] = (~self.characs["databook page"].isna() | ~self.characs["default value"].isna()).astype(float) else: fill_ones = self.characs["setup weight"].isna() & (~self.characs["databook page"].isna() | ~self.characs["default value"].isna()) + self.characs["setup weight"] = self.characs["setup weight"].astype(float) self.characs.loc[fill_ones, "setup weight"] = 1 self.characs.loc[self.characs["setup weight"].isna(), "setup weight"] = 0 - self.characs["setup weight"] = self.characs["setup weight"].astype(float) if "calibrate" not in self.characs: # If calibration column is not present, then it calibrate if in the databook @@ -903,7 +903,7 @@ def _sanitize_parameters(self) -> None: # If framework has units that case-insensitively match the standard units, then correct the case if not self.pars.empty: lower_idx = self.pars["format"].str.lower().isin(FS.STANDARD_UNITS) - self.pars["format"][lower_idx] = self.pars["format"][lower_idx].str.lower() + self.pars.loc[lower_idx, "format"] = self.pars.loc[lower_idx, "format"].str.lower() def _process_transitions(self) -> None: """ diff --git a/atomica/model.py b/atomica/model.py index 3a354ff9..59b2d145 100644 --- a/atomica/model.py +++ b/atomica/model.py @@ -1973,7 +1973,7 @@ def report_characteristic(charac, n_indent=0): for i in range(0, len(comps)): if x[i] < -model_settings["initialization_tolerance"]: - error_msg += "Compartment %s %s - Calculated %f\n" % (self.name, comps[i].name, x[i]) + error_msg += "Compartment %s %s - Calculated %f\n" % (self.name, comps[i].name, x[i,0]) for charac in b_objs: try: if comps[i] in charac.get_included_comps(): diff --git a/atomica/optimization.py b/atomica/optimization.py index f43319d0..556e597e 100644 --- a/atomica/optimization.py +++ b/atomica/optimization.py @@ -998,7 +998,7 @@ def get_hard_constraint(self, optimization, instructions: ProgramInstructions) - # Lastly, apply the budget factor if len(self.budget_factor) == 1: - hard_constraints["initial_total_spend"][t] = total_spend * self.budget_factor + hard_constraints["initial_total_spend"][t] = total_spend * self.budget_factor.item() else: hard_constraints["initial_total_spend"][t] = total_spend * self.budget_factor[idx] diff --git a/atomica/reconciliation.py b/atomica/reconciliation.py index e87f6e8e..e27627ea 100644 --- a/atomica/reconciliation.py +++ b/atomica/reconciliation.py @@ -161,7 +161,7 @@ def _objective(x, mapping, progset, eval_years, target_vals, num_eligible, dt): return obj -def _convert_to_single_year(progset, reconciliation_year): +def _convert_to_single_year(progset, reconciliation_year: float): # Take in a progset # Return a progset with values only in the reconciliation year # This is then what actually gets reconciled @@ -242,11 +242,15 @@ def reconcile(project, parset, progset, reconciliation_year: float, max_time=10, logger.warning("Reconcilation when parameter is in number units not fully tested") - reconciliation_year = sc.promotetoarray(reconciliation_year) - assert len(reconciliation_year) == 1, "Reconciliation year must be a scalar" + # Convert reconciliation year to a scalar + if hasattr(reconciliation_year, "__len__"): + if len(reconciliation_year) == 1: + reconciliation_year = reconciliation_year[0] + else: + raise ValueError("Reconciliation year must be a scalar") if eval_range is None: - eval_range = [reconciliation_year[0], reconciliation_year[0] + project.settings.sim_dt] + eval_range = [reconciliation_year, reconciliation_year + project.settings.sim_dt] # Do a prerun to get the baseline values and coverage denominator parset_results = project.run_sim(parset=parset, progset=progset, store_results=False) @@ -255,7 +259,7 @@ def reconcile(project, parset, progset, reconciliation_year: float, max_time=10, target_vals, num_eligible = _extract_targets(parset_results, progset, ti, eval_pars) # Prepare ASD inputs - new_progset = _convert_to_single_year(progset, reconciliation_year[0]) + new_progset = _convert_to_single_year(progset, reconciliation_year) bounds = _prepare_bounds(new_progset, unit_cost_bounds, baseline_bounds, capacity_bounds, outcome_bounds) # Convert reconcile() inputs into full detailed bounds x0, xmin, xmax, mapping = _prepare_asd_inputs(new_progset, bounds) # Assemble ASD variables diff --git a/atomica/utils.py b/atomica/utils.py index 21a1a345..335e0f72 100644 --- a/atomica/utils.py +++ b/atomica/utils.py @@ -377,8 +377,15 @@ def insert(self, t, v) -> None: :param v: Value to insert. If ``None``, this function will return immediately without doing anything """ + # TODO - could potentially incorporate iterability check above for greater efficiency + # TODO - add handling series inputs here too? + + # Convert 1-element lists/arrays to scalars + if hasattr(t, "__len__") and len(t) == 1: + t = t[0] + if hasattr(v, "__len__") and len(v) == 1: + v = v[0] - # Check if inputs are iterable iterable_input = True try: assert len(t) == len(v), "Cannot insert non-matching lengths or types of time and values %s and %s" % (t, v) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 5a918b58..ed2b192b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -9,8 +9,8 @@ schedules: jobs: - job: 'tox' variables: - python.version: '3.12' - TOXENV: 'py312' + python.version: '3.14' + TOXENV: 'py314' strategy: matrix: linux: diff --git a/tox.ini b/tox.ini index e3648053..889520bb 100644 --- a/tox.ini +++ b/tox.ini @@ -12,7 +12,7 @@ commands = pytest --nbsmoke-run {toxinidir} {posargs} [pytest] -addopts = -ra -v -n 2 --junitxml=junit/test-results.xml --color=no --cov=atomica --cov-report=xml --cov-report=html +addopts = -ra -v -n 2 --junitxml=junit/test-results.xml --color=no --cov=atomica --cov-report=xml --cov-report=html --log-level=DEBUG junit_family=xunit1 nbsmoke_cell_timeout = 600 console_output_style = count From b739bfdb5df6f583da93dd3c18ded6bd43d21553 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 28 Jan 2026 10:53:04 +1100 Subject: [PATCH 154/161] Fix deprecated ast.Str This class has now been replaced by ast.Constant encompassing all constant values. For simplicity, this check has been relaxed to accept any constant as this should offer an equivalent level of parsing safety (otherwise we could additionally check that the value was a string) --- atomica/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/utils.py b/atomica/utils.py index 335e0f72..c20dfd7c 100644 --- a/atomica/utils.py +++ b/atomica/utils.py @@ -680,7 +680,7 @@ def evaluate_plot_string(plot_string: str): fcn_ast = ast.parse(plot_string, mode="eval") for node in ast.walk(fcn_ast): if not (node is fcn_ast): - assert isinstance(node, ast.Dict) or isinstance(node, ast.Str) or isinstance(node, ast.List) or isinstance(node, ast.Load), "Only allowed to initialize lists and dicts of strings here" + assert isinstance(node, ast.Dict) or isinstance(node, ast.List) or isinstance(node, ast.Load) or isinstance(node, ast.Constant), "Only allowed to initialize lists and dicts of strings here" compiled_code = compile(fcn_ast, filename="", mode="eval") return eval(compiled_code) else: From 3ebab7391efd805c2c663070f042c4d1a7ff36cd Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Wed, 28 Jan 2026 10:55:42 +1100 Subject: [PATCH 155/161] Increment version --- CHANGELOG.md | 4 ++++ atomica/version.py | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f73acaec..bfec4729 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ This file records changes to the codebase grouped by version release. Unreleased changes are generally only present during development (relevant parts of the changelog can be written and saved in that section before a version number has been assigned) +## [1.31.4] - 2026-01-28 + +- Updated internal functions for Python 3.14 and Pandas 3.0.0 + ## [1.31.3] - 2025-08-11 - Changed initialization method to increase prioritization for characteristics with zero value. If a characteristic has a zero value, this will now automatically force included compartments to have a zero value. In practice, this means that it is less likely that frameworks will cause negative initial popsizes, so some frameworks that previously did not work will now initialize correctly. diff --git a/atomica/version.py b/atomica/version.py index 560edd03..3277ea6b 100644 --- a/atomica/version.py +++ b/atomica/version.py @@ -3,5 +3,5 @@ Standard location for module version number and date. """ -version = "1.31.3" -versiondate = "2025-08-11" +version = "1.31.4" +versiondate = "2026-01-28" From 684ebb42077c59088660f1d2bdc42edd778191a8 Mon Sep 17 00:00:00 2001 From: Cliff Kerr Date: Mon, 25 May 2026 08:55:01 -0400 Subject: [PATCH 156/161] Update pyswarm syntax and version --- atomica/optimization.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atomica/optimization.py b/atomica/optimization.py index 556e597e..a31aa34d 100644 --- a/atomica/optimization.py +++ b/atomica/optimization.py @@ -1452,7 +1452,7 @@ def optimize(project, optimization, parset: ParameterSet, progset: ProgramSet, i errormsg = "PSO optimization requires finite upper and lower bounds to specify the search domain (i.e. every Adjustable needs to have finite bounds)" raise Exception(errormsg) - x_opt, _ = pyswarm.pso(_objective_fcn, kwargs=args, **optim_args) + x_opt = pyswarm.pso(_objective_fcn, kwargs=args, **optim_args) elif optimization.method == "hyperopt": diff --git a/pyproject.toml b/pyproject.toml index af0cf1e5..9a444bc0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,7 @@ dependencies = [ "pandas", "xlsxwriter", "openpyxl", - "pyswarm", + "pyswarm>=1.0", "hyperopt", "sciris", "tqdm", From 22aef7353c282c1cf35e7aa87088191e04c8dacf Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Tue, 26 May 2026 09:44:10 +1000 Subject: [PATCH 157/161] Fix pyswarm.pso() call and update pyproject.toml --- atomica/optimization.py | 2 +- pyproject.toml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/atomica/optimization.py b/atomica/optimization.py index a31aa34d..0c6235f8 100644 --- a/atomica/optimization.py +++ b/atomica/optimization.py @@ -1452,7 +1452,7 @@ def optimize(project, optimization, parset: ParameterSet, progset: ProgramSet, i errormsg = "PSO optimization requires finite upper and lower bounds to specify the search domain (i.e. every Adjustable needs to have finite bounds)" raise Exception(errormsg) - x_opt = pyswarm.pso(_objective_fcn, kwargs=args, **optim_args) + x_opt = pyswarm.pso(_objective_fcn, kwargs=args, **optim_args).x elif optimization.method == "hyperopt": diff --git a/pyproject.toml b/pyproject.toml index 9a444bc0..e70c3c0f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ classifiers = [ "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13" ] -requires-python = ">=3.7" +requires-python = ">=3.10" dependencies = [ "matplotlib", @@ -37,7 +37,7 @@ dependencies = [ "pandas", "xlsxwriter", "openpyxl", - "pyswarm>=1.0", + "pyswarm", "hyperopt", "sciris", "tqdm", @@ -53,4 +53,4 @@ include-package-data = true where = ["."] [tool.setuptools.dynamic] -version = {attr = "atomica.version.version"} \ No newline at end of file +version = {attr = "atomica.version.version"} From 836f4815d888fe12b3957737517f7404f5da4c5b Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Tue, 26 May 2026 09:44:18 +1000 Subject: [PATCH 158/161] Increment version --- CHANGELOG.md | 5 +++++ atomica/version.py | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfec4729..44ecf4d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ This file records changes to the codebase grouped by version release. Unreleased changes are generally only present during development (relevant parts of the changelog can be written and saved in that section before a version number has been assigned) +## [1.31.5] - 2026-05-26 + +- Update optimization function for compatibility with latest `pyswarm` release +- Update minimum Python version to 3.10 as previous versions are deprecated + ## [1.31.4] - 2026-01-28 - Updated internal functions for Python 3.14 and Pandas 3.0.0 diff --git a/atomica/version.py b/atomica/version.py index 3277ea6b..fa7668d7 100644 --- a/atomica/version.py +++ b/atomica/version.py @@ -3,5 +3,5 @@ Standard location for module version number and date. """ -version = "1.31.4" -versiondate = "2026-01-28" +version = "1.31.5" +versiondate = "2026-05-26" From 4ce4337077111057f3f1dc64b74ff17473a9acb3 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Tue, 26 May 2026 09:56:07 +1000 Subject: [PATCH 159/161] Force pyswarm 1.0.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e70c3c0f..723895bb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,7 @@ dependencies = [ "pandas", "xlsxwriter", "openpyxl", - "pyswarm", + "pyswarm>=1.0.0", "hyperopt", "sciris", "tqdm", From e02a0546c73189ad7d3337c4d39dfd36f04caf3b Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Tue, 26 May 2026 10:10:56 +1000 Subject: [PATCH 160/161] Maintain compatibility as Mac OS is installing a different version --- atomica/optimization.py | 7 ++++++- pyproject.toml | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/atomica/optimization.py b/atomica/optimization.py index 0c6235f8..f872612c 100644 --- a/atomica/optimization.py +++ b/atomica/optimization.py @@ -1452,7 +1452,12 @@ def optimize(project, optimization, parset: ParameterSet, progset: ProgramSet, i errormsg = "PSO optimization requires finite upper and lower bounds to specify the search domain (i.e. every Adjustable needs to have finite bounds)" raise Exception(errormsg) - x_opt = pyswarm.pso(_objective_fcn, kwargs=args, **optim_args).x + if sc.compareversions(pyswarm, ">1.0.0"): + x_opt = pyswarm.pso(_objective_fcn, kwargs=args, **optim_args).x + else: + # On Mac OS, Pyswarm 1.0.0 is not installing yet. This can be revisited and hopefully + # removed once the incompatibility is resolved (possibly by switching to more recent UV pipeline) + x_opt, _ = pyswarm.pso(_objective_fcn, kwargs=args, **optim_args) elif optimization.method == "hyperopt": diff --git a/pyproject.toml b/pyproject.toml index 723895bb..e70c3c0f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,7 @@ dependencies = [ "pandas", "xlsxwriter", "openpyxl", - "pyswarm>=1.0.0", + "pyswarm", "hyperopt", "sciris", "tqdm", From b365b318f770f1cc0f58b2f4b7413a029b6db877 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Tue, 26 May 2026 10:23:29 +1000 Subject: [PATCH 161/161] Fix typo --- atomica/optimization.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomica/optimization.py b/atomica/optimization.py index f872612c..7620a87f 100644 --- a/atomica/optimization.py +++ b/atomica/optimization.py @@ -1452,7 +1452,7 @@ def optimize(project, optimization, parset: ParameterSet, progset: ProgramSet, i errormsg = "PSO optimization requires finite upper and lower bounds to specify the search domain (i.e. every Adjustable needs to have finite bounds)" raise Exception(errormsg) - if sc.compareversions(pyswarm, ">1.0.0"): + if sc.compareversions(pyswarm, ">=1.0.0"): x_opt = pyswarm.pso(_objective_fcn, kwargs=args, **optim_args).x else: # On Mac OS, Pyswarm 1.0.0 is not installing yet. This can be revisited and hopefully

    !M_5BFiS!}j1L+C;+QTT-fsx~;9w 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%0ACXf#^f#Xfo&V}~_l0xITswOf~wyrss%fSotC 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 From 9c9b456f76db261d810373945e43939acc46282d Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 17 Feb 2025 14:14:46 +1000 Subject: [PATCH 106/161] Resolve todos and fix links --- docs/general/YAML_calibration.ipynb | 7 ++-- .../tutorial/T7/T7_YAML_autocalibration.ipynb | 40 ++++++++----------- docs/tutorial/index.rst | 1 + 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/docs/general/YAML_calibration.ipynb b/docs/general/YAML_calibration.ipynb index bd8c7dab..027215e2 100644 --- a/docs/general/YAML_calibration.ipynb +++ b/docs/general/YAML_calibration.ipynb @@ -23,7 +23,7 @@ "source": [ "## YAML internal structure\n", "\n", - "The native representation of the YAML calibration is as a graph of 'nodes' where each node corresponds to either an action or a section containing other nodes. Each node has associated with it a collection of attributes/settings defined for that node (`instructions`), and a collection of attributes inherited from all parent nodes (`context`). The `atomica.yaml_calibration.build()` function takes in the content of the YAML file and loads it into a tree of `at.yaml_calibration.BaseNode` instances with a root node called 'calibration' at the top level. For example, consider the following YAML file:" + "The native representation of the YAML calibration is as a graph of 'nodes' where each node corresponds to either an action or a section containing other nodes. Each node has associated with it a collection of attributes/settings defined for that node (`instructions`), and a collection of attributes inherited from all parent nodes (`context`). The `atomica.yaml_calibration.build()` function takes in the content of the YAML file and loads it into a tree of `at.yaml_calibration.BaseNode` instances with a root node called 'calibration' at the top level. For example, consider the following YAML file from Tutorial 7:" ] }, { @@ -34,7 +34,8 @@ "outputs": [], "source": [ "import atomica as at\n", - "print(open('T7_YAML_3_repeats.yaml').read())" + "yaml_file = at.rootdir/'docs'/'tutorial'/'T7'/'calibrations'/'T7_YAML_3_repeats.yaml'\n", + "print(open(yaml_file).read())" ] }, { @@ -53,7 +54,7 @@ "outputs": [], "source": [ "import atomica.yaml_calibration \n", - "nodes = at.yaml_calibration.build('T7_YAML_3_repeats.yaml') \n", + "nodes = at.yaml_calibration.build(yaml_file) \n", "print(nodes)" ] }, diff --git a/docs/tutorial/T7/T7_YAML_autocalibration.ipynb b/docs/tutorial/T7/T7_YAML_autocalibration.ipynb index 0f2fbf22..ff2b517e 100644 --- a/docs/tutorial/T7/T7_YAML_autocalibration.ipynb +++ b/docs/tutorial/T7/T7_YAML_autocalibration.ipynb @@ -47,9 +47,7 @@ "source": [ "## Basic calibration example\n", "\n", - "In this tutorial, we will work with a simple version of a typhoid model. This model captures typhoid infections, as well as asymptomatic carriers and vaccination. Firstly, we need to create an Atomica `Project` by loading in the Framework and Databook files, just like we did in [the first atomica tutorial](https://atomica.tools/docs/master/tutorial/T1-Defining-a-model.html). The Framework and Databook for this project can be found in the Atomica repository under `assets/T7`. \n", - "\n", - "_TODO: Update paths when moved to Atomica repository_" + "In this tutorial, we will work with a simple version of a typhoid model. This model captures typhoid infections, as well as asymptomatic carriers and vaccination. Firstly, we need to create an Atomica `Project` by loading in the Framework and Databook files, just like we did in [the first Atomica tutorial](/tutorial/T1-Defining-a-model.html). The Framework and Databook for this project can be found in the Atomica repository under `assets/T7`. " ] }, { @@ -60,8 +58,8 @@ "outputs": [], "source": [ "import atomica as at\n", - "F = at.ProjectFramework('T7_framework.xlsx')\n", - "D = at.ProjectData.from_spreadsheet('T7_databook.xlsx', framework=F)\n", + "F = at.ProjectFramework('assets/T7_framework.xlsx')\n", + "D = at.ProjectData.from_spreadsheet('assets/T7_databook.xlsx', framework=F)\n", "P = at.Project(framework=F,databook=D, do_run=False)\n", "P.settings.update_time_vector(start=2000, end=2040, dt=1/52)" ] @@ -123,7 +121,7 @@ "\n", " calibrated_parset = P.calibrate(parset = cal, adjustables = ['b_rate', 'mig_rate'], measurables = 'alive')\n", "\n", - "Running the YAML calibration is very similar to performing a standalone auto-calibration. After saving the YAML file to disk (e.g. [T7_YAML_1_minimal.yaml](./<`T7_YAML_1_minimal`>.)), the calibration can be run using\n", + "Running the YAML calibration is very similar to performing a standalone auto-calibration. After saving the YAML file to disk (e.g., `T7_YAML_1_minimal.yaml`), the calibration can be run using\n", "\n", " calibrated_parset = P.calibrate(parset = cal, yaml='T7_YAML_1_minimal.yaml')\n", "\n", @@ -228,7 +226,7 @@ "source": [ "## Sections vs Actions\n", "\n", - "As shown above, sections can help us to structure the calibration in a way that is practical and intuitive. They can be used to group blocks of YAML code that are conceptually related, that we want to repeat together several times, or that we want to apply similar settings to (we will cover which settings are supported in [the corresponding section](#specifying-calibration-settings-in-outer-sections)). \n", + "As shown above, sections can help us to structure the calibration in a way that is practical and intuitive. They can be used to group blocks of YAML code that are conceptually related, that we want to repeat together several times, or that we want to apply similar settings to (we will cover which settings are supported in [the corresponding section](#specifying-settings-in-outer-sections). \n", "\n", "Importantly though, _sections_ do not modify the calibration itself – they are merely wrappers for the innermost blocks that actually correspond to specific actions. It is in these _actions_ that operations are performed on the calibration, such as modifying the calibration or saving it.\n", "\n", @@ -247,7 +245,7 @@ "outputs": [], "source": [ "import atomica.yaml_calibration \n", - "calibration_tree = at.yaml_calibration.build('T7_YAML_3_repeats.yaml') \n", + "calibration_tree = at.yaml_calibration.build('calibrations/T7_YAML_3_repeats.yaml') \n", "print(calibration_tree)" ] }, @@ -291,12 +289,12 @@ "\n", "- `meas_label` (required): Measurable parameter codename (can be found in the framework)\n", "- `pop_name`: Population to use for calibration (default: all populations)\n", - "- `weight`: Weight for a particular population (default: 1). By default, all populations are weighted equally regardless of size. See [the documentation on weights]((./YAML_documentation_page.ipynb#measurable-weights \"Measurable weights\") for further details.\n", + "- `weight`: Weight for a particular population (default: 1). By default, all populations are weighted equally regardless of size. See [the documentation on weights](/general/YAML_calibration.html#Measurable-Weights) for further details.\n", "- `metric`: Metric to be used by the optimisation algorithm (default: fractional)\n", "- `cal_start`: Starting year that the calibration will be evaluated from (default: `sim_start`)\n", "- `cal_end`: End year until which the calibration will be evaluated (default: `sim_end`)\n", "\n", - "Note that `sim_start` and `sim_end` are the start and end years that the simulation will run for (the simulation timespan). These are distinct from `cal_start` and `cal_end`, which specify the time period for which we want to calibrate the model, i.e. a subset of the simulation timespan. For more information, see the [section on outer settings](#specifying-calibration-settings-in-outer-sections). The `cal_start` and `cal_end` years can be set per measurable, so it is possible to prioritize different years for different variables or for different steps of the calibration. \n", + "Note that `sim_start` and `sim_end` are the start and end years that the simulation will run for (the simulation timespan). These are distinct from `cal_start` and `cal_end`, which specify the time period for which we want to calibrate the model, i.e. a subset of the simulation timespan. For more information, see the [section on outer settings](#specifying-settings-in-outer-sections). The `cal_start` and `cal_end` years can be set per measurable, so it is possible to prioritize different years for different variables or for different steps of the calibration. \n", "To specify these adjustables and measurables settings in the YAML file, we simply write the setting names and their values under the relevant parameter name. Each adjustable and measurable is placed on a new line, and their respective settings are also specified on separate indented lines, like so: \n", "\n", " calibration: \n", @@ -318,7 +316,6 @@ "cell_type": "markdown", "id": "13", "metadata": { - "editable": true, "slideshow": { "slide_type": "" }, @@ -356,7 +353,7 @@ " \tcal_start: 2000\n", " \tcal_end: 2040\n", "\n", - "Finally, this same syntax can be used to calibrate transfers and interactions, but in such cases the tuple should have three elements - the parameter name, the _from_ population and the _to_ population. For more information on calibrating in these cases, see [Calibrating transfers and interactions](./YAML_documentation_page.ipynb#calibrating-transfers-and-interactions \"Calibrating transfern detail by this point> TODO: Update link \n" + "Finally, this same syntax can be used to calibrate transfers and interactions, but in such cases the tuple should have three elements - the parameter name, the _from_ population and the _to_ population. For more information on calibrating in these cases, see [Calibrating transfers and interactions](/general/YAML_calibration.html#Calibrating-transfers-and-interactions)." ] }, { @@ -389,7 +386,7 @@ "\n", "\"Post-initialization\n", "\n", - "If the model parameters are not roughly constant, the equilibrium that the model converges to in the future might not correspond to the equilibrium solution for the model's initial parameter values. In that case, an initial transient will still occur. To address this, we can remove any time variation in the model's parameter values using the `ParameterSet.make_constant()` method. This will return a copy of the parset in which all parameters are constant over time, thus ensuring that the future compartment sizes are computed based on the same parameter values as the initial simulation year. This often provides a suitable solution, although changes to the total population size due to births and deaths can still take place, so in some cases an initial transient may still be present. In such cases, repeatedly setting initialization based on a shorter simulation can help minimize the discrepancy. For more information on Atomica initializations, see the [documentation](./YAML_documentation_page.ipynb \"Documentation\").\n", + "If the model parameters are not roughly constant, the equilibrium that the model converges to in the future might not correspond to the equilibrium solution for the model's initial parameter values. In that case, an initial transient will still occur. To address this, we can remove any time variation in the model's parameter values using the `ParameterSet.make_constant()` method. This will return a copy of the parset in which all parameters are constant over time, thus ensuring that the future compartment sizes are computed based on the same parameter values as the initial simulation year. This often provides a suitable solution, although changes to the total population size due to births and deaths can still take place, so in some cases an initial transient may still be present. In such cases, repeatedly setting initialization based on a shorter simulation can help minimize the discrepancy. For more information on Atomica initializations, see the [documentation](/general/YAML_calibration.html).\n", "\n", "In the YAML file, we indicate that we want to set a new initialization by making a YAML block with the title `set_initialisation`. Under this title, we can specify further settings: \n", "\n", @@ -478,7 +475,7 @@ "\n", " calibrated_parset = P.calibrate(parset = cal, yaml='T7_YAML_1_minimal.yaml', save_intermediate=True)\n", "\n", - "For more information on intermediate calibrations, see the relevant [documentation section](./YAML_documentation_page.ipynb#saving-intermediate-calibrations \"Saving intermediate calibrations\")." + "For more information on intermediate calibrations, see the relevant [documentation section](/general/YAML_calibration.html#saving-intermediate-calibrations \"Saving intermediate calibrations\")." ] }, { @@ -650,7 +647,7 @@ "\n", "**Hint**: Use `save_calibration` and specify a `fname`.\n", "\n", - "All solutions to the worked example are in the `Worked_example` folder. _TODO: Update paths when moved to Atomica repository_ The calibration obtained after running the last YAML file in this exercise yields the following simulation result: \n", + "All solutions to the worked example are in the `Worked_example` folder in code repository. The calibration obtained after running the last YAML file in this exercise yields the following simulation result: \n", "\n", "\"Worked" ] @@ -664,7 +661,7 @@ "\n", "### Epidemiological calibration\n", "\n", - "In this tutorial we have demonstrated the key functionality of Atomica's YAML calibration system applied to a population calibration, focussing on adjusting births and deaths to match population size data, without considering disease burden. This same functionality applies to epidemiological calibration, just with different model parameters and data. A complete YAML file of the population and epidemiological calibration can be found at _TODO: Update paths when moved to Atomica repository_\n", + "In this tutorial we have demonstrated the key functionality of Atomica's YAML calibration system applied to a population calibration, focussing on adjusting births and deaths to match population size data, without considering disease burden. This same functionality applies to epidemiological calibration, just with different model parameters and data. A complete YAML file of the population and epidemiological calibration can be found in the `Worked_example` folder in code repository, in the `typ_calibration_instructions.yaml` file. \n", "\n", "In this YAML file, we have set the `max_time` to 120, to give the calibration a bit more time to reach an optimal solution in each calibration step. \n", "\n", @@ -672,9 +669,6 @@ "\n", "We then calibrate the population following the same principles as illustrated previously, repeating the population calibration ten times, and setting a new initialization at the end of each loop, with `constant_parset=True` and the `init_year` set to 2030. \n", "\n", - "After the population calibration, the typhoid y-factors get set t\n", - "#TODO: Deal with issue: epi y-factors get reset to 1 in every pass, which means a) all the epi calibration loops except the first one don't achieve anything, b) if we remove those loops, there's no going back to the pop calibration after the epi calibration to make sure it still fits well after calibrating epi \n", - "\n", "In the epidemiological calibration section, the typhoid incidence, prevalence, and typhoid deaths are calibrated. Since we don't have a lot of information on the order of magnitude of the susceptibility and infectiousness, the lower and upper bounds are expanded to leave more room for variation. However, we don't want the disease duration `typ_gen_dur` to vary a lot, since we have a pretty clear idea of its magnitude and don't want it to vary too much between calibrations and settings, so we set stricter bounds. \n", "\n", "At the end of the typhoid calibration, we set an initialisation in the same way we did for the population calibration. We then repeat the epidemiological calibration ten times, and finally, repeat the whole YAML calibration process (except silencing the epi y-factors) twice. \n", @@ -685,15 +679,15 @@ "\n", "### Documentation\n", "\n", - "For more information on using Atomica's YAML calibration functionality, see [the documentation](./YAML_documentation_page.ipynb#yaml-calibration-documentation-page \"YAML documentation page\").\n" + "For additional information on YAML calibration functionality, see [the documentation](/general/YAML_calibration.html).\n" ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python [conda env:atomica312]", "language": "python", - "name": "python3" + "name": "conda-env-atomica312-py" }, "language_info": { "codemirror_mode": { @@ -705,7 +699,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.2" }, "toc": { "base_numbering": 1, diff --git a/docs/tutorial/index.rst b/docs/tutorial/index.rst index 8cf8a11c..ec817ec7 100644 --- a/docs/tutorial/index.rst +++ b/docs/tutorial/index.rst @@ -12,3 +12,4 @@ These tutorials walk through getting starting with building models in Atomica T4-Characteristics T5-Junctions T6-Programs + T7/T7_YAML_autocalibration From 6963e52be452aa68f477b5ebb7b431a0a8931962 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 17 Feb 2025 19:02:02 +1000 Subject: [PATCH 107/161] Switch to non-sciris separate legend routine and update for matplotlib 3.10 --- atomica/plotting.py | 48 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/atomica/plotting.py b/atomica/plotting.py index 826fc997..3bd51d3a 100644 --- a/atomica/plotting.py +++ b/atomica/plotting.py @@ -1237,6 +1237,44 @@ def interpolate(self, new_tvec): return np.interp(sc.promotetoarray(new_tvec), self.tvec, self.vals, left=np.nan, right=np.nan) + +def separatelegend(ax=None, handles=None, labels=None, reverse=False, legendsettings=None): + ''' Allows the legend of a figure to be rendered in a separate window instead ''' + + # Handle settings + if ax is None: + fig, ax = plt.subplots() + else: + fig = ax.figure + fig.set_size_inches(4.0,4.8) + + l_settings = sc.mergedicts({'loc': 'center', 'bbox_to_anchor': None, 'frameon': False}, legendsettings) + + # Get handles and labels + if handles is None and labels is None: + handles, labels = ax.get_legend_handles_labels() + elif handles is None: + handles, _ = ax.get_legend_handles_labels() + elif labels is None: + labels = [h.get_label() for h in handles] + assert len(handles) == len(labels), f"Number of handles ({len(handles)}) and labels ({len(labels)}) must match" + + # Set up new plot + ax.set_position([-0.05,-0.05,1.1,1.1]) + ax.set_axis_off() + + # Reverse order, e.g. for stacked plots + if reverse: # pragma: no cover + handles = handles[::-1] + labels = labels[::-1] + + # Plot the new legend + ax.legend(handles=handles, labels=labels, **l_settings) + + return fig + + + def plot_bars(plotdata, stack_pops=None, stack_outputs=None, outer=None, legend_mode=None, show_all_labels=False, orientation="vertical") -> list: """ Produce a bar plot @@ -1583,7 +1621,7 @@ def process_input_stacks(input_stacks, available_items): if legend_mode == "together": _render_legend(ax, plot_type="bar", handles=legend_patches) elif legend_mode == "separate": - figs.append(sc.separatelegend(handles=legend_patches, reverse=True)) + figs.append(separatelegend(handles=legend_patches, reverse=True)) return figs @@ -1760,14 +1798,12 @@ def _prepare_figures(dim1, dim2, n_cols): if legend_mode == "separate": reverse_legend = True if plot_type in ["stacked", "proportion"] else False + handles, labels = ax.get_legend_handles_labels() if not subplots: - # Replace the last figure with a legend figure - plt.close(figs[-1]) # TODO - update Sciris to allow passing in an existing figure - figs[-1] = sc.separatelegend(ax, reverse=reverse_legend) + separatelegend(axes[-1], handles=handles, labels=labels, reverse=reverse_legend) else: legend_ax = axes[-1] - handles, labels = ax.get_legend_handles_labels() legend_ax.set_axis_off() # Hide axis lines if reverse_legend: # pragma: no cover handles = handles[::-1] @@ -1884,7 +1920,7 @@ def plot_legend(entries: dict, plot_type=None, fig=None, legendsettings: dict = raise Exception(f'Unknown plot type "{p_type}"') if fig is None: # Draw in a new figure - fig = sc.separatelegend(handles=h, legendsettings=legendsettings) + fig = separatelegend(handles=h, legendsettings=legendsettings) else: existing_legend = fig.findobj(Legend) if existing_legend and existing_legend[0].parent is fig: # If existing legend and this is a separate legend fig From 3147dd5babeccfda706a0be18d3cf997df9bdbdc Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 17 Feb 2025 19:02:18 +1000 Subject: [PATCH 108/161] Increment version --- CHANGELOG.md | 7 ++++++- atomica/version.py | 4 ++-- docs/conf.py | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aae5da61..471965e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,12 @@ This file records changes to the codebase grouped by version release. Unreleased changes are generally only present during development (relevant parts of the changelog can be written and saved in that section before a version number has been assigned) -## [1.XX.0] - 2024 +## [1.30.0] - 2025-02-17 + +- Automatic calibration can now selectively weight parts of the time series to select or prioritise a subset of time points. +- Added YAML-based calibration support to Atomica, covered in Tutorial 7 in the online documentation. + +## [1.29.0] - 2024-10-30 - `ProjectSettings` now computes the simulation time vector in a more robust way to reduce edge cases where the reported `sim_dt` doesn't match the input. - `ParameterSet.load_calibration()` now clears any existing initialization if the calibration being loaded does not contain an initialization. Previously, the absence of an 'initialization' sheet in the calibration would be treated as not making any change to the initialization. This could cause calibrations to become mixed if a calibration without an initialization was loaded after a calibration with an initialization. Now, a missing initialization sheet is treated as meaning 'no initialization' and any existing initialization will be cleared when the calibration is loaded. diff --git a/atomica/version.py b/atomica/version.py index 4091ba3f..91aaedea 100644 --- a/atomica/version.py +++ b/atomica/version.py @@ -6,6 +6,6 @@ import sciris as sc -version = "1.29.0" -versiondate = "2024-10-30" +version = "1.30.0" +versiondate = "2025-02-17" gitinfo = sc.gitinfo(__file__) diff --git a/docs/conf.py b/docs/conf.py index edda0d44..699d1c5b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -24,7 +24,7 @@ # -- Project information ----------------------------------------------------- project = "Atomica" -copyright = "2023, Atomica Team" +copyright = "2025, Atomica Team" author = "Atomica Team" import atomica From 16cce415ebab27c0d4f4b22eeeb81f4222bf8238 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 17 Feb 2025 19:02:51 +1000 Subject: [PATCH 109/161] Apply auto-formatting --- atomica/calibration.py | 22 +- atomica/plotting.py | 22 +- atomica/project.py | 19 +- atomica/system.py | 2 +- atomica/utils.py | 2 +- atomica/yaml_calibration.py | 246 +++++++++--------- .../T7/calibrations/run_model_autocals.py | 60 ++--- .../T7/calibrations/run_tutorial_autocals.py | 55 ++-- tests/test_time_vector.py | 2 +- tests/test_tox_yaml.py | 18 +- 10 files changed, 220 insertions(+), 228 deletions(-) diff --git a/atomica/calibration.py b/atomica/calibration.py index 4d873e90..c100a8b5 100644 --- a/atomica/calibration.py +++ b/atomica/calibration.py @@ -39,6 +39,7 @@ def _update_parset(parset, y_factors, pars_to_adjust) -> None: else: par.y_factor[pop_name] = y_factors[i] + def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, project, *args, **kwargs) -> float: """ Run the model for a given set of y-factors and return the objective/goodness-of-fit @@ -79,7 +80,7 @@ def _calculate_objective(y_factors, pars_to_adjust, output_quantities, parset, p inds = (data_t >= start_year) & (data_t <= end_year) if np.count_nonzero(inds) == 0: # If no time points remain after filtering down to the time points the user requested - logger.info(f'No data points remaining after filtering down to requested time period. Skipping...') + logger.info(f"No data points remaining after filtering down to requested time period. Skipping...") continue data_t = data_t[inds] data_v = data_v[inds] @@ -164,7 +165,6 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, """ - # Expand out pop=None in pars_to_adjust p2 = [] for par_tuple in pars_to_adjust: @@ -215,20 +215,20 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, par = parset.get_par(par_name) - #if initial_value has not been explicitly set in the tuple: use y_factor in parset + # if initial_value has not been explicitly set in the tuple: use y_factor in parset if initial_value is None: if pop_name == "all": initial_value = par.meta_y_factor else: initial_value = par.y_factor[pop_name] - #if this value is outside the min and max bounds, make it equal to min or max (whichever is closest) - #if min == max, this should make the initial value equal to min and max + # if this value is outside the min and max bounds, make it equal to min or max (whichever is closest) + # if min == max, this should make the initial value equal to min and max initial_value = np.clip(initial_value, scale_min, scale_max) else: - assert (initial_value >= scale_min) and (initial_value <= scale_max), 'Initial value is not consistent with the lower/upper bounds' + assert (initial_value >= scale_min) and (initial_value <= scale_max), "Initial value is not consistent with the lower/upper bounds" - #update y_factors in parset - if pop_name == 'all': + # update y_factors in parset + if pop_name == "all": par.meta_y_factor = initial_value else: par.y_factor[pop_name] = initial_value @@ -241,8 +241,6 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, xmin.append(scale_min) xmax.append(scale_max) - - args = { "project": project, "parset": parset, @@ -270,7 +268,7 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, } optim_args.update(kwargs) - if 'verbose' not in optim_args: + if "verbose" not in optim_args: log_level = logger.getEffectiveLevel() if log_level < logging.WARNING: optim_args["verbose"] = 2 @@ -297,7 +295,7 @@ def calibrate(project, parset: ParameterSet, pars_to_adjust, output_quantities, _update_parset(args["parset"], x1, args["pars_to_adjust"]) else: - logger.info('No parameters to adjust provided to the optimisation function. Skipping optimisation...') + logger.info("No parameters to adjust provided to the optimisation function. Skipping optimisation...") # Log out the commands required for equivalent manual calibration if desired for i, x in enumerate(pars_to_adjust): diff --git a/atomica/plotting.py b/atomica/plotting.py index 3bd51d3a..d85d34e8 100644 --- a/atomica/plotting.py +++ b/atomica/plotting.py @@ -662,8 +662,8 @@ def time_aggregate(self, t_bins, time_aggregation=None, interpolation_method=Non scale = 1.0 vals = np.full(lower.shape, fill_value=np.nan) - lower_idx = np.searchsorted(s.tvec, lower, side='left') # Time index for bin start - upper_idx = np.searchsorted(s.tvec, upper, side='right') # Time index for bin end + lower_idx = np.searchsorted(s.tvec, lower, side="left") # Time index for bin start + upper_idx = np.searchsorted(s.tvec, upper, side="right") # Time index for bin end for i, (l, u, l_idx, u_idx) in enumerate(zip(lower, upper, lower_idx, upper_idx)): @@ -678,14 +678,14 @@ def time_aggregate(self, t_bins, time_aggregation=None, interpolation_method=Non # The bins will consist of the actual simulation time points, plus # partial bins that are interpolated before and after if the requested # bins don't line up with the simulation timepoints - idx = np.arange(l_idx,u_idx) + idx = np.arange(l_idx, u_idx) t2 = s.tvec[idx] interpolate = False if t2[0] > l or t2[-1] < u: interpolate = True t2 = list(t2) if t2[0] > l: - t2.insert(0,l) + t2.insert(0, l) if t2[-1] < u: t2.append(u) t2 = np.array(t2, dtype=float) @@ -1237,18 +1237,17 @@ def interpolate(self, new_tvec): return np.interp(sc.promotetoarray(new_tvec), self.tvec, self.vals, left=np.nan, right=np.nan) - def separatelegend(ax=None, handles=None, labels=None, reverse=False, legendsettings=None): - ''' Allows the legend of a figure to be rendered in a separate window instead ''' + """Allows the legend of a figure to be rendered in a separate window instead""" # Handle settings if ax is None: fig, ax = plt.subplots() else: fig = ax.figure - fig.set_size_inches(4.0,4.8) + fig.set_size_inches(4.0, 4.8) - l_settings = sc.mergedicts({'loc': 'center', 'bbox_to_anchor': None, 'frameon': False}, legendsettings) + l_settings = sc.mergedicts({"loc": "center", "bbox_to_anchor": None, "frameon": False}, legendsettings) # Get handles and labels if handles is None and labels is None: @@ -1260,13 +1259,13 @@ def separatelegend(ax=None, handles=None, labels=None, reverse=False, legendsett assert len(handles) == len(labels), f"Number of handles ({len(handles)}) and labels ({len(labels)}) must match" # Set up new plot - ax.set_position([-0.05,-0.05,1.1,1.1]) + ax.set_position([-0.05, -0.05, 1.1, 1.1]) ax.set_axis_off() # Reverse order, e.g. for stacked plots - if reverse: # pragma: no cover + if reverse: # pragma: no cover handles = handles[::-1] - labels = labels[::-1] + labels = labels[::-1] # Plot the new legend ax.legend(handles=handles, labels=labels, **l_settings) @@ -1274,7 +1273,6 @@ def separatelegend(ax=None, handles=None, labels=None, reverse=False, legendsett return fig - def plot_bars(plotdata, stack_pops=None, stack_outputs=None, outer=None, legend_mode=None, show_all_labels=False, orientation="vertical") -> list: """ Produce a bar plot diff --git a/atomica/project.py b/atomica/project.py index 2dda2c1a..a7911dd4 100644 --- a/atomica/project.py +++ b/atomica/project.py @@ -576,18 +576,7 @@ def run_sampled_sims(self, parset, progset=None, progset_instructions=None, resu return results - def calibrate(self, - parset=None, - adjustables=None, - measurables=None, - save_to_project=False, - new_name=None, - default_min_scale=0.0, - default_max_scale=2.0, - default_weight=1.0, - default_metric="fractional", - yaml=None, - **kwargs) -> ParameterSet: + def calibrate(self, parset=None, adjustables=None, measurables=None, save_to_project=False, new_name=None, default_min_scale=0.0, default_max_scale=2.0, default_weight=1.0, default_metric="fractional", yaml=None, **kwargs) -> ParameterSet: """ Method to perform automatic calibration. @@ -638,10 +627,11 @@ def calibrate(self, parset = self.parsets[parset] if yaml is not None: - import atomica.yaml_calibration # Avoid circular import + import atomica.yaml_calibration # Avoid circular import + assert adjustables is None, "If a YAML file is specified, adjustables should not be set" assert measurables is None, "If a YAML file is specified, measurables should not be set" - assert 'time_period' not in kwargs, "If a YAML file is specified, time_period should not be set - instead, set cal_start and cal_end in the YAML file" + assert "time_period" not in kwargs, "If a YAML file is specified, time_period should not be set - instead, set cal_start and cal_end in the YAML file" new_parset = atomica.yaml_calibration.run(yaml, self, parset, **kwargs) else: if adjustables is None: @@ -663,7 +653,6 @@ def calibrate(self, new_parset = calibrate(project=self, parset=parset, pars_to_adjust=adjustables, output_quantities=measurables, **kwargs) - if new_name is None: new_name = parset.name + " (auto-calibrated)" new_parset.name = new_name # The new parset is a calibrated copy of the old, so change id. diff --git a/atomica/system.py b/atomica/system.py index 67816a43..9e3c149c 100644 --- a/atomica/system.py +++ b/atomica/system.py @@ -90,4 +90,4 @@ class FrameworkSettings: RESERVED_SYMBOLS = set(":,;/+-*'\" @") # A code_name in the framework (for characs, comps, pars) cannot contain any of these characters - DEFAULT_PROVENANCE = "Framework-supplied default" \ No newline at end of file + DEFAULT_PROVENANCE = "Framework-supplied default" diff --git a/atomica/utils.py b/atomica/utils.py index c33b7618..eb7bb3d8 100644 --- a/atomica/utils.py +++ b/atomica/utils.py @@ -994,7 +994,7 @@ def get_sigfigs_necessary(x, y, min_sigfigs: int = 2) -> int: :return: Number of significant figures required """ msf = min_sigfigs - assert sc.isnumber(x) and sc.isnumber(y), f'Cannot compare sigfigs as {x} and {y} are not both numbers' + assert sc.isnumber(x) and sc.isnumber(y), f"Cannot compare sigfigs as {x} and {y} are not both numbers" if x == y or np.isnan(x) or np.isnan(y): return msf else: diff --git a/atomica/yaml_calibration.py b/atomica/yaml_calibration.py index 9b97f7a1..25ebd4ef 100644 --- a/atomica/yaml_calibration.py +++ b/atomica/yaml_calibration.py @@ -13,7 +13,7 @@ import time import re -__all__ = ['build', 'run'] +__all__ = ["build", "run"] from atomica import ParameterSet @@ -24,7 +24,8 @@ def _get_named_nodes(): """ return {x._name: x for x in BaseNode.__subclasses__() if x._name is not None} -def build(instructions=None, context=None, name='calibration'): + +def build(instructions=None, context=None, name="calibration"): """ Construct nodes representing a calibration @@ -38,17 +39,18 @@ def build(instructions=None, context=None, name='calibration'): if (sc.isstring(instructions) or isinstance(instructions, Path)) and Path(instructions).exists(): with open(instructions) as file: - instructions = yaml.load(file, Loader=yaml.FullLoader) + instructions = yaml.load(file, Loader=yaml.FullLoader) named_nodes = _get_named_nodes() - if isinstance(instructions, dict) and ('adjustables' in instructions or (context is not None and 'adjustables' in context)) and ('measurables' in instructions or (context is not None and 'measurables' in context)): + if isinstance(instructions, dict) and ("adjustables" in instructions or (context is not None and "adjustables" in context)) and ("measurables" in instructions or (context is not None and "measurables" in context)): return CalibrationNode(instructions, context, name) elif name in named_nodes: return named_nodes[name](instructions, context, name) else: return SectionNode(instructions, context, name) -def run(node, project, parset, savedir=None, save_intermediate=False, log_output:bool=False,*args, **kwargs): + +def run(node, project, parset, savedir=None, save_intermediate=False, log_output: bool = False, *args, **kwargs): """ Run YAML calibration @@ -63,7 +65,7 @@ def run(node, project, parset, savedir=None, save_intermediate=False, log_output """ if savedir is None: - savedir = Path('.') + savedir = Path(".") else: savedir = Path(savedir) savedir.mkdir(exist_ok=True, parents=True) @@ -76,14 +78,14 @@ def run(node, project, parset, savedir=None, save_intermediate=False, log_output parset = sc.dcp(project.parset(parset)) - nodes = list(node.walk()) # Make a flat list of all nodes to execute in order + nodes = list(node.walk()) # Make a flat list of all nodes to execute in order n_steps = len([x for x in nodes if not isinstance(x[1], SectionNode)]) n = 1 if log_output: - at.start_logging(savedir/'calibration_log.txt') + at.start_logging(savedir / "calibration_log.txt") - at.logger.info(f'\nStarting calibration ({n_steps} steps)') + at.logger.info(f"\nStarting calibration ({n_steps} steps)") for n_reps, node in nodes: @@ -96,11 +98,11 @@ def run(node, project, parset, savedir=None, save_intermediate=False, log_output if save_intermediate and not isinstance(node, SaveCalibrationNode): output = savedir / f'intermediate_calibration_{n:0{len(str(n_steps))}}_{node.name.replace(" ", "_")}' - at.logger.info(f'Saving intermediate calibration...') + at.logger.info(f"Saving intermediate calibration...") parset.save_calibration(output) t = time.process_time() - at.logger.info(f'\nCalibration completed. Total time elapsed: {round(t, 2)} seconds ({round(t/60, 2)} minutes)') + at.logger.info(f"\nCalibration completed. Total time elapsed: {round(t, 2)} seconds ({round(t/60, 2)} minutes)") if log_output: at.stop_logging() @@ -150,9 +152,9 @@ def __str__(self, indent=0): :param indent: Recursively increase the indent for child nodes :return: """ - s = '\t' * indent + self.__repr__() + s = "\t" * indent + self.__repr__() for child in self.children: - s += '\n' + child.__str__(indent=indent + 1) + s += "\n" + child.__str__(indent=indent + 1) return s @property @@ -178,8 +180,8 @@ def __contains__(self, item): def repeats(self): # Although repeats may be part of the context, we only repeat a node if the instructions requested a repeat # i.e., repeats are not inherited - if isinstance(self.instructions, dict) and 'repeats' in self.instructions: - return self.instructions['repeats'] + if isinstance(self.instructions, dict) and "repeats" in self.instructions: + return self.instructions["repeats"] else: return 1 @@ -197,10 +199,12 @@ def apply(self, project: at.Project, parset: at.ParameterSet, savedir, *args, ** """ return parset + class SectionNode(BaseNode): """ A section node is a special kind of node, that contains other nodes """ + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.children = self.make_children() @@ -224,35 +228,36 @@ def make_children(self): return children + class CalibrationNode(BaseNode): # Order for list of adjustable parameters and default values adj_defaults = { - 'lower_bound': 0.1, - 'upper_bound': 10.0, - 'starting_y_factor': None, + "lower_bound": 0.1, + "upper_bound": 10.0, + "starting_y_factor": None, } # Order for list of measurable parameters and default values meas_defaults = { - 'weight': 1.0, - 'metric': 'fractional', - 'cal_start': -np.inf, - 'cal_end': np.inf, + "weight": 1.0, + "metric": "fractional", + "cal_start": -np.inf, + "cal_end": np.inf, } @staticmethod def parse_list(l, defaults): # Routine to parse list of arguments into a dictionary of values d = {} - #convert number strings back to numerical values + # convert number strings back to numerical values for i, e in enumerate(l.copy()): try: - l[i] = float(e) + l[i] = float(e) except ValueError: pass - for k, v in zip(list(defaults.keys())[:len(l)], l): + for k, v in zip(list(defaults.keys())[: len(l)], l): d[k] = v return d @@ -269,34 +274,34 @@ def separate_keys(keys_str: str) -> list: :return list : A list of strings, each of which represents a single key. """ in_brackets = False - brackets_str = '' - nobrackets_str = '' + brackets_str = "" + nobrackets_str = "" separated_keys = [] for ch in keys_str: - if ch == '(': + if ch == "(": in_brackets = True continue - elif ch == ')': + elif ch == ")": in_brackets = False separated_keys.append(brackets_str) - brackets_str = '' + brackets_str = "" continue if in_brackets: brackets_str += ch else: - if ch == ',': - if nobrackets_str == ' ' or nobrackets_str == '': - nobrackets_str = '' + if ch == ",": + if nobrackets_str == " " or nobrackets_str == "": + nobrackets_str = "" continue else: separated_keys.append(nobrackets_str) - nobrackets_str = '' + nobrackets_str = "" else: nobrackets_str += ch - if nobrackets_str != '' and nobrackets_str != ' ': + if nobrackets_str != "" and nobrackets_str != " ": separated_keys.append(nobrackets_str) return [x.strip() for x in separated_keys] @@ -319,12 +324,12 @@ def process_key(key: str) -> tuple: INPUT: 'aging, 0-4, 5-14' OUTPUT: (aging, 0-4, 5-14) """ - if ',' in key: - return tuple([x.strip() for x in key.strip('() ').split(',') if x]) + if "," in key: + return tuple([x.strip() for x in key.strip("() ").split(",") if x]) else: return (key.strip(), None) - def process_list(l: list) -> (tuple,list): + def process_list(l: list) -> (tuple, list): """ Process list-format inputs and separate them into a key (par_name, pop_name tuple) and a value (list of parameter settings). @@ -340,20 +345,20 @@ def process_list(l: list) -> (tuple,list): OUTPUT: (b_rate, 0-4) ; [0.1, 10, 1.5] """ if len(l) == 1: - #if the list is already just one string, return that string as key with None pop and vals - return (l[0].strip('() '), None), None - elif '(' in str(l): + # if the list is already just one string, return that string as key with None pop and vals + return (l[0].strip("() "), None), None + elif "(" in str(l): # separate out the parenthesis contents as the par/pop/s, # then output the key (par, pop tuple) and value # process keys s = str(l).strip("[] ").replace("'", "") - s1 = re.findall(r'\(.*?\)', s) - key = process_key(s1[0].replace('(', '').replace(')', '')) + s1 = re.findall(r"\(.*?\)", s) + key = process_key(s1[0].replace("(", "").replace(")", "")) # process values/settings - value = s.replace(s1[0], '').strip(', ').split(',') - value = [x.strip(', ') for x in value if x] + value = s.replace(s1[0], "").strip(", ").split(",") + value = [x.strip(", ") for x in value if x] return key, value else: key = process_key(l[0]) @@ -382,22 +387,22 @@ def process_inputs(inputs, defaults: dict) -> dict: if sc.isstring(inputs): # Support a comma separated string with "quantity pop" specifications of adjustables and measurables # In this case, default values should be used for all other items. Proceed by splitting into a list - inputs = inputs.split(',') + inputs = inputs.split(",") if isinstance(inputs, (tuple, list)): for l in inputs: l = sc.promotetolist(l) keyspops, v = process_list(l) - - #process key + + # process key if len(keyspops) == 2: key, pop_name = keyspops else: - assert len(keyspops) == 3, f'Number of populations must be 0, 1 or 2.' - key = f'{keyspops[0]}_from_{keyspops[1]}' + assert len(keyspops) == 3, f"Number of populations must be 0, 1 or 2." + key = f"{keyspops[0]}_from_{keyspops[1]}" pop_name = keyspops[2] - #process value + # process value if v is None: value = defaults else: @@ -410,16 +415,16 @@ def process_inputs(inputs, defaults: dict) -> dict: separated_keys = separate_keys(keys) for key in separated_keys: - #separate par name from pop name + # separate par name from pop name keyspops = process_key(key.strip()) if len(keyspops) == 2: key, pop_name = keyspops else: - assert len(keyspops) == 3, f'Number of populations must be 0, 1 or 2.' - key = f'{keyspops[0]}_from_{keyspops[1]}' + assert len(keyspops) == 3, f"Number of populations must be 0, 1 or 2." + key = f"{keyspops[0]}_from_{keyspops[1]}" pop_name = keyspops[2] - #process values + # process values if isinstance(v, (tuple, list)): value = self.parse_list(v, defaults) elif v is None: @@ -427,12 +432,12 @@ def process_inputs(inputs, defaults: dict) -> dict: else: value = v.copy() - #add keys and values to outputs dict + # add keys and values to outputs dict out[key, pop_name] = sc.mergedicts(out.get((key, pop_name), {}), value) return out - self['adjustables'] = process_inputs(self['adjustables'], self.adj_defaults) - self['measurables'] = process_inputs(self['measurables'], self.meas_defaults) + self["adjustables"] = process_inputs(self["adjustables"], self.adj_defaults) + self["measurables"] = process_inputs(self["measurables"], self.meas_defaults) def check_optional_number(key, v, defaults): if key in v and v[key] is not None: @@ -440,25 +445,25 @@ def check_optional_number(key, v, defaults): raise TypeError(f"Adjustable argument {key} needs to be a number or None (defaults to {defaults[key]}). Provided value: {v[key]} ") # Validate adjustables - assert len(self['adjustables']) > 0, f'Cannot calibrate with no adjustables for calibration section {self.name}' - for (quantity, pop_name), v in self['adjustables'].items(): - assert 'pop_name' not in v, f'Setting the population name through "pop_name: {v["pop_name"]}" is not supported. Instead, the name of the adjustable quantity should include the population name ("{quantity} {v["pop_name"]}")' - assert isinstance(quantity, str), f'Adjustable codename {quantity} needs to be a string' - assert pop_name is None or isinstance(pop_name, str), f'Adjustable population {pop_name} needs to be a string or None (defaults to all populations for that parameter)' - check_optional_number('lower_bound',v, self.adj_defaults) - check_optional_number('upper_bound',v, self.adj_defaults) - check_optional_number('starting_y_factor',v, self.adj_defaults) + assert len(self["adjustables"]) > 0, f"Cannot calibrate with no adjustables for calibration section {self.name}" + for (quantity, pop_name), v in self["adjustables"].items(): + assert "pop_name" not in v, f'Setting the population name through "pop_name: {v["pop_name"]}" is not supported. Instead, the name of the adjustable quantity should include the population name ("{quantity} {v["pop_name"]}")' + assert isinstance(quantity, str), f"Adjustable codename {quantity} needs to be a string" + assert pop_name is None or isinstance(pop_name, str), f"Adjustable population {pop_name} needs to be a string or None (defaults to all populations for that parameter)" + check_optional_number("lower_bound", v, self.adj_defaults) + check_optional_number("upper_bound", v, self.adj_defaults) + check_optional_number("starting_y_factor", v, self.adj_defaults) # Validate measurables - assert len(self['measurables']) > 0, f'Cannot calibrate with no measurables for calibration section {self.name}' - for (quantity, pop_name), v in self['measurables'].items(): - assert isinstance(quantity, str), f'Measurable codename {quantity} needs to be a string' - assert pop_name is None or isinstance(pop_name, str), f'Adjustable population {pop_name} needs to be a string or None (defaults to all populations for that parameter)' - assert 'metric' not in v or v['metric'] is None or isinstance(v["metric"], str), f"Measurable metric {v['metric']} needs to be a number or None (defaults to 'fractional')" + assert len(self["measurables"]) > 0, f"Cannot calibrate with no measurables for calibration section {self.name}" + for (quantity, pop_name), v in self["measurables"].items(): + assert isinstance(quantity, str), f"Measurable codename {quantity} needs to be a string" + assert pop_name is None or isinstance(pop_name, str), f"Adjustable population {pop_name} needs to be a string or None (defaults to all populations for that parameter)" + assert "metric" not in v or v["metric"] is None or isinstance(v["metric"], str), f"Measurable metric {v['metric']} needs to be a number or None (defaults to 'fractional')" - check_optional_number('weight',v, self.meas_defaults) - check_optional_number('cal_start',v, self.meas_defaults) - check_optional_number('cal_end',v, self.meas_defaults) + check_optional_number("weight", v, self.meas_defaults) + check_optional_number("cal_start", v, self.meas_defaults) + check_optional_number("cal_end", v, self.meas_defaults) def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, quiet=False, compare_results=False, **kwargs) -> ParameterSet: @@ -469,12 +474,12 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui # Expand adjustables adjustables = {} - par_names = {x[0] for x in attributes['adjustables']}.intersection(x.name for x in parset.all_pars()) - pop_names = {x[1] for x in attributes['adjustables']}.intersection({*parset.pop_names} | {'all', None}) + par_names = {x[0] for x in attributes["adjustables"]}.intersection(x.name for x in parset.all_pars()) + pop_names = {x[1] for x in attributes["adjustables"]}.intersection({*parset.pop_names} | {"all", None}) - adj_defaults = {k:self.attributes[k] if k in self.attributes else self.adj_defaults[k] for k in self.adj_defaults} + adj_defaults = {k: self.attributes[k] if k in self.attributes else self.adj_defaults[k] for k in self.adj_defaults} - for par_name, pop_name in attributes['adjustables']: + for par_name, pop_name in attributes["adjustables"]: if par_name not in par_names: at.logger.warning(f"Extra YAML adjustable parameter '{par_name}' does not exist in this project's framework/parset and will be ignored") @@ -489,25 +494,24 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui pops = sc.promotetolist(pop_name) for pop in pops: - d = sc.mergedicts(adj_defaults, attributes['adjustables'].get((par_name, None), None), attributes['adjustables'].get((par_name, pop), None)) - adjustables[(par_name, pop)] = (d['lower_bound'], d['upper_bound'], d['starting_y_factor']) - adjustables = [(*k, *v) for k,v in adjustables.items()] - + d = sc.mergedicts(adj_defaults, attributes["adjustables"].get((par_name, None), None), attributes["adjustables"].get((par_name, pop), None)) + adjustables[(par_name, pop)] = (d["lower_bound"], d["upper_bound"], d["starting_y_factor"]) + adjustables = [(*k, *v) for k, v in adjustables.items()] # Expand measurables measurables = {} - par_names = {x[0] for x in attributes['measurables']}.intersection(x.name for x in parset.all_pars()) # TODO: This is probably OK for now but will need to validate that pars have databook entries in the future - pop_names = {x[1] for x in attributes['measurables']}.intersection({*parset.pop_names} | {None}) + par_names = {x[0] for x in attributes["measurables"]}.intersection(x.name for x in parset.all_pars()) # TODO: This is probably OK for now but will need to validate that pars have databook entries in the future + pop_names = {x[1] for x in attributes["measurables"]}.intersection({*parset.pop_names} | {None}) meas_defaults = {k: self.attributes[k] if k in self.attributes else self.meas_defaults[k] for k in self.meas_defaults} - for par_name, pop_name in attributes['measurables']: + for par_name, pop_name in attributes["measurables"]: if par_name not in par_names: at.logger.warning(f"Extra YAML measurable variable '{par_name}' does not exist in this project's framework and will be ignored") continue elif pop_name not in pop_names: - if not (pop_name.lower() == 'total' and pop_name.lower() in {x.lower() for x in project.data.tdve[par_name].ts.keys()}): + if not (pop_name.lower() == "total" and pop_name.lower() in {x.lower() for x in project.data.tdve[par_name].ts.keys()}): at.logger.warning(f"Extra YAML measurable population '{pop_name}' does not exist in this project's databook and will be ignored") continue @@ -517,20 +521,20 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui pops = sc.promotetolist(pop_name) for pop in pops: - d = sc.mergedicts(meas_defaults, attributes['measurables'].get((par_name, None), None), attributes['measurables'].get((par_name, pop), None)) - measurables[(par_name, pop)] = (d['weight'], d['metric'], d['cal_start'], d['cal_end']) - measurables = [(*k, *v) for k,v in measurables.items()] + d = sc.mergedicts(meas_defaults, attributes["measurables"].get((par_name, None), None), attributes["measurables"].get((par_name, pop), None)) + measurables[(par_name, pop)] = (d["weight"], d["metric"], d["cal_start"], d["cal_end"]) + measurables = [(*k, *v) for k, v in measurables.items()] # Calibration if len(adjustables): # note: attributes = instructions + context kwargs = sc.mergedicts(self.attributes, kwargs) - del kwargs['adjustables'] # supplied via the adjustables variable - del kwargs['measurables'] # supplied via the measurables variable + del kwargs["adjustables"] # supplied via the adjustables variable + del kwargs["measurables"] # supplied via the measurables variable - if 'repeats' in kwargs: - del kwargs['repeats'] + if "repeats" in kwargs: + del kwargs["repeats"] if quiet: with at.Quiet(show_warnings=False): @@ -553,13 +557,13 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui new = new_cal_parset.get_par(par).y_factor[pop] if new != old: - at.logger.info(f'...adjusted the y-factor for {par} in {pop} from {old} to {new}') + at.logger.info(f"...adjusted the y-factor for {par} in {pop} from {old} to {new}") made_changes = True else: - at.logger.debug(f'...did NOT adjust the y-factor for {par} in {pop} from {old} to {new}') + at.logger.debug(f"...did NOT adjust the y-factor for {par} in {pop} from {old} to {new}") if not made_changes: - at.logger.info(f'...made no changes!') + at.logger.info(f"...made no changes!") if compare_results: base_res = project.run_sim(parset=parset) @@ -579,58 +583,58 @@ def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, qui cal_rms_error += (data_time_val - cal_time_val) ** 2 sf = at.get_sigfigs_necessary(base_time_val, cal_time_val) - at.logger.info(f'...for parameter {par_name} and population {pop} at time {time_value} the data value was {sc.sigfig(data_time_val, sf)}, the baseline value was {sc.sigfig(base_time_val, sf)}, and the calibrated value was {sc.sigfig(cal_time_val, sf)}.') + at.logger.info(f"...for parameter {par_name} and population {pop} at time {time_value} the data value was {sc.sigfig(data_time_val, sf)}, the baseline value was {sc.sigfig(base_time_val, sf)}, and the calibrated value was {sc.sigfig(cal_time_val, sf)}.") - base_rms_error = base_rms_error ** 0.5 - cal_rms_error = cal_rms_error ** 0.5 + base_rms_error = base_rms_error**0.5 + cal_rms_error = cal_rms_error**0.5 sf = at.get_sigfigs_necessary(base_rms_error, cal_rms_error) - at.logger.info(f'...RMS error for parameter {par_name} has changed from baseline {sc.sigfig(base_rms_error, sf)} to calibrated {sc.sigfig(cal_rms_error, sf)}') + at.logger.info(f"...RMS error for parameter {par_name} has changed from baseline {sc.sigfig(base_rms_error, sf)} to calibrated {sc.sigfig(cal_rms_error, sf)}") return new_cal_parset class InitializationNode(BaseNode): - _name = 'set_initialization' + _name = "set_initialization" - def __init__(self, instructions, context, name ): + def __init__(self, instructions, context, name): new_instructions = {} if isinstance(instructions, dict): new_instructions.update(instructions) elif type(instructions) is int: - new_instructions.update({'init_year': instructions}) + new_instructions.update({"init_year": instructions}) elif isinstance(instructions, (tuple, list)): sc.promotetolist(instructions) - new_instructions.update({'init_year': instructions[0]}) + new_instructions.update({"init_year": instructions[0]}) if len(instructions) > 1: - new_instructions.update({'constant_parset': instructions[1]}) + new_instructions.update({"constant_parset": instructions[1]}) super().__init__(new_instructions, context, name) def validate(self): - assert 'init_year' in self, f'Initialization year must be specified' - assert sc.isnumber(self['init_year']), f'Initialization year {self["init_year"]} must be numeric.' - if 'constant_parset' in self: - assert isinstance(self['constant_parset'], int), f'Constant parset (optional) {self["constant_parset"]} must be numeric (boolean, or int to specify constant parset year).' + assert "init_year" in self, f"Initialization year must be specified" + assert sc.isnumber(self["init_year"]), f'Initialization year {self["init_year"]} must be numeric.' + if "constant_parset" in self: + assert isinstance(self["constant_parset"], int), f'Constant parset (optional) {self["constant_parset"]} must be numeric (boolean, or int to specify constant parset year).' def apply(self, project: at.Project, parset: at.ParameterSet, n: int, *args, **kwargs) -> ParameterSet: p2 = sc.dcp(parset) - if 'constant_parset' in self: - if self['constant_parset'] == False: + if "constant_parset" in self: + if self["constant_parset"] == False: pass - elif self['constant_parset'] == True: + elif self["constant_parset"] == True: p2 = parset.make_constant(year=project.settings.sim_start) - elif sc.isnumber(self['constant_parset']): #constant parset year was provided - p2 = parset.make_constant(year=self['constant_parset']) + elif sc.isnumber(self["constant_parset"]): # constant parset year was provided + p2 = parset.make_constant(year=self["constant_parset"]) new_settings = sc.dcp(project.settings) - new_settings.update_time_vector(end=self['init_year']) + new_settings.update_time_vector(end=self["init_year"]) res = at.run_model(settings=new_settings, framework=project.framework, parset=p2) - parset.set_initialization(res, self['init_year']) + parset.set_initialization(res, self["init_year"]) return parset class ClearInitializationNode(BaseNode): - _name = 'clear_initialization' + _name = "clear_initialization" def __init__(self, instructions, context, name): super().__init__(instructions=None, context=context, name=name) @@ -645,16 +649,16 @@ class SaveCalibrationNode(BaseNode): Block in YAML file with "save calibration: " """ - _name = 'save_calibration' + _name = "save_calibration" def __init__(self, instructions, context, name): if not isinstance(instructions, dict): - instructions = {'fname': instructions} + instructions = {"fname": instructions} super().__init__(instructions, context, name) def validate(self): - assert self['fname'] is not None, 'A "save calibration" node must have a file name explicitly specified' + assert self["fname"] is not None, 'A "save calibration" node must have a file name explicitly specified' def apply(self, project: at.Project, parset: at.ParameterSet, savedir=None, *args, **kwargs) -> ParameterSet: - parset.save_calibration(savedir / self['fname']) + parset.save_calibration(savedir / self["fname"]) return parset diff --git a/docs/tutorial/T7/calibrations/run_model_autocals.py b/docs/tutorial/T7/calibrations/run_model_autocals.py index f4baac2c..0dc315d6 100644 --- a/docs/tutorial/T7/calibrations/run_model_autocals.py +++ b/docs/tutorial/T7/calibrations/run_model_autocals.py @@ -13,20 +13,20 @@ import winsound print(os.getcwd()) -#run settings -yaml_dir = '../calibrations' -yaml_fname = 'typ_calibration_instructions' -yaml_path = f'{yaml_dir}/{yaml_fname}.yaml' -testing = False #<------------ +# run settings +yaml_dir = "../calibrations" +yaml_fname = "typ_calibration_instructions" +yaml_path = f"{yaml_dir}/{yaml_fname}.yaml" +testing = False # <------------ savecals = True -dis_model = 'typh' -out_path = 'outputs' +dis_model = "typh" +out_path = "outputs" -#make project ------------------------------------------------ +# make project ------------------------------------------------ print(os.getcwd()) -inputs = '../assets' -F = at.ProjectFramework(f'{inputs}/T7_framework.xlsx') -D = at.ProjectData.from_spreadsheet(f'{inputs}/T7_databook.xlsx', framework=F) +inputs = "../assets" +F = at.ProjectFramework(f"{inputs}/T7_framework.xlsx") +D = at.ProjectData.from_spreadsheet(f"{inputs}/T7_databook.xlsx", framework=F) P = at.Project(framework=F, databook=D, do_run=False) P.settings.update_time_vector(start=2000, end=2050, dt=1 / 52) @@ -37,44 +37,44 @@ # new folder to put calibrations in date = time.strftime("%Y-%m-%d_%H%M") -calspath = f'{out_path}/cal_{yaml_fname}' +calspath = f"{out_path}/cal_{yaml_fname}" if testing: - calspath += '_TESTING' + calspath += "_TESTING" savecals = False if savecals: - #save everything in folder + # save everything in folder try: os.makedirs(calspath) except FileExistsError: - calspath += f'_{date}' - os.makedirs(f'{calspath}') + calspath += f"_{date}" + os.makedirs(f"{calspath}") # save yaml file for reference - new_fname = f'{yaml_fname}_{date}.yaml' + new_fname = f"{yaml_fname}_{date}.yaml" shutil.copy(yaml_path, calspath) - shutil.move(f'{calspath}/{yaml_fname}.yaml', f'{calspath}/{new_fname}.yaml') #renaming file + shutil.move(f"{calspath}/{yaml_fname}.yaml", f"{calspath}/{new_fname}.yaml") # renaming file - #save logfile - at.start_logging(f'{calspath}/logfile_{date}.txt') + # save logfile + at.start_logging(f"{calspath}/logfile_{date}.txt") # save current runfile for reference - runfile_name = f'{os.path.basename(__file__)}_{date}' - shutil.copy(__file__, f'{calspath}/{runfile_name}') + runfile_name = f"{os.path.basename(__file__)}_{date}" + shutil.copy(__file__, f"{calspath}/{runfile_name}") # display tree cal_tree = at.yaml_calibration.build(yaml_path) print(cal_tree) -#run calibration w yaml instructions # <-------------------------- -newcal = P.calibrate(parset = cal, yaml=yaml_path, quiet=False, savedir=calspath, save_intermediate=False, verbose=0) +# run calibration w yaml instructions # <-------------------------- +newcal = P.calibrate(parset=cal, yaml=yaml_path, quiet=False, savedir=calspath, save_intermediate=False, verbose=0) -#save final calibration +# save final calibration date = time.strftime("%Y-%m-%d_%H%M") -newcal.save_calibration(f'{calspath}/typ_calibration.xlsx') +newcal.save_calibration(f"{calspath}/typ_calibration.xlsx") at.stop_logging() -#Notification - calibration finished -winsound.Beep(frequency = 2500, duration = 200) -winsound.Beep(frequency = 2750, duration = 200) -winsound.Beep(frequency = 3050, duration = 200) +# Notification - calibration finished +winsound.Beep(frequency=2500, duration=200) +winsound.Beep(frequency=2750, duration=200) +winsound.Beep(frequency=3050, duration=200) diff --git a/docs/tutorial/T7/calibrations/run_tutorial_autocals.py b/docs/tutorial/T7/calibrations/run_tutorial_autocals.py index 8a8bd7c7..5510fe43 100644 --- a/docs/tutorial/T7/calibrations/run_tutorial_autocals.py +++ b/docs/tutorial/T7/calibrations/run_tutorial_autocals.py @@ -5,7 +5,8 @@ # re-running the calibrations or trying out new versions of the model. import sys -in_path = '../inputs' + +in_path = "../inputs" sys.path.append(in_path) import atomica as at import atomica.yaml_calibration @@ -18,16 +19,16 @@ yaml_dir = os.getcwd() fnames = [f for f in os.listdir(yaml_dir) if isfile(f"{yaml_dir}/{f}")] yaml_files = [f for f in fnames if ".yaml" in f and "T7_YAML" in f] -yaml_files += 'WE_8' +yaml_files += "WE_8" -testing = False #<------------ +testing = False # <------------ savecals = True -out_path = 'outputs' +out_path = "outputs" -#make project ------------------------------------------------ -inputs = '../assets' -F = at.ProjectFramework(f'{inputs}/T7_framework.xlsx') -D = at.ProjectData.from_spreadsheet(f'{inputs}/T7_databook.xlsx', framework=F) +# make project ------------------------------------------------ +inputs = "../assets" +F = at.ProjectFramework(f"{inputs}/T7_framework.xlsx") +D = at.ProjectData.from_spreadsheet(f"{inputs}/T7_databook.xlsx", framework=F) P = at.Project(framework=F, databook=D, do_run=False) P.settings.update_time_vector(start=2000, end=2050, dt=1 / 52) @@ -37,44 +38,44 @@ # print('Existing calibration loaded') for yaml_fname in yaml_files: - yaml_path = f'{yaml_dir}/{yaml_fname}' + yaml_path = f"{yaml_dir}/{yaml_fname}" # new folder to put calibrations in date = time.strftime("%Y-%m-%d_%H%M") - calspath = f'{out_path}/cals_{yaml_fname[8]}' + calspath = f"{out_path}/cals_{yaml_fname[8]}" if savecals: - #save everything in folder + # save everything in folder try: os.makedirs(calspath) except FileExistsError: - calspath += f'_{date}' - os.makedirs(f'{calspath}') + calspath += f"_{date}" + os.makedirs(f"{calspath}") # save yaml file for reference - new_fname = f'{yaml_fname}_{date}.yaml' + new_fname = f"{yaml_fname}_{date}.yaml" shutil.copy(yaml_path, calspath) - shutil.move(f'{calspath}/{yaml_fname}', f'{calspath}/{new_fname}') #renaming file + shutil.move(f"{calspath}/{yaml_fname}", f"{calspath}/{new_fname}") # renaming file - #save logfile - at.start_logging(f'{calspath}/logfile_{date}.txt') + # save logfile + at.start_logging(f"{calspath}/logfile_{date}.txt") # save current runfile for reference - runfile_name = f'{os.path.basename(__file__)}_{date}' - shutil.copy(__file__, f'{calspath}/{runfile_name}') + runfile_name = f"{os.path.basename(__file__)}_{date}" + shutil.copy(__file__, f"{calspath}/{runfile_name}") # display tree cal_tree = at.yaml_calibration.build(yaml_path) print(cal_tree) - #run calibration w yaml instructions # <-------------------------- - newcal = P.calibrate(parset = cal, yaml=yaml_path, quiet=False, savedir=calspath, save_intermediate=False, verbose=0) + # run calibration w yaml instructions # <-------------------------- + newcal = P.calibrate(parset=cal, yaml=yaml_path, quiet=False, savedir=calspath, save_intermediate=False, verbose=0) - #save final calibration - newcal.save_calibration(f'{calspath}/cal_{yaml_fname[8]}') #newcal.save_calibration(f'{calspath}/cal_{yaml_fname}') + # save final calibration + newcal.save_calibration(f"{calspath}/cal_{yaml_fname[8]}") # newcal.save_calibration(f'{calspath}/cal_{yaml_fname}') at.stop_logging() -#Notification - calibration finished -winsound.Beep(frequency = 2500, duration = 200) -winsound.Beep(frequency = 2750, duration = 200) -winsound.Beep(frequency = 3050, duration = 200) +# Notification - calibration finished +winsound.Beep(frequency=2500, duration=200) +winsound.Beep(frequency=2750, duration=200) +winsound.Beep(frequency=3050, duration=200) diff --git a/tests/test_time_vector.py b/tests/test_time_vector.py index 652445cb..5fc3fae2 100644 --- a/tests/test_time_vector.py +++ b/tests/test_time_vector.py @@ -18,7 +18,7 @@ def test_time_vector(): dt = 1 / 12 settings = at.ProjectSettings(sim_start=analysis_years[0], sim_end=analysis_years[1] + 1 - dt, sim_dt=dt) #: Atomica project settings tvec = settings.tvec #: Simulation/result time points - assert set(np.unique(tvec.astype(int), return_counts=True)[1]) == {1/dt} # or pd.Series(tvec).astype(int).value_counts() + assert set(np.unique(tvec.astype(int), return_counts=True)[1]) == {1 / dt} # or pd.Series(tvec).astype(int).value_counts() if __name__ == "__main__": diff --git a/tests/test_tox_yaml.py b/tests/test_tox_yaml.py index 0e19195f..53c90bf9 100644 --- a/tests/test_tox_yaml.py +++ b/tests/test_tox_yaml.py @@ -7,21 +7,23 @@ # Basic minimum working product test to verify all yaml features run testdir = at.parent_dir() -tmpdir = testdir / 'temp' -yaml_dir = testdir/'yaml_tests' +tmpdir = testdir / "temp" +yaml_dir = testdir / "yaml_tests" # List yaml files in directory -yaml_files = list(yaml_dir.glob('*.yaml')) +yaml_files = list(yaml_dir.glob("*.yaml")) @pytest.fixture() def project(): - P = at.demo('udt_dyn', do_run=False) - P.settings.update_time_vector(start=2000, end=2050, dt=1/52) + P = at.demo("udt_dyn", do_run=False) + P.settings.update_time_vector(start=2000, end=2050, dt=1 / 52) return P + def test_save_intermediate(project): - project.calibrate(yaml=yaml_files[0], parset=project.make_parset(), quiet=False, savedir=tmpdir/'yaml_save_test', save_intermediate=True, verbose=0, max_time=0.1) + project.calibrate(yaml=yaml_files[0], parset=project.make_parset(), quiet=False, savedir=tmpdir / "yaml_save_test", save_intermediate=True, verbose=0, max_time=0.1) + @pytest.mark.parametrize("yaml_fname", yaml_files, ids=[x.stem for x in yaml_files]) def test_yaml_calibration(project, yaml_fname): @@ -36,8 +38,8 @@ def test_yaml_calibration(project, yaml_fname): # print(config_file_path) project.calibrate(yaml=yaml_fname, parset=project.make_parset(), quiet=False, savedir=tmpdir, save_intermediate=False, verbose=0, max_time=0.1) - #or can import in all the diff ways - make function - #also run in several diff ways? Or have a separate test for that? + # or can import in all the diff ways - make function + # also run in several diff ways? Or have a separate test for that? # Test saving the calibration # save() From 760d17539269c054ca8324ed74e52c77f07a0912 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 17 Feb 2025 19:43:57 +1000 Subject: [PATCH 110/161] Replace with patched sciris function --- atomica/plotting.py | 78 +++++++++++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/atomica/plotting.py b/atomica/plotting.py index d85d34e8..2f1567e8 100644 --- a/atomica/plotting.py +++ b/atomica/plotting.py @@ -1237,42 +1237,70 @@ def interpolate(self, new_tvec): return np.interp(sc.promotetoarray(new_tvec), self.tvec, self.vals, left=np.nan, right=np.nan) -def separatelegend(ax=None, handles=None, labels=None, reverse=False, legendsettings=None): - """Allows the legend of a figure to be rendered in a separate window instead""" +# Temporary copy of function from Sciris to remove after Sciris update +def _get_legend_handles(ax, handles, labels): + """ + Construct handle and label list, from one of: - # Handle settings - if ax is None: - fig, ax = plt.subplots() - else: - fig = ax.figure - fig.set_size_inches(4.0, 4.8) + - A list of handles and a list of labels + - A list of handles, where each handle contains the label + - An axis object, containing the objects that should appear in the legend + - A figure object, from which the first axis will be used + """ + if handles is None: + if ax is None: + ax = plt.gca() + elif isinstance(ax, plt.Figure): # Allows an argument of a figure instead of an axes # pragma: no cover + ax = ax.axes[-1] + handles, labels = ax.get_legend_handles_labels() + else: # pragma: no cover + if labels is None: + labels = [h.get_label() for h in handles] + else: + assert len(handles) == len(labels), f"Number of handles ({len(handles)}) and labels ({len(labels)}) must match" + return ax, handles, labels - l_settings = sc.mergedicts({"loc": "center", "bbox_to_anchor": None, "frameon": False}, legendsettings) +# Temporary copy of function from Sciris to remove after Sciris update +def separatelegend(ax=None, handles=None, labels=None, reverse=False, figsettings=None, legendsettings=None): + """ Allows the legend of a figure to be rendered in a separate window instead """ + + # Handle settings + f_settings = sc.mergedicts({'figsize':(4.0,4.8)}, figsettings) # (6.4,4.8) is the default, so make it a bit narrower + l_settings = sc.mergedicts({'loc': 'center', 'bbox_to_anchor': None, 'frameon': False}, legendsettings) # Get handles and labels - if handles is None and labels is None: - handles, labels = ax.get_legend_handles_labels() - elif handles is None: - handles, _ = ax.get_legend_handles_labels() - elif labels is None: - labels = [h.get_label() for h in handles] - assert len(handles) == len(labels), f"Number of handles ({len(handles)}) and labels ({len(labels)}) must match" + _, handles, labels = _get_legend_handles(ax, handles, labels) # Set up new plot - ax.set_position([-0.05, -0.05, 1.1, 1.1]) - ax.set_axis_off() + fig = plt.figure(**f_settings) + ax = fig.add_subplot(111) + ax.set_position([-0.05,-0.05,1.1,1.1]) # This cuts off the axis labels, ha-ha + ax.set_axis_off() # Hide axis lines + + # A legend renders the line/patch based on the object handle. However, an object + # can only appear in one figure. Thus, if the legend is in a different figure, the + # object cannot be shown in both the original figure and in the legend. Thus we need + # to copy the handles, and use the copies to render the legend + handles2 = [] + for h in handles: + h2 = sc.cp(h) + h2.axes = None + h2._parent_figure = None + h2.figure = None + handles2.append(h2) # Reverse order, e.g. for stacked plots - if reverse: # pragma: no cover - handles = handles[::-1] - labels = labels[::-1] + if reverse: # pragma: no cover + handles2 = handles2[::-1] + labels = labels[::-1] # Plot the new legend - ax.legend(handles=handles, labels=labels, **l_settings) + ax.legend(handles=handles2, labels=labels, **l_settings) return fig + def plot_bars(plotdata, stack_pops=None, stack_outputs=None, outer=None, legend_mode=None, show_all_labels=False, orientation="vertical") -> list: """ Produce a bar plot @@ -1796,12 +1824,14 @@ def _prepare_figures(dim1, dim2, n_cols): if legend_mode == "separate": reverse_legend = True if plot_type in ["stacked", "proportion"] else False - handles, labels = ax.get_legend_handles_labels() if not subplots: - separatelegend(axes[-1], handles=handles, labels=labels, reverse=reverse_legend) + # Replace the last figure with a legend figure + plt.close(figs[-1]) # TODO - update Sciris to allow passing in an existing figure + figs[-1] = separatelegend(ax, reverse=reverse_legend) else: legend_ax = axes[-1] + handles, labels = ax.get_legend_handles_labels() legend_ax.set_axis_off() # Hide axis lines if reverse_legend: # pragma: no cover handles = handles[::-1] From f8091fdb1349fa4b2a3700dbacb246d939a86af3 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 17 Feb 2025 21:15:17 +1000 Subject: [PATCH 111/161] Update python version in tox.ini --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 8172f379..e3648053 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py311 +envlist = py312 [testenv] description = Run basic usage tests From 6af1b2042c9a5ee0c5ae22665c6a60db19a7a712 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Mon, 17 Feb 2025 21:16:03 +1000 Subject: [PATCH 112/161] Update how path is identified --- docs/general/YAML_calibration.ipynb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/general/YAML_calibration.ipynb b/docs/general/YAML_calibration.ipynb index 027215e2..adf79647 100644 --- a/docs/general/YAML_calibration.ipynb +++ b/docs/general/YAML_calibration.ipynb @@ -34,7 +34,8 @@ "outputs": [], "source": [ "import atomica as at\n", - "yaml_file = at.rootdir/'docs'/'tutorial'/'T7'/'calibrations'/'T7_YAML_3_repeats.yaml'\n", + "import pathlib\n", + "yaml_file = pathlib.Path.cwd()/'..'/'tutorial'/'T7'/'calibrations'/'T7_YAML_3_repeats.yaml'\n", "print(open(yaml_file).read())" ] }, From 4d4fa1713924f5bc5d767f0b73f8687d56af311a Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Tue, 18 Feb 2025 11:03:22 +1000 Subject: [PATCH 113/161] Add test --- tests/sir_framework_default_all.xlsx | Bin 0 -> 27090 bytes tests/test_tox_databooks.py | 18 +++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 tests/sir_framework_default_all.xlsx diff --git a/tests/sir_framework_default_all.xlsx b/tests/sir_framework_default_all.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..99b7b42940ba3e133959ba8709ee237e3ea7e964 GIT binary patch literal 27090 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 KlxG&d{{0`UMU7(s literal 0 HcmV?d00001 diff --git a/tests/test_tox_databooks.py b/tests/test_tox_databooks.py index 7958424f..0952a698 100644 --- a/tests/test_tox_databooks.py +++ b/tests/test_tox_databooks.py @@ -180,10 +180,26 @@ def test_databook_all(): d = at.PlotData(res, outputs=["sus", "ch_prev", "ch_all"], project=P) at.plot_series(d, axis="pops", data=P.data) +def test_databook_default_all(): + F = at.ProjectFramework(testdir/'sir_framework_default_all.xlsx') + D = at.ProjectData.new(F, np.arange(2000,2005), pops=4, transfers=1) + D.save(tmpdir / "databook_default_all_test.xlsx") # Test saving it back + + D.add_pop('new','new') + assert list(D.tdve['sus'].ts.keys()) == ['pop_0','pop_1','pop_2','pop_3','new'] + assert list(D.tdve['ch_prev'].ts.keys()) == ['All'] + + D.tdve['contacts'].ts['pop_0'] = D.tdve['contacts'].ts['All'] + del D.tdve['contacts'].ts['All'] + D.add_pop('new2','new2') + assert list(D.tdve['ch_prev'].ts.keys()) == ['All'] + assert list(D.tdve['contacts'].ts.keys()) == ['pop_0','new2'] + D.save(tmpdir / "databook_default_all_test_2.xlsx") # Test saving it back if __name__ == "__main__": # test_mixed_years_2() # test_mixed_years_1() # test_databooks() # test_databook_comments() - test_databook_all() + # test_databook_all() + test_databook_default_all() From e16cdfaee63b167c6894b91e2b017eb77cc4ba66 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Tue, 18 Feb 2025 11:03:53 +1000 Subject: [PATCH 114/161] Fix migrations --- atomica/data.py | 11 +++++++++- atomica/migration.py | 41 +++++++++++++++++++++++++++++++++++++ tests/test_tox_migration.py | 5 +++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/atomica/data.py b/atomica/data.py index d8531d7d..6737645b 100644 --- a/atomica/data.py +++ b/atomica/data.py @@ -58,11 +58,20 @@ def __init__(self, framework): self.tdve_pages = sc.odict() #: This is an odict mapping worksheet name to an (ordered) list of TDVE code names appearing on that sheet # Internal storage used with methods while writing - self._pop_types = list(framework.pop_types.keys()) # : Store set of valid population types from framework + self._pop_types = list(framework.pop_types.keys()) #: Store set of valid population types from framework self._formats = None #: Temporary storage for the Excel formatting while writing a databook self._book = None #: Temporary storage for the workbook while writing a databook self._references = None #: Temporary storage for cell references while writing a databook + + def __setstate__(self, d): + from .migration import migrate + + self.__dict__ = d + projectdata = migrate(self) + self.__dict__ = projectdata.__dict__ + + def tables(self): """ Return iterator over all TDVE and TDC tables diff --git a/atomica/migration.py b/atomica/migration.py index 10abed30..fdc351f9 100644 --- a/atomica/migration.py +++ b/atomica/migration.py @@ -812,3 +812,44 @@ def _convert_framework_columns(framework): def _parset_add_initialization(parset): parset.initialization = None return parset + + +@migration("ProjectData", "1.30.0", "1.31.0", "Add pop types attribute and default_all") +def _projectdata_add_types_default(D): + + if not hasattr(D,'_pop_types'): + # We have to check for existence because + # Are any population types present? + pop_types = list(x['type'] for x in D.pops.values() if 'type' in x) + if not pop_types: + pop_types = [FS.DEFAULT_POP_TYPE] + + for pop, spec in D.pops.items(): + if 'type' not in spec: + spec['type'] = pop_types[0] + D._pop_types = list({x['type']:None for x in D.pops.values()}.keys()) # Using a dictionary here allows for order-preserving unique + + for tdve in D.tdve.values(): + + # Fix the '_add_pop_type' migration which added tdve.type instead of tdve.pop_type + if hasattr(tdve, 'type'): + tdve.pop_type = tdve.type + delattr(tdve, 'type') + elif not hasattr(tdve, 'pop_type'): + tdve.pop_type = D._pop_types[0] # The majority of the time, if the pop_type is missing, the default needs to be added + + # Also add the default_all attribute + tdve.default_all = False + + # Some old TDVE tables have a lowercase 'n.a.' instead of the correct default value + for ts in tdve.ts.values(): + if ts.units == FS.DEFAULT_SYMBOL_INAPPLICABLE.lower(): + ts.units = FS.DEFAULT_SYMBOL_INAPPLICABLE + + # A TDVE should always have some allowed units, if the allowed units have not been populated, then draw + # them from the ts entries. There are some older saved files that may have no allowed units even though the ts + # entries themselves have units. + if not hasattr(tdve, 'allowed_units') or not tdve.allowed_units: + tdve.allowed_units = list({x.units:None for x in tdve.ts.values()}.keys()) + + return D diff --git a/tests/test_tox_migration.py b/tests/test_tox_migration.py index 63393827..d3219bc4 100644 --- a/tests/test_tox_migration.py +++ b/tests/test_tox_migration.py @@ -33,6 +33,11 @@ def test_migration(): P.databook.save(tmpdir / "migration_test_databook_save") # Save original databook P.data.save(tmpdir / "migration_test_data_save") # Re-convert data to spreadsheet and save + # Test databook operations + P.data.add_pop('test_pop','test_pop') # Requires migration + P.data.add_transfer('test_transfer','test_transfer') + P.data.add_interaction('test_interaction','test_interaction') + if __name__ == "__main__": test_migration() From 5d26e8954451ea1d28a3abe9e2039b86829b5a9e Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Tue, 18 Feb 2025 11:06:09 +1000 Subject: [PATCH 115/161] Increment version, update logic for manually edited tables --- CHANGELOG.md | 4 ++++ atomica/data.py | 17 ++++++++++------- atomica/excel.py | 4 ++-- atomica/version.py | 2 +- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 471965e1..c1f60ebb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ This file records changes to the codebase grouped by version release. Unreleased changes are generally only present during development (relevant parts of the changelog can be written and saved in that section before a version number has been assigned) +## [1.31.0] - 2025-02-18 + +- Framework definitions of compartments, characteristics, and parameters support a new column 'databook default all'. If set to 'y', then when a databook is produced, the data entry table will only contain a record for 'All' instead of having population-specific rows. Further manual editing of the tables is supported as normal. + ## [1.30.0] - 2025-02-17 - Automatic calibration can now selectively weight parts of the time series to select or prioritise a subset of time points. diff --git a/atomica/data.py b/atomica/data.py index 6737645b..8f7b5eb9 100644 --- a/atomica/data.py +++ b/atomica/data.py @@ -63,7 +63,6 @@ def __init__(self, framework): self._book = None #: Temporary storage for the workbook while writing a databook self._references = None #: Temporary storage for cell references while writing a databook - def __setstate__(self, d): from .migration import migrate @@ -71,7 +70,6 @@ def __setstate__(self, d): projectdata = migrate(self) self.__dict__ = projectdata.__dict__ - def tables(self): """ Return iterator over all TDVE and TDC tables @@ -270,7 +268,7 @@ class instance (e.g. if creating a new databook). pop_type = spec.get("population type") databook_order = spec.get("databook order") full_name = spec["display name"] - default_all = spec.get("databook default all") + default_all = spec["databook default all"] == "y" allowed_units = [framework.get_databook_units(full_name)] if pd.isna(databook_order): @@ -287,8 +285,10 @@ class instance (e.g. if creating a new databook). data.tdve[spec.name].tvec = [] # If parameter is timed, don't show any years data.tdve[spec.name].write_uncertainty = False # Don't show uncertainty for timed parameters. In theory users could manually add the column and sample over it, but because the duration is rounded to the timestep, it's likely to have confusing stepped effects data.tdve[spec.name].pop_type = pop_type + if default_all: - data.tdve[spec.name].ts['All'] = TimeSeries(units=allowed_units[0]) + # add_pop normally adds TDVE rows, but it won't operate on any TDVEs that default to 'All' so we need to add the 'All' rows here + data.tdve[spec.name].ts["All"] = TimeSeries(units=allowed_units[0]) # Now convert pages to full names and sort them into the correct order for _, spec in framework.sheets["databook pages"][0].iterrows(): @@ -640,7 +640,7 @@ def add_pop(self, code_name: str, full_name: str, pop_type: str = None) -> None: :param code_name: The code name for the new population :param full_name: The full name/label for the new population - :param pop_type: String with the population type code name + :param pop_type: String with the population type code name (optional) - default is the type of the first population """ @@ -666,8 +666,11 @@ def add_pop(self, code_name: str, full_name: str, pop_type: str = None) -> None: for tdve in self.tdve.values(): # Since TDVEs in databooks must have the unit set in the framework, all ts objects must share the same units # And, there is only supposed to be one type of unit allowed for TDVE tables (if the unit is empty, it will be 'N.A.') - # so can just pick the first of the allowed units - if tdve.pop_type == pop_type and not (hasattr(tdve, 'default_all') and tdve.default_all): + # so can just pick the first of the allowed units. We will add the population row if the pop type matches and if + # the TDVE is either not a 'default_all' or if the user has removed the 'All' row from the TDVE despite it being default_all + if tdve.pop_type != pop_type or (tdve.default_all and ("All" in tdve.ts or "all" in tdve.ts)): + continue + else: tdve.ts[code_name] = TimeSeries(units=tdve.allowed_units[0]) def rename_pop(self, existing_code_name: str, new_code_name: str, new_full_name: str) -> None: diff --git a/atomica/excel.py b/atomica/excel.py index 9501b184..304490ab 100644 --- a/atomica/excel.py +++ b/atomica/excel.py @@ -906,8 +906,8 @@ def __init__(self, name, tvec: np.array = None, ts=None, allowed_units: list = N self.write_units = None #: Write a column for units (if None, units will be written if any of the TimeSeries have units) self.write_uncertainty = None #: Write a column for uncertainty (if None, uncertainty will be written if any of the TimeSeries have uncertainty) self.write_assumption = None #: Write a column for assumption/constant (if None, assumption will be written if any of the TimeSeries have an assumption) - - self.default_all = default_all #If the TDVE should by default only have the 'All' population in the databook e.g. the same value for all populations unless exceptions are manually entered + + self.default_all = default_all #: Record whether the framework specifies that this TDVE should default to having an 'All' row instead of population-specific rows (the user can manually modify further) def __repr__(self): output = sc.prepr(self) diff --git a/atomica/version.py b/atomica/version.py index 91aaedea..6d57766a 100644 --- a/atomica/version.py +++ b/atomica/version.py @@ -6,6 +6,6 @@ import sciris as sc -version = "1.30.0" +version = "1.31.0" versiondate = "2025-02-17" gitinfo = sc.gitinfo(__file__) From d8d59260b03f49f44366b45924068d467a13d630 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Tue, 18 Feb 2025 11:06:25 +1000 Subject: [PATCH 116/161] Update formatting --- atomica/framework.py | 6 ++++++ atomica/migration.py | 22 +++++++++++----------- atomica/plotting.py | 18 +++++++++--------- tests/test_tox_databooks.py | 22 ++++++++++++---------- tests/test_tox_migration.py | 6 +++--- 5 files changed, 41 insertions(+), 33 deletions(-) diff --git a/atomica/framework.py b/atomica/framework.py index 7028bcd0..76d13de1 100644 --- a/atomica/framework.py +++ b/atomica/framework.py @@ -632,6 +632,7 @@ def _sanitize_compartments(self) -> None: "is source": "n", "is junction": "n", "databook page": None, + "databook default all": "n", "default value": None, "population type": None, "databook order": None, # Default is for it to be randomly ordered if the databook page is not None @@ -643,6 +644,7 @@ def _sanitize_compartments(self) -> None: "is sink": {"y", "n"}, "is source": {"y", "n"}, "is junction": {"y", "n"}, + "databook default all": {"y", "n"}, } numeric_columns = ["databook order", "default value"] @@ -723,6 +725,7 @@ def _sanitize_characteristics(self) -> None: "default value": None, "databook page": None, "databook order": None, + "databook default all": "n", "guidance": None, "population type": None, "provenance": FS.DEFAULT_PROVENANCE, @@ -730,6 +733,7 @@ def _sanitize_characteristics(self) -> None: valid_content = { "display name": None, "components": None, + "databook default all": {"y", "n"}, } numeric_columns = ["databook order", "default value"] @@ -861,6 +865,7 @@ def _sanitize_parameters(self) -> None: "function": None, "databook page": None, "databook order": None, + "databook default all": "n", "targetable": "n", "guidance": None, "timescale": None, @@ -874,6 +879,7 @@ def _sanitize_parameters(self) -> None: "targetable": {"y", "n"}, "is derivative": {"y", "n"}, "timed": {"y", "n"}, + "databook default all": {"y", "n"}, } numeric_columns = ["databook order", "default value", "minimum value", "maximum value", "timescale"] diff --git a/atomica/migration.py b/atomica/migration.py index fdc351f9..724855a7 100644 --- a/atomica/migration.py +++ b/atomica/migration.py @@ -817,26 +817,26 @@ def _parset_add_initialization(parset): @migration("ProjectData", "1.30.0", "1.31.0", "Add pop types attribute and default_all") def _projectdata_add_types_default(D): - if not hasattr(D,'_pop_types'): + if not hasattr(D, "_pop_types"): # We have to check for existence because # Are any population types present? - pop_types = list(x['type'] for x in D.pops.values() if 'type' in x) + pop_types = list(x["type"] for x in D.pops.values() if "type" in x) if not pop_types: pop_types = [FS.DEFAULT_POP_TYPE] for pop, spec in D.pops.items(): - if 'type' not in spec: - spec['type'] = pop_types[0] - D._pop_types = list({x['type']:None for x in D.pops.values()}.keys()) # Using a dictionary here allows for order-preserving unique + if "type" not in spec: + spec["type"] = pop_types[0] + D._pop_types = list({x["type"]: None for x in D.pops.values()}.keys()) # Using a dictionary here allows for order-preserving unique for tdve in D.tdve.values(): # Fix the '_add_pop_type' migration which added tdve.type instead of tdve.pop_type - if hasattr(tdve, 'type'): + if hasattr(tdve, "type"): tdve.pop_type = tdve.type - delattr(tdve, 'type') - elif not hasattr(tdve, 'pop_type'): - tdve.pop_type = D._pop_types[0] # The majority of the time, if the pop_type is missing, the default needs to be added + delattr(tdve, "type") + elif not hasattr(tdve, "pop_type"): + tdve.pop_type = D._pop_types[0] # The majority of the time, if the pop_type is missing, the default needs to be added # Also add the default_all attribute tdve.default_all = False @@ -849,7 +849,7 @@ def _projectdata_add_types_default(D): # A TDVE should always have some allowed units, if the allowed units have not been populated, then draw # them from the ts entries. There are some older saved files that may have no allowed units even though the ts # entries themselves have units. - if not hasattr(tdve, 'allowed_units') or not tdve.allowed_units: - tdve.allowed_units = list({x.units:None for x in tdve.ts.values()}.keys()) + if not hasattr(tdve, "allowed_units") or not tdve.allowed_units: + tdve.allowed_units = list({x.units: None for x in tdve.ts.values()}.keys()) return D diff --git a/atomica/plotting.py b/atomica/plotting.py index 2f1567e8..1931b996 100644 --- a/atomica/plotting.py +++ b/atomica/plotting.py @@ -1250,23 +1250,24 @@ def _get_legend_handles(ax, handles, labels): if handles is None: if ax is None: ax = plt.gca() - elif isinstance(ax, plt.Figure): # Allows an argument of a figure instead of an axes # pragma: no cover + elif isinstance(ax, plt.Figure): # Allows an argument of a figure instead of an axes # pragma: no cover ax = ax.axes[-1] handles, labels = ax.get_legend_handles_labels() - else: # pragma: no cover + else: # pragma: no cover if labels is None: labels = [h.get_label() for h in handles] else: assert len(handles) == len(labels), f"Number of handles ({len(handles)}) and labels ({len(labels)}) must match" return ax, handles, labels + # Temporary copy of function from Sciris to remove after Sciris update def separatelegend(ax=None, handles=None, labels=None, reverse=False, figsettings=None, legendsettings=None): - """ Allows the legend of a figure to be rendered in a separate window instead """ + """Allows the legend of a figure to be rendered in a separate window instead""" # Handle settings - f_settings = sc.mergedicts({'figsize':(4.0,4.8)}, figsettings) # (6.4,4.8) is the default, so make it a bit narrower - l_settings = sc.mergedicts({'loc': 'center', 'bbox_to_anchor': None, 'frameon': False}, legendsettings) + f_settings = sc.mergedicts({"figsize": (4.0, 4.8)}, figsettings) # (6.4,4.8) is the default, so make it a bit narrower + l_settings = sc.mergedicts({"loc": "center", "bbox_to_anchor": None, "frameon": False}, legendsettings) # Get handles and labels _, handles, labels = _get_legend_handles(ax, handles, labels) @@ -1274,7 +1275,7 @@ def separatelegend(ax=None, handles=None, labels=None, reverse=False, figsetting # Set up new plot fig = plt.figure(**f_settings) ax = fig.add_subplot(111) - ax.set_position([-0.05,-0.05,1.1,1.1]) # This cuts off the axis labels, ha-ha + ax.set_position([-0.05, -0.05, 1.1, 1.1]) # This cuts off the axis labels, ha-ha ax.set_axis_off() # Hide axis lines # A legend renders the line/patch based on the object handle. However, an object @@ -1290,9 +1291,9 @@ def separatelegend(ax=None, handles=None, labels=None, reverse=False, figsetting handles2.append(h2) # Reverse order, e.g. for stacked plots - if reverse: # pragma: no cover + if reverse: # pragma: no cover handles2 = handles2[::-1] - labels = labels[::-1] + labels = labels[::-1] # Plot the new legend ax.legend(handles=handles2, labels=labels, **l_settings) @@ -1300,7 +1301,6 @@ def separatelegend(ax=None, handles=None, labels=None, reverse=False, figsetting return fig - def plot_bars(plotdata, stack_pops=None, stack_outputs=None, outer=None, legend_mode=None, show_all_labels=False, orientation="vertical") -> list: """ Produce a bar plot diff --git a/tests/test_tox_databooks.py b/tests/test_tox_databooks.py index 0952a698..03110d42 100644 --- a/tests/test_tox_databooks.py +++ b/tests/test_tox_databooks.py @@ -180,22 +180,24 @@ def test_databook_all(): d = at.PlotData(res, outputs=["sus", "ch_prev", "ch_all"], project=P) at.plot_series(d, axis="pops", data=P.data) + def test_databook_default_all(): - F = at.ProjectFramework(testdir/'sir_framework_default_all.xlsx') - D = at.ProjectData.new(F, np.arange(2000,2005), pops=4, transfers=1) + F = at.ProjectFramework(testdir / "sir_framework_default_all.xlsx") + D = at.ProjectData.new(F, np.arange(2000, 2005), pops=4, transfers=1) D.save(tmpdir / "databook_default_all_test.xlsx") # Test saving it back - D.add_pop('new','new') - assert list(D.tdve['sus'].ts.keys()) == ['pop_0','pop_1','pop_2','pop_3','new'] - assert list(D.tdve['ch_prev'].ts.keys()) == ['All'] + D.add_pop("new", "new") + assert list(D.tdve["sus"].ts.keys()) == ["pop_0", "pop_1", "pop_2", "pop_3", "new"] + assert list(D.tdve["ch_prev"].ts.keys()) == ["All"] - D.tdve['contacts'].ts['pop_0'] = D.tdve['contacts'].ts['All'] - del D.tdve['contacts'].ts['All'] - D.add_pop('new2','new2') - assert list(D.tdve['ch_prev'].ts.keys()) == ['All'] - assert list(D.tdve['contacts'].ts.keys()) == ['pop_0','new2'] + D.tdve["contacts"].ts["pop_0"] = D.tdve["contacts"].ts["All"] + del D.tdve["contacts"].ts["All"] + D.add_pop("new2", "new2") + assert list(D.tdve["ch_prev"].ts.keys()) == ["All"] + assert list(D.tdve["contacts"].ts.keys()) == ["pop_0", "new2"] D.save(tmpdir / "databook_default_all_test_2.xlsx") # Test saving it back + if __name__ == "__main__": # test_mixed_years_2() # test_mixed_years_1() diff --git a/tests/test_tox_migration.py b/tests/test_tox_migration.py index d3219bc4..76c63e4e 100644 --- a/tests/test_tox_migration.py +++ b/tests/test_tox_migration.py @@ -34,9 +34,9 @@ def test_migration(): P.data.save(tmpdir / "migration_test_data_save") # Re-convert data to spreadsheet and save # Test databook operations - P.data.add_pop('test_pop','test_pop') # Requires migration - P.data.add_transfer('test_transfer','test_transfer') - P.data.add_interaction('test_interaction','test_interaction') + P.data.add_pop("test_pop", "test_pop") # Requires migration + P.data.add_transfer("test_transfer", "test_transfer") + P.data.add_interaction("test_interaction", "test_interaction") if __name__ == "__main__": From 23ac4244a5224e6b808e07e543f815d3b8ef7c47 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Tue, 18 Feb 2025 11:09:35 +1000 Subject: [PATCH 117/161] Update PyPI url --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2316c6cb..abea6312 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# Atomica +1# Atomica [![Build Status](https://dev.azure.com/AtomicaTeam/Atomica/_apis/build/status/atomicateam.atomica?branchName=master)](https://dev.azure.com/AtomicaTeam/Atomica/_build/latest?definitionId=1&branchName=master) -[![PyPi version](https://badgen.net/pypi/v/atomica/)](https://pypi.com/project/atomica) +[![PyPi version](https://badgen.net/pypi/v/atomica/)](https://pypi.org/project/atomica) Atomica is a simulation engine for compartmental models. It can be used to simulate disease epidemics, health care cascades, and many other things. From aef5b474ed4c0719c0efd253c33cc5328878e970 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Tue, 18 Feb 2025 11:33:33 +1000 Subject: [PATCH 118/161] Add version attribute --- atomica/data.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/atomica/data.py b/atomica/data.py index 8f7b5eb9..60763755 100644 --- a/atomica/data.py +++ b/atomica/data.py @@ -21,6 +21,7 @@ from collections import defaultdict import pandas as pd import itertools +from .version import version, gitinfo __all__ = ["InvalidDatabook", "ProjectData"] @@ -63,6 +64,9 @@ def __init__(self, framework): self._book = None #: Temporary storage for the workbook while writing a databook self._references = None #: Temporary storage for cell references while writing a databook + self.version = version #: Current Atomica version + self.gitinfo = sc.dcp(gitinfo) #: Atomica Git version information, if being run in a Git repository + def __setstate__(self, d): from .migration import migrate From 13b1117a8c2d49eb031d0ff4992a1eba1cb50327 Mon Sep 17 00:00:00 2001 From: Romesh Abeysuriya Date: Tue, 18 Feb 2025 12:51:32 +1000 Subject: [PATCH 119/161] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index abea6312..59573fd3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -1# Atomica +# Atomica [![Build Status](https://dev.azure.com/AtomicaTeam/Atomica/_apis/build/status/atomicateam.atomica?branchName=master)](https://dev.azure.com/AtomicaTeam/Atomica/_build/latest?definitionId=1&branchName=master) From ffa16e730313041394e13fa6780f0197eb966c9d Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Thu, 20 Feb 2025 14:03:38 +0100 Subject: [PATCH 120/161] Add deaths calibration to all worked example steps --- docs/tutorial/T7/calibrations/WE_1.yaml | 3 +-- docs/tutorial/T7/calibrations/WE_2.yaml | 5 +++++ docs/tutorial/T7/calibrations/WE_3.yaml | 7 ++++++- docs/tutorial/T7/calibrations/WE_4.yaml | 7 ++++++- docs/tutorial/T7/calibrations/WE_5.yaml | 5 +++++ docs/tutorial/T7/calibrations/WE_6.yaml | 5 +++++ docs/tutorial/T7/calibrations/WE_7.yaml | 5 +++++ docs/tutorial/T7/calibrations/WE_8.yaml | 1 - 8 files changed, 33 insertions(+), 5 deletions(-) diff --git a/docs/tutorial/T7/calibrations/WE_1.yaml b/docs/tutorial/T7/calibrations/WE_1.yaml index d99f3331..e93ca5e4 100644 --- a/docs/tutorial/T7/calibrations/WE_1.yaml +++ b/docs/tutorial/T7/calibrations/WE_1.yaml @@ -1,7 +1,6 @@ - - calibration: Population calibration: + Match population sizes: adjustables: b_rate, mig_rate measurables: alive diff --git a/docs/tutorial/T7/calibrations/WE_2.yaml b/docs/tutorial/T7/calibrations/WE_2.yaml index d2aa7e29..00af8391 100644 --- a/docs/tutorial/T7/calibrations/WE_2.yaml +++ b/docs/tutorial/T7/calibrations/WE_2.yaml @@ -1,9 +1,14 @@ calibration: Population calibration: repeats: 10 + Match population sizes: adjustables: b_rate, mig_rate: lower_bound: 0.1 upper_bound: 10 measurables: alive + + Match deaths: + adjustables: d_rate + measurables: deaths diff --git a/docs/tutorial/T7/calibrations/WE_3.yaml b/docs/tutorial/T7/calibrations/WE_3.yaml index fa87a1c3..6e90a45e 100644 --- a/docs/tutorial/T7/calibrations/WE_3.yaml +++ b/docs/tutorial/T7/calibrations/WE_3.yaml @@ -4,6 +4,11 @@ calibration: Population calibration: repeats: 10 + Match population sizes: adjustables: b_rate, mig_rate - measurables: alive \ No newline at end of file + measurables: alive + + Match deaths: + adjustables: d_rate + measurables: deaths \ No newline at end of file diff --git a/docs/tutorial/T7/calibrations/WE_4.yaml b/docs/tutorial/T7/calibrations/WE_4.yaml index 77560b42..a422925a 100644 --- a/docs/tutorial/T7/calibrations/WE_4.yaml +++ b/docs/tutorial/T7/calibrations/WE_4.yaml @@ -4,6 +4,11 @@ calibration: Population calibration: repeats: 10 + Match population sizes: adjustables: (b_rate, 0-4), mig_rate - measurables: alive \ No newline at end of file + measurables: alive + + Match deaths: + adjustables: d_rate + measurables: deaths \ No newline at end of file diff --git a/docs/tutorial/T7/calibrations/WE_5.yaml b/docs/tutorial/T7/calibrations/WE_5.yaml index 3cdce1e6..da9fa653 100644 --- a/docs/tutorial/T7/calibrations/WE_5.yaml +++ b/docs/tutorial/T7/calibrations/WE_5.yaml @@ -4,6 +4,7 @@ calibration: Population calibration: repeats: 10 + Match population sizes: adjustables: (b_rate, 0-4): @@ -11,3 +12,7 @@ calibration: mig_rate: lower_bound: 0.1 measurables: alive + + Match deaths: + adjustables: d_rate + measurables: deaths diff --git a/docs/tutorial/T7/calibrations/WE_6.yaml b/docs/tutorial/T7/calibrations/WE_6.yaml index 70669139..02a6554c 100644 --- a/docs/tutorial/T7/calibrations/WE_6.yaml +++ b/docs/tutorial/T7/calibrations/WE_6.yaml @@ -4,6 +4,7 @@ calibration: Population calibration: repeats: 10 + Match population sizes: adjustables: (b_rate, 0-4): @@ -12,5 +13,9 @@ calibration: lower_bound: 0.1 measurables: alive + Match deaths: + adjustables: d_rate + measurables: deaths + set_initialization: init_year: 2025 \ No newline at end of file diff --git a/docs/tutorial/T7/calibrations/WE_7.yaml b/docs/tutorial/T7/calibrations/WE_7.yaml index 1a3c6dc2..1628e563 100644 --- a/docs/tutorial/T7/calibrations/WE_7.yaml +++ b/docs/tutorial/T7/calibrations/WE_7.yaml @@ -4,6 +4,7 @@ calibration: Population calibration: repeats: 10 + Match population sizes: adjustables: (b_rate, 0-4): @@ -12,6 +13,10 @@ calibration: lower_bound: 0.1 measurables: alive + Match deaths: + adjustables: d_rate + measurables: deaths + clear_initialization: True set_initialization: diff --git a/docs/tutorial/T7/calibrations/WE_8.yaml b/docs/tutorial/T7/calibrations/WE_8.yaml index 4256b51b..849d5750 100644 --- a/docs/tutorial/T7/calibrations/WE_8.yaml +++ b/docs/tutorial/T7/calibrations/WE_8.yaml @@ -19,7 +19,6 @@ calibration: adjustables: d_rate measurables: deaths - clear_initialization: True set_initialization: From 0e789fc8422fafed2be16983993592373c7d4e5f Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Thu, 20 Feb 2025 14:08:55 +0100 Subject: [PATCH 121/161] Change initialisation spelling to initialization in YAML files --- .../T7/calibrations/T7_YAML_7_transience_initialisation.yaml | 2 +- docs/tutorial/T7/calibrations/T7_YAML_8_clearing_init.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/T7/calibrations/T7_YAML_7_transience_initialisation.yaml b/docs/tutorial/T7/calibrations/T7_YAML_7_transience_initialisation.yaml index d0d4e37e..508c0749 100644 --- a/docs/tutorial/T7/calibrations/T7_YAML_7_transience_initialisation.yaml +++ b/docs/tutorial/T7/calibrations/T7_YAML_7_transience_initialisation.yaml @@ -3,7 +3,7 @@ - set_initialisation: + set_initialization: init_year: 2010 constant_parset: True diff --git a/docs/tutorial/T7/calibrations/T7_YAML_8_clearing_init.yaml b/docs/tutorial/T7/calibrations/T7_YAML_8_clearing_init.yaml index 6dd34940..314f0069 100644 --- a/docs/tutorial/T7/calibrations/T7_YAML_8_clearing_init.yaml +++ b/docs/tutorial/T7/calibrations/T7_YAML_8_clearing_init.yaml @@ -1,6 +1,6 @@ calibration: - clear_initialisation: True + clear_initialization: True From e30d0848f75f28a926fbc592fb07ad7aa20509d1 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Fri, 21 Feb 2025 18:35:36 +0100 Subject: [PATCH 122/161] Update T7 notebook -Update text, fix typos -Fix broken links and paths -Fix worked example table -Consistent spelling of 'initialization' --- .../tutorial/T7/T7_YAML_autocalibration.ipynb | 115 +++++++++--------- 1 file changed, 57 insertions(+), 58 deletions(-) diff --git a/docs/tutorial/T7/T7_YAML_autocalibration.ipynb b/docs/tutorial/T7/T7_YAML_autocalibration.ipynb index ff2b517e..321f7b87 100644 --- a/docs/tutorial/T7/T7_YAML_autocalibration.ipynb +++ b/docs/tutorial/T7/T7_YAML_autocalibration.ipynb @@ -47,7 +47,7 @@ "source": [ "## Basic calibration example\n", "\n", - "In this tutorial, we will work with a simple version of a typhoid model. This model captures typhoid infections, as well as asymptomatic carriers and vaccination. Firstly, we need to create an Atomica `Project` by loading in the Framework and Databook files, just like we did in [the first Atomica tutorial](/tutorial/T1-Defining-a-model.html). The Framework and Databook for this project can be found in the Atomica repository under `assets/T7`. " + "In this tutorial, we will work with a simple version of a typhoid model. This model captures typhoid infections, as well as asymptomatic carriers and vaccination. Firstly, we need to create an Atomica `Project` by loading in the Framework and Databook files, just like we did in [the first Atomica tutorial](https://atomica.tools/docs/master/tutorial/T1-Defining-a-model.html). The Framework and Databook for this project can be found in the Atomica repository under `T7/assets`." ] }, { @@ -260,7 +260,7 @@ "\n", "- Calibration block\n", "- Initialization block\n", - "- Clear intialization block\n", + "- Intialization clearing block\n", "- Saving block" ] }, @@ -271,11 +271,11 @@ "source": [ "### Calibration blocks\n", "\n", - "In all of the YAML examples shown above, we have worked with 'calibration blocks', which are the main type of action. Calibration blocks are defined by the fact that they contain the keywords `adjustables` and `measurables`. Under `adjustables`, we list the parameters for Atomica’s optimisation algorithm to adjust, and under `measurables`, we list the parameters to calibrate to. Each calibration block provides instructions for one optimisation run, and is equivalent to making a call to `P.calibrate()` with the same adjustables and measurables.\n", + "In all of the YAML examples shown above, we have worked with 'calibration blocks', which are the main type of action. Calibration blocks are defined by the fact that they contain the keywords `adjustables` and `measurables`. Under `adjustables`, we list the parameters for Atomica’s optimisation algorithm to adjust, and under `measurables`, we list the parameters to calibrate to. Each calibration block provides instructions for one optimisation run, and is equivalent to making one call to `P.calibrate()` with the same adjustables and measurables.\n", "\n", "#### Adjustable and measurable settings\n", "\n", - "So far, we have only specified the names of the adjustables and measurables, with no further information – in that case, the optimisation algorithm will use the default settings for adjustables and measurables. For more flexibility, we can customise the settings to be used for the optimisation. The settings for the adjustables and measurables directly map to the options supported by `P.calibrate()`. \n", + "So far, we have only specified the names of the adjustables and measurables, with no further information – in that case, the optimisation algorithm will use the default calibration settings for adjustables and measurables. For more flexibility, we can customise the settings that will be used for the optimisation, which directly map to the options supported by `P.calibrate()`.\n", "\n", "Each adjustable has:\n", "\n", @@ -283,21 +283,21 @@ "- `pop_name`: Population to calibrate (default: all populations)\n", "- `lower_bound`: Lowest value the y-factor will be allowed to take (default: 0.1)\n", "- `upper_bound`: Highest value the y-factor will be allowed to take (default: 10)\n", - "- `starting_y_factor`: Y-factor value the autocalibration will start from when running the optimisation algorithm (default: the adjustable’s current `y_factor` in the parset)\n", + "- `starting_y_factor`: Y-factor value the optimisation algorithm will start from (default: the adjustable's current `y_factor` in the parset)\n", "\n", "Each measurable has:\n", "\n", "- `meas_label` (required): Measurable parameter codename (can be found in the framework)\n", "- `pop_name`: Population to use for calibration (default: all populations)\n", - "- `weight`: Weight for a particular population (default: 1). By default, all populations are weighted equally regardless of size. See [the documentation on weights](/general/YAML_calibration.html#Measurable-Weights) for further details.\n", + "- `weight`: Weight for a particular population (default: 1). By default, all populations are weighted equally regardless of size. See [the documentation on weights](https://atomica.tools/docs/master/general/YAML_calibration.html#Measurable-Weights \"Measurable weights\") for further details.\n", "- `metric`: Metric to be used by the optimisation algorithm (default: fractional)\n", "- `cal_start`: Starting year that the calibration will be evaluated from (default: `sim_start`)\n", "- `cal_end`: End year until which the calibration will be evaluated (default: `sim_end`)\n", "\n", - "Note that `sim_start` and `sim_end` are the start and end years that the simulation will run for (the simulation timespan). These are distinct from `cal_start` and `cal_end`, which specify the time period for which we want to calibrate the model, i.e. a subset of the simulation timespan. For more information, see the [section on outer settings](#specifying-settings-in-outer-sections). The `cal_start` and `cal_end` years can be set per measurable, so it is possible to prioritize different years for different variables or for different steps of the calibration. \n", - "To specify these adjustables and measurables settings in the YAML file, we simply write the setting names and their values under the relevant parameter name. Each adjustable and measurable is placed on a new line, and their respective settings are also specified on separate indented lines, like so: \n", + "Note that `sim_start` and `sim_end` are the start and end years that the simulation will run for (the simulation timespan). These are distinct from `cal_start` and `cal_end`, which specify the time period for which we want to calibrate the model, i.e. a subset of the simulation timespan. For more information, see the [section on outer settings](#specifying-settings-in-outer-sections \"Specifying settings in outer sections\"). The `cal_start` and `cal_end` years can be set independently for each measurable, so it is possible to prioritize different years for different variables or for different steps of the calibration.\n", + "To specify these adjustables and measurables settings in the YAML file, we simply write the setting names and their values under the relevant parameter name. Each adjustable and measurable is placed on a new line, and their respective settings are also specified on separate indented lines, like so:\n", "\n", - " calibration: \n", + " calibration:\n", " Match population sizes:\n", " adjustables: \n", " \tb_rate: \n", @@ -316,6 +316,7 @@ "cell_type": "markdown", "id": "13", "metadata": { + "editable": true, "slideshow": { "slide_type": "" }, @@ -324,7 +325,7 @@ "source": [ "#### Specifying Populations\n", "\n", - "In some cases, you may want to only set adjustables or evaluation measurables for a specific population, or you may wish to use different settings for one population compared to another. A population can optionally be specified after the parameter name, as the second element of a tuple. Thus, if we only wish to calibrate some populations, we can rewrite our previous YAML file like so: \n", + "In some cases, you may want to only set adjustables or measurables for a specific population, or you may wish to use different settings for one population compared to another. A population can optionally be specified after the parameter name, as the second element of a tuple. Thus, if we only wish to calibrate some populations, we can rewrite our previous YAML file like so:\n", "\n", " calibration: \n", " Match population sizes:\n", @@ -353,7 +354,7 @@ " \tcal_start: 2000\n", " \tcal_end: 2040\n", "\n", - "Finally, this same syntax can be used to calibrate transfers and interactions, but in such cases the tuple should have three elements - the parameter name, the _from_ population and the _to_ population. For more information on calibrating in these cases, see [Calibrating transfers and interactions](/general/YAML_calibration.html#Calibrating-transfers-and-interactions)." + "Finally, the same syntax we use to calibrate populations can be used to calibrate transfers and interactions, but in such cases the tuple should have three elements - the parameter name, the _from_ population and the _to_ population. For more information on how to calibrate in these cases, see the documentation on [Calibrating transfers and interactions](https://atomica.tools/docs/master/general/YAML_calibration.html#Calibrating-transfers-and-interactions \"Calibrating transfers and interactions\")." ] }, { @@ -366,7 +367,7 @@ "tags": [] }, "source": [ - "### Setting initialisations\n", + "### Setting initializations\n", "\n", "In some cases, the model may exhibit an unrealistically large transient at the start of the simulation. This can occur if the initial compartment sizes calculated by Atomica are very different to the equilibrium compartment sizes associated with the model's parameters. Two common reasons for this are:\n", "\n", @@ -379,25 +380,25 @@ "\n", "In some models, this can be treated as a 'burn-in' period and the initial part of the simulation can simply be discarded. However, there is a risk that being too far from the correct initialization results in contamination of the estimates of parameters during the calibration period. For example, if the model is initialized with the incorrect prevalence, the calibration applied to the force of infection in order to match the observed incidence would be impacted, which might subsequently affect the model's sensitivity to interventions that change the prevalence later on. Therefore, we wish to minimize the effect of the transient on the calibration. \n", "\n", - "We can sometimes achieve this by setting the calibration start year `cal_start` to be a few years after the simulation start year `sim_start`, so that the simulation has a few years to reach equilibrium before the calibration process itself begins. However, this extends the duration of the simulation, or might limit the amount of data used for the calibraiton.\n", + "We can sometimes achieve this by setting the calibration start year `cal_start` to be a few years after the simulation start year `sim_start`, so that the simulation has a few years to reach equilibrium before the calibration process itself begins. However, this extends the duration of the simulation, or might limit the amount of data used for the calibration.\n", "\n", - "An alternative approach is to override the initialisation for our calibration. Initialisations work by running a normal Atomica simulation for a few years (past the initial transient), taking the compartment sizes of that future year, and setting the initial compartment sizes to those stabilized values. In cases where the model parameters are mostly constant, these future compartment sizes will be roughly equivalent to what the initial compartment sizes should be, which will avoid the initial transient in the model. \n", + "An alternative approach is to override the initialization for our calibration. initializations work by running a normal Atomica simulation for a few years (past the initial transient), taking the compartment sizes of that future year, and setting the initial compartment sizes to those stabilized values. In cases where the model parameters are mostly constant, these future compartment sizes will be roughly equivalent to what the initial compartment sizes should be, which will avoid the initial transient in the model.\n", "\n", "\n", "\"Post-initialization\n", "\n", - "If the model parameters are not roughly constant, the equilibrium that the model converges to in the future might not correspond to the equilibrium solution for the model's initial parameter values. In that case, an initial transient will still occur. To address this, we can remove any time variation in the model's parameter values using the `ParameterSet.make_constant()` method. This will return a copy of the parset in which all parameters are constant over time, thus ensuring that the future compartment sizes are computed based on the same parameter values as the initial simulation year. This often provides a suitable solution, although changes to the total population size due to births and deaths can still take place, so in some cases an initial transient may still be present. In such cases, repeatedly setting initialization based on a shorter simulation can help minimize the discrepancy. For more information on Atomica initializations, see the [documentation](/general/YAML_calibration.html).\n", + "If the model parameters are not roughly constant, the equilibrium that the model converges to in the future might not correspond to the equilibrium solution for the model's initial parameter values. In that case, an initial transient will still occur. To address this, we can remove any time variation in the model's parameter values using the `ParameterSet.make_constant()` method. This will return a copy of the parset in which all parameters are constant over time, thus ensuring that the future compartment sizes are computed based on the same parameter values as the initial simulation year. This often provides a suitable solution, although changes to the total population size due to births and deaths can still take place, so in some cases an initial transient may still be present. In such cases, repeatedly setting initialization based on a shorter simulation can help minimize the discrepancy. For more information on Atomica initializations, see the [documentation](https://atomica.tools/docs/master/general/YAML_calibration.html \"Documentation\").\n", "\n", - "In the YAML file, we indicate that we want to set a new initialization by making a YAML block with the title `set_initialisation`. Under this title, we can specify further settings: \n", + "In the YAML file, we indicate that we want to set a new initialization by making a YAML block with the title `set_initialization`. Under this title, we can specify further settings:\n", "\n", "- `init_year` (required): The year to use to take the compartment sizes from. The simulation will be run up to this year\n", - "- `constant_parset` (default: False): Whether to use a constant parset for the initialisation, and which year to use in `parset.make_constant()`. It can be a Boolean (True/False) or numerical value (representing the year from which to draw the constant values for the parset, defaults to the same year as `sim_start`).\n", + "- `constant_parset` (default: False): Whether to use a constant parset for the initialization, and which year to use in `parset.make_constant()`. It can be a Boolean (True/False) or numerical value (representing the year from which to draw the constant values for the parset, defaults to the same year as `sim_start`).\n", "\n", "There are thus several valid ways to set an initialization. For example, only setting the initialization year:\n", "\n", "```\n", "calibration:\n", - " set_initialisation:\n", + " set_initialization:\n", " init_year: 2030\n", "```\n", "\n", @@ -405,7 +406,7 @@ "\n", "```\n", "calibration:\n", - " set_initialisation:\n", + " set_initialization:\n", " init_year: 2030\n", " constant_parset: True\n", "```\n", @@ -415,7 +416,7 @@ "\n", "```\n", "calibration:\n", - " set_initialisation:\n", + " set_initialization:\n", " init_year: 2030\n", " constant_parset: 2005\n", "```\n" @@ -426,25 +427,25 @@ "id": "15", "metadata": {}, "source": [ - "### Clearing initialisations\n", + "### Clearing initializations\n", "\n", - "If we have previously set an initialisation in our calibration algorithm, and then set another initialisation later in the YAML file, it uses information from the previous initialisation to calculate the next, since the new simulation will start from the initial compartment sizes calculated in the previous initialization.\n", + "If we have previously set an initialization in our calibration algorithm, and then set another initialization later in the YAML file, it uses information from the previous initialization to calculate the next, since the new simulation will start from the initial compartment sizes calculated in the previous initialization.\n", "\n", - "Sometimes we might want to calculate a new initialisation from scratch, without using the previous initialisation as a starting point. This could be useful if we have done some calibration steps between the previous initialisation and now, in which case the y-factors will have changed, and we might be better off using a different starting point. \n", + "Sometimes we might want to calculate a new initialization from scratch, without using the previous initialization as a starting point. This could be useful if we have done some calibration steps between the previous initialization and now, in which case the y-factors will have changed, and we might be better off using a different starting point.\n", "\n", - "To do this in the YAML file, we can add a section titled `clear_initialisation`, followed by a boolean value. If it is set to `True`, any existing initialization will be cleared; if `False`, nothing will happen. For example:\n", + "To do this in the YAML file, we can add a section titled `clear_initialization`, followed by a boolean value. If it is set to `True`, any existing initialization will be cleared; if `False`, nothing will happen. For example:\n", "\n", " calibration:\n", - " set_initialisation 1:\n", + " set_initialization 1:\n", " \t\tinit_year: 2030\n", "\n", " Match population sizes:\n", " adjustables: b_rate, mig_rate\n", " \tmeasurables: alive\n", " \n", - " \tclear_initialisation: True\n", + " \tclear_initialization: True\n", " \n", - " set_initialisation 2:\n", + " set_initialization 2:\n", " \t\tinit_year: 2030" ] }, @@ -469,13 +470,11 @@ "\n", " \tsave_calibration: epi_calibration.xlsx\n", " \n", - "Note that when we save a calibration, if initial compartment sizes have been explicitly specified by using `set_initialization`, these compartment sizes will be saved along with the y-factors in the same Excel file. Loading the calibration from this file will thus include the initial compartment sizes. \n", + "Note that when we save a calibration, if initial compartment sizes have been explicitly specified by using `set_initialization`, these compartment sizes will be saved along with the y-factors in the same Excel file. Loading the calibration from this file will thus include the initial compartment sizes.\n", "\n", "Another option that can be useful for debugging is to save the calibration state at every intermediate step of the YAML file. In that case, you can use the `save_intermediate_calibrations` option when running the calibration e.g.\n", "\n", - " calibrated_parset = P.calibrate(parset = cal, yaml='T7_YAML_1_minimal.yaml', save_intermediate=True)\n", - "\n", - "For more information on intermediate calibrations, see the relevant [documentation section](/general/YAML_calibration.html#saving-intermediate-calibrations \"Saving intermediate calibrations\")." + " calibrated_parset = P.calibrate(parset = cal, yaml='T7_YAML_1_minimal.yaml', save_intermediate=True)" ] }, { @@ -492,7 +491,7 @@ "Some settings that this feature is commonly used for include: \n", "\n", "- `max_time`: Maximum amount of time each call to the optimisation algorithm will run for \n", - "- `stepsize`: Initial stepsize, i.e. how much the y-factors will be incremented/decreased by in the optimisation algorithm.\n", + "- `stepsize`: Initial step size, i.e. how much the y-factors will be increased/decreased by in the optimisation algorithm.\n", "\n", "Additionally, any adjustable or measurable setting can also be set outside of its calibration block, although some settings lend themselves more to this feature than others. For example, changing the measurable `weight` for an entire calibration block has no effect, as what matters is the proportion between the weights of different measurables in the same block. The following settings can be useful to set in parent sections:\n", "\n", @@ -538,7 +537,7 @@ "\n", "### Adjustables/measurables settings\n", "\n", - "Finally, here is an example of how to use the adjustables and measurables settings outside of a calibration block: \n", + "Finally, here is an example of how to use the adjustables and measurables settings outside of a calibration block:\n", "\n", " calibration:\n", " Population calibration:\n", @@ -582,7 +581,7 @@ " import yaml\n", " calibration_yaml = yaml.load(file, Loader=yaml.FullLoader)\n", " \n", - "The `calibration_yaml` variable above can be passed to `P.calibrate(..., yaml=calibration_yaml)`. This enables changes to be made to the YAML content programatically prior to running the calibration. " + "The `calibration_yaml` variable above can be passed to `P.calibrate(..., yaml=calibration_yaml)`. This enables changes to be made to the YAML content programmatically prior to running the calibration." ] }, { @@ -592,7 +591,7 @@ "source": [ "## Exercise: worked example\n", "\n", - "Now that we understand what all of the working parts of a YAML file are, let's put it all together. For each question, write a YAML file to calibrate the model as described. Each question will consist of incremental additions to the previous solution. \n", + "Now that we understand what all the working parts of a YAML file are, let's put it all together. For each question, write a YAML file to calibrate the model as described. Each question will consist of incremental additions to the previous solution.\n", "\n", "_**Question 1.** We want to do a basic population calibration, where we calibrate the death rate and migration rate to match the data corresponding to the total number of people alive. We also want to calibrate the death rate. What should this YAML file look like?_\n", "\n", @@ -600,18 +599,18 @@ "\n", "**Hint 2**: Some of the parameter `Code Names` and `Display Names` in the databook are as follows: \n", "\n", - "| Framework Sheet | Code Name | Display Name | Databook Page |\n", - "| :---------------- | :------: | :------: | ----: |\n", - "|COMPARTMENTS | |\n", - "| |birth\t\t|Birth \t\t\t\t\t\t|none|\n", - "| |death \t|Death \t\t\t\t\t\t |none|\n", - "| PARAMETERS | |\n", - "| |b_rate\t\t|Birth rate \t\t\t\t|demographic|\n", - "| |deaths\t\t|All-cause deaths \t\t\t|demographic|\n", - "| |d_rate\t\t|Background mortality rate \t|demographic|\n", - "| |mig_rate\t|Migration Rate \t\t\t\t|demographic|\n", + "| Framework Sheet | Code Name | Display Name | Databook Page |\n", + "|:----------------|:--------------:|:------------------------------:|--------------:|\n", + "| COMPARTMENTS | |\n", + "| | birth\t\t | Birth \t\t\t\t\t\t | none |\n", + "| | death \t | Death \t\t\t\t\t\t | none |\n", + "| PARAMETERS | |\n", + "| | b_rate\t\t | Birth rate \t\t\t\t | demographic |\n", + "| | deaths\t\t | All-cause deaths \t\t\t | demographic |\n", + "| | d_rate\t\t | Background mortality rate \t | demographic |\n", + "| | mig_rate\t | Migration Rate \t\t\t\t | demographic |\n", "| CHARACTERISTICS | |\n", - "| |alive\t|\tTotal population\t\t| demographic" + "| | alive\t | \tTotal population\t\t | demographic |" ] }, { @@ -619,7 +618,7 @@ "id": "20", "metadata": {}, "source": [ - "_**Question 2.** A single calibration run may not be enough to get good results, so let's loop over our simple population calibration ten times. How would we make that change to the the YAML file?_\n", + "_**Question 2.** A single calibration run may not be enough to get good results, so let's loop over our simple population calibration ten times. How would we make that change to the YAML file?_\n", "\n", "**Hint**: Use the `repeats` keyword.\n", "\n", @@ -639,15 +638,15 @@ "\n", "**Hint**: Use `set_initialization` after the calibration blocks, and make sure the initialization gets re-calculated in every loop! \n", "\n", - "_**Question 7.** We also want to clear the previous initialisation every time we make a new one, instead of using information from the previous initialisation. How can we update the YAML file to reflect this?_\n", + "_**Question 7.** We also want to clear the previous initialization every time we make a new one, instead of using information from the previous initialization. How can we update the YAML file to reflect this?_\n", "\n", - "**Hint**: Use `clear_initialisation`, and make sure the initialization gets cleared and re-calculated in every loop!\n", + "**Hint**: Use `clear_initialization`, and make sure the initialization gets cleared and re-calculated in every loop!\n", "\n", "_**Question 8.** We are almost ready to run the YAML calibration! Now, what instructions do we need to add to automatically save our population calibration once it is done?_\n", "\n", "**Hint**: Use `save_calibration` and specify a `fname`.\n", "\n", - "All solutions to the worked example are in the `Worked_example` folder in code repository. The calibration obtained after running the last YAML file in this exercise yields the following simulation result: \n", + "All solutions to the worked example are in the `docs/tutorial/T7/calibrations` folder of the Atomica repository. The calibration obtained after running the last YAML file in this exercise yields the following simulation result:\n", "\n", "\"Worked" ] @@ -661,17 +660,17 @@ "\n", "### Epidemiological calibration\n", "\n", - "In this tutorial we have demonstrated the key functionality of Atomica's YAML calibration system applied to a population calibration, focussing on adjusting births and deaths to match population size data, without considering disease burden. This same functionality applies to epidemiological calibration, just with different model parameters and data. A complete YAML file of the population and epidemiological calibration can be found in the `Worked_example` folder in code repository, in the `typ_calibration_instructions.yaml` file. \n", + "In this tutorial we have demonstrated the key functionality of Atomica's YAML calibration system applied to a population calibration, focussing on adjusting births and deaths to match population size data, without considering disease burden. This same functionality applies to epidemiological calibration, just with different model parameters and data. A complete YAML file of the population and epidemiological calibration instructions (`typ_calibration_instructions.yaml`) can be found in the Atomica code repository, at `docs/tutorial/T7/calibrations`.\n", "\n", "In this YAML file, we have set the `max_time` to 120, to give the calibration a bit more time to reach an optimal solution in each calibration step. \n", "\n", - "At the beginning of the calibration, we also set the parameters relating to the typhoid disease (`typ_active_inf` and `typ_car`) to zero for the first pass of the population calibration. This essentially \"turns off\" of the typhoid disease until it gets reactivated in the `reset epi y-factors` step, giving the population an opportunity to be reasonably calibrated without interference from the disease components. This can be useful to do since, before calibrating the disease, the magnitude of the disease parameters could be large enough to significantly inmpact the population calibration results. \n", + "At the beginning of the calibration, we also set the parameters relating to the typhoid disease (`typ_active_inf` and `typ_car`) to zero for the first pass of the population calibration. This essentially \"turns off\" of the typhoid disease until it gets reactivated in the `reset epi y-factors` step, giving the population an opportunity to be reasonably calibrated without interference from the disease components. This can be useful to do since, before calibrating the disease, the magnitude of the disease parameters could be large enough to significantly impact the population calibration results.\n", "\n", - "We then calibrate the population following the same principles as illustrated previously, repeating the population calibration ten times, and setting a new initialization at the end of each loop, with `constant_parset=True` and the `init_year` set to 2030. \n", + "We then calibrate the population following the same principles as illustrated previously, repeating the population calibration ten times, and setting a new initialization at the end of each loop, with `constant_parset=True` and the `init_year` set to 2030.\n", "\n", "In the epidemiological calibration section, the typhoid incidence, prevalence, and typhoid deaths are calibrated. Since we don't have a lot of information on the order of magnitude of the susceptibility and infectiousness, the lower and upper bounds are expanded to leave more room for variation. However, we don't want the disease duration `typ_gen_dur` to vary a lot, since we have a pretty clear idea of its magnitude and don't want it to vary too much between calibrations and settings, so we set stricter bounds. \n", "\n", - "At the end of the typhoid calibration, we set an initialisation in the same way we did for the population calibration. We then repeat the epidemiological calibration ten times, and finally, repeat the whole YAML calibration process (except silencing the epi y-factors) twice. \n", + "At the end of the typhoid calibration, we set an initialization in the same way we did for the population calibration. We then repeat the epidemiological calibration ten times, and finally, repeat the whole YAML calibration process (except silencing the epi y-factors) twice.\n", "\n", "The resulting calibration from running this YAML file is like so:\n", "\n", @@ -679,15 +678,15 @@ "\n", "### Documentation\n", "\n", - "For additional information on YAML calibration functionality, see [the documentation](/general/YAML_calibration.html).\n" + "For more information on using Atomica's YAML calibration functionality, see [the documentation](https://atomica.tools/docs/master/general/YAML_calibration.html \"YAML documentation page\").\n" ] } ], "metadata": { "kernelspec": { - "display_name": "Python [conda env:atomica312]", + "display_name": "Python 3 (ipykernel)", "language": "python", - "name": "conda-env-atomica312-py" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -699,7 +698,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.10.13" }, "toc": { "base_numbering": 1, From a12466e162741b86095dfa9e6bb7143755a3de33 Mon Sep 17 00:00:00 2001 From: Eloisa Perez-Bennetts <49991958+epbennetts@users.noreply.github.com> Date: Tue, 4 Mar 2025 17:41:25 +0100 Subject: [PATCH 123/161] Update YAML tutorial notebooks Update notebook text, fix broken links --- .../tutorial/T7/T7_YAML_autocalibration.ipynb | 1451 +++++++++-------- 1 file changed, 732 insertions(+), 719 deletions(-) diff --git a/docs/tutorial/T7/T7_YAML_autocalibration.ipynb b/docs/tutorial/T7/T7_YAML_autocalibration.ipynb index 321f7b87..d6d3d2d0 100644 --- a/docs/tutorial/T7/T7_YAML_autocalibration.ipynb +++ b/docs/tutorial/T7/T7_YAML_autocalibration.ipynb @@ -1,719 +1,732 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "0", - "metadata": {}, - "source": [ - "# T7 - YAML calibration\n", - "\n", - "As we saw in the earlier calibration tutorial, most autocalibrations involve multiple steps, since the optimization algorithm often gets stuck in local minima if we try to optimize too many parameters at once. We could run each of these steps ourselves through separate calls to `P.calibrate()` – however, there is significant value in being able to explicitly frame the overall calibration process as an algorithm, as this makes it easier to modify the calibration steps and apply the calibration algorithm across a collection of projects. This is implemented in Atomica through the 'YAML calibration' feature, in which the calibration steps are specified in a file which Atomica can then read and use to execute the calibration.\n", - "\n", - "## YAML files\n", - "\n", - "The calibration algorithm files used by Atomica are written in YAML. YAML is a plain-text, human-readable data serialization language used to make configuration files. Essentially, a YAML file can be read into Python variables (dictionaries, lists, strings) which in turn can be used as arguments to Python functions. Here is an example of how variables can be specified in a YAML file:\n", - "\n", - "```\n", - " foo: a string\n", - " bar: 1\n", - " baz: [a,b,c]\n", - " list:\n", - " - i\n", - " - j\n", - " nested:\n", - " x: 1\n", - " y: 2\n", - " ```\n", - "\n", - "When parsed into Python, this becomes\n", - "\n", - "```\n", - "{'foo': 'a string',\n", - " 'bar': 1,\n", - " 'baz': ['a', 'b', 'c'],\n", - " 'list': ['i', 'j'],\n", - " 'nested': {'x': 1, 'y': 2}}\n", - "```\n", - "\n", - "Using YAML files provides a simple way to define a calibration algorithm in a format that is easy to work with and that Atomica can directly execute. This can cut down the time we spend manually calibrating, or even running autocalibrations. It allows us to conduct reproducible calibration runs, and is also highly scalable, since it allows us to apply the same calibration algorithm in multiple countries or settings.\n", - "\n", - "The following tutorial outlines how to use the YAML framework that has been developed for Atomica calibration. Specifically, it will cover how to write a YAML configuration file with calibration instructions for Atomica, and how to use this file to execute a calibration. Bear in mind that YAML calibration is not intended to be a standalone tool that will perfectly calibrate any model – rather, it is one part of the calibration toolbox. It can be used to reduce the time spent on calibration by autocalibrating Atomica models to a reasonable level, but additional tweaking may be required to obtain a consistently high calibration quality across all parameters, populations and/or countries." - ] - }, - { - "cell_type": "markdown", - "id": "1", - "metadata": {}, - "source": [ - "## Basic calibration example\n", - "\n", - "In this tutorial, we will work with a simple version of a typhoid model. This model captures typhoid infections, as well as asymptomatic carriers and vaccination. Firstly, we need to create an Atomica `Project` by loading in the Framework and Databook files, just like we did in [the first Atomica tutorial](https://atomica.tools/docs/master/tutorial/T1-Defining-a-model.html). The Framework and Databook for this project can be found in the Atomica repository under `T7/assets`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2", - "metadata": {}, - "outputs": [], - "source": [ - "import atomica as at\n", - "F = at.ProjectFramework('assets/T7_framework.xlsx')\n", - "D = at.ProjectData.from_spreadsheet('assets/T7_databook.xlsx', framework=F)\n", - "P = at.Project(framework=F,databook=D, do_run=False)\n", - "P.settings.update_time_vector(start=2000, end=2040, dt=1/52)" - ] - }, - { - "cell_type": "markdown", - "id": "3", - "metadata": {}, - "source": [ - "In the example above, no calibration has been loaded, so all of the calibration Y-factors are equal to 1, and the model is uncalibrated. We can run a simulation and plot it, to see what our model looks like before calibration:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4", - "metadata": {}, - "outputs": [], - "source": [ - "cal = P.make_parset()\n", - "res = P.run_sim(parset=cal, result_name = 'Uncalibrated')\n", - "d = at.PlotData(res, outputs=['alive','deaths', 'typ_prev', 'typ_num_deaths'], project=P)\n", - "fig = at.plot_series(d,axis='pops', data=P.data, n_cols=2, legend_mode='none')[0]\n", - "fig.set_size_inches(10,7)\n", - "fig.tight_layout()" - ] - }, - { - "cell_type": "markdown", - "id": "5", - "metadata": {}, - "source": [ - "Two issues with these simulation outputs immediately stand out. First, for the variables and years in which data is available, the model output doesn't match the data very well at all. Second, there is a large sudden change in the values of several variables right at the start of the simulation. In the absence of associated changes in interventions or disease transmission, disease burden is typically much more stable over time, so we would not expect to see such sudden changes at the start of the simulation.\n", - "\n", - "Tutorial 2 covers some of the detail around how to approach calibration. Although the parameters used for calibration vary from model to model, as a general rule, calibration proceeds by\n", - "\n", - "1. Demographic calibration: Adjusting birth and background death rates to match quantities like the total population size.\n", - "2. Epidemiological calibration: Adjusting parameters such as force of infection, diagnosis rate and mortality rate, to match quantities like incidence, prevalence and deaths.\n", - "\n", - "Each of these steps involves calibrating multiple parameters, which may be adjusted sequentially and repeatedly. They may also be interspersed with adjusting the model's initialization, to help minimize sudden transients at the start of the simulation. The purpose of the YAML file is to specify the sequence of steps to follow in carrying out a calibration run, in terms of which parameters to adjust, the order in which to adjust them (or whether some should be adjusted simultaneously), and how to assess the quality of the calibration at each step of the process. In this tutorial, we will use YAML files to specify a sequence of steps to calibrate the simple typhoid model shown above, starting with a minimal example and then introducing key features provided by Atomica's YAML calibration system." - ] - }, - { - "cell_type": "markdown", - "id": "6", - "metadata": { - "jp-MarkdownHeadingCollapsed": true - }, - "source": [ - "## Minimal YAML file\n", - "\n", - "To illustrate how YAML calibration works, let’s start with a simple example of what a YAML file could look like:\n", - "\n", - " calibration:\n", - " \tadjustables: b_rate, mig_rate\n", - " \tmeasurables: alive\n", - "\n", - "The above YAML file represents a single call to the autocalibration optimisation function, where the `b_rate` and `mig_rate` y-factors are adjusted to match `alive`. It is equivalent to running a calibration with the following command:\n", - "\n", - " calibrated_parset = P.calibrate(parset = cal, adjustables = ['b_rate', 'mig_rate'], measurables = 'alive')\n", - "\n", - "Running the YAML calibration is very similar to performing a standalone auto-calibration. After saving the YAML file to disk (e.g., `T7_YAML_1_minimal.yaml`), the calibration can be run using\n", - "\n", - " calibrated_parset = P.calibrate(parset = cal, yaml='T7_YAML_1_minimal.yaml')\n", - "\n", - "As the YAML calibration framework allows us to specify the adjustables and measurables, it is not necessary to provide them to `Project.calibrate()` – simply providing the YAML file is sufficient. However, the YAML file can contain multiple calibration commands, and therefore a single call to `Project.calibrate()` with a YAML file might be equivalent to multiple explicit calibration steps. The resulting simulation after running this simple calibration is like so: \n", - "\n", - "\"Simple\n", - "\"Simple\n", - "\n", - "As you can see, these plots don't look very different to the uncalibrated simulation results. If we plot the uncalibrated simulation in the same plot as our simple calibration, we can see that there has been a slight change, but not nearly enough to be able to consider this a good calibration. Next, we will illustrate the YAML calibration features that we can use to improve on this initial result. " - ] - }, - { - "cell_type": "markdown", - "id": "7", - "metadata": {}, - "source": [ - "## Sections\n", - "\n", - "At the most basic level, a YAML calibration file defines a sequence of individual steps, where each step incrementally modifies the calibration. The YAML file therefore defines an overall _algorithm_ for performing an automatic calibration. This algorithm is defined using two structures in the YAML file:\n", - "\n", - "- _actions_, which are associated with particular operations, like running a gradient-descent calibration step with a particular set of parameters and data. A calibration action contains `adjustables` and `measurables`. Other examples of actions are detailed below.\n", - "- _sections_, which are containers for actions. Sections can contain attributes, such as how many times to repeat the contents of the section, or they can define settings that are applied to any relevant actions within that section.\n", - "\n", - "The original YAML file above consisted of a single calibration action. If we wanted to extend the algorithm by adding a step to calibrate the death rate, we could update our YAML file to the following: \n", - "\n", - "\n", - "```\n", - "calibration:\n", - " Match population sizes:\n", - " adjustables: b_rate, mig_rate\n", - " measurables: alive\n", - " Match deaths:\n", - " adjustables: d_rate\n", - " measurables: deaths\n", - "```\n", - "\n", - "To organize the YAML file further, we could group these into an additional section. Both of these actions affect the overall population calibration, so we could logically group them as follows:\n", - "\n", - "```\n", - "calibration: \n", - " Population calibration:\n", - " Match population sizes:\n", - " adjustables: b_rate, mig_rate\n", - " measurables: alive\n", - " Match deaths:\n", - " adjustables: d_rate\n", - " measurables: deaths\n", - "```\n", - "\n", - "The overall structure of this YAML file is thus:\n", - "\n", - "1. A top-level section titled `calibration`, which has one sub-section (`Population calibration`)\n", - "2. A sub-section called `Population calibration`, which in turn contains two actions\n", - "3. An action called `Match population sizes`, corresponding to the original calibration step we used to adjust the birth rate and migration rate\n", - "4. An action called `Match deaths`, corresponding to the new step of adjusting the death rate\n", - "\n", - "An action is differentiated from a section in two possible ways:\n", - "\n", - "- By its contents (e.g. if it contains `adjustables` and `measurables`, then it will be interpreted as a calibration action rather than a section)\n", - "- By the title (if the name corresponds to the name of a supported operation, as described below)\n", - "\n", - "Additionally, actions can never contain any sub-sections, whereas sections do. \n", - "Apart from the names of supported operations, sections can be freely named." - ] - }, - { - "cell_type": "markdown", - "id": "8", - "metadata": {}, - "source": [ - "### Repeating a section\n", - "\n", - "The *repeats* keyword can be used to loop over any part of the calibration multiple times. We do this by writing `repeats: n` inside a particular section, where *n* is the number of times we would like to loop over that section. All subsections contained in it will also be looped over *n* times. \n", - "\n", - " calibration: \n", - " repeats: 2\n", - " Population calibration:\n", - " Match population sizes:\n", - " repeats: 2\n", - " adjustables: b_rate, mig_rate\n", - " measurables: alive\n", - " Match deaths:\n", - " adjustables: d_rate\n", - " measurables: deaths\n", - "\n", - "In the above example, we have set `repeats: 2` inside the `calibration` section, so the entire YAML calibration will be repeated twice. Then, the `Match population sizes` section also has `repeats: 2`, so the calibration step defined in that section will also be repeated twice each time. In total, there will be four calls to the optimisation algorithm to match `alive`, and two to match `deaths, so the YAML file above would be equivalent to \n", - "\n", - " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", - " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", - " parset = P.calibrate(parset = parset, adjustables = [d_rate], measurables=deaths)\n", - " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", - " parset = P.calibrate(parset = parset, adjustables = [b_rate, mig_rate], measurables=alive)\n", - " parset = P.calibrate(parset = parset, adjustables = [d_rate], measurables=deaths)\n", - "\n", - "In this way, it is possible for even a very compact YAML file to correspond to a large number of individual autocalibration steps. " - ] - }, - { - "cell_type": "markdown", - "id": "9", - "metadata": {}, - "source": [ - "## Sections vs Actions\n", - "\n", - "As shown above, sections can help us to structure the calibration in a way that is practical and intuitive. They can be used to group blocks of YAML code that are conceptually related, that we want to repeat together several times, or that we want to apply similar settings to (we will cover which settings are supported in [the corresponding section](#specifying-settings-in-outer-sections). \n", - "\n", - "Importantly though, _sections_ do not modify the calibration itself – they are merely wrappers for the innermost blocks that actually correspond to specific actions. It is in these _actions_ that operations are performed on the calibration, such as modifying the calibration or saving it.\n", - "\n", - "