Derived Columns and Output
This example demonstrates the [derived] and [output] blocks, which add post-fit computed columns and individual PK parameter columns to the sdtab. The complete model file is examples/warfarin_derived.ferx.
When to use
Use [derived] when you need columns in the sdtab that are not observations or predictions — for example, elimination half-life, NCA metrics (AUC, Cmax), or dosing-day labels. Use [output] when you want individual parameter estimates (CL, V, …) or covariates echoed directly into the sdtab alongside diagnostics.
Model file
This is the contents of examples/warfarin_derived.ferx:
# One-compartment oral PK model (warfarin) -- [derived] and [output] demo
[parameters]
theta TVCL(0.2, 0.001, 10.0)
theta TVV(10.0, 0.1, 500.0)
theta TVKA(1.5, 0.01, 50.0)
omega ETA_CL ~ 0.09
omega ETA_V ~ 0.04
omega ETA_KA ~ 0.30
sigma PROP_ERR ~ 0.02 (sd)
[individual_parameters]
CL = TVCL * exp(ETA_CL)
V = TVV * exp(ETA_V)
KA = TVKA * exp(ETA_KA)
[structural_model]
pk one_cpt_oral(cl=CL, v=V, ka=KA)
[error_model]
DV ~ proportional(PROP_ERR)
[derived]
# Per-row: elimination rate and half-life
KE = CL / V
T_HALF = 0.6931472 / KE
# Which dosing day (tau = 24 h)
DAY = floor(TAFD / 24) + 1
TAU_TIME = TAFD mod 24
# Subject-level aggregates (one scalar per subject, repeated across rows)
CMAX = max(IPRED)
TMAX = tmax(IPRED)
CTROUGH = min(IPRED, TAD < 1e-10)
CMAX_D1 = max(IPRED, TAFD < 24)
CMAX_D14 = max(IPRED, TAFD >= 312 && TAFD < 336)
# AUC over first 72 h (fine internal grid, 500 steps)
AUC_0_72 = integral(IPRED, from=0, to=72)
# Periodic AUC: one value per 24-h dosing window
AUC_TAU = integral(IPRED, window=24, anchor=0, step=0.1)
# DV-based AUC (observation times only -- no interpolation)
AUC_DV_72 = integral(DV, from=0, to=72)
[output]
CL V KA
[fit_options]
method = foce
maxiter = 300
covariance = true
Key points:
[derived]expressions are evaluated for each observation row after the fit. They can reference individual-parameter names (CL,V), theta names (TVCL), eta names (ETA_CL), covariate names,IPRED,PRED,DV,TAFD,TAD, andTIME.- Per-row expressions like
KE = CL / Vproduce one value per observation. - Aggregate expressions (
max,min,tmax) produce one value per subject, broadcast to all of that subject’s observation rows. - Integral expressions compute AUC. Use
from=/to=for a fixed window orwindow=for periodic (per-dose) AUC. Astep=argument causes evaluation on a uniform grid (useful for time-above-threshold or dense AUC). [output]echoes individual parameters (CL V KA) and covariates as additional sdtab columns. Derived columns (from[derived]) are already written automatically — no need to list them again in[output].
Running the fit
ferx examples/warfarin_derived.ferx --data data/warfarin.csvOr via the Rust API:
let result = fit_from_files("examples/warfarin_derived.ferx", "data/warfarin.csv")?;
// Derived columns are in result.sdtab_extra or the written CSVInterpreting output
The sdtab gains extra columns after the mandatory minimum (ID, TIME, DV, PRED, IPRED, …):
ID,TIME,DV,PRED,IPRED,CWRES,IWRES,EBE_OFV,N_OBS,TAFD,TAD,KE,T_HALF,DAY,TAU_TIME,CMAX,TMAX,CTROUGH,CMAX_D1,CMAX_D14,AUC_0_72,AUC_TAU,AUC_DV_72,CL,V,KA
Subject-level aggregates (CMAX, TMAX, AUC_TAU, etc.) repeat the same value on every observation row for a given subject, making them easy to join to per-subject summaries.
Tips
- Sequential scoping: a derived expression may reference any derived name defined earlier in the same
[derived]block.T_HALF = 0.6931472 / KEis valid becauseKEis defined one line above. - AUC step size:
step=0.1(6-minute grid) is sufficient for most PK curves. Reduce tostep=0.01only if the half-life is very short relative to the dosing interval. - Trough via TAD:
min(IPRED, TAD < 1e-10)catches the dose-time row after ADDL expansion. The1e-10tolerance absorbs floating-point residuals from modular time arithmetic. - Covariate shadowing: listing a covariate name in
[derived]replaces the raw covariate with your computed value. AW_DERIVED_COVARIATE_SHADOWwarning is emitted; this is intentional if you want a transformed covariate in the sdtab. - Names that clash with mandatory sdtab columns (
ID,TIME,DV,PRED,IPRED,CWRES,IWRES,EBE_OFV,N_OBS,TAFD,TAD,CENS,OCC,CMT) are rejected at parse time.