From nlmixr2llm
Use this skill when the user wants to fit an nlmixr2-style model using a non-nlmixr2 backend — NONMEM, Monolix, or PKNCA — through `babelmixr2`. Triggers include `nlmixr(..., est = "nonmem")`, `est = "monolix"`, `est = "pknca"`, calls to `nonmemControl()` / `monolixControl()` / `pkncaControl()`, or "run my nlmixr2 model in NONMEM/Monolix".
How this skill is triggered — by the user, by Claude, or both
Slash command
/nlmixr2llm:babelmixr2The summary Claude sees in its skill listing — used to decide when to auto-load this skill
`babelmixr2` translates an nlmixr2 model function into the input format of another tool (NONMEM, Monolix, PKNCA), runs that tool, parses the results back, and hands you what looks like a normal `nlmixr2` fit object. The user writes one model in nlmixr2 syntax and can fit it across engines for cross-validation, regulatory submission, or NCA.
babelmixr2 translates an nlmixr2 model function into the input format of another tool (NONMEM, Monolix, PKNCA), runs that tool, parses the results back, and hands you what looks like a normal nlmixr2 fit object. The user writes one model in nlmixr2 syntax and can fit it across engines for cross-validation, regulatory submission, or NCA.
Activate whenever the user is:
nlmixr(model, data, est = "nonmem" | "monolix" | "pknca", ...).nonmemControl(), monolixControl(), or pkncaControl().options("babelmixr2.nonmem") / options("babelmixr2.monolix").est= | What babelmixr2 does |
|---|---|
"nonmem" | Generates a control stream + dataset, runs NONMEM via runCommand, reads results back and combines with the original model to return an nlmixr2 fit object |
"monolix" | Generates an .mlxtran project + dataset, runs Monolix (CLI or lixoftConnectors), reads results back and combines the original model to return an nlmixr2 fit object |
"pknca" | Runs non-compartmental analysis via PKNCA on the dataset and wraps the result in an nlmixr2-shaped object — useful as a starting point for popPK initial estimates |
library(babelmixr2)
options("babelmixr2.nonmem" = "nmfe743") # set once per R session
pk.turnover.emax3 <- function() {
ini({
tktr <- log(1); tka <- log(1)
tcl <- log(0.1); tv <- log(10)
eta.ktr ~ 1; eta.ka ~ 1; eta.cl ~ 2; eta.v ~ 1
prop.err <- 0.1
pkadd.err <- 0.1
temax <- logit(0.8); tec50 <- log(0.5)
tkout <- log(0.05); te0 <- log(100)
eta.emax ~ .5; eta.ec50 ~ .5; eta.kout ~ .5; eta.e0 ~ .5
pdadd.err <- 10
})
model({
ktr <- exp(tktr + eta.ktr)
ka <- exp(tka + eta.ka)
cl <- exp(tcl + eta.cl)
v <- exp(tv + eta.v)
emax <- expit(temax + eta.emax)
ec50 <- exp(tec50 + eta.ec50)
kout <- exp(tkout + eta.kout)
e0 <- exp(te0 + eta.e0)
DCP <- center / v
PD <- 1 - emax * DCP / (ec50 + DCP)
effect(0) <- e0
kin <- e0 * kout
d/dt(depot) <- -ktr * depot
d/dt(gut) <- ktr * depot - ka * gut
d/dt(center) <- ka * gut - cl / v * center
d/dt(effect) <- kin * PD - kout * effect
cp <- center / v
cp ~ prop(prop.err) + add(pkadd.err)
effect ~ add(pdadd.err) | pca
})
}
fit <- nlmixr(pk.turnover.emax3, nlmixr2data::warfarin, "nonmem",
nonmemControl(modelName = "pk.turnover.emax3"))
Same model function, swap the last call:
options("babelmixr2.monolix" = "monolix") # or rely on lixoftConnectors
fit <- nlmixr(pk.turnover.emax3, nlmixr2data::warfarin, "monolix",
monolixControl(modelName = "pk.turnover.emax3"))
ini({}) / model({})). The same function works across est= values — don't fork it per engine.modelName controls the output directory name. Set it explicitly so re-runs are reproducible and don't overwrite each other.options("babelmixr2.nonmem" = "nmfe743") (or full path), or pass runCommand= to nonmemControl().lixoftConnectors and it auto-detects, or set options("babelmixr2.monolix" = "monolix"), or pass runCommand= to monolixControl().runCommand can be a function. Useful for cluster submission — return after the run completes and the output files exist.fit$parFixed, augPred(fit), vpcPlot(fit), fit$omega, as.data.frame(fit). If something appears missing, it usually means the import hit an unsupported output — see Debugging below.est = "pknca" doesn't fit a model — it runs NCA and returns an object you can use to seed initial estimates for a subsequent popPK fit. Drive it with pkncaControl(concu=, doseu=, timeu=, volumeu=).The skill is "done" only when the fit has been executed and inspected, not just queued:
getOption("babelmixr2.nonmem") etc.).nlmixr(...) with the chosen est=. Capture stdout/stderr — engine errors surface here.print(fit), fit$parFixed, an augPred() plot or VPC. Verify the OFV / objective is finite and parameters are sane.| Symptom | Likely cause |
|---|---|
could not find NONMEM / could not find Monolix | runCommand not set or wrong; check getOption("babelmixr2.nonmem") |
| Run launches but exits with rounding errors | model didn't converge — same fix as in NONMEM directly; consider nonmemControl(readRounding = TRUE) to read partial results |
Fit object missing standard errors / $parFixed empty | back-translation (via nonmem2rx / monolix2rx) failed silently — load the engine output file directly and inspect |
| Parameter estimates differ from a hand-written ctl | check transforms — babelmixr2 generates MU-referenced code; manual ctls often don't |
| Monolix run "succeeds" but no fit | lixoftConnectors not installed and babelmixr2.monolix option unset |
| PKNCA result has no concentrations | unit args (concu, doseu, timeu, volumeu) missing or inconsistent with the dataset |
est= between runs without changing modelName — output directories will collide.nonmem2rx / monolix2rx errors during back-translation; they're the canary for unsupported features.vignettes/articles/running-nonmem.Rmd — full NONMEM workflowvignettes/articles/running-monlix.Rmd — full Monolix workflowvignettes/articles/running-pknca.Rmd — NCA → popPK initial estimatesvignettes/articles/new-estimation.Rmd — adding a new backendvignettes/articles/PopED.Rmd — optimal design integrationbabelmixr2 is the forward path (nlmixr2 → engine). nonmem2rx and monolix2rx are the backward path (engine output → rxode2/nlmixr2). babelmixr2 does not call the backward translation after the run completes because it already knows what the original nlmixr2 model was. If a babelmixr2 fit looks broken, the bug is almost always in import — you can debug this by trying to load the engine output directly with nonmem2rx() / monolix2rx() and seeing if a nlmixr2 fit can be generated from these outputs.
npx claudepluginhub john-harrold/nlmixr2llm --plugin nlmixr2llmProvides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Searches MemPalace before answering questions about past work, people, projects, or prior decisions. Returns verbatim stored content instead of guessing from model memory.