Example: Transit absorption + two-compartment ODE
This example fits an ODE-based two-compartment model with a three-transit absorption chain and allometric scaling. It demonstrates how to combine several features in one model: transit compartments, a lag time, allometric covariate scaling, and a multi-state ODE system.
The transit chain is the standard Savic (2007) parameterization: KTR = (n + 1) / MTT where n = 3 transit compartments, so KTR = 4 / MTT.
Model structure
| State | CMT | Role |
|---|---|---|
transit1 |
1 | Oral dose lands here; lag time applied |
transit2 |
2 | Transit |
transit3 |
3 | Transit |
central |
4 | Observation compartment (concentration, mg/L) |
peripheral |
5 | Peripheral distribution |
ODEs:
d/dt(transit1) = -KTR * transit1
d/dt(transit2) = KTR * transit1 - KTR * transit2
d/dt(transit3) = KTR * transit2 - KTR * transit3
d/dt(central) = KA * transit3 / V1 - (CL/V1 + Q/V1) * central + Q/V2 * peripheral
d/dt(peripheral) = Q * central / V1 - Q/V2 * peripheral
Allometric scaling uses a reference body weight of 70 kg:
CL = TVCL * (WT / 70)^0.75 * exp(ETA_CL)
V1 = TVV1 * (WT / 70)^1.00 * exp(ETA_V1)
V2 = TVV2 * (WT / 70)^1.00
Model file
[parameters]
theta TVCL(5.0, 0.1, 100.0)
theta TVV1(50.0, 5.0, 500.0)
theta TVQ(10.0, 0.1, 200.0)
theta TVV2(100.0, 5.0, 1000.0)
theta TVMTT(1.0, 0.1, 10.0)
omega ETA_CL ~ 0.09
omega ETA_V1 ~ 0.09
omega ETA_KA ~ 0.09
sigma PROP_ERR ~ 0.30 (sd)
[individual_parameters]
CL = TVCL * (WT / 70)^0.75 * exp(ETA_CL)
V1 = TVV1 * (WT / 70)^1.00 * exp(ETA_V1)
Q = TVQ
V2 = TVV2 * (WT / 70)^1.00
KTR = 4.0 / TVMTT
KA = KTR * exp(ETA_KA)
[structural_model]
ode(obs_cmt=central, states=[transit1, transit2, transit3, central, peripheral])
[odes]
d/dt(transit1) = -KTR * transit1
d/dt(transit2) = KTR * transit1 - KTR * transit2
d/dt(transit3) = KTR * transit2 - KTR * transit3
d/dt(central) = KA * transit3 / V1 - (CL / V1 + Q / V1) * central + Q / V2 * peripheral
d/dt(peripheral) = Q * central / V1 - Q / V2 * peripheral
[error_model]
DV ~ proportional(PROP_ERR)
[fit_options]
method = focei
maxiter = 500
covariance = true
The ODE states are listed in [structural_model] in the order they receive doses (CMT 1 = transit1 is the dosing compartment). The obs_cmt=central argument tells ferx which state to predict against DV.
Running
library(ferx)
ex <- ferx_example("transit_2cpt")
fit <- ferx_fit(ex$model, ex$data)
fit
# Inspect the parsed structure
ferx_model_inspect(fit)Dataset requirements
The data file must include a WT covariate column (body weight in kg); it is referenced directly in [individual_parameters]. Dose rows target CMT=1 (transit1).
The transit chain provides the absorption delay via MTT — no separate lag time parameter is needed in this model. To add a true pre-transit lag on top of the transit delay, declare a theta TVLAG and wire it in:
LAGTIME = TVLAG
[structural_model]
ode(obs_cmt=central, states=[transit1, ...], lagtime=LAGTIME)
Tips
- Number of transit compartments: the model is easy to extend. Change the
states=[...]list, add corresponding ODE equations, and updateKTR = (n+1) / TVMTTwith the newn. - Allometric exponents: 0.75 on CL (three-quarter power law) and 1.0 on V are the standard physiological allometry values. Override with estimated thetas if the dataset supports it.
- BSV on Q/V2: Q and V2 carry no BSV here. Add ETAs if peripheral samples are available and residuals show systematic subject-level bias.
See also
- ODE models
- Example: Covariate model — simpler covariate setup
- Example: ODE model (Michaelis-Menten)
- Lag time