# Nonmem

> Author, edit, debug, and interpret NONMEM control streams (.ctl, .mod), datasets, and output files for population PK/PD modeling. Use whenever the user mentions NONMEM, NM-TRAN, PREDPP, control streams, $PROBLEM/$INPUT/$DATA/$SUBROUTINES/$PK/$ERROR/$THETA/$OMEGA/$SIGMA/$ESTIMATION blocks, ADVAN/TRANS routines, FOCE/FOCEI/Laplace/SAEM/IMP/BAYES/ITS/NUTS methods, MU referencing, EVID/AMT/RATE/ADDL/SS/MDV dataset items, .lst/.ext/.phi/.cov/.cor output files, VPCs/pcVPCs, or anything resembling a NONMEM workflow. Use even when the user just shows a `.ctl`-looking file or talks about "estimating a pop-PK model" without naming NONMEM explicitly — this skill applies.

- Skill: `jaj42/nonmem` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add jaj42/nonmem`
- Raw SKILL.md: https://api.skillmd.com/api/skills/jaj42/nonmem/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: jaj42 (https://skillmd.com/u/jaj42)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/jaj42/nonmem

---


# NONMEM

A working skill for editing and reasoning about NONMEM control streams, datasets, and outputs. Assume the user knows pharmacometrics; the value here is consolidating the rules that frequently bite people — dataset events, MU referencing, estimation-method choice, and output-file structure.

## What's in this skill

- This file: the daily-driver reference. Workflow, control-stream skeleton, dataset rules, MU referencing, method choice, output files.
- `references/control-records.md`: detailed syntax of common `$`-records.
- `references/advan-trans.md`: when to pick which ADVAN/TRANS and what parameters they require.
- `references/diagnostics-vpc.md`: VPC and pcVPC workflow, residual diagnostics, shrinkage.
- `references/common-errors.md`: the error messages that come up over and over and how to fix them.

Read this file first. Pull in references only when the task needs that depth (e.g. picking ADVAN for a stiff ODE system → `advan-trans.md`).

## Workflow

When the user asks for help with a NONMEM task, work in this order:

1. **Read what they have.** If a `.ctl` (or `.mod`/`.nm`) file is mentioned or pasted, look at it before suggesting changes. The structure of the existing model tells you what ADVAN/TRANS is in play, what's MU-referenced, what error model is being used, and which estimation method is set. Don't propose changes that conflict silently with what's already there.
2. **Read the data layout.** A control stream cannot be evaluated without the `$INPUT` line and ideally a sample of the dataset. Dose/observation interleaving, EVID values, RATE vs II/ADDL — these change what the model is actually doing.
3. **Identify the goal.** "Add a covariate", "switch to SAEM", "fix the round-off error in $COV", "set up a VPC" — each has a standard playbook below or in references.
4. **Make minimal, syntactically valid edits.** NM-TRAN is strict. Trailing characters, the wrong record order, a comment that exceeds the column limit — any of these can break a run silently or with a cryptic error. When editing, preserve indentation and comments.
5. **Sanity-check the change.** Before declaring done: do the THETA/ETA/EPS indices still line up? Do `$OMEGA` and `$SIGMA` have the right dimension for the references in `$PK`/`$ERROR`? Is the data file readable with the new `$INPUT`?

## Control-stream skeleton

A minimal population PK control stream looks like this. The record order shown is conventional and safe:

```
$PROBLEM Two-compartment IV, FOCE-I
$INPUT   ID TIME AMT RATE EVID MDV CMT DV WT
$DATA    data.csv IGNORE=@
$SUBROUTINES ADVAN3 TRANS4

$PK
  TVCL = THETA(1) * (WT/70)**0.75
  TVV1 = THETA(2) * (WT/70)
  TVQ  = THETA(3) * (WT/70)**0.75
  TVV2 = THETA(4) * (WT/70)

  CL = TVCL * EXP(ETA(1))
  V1 = TVV1 * EXP(ETA(2))
  Q  = TVQ  * EXP(ETA(3))
  V2 = TVV2 * EXP(ETA(4))

  S1 = V1   ; scale central compartment so A(1)/V1 has concentration units

