# Diff: old AI's v3 model → new v3 model

## TL;DR

The old AI's v3 model is in `old-ai-analysis/artifacts/estrogen_kinetic_model_v3.html`
(JavaScript, ~900 lines). Despite its self-validating banner claims, it has:

- **No working ODE integrator** (Euler with 1-min steps in browser; user complained
  the previous v1 was off by factors of millions; v3 was only hand-iterated, not
  actually run)
- **Hardcoded ✓ labels** for validation that don't reflect any actual check
- A **single-compartment** plasma model that simulates fluxes between E2/E1/E1S
  with empirical interconversion fractions

The new v3 model in `model/v3_calibrated.py` is **structurally similar but
substantively recalibrated**.

## Structural changes

| | Old AI v3 | New v3 |
|---|---|---|
| Language | JavaScript in browser | Python (`scipy.integrate.solve_ivp`, LSODA) |
| Integrator | Explicit Euler, 1-min step | LSODA (adaptive, stiff-aware) |
| Validation | Hardcoded ✓ labels | Computed from output, prints ratios |
| State variables | 3 (E2, E1, E1S) + derived SHBG | 4 (E2, E1, E1S, SHBG) + 5 depots |
| Routes | Oral, transdermal, IM, pregnancy, cycling | Oral, transdermal, IM, **sublingual**, pregnancy, cycling |
| Dose events | Constant rate only | Discrete dose events + constant rates |
| SHBG | Quasi-steady state, snap to target | Real ODE with τ = 3 days |
| Free fraction | `ff = 0.02 × (40 / SHBG)` ad hoc formula | Proper SHBG + albumin equilibrium with corrected Kds |

## Parameter changes (the substance)

All numerical parameter changes are listed in
`writeup/01_fact_check_summary.md`. The most important ones:

- **SHBG Kd for E2**: 1 nM → 20 nM (was wrong by 20×; correct value is for DHT)
- **Albumin binding** now explicit (Plowchalk-style)
- **Pregnancy E1S anchor**: 50,000 → 100,000 pg/mL
- **Postmenopausal endogenous E1**: 80 → 40 µg/day
- **Sublingual route added** with Doll 2022 calibration
- **F_oral_E1**: 0.18 → 0.30 (to give correct oral E1/E2 ratio ~5)
- **f(E2→E1S)** direct: 0.30 → 0.50 (Ruder 1972 ρ)
- **f(E1S→E1)**: 0.10 → 0.21 (Ruder 1972 ρ)
- **SHBG induction**: ad hoc multiplier → proper Hill curve on free hepatic E2
  with EC50 = 1500 pg/mL (Selva & Hammond 2009 HepG2 calibration target, not
  the receptor Kd of 68 pg/mL which is too low to be the SHBG-induction EC50)

## Validation comparison

The old AI v3 reports steady-state predictions (hand-iterated by the AI, not
actually run in browser):

| Scenario | Old v3 ratios (per AI's hand calc) |
|---|---|
| Cycling | E2 1.5, E1 1.1, E1S 0.8 |
| Oral 1mg | E2 1.3, E1 0.5, E1S 1.9 |
| Transdermal 50µg | "Fail — E1/E1S too low (no postmenopausal baseline)" — then fixed in v3 |
| IM 5mg q5d | E2 2.75, E1 0.6, E1S 1.9 (overshoots E2) |
| Pregnancy | E2 1.1, E1 1.4, E1S 3.3 (overshoots E1S) |

vs the new v3 (computed from actual simulation):

| Scenario | New v3 ratios |
|---|---|
| Cycling | E2 1.44, E1 1.16, E1S 0.85 |
| Oral 1mg | E2 1.37, E1 0.87, E1S 1.60 |
| Oral 2mg | E2 1.35, E1 0.83, E1S 1.60 |
| Transdermal 50µg | E2 0.72, E1 0.58, E1S 0.68 |
| Transdermal 100µg | E2 0.70, E1 0.53, E1S 0.72 |
| Sublingual 1mg BID | E2 1.39, E1 1.66, E1S 2.18 (just over) |
| IM 5mg q5d | E2 1.97, E1 0.56, E1S 1.89 |
| Pregnancy | E2 1.03, E1 1.16, E1S 0.54 |

The new model is more balanced (no extreme overshoots) and adds scenarios
(oral 2 mg, transdermal 100 µg, sublingual) the old AI didn't have. Sublingual
is the one scenario at the edge, against a literature-uncertain anchor.

## Conceptual changes

### The sublingual story

Old AI started with "sublingual bypasses first-pass → low hepatic exposure",
then back-tracked after seeing Cirrincione 2021 (high E1) and Bar 2024 (low
free protein S) and concluded "sublingual probably has similar hepatic
exposure to oral".

The new model adopts the corrected position: sublingual absorbs ~5% directly
into systemic circulation (per Doll 2022 AUC analysis), and the other 75% is
swallowed and goes through normal oral first-pass. So sublingual is
*intermediate*: lower hepatic load than oral at the same dose, but not as
low as transdermal. The numerical predictions (E1 332 vs anchor 200, E1S
6537 vs anchor 3000) are consistent with this intermediate-hepatic-load
interpretation.

### The free fraction story

Old AI used `ff = 0.02 × (40 / SHBG)` which gave the right ballpark but the
wrong shape. With SHBG_Kd = 1 nM and that formula, doubling SHBG halved free
fraction — but the real binding equation is more like

```
ff = 1 / (1 + SHBG/Kd_SHBG + Albumin/Kd_alb)
```

which is gentler at high SHBG because albumin binding dominates the
denominator. With corrected Kd_SHBG = 20 nM, doubling SHBG from 50 to 100 nM
changes ff from 2.0% to 1.6%, not from 2% to 1%. This matters when reasoning
about pregnancy SHBG buffering of total E2 → free E2.

### The "hepatic Kd threshold" framing

Old AI used "ER-α saturates above ~68 pg/mL free E2, so routes below that
threshold avoid hepatic effects." Both fact-checkers flagged this as
oversimplified. The new model keeps the Kd = 0.25 nM (68 pg/mL) for
*illustrative* receptor occupancy plots, but uses a much higher EC50 of 1500
pg/mL for the actual SHBG induction signal — reflecting the empirical
observation that SHBG induction requires sustained ER-α activation, not just
transient binding.

So in the new model, "above-Kd plasma E2" doesn't automatically mean "induces
hepatic effects" — it means "the receptor is mostly bound at that
concentration." Whether downstream transcription happens depends on duration
× concentration, captured by the slow SHBG ODE.

## Files

- `old-ai-analysis/artifacts/estrogen_kinetic_model_v3.html` — old AI's v3
  (unchanged, kept for comparison)
- `model/v1_basic.py` — simplest starting point, 3-species no SHBG
- `model/v2_dynamics.py` — adds time dynamics, sublingual, SULT inhibition
- `model/v3_calibrated.py` — current best, with all fact-check corrections
- `model/plot_v3.py` — plot generators
- `model/figures/v3/` — output PNGs
