Fast nonlinear mixed effects (NLME) modeling in R, powered by a Rust backend with Enzyme automatic differentiation for exact gradients.
.ferx text filesA Rust installation with the Enzyme AutoDifferentiation engine is required for FeRx to compute gradients. Most likely you will need to build Rust from source, which may take an hour or so.
See documentation for installation instructions.
After installing Rust, in R run:
devtools::install_github("FeRx-NLME/ferx-r")Or from a local clone:
Native Windows installs are supported, but without the Enzyme autodiff backend — gradients fall back to finite differences, which is slower and less accurate. For full-fidelity autodiff on Windows, use the Docker image below.
Prerequisites:
You do not need to rustup default it — the package’s build pins this toolchain automatically on Windows. (The rustup default on Windows is the MSVC ABI, which is not link-compatible with Rtools’ MinGW linker.)
Then install in R:
devtools::install_github("FeRx-NLME/ferx-r")
library(ferx)
# Get bundled example paths
ex <- ferx_example("warfarin")
# Fit a one-compartment oral PK model
result <- ferx_fit(ex$model, ex$data, method = "focei")
result
# Simulate at the fitted estimates (typical VPC flow)
sim <- ferx_simulate(ex$model, ex$data, n_sim = 100, seed = 42, fit = result)
# Population predictions at the fitted estimates
preds <- ferx_predict(ex$model, ex$data, fit = result)Pass fit = <ferx_fit result> to ferx_simulate() / ferx_predict() to use the fitted theta / omega / sigma. Omit it to use the model file’s initial values.
For observations below the lower limit of quantification, flag them with a CENS column in the data (1 = censored, with DV carrying the LLOQ value) and pass bloq_method = "m3" to ferx_fit(). Each censored observation then contributes P(y < LLOQ | θ, η) = Φ((LLOQ − f)/√V) to the likelihood instead of a Gaussian residual, avoiding the terminal-phase bias that comes from simply dropping BLOQ rows.
bloq <- ferx_example("warfarin_bloq")
result <- ferx_fit(bloq$model, bloq$data, method = "focei", bloq_method = "m3")
sim <- ferx_simulate(bloq$model, bloq$data, n_sim = 100, seed = 42, fit = result)See inst/examples/ex1a_warfarin_bloq.R for a full fit + VPC walkthrough.
Models are defined in .ferx files:
[parameters]
theta TVCL(0.2, 0.001, 10.0) # name(initial, lower, upper)
theta TVV(10.0, 0.1, 500.0)
theta TVKA(1.5, 0.01, 50.0)
omega ETA_CL ~ 0.09 # between-subject variability (variance)
omega ETA_V ~ 0.04
omega ETA_KA ~ 0.30
sigma PROP_ERR ~ 0.02
[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)
See ferx_example() for available bundled examples.
| Function | Description |
|---|---|
ferx_fit() |
Fit a NLME model (FOCE/FOCEI). bloq_method = "m3" enables M3. |
ferx_simulate() |
Simulate replicates with BSV and residual error. Pass fit = to use fitted estimates. |
ferx_predict() |
Population predictions (ETA = 0). Pass fit = to use fitted theta. |
ferx_example() |
Get paths to bundled example models and data |
MIT — see LICENSE.md.