$ERROR
  IPRED = F
  Y     = IPRED * (1 + EPS(1)) + EPS(2)   ; combined proportional + additive

$THETA
  (0, 5)    ; [1] CL  (L/h)
  (0, 30)   ; [2] V1  (L)
  (0, 10)   ; [3] Q   (L/h)
  (0, 50)   ; [4] V2  (L)

$OMEGA
  0.1       ; [1] IIV CL
  0.1       ; [2] IIV V1
  0.1       ; [3] IIV Q
  0.1       ; [4] IIV V2

$SIGMA
  0.04      ; [1] proportional
  0.01      ; [2] additive

$ESTIMATION METHOD=COND INTERACTION MAXEVAL=9999 PRINT=5 NOABORT
$COVARIANCE UNCONDITIONAL MATRIX=R PRINT=E
$TABLE ID TIME DV PRED IPRED CWRES IWRES NPDE CL V1 Q V2 ETA1 ETA2 ETA3 ETA4
       NOPRINT NOAPPEND ONEHEADER FILE=run001.tab
```

Things people get wrong about this skeleton:

- `$INPUT` labels are positional: NM-TRAN reads the dataset columns in this order and assigns them these names. Reserved labels (`ID`, `TIME`, `AMT`, `RATE`, `EVID`, `MDV`, `CMT`, `DV`, `SS`, `II`, `ADDL`, `L1`, `L2`, `PCMT`, `CONT`, `DATE`, `DAT1`–`DAT3`, `CALL`) trigger special behavior in PREDPP. Non-reserved labels are just column names. To rename, use `X=Y` (e.g. `CONC=DV`). To drop, use `X=DROP`.
- `$DATA file.csv IGNORE=@` skips records starting with any letter — the most common idiom for skipping a header row. `IGNORE=C` skips records starting with `C`, which pairs with putting `C` in the first column on `$INPUT` for comment lines.
- The order matters: `$INPUT` must come before any record referring to data items by name. `$SUBROUTINES` must precede `$PK`/`$ERROR`. `$THETA`/`$OMEGA`/`$SIGMA` come after `$PK`/`$ERROR` so NM-TRAN can index the references.
- THETA references in `$PK`/`$ERROR` are 1-indexed and must match the number of entries in `$THETA`. Same for ETA ↔ `$OMEGA` and EPS ↔ `$SIGMA`.
- `S1 = V1` is the scaling for compartment 1. With TRANS4 (ADVAN3) the central compartment is #1; the predicted amount A(1) is divided by S1 to give concentration. Forgetting `Sn` is one of the most common causes of "values look 1000× off".
- Comments after `;` are ignored. Keep parameter labels in comments (`; [1] CL`) — they survive into the `.lst` and make debugging much faster.

## Dataset conventions — the part that breaks most often

NONMEM datasets are event-record-oriented, not subject-row-oriented. Each row is one event for one subject at one time. The interpretation of the row depends on `EVID`:

| EVID | Meaning                              | Required items                          |
|------|--------------------------------------|-----------------------------------------|
| 0    | Observation                          | `DV` populated; `AMT`/`RATE`/`SS`/`II`/`ADDL` must be 0 |
| 1    | Dose                                 | `AMT` (and possibly `RATE`); `DV` ignored |
| 2    | Other event (covariate change, etc.) | `DV` and dose items zero                |
| 3    | Reset (re-initialize the system)     | Time resets, compartments zeroed        |
| 4    | Reset + dose                         | Combine 3 and 1                         |

Rules that consistently trip people up:

- **A dose row and an observation row cannot share the same `TIME` and same record.** They must be separate rows. A common pattern is dose at t=0 (EVID=1, AMT>0, DV=0) followed by an observation at t=0 (EVID=0, AMT=0, DV=observed_value).
- **Bolus dose:** `AMT > 0`, `RATE = 0` (or omit RATE), `EVID = 1`.
- **Zero-order infusion (rate-specified):** `AMT > 0`, `RATE > 0`. NONMEM computes duration as `AMT*F1/RATE`.
- **Zero-order infusion (duration-specified):** `RATE = -2` and duration is modeled in `$PK` via `D1`, `D2`, etc.
- **Model-derived rate:** `RATE = -1` and `R1` etc. modeled in `$PK`.
- **Steady state:** `SS = 1` (steady-state dose at this row, prior history cleared), `SS = 2` (steady-state superimposed on prior history), with `II` = dosing interval. For an IV infusion to steady state, use `SS=1`, `II=tau`, and the appropriate `AMT`/`RATE`.
- **Additional doses:** `ADDL = n` (n additional doses), `II` = interval. NONMEM will generate the n implicit additional events at `t, t+II, t+2*II, …` without needing rows for them.
- **MDV:** Missing Dependent Variable. `MDV = 1` means "ignore DV on this row". NONMEM appends MDV automatically if absent, but if it's present, it's authoritative. `MDV = 1` is required on any non-observation row (doses, resets, covariate events) when DV happens to be populated. As of NONMEM 7, if MDV is in `$INPUT` but EVID is not, NM-TRAN sets EVID=2 (other event) on non-dose, MDV=1 rows — *not* EVID=0.
- **CMT:** which compartment the event acts on. For ADVAN3 (two-comp IV), the central compartment is #1, peripheral is #2, output is #3. For ADVAN4 (oral two-comp), depot is #1, central is #2. Get this wrong and dose goes into the wrong place silently.
- **ID:** must group all rows for one subject contiguously. Same ID value separated by a different ID is treated as two different subjects (this is occasionally useful but usually a bug).
- **Sort order within an ID:** monotonically increasing TIME, except where a reset (EVID=3 or 4) explicitly resets time.

For multi-occasion designs where each subject has multiple administration episodes that should share ETAs but reset compartments, use EVID=4 at the start of each occasion (reset + dose) and define a composite ID like `BIO_ID*100 + OCC` with a `bio_map` to share inter-individual variability across occasions.

## MU referencing — required for EM/Bayes, optional for FOCE

The new estimation methods (ITS, SAEM, IMP, BAYES, NUTS) need to know which THETAs define the population mean of each ETA. The convention is:

```
  PHI(j) = MU_j(THETA) + ETA(j)
  CL = EXP(MU_3 + ETA(3))     ; if log-normal IIV
