New in 1.0.8

Find out what’s new in mrgsolve version 1.0.8

new release

Kyle Baron


March 4, 2023

1 Introduction

mrgsolve version 1.0.8 was released to CRAN on March 4th, 2023. This blog post introduces some of the new features in 1.0.8 as well as 1.0.7, which was not released to CRAN.


2 Missing values and input data sets

Missing values (NA) are now allowed in the following columns of input data sets:

  • CMT
  • AMT
  • RATE
  • EVID
  • II
  • ADDL
  • SS

The lower case versions of these names may also include NA.

  • cmt
  • amt
  • rate
  • evid
  • ii
  • addl
  • ss

In previous versions of mrgsolve, it was an error to include NA in these data set columns. Starting with version 1.0.7, mrgsolve will convert NA to 0 for these columns only. mrgsolve will continue to warn the user when missing values are in parameter columns.

3 Convenient ETA capture

The $CAPTURE block gains a new option for capturing any or all ETAs into the simulated output. The user writes an expression which evaluates to the integer numbers of ETAs to capture into the @etas option. For example

$OMEGA 0.1 0.2 0.3


will capture ETAs 1, 2, and 3 into ETA1, ETA2, and ETA3 in the simulated output.

Note that the syntax resembles what you might write in NONMEM where last is the total number of ETAs in the problem.

Note also that ETA naming resembles what you would get from NONMEM. This is contrasted with the naming that you continue to get when you simply capture ETA(1)


In this case, the name would be ETA_1, with () getting removed and replaced with _. This sanitization of names happens any time a captured item has parens or brackets in the name.

4 New model macro: SIGMA()

The user can now access on-diagonal elements of $SIGMA through the SIGMA() macro. For example

$SIGMA 0.1 12

double STD=sqrt(SIGMA(1)+pow(F,2)*SIGMA(2));

This macro provides read-only access to the $SIGMA elements.

5 Matching mrgsolve and NONMEM run numbers

When a mrgsolve model is translated from a NONMEM run, it is common to give them matching file names. For example, if 101.ctl is the NONMEM control stream name, we might create an mrgsolve version of that run as 101.cpp or 101.mod.

In this case, we will likely use $NMEXT or $NMXML blocks to import the estimates from the completed NONMEM run with code like this

run = 101
project = "model/nonmem"

if the run completed in the model/nonmem directory.

Starting with mrgsolve version 1.0.7, users can assume this connection in run numbers by setting the run to @cppstem

run = "@cppstem"
project = "model/nonmem"

This tells $NMEXT (and $NMXML) to look for 101.ext (or 101.xml) in the model/nonmem/101 directory. Using this syntax will relieve the user from having to update the run number in these blocks when forking one model file to match a new NONMEM run.

6 Scrape ETAs from the input data set

mrgsim() gains a new argument called etasrc which allows you to look to the data set for ETAs rather than simulating them from $OMEGA. This feature has several applications, including validation of your model translation from NONMEM and simulating from empirical Bayes estimates. These topics will be covered more in depth in separate blog posts.

For now, let’s look at an example. This model has three ETAs

mod <- mcode("etas", 
  $OMEGA 1 2 3
  $CAPTURE @etas 1:last
  end = 3

By default, the ETAs are random draws from $OMEGA

mrgsim(mod, end = -1, nid = 4) 
Model:  etas 
Dim:    4 x 5 
Time:   0 to 0 
ID:     4 
    ID time    ETA1    ETA2    ETA3
1:   1    0  0.6358  2.0476  2.5184
2:   2    0 -1.0663 -0.9353  1.3713
3:   3    0 -0.9820 -1.6954 -0.9905
4:   4    0 -0.5072  0.6018 -2.0783

When you have ETAs coded into your data set

data <- expand.ev(cmt = 0, ETA1 = 0.1, ETA2 = 0.2, ETA3 = 0.3)
  ID time amt cmt evid ETA1 ETA2 ETA3
1  1    0   0   0    1  0.1  0.2  0.3

you can ask mrgsolve to use the data set ETAs rather than simulating new ones

mrgsim(mod, data, etasrc = "data")
Model:  etas 
Dim:    5 x 5 
Time:   0 to 3 
ID:     1 
    ID time ETA1 ETA2 ETA3
1:   1    0  0.1  0.2  0.3
2:   1    0  0.1  0.2  0.3
3:   1    1  0.1  0.2  0.3
4:   1    2  0.1  0.2  0.3
5:   1    3  0.1  0.2  0.3

If the data set is missing one of the ETAs, it will be filled with 0

miss2 <- select(data, -ETA2)

mrgsim(mod, miss2, etasrc = "data")
Model:  etas 
Dim:    5 x 5 
Time:   0 to 3 
ID:     1 
    ID time ETA1 ETA2 ETA3
1:   1    0  0.1    0  0.3
2:   1    0  0.1    0  0.3
3:   1    1  0.1    0  0.3
4:   1    2  0.1    0  0.3
5:   1    3  0.1    0  0.3

You can ask for an error to be generated if not all ETAs are found on the data set by using etasrc = "data.all"

try(mrgsim(mod, miss2, etasrc = "data.all"))
Error : all 3 ETAs must be provided when `etasrc` is "data.all".

Also, an error will be generated if you ask for ETAs from the data set, but there are none

missall <- select(data, -contains("ETA"))

try(mrgsim(mod, missall, etasrc = "data"))
Error : at least one ETA must be provided when `etasrc` is "data".

You can get more information about the etasrc argument in the ‘Details’ section of the mrgsim() help page.