forked from dkaschek/dMod
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathREADME.Rmd
More file actions
223 lines (156 loc) · 6.4 KB
/
README.Rmd
File metadata and controls
223 lines (156 loc) · 6.4 KB
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
---
title: "dMod - Dynamic Modeling and Parameter Estimation in R"
output:
github_document:
toc: false
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(
fig.width = 8,
fig.height = 3,
out.width = "100%",
dpi = 150
)
```
<!-- badges: start -->
[](https://github.com/JetiLab/dMod/actions/workflows/R-CMD-check.yaml)
<!-- badges: end -->
The dMod package is a framework that provides functions to generate ODEs of reaction networks, parameter transformations, observation functions, residual functions, etc. The framework follows the paradigm that derivative information should be used for optimization whenever possible. Therefore, all major functions produce and can handle expressions for symbolic derivatives.
## System requirements
dMod uses the package [cOde](https://github.com/dkaschek/cOde) to set up ODE models as compiled C code (deSolve) or [CppODE](https://github.com/simonbeyer1/CppODE) to autogenerate C++ code (Boost.Odeint). This means that **C and C++ compilers** are required on the system. On Linux, the compilers are installed by default. Windows users need to install [RTools](https://cran.r-project.org/bin/windows/Rtools/).
For **parallelization**, dMod uses `mclapply()` on Linux and macOS. On Windows, parallelization is implemented via the `foreach` package using `%dopar%`.
## Installation from GitHub
To **install dMod from the GitHub repository**, it is convenient to use **RStudio**.
1. Create a new project via\
**File → New Project → Version Control → Git**.
2. Use the repository URL\
```
jetilab/dMod
```
and create the project.
3. Install all required package dependencies (including GitHub dependencies specified via `Remotes`) by running:
``` r
remotes::install_deps(dependencies = TRUE)
```
4. Open the **Build** tab in RStudio and click **Build and Reload** (or **Install**).
Once these steps are completed, it should be possible to run the following example.
------------------------------------------------------------------------
If **PEtab support** is required, **libSBML** is needed in addition. Installation and usage instructions can be found in the wiki under [Support for PEtab](https://github.com/dkaschek/dMod/wiki/Support-for-PEtab).
------------------------------------------------------------------------
## Simple example: enzyme kinetics
### Load required packages
```{r libraries, message=FALSE}
library(dMod)
library(ggplot2)
```
### Generate an ODE model of enzyme kinetics with enzyme degradation
```{r model}
# Reactions
f <- NULL
f <- addReaction(f,
from = "Enz + Sub",
to = "Compl",
rate = "k1*Enz*Sub",
description = "production of complex")
f <- addReaction(f,
from = "Compl",
to = "Enz + Sub",
rate = "k2*Compl",
description = "decay of complex")
f <- addReaction(f,
from = "Compl",
to = "Enz + Prod",
rate = "k3*Compl",
description = "production of product")
f <- addReaction(f,
from = "Enz",
to = "" ,
rate = "k4*Enz",
description = "enzyme degradation")
# ODE model
model <- odemodel(f, modelname = "enzymeKinetics")
# Prediction function
x <- Xs(model)
```
### Define observables and generate observation function `g`
```{r observables}
observables <- eqnvec(
product = "Prod",
substrate = "(Sub + Compl)",
enzyme = "(Enz + Compl)"
)
# Generate observation functions
g <- Y(observables, x, compile = TRUE, modelname = "obsfn", attach.input = FALSE)
```
### Define parameter transformation for two experimental conditions
```{r trafo}
# Get all parameters
innerpars <- getParameters(g*x)
# Identity transformation
trafo <- repar("x~x", x = innerpars)
# Set some initial value parameters
trafo <- repar("x~0", x = c("Compl", "Prod"), trafo)
# Explicit log-transform of all parameters
trafo <- repar("x~exp(x)", x = innerpars, trafo)
## Split transformation into two
trafo1 <- trafo2<- trafo
# Set the degradation rate in the first condition to 0
trafo1["k4"] <- "0"
# Generate parameter transformation functions
p <- NULL
p <- p + P(trafo1, condition = "noDegradation")
p <- p + P(trafo2, condition = "withDegradation")
```
### Initialize parameters and make prediction
```{r prediction}
# Initialize with randomly chosen parameters
set.seed(1)
outerpars <- getParameters(p)
pouter <- structure(rnorm(length(outerpars), -2, .5), names = outerpars)
times <- 0:100
plot((g*x*p)(times, pouter))
```
### Define data to be fitted by the model
```{r data}
data <- datalist(
noDegradation = data.frame(
name = c("product", "product", "product", "substrate", "substrate", "substrate"),
time = c(0, 25, 100, 0, 25, 100),
value = c(0.0025, 0.2012, 0.3080, 0.3372, 0.1662, 0.0166),
sigma = 0.02),
withDegradation = data.frame(
name = c("product", "product", "product", "substrate", "substrate", "substrate", "enzyme", "enzyme", "enzyme"),
time = c(0, 25, 100, 0, 25, 100, 0, 25, 100),
value = c(-0.0301, 0.1512, 0.2403, 0.3013, 0.1635, 0.0411, 0.4701, 0.2001, 0.0383),
sigma = 0.02)
)
timesD <- sort(unique(unlist(lapply(data, function(d) d$time))))
# Compare data to prediction
plot(data) + geom_line()
plot((g*x*p)(times, pouter), data)
```
### Define an objective function to be minimized and run minimization by `trust()`
```{r trust}
# Define prior values for parameters
prior <- structure(rep(0, length(pouter)), names = names(pouter))
# Set up objective function
obj <- normL2(data, g*x*p) + constraintL2(mu = prior, sigma = 10)
# Optimize the objective function
myfit <- trust(obj, pouter, rinit = 1, rmax = 10)
plot((g*x*p)(times, myfit$argument), data)
```
### Compute the profile likelihood to analyze parameter identifiability
```{r profiles, fig.height = 5}
# Compute the profile likelihood around the optimum
bestfit <- myfit$argument
profiles <- profile(obj, bestfit, names(bestfit), limits = c(-10, 10), cores = 4)
# Take a look at each parameter
plotProfile(profiles)
```
```{r, echo=FALSE}
# Cleaning step
dlls <- list.files(pattern = "\\.(so|dll)$")
for (d in dlls) try(dyn.unload(d), silent = TRUE)
files <- list.files(pattern = "^(enzymeKinetics|obsfn|expl_parfn_noDegradation|expl_parfn_withDegradation).*(c|cpp|o|dll|so)$")
unlink(files)
```