calibration Module#
Parameter calibration for compartmental models.
This module provides tools to fit model parameters to observed incidence or mortality data using scipy.optimize.minimize.
Classes#
- class episia.models.calibration.ModelCalibrator(model_class, param_class, fixed_params, fit_params, loss='mse')[source]#
Bases:
objectFit a compartmental model to observed time-series data.
Supports simultaneous fitting to multiple compartments (e.g. infected + deaths for SEIRD).
Example:
from episia.models.calibration import ModelCalibrator from episia.models.sir import SIRModel from episia.models.parameters import SIRParameters calibrator = ModelCalibrator( model_class=SIRModel, param_class=SIRParameters, fixed_params=dict(N=1_000_000, I0=1, t_span=(0, 60)), fit_params={ "beta": (0.05, 1.0), # (lower_bound, upper_bound) "gamma": (0.01, 0.5), }, ) result = calibrator.fit( t_observed=days, observed={"I": infected_counts}, ) print(result)
- __init__(model_class, param_class, fixed_params, fit_params, loss='mse')[source]#
- Parameters:
model_class – CompartmentalModel subclass (SIRModel, SEIRModel…).
param_class – Matching parameters class.
fixed_params (Dict[str, Any]) – Parameters held constant during optimisation.
fit_params (Dict[str, Tuple[float, float]]) – Parameters to fit; values are (lower, upper) bounds.
loss (str) – Loss function: ‘mse’, ‘rmse’, ‘mae’, ‘poisson’.
- fit(t_observed, observed, method='L-BFGS-B', options=None)[source]#
Fit model parameters to observed data.
- Parameters:
t_observed (ndarray) – Time points of observations (days).
observed (Dict[str, ndarray]) – Dict mapping compartment name → array of observations. E.g. {‘I’: infected_array} or {‘I’: …, ‘D’: …}.
method (str) – scipy.optimize.minimize method (default L-BFGS-B).
options (Dict | None) – Extra options for scipy.optimize.minimize.
- Returns:
CalibrationResult with best-fit parameters and diagnostics.
- Return type:
- class episia.models.calibration.CalibrationResult(parameters, loss, success, message, n_iterations, residuals=None)[source]#
Bases:
objectResult of a parameter calibration run.
- Parameters:
- residuals#
Observed − predicted array.
- Type:
numpy.ndarray | None
Examples#
Fitting an SIR model to incidence data:
import numpy as np
from episia.models import SIRModel
from episia.models.parameters import SIRParameters
from episia.models.calibration import ModelCalibrator
# Observed weekly cases
days = np.arange(0, 140, 7)
observed_cases = np.array([10, 25, 60, 120, 200, 280, 350, 380, 370, 300, 210, 130, 70, 30, 15, 8, 4, 2, 1, 0])
calibrator = ModelCalibrator(
model_class=SIRModel,
param_class=SIRParameters,
fixed_params={
'N': 1_000_000,
'I0': observed_cases[0],
't_span': (0, 140)
},
fit_params={
'beta': (0.1, 1.0), # Search bounds
'gamma': (0.05, 0.5)
},
loss='rmse'
)
result = calibrator.fit(
t_observed=days,
observed={'I': observed_cases}
)
print(f"Best fit: β={result.parameters['beta']:.3f}, γ={result.parameters['gamma']:.3f}")
print(f"R₀={result.parameters['beta']/result.parameters['gamma']:.2f}")
print(f"Loss: {result.loss:.2f}")
# Run calibrated model
cal_result, model_result = calibrator.fit_and_apply(days, {'I': observed_cases})
model_result.plot().show()
Fitting multiple compartments (SEIRD):
# Fit to both cases and deaths
calibrator = ModelCalibrator(
model_class=SEIRDModel,
param_class=SEIRDParameters,
fixed_params={'N': 1e6, 'I0': 10, 'E0': 50, 't_span': (0, 200)},
fit_params={
'beta': (0.1, 1.0),
'mu': (0.001, 0.1) # Mortality rate
}
)
result = calibrator.fit(
t_observed=days,
observed={
'I': observed_cases,
'D': observed_deaths
}
)