# Stage 5 — Model Fitting and Calibration Report

**Pipeline stage:** 5 of 14
**Date:** 2 May 2026
**Author:** IQANOVA AI-QSP Master Pipeline v2.0

---

## 5.1 Approach

The v2.0 ODE model was implemented in Python as a faithful mirror of the SBML L3V2 specification (Stage 2). Time-course integration used `scipy.integrate.solve_ivp` with the LSODA adaptive method, relative tolerance 1×10⁻⁶ and absolute tolerance 1×10⁻⁹. Dose events at days 0, 14, 28, … 364 (27 fortnightly events) were applied as discrete impulses to the plasma compartment. Calibration was framed as minimisation of a weighted sum of squared residuals over 40 reliability-A anchor datapoints (calibration + bridge calibration roles only); the weight on each row was the reciprocal of its standard error squared. Optimisation used Nelder-Mead with the adaptive variant (`scipy.optimize.minimize`).

## 5.2 Free parameters

Sixteen physiological-rate and shape parameters were treated as free for adult calibration; an additional two parameters (`k_height_catchup`, `height_z_asymptote`) were free in the paediatric calibration. All free parameters carried explicit lower and upper bounds (Q1 traceability requirement). Initial guesses were taken from the v1.3 nominal values where these were biologically defensible, otherwise from the midpoint of the bounds.

| Adult / paediatric free parameter | Bound (lower) | Bound (upper) | Source |
|---|---|---|---|
| k_spleen_resolution | 0.0010 | 0.020 | FITTED |
| k_liver_resolution | 0.0010 | 0.020 | FITTED |
| k_lung_resolution | 0.0008 | 0.015 | FITTED |
| spleen_resolution_max_frac | 0.30 | 0.65 | FITTED (anchored to ASCEND-OLE 2y nadir) |
| liver_resolution_max_frac | 0.20 | 0.50 | FITTED (anchored to ASCEND-OLE 2y nadir) |
| lung_resolution_max_frac | 0.20 | 0.55 | FITTED (anchored to ASCEND-OLE DLCO peak) |
| kcat_ASM | 0.30 | 1.50 | FITTED (Schuchman & Desnick 2017 enzymology) |
| k_LysoSM_generation | 0.0010 | 0.020 | FITTED (EMA PI 2024 biomarker dynamics) |
| k_LysoSM_clearance | 0.0010 | 0.030 | FITTED |
| k_ceramide_generation_from_SM | 0.005 | 0.040 | FITTED |
| k_ceramide_clearance | 0.020 | 0.150 | FITTED |
| ceramide_burden_coupling | 0.10 | 1.00 | FITTED |
| DLCO_gain_max_pct | 15.0 | 60.0 | FITTED (anchored to W104 ASCEND-OLE) |
| DLCO_kinetic_rate | 0.001 | 0.015 | FITTED (n.b. supplanted by linear-proportional formula in v2.0) |
| platelet_gain_max_frac | 0.10 | 0.50 | FITTED |
| platelet_kinetic_rate | 0.001 | 0.020 | FITTED (n.b. supplanted by linear-proportional formula in v2.0) |
| k_height_catchup (paediatric only) | 0.001 | 0.010 | FITTED |
| height_z_asymptote (paediatric only) | 0.5 | 2.0 | FITTED (Diaz 2024 ASCEND-Peds 2y) |

All other parameters are fixed at biologically grounded literature values.

## 5.3 Mid-pipeline correction (made during this calibration)

During initial calibration, DLCO and platelet predictions clustered near 0% despite tissue burden resolution proceeding correctly. Diagnostic inspection showed that the saturating-exponential observable formulas `1 − exp(−κ·Δburden/baseline)` were operating in the linear regime at all relevant time points (the kinetic_rate × fractional-clearance argument was always ≪ 1 because both factors were small). The observable formulas were reformulated as linear-proportional functions:

```
DLCO_percent_change      = DLCO_gain_max_pct      × (Δlung_burden  / (baseline_lung  × lung_resolution_max_frac))
platelet_percent_change  = 100 × platelet_gain_max_frac × (Δspleen_burden / (baseline_spleen × spleen_resolution_max_frac))
```

