Example 5: Local Sensitivity Analysis — One-At-a-Time (OAT) Sampling
This notebook uses OAT (One-At-a-Time) sampling to build a simulation database for local sensitivity analysis on the virus-mac-new model. OAT varies one parameter at a time around a reference point while holding all others fixed — an efficient first screen before committing to a full Sobol analysis (ex3).
What you will learn:
How
sampler='OAT'works —perturbationvalues define the % deviations tested aroundref_valueWhy
qois_info={}is used here (Mode B — raw MCDS stored) and when that is the right choice (see ex2)How to query any QoI from a raw-MCDS database after runs complete using
calculate_qoi_from_db_file
Parameters explored:
mac_phag_rate_infected— macrophage phagocytosis rate of infected cellsmac_motility_bias— macrophage chemotactic motility biasepi2infected_sat— saturation of epithelial infection transitionepi2infected_hfm— half-maximum rate of epithelial infection transition
Storage note:
qois_info={}stores the full MCDS time series per simulation (Mode B from ex2). OAT is often exploratory, so raw storage lets you compute any QoI post-hoc without re-running.
import warnings
warnings.filterwarnings('ignore')
from uq_physicell.model_analysis import ModelAnalysisContext, calculate_qoi_from_db_file
db_path = "ex5_Simulations_OAT.db"
model_config = {"ini_path": "uq_pc_struc.ini", "struc_name": "Model_struc"}
# perturbation values are % deviations applied symmetrically around ref_value
params_info = {
"mac_phag_rate_infected": {"ref_value": 1.0, "perturbation": [1.0, 5.0, 10.0]},
"mac_motility_bias": {"ref_value": 0.15, "perturbation": [1.0, 5.0, 10.0]},
"epi2infected_sat": {"ref_value": 0.1, "perturbation": [1.0, 5.0, 10.0]},
"epi2infected_hfm": {"ref_value": 0.4, "perturbation": [1.0, 5.0, 10.0]},
}
# Empty qois_info → Mode B: raw MCDS stored, QoIs computed post-hoc (see ex2)
qois_info = {}
Generate samples and run simulations
context = ModelAnalysisContext(db_path, model_config, "OAT", params_info, qois_info, num_workers=8)
context.generate_samples()
print(f"Generated {len(context.dic_samples)} samples using OAT")
Generated 25 samples using OAT
Run simulations
context.run()
Simulations completed and results stored in the database: ex5_Simulations_OAT.db.
Query any QoI post-hoc from the stored MCDS database
# Define any QoI — no re-simulation required because raw MCDS is in the database
qoi_funcs = {
"mac_count": lambda df_cell: len(df_cell[df_cell['cell_type'] == 'macrophage']),
"infected_count": lambda df_cell: len(df_cell[df_cell['cell_type'] == 'infected epithelial']),
}
df_qois = calculate_qoi_from_db_file(db_path, qoi_funcs)
display(df_qois.head())
| SampleID | time | ReplicateID | infected_count | mac_count | |
|---|---|---|---|---|---|
| 0 | 0 | 0.0 | 0 | 0 | 10 |
| 1 | 0 | 0.0 | 1 | 0 | 10 |
| 2 | 0 | 0.0 | 2 | 0 | 10 |
| 3 | 0 | 0.0 | 3 | 0 | 10 |
| 4 | 0 | 0.0 | 4 | 0 | 10 |
Next: ex6 uses Latin Hypercube Sampling (LHS) for a global space-filling design — all parameters vary simultaneously instead of one at a time.