[Forge] Biophysical model template: ODEs, parameter fitting, sensitivity analysis
Goal
Create a reusable template that analyses can invoke to build biophysical (mechanistic) models. The template handles the common workflow: define ODE system, fit parameters to data, assess sensitivity, and visualize results. This makes it possible for SciDEX analyses to go beyond statistical summaries and build predictive mechanistic models.
Template Components
1. ODE System Definition
class BiophysicalModel:
def __init__(self, species, reactions, parameters):
self.species = species # ["A_beta", "microglia", "cytokines"]
self.reactions = reactions # [{"type": "production", "species": "A_beta", "rate": "k_prod"}, ...]
self.parameters = parameters # {"k_prod": 0.1, "k_clear": 0.05, ...}
def ode_system(self, t, y):
"""Define dy/dt for each species based on reactions."""
...
def solve(self, t_span, y0, method="RK45"):
"""Solve ODE system using scipy.integrate.solve_ivp."""
return solve_ivp(self.ode_system, t_span, y0, method=method, dense_output=True)
2. Parameter Fitting
def fit_parameters(model, dataset, target_columns,
method="least_squares", bounds=None):
"""Fit model parameters to observed data.
Args:
model: BiophysicalModel instance
dataset: tabular dataset artifact (time-series observations)
target_columns: which dataset columns map to which species
method: optimization method (least_squares, differential_evolution, basin_hopping)
bounds: parameter bounds dict {param_name: (low, high)}
Returns:
fitted_parameters: dict of optimized parameter values
fit_quality: dict with rmse, r_squared, aic, bic
residuals: array of fitting residuals
"""
from scipy.optimize import minimize, least_squares
...
3. Sensitivity Analysis
def sensitivity_analysis(model, parameter_ranges, n_samples=1000):
"""Assess which parameters most affect model output.
Uses Sobol sensitivity analysis (SALib) or simpler one-at-a-time (OAT):
- First-order indices: direct effect of each parameter
- Total-order indices: including interactions
Returns:
sensitivity_indices: {param: {"S1": float, "ST": float}}
tornado_plot_data: sorted parameter importance for visualization
"""
...
4. Result Visualization
Generate figure artifacts:
- Time-course plot: model predictions vs observed data
- Parameter sensitivity tornado: ranked parameter importance
- Phase portrait: 2D state-space trajectories (optional)
- Fit residual plot: residuals over time to check systematic bias
5. Artifact Registration
After execution, register:
Model artifact (type=model, family=biophysical) with fitted parameters
Figure artifacts for each visualization
All linked via artifact_links (model derives_from dataset, figures derive_from model)Example Usage (from an analysis step)
# In analysis execution engine
model = BiophysicalModel(
species=["A_beta", "microglia", "IL1b"],
reactions=[
{"type": "production", "species": "A_beta", "rate": "k_prod"},
{"type": "clearance", "species": "A_beta", "rate": "k_clear", "catalyst": "microglia"},
{"type": "activation", "species": "microglia", "rate": "k_act", "trigger": "A_beta"},
{"type": "secretion", "species": "IL1b", "rate": "k_secrete", "source": "microglia"}
],
parameters=get_initial_params_from_kg(hypothesis_id) # KG-derived initial guesses
)
fitted = fit_parameters(model, dataset, target_columns={"A_beta": "amyloid_level", "microglia": "iba1_count"})
sensitivity = sensitivity_analysis(model, parameter_ranges=auto_bounds(fitted.parameters))
# Register artifacts
model_id = register_model("biophysical", "Microglial Activation ODE v1",
metadata={...fitted...},
trained_on_dataset_id=dataset_id)
Acceptance Criteria
☐ BiophysicalModel class handles ODE definition and solving
☐ Parameter fitting against tabular dataset data
☐ At least two fitting methods supported (least_squares + one global)
☐ Sensitivity analysis produces parameter importance ranking
☐ Time-course visualization generated as figure artifact
☐ Sensitivity tornado plot generated as figure artifact
☐ All outputs registered as versioned artifacts with provenance links
☐ Template can be invoked from analysis model_building step
☐ Work log updated with timestamped entry
Dependencies
- frg-mb-01-ANLX (model-building step type in analysis framework)
Dependents
- d16-23-BMOD0001 (demo: biophysical model from KG parameters)
Work Log
2026-04-26 04:30 PT — Slot 42
- Verified
scidex/forge/biophysical_model_template.py already committed to main (SHA: a8987981d)
- Template includes:
BiophysicalModel class (ODE + solve), fit_parameters (least_squares/differential_evolution/minimize), sensitivity_analysis (OAT), plot_time_course, plot_sensitivity_tornado, plot_residuals, register_biophysical_model_artifacts
- Tested import and model.solve() — both OK
- Template in use: 3 artifact training scripts in
artifacts/models/ import from scidex.forge.biophysical_model_template
- Fixed unused
import sqlite3 (SQLite retired in SciDEX; violated retirement policy)
- Acceptance criteria: all met — BiophysicalModel ODE/solve ✓, parameter fitting ✓, ≥2 fit methods ✓, sensitivity analysis ✓, time-course plot ✓, sensitivity tornado ✓, artifact registration ✓, invocable from analysis scripts ✓