These formulas approach `DLCO_gain_max_pct` (resp. `100 × platelet_gain_max_frac`) as the burden reaches its resolution asymptote and 0 at baseline. The corrected SBML rules use `piecewise()` to enforce non-negativity. After this correction, the calibration weighted SSR dropped from **259** (initial) to **10.75** (final), a **24×** improvement.

## 5.4 Calibration result summary

| Metric | Value |
|---|---|
| Initial weighted SSR | 259.07 |
| Final weighted SSR | 10.75 |
| Improvement factor | 24.1× |
| Calibration anchor rows | 40 |
| Predictions evaluated (all roles) | 370 |
| Overall PASS rate (\|residual\| ≤ 1.5×SE) | **93.0%** |
| Calibration rows PASS rate | **96.0%** |
| Holdout rows PASS rate | **83.3%** |

## 5.5 RMSE per endpoint per population (all rows)

| Population | Endpoint | n | RMSE | PASS % |
|---|---|---|---|---|
| Adult | spleen_volume_pct | 29 | **0.79** | 100.0 |
| Adult | liver_volume_pct  | 29 | **0.93** | 100.0 |
| Adult | DLCO_pct          | 29 | **0.35** | 100.0 |
| Adult | platelet_pct      | 28 | **0.75** | 100.0 |
| Adult | LysoSM_pct        | 28 | 12.55    | 57.1 |
| Adult | Ceramide_pct      | 28 | **2.78** | 100.0 |
| Paediatric | spleen_volume_pct | 29 | **0.99** | 100.0 |
| Paediatric | liver_volume_pct  | 29 | **1.47** | 100.0 |
| Paediatric | DLCO_pct          | 29 | **1.87** | 100.0 |
| Paediatric | platelet_pct      | 28 | **4.60** | 100.0 |
| Paediatric | LysoSM_pct        | 28 | **7.86** | 100.0 |
| Paediatric | Ceramide_pct      | 28 | 28.50    | 50.0 |
| Paediatric | height_z_change   | 28 | **0.22** | 100.0 |

**Bold = endpoints meeting pre-specified RMSE benchmark (≤ 1.5× SE per row average).**

## 5.6 Endpoints requiring further attention (Limitations / v2.1)

Two endpoints did not fully meet the pre-specified benchmark and are flagged for v2.1 re-calibration with denser early-time data and a richer biomarker model:

1. **Adult LysoSM_pct** (RMSE 12.55%, PASS 57%): the model overshoots the W52 and W104 nadirs (predicted ≈ −91 to −99%; observed −77.7 to −82%). Root cause: substrate-driven generation rate `k_LysoSM_generation` saturates the system once `SM_lysosome` falls below its ~50% asymptote. Action: introduce a saturating Hill function in `LysoSM_plasma` generation; refit in v2.1.
2. **Paediatric Ceramide_pct** (RMSE 28.50%, PASS 50%): early-week peak (~+12.5%) and W26 trough are not fully captured by the current sphingolipid pharmacodynamics (predicted −65% vs observed −34% at W26). Root cause: the burden-coupling term is too aggressive in paediatrics; needs a two-compartment plasma ceramide model (acute + chronic). Action: add explicit acute and chronic ceramide pools in v2.1.

## 5.7 Files produced

| File | Description |
|---|---|
| `stage05_calibration/calibrate_v2.py` | ODE simulator + Nelder-Mead calibration script |
| `stage05_calibration/ASMD_Xenpozyme_QSP_v2_0_parameters.csv` | All parameters with FITTED/LIT label and bounds |
| `stage05_calibration/ASMD_Xenpozyme_QSP_v2_0_predictions.csv` | All 370 predictions with residuals, Z-scores, PASS flags |
| `stage05_calibration/ASMD_Xenpozyme_QSP_v2_0_rmse_summary.csv` | RMSE table per population × endpoint × role |
| `stage05_calibration/p_fitted_adult.npy` | Adult fitted parameter vector |
| `stage05_calibration/p_fitted_paediatric.npy` | Paediatric fitted parameter vector |
| `stage05_calibration/model_summary.json` | Full model summary including loss history |

**Gates G3 (parameter provenance) and G4 (RMSE benchmarks) — PASS for 11/13 endpoints; CONDITIONAL PASS overall (two endpoints flagged for v2.1). Gate to Stage 6: OPEN.**
