Framework overview#

Pymob is built around pymob.simulation.SimulationBase, which is the object where all necessary information are pooled. For configuration, pymob relies on pymob.sim.config.Config, which uses pydantic to validate the configuration, before it is used to set up the simulation.

from pymob import SimulationBase

# initializing a Simulation with a config file
sim = SimulationBase()

# accessing the config file
sim.config
/home/docs/checkouts/readthedocs.org/user_builds/pymob/envs/latest/lib/python3.11/site-packages/pymob/sim/config/base.py:397: UserWarning: Case study 'unnamed_case_study' could not be imported. Install the case study with `pip install unnamed_case_study`.
  warnings.warn(





Config(case_study=Casestudy(init_root='/home/docs/checkouts/readthedocs.org/user_builds/pymob/checkouts/latest/docs/source/user_guide', root='.', name='unnamed_case_study', version=None, pymob_version='0.5.30', scenario='unnamed_scenario', package='case_studies', modules=['sim', 'mod', 'prob', 'data', 'plot'], simulation='Simulation', output=None, data=None, scenario_path_override=None, observations=None, logging='DEBUG', logfile=None, output_path='case_studies/unnamed_case_study/results/unnamed_scenario', data_path='case_studies/unnamed_case_study/data', default_settings_path='case_studies/unnamed_case_study/scenarios/unnamed_scenario/settings.cfg'), simulation=Simulation(model=None, model_class=None, solver=None, y0=[], x_in=[], input_files=[], n_ode_states=-1, batch_dimension='batch_id', x_dimension='time', modeltype='deterministic', solver_post_processing=None, seed=1), data_structure=Datastructure(indices=[]), solverbase=Solverbase(x_dim='time', exclude_kwargs_model=('t', 'time', 'x_in', 'y', 'x', 'Y', 'X'), exclude_kwargs_postprocessing=('t', 'time', 'interpolation', 'results')), jaxsolver=Jaxsolver(diffrax_solver='Dopri5', rtol=1e-06, atol=1e-07, pcoeff=0.0, icoeff=1.0, dcoeff=0.0, max_steps=100000, throw_exception=True), inference=Inference(eps=1e-08, objective_function='total_average', n_objectives=1, objective_names=[], backend=None, extra_vars=[], plot=None, n_predictions=100), model_parameters=Modelparameters(), error_model=Errormodel(), multiprocessing=Multiprocessing(cores=1), inference_pyabc=Pyabc(sampler='SingleCoreSampler', population_size=100, minimum_epsilon=0.0, min_eps_diff=0.0, max_nr_populations=1000, database_path='/tmp/pyabc.db'), inference_pyabc_redis=Redis(password='nopassword', port=1111, n_predictions=50, history_id=-1, model_id=0), inference_pymoo=Pymoo(algortihm='UNSGA3', population_size=100, max_nr_populations=1000, ftol=1e-05, xtol=1e-07, cvtol=1e-07, verbose=True), inference_numpyro=Numpyro(user_defined_probability_model=None, user_defined_error_model=None, user_defined_preprocessing=None, gaussian_base_distribution=False, kernel='nuts', init_strategy='init_to_uniform', chains=1, draws=2000, warmup=1000, thinning=1, nuts_draws=2000, nuts_step_size=0.8, nuts_max_tree_depth=10, nuts_target_accept_prob=0.8, nuts_dense_mass=True, nuts_adapt_step_size=True, nuts_adapt_mass_matrix=True, sa_adapt_state_size=None, svi_iterations=10000, svi_learning_rate=0.0001), report=Report(debug_report=False, pandoc_output_format='html', model=True, parameters=True, parameters_format='pandas', diagnostics=True, diagnostics_with_batch_dim_vars=False, diagnostics_exclude_vars=[], goodness_of_fit=True, goodness_of_fit_use_predictions=True, goodness_of_fit_nrmse_mode='range', table_parameter_estimates=True, table_parameter_estimates_format='csv', table_parameter_estimates_significant_figures=3, table_parameter_estimates_error_metric='sd', table_parameter_estimates_parameters_as_rows=True, table_parameter_estimates_with_batch_dim_vars=False, table_parameter_estimates_exclude_vars=[], table_parameter_estimates_override_names={}, plot_trace=True, plot_parameter_pairs=True))

Pymob API#

framework-overview

Pymob exposes the following input and output interfaces#

Config#

Pymob uses pydantic Models for validation of the configuration files. The configuration is organized into sections, e.g.

sim.config.data_structure
Datastructure(indices=[])

We use a DataVariable to populate the data structure. Let’s say we have made some concentration measurments

from pymob.sim.config import DataVariable

sim.config.data_structure.y = DataVariable(dimensions=["x"], observed=True)
sim.config.data_structure
Datastructure(indices=[], y=DataVariable(dimensions=['x'], unit=None, min=nan, max=nan, observed=True, dimensions_evaluator=None))

Configurations can be changed in the files before a simulation is initialized from a config file, or directly in the script.

sim.config.data_structure.y.min = 0
sim.config.data_structure
Datastructure(indices=[], y=DataVariable(dimensions=['x'], unit=None, min=0.0, max=nan, observed=True, dimensions_evaluator=None))

As can be seen in the figure above, it is the communication between Simulation class and config files is bidirectional, this means, Simulations can be created from config files or in a scripting environment, and successively exported to config files. For more information see configuration for details

Solver#

Solvers solve the model. In order to automatize dimension handling and solving the model for the correct coordinates. Solvers subclass pymob.solver.SolverBase.

from pymob.solvers.analytic import solve_analytic_1d

sim.solver = solve_analytic_1d

Model#

Models are provided as plain Python functions.

def linear_regression(x, a, b):
    return b * x + a

sim.model = linear_regression

Coordinates#

A model is evaluated along the coordinates of the model dimensions

import numpy as np
sim.config.simulation.x_dimension = "x"

sim.coordinates["x"] = np.array([0,1,2,3,4,5])

Model parameters#

Model parameters carry any function parameters, initial values (for ODE models) and other model input such as forcings

.dispatch()#

dispatch() launches a forward pass through the simulation. dispatch_constructor() does all the repetitive work that is only necessary once. It is recommended to use dispatch_constructor after any configuration change

sim.dispatch_constructor()

evaluator_1 = sim.dispatch({"a": 1, "b": 2})
evaluator_2 = sim.dispatch({"a": 10, "b": 3})

evaluator_1()
evaluator_2()
/home/docs/checkouts/readthedocs.org/user_builds/pymob/envs/latest/lib/python3.11/site-packages/pymob/simulation.py:723: UserWarning: The number of ODE states was not specified in the config file [simulation] > 'n_ode_states = <n>'. Extracted the return arguments ['b*x+a'] from the source code. Setting 'n_ode_states=1.
  warnings.warn(

Observations#

Observations are required to be xarray Datasets. An xarray.Dataset is a collection of annotated arrays, using HDF5 data formats for input/output operations.

Simulation results#

Simulation results are returned by the solver. Plainly they are returned as dictionaries containing NDarrays. However, due to the information contained in the observations dataset, the results dictionary is automatically casted to an xarray.Dataset, which has the same shape as the observations. This makes comparisons between observations and simulations extremely easy.

evaluator_1.results
<xarray.Dataset>
Dimensions:  (x: 6)
Coordinates:

  • x (x) int64 0 1 2 3 4 5 Data variables: y (x) int64 1 3 5 7 9 11

evaluator_2.results
<xarray.Dataset>
Dimensions:  (x: 6)
Coordinates:

  • x (x) int64 0 1 2 3 4 5 Data variables: y (x) int64 10 13 16 19 22 25

Parameter estimates#

Parameter estimates are harmonized by reporting them as arviz.InferenceData using xarray.Datasets under the hood. Thereby pymob supports variably dimensional datasets

Parameter estimation#

Parameter estimation is implemented through backends, which can be seen as converters between the pymob.simulation.SimulationBase object and the API of the Inference tool. Inference backends are selected by using

sim.set_inferer("numpyro")
Jax 64 bit mode: False
Absolute tolerance: 1e-07

Supported Algorithms and Planned Features#

Backend

Supported Algorithms

Inference

Hierarchical Models

numpyro

Markov Chain Monte Carlo (MCMC), Stochastic Variational Inference (SVI)

pymoo

(Global) Multi-objective optimization

plan

pyabc

Approximate Bayes

plan

scipy

Local optimization (minimize)

dev

plan

pymc

MCMC

plan

plan

sbi

Simulation Based Inference (in planning)

hold

hold

interactive

interactive backend in jupyter notebookswith parameter sliders

plan