Model File Reference
ferx-core models are defined in .ferx files using a declarative DSL. Each file is organized into blocks, each denoted by a [block_name] header.
Block Overview
| Block | Required | Purpose |
|---|---|---|
[parameters] |
Yes | Define theta, omega, and sigma parameters |
[individual_parameters] |
Yes | Map population parameters to individual PK parameters |
[structural_model] |
Yes | Specify the PK model (analytical or ODE) |
[error_model] |
Yes | Define the residual error model |
[odes] |
If ODE | ODE right-hand-side equations |
[adaptive_dosing] |
No | Feedback / TDM dose controller for simulate() |
[covariates] |
No | Declare which data columns are covariates (and how they interpolate) |
[covariate_nn NAME] |
No | Neural-network covariate model (needs --features nn) |
[data] |
No | Point at the dataset CSV ($DATA equivalent); overridden by an explicit CLI/R path |
[data_selection] |
No | Row/subject filters applied to the dataset |
[derived] |
No | Post-hoc derived quantities written to sdtab |
[diffusion] |
No | SDE diffusion terms |
[fit_options] |
No | Configure estimation method and optimizer |
[initial_conditions] |
No | Non-zero compartment initial amounts |
[mixture] |
No | Mixture (subpopulation) model |
[output] |
No | Extra sdtab output columns |
[scaling] |
No | Compartment scaling / observation readouts |
[simulation] |
No | Define a simulation trial design |
[binary_model] |
No | Binary / logistic endpoint (needs --features survival) |
[event_model] |
No | Time-to-event endpoint (needs --features survival) |
[markov_model] |
No | Continuous-time Markov endpoint (needs --features markov) |
Block names are closed-world: a header that is not in this table is an error (E_UNKNOWN_BLOCK), reported with its line number and a did-you-mean when there is a near match. A misspelled optional block used to be ignored in silence — a [fit_option] typo left the fit running with the default method and no covariance step while ferx check still reported valid: true.
The same applies to the instance-name form: [covariate_nn NAME] requires a name, and every other block refuses one (E_BLOCK_INSTANCE_NAME). A block whose cargo feature this binary lacks is refused too, rather than quietly dropped (E_BLOCK_FEATURE_DISABLED); the valid-set the error message enumerates is likewise the set this build accepts, so a default build does not advertise [event_model].
[initial_values] is not a block. Initial estimates are declared inline in [parameters] (theta NAME(init, lower, upper), omega NAME ~ variance); the separate block predates that and has not been read for several releases. A file still carrying one is now rejected with E_DEPRECATED_BLOCK naming the replacement — delete the block.
Model name
A file may name its model on one line before the first [block] header, in either spelling:
model warfarin_pk
model = warfarin_pk
The name is what fit$model_name, ferx run’s summary line, the -fit.json model_name field and ferx check --json’s model field report; a file with no model line is named after its file stem (warfarin_pk.ferx → warfarin_pk). It does not name the output files: {stem}-fit.yaml, {stem}-sdtab.csv and friends are always derived from the file stem, so model warfarin_pk in run3.ferx still writes run3-fit.yaml (and -fit.yaml itself carries no name field). Names are letters, digits and underscores. A model line the parser cannot read (model = two words), or a second one, is an error naming the accepted forms — model = NAME used to be dropped in silence, leaving the stem in place with no diagnostic. Only the preamble is read: a model NAME / model = NAME declaration inside any block is an error naming the block, since a block that ignores unrecognised lines would otherwise drop it silently. A line that merely starts with the keyword (model = CL * 2) is that block’s own line. Other non-comment preamble text is ignored.
Minimal Example
[parameters]
theta TVCL(0.1, 0.001, 10.0)
theta TVV(10.0, 0.1, 500.0)
omega ETA_CL ~ 0.09
omega ETA_V ~ 0.04
sigma ADD_ERR ~ 1.0
[individual_parameters]
CL = TVCL * exp(ETA_CL)
V = TVV * exp(ETA_V)
[structural_model]
pk one_cpt_iv(cl=CL, v=V)
[error_model]
DV ~ additive(ADD_ERR)
Lines beginning with # are treated as comments.