-
Notifications
You must be signed in to change notification settings - Fork 6
/
README.Rmd
297 lines (235 loc) · 13.1 KB
/
README.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
---
output: github_document
---
<!-- README.md is generated from README.Rmd. Please edit that file -->
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
library(NMdata)
library(data.table)
library(NMsim)
NMdataConf(reset=TRUE)
library(kableExtra)
```
# NMsim<a href='https://NMautoverse.github.io/NMsim/'><img src='man/figures/NMsimlogo240.png' align="right" height="120" /></a>
<!-- badges: start -->
[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html)
[![CRAN status](https://www.r-pkg.org/badges/version/NMsim)](https://CRAN.R-project.org/package=NMsim)
[![CRAN downloads](https://cranlogs.r-pkg.org/badges/NMsim)](https://cran.r-project.org/package=NMsim)
[![Codecov test coverage](https://codecov.io/gh/NMautoverse/NMsim/branch/main/graph/badge.svg)](https://app.codecov.io/gh/NMautoverse/NMsim?branch=main)
[![R-CMD-check](https://github.com/NMautoverse/NMsim/workflows/R-CMD-check/badge.svg)](https://github.com/NMautoverse/NMsim/actions)
<!-- badges: end -->
Please make sure to read this at
[`The NMsim website`](https://NMautoverse.github.io/NMsim/) where you can browse several vignettes with examples on specific topics.
`NMsim` is an R package that can simulate Nonmem models (using the
`NMsim` function) based on just a simulation data set and a path to an
estimation control stream. It will retrive and combine output
tables with input data once Nonmem has finished and return the results
to R.
The interface is "seamless" or fully integrated in R. Run a simulation
of the (estimated) model stored in "path/to/file.mod" using the
simulation input data set stored in the variable `data.sim` this way:
```{r,eval=FALSE}
simres <- NMsim(file.mod="/path/to/file.mod",
data=data.sim)
```
You will quickly learn to do this on your own models, but if you can't wait to see this working, you can do the following:
```{r,eval=FALSE}
data.sim <- read.csv(system.file("examples/derived/dat_sim1.csv",package="NMsim"))
simres <- NMsim(file.mod=system.file("examples/nonmem/xgxr021.mod",package="NMsim"),
data=data.sim,
dir.sims=".")
```
where `dir.sims` may be needed because the model in this case may be in a read-only location.
Notice, that could be any working Nonmem model as long as the provided simulation data set is sufficient to run it. We are ready to plot:
```{r,include=FALSE,eval=FALSE}
data.sim <- read.csv(system.file("examples/derived/dat_sim1.csv",package="NMsim"))
simres <- NMsim(file.mod=system.file("examples/nonmem/xgxr021.mod",package="NMsim"),
data=data.sim,
dir.sims="vignettes/simulate-results")
```
```{r,include=FALSE,eval=TRUE}
simres <- NMreadSim("vignettes/simulate-results/xgxr021_noname_MetaData.rds")
```
```{r,simple-sim-show,eval=FALSE,fig.height = 4, fig.width = 7}
library(ggplot2)
datl <- as.data.table(simres) |>
melt(measure.vars=cc(PRED,IPRED,Y))
ggplot(datl,aes(TIME,value,colour=variable))+
geom_line(data=function(x)x[variable!="Y"])+
geom_point(data=function(x)x[variable=="Y"])+
labs(x="Hours since first dose",y="Concentration (ng/mL)")
```
```{r,simple-sim,eval=TRUE,fig.height = 4, fig.width = 7,include=TRUE,echo=FALSE}
library(ggplot2)
theme_set(theme_bw())
datl <- as.data.table(simres) |>
melt(measure.vars=cc(PRED,IPRED,Y))
ggplot(datl,aes(TIME,value,colour=variable))+
geom_line(data=function(x)x[variable!="Y"])+
geom_point(data=function(x)x[variable=="Y"])+
labs(x="Hours since first dose",y="Concentration (ng/mL)")
```
This example was a simulation of a multiple dose regimen with a loading dose using a model estimated on single dose data. It is from the first vignette [`NMsim-intro.html`](https://NMautoverse.github.io/NMsim/articles/NMsim-intro.html). Go there next to get started with `NMsim`.
## Motivation
While NONMEM offers great flexibility for estimation of PK and PK/PD
models, many users find the simulation features in NONMEM insufficient
and turn to alternative software for simulation. This leads to
additional work of model reimplementation, with risk of the simulation
model deviating from the estimated model, due to bugs in the
reimplementation. For a wide range of model types, the limitation is
not in NONMEM's ability to perform such simulations, but rather in the
lack of a simple user-interface to obtain the
simulations. [`NMsim`](https://cran.r-project.org/package=NMsim)
provides such an interface as an R package, allowing the modeler to
simulate models as soon as an estimate is available.
The goal for NMsim is to automate the NONMEM simulation workflow and
provide a simple, flexible, and powerful R interface. This allows for
automation of most simulation-based analyses.
<img src='man/figures/intro-tab.png' height="140" alt="NMsim can simulate NONMEM models right away - but only ifh NONMEM is avaiable." />
## Supported types of simulations
`NMsim` has a flexible way to define simulation methods. The following
methods are currently provided:
- Simulation of new subjects (default or explicitly with `method.sim=NMsim_default`)
- Simulation of subjects already estimated in Nonmem model (`method.sim=NMsim_EBE`)
- Simulation with parameter uncertainty based on a Nonmem covariance step (`method.sim=NMsim_VarCov`)
- Simulation "as is" in case you already prepared a simulation control stream and just want to automate the use of it in combination with simulation data sets (`method.sim=NMsim_asis`)
In addition, `NMsim` provides other features to further modify the simulation control stream
- Simulation of typical subjects with all ETAs equal 0 (`typical=TRUE`)
- Custom modification of control stream sections (`modify.sections` argument)
To learn how to run these simulations on your Nonmem models, get
started with
[`NMsim-intro.html`](https://NMautoverse.github.io/NMsim/articles/NMsim-intro.html). It
is really easy.
In addition, `NMsim` can simulate multiple models at a time. E.g., if a
bootstrap run of a model is available, NMsim can run the simulation
with each of the bootstrap models and collect all the results in one
dataset. This provides a robust and easy way to simulate a Nonmem
model with uncertainty.
You can also write your own methods, if you have some other
Nonmem-based simulation (or other job) you want to automate using
`NMsim`.
Many features are available. Prominent ones are:
* Can use submit jobs to clusters. It can wait for the simulations to be done and automatically collect the results like in the example above.
* Simulation replicates using Nonmem `SUBPROBLEMS` feature avaible
through the `subproblems` argument
* Can modify the simulation control stream on the fly - a powerful
feature for studying the effect of varying model parameters
* Simulations of models on transformed observations can be
automatically transformed back using the `transform` argument.
If residual variability is not implemented in the simulated model,
`NMsim` provides a way (`addResVar()`) to add residual variability in
R after the simulation has been run.
## How NMsim works
`NMsim` does not simulate, translate or otherwise interpret a NONMEM
model. Instead, it automates the NONMEM simulation workflow (including
execution of NONMEM) and wraps it all into one R function. Provided
with a path to a NONMEM control stream and a data.frame to simulate,
`NMsim` will do the following:
* Save the simulation input data in a csv file for NONMEM
* Create a simulation input control stream based on `file.mod` (`$INPUT`
and `$DATA` matching the saved simulation data set; `$SIMULATE` instead of
`$ESTIMATION` and `$COVARIANCE`)
* Update and fix initial values based on estimate (from `file.ext`)
* Run NONMEM on the generated simulation control stream
* Collect output data tables, combine them, and merge with the simulation input
data
* Return the collected data in R
`NMsim` can call NONMEM directly or via `PSN`. If `NMsim` is run on a
system where NONMEM cannot be executed, `NMsim` can still prepare the
simulation control stream and datafile.
`NMsim` is in itself a relatively small R package. It makes extensive use of
functionality to handle NONMEM data and control streams provided by
the R package
[`NMdata`](https://cran.r-project.org/package=NMdata).
## Supported model types
The methods currently provided by `NMsim` will work with (many or
most) Pop PK models and most continuous-scale PD models. Methods are
currently not provided for for time-to-event models. Also, depending
on the coding of the models, other censored data models may not work
out of the box, because the model may not have a single variable (in
Nonmem) that simulates the wanted information for all data rows, as
their interpretation may depend on other values.
The input data set must contain whatever variables are needed by the
Nonmem model. A common issue is if the Nonmem model uses a covariate
that is not in the simulation input data set. `NMdata`'s
[NMcheckData](https://NMautoverse.github.io/NMdata/reference/NMcheckData.html)
is a good help identifying input data issues before running Nonmem -
and when Nonmem acts unexpectedly.
## NMsim and speed
Nonmem may not be the fastest simulator out there. But actually most
often, the reason Nonmem is slow at providing a simulation result is
that it takes a long time writing the `$TABLE` files (yes, that can
account for 90% or more of the time Nonmem spends). `NMsim` provides a
simple way to get around this. The argument `text.table` can be used
to define only the columns needed in the simulation output (which may
be as little as `PRED`, `IPRED`, and a couple more - remember the
input data is merged back automatically). As a result, `NMsim` may
still be slower than a re-implementation in a different framework. But
it's extremely easy to do.
## Requirements
NMsim is dependent on running Nonmem. Often, that will mean Nonmem
must be available on the same system as the one running R. However, if
Nonmem is run on a separate system through `qsub` or in another way
initiates Nonmem on another system, that will work too. Then however,
only if R can read the file system where Nonmem writes the results, it
can retrieve the results.
NMsim does not need PSN but can use it. However, not all features are
available with PSN, so for some features you will have to specify the path to the
Nonmem executable (say `path.nonmem=/path/to/nmfe75` or any Nonmem
executable you want to use). Specifically of the simulation types
currently available, simulation of known subjects is not possible
using PSN (but works if a Nonmem executable is provided).
If PSN is used, `NMsim` uses PSN's `execute` to run models. In
addition, `NMsim` by default uses PSN's `update_inits` to update initial
values in control streams, if PSN is available. `NMsim` does also include its own simple
function to do this if `PSN` is not available.
## Is `NMsim` reliable?
Importantly, `NMsim` does not (at least not by default) modify, translate or simulate the model
itself. It does modify control stream sections `$INPUT`, `$DATA`,
`$ESTIMATION`, `$SIMULATION`, `$THETA`, `$OMEGA`, `$SIGMA`, `$TABLE`
as needed. The fact that `NMsim` allows for skipping the
re-implementation but just uses Nonmem to simulate the Nonmem model as is,
eliminates the risk of discrepancies between the estimated model and
the simulated model.
The produced control stream is saved together with simulation data set
open for manual inspection and can obviously be run with Nonmem
independently of `NMsim`.
## Easily create simulation datasets
`NMsim` includes functions (`NMcreateDoses` and `addEVID2`) to very
easily create simulation data sets. While one certainly does not need to
use these functions to use `NMsim`, they do add to the package
providing a framework that enables a complete simulation workflow in
only 5-15 simple lines of R code.
## Run Nonmem from R
There are several other packages out there that can do this, and
`NMsim` may not be your best choice if this feature is all you are
looking for. However, running Nonmem using the `NMexec()` function
provided by `NMsim` has one important advantage in that it saves the
input data together with the Nonmem control streams. This ensures that
output data can be merged with input data as it went into the model,
even if the input data file should be modified or lost.
- Saves input data with Nonmem model
- Provides a simple R command for submission of Nonmem jobs
- Optionally handles cluster configuration
- Saves the xml file by default
`NMexec` will submit model runs to a cluster by default. This can be
switched off for running Nonmem locally. Please notice the jobs are
submitted to a cluster in a very specific way using `PSN`. If your
setup is different, this is for now not supported. Please use
`NMexec(sge=FALSE)` in that case (which may not be desirable). Notice
that simulations are not done on a cluster by default so you may still
be able to use `NMsim`.
## Install
`NMsim` is on CRAN, MPN and github:
```{r,eval=FALSE}
## From CRAN/MPN repositories
install.packages("NMsim")
## From github
library(remotes)
install_github("NMautoverse/NMsim")
```