```

To MU-reference a parameter, define `MU_j` as a function of THETAs only (no ETAs, no record-varying covariates that don't map cleanly to a single THETA), then write the individual parameter as `EXP(MU_j + ETA(j))` for log-normal IIV. Example:

```
  MU_1 = LOG(THETA(1)) + THETA(5)*LOG(WT/70)
  MU_2 = LOG(THETA(2)) + THETA(6)*LOG(WT/70)
  CL   = EXP(MU_1 + ETA(1))
  V1   = EXP(MU_2 + ETA(2))
```

**Linear MU referencing is preferred.** If you write `MU_1 = THETA(1) + THETA(5)*LOG(WT/70)` (THETAs entering linearly), the EM update step becomes a one-step linear regression and is much more robust. To keep this linear form while still entering `THETA(1)` on the natural (un-logged) scale, log-transform the initial value rather than wrapping `LOG()` inside the MU equation.

Rules and gotchas:

- Each MU_j corresponds to exactly one ETA(j). If you have IIV on CL via ETA(3), you write MU_3, not MU_1.
- A THETA that has no ETA associated with it is not MU-referenced — that's fine, EM still works, just less efficiently for that parameter.
- Covariates that change within a subject (record-varying WT for time-varying BSA, for example) generally cannot live inside a MU equation. Pull the covariate effect outside: `CL = WT**THETA(5) * EXP(MU_1 + ETA(1))` with MU_1 = LOG(THETA(1)).
- NM-TRAN catches some MU-referencing errors but not all. If an EM run is slow or unstable, the first suspect is broken MU referencing.
- FOCE/FOCEI/Laplace ignore MU references — they're harmless to include and useful for keeping a single control stream compatible with multiple methods.
- In PyMC/HMC the non-centered parameterization (`eta_raw ~ N(0, 1)`, `eta = omega * eta_raw`) is the structural analog: NUTS benefits from decoupled posterior geometry, NONMEM's EM benefits from linear update steps. They're aimed at the same problem (hierarchical posterior geometry) but exploit it differently.

## Estimation methods — choosing the right one

| Method                | When to use                                                                                              |
|-----------------------|----------------------------------------------------------------------------------------------------------|
| `METHOD=COND INTER`   | FOCE with interaction. Default for rich-data continuous PK/PD. Most reproducible. No MU needed.          |
| `METHOD=COND LAPLACE` | Laplace conditional. Use for non-normal data (categorical, ordered, BQL likelihood with `F_FLAG=1`).     |
| `METHOD=ITS`          | Iterative Two-Stage. Fast preliminary; good initial values for SAEM/IMP. Less accurate when data sparse. |
| `METHOD=SAEM`         | Stochastic Approximation EM. Categorical or sparse data, complex ODEs, full OMEGA blocks. Needs MU.      |
| `METHOD=IMP`          | Monte Carlo importance sampling. Complex PK/PD with many params and/or ODEs. Tracks the true OFV.        |
| `METHOD=BAYES`        | MCMC Bayesian. Posterior distribution rather than point estimates. Needs priors and MU references.       |
| `METHOD=NUTS`         | NUTS Hamiltonian MC (NM 7.4+). Highest-quality posterior sampling. Needs `MUFIRSTREC` and `OBJQUICK`.    |

Common idioms:

- **SAEM then IMP for final OFV:** SAEM converges fast but doesn't give the true OFV directly. Follow it with an IMP step that uses `EONLY=1` (expectation only, no maximization) to compute the marginal likelihood OFV at the SAEM-converged parameters.
- **MSFO/MSFI for restart:** `MSFO=run001.msf` writes a model specification file at the end of estimation; the next problem can `MSFI=run001.msf` to pick up exactly where it left off. Useful for SAEM → IMP chains.
- **Multiple $EST records:** Each subsequent `$EST` uses the previous one's final estimates as starting values. So `$EST METHOD=ITS NITER=100` followed by `$EST METHOD=SAEM NBURN=500 NITER=500` followed by `$EST METHOD=IMP EONLY=1 NITER=10 ISAMPLE=3000` is a typical EM workflow.
- **Convergence tests during exploration:** Disable them. EM convergence tests can keep running excessively or end prematurely; better to fix `NITER` during initial development.

Initial settings to start with for unfamiliar problems:

```
$EST METHOD=ITS  NITER=100
$EST METHOD=SAEM NBURN=500 NITER=500
$EST METHOD=IMP  NITER=100 ISAMPLE=300
```

If a 3+ compartment ODE model takes hours under FOCE, it's almost always worth porting it to MU-referenced IMP or SAEM — speedups of 5–10× are common.

## Output files

After a successful run, the following files appear (root = control-stream name without extension):

- `root.lst` (or `.res`) — the human-readable report. Final estimates, OFV, standard errors, covariance matrices, run statistics.
- `root.ext` — raw output table: every iteration's parameter values plus the final line. Easy to parse for trace plots.
- `root.phi` — individual parameter estimates: PHI(i) = MU(i) + ETA(i), and their variances. One row per subject (or per occasion if L2 is used).
- `root.cov` — full variance-covariance matrix of THETA/SIGMA/OMEGA estimates.
- `root.cor` — correlation matrix; diagonals are standard errors, off-diagonals are correlations.
- `root.coi` — inverse covariance (Fisher information) matrix.
- `root.tab` (and any other `$TABLE FILE=` outputs) — predictions, residuals, individual parameters at each event.
- `root.shk` — eta/eps shrinkage.
- `root.xml` — XML summary of the run, useful for programmatic post-processing.
- `root.msf` — model specification file (only if `MSFO=` was set).

Quick interpretation cues from `.lst`:

- "MINIMIZATION SUCCESSFUL" — FOCE found a local optimum. No guarantee it's global.
- "ROUNDING ERRORS" — gradient evaluation hit precision limits. Often genuine convergence but with caveats. Try `SIGL=` lower, or switch to EM.
- "DUE TO PROXIMITY OF NEXT ITERATION EST. TO A VALUE AT WHICH THE OBJ. FUNC. IS INFINITE" — usually a boundary issue. Check that initial estimates aren't at the lower bound of THETA.
- "$COV step aborted" — R or S matrix is singular or non-positive-definite. Often a sign of over-parameterization or correlation near 1 between two parameters. Inspect `root.cor`.
- Condition number (in `.lst` near the bottom of $COV): >1000 is concerning, >10000 suggests serious identifiability issues.

For details on each file's format and how to use them, see `references/output-files.md`.

## VPC and pcVPC

For a Visual Predictive Check, the standard workflow is:

1. Run the estimation to convergence.
2. Build a simulation control stream using `$SIMULATION SUBPROBLEMS=n ONLYSIM` with `NSUB=` typically 200–1000 replicates of the original dataset. Same `$PK`, `$ERROR`, `$THETA`, `$OMEGA`, `$SIGMA` fixed at the estimated values. Output `DV`, `IPRED`, `PRED`, `TIME`, `ID`, and any binning/stratification variables to `$TABLE`.
3. For each time bin, compute the 5th/50th/95th percentile of simulated DV. Plot these as ribbons/lines, with observed percentiles overlaid.
4. If dose adjustments or adaptive designs are present, use **prediction-corrected VPC (pcVPC)**: divide each observation by the typical population prediction at that bin's median time, and do the same for simulations. This removes the variability from binning across heterogeneous dose/covariate values and is essential when there's a posteriori dose adaptation (TDM) or wide variation in the dosing regimen.

Holford/Bergstrand conventions for the figure: bins narrow enough that within-bin variability is small but wide enough that each bin has ≥10 observations; show observed 5/50/95 as lines and simulated 5/50/95 as shaded confidence intervals (typically the 95% CI of each percentile across simulation replicates).

See `references/diagnostics-vpc.md` for the worked formulas and tips on BQL handling, dose-adaptive corrections, and stratification.

## Common errors and recovery

A short list; the full table is in `references/common-errors.md`.

- **"FILE RECORD MISSING"** — almost always means NONMEM was handed an NM-TRAN control stream (`$PROBLEM ...`) instead of the FCON file that NM-TRAN produces. Run NM-TRAN first (typically `nmfe74 run001.ctl run001.lst`).
- **"TOO MANY OBSERVATIONS PER INDIVIDUAL"** — bump `LIM6` in $SIZES or split the subject.
- **PRED EXIT CODE 1** — fatal error in $PK or $DES. Almost always division by zero, log of a non-positive number, or an `EXP` overflow. Add guards.
- **OFV is "INF" or NaN** — usually a SIGMA combined model with both proportional and additive going to zero. Or `IPRED ≤ 0` getting fed into a proportional residual. Add `W = SQRT(SIGMA(1,1)*IPRED**2 + SIGMA(2,2))` style guards.
- **Convergence "failed" but parameters look reasonable** — for EM/Bayes, this often just means the stochastic test couldn't certify convergence within the iterations given. Re-run with `MASSRESET=1` or more iterations. Inspect the `.ext` trace.

## Cross-references within this skill

- For exhaustive `$`-record syntax: `references/control-records.md`.
- For "which ADVAN/TRANS should I use for a 3-compartment IV with depot": `references/advan-trans.md`.
- For VPC computation, NPDE, shrinkage interpretation: `references/diagnostics-vpc.md`.
- For error messages and recovery: `references/common-errors.md`.

## External references the user already has in the project

- `intro7.pdf` — NONMEM 7.6.0 introduction (comprehensive feature list, MU referencing details, new method options).
- `NONMEM7_Technical_Guide.pdf` — algorithmic details for FOCE, Laplace, EM methods.
- Bauer 2019 CPT-PSP Tutorial Parts I and II — the most accessible reference for control-stream construction and method selection.
- User Guides I (Basic), II (Supplemental), III (Detailed Methods Guide), IV (NM-TRAN), V (Introductory Guide), VI (PREDPP), VII (Conditional Estimation), VIII (Help Guide / detailed record descriptions).
- `pcvpc.pdf` (Bergstrand 2011) and `A_stepbystep_guide_to_prediction_corrected_visual_predictive_checks_VPC_of_NONMEM_models___PMX_Solutions.pdf` — pcVPC theory and worked R example.

Prefer pointing to these for material this skill summarizes briefly. The user guides are the authoritative reference for any record-level question.

