Metamodels in RsNLME
metamodels_overview.Rmd
Introduction
A metamodel (file with a .mmdl extension) simplifies the integration of RsNLME with Pirana. It acts like a container for all the information needed to run a Pharmacometric Modeling Language (PML) model. PML is the language that powers both Phoenix NLME and RsNLME. Think of a metamodel as similar to a NONMEM control file.
This guide explains metamodels and demonstrates how they can be used for conveniently storing, fitting, and exploring PML models. To understand this, we need to first look at how PML models are run in Phoenix NLME and RsNLME.
Assumptions:
- Both your input data and PML model files are in your current working directory.
- The directory containing the NLME Engine is specified in the
INSTALLDIR
environment variable. You can verify this with the following R commands:
# Load the RsNLME package
library(Certara.RsNLME)
# check if the env.variable is set correctly
Sys.getenv("INSTALLDIR")
These assumptions will hold throughout this document.
PML Models in Phoenix NLME
If you’ve used Phoenix NLME before, you’ll recognize that PML models in Phoenix are saved as .mdl files. These files contain the model’s statements, equations, and assignments. But they don’t specify things like the dataset to use, how columns should be mapped to model variables, or what tables should be generated as output (see the example below, which follows the syntax described in the linked documentation).
test(){
cfMicro(A1, Cl / V)
dosepoint(A1)
C = A1 / V
error(CEps = 0.1)
observe(CObs = C * (1 + CEps))
stparm(V = tvV * exp(nV))
stparm(Cl = tvCl * exp(nCl))
fixef(tvV = c(, 5, ))
fixef(tvCl = c(, 1, ))
ranef(diag(nV, nCl) = c(1, 1))
}
Phoenix stores all this information (model, data, mappings) within the project itself. The NLME executables only access this information during the model run. However, if you want to run PML models from the command line, you need to provide separate files for data, column definitions (linking data columns to model variables), and any additional input options (like ADDL and SS) along with the engine arguments:
%INSTALLDIR%\runNLME.bat 5 100 OneCpt_IVInfusion.mdl columnMapping.txt OneCpt_IVInfusionData.csv
PML Models in RsNLME
Certara.RsNLME also allows you to run PML models from the command line. You’ll need to provide the input data and PML model files to create a model object. If column mappings aren’t automatically detected, you’ll need to specify them. You can also provide additional input options (like ADDL, SS, Reset, MDV, and infusion). Here’s an example:
PMLModelCodeOutput <-"
test(){
cfMicro(A1, Cl / V)
dosepoint(A1)
C = A1 / V
error(CEps = 0.1)
observe(CObs = C * (1 + CEps))
stparm(V = tvV * exp(nV))
stparm(Cl = tvCl * exp(nCl))
fixef(tvV = c(, 5, ))
fixef(tvCl = c(, 1, ))
ranef(diag(nV, nCl) = c(1, 1))
} "
PMLModelCodeFile <- file.path(tempdir(TRUE), "OneCpt_IVInfusion.mdl")
writeLines(PMLModelCodeOutput, PMLModelCodeFile)
# for the input data description please refer to ?OneCpt_IVInfusionData
# Create the model object
model <- textualmodel(modelName = "OneCpt_IVInfusion",
mdl = PMLModelCodeFile,
data = OneCpt_IVInfusionData)
# Manually map the un-mapped model variables
model <- colMapping(model, mappings = c(id = "Subject", A1 = "Dose"))
# Add infusion information for dosing compartment A1
model <- addInfusion(model, "A1", isDuration = TRUE, colName = "Duration")
As you can see, the model object (an instance of the NlmePmlModel class) holds information about the model code, column mappings, and data — all in a binary format. Metamodels simplify this by combining these elements into a single, human-readable text file.
Metamodel Overview
Metamodels are structured with different blocks, each starting with a
double number sign (##
) followed by the block name.
Comments within metamodels use the same syntax as PML models:
#
or //
for single-line comments and
/* ... */
for multi-line comments.
Metamodel Blocks:
-
Author:
- Specifies the metamodel’s author (e.g.,
##Author: User
). - This block is optional and not used during model estimation.
- Specifies the metamodel’s author (e.g.,
-
Description:
- Used by Pirana to display a description of the metamodel’s purpose
(e.g.,
##Description: PK model for Drug X
). - This block is optional and not used during model estimation.
- Used by Pirana to display a description of the metamodel’s purpose
(e.g.,
-
Based on:
- Indicates the name of a reference metamodel, used by Pirana for
building reference trees (e.g.,
##Based on: BasePKModel.mmdl
). - This block is optional and not used during model estimation.
- Indicates the name of a reference metamodel, used by Pirana for
building reference trees (e.g.,
-
DATA:
- Required: Specifies the path to the input data file. Both absolute and relative paths are allowed.
- The
data.table::fread()
function (with default settings) is used to load the data (e.g.,##DATA ./data.csv
).
-
MAP:
- Defines mappings between model variables and data columns using the
=
sign (e.g.,variableName=columnName
). - If a mapping isn’t provided for a model variable, it’s assumed that
the variable name and column name are the same (e.g.,
CObs
is equivalent toCObs=CObs
). -
Special Variables: This block can also map special
variables not explicitly present in the model:
-
id
: Required for population models. Maps up to five data columns (separated by commas) to identify individual subject profiles. If not mapped, the model is treated as individual. -
time
: Required for time-based models. Maps the time variable. -
dosingCompartmentName_Rate
: Indicates that the specified dosing compartment involves infusion, with rate information provided in the mapped column. -
dosingCompartmentName_Duration
: Indicates that the specified dosing compartment involves infusion, with duration information provided in the mapped column. -
SS
: Indicates that the mapped column contains a steady-state flag. Translated to thesscol
statement in the column definition file. -
SSOffSet
: Indicates that the mapped column contains the SS offset. Only applicable ifSS
is also mapped. Translated to thessoffcol
statement. -
ADDL
: Indicates that the mapped column contains an additional identical dose flag. Translated to theaddlcol
statement. -
II
: Represents the inter-dose interval. Must be mapped if eitherSS
orADDL
is used. Translated to theiicol
statement. -
MDV
: Indicates that the mapped column contains missing data values (MDV). Rows with non-zero numeric values in this column will be ignored. -
Reset
: Indicates that the mapped column contains a reset flag. If the value in the reset column is not zero, time is allowed to be reset on that row.
-
-
Categorical Covariates: For categorical covariates
(defined using
fcovariate
orcovariate
with an empty parenthesis), you can define label names for each category value if the mapped data column is of character type. Label names are specified in round brackets after the column name (e.g.,Sex = Gender(Male = 0, Female = 1)
).
- Defines mappings between model variables and data columns using the
-
DOSING CYCLE:
- Provides an alternative way to define ADDL or SS dosing cycles for
specific dosing compartments. The syntax is:
- For SS:
SS = [COL] Dosepoint = [CMT] Amount = [NUM/COL] Delta = [NUM/COL] Duration = [NUM/COL] Rate = [NUM/COL]
- For ADDL:
ADDL = [COL] Delta = [NUM/COL] Dosepoint = [CMT] Amount = [NUM/COL] Duration = [NUM/COL] Rate = [NUM/COL]
- For SS:
- Where:
-
[COL]
is the column name containing the ADDL/SS flag. -
[CMT]
is the dosing compartment name from the model. -
[NUM/COL]
is either a column name or a numeric value. -
Delta
represents the inter-dose interval.
-
- Provides an alternative way to define ADDL or SS dosing cycles for
specific dosing compartments. The syntax is:
-
COLDEF:
- Defines column definitions using the syntax described here.
- Useful when column definitions can’t be defined through
##MAP
or##DOSING CYCLE
. - You can use both
##MAP
and##COLDEF
; definitions from both blocks will be combined. - Example (defining all column definitions):
##COLDEF id("id") time("time") dose(A1<-"dose") covr(sex<-"sex"("male" = 0, "female" = 1)) covr(wt<-"wt") obs(CObs<-"conc")
-
MODEL:
- Required: Contains the PML model code. Refer to the “Modeling Syntax” documentation for details.
-
ESTARGS:
- Specifies engine arguments using the syntax of the
engineParams()
function in theCertara.RsNLME
package. Arguments are separated by commas or spaces. - If not provided, default values are used.
- Example:
##ESTARGS method = "QRPEM", iSample = 1200, maxStepsODE = 50000000, mapAssist = 1, ODE = "AutoDetect", numIterations = 0
- You can define multiple
ESTARGS
blocks; they will be executed sequentially, with each run using the final estimates from the previous run.
- Specifies engine arguments using the syntax of the
-
SIMARGS:
- Specifies arguments for model simulation:
-
numReplicates
: Number of simulation replicates (default: 100). -
seed
: Random number generator seed (default: 1234). -
sort
,ODE
,rtolODE
,atolODE
,maxStepsODE
: See theengineParams()
documentation.
-
- Multiple
ESTARGS
andSIMARGS
blocks are supported and applied sequentially (allESTARGS
runs first, followed by allSIMARGS
runs).
- Specifies arguments for model simulation:
-
TABLES:
- Defines additional output tables (note: a
posthoc.csv
table with structural parameters and covariates at each data row is created by default). - Use the table statement syntax documented here.
- Example:
##TABLES table(file="table01.csv", time(0,10,seq(2,8,0.1)), dose(A1), covr(BW), obs(Conc), BW, C, cObs, V, Ke)
- Tables can also be defined in the
##COLDEF
block. If defined in both, all tables will be included in the column definition file.
- Defines additional output tables (note: a
Metamodel Example
Let’s create a simple metamodel called
OneCpt_IVInfusion.mmdl
.
## Description: A one-compartment model with IV infusion
# The model is fitted using the default FOCE-ELS engine.
# Note: the default values for the relevant NLME engine arguments are chosen based on the model, type ?engineParams for details.
## DATA OneCpt_IVInfusion.csv
## MAP id = Subject time = Time A1 = Dose A1_Rate = Rate CObs
## MODEL
test(){
cfMicro(A1, Cl / V)
dosepoint(A1)
C = A1 / V
error(CEps = 0.1)
observe(CObs = C * (1 + CEps))
stparm(V = tvV * exp(nV))
stparm(Cl = tvCl * exp(nCl))
fixef(tvV = c(, 5, ))
fixef(tvCl = c(, 1, ))
ranef(diag(nV, nCl) = c(1, 1))
}
## ESTARGS
numIterations = 1 # one iteration only
stdErr = "None" # no standard error estimation requested
Explanation of Blocks:
- Description: Provides a brief description of the model.
-
DATA: Specifies that the input data is in the
OneCpt_IVInfusion.csv
file (in the current directory). -
MAP: Maps model variables to data columns:
-
id = Subject
: Maps the individual identifier to theSubject
column. -
time = Time
: Maps the time variable to theTime
column. -
A1 = Dose
: Maps the amount administered to dosing compartmentA1
to theDose
column. -
A1_Rate = Rate
: Maps the infusion rate for dosing compartmentA1
to theRate
column (if rate is zero or missing, a bolus dose is assumed). -
CObs
: Maps the observed concentration to theCObs
column (this is shorthand forCObs = CObs
).
-
- MODEL: Defines a one-compartment population model with clearance parameterization.
-
ESTARGS: Sets specific engine arguments:
-
numIterations = 1
: Limits the optimization to a single iteration. -
stdErr = "None"
: Disables standard error calculation.
-
Running a Metamodel
You can run a metamodel using the run_metamodel()
function. Here’s how to run the example metamodel locally without
parallelization (if you don’t specify a host and MPI is available, it
will automatically parallelize over 4 threads; otherwise, it will run on
a single core).
Note: We’ll use the directoryToRun
argument to
create a new subfolder named OneCpt_IVInfusion
in your
working directory, where the model output files will be stored.
host <- hostParams(parallelMethod = "None",
hostName = "local",
numCores = 1)
OneCpt_IVInfusionFile <-
system.file("vignettesdata/OneCpt_IVInfusion.mmdl",
package = "Certara.RsNLME",
mustWork = TRUE)
OneCpt_IVInfusionResults <-
run_metamodel(mmdlfile = OneCpt_IVInfusionFile,
directoryToRun = "OneCpt_IVInfusion",
host = host)
print(OneCpt_IVInfusionResults$Overall)
#> Scenario RetCode LogLik -2LL AIC BIC nParm nObs nSub
#> 1: WorkFlow 4 -1085.769 2171.538 2181.538 2204.294 5 700 100
#> EpsShrinkage Condition
#> 1: 0.12159 NA
Loading a Metamodel for Other Run Modes
If you want to perform a different type of run (e.g., bootstrap), you
need to load the metamodel into R using the
create_model_from_metamodel()
function. This function
returns a list containing the model object and engine parameters (if
specified in the metamodel). You can then pass these to the appropriate
model execution function.
Example (Bootstrap Run):
ModelParamsList <-
create_model_from_metamodel(mmdlfile = OneCpt_IVInfusionFile)
bootParams <- BootstrapParams(numReplicates = 5,
randomNumSeed = 1234)
bootResults <-
bootstrap(model = ModelParamsList$model,
params = ModelParamsList$params,
bootParams = bootParams)
print(bootResults$BootTheta)
#> Scenario Parameter Mean Stderr CV% Median 2.5%
#> 1: (B) tvV 4.7780358 0.010690711 0.223747 4.7720495 4.7682849
#> 2: (B) tvCl 0.8549129 0.010439461 1.221114 0.8508297 0.8473296
#> 3: (B) CEps 0.0941178 0.007253549 7.706883 0.0912145 0.0849065
#> 97.5%
#> 1: 4.7949070
#> 2: 0.8731682
#> 3: 0.1038233