babelmixr2
0.1.12Use 'nlmixr2' to Interact with Open Source and Commercial Software
Overview
Run other estimation and simulation software via the 'nlmixr2' (Fidler et al (2019) doi:10.1002/psp4.12445) interface including 'PKNCA', 'NONMEM' and 'Monolix'. It also converts 'nlmixr2'/'rxode2' models to 'PopED' optimal design databases (Fidler et al (2024) doi:10.70534/XUMG6226). While not required, you can get/install the 'lixoftConnectors' package in the 'Monolix' installation, as described at the following url https://monolixsuite.slp-software.com/r-functions/2024R1/installation-and-initialization. When 'lixoftConnectors' is available, 'Monolix' can be run directly instead of setting up command line usage.
est="pknca"unit conversion scales the whole DV expression, so an additive term (like a baseline) is converted too (#236)- NONMEM: names that differ only by case get one NONMEM name each for the whole control stream, so the data columns,
$INPUT,$MODEL,$PK,$DESand$ERRORagree. Covariates ignore case (like rxode2), sowtandWTare one data column; a variable or compartment that clashes is renamedRXC001, ... (#237) - Monolix: a modeled
rate()withf()infuses overf*amt/rate, the rxode2 (and NONMEM) duration, instead ofamt/rate(#239) as.nlmixr2()of a nonmem2rx import solves withrxControl(nonmem = TRUE, addlKeepsCov = FALSE), the way nonmem2rx validates the import, when rxode2 supports it (nlmixr2/rxode2#1429) and nlmixr2est keeps it through its fits (nlmixr2/nlmixr2est#1167). Statements that do not depend on a state (NONMEM's$PK) then readTIMEas the time of the record ending each interval, like NONMEM, instead of the continuous time; forTIMEin$PKthe IPRED difference to NONMEM goes from 21.8% to 0.004% (#252). Models withdelay()keep the continuous time.
Show all changes in 0.1.12Hide the rest of the changes in 0.1.12
- An empty Monolix administration table builds its
typefactor withfactor(levels=)instead ofstructure(.Label=), which R-devel'sR CMD checkflags as deprecated. - Monolix imports (
as.nlmixr2()of a monolix2rx model) no longer fail when the project's steady-state dose count (nbdoses) is below 6:minSS/maxSScome from monolix2rx's.getSsLimits(), raised to rxode2's floor of 5 and 7. simplifyUnit()andmodelUnitConversion()work without the suggested packages testthat and units installed:simplifyUnit()checked its arguments with checkmate'sexpect_*()(testthat expectations) instead ofassert_*(), and both now ask for units withrxode2::rxReq(). Their examples run only when units is installed, and the PKNCA and saemix tests skip when those packages are not installed (CRAN's noSuggests check).- Monolix (fourth stress kit run):
EQUATION:only has assignments and conditions, so PK macros there were rejected. The model lines before the ODEs (with the compartment properties the macros use) are now written in thePK:block before the macros, and the ODEs stay inEQUATION:. Compartment properties set after the ODEs are moved before them, and a property set in anifis set in every branch (rxode2's default in the others) instead of from a default assigned before theif, which Monolix cannot reassign. A missingLIMITis written as missing instead of-Inf. - Monolix projects Monolix could not load (third stress kit run, with Monolix's reasons):
- "Conflicting variable definition": Monolix assigns a variable once, so a reassigned variable (like
if (SEX == 1) cl <- cl * 1.2, or the prunedelse if) gets a new name (cl_rx1); anif/elsethat changes a defined variable is pruned first. - "Undefined variable": compartment properties set in the model (
f(),alag(),dur(),rate()) are defined inEQUATION:, so the PK macros using them are now written inEQUATION:after them (not in aPK:block before). A modeled rate usesTk0=rx_tk0_<state>withrx_tk0_<state> = amtDose/rate(macro arguments cannot be calculations). monolixControl(stiff=TRUE)wroteodeType = stiffwhere Monolix expects an input definition; it is now inEQUATION:.- A
LIMITon uncensored observations (M2) is refused: Monolix only usesLIMITwith censored values. - Monolix fits use the number of observations Monolix used for the objective function, like NONMEM fits; it was off for data with
evid=2records or time not starting at zero. - Monolix: a mu-referenced parameter that stays inside
exp()in the model (likecl <- exp(tcl + eta.cl) * (CRCL/100)^cl.crcl, orf(depot) <- exp(lfdepot)) was given a log-normal distribution while the model still tookexp()of it, soexp()was applied twice. It is now a normal parameter on nlmixr2's scale (its initial value, estimate and covariance too). - When lixoftConnectors cannot load or run a Monolix project, the error now includes Monolix's reason (its
[ERROR]lines) instead of "see Monolix's [ERROR] above". - Fixes found by running the NONMEM/Monolix stress kit with NONMEM 7.4:
nonmemControl(est="imp")andest="its"fits were always reported as unsuccessful; NONMEM ends them with "OPTIMIZATION WAS NOT TESTED FOR CONVERGENCE", which is now read as finished.nonmemControl(est="posthoc")fits could not be read (no#TERM:block and no parameter history).- Box-Cox, Yeo-Johnson and logit + Yeo-Johnson residual errors were rejected by NM-TRAN (IPRED redefined in nested/
ELSE IFstructures); the transformations are now written without nested IFs. They are still transform-both-sides (DV inCCONTR, IPRED in$ERROR). Predictions at or belowsqrt(DBL_EPSILON)are floored like rxode2 instead of being set to-1000000000(which gavelnorm()fits a huge objective function), and Box-Cox no longer divides by zero when lambda is 0. - The
IPRED/PREDcomparison with NONMEM now undoes the residual transformation first (NONMEM's predictions are on the transformed scale). - Censored (
CENS,CENS+LIMIT,LIMITonly) models were rejected by NM-TRAN ("random variable is defined in a nested IF structure"). - A
$PKparameter changed later in the model (likeif (SEX == 1) cl <- cl * 1.2) was changed in$DES, which NONMEM does not allow, and used undefined in$ERROR; it is now defined asRXPK_<name>in$PK. - Models without random effects are refused (NONMEM treats them as single-subject data, where
METHOD=CONDis invalid). - Monolix fixes found by running the NONMEM/Monolix stress kit:
- Infusions given by rate (
RATE) or duration (TINF) were written to the data but not declared in[CONTENT], so Monolix gave them as bolus doses. - Endpoints with dotted names (like
concentration.in.plasma) kept the dots in the Monolix project (OUTPUT, observation names, predictions), which Monolix cannot load. - Reading a fit with a fixed parameter (like
tfdepot <- fix(0.8)) failed with "subscript out of bounds"; Monolix's covariance has only the estimated parameters. - A
monolixControl(runCommand=)command that finished without writing Monolix's output now stops with an error instead of waiting for it forever. nonmemControl(cov="")now skips the covariance step as documented; before it gave an error becausematch.arg()cannot match"".- The NONMEM/Monolix stress test (
inst/stress) is now a kit to run on a machine with NONMEM and/or Monolix:install-kit.Rinstalls the versions to test,run-stress.R --checkfinds NONMEM/Monolix, andrun-stress.R --kitruns every case end to end, checks that rxode2 reproduces the NONMEM/Monolix predictions and that a second fit reads the saved output, and zips the results to send back. New cases cover missing observations,evid=2, character IDs, time not starting at zero, extra data columns, a single subject, oral plus iv doses, ODE infusions (rate, steady state, modeled duration), two endpoints, bounded thetas, several covariates, models without random effects and the NONMEM/Monolix estimation options. - NONMEM control streams now use
$ABBR PROTECTso NM-TRAN replacesLOG,EXP,SQRT, division and powers with NONMEM's protected functions (NONMEM 7.4 or later). Turn it off withnonmemControl(protect=FALSE)oroptions(babelmixr2.nmProtect=FALSE). Since NM-TRAN writesB**EasPEXP(E*PLOG(B)), integer powers are written as products (or powers ofx*x, which is never negative) and powers of a positive number withDEXP(). Functions of numbers (likeexp(0),log(2*pi)orexpit(0)) and divisions of numbers are written as numbers, and model variables named like a protected function (likeplog) are renamed. babelmixr2's own zero protection (protectZeros) is now only used withprotect=FALSE, like for NONMEM before 7.4 (#62). - NONMEM control streams now explain the zero-protection code babelmixr2 adds: each
RXDZ###IFblock is preceded by a comment saying what it keeps the variable away from and why, as is theIF (W1 .EQ. 0.0)residual variance protection (#91). The protection forlfactorial()/lgamma1p()now keeps its argument above-1(it previously clamped it just below-1, makingx+1negative),log(x)and1/xno longer share one protected variable, so1/xkeeps the sign of a negativex, and a variable reassigned in the model is protected again instead of reusing the protection of its old value. Zero protection needed byf(),alag(),rate()ordur()(written in$PK) is no longer shared with other lines, which could use it before (or without) it being calculated. est="pknca"now works with covariates in the data and with a mix of intravascular and extravascular doses (#102). Doses into a compartment that the observations are calculated from are intravascular. With both routes,kais estimated from the extravascular doses andvcandclfrom the intravascular doses. Intravascular bolus doses have the concentration at the time of dosing back-extrapolated (replacing a predose concentration at the first dose), and other doses have it imputed (as the predose concentration, or zero for the first dose). When no doses are only extravascular,kais not updated. Multiple-dose data no longer need a concentration at each dose time; each dose until the next (with at least 2 concentrations) is used, withvcfrom the first dose of each route andclfrom dosing intervals mostly covered by concentrations. Doses at the same time are combined.- When a NONMEM run fails,
est="nonmem"now says why and where to look instead of failing with an unclear error: a run command that was not found or wrote no output, a NONMEM license problem, an NM-TRAN error in the control stream or the data, NONMEM not starting (for example a compiler problem), NONMEM crashing or stopping during estimation, and output babelmixr2 cannot read (#46). est="pknca"now updates the initial estimates of models that are not mu-referenced, likeka <- tka * exp(eta.ka), instead of failing with "Must have names" (#101). When there is novc, a central volume namedv,V,Vc,VC,v1orV1(only one of them) now gets the NCA central volume estimate. Parameters defined asexpit()of a theta are now transformed back correctly. A message lists the parameters that could not be updated.- NONMEM models can now use nested
if/else if/elsestatements (andifelse()): their branches are pruned with rxode2's branch pruning before the model is translated to NONMEM (#11). With the defaultnonmemControl(prune="auto")a model whoseifblocks are simple is still written with NONMEMIFblocks and only a model that needs it is pruned;prune=TRUEalways prunes andprune=FALSEnever prunes (the error for unsupportedif/elsestatements suggestsprune=TRUE). monolixControl(prune=)has the same option for Monolix. Monolix writesif/elseif/else(and nestedif) statements directly, soprune="auto"(the default) only prunes a model that usesifelse(), which Monolix cannot write;prune=TRUEalways prunes andprune=FALSEnever prunes. A logical expression used as a number in a Monolix model is written as a 0/1 indicator variable (#11).- A logical expression used as a number in a NONMEM model (like
cl <- tcl * (WT > 70)) is now written as a 0/1 indicator variable, since NONMEM cannot use a logical expression as a number. A numericif ()condition is written as not equal to zero. est="nonmem"andest="monolix"fits withtable=tableControl(cwres=TRUE)no longer fail with "objective function 'FOCEi' already present". The fit keeps both the NONMEM (or Monolix) objective, which stays in use, and nlmixr2's FOCEi objective (#94).as.nlmixr2()of anonmem2rxormonolix2rxmodel now also keeps the imported objective in use withcwres=TRUE, and no longer fails after an earlier import withcwres=TRUE(it started from that fit's etas).est="monolix"now translates compartment properties (f(),alag(),rate()anddur()) that are expressions, likef(depot) <- exp(lfdepot), instead of erroring with "the complex F is not supported by babelmixr2" (#115). The expression is calculated in a new variable (likerx_f_depot) that thePK:macro uses. A property set only inside anifnow keeps rxode2's default otherwise (1 forf(), 0 foralag()) instead of being applied unconditionally.- The ACoP 2024
babelmixr2/PopEDabstract (doi:10.70534/XUMG6226) is now incitation("babelmixr2"), the package description and thePopEDarticle (#155). as.nlmixr2()of anonmem2rxmodel now stops with an informative error when the model still contains untranslated NONMEM residual variables (eps#orerr#) instead of failing inside the estimation routine (#95).popedControl(sigdig=)now sets the ODE solver tolerances itself (atol = rtol = 0.5*10^(-sigdig-2), the same values as before) instead of usingrxode2::rxControl(sigdig=). rxode2 5.1.5 loosened the tolerances thatrxControl(sigdig=)gives, which made the finite-difference FIM, and so the design OFV and RSEs, less accurate (#223).est="nonmem"now fits censored data the way nlmixr2 does (#92). M3 (CENS), M4 (CENSwith a finiteLIMIT) and M2 (CENS=0with a finiteLIMIT, including data with aLIMITbut noCENScolumn) useF_FLAGlikelihoods in$ERRORwithLAPLACIANestimation. A missingLIMITis now written as NONMEM's infinity instead of0,CENS/LIMITcolumns that do not censor anything are dropped, the objective function is adjusted so the log-likelihood includes the censored observations correctly, and censoring with a transformed endpoint (likelnorm()) is refused instead of giving the wrong likelihood. The censored observations are left out of the NONMEMPREDcomparison since NONMEM'sPREDis their likelihood.est="nonmem"andest="monolix"now fitlinCmt()models. A purelinCmt()model uses NONMEM's closed-form solutions (ADVAN1-ADVAN4,ADVAN11orADVAN12withTRANS1micro-constants) or Monolix'spkmodel(); a model the closed form cannot represent (other ODEs, parameters that change with time, and for Monolix modeled rates or durations, doses into more than one compartment or amounts used in the model) is translated to ODEs withrxode2::linToOde().nonmemControl(linCmt="ode")andmonolixControl(linCmt="ode")always use ODEs. The closed-form solutions need an rxode2 withlinCmtMicro(); with an older rxode2,linCmt()models use ODEs.est="poped"now designslinCmt()models (translated to ODEs).est="nlmer",est="fmeMcmc"andest="pseudoOptim"are now tested withlinCmt()models.- New NONMEM/Monolix stress test (
inst/stress/), shared by the package tests and a command line runner (run-stress.R). The runner can also fit every case with NONMEM and/or Monolix end to end on a machine that has them, and optionally translate the nlmixr2lib models; seeinst/stress/README.md. - The NONMEM data dropped the
RATE,SSandIIitems: which items were written was decided from settings made only after the data were converted, so infusions, steady state doses and modeled rates or durations were written as plain bolus doses. The items are now kept when the data use them. - A steady state dose with a lag time (which rxode2 splits in two) is now written as one
SSdose for NONMEM and Monolix, not as two bolus doses. - NONMEM now writes a modeled duration as
Dn(it wasDURn, which NONMEM does not know) and a modeled rate asRn(it was dropped). - NONMEM now uses the NONMEM name of a mu-reference
The NEWS section is longer than shown here.
From NEWS.md in the release
Install
Health
NOTER code for possible problemsr-devel-linux-x86_64-debian-clang, r-devel-linux-x86_64-debian-gcc, r-devel-windows-x86_64
Found calls to structure() using deprecated special names: babelmixr2/R/monolixNlmixr2est.R (.Label: 1) '.Label' should be changed to 'levels'.
- NOTE10 OK, 3 NOTENow
- NOTE8 OK, 5 NOTE2026-10-14
- ERROR8 OK, 4 NOTE, 1 ERROR2026-09-15
- NOTE8 OK, 5 NOTE2026-08-12
- ERROR6 OK, 5 NOTE, 2 ERROR2026-08-04
- NOTE11 OK, 2 NOTE2026-07-16
Show 6 earlier changesHide 6 earlier changes
- OK13 OK2026-06-09
- ERROR12 OK, 1 ERROR2026-06-08
- OK12 OK2026-04-25
- NOTE11 OK, 3 NOTE2026-04-22
- ERROR10 OK, 3 NOTE, 1 ERROR2026-04-18
- NOTE11 OK, 3 NOTE2026-03-10
Documentation
The repository also keeps web-only articles.
- Help pages
- 49 (14 internal)
- Examples that run
- 50%7 run in a plain check (3 of them under a condition) · 7 only when donttest examples are enabled (R CMD check --as-cran)
- Exported functions with examples
- 42%
- Documented parameters
- 91%
- Return-value docs
- 97%
- Help pages citing references
- 4%
Downloads
Repository
- PRs merged (all time)
- 98%
- Median days to close, 50 most recently updated closed issues
- 42
- Median days to close, 50 most recently updated closed PRs
- 0
Stars over time
Forks over time
Releases over time
Issues over time
PRs over time
Commits over time
Commit identities over time
10 development-tooling and community-health practices detected across 5 families in the upstream repository
Checks run against github.com/nlmixr2/babelmixr2 on 2026-10-11.
The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel
GitHub Pages site last deployed 2026-10-09 · The repository has a site deploy workflow
pkgdown site last built 2026-10-09, before release 0.1.12 (2026-10-16)
Show all practicesHide 1 practice
This repository shows signs of AI coding tools.
- Claude Codefirst seen 2026-04-02Pull request it wrote: opened by a project memberCommits: at least 38 crediting it in the message
- Claude CodePull requests: 1 from outside contributors, first on 2026-06-18
- Claude Opus 4.814 commits · Jun to Jul 2026
- Claude Fable 58 commits · Jul 2026
- Claude Sonnet 4.64 commits · Apr to Jun 2026
- Claude Opus 4.72 commits · Jun 2026
- Claude Opus 51 commit · Jul 2026
Dependencies
Installing babelmixr2 adds 140 packages (90 with compiled code, 114 MB of source tarballs). Heaviest: BH 14 MB, stringi 11 MB, ggplot2 6.0 MB.
CRAN will archive these unless their check problems are fixed by the date shown. This package needs each one to install.
- nonmem2rxfix by Oct 18
- nlmixr2plotfix by Oct 22
- nlmixr2estfix by Oct 23
Code & Tests
People & History
Pick two releases to compare their code metrics.
- 0.1.12Latest2026-10-16 · current release · diff ↗ ··
added 6 exports
.nlmerCurrentFormula, .nlmerNlmerFun, iterPrintControl, nlmerControl, nlmixr2NlmerControl, saemixControllisted once in CRAN's queue
Seen in one reading of CRAN's incoming queue, at 2026-10-16 17:07 UTC, so it stayed less than the time between readings. - RR 4.6.0 released · 2026-04-24
- 0.1.112025-11-28 · diff ↗
- 0.1.102025-10-14 · diff ↗
- 0.1.9
- 0.1.82025-07-15 · diff ↗ ·
added 97 exports
%>%, ini<-, model<-, .nlmixrNlmeFun, ACF, RxODE, VarCorr, add.dosing, add.sampling, addCwres, addNpde, addTable, augPred, bobyqaControl, bootplot, bootstrapFit, et, etExpand, eventTable, expit, fixed.effects, fixef, foceiControl, geom_amt, geom_cens, getData, getVarCov, groupedData, ini, lbfgsb3cControl and 67 more - 0.1.72025-05-07 · diff ↗
- RR 4.5.0 released · 2025-04-11
- 0.1.62025-01-20 · diff ↗
- 0.1.5
- 0.1.42024-09-23 · diff ↗ ·
added 20 exports
.popedF, .popedFree, .popedRxRunSetup, .popedSetup, .popedSolveIdME, .popedSolveIdME2, .popedW, babel.poped.database, mlxtran, monolix2rx, nmcov, nmext, nminfo, nmtab, nmxml, popedControl, popedGetMultipleEndpointModelingTimes, popedMultipleEndpointIndexDataFrame, popedMultipleEndpointParam, popedMultipleEndpointResetTimeIndex - RR 4.4.0 released · 2024-04-24
- 0.1.22023-12-12 · diff ↗
- 0.1.1
- RR 4.3.0 released · 2023-04-21
- 0.1.02022-10-28
Show 1 earlier eventHide 1 earlier event
- RR 4.2.0 released · 2022-04-22
Package metadata
- First published
- 2022-10-28
- Total releases
- 12 / 4 yrs
- License
- GPL (>= 3) OSI
- Minimum R
- ≥ 3.5
- Download size
- 4.2 MB
Cite
Cite this package
Run in R for the authors' preferred citation:
citation("babelmixr2")The package provides a citation file that builds its entry when R runs it. Run citation() to see it.
Cite the R Observatory
For a number measured here: a download total, a coverage figure, an archival date.
From data release v2026-10-17, which the citation names so these numbers can be found later. More on citing and the projects behind them.