aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GNUmakefile9
-rw-r--r--NAMESPACE106
-rw-r--r--R/AIC.mmkin.R50
-rw-r--r--R/CAKE_export.R44
-rw-r--r--R/DFOP.solution.R32
-rw-r--r--R/FOMC.solution.R40
-rw-r--r--R/HS.solution.R35
-rw-r--r--R/IORE.solution.R41
-rw-r--r--R/SFO.solution.R26
-rw-r--r--R/SFORB.solution.R44
-rw-r--r--R/add_err.R96
-rw-r--r--R/endpoints.R377
-rw-r--r--R/ilr.R46
-rw-r--r--R/logLik.mkinfit.R52
-rw-r--r--R/logistic.solution.R55
-rw-r--r--R/max_twa_parent.R70
-rw-r--r--R/mkin_long_to_wide.R57
-rw-r--r--R/mkin_wide_to_long.R68
-rw-r--r--R/mkinds.R55
-rw-r--r--R/mkinerrmin.R55
-rw-r--r--R/mkinerrplot.R56
-rw-r--r--R/mkinfit.R1801
-rw-r--r--R/mkinmod.R866
-rw-r--r--R/mkinparplot.R37
-rw-r--r--R/mkinplot.R4
-rw-r--r--R/mkinpredict.R119
-rw-r--r--R/mkinresplot.R149
-rw-r--r--R/mkinsub.R54
-rw-r--r--R/mmkin.R113
-rw-r--r--R/nafta.R79
-rw-r--r--R/plot.mkinfit.R126
-rw-r--r--R/plot.mmkin.R68
-rw-r--r--R/sigma_twocomp.R26
-rw-r--r--R/summary.mkinfit.R272
-rw-r--r--R/transform_odeparms.R438
-rw-r--r--man/AIC.mmkin.Rd39
-rw-r--r--man/CAKE_export.Rd104
-rw-r--r--man/DFOP.solution.Rd74
-rw-r--r--man/Extract.mmkin.Rd22
-rw-r--r--man/FOMC.solution.Rd99
-rw-r--r--man/HS.solution.Rd73
-rw-r--r--man/IORE.solution.Rd95
-rw-r--r--man/SFO.solution.Rd61
-rw-r--r--man/SFORB.solution.Rd78
-rw-r--r--man/add_err.Rd92
-rw-r--r--man/endpoints.Rd38
-rw-r--r--man/ilr.Rd52
-rw-r--r--man/logLik.mkinfit.Rd54
-rw-r--r--man/logistic.solution.Rd52
-rw-r--r--man/max_twa_parent.Rd112
-rw-r--r--man/mkin_long_to_wide.Rd44
-rw-r--r--man/mkin_wide_to_long.Rd37
-rw-r--r--man/mkinds.Rd26
-rw-r--r--man/mkinerrmin.Rd106
-rw-r--r--man/mkinerrplot.Rd118
-rw-r--r--man/mkinfit.Rd438
-rw-r--r--man/mkinmod.Rd238
-rw-r--r--man/mkinparplot.Rd67
-rw-r--r--man/mkinplot.Rd28
-rw-r--r--man/mkinpredict.Rd133
-rw-r--r--man/mkinresplot.Rd141
-rw-r--r--man/mkinsub.Rd54
-rw-r--r--man/mmkin.Rd76
-rw-r--r--man/nafta.Rd79
-rw-r--r--man/plot.mkinfit.Rd213
-rw-r--r--man/plot.mmkin.Rd96
-rw-r--r--man/plot.nafta.Rd43
-rw-r--r--man/print.mkinds.Rd21
-rw-r--r--man/print.mkinmod.Rd28
-rw-r--r--man/print.nafta.Rd27
-rw-r--r--man/sigma_twocomp.Rd41
-rw-r--r--man/summary.mkinfit.Rd152
-rw-r--r--man/transform_odeparms.Rd110
-rw-r--r--test.log8
-rw-r--r--tests/testthat/FOCUS_2006_D.csf2
75 files changed, 5103 insertions, 3834 deletions
diff --git a/GNUmakefile b/GNUmakefile
index 231273c1..a98129e0 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -39,11 +39,14 @@ $(TGZ): $(pkgfiles) vignettes
$(RM) Rplots.pdf
"$(RBIN)/R" CMD build . 2>&1 | tee build.log
+roxygen:
+ "$(RBIN)/Rscript" -e 'devtools::document()'
+
$(TGZVNR): $(pkgfiles)
"$(RBIN)/R" CMD build . --no-build-vignettes;\
mv $(TGZ) $(TGZVNR)
-build: $(TGZ)
+build: roxygen $(TGZ)
build-no-vignettes: $(TGZVNR)
@@ -53,10 +56,10 @@ install: build
quickinstall: build-no-vignettes
"$(RBIN)/R" CMD INSTALL $(TGZVNR)
-check: build
+check: roxygen build
_R_CHECK_CRAN_INCOMING_REMOTE_=false "$(RBIN)/R" CMD check --as-cran --no-tests $(TGZ) 2>&1 | tee check.log
-quickcheck: build-no-vignettes
+quickcheck: roxygen build-no-vignettes
mv $(TGZVNR) $(TGZ)
"$(RBIN)/R" CMD check --no-tests --no-build-vignettes --no-vignettes $(TGZ)
mv $(TGZ) $(TGZVNR)
diff --git a/NAMESPACE b/NAMESPACE
index 18adb9c5..72ad9d3a 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -1,35 +1,73 @@
-# Export all names except for those starting with a dot
-exportPattern("^[^\\.]")
+# Generated by roxygen2: do not edit by hand
-S3method(print, mkinmod)
-S3method(print, mkinds)
-S3method(print, nafta)
-
-S3method(plot, mkinfit)
-S3method(plot, mmkin)
-S3method(plot, nafta)
-
-S3method(summary, mkinfit)
-S3method(print, summary.mkinfit)
-
-S3method(logLik, mkinfit)
-S3method("[", mmkin)
-S3method(AIC, mmkin)
-
-S3method(mkinpredict, mkinmod)
-S3method(mkinpredict, mkinfit)
-
-import(
- stats,
- graphics,
- inline,
- parallel
-)
-
-importFrom(deSolve, ode)
-importFrom(methods, signature)
-importFrom(R6, R6Class)
-importFrom(grDevices, dev.cur)
-importFrom(plyr, join)
-importFrom(utils, write.table)
-importFrom(numDeriv, hessian)
+S3method("[",mmkin)
+S3method(AIC,mmkin)
+S3method(logLik,mkinfit)
+S3method(mkinpredict,mkinfit)
+S3method(mkinpredict,mkinmod)
+S3method(plot,mkinfit)
+S3method(plot,mmkin)
+S3method(plot,nafta)
+S3method(print,mkinds)
+S3method(print,mkinmod)
+S3method(print,nafta)
+S3method(print,summary.mkinfit)
+S3method(summary,mkinfit)
+export(CAKE_export)
+export(DFOP.solution)
+export(FOMC.solution)
+export(HS.solution)
+export(IORE.solution)
+export(SFO.solution)
+export(SFORB.solution)
+export(add_err)
+export(backtransform_odeparms)
+export(endpoints)
+export(ilr)
+export(invilr)
+export(logistic.solution)
+export(max_twa_dfop)
+export(max_twa_fomc)
+export(max_twa_hs)
+export(max_twa_parent)
+export(max_twa_sfo)
+export(mkin_long_to_wide)
+export(mkin_wide_to_long)
+export(mkinds)
+export(mkinerrmin)
+export(mkinerrplot)
+export(mkinfit)
+export(mkinmod)
+export(mkinparplot)
+export(mkinplot)
+export(mkinpredict)
+export(mkinresplot)
+export(mkinsub)
+export(mmkin)
+export(nafta)
+export(plot_err)
+export(plot_res)
+export(plot_sep)
+export(sigma_twocomp)
+export(transform_odeparms)
+import(deSolve)
+import(graphics)
+importFrom(R6,R6Class)
+importFrom(grDevices,dev.cur)
+importFrom(inline,cfunction)
+importFrom(inline,getDynLib)
+importFrom(methods,signature)
+importFrom(parallel,detectCores)
+importFrom(parallel,mclapply)
+importFrom(parallel,parLapply)
+importFrom(stats,aggregate)
+importFrom(stats,cov2cor)
+importFrom(stats,dist)
+importFrom(stats,nlminb)
+importFrom(stats,optimize)
+importFrom(stats,pt)
+importFrom(stats,qchisq)
+importFrom(stats,qf)
+importFrom(stats,qt)
+importFrom(stats,rnorm)
+importFrom(utils,write.table)
diff --git a/R/AIC.mmkin.R b/R/AIC.mmkin.R
index 1d306ff9..ab17f0a0 100644
--- a/R/AIC.mmkin.R
+++ b/R/AIC.mmkin.R
@@ -1,21 +1,35 @@
-# Copyright (C) 2018 Johannes Ranke
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
-AIC.mmkin <- function(object, ..., k = 2) {
+#' Calculated the AIC for a column of an mmkin object
+#'
+#' Provides a convenient way to compare different kinetic models fitted to the
+#' same dataset.
+#'
+#' @param object An object of class \code{\link{mmkin}}, containing only one
+#' column.
+#' @param \dots For compatibility with the generic method
+#' @param k As in the generic method
+#' @return As in the generic method (a numeric value for single fits, or a
+#' dataframe if there are several fits in the column).
+#' @author Johannes Ranke
+#' @examples
+#'
+#' \dontrun{ # skip, as it takes > 10 s on winbuilder
+#' f <- mmkin(c("SFO", "FOMC", "DFOP"),
+#' list("FOCUS A" = FOCUS_2006_A,
+#' "FOCUS C" = FOCUS_2006_C), cores = 1, quiet = TRUE)
+#' AIC(f[1, "FOCUS A"]) # We get a single number for a single fit
+#'
+#' # For FOCUS A, the models fit almost equally well, so the higher the number
+#' # of parameters, the higher (worse) the AIC
+#' AIC(f[, "FOCUS A"])
+#' AIC(f[, "FOCUS A"], k = 0) # If we do not penalize additional parameters, we get nearly the same
+#'
+#' # For FOCUS C, the more complex models fit better
+#' AIC(f[, "FOCUS C"])
+#' }
+#'
+#' @export
+AIC.mmkin <- function(object, ..., k = 2)
+{
# We can only handle a single column
if (ncol(object) != 1) stop("Please provide a single column object")
n.fits <- length(object)
diff --git a/R/CAKE_export.R b/R/CAKE_export.R
index db9caa8d..70661b10 100644
--- a/R/CAKE_export.R
+++ b/R/CAKE_export.R
@@ -1,20 +1,30 @@
-# Copyright (C) 2019 Johannes Ranke
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
+#' Export a list of datasets format to a CAKE study file
+#'
+#' In addition to the datasets, the pathways in the degradation model can be
+#' specified as well.
+#'
+#' @param ds A named list of datasets in long format as compatible with
+#' \code{\link{mkinfit}}.
+#' @param map A character vector with CAKE compartment names (Parent, A1, ...),
+#' named with the names used in the list of datasets.
+#' @param links An optional character vector of target compartments, named with
+#' the names of the source compartments. In order to make this easier, the
+#' names are used as in the datasets supplied.
+#' @param filename Where to write the result. Should end in .csf in order to be
+#' compatible with CAKE.
+#' @param path An optional path to the output file.
+#' @param overwrite If TRUE, existing files are overwritten.
+#' @param study The name of the study.
+#' @param description An optional description.
+#' @param time_unit The time unit for the residue data.
+#' @param res_unit The unit used for the residues.
+#' @param comment An optional comment.
+#' @param date The date of file creation.
+#' @param optimiser Can be OLS or IRLS.
+#' @importFrom utils write.table
+#' @return The function is called for its side effect.
+#' @author Johannes Ranke
+#' @export
CAKE_export <- function(ds, map = c(parent = "Parent"),
links = NA,
filename = "CAKE_export.csf", path = ".", overwrite = FALSE,
diff --git a/R/DFOP.solution.R b/R/DFOP.solution.R
index 8531cfed..608e7e18 100644
--- a/R/DFOP.solution.R
+++ b/R/DFOP.solution.R
@@ -1,5 +1,27 @@
-DFOP.solution <- function(t, parent.0, k1, k2, g)
-{
- parent = g * parent.0 * exp(-k1 * t) +
- (1 - g) * parent.0 * exp(-k2 * t)
-}
+#' Double First-Order in Parallel kinetics
+#'
+#' Function describing decline from a defined starting value using the sum of
+#' two exponential decline functions.
+#'
+#' @param t Time.
+#' @param parent.0 Starting value for the response variable at time zero.
+#' @param k1 First kinetic constant.
+#' @param k2 Second kinetic constant.
+#' @param g Fraction of the starting value declining according to the first
+#' kinetic constant.
+#' @return The value of the response variable at time \code{t}.
+#' @references FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence
+#' and Degradation Kinetics from Environmental Fate Studies on Pesticides in
+#' EU Registration} Report of the FOCUS Work Group on Degradation Kinetics,
+#' EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
+#' \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+#' @examples
+#'
+#' plot(function(x) DFOP.solution(x, 100, 5, 0.5, 0.3), 0, 4, ylim = c(0,100))
+#'
+#' @export
+DFOP.solution <- function(t, parent.0, k1, k2, g)
+{
+ parent = g * parent.0 * exp(-k1 * t) +
+ (1 - g) * parent.0 * exp(-k2 * t)
+}
diff --git a/R/FOMC.solution.R b/R/FOMC.solution.R
index 8bd13d6b..f5e6a7ea 100644
--- a/R/FOMC.solution.R
+++ b/R/FOMC.solution.R
@@ -1,4 +1,36 @@
-FOMC.solution <- function(t, parent.0, alpha, beta)
-{
- parent = parent.0 / (t/beta + 1)^alpha
-}
+#' First-Order Multi-Compartment kinetics
+#'
+#' Function describing exponential decline from a defined starting value, with
+#' a decreasing rate constant.
+#'
+#' The form given here differs slightly from the original reference by
+#' Gustafson and Holden (1990). The parameter \code{beta} corresponds to 1/beta
+#' in the original equation.
+#'
+#' @param t Time.
+#' @param parent.0 Starting value for the response variable at time zero.
+#' @param alpha Shape parameter determined by coefficient of variation of rate
+#' constant values.
+#' @param beta Location parameter.
+#' @return The value of the response variable at time \code{t}.
+#' @note The solution of the FOMC kinetic model reduces to the
+#' \code{\link{SFO.solution}} for large values of \code{alpha} and
+#' \code{beta} with \eqn{k = \frac{\beta}{\alpha}}{k = beta/alpha}.
+#' @references FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence
+#' and Degradation Kinetics from Environmental Fate Studies on Pesticides in
+#' EU Registration} Report of the FOCUS Work Group on Degradation Kinetics,
+#' EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
+#' \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+#'
+#' Gustafson DI and Holden LR (1990) Nonlinear pesticide dissipation in soil:
+#' A new model based on spatial variability. \emph{Environmental Science and
+#' Technology} \bold{24}, 1032-1038
+#' @examples
+#'
+#' plot(function(x) FOMC.solution(x, 100, 10, 2), 0, 2, ylim = c(0, 100))
+#'
+#' @export
+FOMC.solution <- function(t, parent.0, alpha, beta)
+{
+ parent = parent.0 / (t/beta + 1)^alpha
+}
diff --git a/R/HS.solution.R b/R/HS.solution.R
index 4651a6a8..890ad8ff 100644
--- a/R/HS.solution.R
+++ b/R/HS.solution.R
@@ -1,6 +1,29 @@
-HS.solution <- function(t, parent.0, k1, k2, tb)
-{
- parent = ifelse(t <= tb,
- parent.0 * exp(-k1 * t),
- parent.0 * exp(-k1 * tb) * exp(-k2 * (t - tb)))
-}
+#' Hockey-Stick kinetics
+#'
+#' Function describing two exponential decline functions with a break point
+#' between them.
+#'
+#' @param t Time.
+#' @param parent.0 Starting value for the response variable at time zero.
+#' @param k1 First kinetic constant.
+#' @param k2 Second kinetic constant.
+#' @param tb Break point. Before this time, exponential decline according to
+#' \code{k1} is calculated, after this time, exponential decline proceeds
+#' according to \code{k2}.
+#' @return The value of the response variable at time \code{t}.
+#' @references FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence
+#' and Degradation Kinetics from Environmental Fate Studies on Pesticides in
+#' EU Registration} Report of the FOCUS Work Group on Degradation Kinetics,
+#' EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
+#' \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+#' @examples
+#'
+#' plot(function(x) HS.solution(x, 100, 2, 0.3, 0.5), 0, 2, ylim=c(0,100))
+#'
+#' @export
+HS.solution <- function(t, parent.0, k1, k2, tb)
+{
+ parent = ifelse(t <= tb,
+ parent.0 * exp(-k1 * t),
+ parent.0 * exp(-k1 * tb) * exp(-k2 * (t - tb)))
+}
diff --git a/R/IORE.solution.R b/R/IORE.solution.R
index 5405be96..58807108 100644
--- a/R/IORE.solution.R
+++ b/R/IORE.solution.R
@@ -1,4 +1,37 @@
-IORE.solution <- function(t, parent.0, k__iore, N)
-{
- parent = (parent.0^(1 - N) - (1 - N) * k__iore * t)^(1/(1 - N))
-}
+#' Indeterminate order rate equation kinetics
+#'
+#' Function describing exponential decline from a defined starting value, with
+#' a concentration dependent rate constant.
+#'
+#' @param t Time.
+#' @param parent.0 Starting value for the response variable at time zero.
+#' @param k__iore Rate constant. Note that this depends on the concentration
+#' units used.
+#' @param N Exponent describing the nonlinearity of the rate equation
+#' @return The value of the response variable at time \code{t}.
+#' @note The solution of the IORE kinetic model reduces to the
+#' \code{\link{SFO.solution}} if N = 1. The parameters of the IORE model can
+#' be transformed to equivalent parameters of the FOMC mode - see the NAFTA
+#' guidance for details.
+#' @references NAFTA Technical Working Group on Pesticides (not dated) Guidance
+#' for Evaluating and Calculating Degradation Kinetics in Environmental Media
+#' @keywords manip
+#' @examples
+#'
+#' plot(function(x) IORE.solution(x, 100, 0.2, 1.3), 0, 2, ylim = c(0, 100))
+#' \dontrun{
+#' fit.fomc <- mkinfit("FOMC", FOCUS_2006_C, quiet = TRUE)
+#' fit.iore <- mkinfit("IORE", FOCUS_2006_C, quiet = TRUE)
+#' fit.iore.deS <- mkinfit("IORE", FOCUS_2006_C, solution_type = "deSolve", quiet = TRUE)
+#'
+#' print(data.frame(fit.fomc$par, fit.iore$par, fit.iore.deS$par,
+#' row.names = paste("model par", 1:4)))
+#' print(rbind(fomc = endpoints(fit.fomc)$distimes, iore = endpoints(fit.iore)$distimes,
+#' iore.deS = endpoints(fit.iore)$distimes))
+#' }
+#'
+#' @export
+IORE.solution <- function(t, parent.0, k__iore, N)
+{
+ parent = (parent.0^(1 - N) - (1 - N) * k__iore * t)^(1/(1 - N))
+}
diff --git a/R/SFO.solution.R b/R/SFO.solution.R
index 3a376e48..17c16a4d 100644
--- a/R/SFO.solution.R
+++ b/R/SFO.solution.R
@@ -1,4 +1,22 @@
-SFO.solution <- function(t, parent.0, k)
-{
- parent = parent.0 * exp(-k * t)
-}
+#' Single First-Order kinetics
+#'
+#' Function describing exponential decline from a defined starting value.
+#'
+#' @param t Time.
+#' @param parent.0 Starting value for the response variable at time zero.
+#' @param k Kinetic constant.
+#' @return The value of the response variable at time \code{t}.
+#' @references FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence
+#' and Degradation Kinetics from Environmental Fate Studies on Pesticides in
+#' EU Registration} Report of the FOCUS Work Group on Degradation Kinetics,
+#' EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
+#' \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+#' @examples
+#'
+#' \dontrun{plot(function(x) SFO.solution(x, 100, 3), 0, 2)}
+#'
+#' @export
+SFO.solution <- function(t, parent.0, k)
+{
+ parent = parent.0 * exp(-k * t)
+}
diff --git a/R/SFORB.solution.R b/R/SFORB.solution.R
index 4cb94def..2abe4577 100644
--- a/R/SFORB.solution.R
+++ b/R/SFORB.solution.R
@@ -1,9 +1,35 @@
-SFORB.solution = function(t, parent.0, k_12, k_21, k_1output) {
- sqrt_exp = sqrt(1/4 * (k_12 + k_21 + k_1output)^2 + k_12 * k_21 - (k_12 + k_1output) * k_21)
- b1 = 0.5 * (k_12 + k_21 + k_1output) + sqrt_exp
- b2 = 0.5 * (k_12 + k_21 + k_1output) - sqrt_exp
-
- parent = parent.0 *
- (((k_12 + k_21 - b1)/(b2 - b1)) * exp(-b1 * t) +
- ((k_12 + k_21 - b2)/(b1 - b2)) * exp(-b2 * t))
-}
+#' Single First-Order Reversible Binding kinetics
+#'
+#' Function describing the solution of the differential equations describing
+#' the kinetic model with first-order terms for a two-way transfer from a free
+#' to a bound fraction, and a first-order degradation term for the free
+#' fraction. The initial condition is a defined amount in the free fraction
+#' and no substance in the bound fraction.
+#'
+#' @param t Time.
+#' @param parent.0 Starting value for the response variable at time zero.
+#' @param k_12 Kinetic constant describing transfer from free to bound.
+#' @param k_21 Kinetic constant describing transfer from bound to free.
+#' @param k_1output Kinetic constant describing degradation of the free
+#' fraction.
+#' @return The value of the response variable, which is the sum of free and
+#' bound fractions at time \code{t}.
+#' @references FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence
+#' and Degradation Kinetics from Environmental Fate Studies on Pesticides in
+#' EU Registration} Report of the FOCUS Work Group on Degradation Kinetics,
+#' EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
+#' \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+#' @examples
+#'
+#' \dontrun{plot(function(x) SFORB.solution(x, 100, 0.5, 2, 3), 0, 2)}
+#'
+#' @export
+SFORB.solution = function(t, parent.0, k_12, k_21, k_1output) {
+ sqrt_exp = sqrt(1/4 * (k_12 + k_21 + k_1output)^2 + k_12 * k_21 - (k_12 + k_1output) * k_21)
+ b1 = 0.5 * (k_12 + k_21 + k_1output) + sqrt_exp
+ b2 = 0.5 * (k_12 + k_21 + k_1output) - sqrt_exp
+
+ parent = parent.0 *
+ (((k_12 + k_21 - b1)/(b2 - b1)) * exp(-b1 * t) +
+ ((k_12 + k_21 - b2)/(b1 - b2)) * exp(-b2 * t))
+}
diff --git a/R/add_err.R b/R/add_err.R
index b2a1808e..a523e9c2 100644
--- a/R/add_err.R
+++ b/R/add_err.R
@@ -1,24 +1,78 @@
-# Copyright (C) 2015-2018 Johannes Ranke
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
-
-add_err = function(prediction, sdfunc, secondary = c("M1", "M2"),
- n = 1000, LOD = 0.1, reps = 2,
- digits = 1, seed = NA)
+#' Add normally distributed errors to simulated kinetic degradation data
+#'
+#' Normally distributed errors are added to data predicted for a specific
+#' degradation model using \code{\link{mkinpredict}}. The variance of the error
+#' may depend on the predicted value and is specified as a standard deviation.
+#'
+#' @param prediction A prediction from a kinetic model as produced by
+#' \code{\link{mkinpredict}}.
+#' @param sdfunc A function taking the predicted value as its only argument and
+#' returning a standard deviation that should be used for generating the
+#' random error terms for this value.
+#' @param secondary The names of state variables that should have an initial
+#' value of zero
+#' @param n The number of datasets to be generated.
+#' @param LOD The limit of detection (LOD). Values that are below the LOD after
+#' adding the random error will be set to NA.
+#' @param reps The number of replicates to be generated within the datasets.
+#' @param digits The number of digits to which the values will be rounded.
+#' @param seed The seed used for the generation of random numbers. If NA, the
+#' seed is not set.
+#' @importFrom stats rnorm
+#' @return A list of datasets compatible with \code{\link{mmkin}}, i.e. the
+#' components of the list are datasets compatible with \code{\link{mkinfit}}.
+#' @author Johannes Ranke
+#' @references Ranke J and Lehmann R (2015) To t-test or not to t-test, that is
+#' the question. XV Symposium on Pesticide Chemistry 2-4 September 2015,
+#' Piacenza, Italy
+#' http://chem.uft.uni-bremen.de/ranke/posters/piacenza_2015.pdf
+#' @examples
+#'
+#' # The kinetic model
+#' m_SFO_SFO <- mkinmod(parent = mkinsub("SFO", "M1"),
+#' M1 = mkinsub("SFO"), use_of_ff = "max")
+#'
+#' # Generate a prediction for a specific set of parameters
+#' sampling_times = c(0, 1, 3, 7, 14, 28, 60, 90, 120)
+#'
+#' # This is the prediction used for the "Type 2 datasets" on the Piacenza poster
+#' # from 2015
+#' d_SFO_SFO <- mkinpredict(m_SFO_SFO,
+#' c(k_parent = 0.1, f_parent_to_M1 = 0.5,
+#' k_M1 = log(2)/1000),
+#' c(parent = 100, M1 = 0),
+#' sampling_times)
+#'
+#' # Add an error term with a constant (independent of the value) standard deviation
+#' # of 10, and generate three datasets
+#' d_SFO_SFO_err <- add_err(d_SFO_SFO, function(x) 10, n = 3, seed = 123456789 )
+#'
+#' # Name the datasets for nicer plotting
+#' names(d_SFO_SFO_err) <- paste("Dataset", 1:3)
+#'
+#' # Name the model in the list of models (with only one member in this case) for
+#' # nicer plotting later on. Be quiet and use only one core not to offend CRAN
+#' # checks
+#' \dontrun{
+#' f_SFO_SFO <- mmkin(list("SFO-SFO" = m_SFO_SFO),
+#' d_SFO_SFO_err, cores = 1,
+#' quiet = TRUE)
+#'
+#' plot(f_SFO_SFO)
+#'
+#' # We would like to inspect the fit for dataset 3 more closely
+#' # Using double brackets makes the returned object an mkinfit object
+#' # instead of a list of mkinfit objects, so plot.mkinfit is used
+#' plot(f_SFO_SFO[[3]], show_residuals = TRUE)
+#'
+#' # If we use single brackets, we should give two indices (model and dataset),
+#' # and plot.mmkin is used
+#' plot(f_SFO_SFO[1, 3])
+#' }
+#'
+#' @export
+add_err <- function(prediction, sdfunc, secondary = c("M1", "M2"),
+ n = 1000, LOD = 0.1, reps = 2, digits = 1, seed = NA)
{
if (!is.na(seed)) set.seed(seed)
diff --git a/R/endpoints.R b/R/endpoints.R
index f8a44c4d..14beadea 100644
--- a/R/endpoints.R
+++ b/R/endpoints.R
@@ -1,178 +1,199 @@
-endpoints <- function(fit) {
- # Calculate dissipation times DT50 and DT90 and formation
- # fractions as well as SFORB eigenvalues from optimised parameters
- # Additional DT50 values are calculated from the FOMC DT90 and k1 and k2 from
- # HS and DFOP, as well as from Eigenvalues b1 and b2 of any SFORB models
- ep <- list()
- obs_vars <- fit$obs_vars
- parms.all <- c(fit$bparms.optim, fit$bparms.fixed)
- ep$ff <- vector()
- ep$SFORB <- vector()
- ep$distimes <- data.frame(DT50 = rep(NA, length(obs_vars)),
- DT90 = rep(NA, length(obs_vars)),
- row.names = obs_vars)
- for (obs_var in obs_vars) {
- type = names(fit$mkinmod$map[[obs_var]])[1]
-
- # Get formation fractions if directly fitted, and calculate remaining fraction to sink
- f_names = grep(paste("^f", obs_var, sep = "_"), names(parms.all), value=TRUE)
- if (length(f_names) > 0) {
- f_values = parms.all[f_names]
- f_to_sink = 1 - sum(f_values)
- names(f_to_sink) = ifelse(type == "SFORB",
- paste(obs_var, "free", "sink", sep = "_"),
- paste(obs_var, "sink", sep = "_"))
- for (f_name in f_names) {
- ep$ff[[sub("f_", "", sub("_to_", "_", f_name))]] = f_values[[f_name]]
- }
- ep$ff = append(ep$ff, f_to_sink)
- }
-
- # Get the rest
- if (type == "SFO") {
- k_names = grep(paste("^k", obs_var, sep="_"), names(parms.all), value=TRUE)
- k_tot = sum(parms.all[k_names])
- DT50 = log(2)/k_tot
- DT90 = log(10)/k_tot
- if (fit$mkinmod$use_of_ff == "min") {
- for (k_name in k_names)
- {
- ep$ff[[sub("k_", "", k_name)]] = parms.all[[k_name]] / k_tot
- }
- }
- }
- if (type == "FOMC") {
- alpha = parms.all["alpha"]
- beta = parms.all["beta"]
- DT50 = beta * (2^(1/alpha) - 1)
- DT90 = beta * (10^(1/alpha) - 1)
- DT50_back = DT90 / (log(10)/log(2)) # Backcalculated DT50 as recommended in FOCUS 2011
- ep$distimes[obs_var, c("DT50back")] = DT50_back
- }
- if (type == "IORE") {
- k_names = grep(paste("^k__iore", obs_var, sep="_"), names(parms.all), value=TRUE)
- k_tot = sum(parms.all[k_names])
- # From the NAFTA kinetics guidance, p. 5
- n = parms.all[paste("N", obs_var, sep = "_")]
- k = k_tot
- # Use the initial concentration of the parent compound
- source_name = fit$mkinmod$map[[1]][[1]]
- c0 = parms.all[paste(source_name, "0", sep = "_")]
- alpha = 1 / (n - 1)
- beta = (c0^(1 - n))/(k * (n - 1))
- DT50 = beta * (2^(1/alpha) - 1)
- DT90 = beta * (10^(1/alpha) - 1)
- DT50_back = DT90 / (log(10)/log(2)) # Backcalculated DT50 as recommended in FOCUS 2011
- ep$distimes[obs_var, c("DT50back")] = DT50_back
- if (fit$mkinmod$use_of_ff == "min") {
- for (k_name in k_names)
- {
- ep$ff[[sub("k_", "", k_name)]] = parms.all[[k_name]] / k_tot
- }
- }
- }
- if (type == "DFOP") {
- k1 = parms.all["k1"]
- k2 = parms.all["k2"]
- g = parms.all["g"]
- f <- function(log_t, x) {
- t <- exp(log_t)
- fraction <- g * exp( - k1 * t) + (1 - g) * exp( - k2 * t)
- (fraction - (1 - x/100))^2
- }
- DT50_k1 = log(2)/k1
- DT50_k2 = log(2)/k2
- DT90_k1 = log(10)/k1
- DT90_k2 = log(10)/k2
-
- DT50 <- try(exp(optimize(f, c(log(DT50_k1), log(DT50_k2)), x=50)$minimum),
- silent = TRUE)
- DT90 <- try(exp(optimize(f, c(log(DT90_k1), log(DT90_k2)), x=90)$minimum),
- silent = TRUE)
- if (inherits(DT50, "try-error")) DT50 = NA
- if (inherits(DT90, "try-error")) DT90 = NA
-
- ep$distimes[obs_var, c("DT50_k1")] = DT50_k1
- ep$distimes[obs_var, c("DT50_k2")] = DT50_k2
- }
- if (type == "HS") {
- k1 = parms.all["k1"]
- k2 = parms.all["k2"]
- tb = parms.all["tb"]
- DTx <- function(x) {
- DTx.a <- (log(100/(100 - x)))/k1
- DTx.b <- tb + (log(100/(100 - x)) - k1 * tb)/k2
- if (DTx.a < tb) DTx <- DTx.a
- else DTx <- DTx.b
- return(DTx)
- }
- DT50 <- DTx(50)
- DT90 <- DTx(90)
- DT50_k1 = log(2)/k1
- DT50_k2 = log(2)/k2
- ep$distimes[obs_var, c("DT50_k1")] = DT50_k1
- ep$distimes[obs_var, c("DT50_k2")] = DT50_k2
- }
- if (type == "SFORB") {
- # FOCUS kinetics (2006), p. 60 f
- k_out_names = grep(paste("^k", obs_var, "free", sep="_"), names(parms.all), value=TRUE)
- k_out_names = setdiff(k_out_names, paste("k", obs_var, "free", "bound", sep="_"))
- k_1output = sum(parms.all[k_out_names])
- k_12 = parms.all[paste("k", obs_var, "free", "bound", sep="_")]
- k_21 = parms.all[paste("k", obs_var, "bound", "free", sep="_")]
-
- sqrt_exp = sqrt(1/4 * (k_12 + k_21 + k_1output)^2 + k_12 * k_21 - (k_12 + k_1output) * k_21)
- b1 = 0.5 * (k_12 + k_21 + k_1output) + sqrt_exp
- b2 = 0.5 * (k_12 + k_21 + k_1output) - sqrt_exp
-
- DT50_b1 = log(2)/b1
- DT50_b2 = log(2)/b2
- DT90_b1 = log(10)/b1
- DT90_b2 = log(10)/b2
-
- SFORB_fraction = function(t) {
- ((k_12 + k_21 - b1)/(b2 - b1)) * exp(-b1 * t) +
- ((k_12 + k_21 - b2)/(b1 - b2)) * exp(-b2 * t)
- }
-
- f_50 <- function(log_t) (SFORB_fraction(exp(log_t)) - 0.5)^2
- log_DT50 <- try(optimize(f_50, c(log(DT50_b1), log(DT50_b2)))$minimum,
- silent = TRUE)
- f_90 <- function(log_t) (SFORB_fraction(exp(log_t)) - 0.1)^2
- log_DT90 <- try(optimize(f_90, c(log(DT90_b1), log(DT90_b2)))$minimum,
- silent = TRUE)
-
- DT50 = if (inherits(log_DT50, "try-error")) NA
- else exp(log_DT50)
- DT90 = if (inherits(log_DT90, "try-error")) NA
- else exp(log_DT90)
-
- for (k_out_name in k_out_names)
- {
- ep$ff[[sub("k_", "", k_out_name)]] = parms.all[[k_out_name]] / k_1output
- }
-
- # Return the eigenvalues for comparison with DFOP rate constants
- ep$SFORB[[paste(obs_var, "b1", sep="_")]] = b1
- ep$SFORB[[paste(obs_var, "b2", sep="_")]] = b2
-
- ep$distimes[obs_var, c(paste("DT50", obs_var, "b1", sep = "_"))] = DT50_b1
- ep$distimes[obs_var, c(paste("DT50", obs_var, "b2", sep = "_"))] = DT50_b2
- }
- if (type == "logistic") {
- # FOCUS kinetics (2014) p. 67
- kmax = parms.all["kmax"]
- k0 = parms.all["k0"]
- r = parms.all["r"]
- DT50 = (1/r) * log(1 - ((kmax/k0) * (1 - 2^(r/kmax))))
- DT90 = (1/r) * log(1 - ((kmax/k0) * (1 - 10^(r/kmax))))
-
- DT50_k0 = log(2)/k0
- DT50_kmax = log(2)/kmax
- ep$distimes[obs_var, c("DT50_k0")] = DT50_k0
- ep$distimes[obs_var, c("DT50_kmax")] = DT50_kmax
- }
- ep$distimes[obs_var, c("DT50", "DT90")] = c(DT50, DT90)
- }
- return(ep)
-}
+#' Function to calculate endpoints for further use from kinetic models fitted
+#' with mkinfit
+#'
+#' This function calculates DT50 and DT90 values as well as formation fractions
+#' from kinetic models fitted with mkinfit. If the SFORB model was specified
+#' for one of the parents or metabolites, the Eigenvalues are returned. These
+#' are equivalent to the rate constantes of the DFOP model, but with the
+#' advantage that the SFORB model can also be used for metabolites.
+#'
+#' @param fit An object of class \code{\link{mkinfit}}.
+#' @importFrom stats optimize
+#' @return A list with the components mentioned above.
+#' @note The function is used internally by \code{\link{summary.mkinfit}}.
+#' @author Johannes Ranke
+#' @keywords manip
+#' @examples
+#'
+#' fit <- mkinfit("FOMC", FOCUS_2006_C, quiet = TRUE)
+#' endpoints(fit)
+#'
+#' @export
+endpoints <- function(fit) {
+ # Calculate dissipation times DT50 and DT90 and formation
+ # fractions as well as SFORB eigenvalues from optimised parameters
+ # Additional DT50 values are calculated from the FOMC DT90 and k1 and k2 from
+ # HS and DFOP, as well as from Eigenvalues b1 and b2 of any SFORB models
+ ep <- list()
+ obs_vars <- fit$obs_vars
+ parms.all <- c(fit$bparms.optim, fit$bparms.fixed)
+ ep$ff <- vector()
+ ep$SFORB <- vector()
+ ep$distimes <- data.frame(DT50 = rep(NA, length(obs_vars)),
+ DT90 = rep(NA, length(obs_vars)),
+ row.names = obs_vars)
+ for (obs_var in obs_vars) {
+ type = names(fit$mkinmod$map[[obs_var]])[1]
+
+ # Get formation fractions if directly fitted, and calculate remaining fraction to sink
+ f_names = grep(paste("^f", obs_var, sep = "_"), names(parms.all), value=TRUE)
+ if (length(f_names) > 0) {
+ f_values = parms.all[f_names]
+ f_to_sink = 1 - sum(f_values)
+ names(f_to_sink) = ifelse(type == "SFORB",
+ paste(obs_var, "free", "sink", sep = "_"),
+ paste(obs_var, "sink", sep = "_"))
+ for (f_name in f_names) {
+ ep$ff[[sub("f_", "", sub("_to_", "_", f_name))]] = f_values[[f_name]]
+ }
+ ep$ff = append(ep$ff, f_to_sink)
+ }
+
+ # Get the rest
+ if (type == "SFO") {
+ k_names = grep(paste("^k", obs_var, sep="_"), names(parms.all), value=TRUE)
+ k_tot = sum(parms.all[k_names])
+ DT50 = log(2)/k_tot
+ DT90 = log(10)/k_tot
+ if (fit$mkinmod$use_of_ff == "min") {
+ for (k_name in k_names)
+ {
+ ep$ff[[sub("k_", "", k_name)]] = parms.all[[k_name]] / k_tot
+ }
+ }
+ }
+ if (type == "FOMC") {
+ alpha = parms.all["alpha"]
+ beta = parms.all["beta"]
+ DT50 = beta * (2^(1/alpha) - 1)
+ DT90 = beta * (10^(1/alpha) - 1)
+ DT50_back = DT90 / (log(10)/log(2)) # Backcalculated DT50 as recommended in FOCUS 2011
+ ep$distimes[obs_var, c("DT50back")] = DT50_back
+ }
+ if (type == "IORE") {
+ k_names = grep(paste("^k__iore", obs_var, sep="_"), names(parms.all), value=TRUE)
+ k_tot = sum(parms.all[k_names])
+ # From the NAFTA kinetics guidance, p. 5
+ n = parms.all[paste("N", obs_var, sep = "_")]
+ k = k_tot
+ # Use the initial concentration of the parent compound
+ source_name = fit$mkinmod$map[[1]][[1]]
+ c0 = parms.all[paste(source_name, "0", sep = "_")]
+ alpha = 1 / (n - 1)
+ beta = (c0^(1 - n))/(k * (n - 1))
+ DT50 = beta * (2^(1/alpha) - 1)
+ DT90 = beta * (10^(1/alpha) - 1)
+ DT50_back = DT90 / (log(10)/log(2)) # Backcalculated DT50 as recommended in FOCUS 2011
+ ep$distimes[obs_var, c("DT50back")] = DT50_back
+ if (fit$mkinmod$use_of_ff == "min") {
+ for (k_name in k_names)
+ {
+ ep$ff[[sub("k_", "", k_name)]] = parms.all[[k_name]] / k_tot
+ }
+ }
+ }
+ if (type == "DFOP") {
+ k1 = parms.all["k1"]
+ k2 = parms.all["k2"]
+ g = parms.all["g"]
+ f <- function(log_t, x) {
+ t <- exp(log_t)
+ fraction <- g * exp( - k1 * t) + (1 - g) * exp( - k2 * t)
+ (fraction - (1 - x/100))^2
+ }
+ DT50_k1 = log(2)/k1
+ DT50_k2 = log(2)/k2
+ DT90_k1 = log(10)/k1
+ DT90_k2 = log(10)/k2
+
+ DT50 <- try(exp(optimize(f, c(log(DT50_k1), log(DT50_k2)), x=50)$minimum),
+ silent = TRUE)
+ DT90 <- try(exp(optimize(f, c(log(DT90_k1), log(DT90_k2)), x=90)$minimum),
+ silent = TRUE)
+ if (inherits(DT50, "try-error")) DT50 = NA
+ if (inherits(DT90, "try-error")) DT90 = NA
+
+ ep$distimes[obs_var, c("DT50_k1")] = DT50_k1
+ ep$distimes[obs_var, c("DT50_k2")] = DT50_k2
+ }
+ if (type == "HS") {
+ k1 = parms.all["k1"]
+ k2 = parms.all["k2"]
+ tb = parms.all["tb"]
+ DTx <- function(x) {
+ DTx.a <- (log(100/(100 - x)))/k1
+ DTx.b <- tb + (log(100/(100 - x)) - k1 * tb)/k2
+ if (DTx.a < tb) DTx <- DTx.a
+ else DTx <- DTx.b
+ return(DTx)
+ }
+ DT50 <- DTx(50)
+ DT90 <- DTx(90)
+ DT50_k1 = log(2)/k1
+ DT50_k2 = log(2)/k2
+ ep$distimes[obs_var, c("DT50_k1")] = DT50_k1
+ ep$distimes[obs_var, c("DT50_k2")] = DT50_k2
+ }
+ if (type == "SFORB") {
+ # FOCUS kinetics (2006), p. 60 f
+ k_out_names = grep(paste("^k", obs_var, "free", sep="_"), names(parms.all), value=TRUE)
+ k_out_names = setdiff(k_out_names, paste("k", obs_var, "free", "bound", sep="_"))
+ k_1output = sum(parms.all[k_out_names])
+ k_12 = parms.all[paste("k", obs_var, "free", "bound", sep="_")]
+ k_21 = parms.all[paste("k", obs_var, "bound", "free", sep="_")]
+
+ sqrt_exp = sqrt(1/4 * (k_12 + k_21 + k_1output)^2 + k_12 * k_21 - (k_12 + k_1output) * k_21)
+ b1 = 0.5 * (k_12 + k_21 + k_1output) + sqrt_exp
+ b2 = 0.5 * (k_12 + k_21 + k_1output) - sqrt_exp
+
+ DT50_b1 = log(2)/b1
+ DT50_b2 = log(2)/b2
+ DT90_b1 = log(10)/b1
+ DT90_b2 = log(10)/b2
+
+ SFORB_fraction = function(t) {
+ ((k_12 + k_21 - b1)/(b2 - b1)) * exp(-b1 * t) +
+ ((k_12 + k_21 - b2)/(b1 - b2)) * exp(-b2 * t)
+ }
+
+ f_50 <- function(log_t) (SFORB_fraction(exp(log_t)) - 0.5)^2
+ log_DT50 <- try(optimize(f_50, c(log(DT50_b1), log(DT50_b2)))$minimum,
+ silent = TRUE)
+ f_90 <- function(log_t) (SFORB_fraction(exp(log_t)) - 0.1)^2
+ log_DT90 <- try(optimize(f_90, c(log(DT90_b1), log(DT90_b2)))$minimum,
+ silent = TRUE)
+
+ DT50 = if (inherits(log_DT50, "try-error")) NA
+ else exp(log_DT50)
+ DT90 = if (inherits(log_DT90, "try-error")) NA
+ else exp(log_DT90)
+
+ for (k_out_name in k_out_names)
+ {
+ ep$ff[[sub("k_", "", k_out_name)]] = parms.all[[k_out_name]] / k_1output
+ }
+
+ # Return the eigenvalues for comparison with DFOP rate constants
+ ep$SFORB[[paste(obs_var, "b1", sep="_")]] = b1
+ ep$SFORB[[paste(obs_var, "b2", sep="_")]] = b2
+
+ ep$distimes[obs_var, c(paste("DT50", obs_var, "b1", sep = "_"))] = DT50_b1
+ ep$distimes[obs_var, c(paste("DT50", obs_var, "b2", sep = "_"))] = DT50_b2
+ }
+ if (type == "logistic") {
+ # FOCUS kinetics (2014) p. 67
+ kmax = parms.all["kmax"]
+ k0 = parms.all["k0"]
+ r = parms.all["r"]
+ DT50 = (1/r) * log(1 - ((kmax/k0) * (1 - 2^(r/kmax))))
+ DT90 = (1/r) * log(1 - ((kmax/k0) * (1 - 10^(r/kmax))))
+
+ DT50_k0 = log(2)/k0
+ DT50_kmax = log(2)/kmax
+ ep$distimes[obs_var, c("DT50_k0")] = DT50_k0
+ ep$distimes[obs_var, c("DT50_kmax")] = DT50_kmax
+ }
+ ep$distimes[obs_var, c("DT50", "DT90")] = c(DT50, DT90)
+ }
+ return(ep)
+}
diff --git a/R/ilr.R b/R/ilr.R
index 620afc49..e3102cbc 100644
--- a/R/ilr.R
+++ b/R/ilr.R
@@ -1,6 +1,3 @@
-# Copyright (C) 2012 René Lehmann, Johannes Ranke
-# Contact: jranke@uni-bremen.de
-
# This file is part of the R package mkin
# mkin is free software: you can redistribute it and/or modify it under the
@@ -16,6 +13,47 @@
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>
+#' Function to perform isometric log-ratio transformation
+#'
+#' This implementation is a special case of the class of isometric log-ratio
+#' transformations.
+#'
+#' @aliases ilr invilr
+#' @param x A numeric vector. Naturally, the forward transformation is only
+#' sensible for vectors with all elements being greater than zero.
+#' @return The result of the forward or backward transformation. The returned
+#' components always sum to 1 for the case of the inverse log-ratio
+#' transformation.
+#' @author René Lehmann and Johannes Ranke
+#' @seealso Another implementation can be found in R package
+#' \code{robCompositions}.
+#' @references Peter Filzmoser, Karel Hron (2008) Outlier Detection for
+#' Compositional Data Using Robust Methods. Math Geosci 40 233-248
+#' @keywords manip
+#' @examples
+#'
+#' # Order matters
+#' ilr(c(0.1, 1, 10))
+#' ilr(c(10, 1, 0.1))
+#' # Equal entries give ilr transformations with zeros as elements
+#' ilr(c(3, 3, 3))
+#' # Almost equal entries give small numbers
+#' ilr(c(0.3, 0.4, 0.3))
+#' # Only the ratio between the numbers counts, not their sum
+#' invilr(ilr(c(0.7, 0.29, 0.01)))
+#' invilr(ilr(2.1 * c(0.7, 0.29, 0.01)))
+#' # Inverse transformation of larger numbers gives unequal elements
+#' invilr(-10)
+#' invilr(c(-10, 0))
+#' # The sum of the elements of the inverse ilr is 1
+#' sum(invilr(c(-10, 0)))
+#' # This is why we do not need all elements of the inverse transformation to go back:
+#' a <- c(0.1, 0.3, 0.5)
+#' b <- invilr(a)
+#' length(b) # Four elements
+#' ilr(c(b[1:3], 1 - sum(b[1:3]))) # Gives c(0.1, 0.3, 0.5)
+#'
+#' @export
ilr <- function(x) {
z <- vector()
for (i in 1:(length(x) - 1)) {
@@ -24,6 +62,8 @@ ilr <- function(x) {
return(z)
}
+#' @rdname ilr
+#' @export
invilr<-function(x) {
D <- length(x) + 1
z <- c(x, 0)
diff --git a/R/logLik.mkinfit.R b/R/logLik.mkinfit.R
index d812f177..4ec3d7d4 100644
--- a/R/logLik.mkinfit.R
+++ b/R/logLik.mkinfit.R
@@ -1,24 +1,40 @@
-# Copyright (C) 2018,2019 Johannes Ranke
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
+#' Calculated the log-likelihood of a fitted mkinfit object
+#'
+#' This function simply calculates the product of the likelihood densities
+#' calculated using \code{\link{dnorm}}, i.e. assuming normal distribution,
+#' with of the mean predicted by the degradation model, and the standard
+#' deviation predicted by the error model.
+#'
+#' The total number of estimated parameters returned with the value of the
+#' likelihood is calculated as the sum of fitted degradation model parameters
+#' and the fitted error model parameters.
+#'
+#' @param object An object of class \code{\link{mkinfit}}.
+#' @param \dots For compatibility with the generic method
+#' @return An object of class \code{\link{logLik}} with the number of estimated
+#' parameters (degradation model parameters plus variance model parameters)
+#' as attribute.
+#' @author Johannes Ranke
+#' @seealso Compare the AIC of columns of \code{\link{mmkin}} objects using
+#' \code{\link{AIC.mmkin}}.
+#' @examples
+#'
+#' \dontrun{
+#' sfo_sfo <- mkinmod(
+#' parent = mkinsub("SFO", to = "m1"),
+#' m1 = mkinsub("SFO")
+#' )
+#' d_t <- FOCUS_2006_D
+#' f_nw <- mkinfit(sfo_sfo, d_t, quiet = TRUE) # no weighting (weights are unity)
+#' f_obs <- mkinfit(sfo_sfo, d_t, error_model = "obs", quiet = TRUE)
+#' f_tc <- mkinfit(sfo_sfo, d_t, error_model = "tc", quiet = TRUE)
+#' AIC(f_nw, f_obs, f_tc)
+#' }
+#'
+#' @export
logLik.mkinfit <- function(object, ...) {
val <- object$logLik
# Number of estimated parameters
attr(val, "df") <- length(object$bparms.optim) + length(object$errparms)
return(val)
}
-# vim: set ts=2 sw=2 expandtab:
diff --git a/R/logistic.solution.R b/R/logistic.solution.R
index a3bddab3..d9db13d7 100644
--- a/R/logistic.solution.R
+++ b/R/logistic.solution.R
@@ -1,3 +1,58 @@
+#' Logistic kinetics
+#'
+#' Function describing exponential decline from a defined starting value, with
+#' an increasing rate constant, supposedly caused by microbial growth
+#'
+#' @param t Time.
+#' @param parent.0 Starting value for the response variable at time zero.
+#' @param kmax Maximum rate constant.
+#' @param k0 Minumum rate constant effective at time zero.
+#' @param r Growth rate of the increase in the rate constant.
+#' @return The value of the response variable at time \code{t}.
+#' @note The solution of the logistic model reduces to the
+#' \code{\link{SFO.solution}} if \code{k0} is equal to \code{kmax}.
+#' @references FOCUS (2014) \dQuote{Generic guidance for Estimating Persistence
+#' and Degradation Kinetics from Environmental Fate Studies on Pesticides in
+#' EU Registration} Report of the FOCUS Work Group on Degradation Kinetics,
+#' Version 1.1, 18 December 2014
+#' \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+#' @examples
+#'
+#' # Reproduce the plot on page 57 of FOCUS (2014)
+#' plot(function(x) logistic.solution(x, 100, 0.08, 0.0001, 0.2),
+#' from = 0, to = 100, ylim = c(0, 100),
+#' xlab = "Time", ylab = "Residue")
+#' plot(function(x) logistic.solution(x, 100, 0.08, 0.0001, 0.4),
+#' from = 0, to = 100, add = TRUE, lty = 2, col = 2)
+#' plot(function(x) logistic.solution(x, 100, 0.08, 0.0001, 0.8),
+#' from = 0, to = 100, add = TRUE, lty = 3, col = 3)
+#' plot(function(x) logistic.solution(x, 100, 0.08, 0.001, 0.2),
+#' from = 0, to = 100, add = TRUE, lty = 4, col = 4)
+#' plot(function(x) logistic.solution(x, 100, 0.08, 0.08, 0.2),
+#' from = 0, to = 100, add = TRUE, lty = 5, col = 5)
+#' legend("topright", inset = 0.05,
+#' legend = paste0("k0 = ", c(0.0001, 0.0001, 0.0001, 0.001, 0.08),
+#' ", r = ", c(0.2, 0.4, 0.8, 0.2, 0.2)),
+#' lty = 1:5, col = 1:5)
+#'
+#' # Fit with synthetic data
+#' logistic <- mkinmod(parent = mkinsub("logistic"))
+#'
+#' sampling_times = c(0, 1, 3, 7, 14, 28, 60, 90, 120)
+#' parms_logistic <- c(kmax = 0.08, k0 = 0.0001, r = 0.2)
+#' d_logistic <- mkinpredict(logistic,
+#' parms_logistic, c(parent = 100),
+#' sampling_times)
+#' d_2_1 <- add_err(d_logistic,
+#' sdfunc = function(x) sigma_twocomp(x, 0.5, 0.07),
+#' n = 1, reps = 2, digits = 5, LOD = 0.1, seed = 123456)[[1]]
+#'
+#' m <- mkinfit("logistic", d_2_1, quiet = TRUE)
+#' plot_sep(m)
+#' summary(m)$bpar
+#' endpoints(m)$distimes
+#'
+#' @export
logistic.solution <- function(t, parent.0, kmax, k0, r)
{
parent = parent.0 * (kmax / (kmax - k0 + k0 * exp (r * t))) ^(kmax/r)
diff --git a/R/max_twa_parent.R b/R/max_twa_parent.R
index 5129e369..ef3c0ada 100644
--- a/R/max_twa_parent.R
+++ b/R/max_twa_parent.R
@@ -1,21 +1,43 @@
-# Copyright (C) 2016-2019 Johannes Ranke
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
-
+#' Function to calculate maximum time weighted average concentrations from
+#' kinetic models fitted with mkinfit
+#'
+#' This function calculates maximum moving window time weighted average
+#' concentrations (TWAs) for kinetic models fitted with \code{\link{mkinfit}}.
+#' Currently, only calculations for the parent are implemented for the SFO,
+#' FOMC, DFOP and HS models, using the analytical formulas given in the PEC
+#' soil section of the FOCUS guidance.
+#'
+#' @aliases max_twa_parent max_twa_sfo max_twa_fomc max_twa_dfop max_twa_hs
+#' @param fit An object of class \code{\link{mkinfit}}.
+#' @param windows The width of the time windows for which the TWAs should be
+#' calculated.
+#' @param M0 The initial concentration for which the maximum time weighted
+#' average over the decline curve should be calculated. The default is to use
+#' a value of 1, which means that a relative maximum time weighted average
+#' factor (f_twa) is calculated.
+#' @param k The rate constant in the case of SFO kinetics.
+#' @param t The width of the time window.
+#' @param alpha Parameter of the FOMC model.
+#' @param beta Parameter of the FOMC model.
+#' @param k1 The first rate constant of the DFOP or the HS kinetics.
+#' @param k2 The second rate constant of the DFOP or the HS kinetics.
+#' @param g Parameter of the DFOP model.
+#' @param tb Parameter of the HS model.
+#' @return For \code{max_twa_parent}, a numeric vector, named using the
+#' \code{windows} argument. For the other functions, a numeric vector of
+#' length one (also known as 'a number').
+#' @author Johannes Ranke
+#' @references FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence
+#' and Degradation Kinetics from Environmental Fate Studies on Pesticides in
+#' EU Registration} Report of the FOCUS Work Group on Degradation Kinetics,
+#' EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
+#' \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+#' @examples
+#'
+#' fit <- mkinfit("FOMC", FOCUS_2006_C, quiet = TRUE)
+#' max_twa_parent(fit, c(7, 21))
+#'
+#' @export
max_twa_parent <- function(fit, windows) {
parms.all <- c(fit$bparms.optim, fit$bparms.fixed)
obs_vars <- fit$obs_vars
@@ -74,15 +96,27 @@ max_twa_parent <- function(fit, windows) {
names(res) <- windows
return(res)
}
+
+#' @rdname max_twa_parent
+#' @export
max_twa_sfo <- function(M0 = 1, k, t) {
M0 * (1 - exp(- k * t)) / (k * t)
}
+
+#' @rdname max_twa_parent
+#' @export
max_twa_fomc <- function(M0 = 1, alpha, beta, t) {
M0 * (beta)/(t * (1 - alpha)) * ((t/beta + 1)^(1 - alpha) - 1)
}
+
+#' @rdname max_twa_parent
+#' @export
max_twa_dfop <- function(M0 = 1, k1, k2, g, t) {
M0/t * ((g/k1) * (1 - exp(- k1 * t)) + ((1 - g)/k2) * (1 - exp(- k2 * t)))
}
+
+#' @rdname max_twa_parent
+#' @export
max_twa_hs <- function(M0 = 1, k1, k2, tb, t) {
(M0 / t) * (
(1/k1) * (1 - exp(- k1 * tb)) +
diff --git a/R/mkin_long_to_wide.R b/R/mkin_long_to_wide.R
index 081262f8..0125f2da 100644
--- a/R/mkin_long_to_wide.R
+++ b/R/mkin_long_to_wide.R
@@ -1,28 +1,29 @@
-# Copyright (C) 2010-2011 Johannes Ranke
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
-
-mkin_long_to_wide <- function(long_data, time = "time", outtime = "time")
-{
- colnames <- unique(long_data$name)
- wide_data <- data.frame(time = subset(long_data, name == colnames[1], time))
- names(wide_data) <- outtime
- for (var in colnames) {
- wide_data[var] <- subset(long_data, name == var, value)
- }
- return(wide_data)
-}
+#' Convert a dataframe from long to wide format
+#'
+#' This function takes a dataframe in the long form, i.e. with a row for each
+#' observed value, and converts it into a dataframe with one independent
+#' variable and several dependent variables as columns.
+#'
+#' @param long_data The dataframe must contain one variable called "time" with
+#' the time values specified by the \code{time} argument, one column called
+#' "name" with the grouping of the observed values, and finally one column of
+#' observed values called "value".
+#' @param time The name of the time variable in the long input data.
+#' @param outtime The name of the time variable in the wide output data.
+#' @return Dataframe in wide format.
+#' @author Johannes Ranke
+#' @examples
+#'
+#' mkin_long_to_wide(FOCUS_2006_D)
+#'
+#' @export mkin_long_to_wide
+mkin_long_to_wide <- function(long_data, time = "time", outtime = "time")
+{
+ colnames <- unique(long_data$name)
+ wide_data <- data.frame(time = subset(long_data, name == colnames[1], time))
+ names(wide_data) <- outtime
+ for (var in colnames) {
+ wide_data[var] <- subset(long_data, name == var, value)
+ }
+ return(wide_data)
+}
diff --git a/R/mkin_wide_to_long.R b/R/mkin_wide_to_long.R
index 21a7cbe9..bef0e408 100644
--- a/R/mkin_wide_to_long.R
+++ b/R/mkin_wide_to_long.R
@@ -1,34 +1,34 @@
-# $Id$
-
-# Copyright (C) 2010-2013 Johannes Ranke
-# Contact: mkin-devel@lists.berlios.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
-if(getRversion() >= '2.15.1') utils::globalVariables(c("name", "time", "value"))
-
-mkin_wide_to_long <- function(wide_data, time = "t")
-{
- colnames <- names(wide_data)
- if (!(time %in% colnames)) stop("The data in wide format have to contain a variable named ", time, ".")
- vars <- subset(colnames, colnames != time)
- n <- length(colnames) - 1
- long_data <- data.frame(
- name = rep(vars, each = length(wide_data[[time]])),
- time = as.numeric(rep(wide_data[[time]], n)),
- value = as.numeric(unlist(wide_data[vars])),
- row.names = NULL)
- return(long_data)
-}
+if(getRversion() >= '2.15.1') utils::globalVariables(c("name", "time", "value"))
+
+#' Convert a dataframe with observations over time into long format
+#'
+#' This function simply takes a dataframe with one independent variable and
+#' several dependent variable and converts it into the long form as required by
+#' \code{\link{mkinfit}}.
+#'
+#' @param wide_data The dataframe must contain one variable with the time
+#' values specified by the \code{time} argument and usually more than one
+#' column of observed values.
+#' @param time The name of the time variable.
+#' @return Dataframe in long format as needed for \code{\link{mkinfit}}.
+#' @author Johannes Ranke
+#' @keywords manip
+#' @examples
+#'
+#' wide <- data.frame(t = c(1,2,3), x = c(1,4,7), y = c(3,4,5))
+#' mkin_wide_to_long(wide)
+#'
+#' @export
+mkin_wide_to_long <- function(wide_data, time = "t")
+{
+ colnames <- names(wide_data)
+ if (!(time %in% colnames)) stop("The data in wide format have to contain a variable named ", time, ".")
+ vars <- subset(colnames, colnames != time)
+ n <- length(colnames) - 1
+ long_data <- data.frame(
+ name = rep(vars, each = length(wide_data[[time]])),
+ time = as.numeric(rep(wide_data[[time]], n)),
+ value = as.numeric(unlist(wide_data[vars])),
+ row.names = NULL)
+ return(long_data)
+}
diff --git a/R/mkinds.R b/R/mkinds.R
index 5333ca26..a66adb14 100644
--- a/R/mkinds.R
+++ b/R/mkinds.R
@@ -1,21 +1,33 @@
-# Copyright (C) 2015,2018,2019 Johannes Ranke
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
-
+#' A dataset class for mkin
+#'
+#' A dataset class for mkin
+#'
+#' @name mkinds
+#' @docType class
+#' @format An \code{\link{R6Class}} generator object.
+#' @section Fields:
+#'
+#' \describe{ \item{list("title")}{A full title for the dataset}
+#'
+#' \item{list("sampling")}{times The sampling times}
+#'
+#' \item{list("time_unit")}{The time unit}
+#'
+#' \item{list("observed")}{Names of the observed compounds}
+#'
+#' \item{list("unit")}{The unit of the observations}
+#'
+#' \item{list("replicates")}{The number of replicates}
+#'
+#' \item{list("data")}{A dataframe with at least the columns name, time and
+#' value in order to be compatible with mkinfit} }
+#' @importFrom R6 R6Class
+#' @keywords datasets
+#' @examples
+#'
+#' mds <- mkinds$new("FOCUS A", FOCUS_2006_A)
+#'
+#' @export
mkinds <- R6Class("mkinds",
public = list(
title = NULL,
@@ -42,6 +54,13 @@ mkinds <- R6Class("mkinds",
)
)
+#' Print mkinds objects
+#'
+#' Print mkinds objects.
+#'
+#' @param x An \code{\link{mkinds}} object.
+#' @param \dots Not used.
+#' @export
print.mkinds <- function(x, ...) {
cat("<mkinds> with $title: ", x$title, "\n")
cat("Observed compounds $observed: ", paste(x$observed, collapse = ", "), "\n")
diff --git a/R/mkinerrmin.R b/R/mkinerrmin.R
index ce4877d2..0b647b81 100644
--- a/R/mkinerrmin.R
+++ b/R/mkinerrmin.R
@@ -1,22 +1,43 @@
-# Copyright (C) 2010-2019 Johannes Ranke
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
if(getRversion() >= '2.15.1') utils::globalVariables(c("name", "value_mean"))
+#' Calculate the minimum error to assume in order to pass the variance test
+#'
+#' This function finds the smallest relative error still resulting in passing
+#' the chi-squared test as defined in the FOCUS kinetics report from 2006.
+#'
+#' This function is used internally by \code{\link{summary.mkinfit}}.
+#'
+#' @param fit an object of class \code{\link{mkinfit}}.
+#' @param alpha The confidence level chosen for the chi-squared test.
+#' @importFrom stats qchisq aggregate
+#' @return A dataframe with the following components: \item{err.min}{The
+#' relative error, expressed as a fraction.} \item{n.optim}{The number of
+#' optimised parameters attributed to the data series.} \item{df}{The number of
+#' remaining degrees of freedom for the chi2 error level calculations. Note
+#' that mean values are used for the chi2 statistic and therefore every time
+#' point with observed values in the series only counts one time.} The
+#' dataframe has one row for the total dataset and one further row for each
+#' observed state variable in the model.
+#' @references FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence
+#' and Degradation Kinetics from Environmental Fate Studies on Pesticides in EU
+#' Registration} Report of the FOCUS Work Group on Degradation Kinetics, EC
+#' Document Reference Sanco/10058/2005 version 2.0, 434 pp,
+#' \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+#' @keywords manip
+#' @examples
+#'
+#' SFO_SFO = mkinmod(parent = mkinsub("SFO", to = "m1"),
+#' m1 = mkinsub("SFO"),
+#' use_of_ff = "max")
+#'
+#' fit_FOCUS_D = mkinfit(SFO_SFO, FOCUS_2006_D, quiet = TRUE)
+#' round(mkinerrmin(fit_FOCUS_D), 4)
+#' \dontrun{
+#' fit_FOCUS_E = mkinfit(SFO_SFO, FOCUS_2006_E, quiet = TRUE)
+#' round(mkinerrmin(fit_FOCUS_E), 4)
+#' }
+#'
+#' @export
mkinerrmin <- function(fit, alpha = 0.05)
{
parms.optim <- fit$par
diff --git a/R/mkinerrplot.R b/R/mkinerrplot.R
index 6153a3c0..36e22a43 100644
--- a/R/mkinerrplot.R
+++ b/R/mkinerrplot.R
@@ -1,22 +1,44 @@
-# Copyright (C) 2008-2014,2019 Johannes Ranke
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
if(getRversion() >= '2.15.1') utils::globalVariables(c("variable", "residual"))
+#' Function to plot squared residuals and the error model for an mkin object
+#'
+#' This function plots the squared residuals for the specified subset of the
+#' observed variables from an mkinfit object. In addition, one or more dashed
+#' line(s) show the fitted error model. A combined plot of the fitted model
+#' and this error model plot can be obtained with \code{\link{plot.mkinfit}}
+#' using the argument \code{show_errplot = TRUE}.
+#'
+#' @param object A fit represented in an \code{\link{mkinfit}} object.
+#' @param obs_vars A character vector of names of the observed variables for
+#' which residuals should be plotted. Defaults to all observed variables in
+#' the model
+#' @param xlim plot range in x direction.
+#' @param xlab Label for the x axis.
+#' @param ylab Label for the y axis.
+#' @param maxy Maximum value of the residuals. This is used for the scaling of
+#' the y axis and defaults to "auto".
+#' @param legend Should a legend be plotted?
+#' @param lpos Where should the legend be placed? Default is "topright". Will
+#' be passed on to \code{\link{legend}}.
+#' @param col_obs Colors for the observed variables.
+#' @param pch_obs Symbols to be used for the observed variables.
+#' @param frame Should a frame be drawn around the plots?
+#' @param \dots further arguments passed to \code{\link{plot}}.
+#' @return Nothing is returned by this function, as it is called for its side
+#' effect, namely to produce a plot.
+#' @author Johannes Ranke
+#' @seealso \code{\link{mkinplot}}, for a way to plot the data and the fitted
+#' lines of the mkinfit object.
+#' @keywords hplot
+#' @examples
+#'
+#' \dontrun{
+#' model <- mkinmod(parent = mkinsub("SFO", "m1"), m1 = mkinsub("SFO"))
+#' fit <- mkinfit(model, FOCUS_2006_D, error_model = "tc", quiet = TRUE)
+#' mkinerrplot(fit)
+#' }
+#'
+#' @export
mkinerrplot <- function (object,
obs_vars = names(object$mkinmod$map),
xlim = c(0, 1.1 * max(object$data$predicted)),
diff --git a/R/mkinfit.R b/R/mkinfit.R
index d182f5d0..17fd59d0 100644
--- a/R/mkinfit.R
+++ b/R/mkinfit.R
@@ -1,904 +1,897 @@
-# Copyright (C) 2010-2019 Johannes Ranke
-# Portions of this code are copyright (C) 2013 Eurofins Regulatory AG
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
-if(getRversion() >= '2.15.1') utils::globalVariables(c("name", "time", "value"))
-
-mkinfit <- function(mkinmod, observed,
- parms.ini = "auto",
- state.ini = "auto",
- err.ini = "auto",
- fixed_parms = NULL,
- fixed_initials = names(mkinmod$diffs)[-1],
- from_max_mean = FALSE,
- solution_type = c("auto", "analytical", "eigen", "deSolve"),
- method.ode = "lsoda",
- use_compiled = "auto",
- control = list(eval.max = 300, iter.max = 200),
- transform_rates = TRUE,
- transform_fractions = TRUE,
- quiet = FALSE,
- atol = 1e-8, rtol = 1e-10, n.outtimes = 100,
- error_model = c("const", "obs", "tc"),
- error_model_algorithm = c("auto", "d_3", "direct", "twostep", "threestep", "fourstep", "IRLS", "OLS"),
- reweight.tol = 1e-8, reweight.max.iter = 10,
- trace_parms = FALSE,
- ...)
-{
- # Check mkinmod and generate a model for the variable whith the highest value
- # if a suitable string is given
- parent_models_available = c("SFO", "FOMC", "DFOP", "HS", "SFORB", "IORE", "logistic")
- if (class(mkinmod) != "mkinmod") {
- presumed_parent_name = observed[which.max(observed$value), "name"]
- if (mkinmod[[1]] %in% parent_models_available) {
- speclist <- list(list(type = mkinmod, sink = TRUE))
- names(speclist) <- presumed_parent_name
- mkinmod <- mkinmod(speclist = speclist)
- } else {
- stop("Argument mkinmod must be of class mkinmod or a string containing one of\n ",
- paste(parent_models_available, collapse = ", "))
- }
- }
-
- # Get the names of the state variables in the model
- mod_vars <- names(mkinmod$diffs)
-
- # Get the names of observed variables
- obs_vars <- names(mkinmod$spec)
-
- # Subset observed data with names of observed data in the model and remove NA values
- observed <- subset(observed, name %in% obs_vars)
- observed <- subset(observed, !is.na(value))
-
- # Also remove zero values to avoid instabilities (e.g. of the 'tc' error model)
- if (any(observed$value == 0)) {
- warning("Observations with value of zero were removed from the data")
- observed <- subset(observed, value != 0)
- }
-
- # Obtain data for decline from maximum mean value if requested
- if (from_max_mean) {
- # This is only used for simple decline models
- if (length(obs_vars) > 1)
- stop("Decline from maximum is only implemented for models with a single observed variable")
-
- means <- aggregate(value ~ time, data = observed, mean, na.rm=TRUE)
- t_of_max <- means[which.max(means$value), "time"]
- observed <- subset(observed, time >= t_of_max)
- observed$time <- observed$time - t_of_max
- }
-
- # Number observations used for fitting
- n_observed <- nrow(observed)
-
- # Define starting values for parameters where not specified by the user
- if (parms.ini[[1]] == "auto") parms.ini = vector()
-
- # Warn for inital parameter specifications that are not in the model
- wrongpar.names <- setdiff(names(parms.ini), mkinmod$parms)
- if (length(wrongpar.names) > 0) {
- warning("Initial parameter(s) ", paste(wrongpar.names, collapse = ", "),
- " not used in the model")
- parms.ini <- parms.ini[setdiff(names(parms.ini), wrongpar.names)]
- }
-
- # Warn that the sum of formation fractions may exceed one if they are not
- # fitted in the transformed way
- if (mkinmod$use_of_ff == "max" & transform_fractions == FALSE) {
- warning("The sum of formation fractions may exceed one if you do not use ",
- "transform_fractions = TRUE." )
- for (box in mod_vars) {
- # Stop if formation fractions are not transformed and we have no sink
- if (mkinmod$spec[[box]]$sink == FALSE) {
- stop("If formation fractions are not transformed during the fitting, ",
- "it is not supported to turn off pathways to sink.\n ",
- "Consider turning on the transformation of formation fractions or ",
- "setting up a model with use_of_ff = 'min'.\n")
- }
- }
- }
-
- # Do not allow fixing formation fractions if we are using the ilr transformation,
- # this is not supported
- if (transform_fractions == TRUE && length(fixed_parms) > 0) {
- if (any(grepl("^f_", fixed_parms))) {
- stop("Fixing formation fractions is not supported when using the ilr ",
- "transformation.")
- }
- }
-
- # Set initial parameter values, including a small increment (salt)
- # to avoid linear dependencies (singular matrix) in Eigenvalue based solutions
- k_salt = 0
- defaultpar.names <- setdiff(mkinmod$parms, names(parms.ini))
- for (parmname in defaultpar.names) {
- # Default values for rate constants, depending on the parameterisation
- if (grepl("^k", parmname)) {
- parms.ini[parmname] = 0.1 + k_salt
- k_salt = k_salt + 1e-4
- }
- # Default values for rate constants for reversible binding
- if (grepl("free_bound$", parmname)) parms.ini[parmname] = 0.1
- if (grepl("bound_free$", parmname)) parms.ini[parmname] = 0.02
- # Default values for IORE exponents
- if (grepl("^N", parmname)) parms.ini[parmname] = 1.1
- # Default values for the FOMC, DFOP and HS models
- if (parmname == "alpha") parms.ini[parmname] = 1
- if (parmname == "beta") parms.ini[parmname] = 10
- if (parmname == "k1") parms.ini[parmname] = 0.1
- if (parmname == "k2") parms.ini[parmname] = 0.01
- if (parmname == "tb") parms.ini[parmname] = 5
- if (parmname == "g") parms.ini[parmname] = 0.5
- if (parmname == "kmax") parms.ini[parmname] = 0.1
- if (parmname == "k0") parms.ini[parmname] = 0.0001
- if (parmname == "r") parms.ini[parmname] = 0.2
- }
- # Default values for formation fractions in case they are present
- for (box in mod_vars) {
- f_names <- mkinmod$parms[grep(paste0("^f_", box), mkinmod$parms)]
- if (length(f_names) > 0) {
- # We need to differentiate between default and specified fractions
- # and set the unspecified to 1 - sum(specified)/n_unspecified
- f_default_names <- intersect(f_names, defaultpar.names)
- f_specified_names <- setdiff(f_names, defaultpar.names)
- sum_f_specified = sum(parms.ini[f_specified_names])
- if (sum_f_specified > 1) {
- stop("Starting values for the formation fractions originating from ",
- box, " sum up to more than 1.")
- }
- if (mkinmod$spec[[box]]$sink) n_unspecified = length(f_default_names) + 1
- else {
- n_unspecified = length(f_default_names)
- }
- parms.ini[f_default_names] <- (1 - sum_f_specified) / n_unspecified
- }
- }
-
- # Set default for state.ini if appropriate
- parent_name = names(mkinmod$spec)[[1]]
- if (state.ini[1] == "auto") {
- parent_time_0 = subset(observed, time == 0 & name == parent_name)$value
- parent_time_0_mean = mean(parent_time_0, na.rm = TRUE)
- if (is.na(parent_time_0_mean)) {
- state.ini = c(100, rep(0, length(mkinmod$diffs) - 1))
- } else {
- state.ini = c(parent_time_0_mean, rep(0, length(mkinmod$diffs) - 1))
- }
- }
-
- # Name the inital state variable values if they are not named yet
- if(is.null(names(state.ini))) names(state.ini) <- mod_vars
-
- # Transform initial parameter values for fitting
- transparms.ini <- transform_odeparms(parms.ini, mkinmod,
- transform_rates = transform_rates,
- transform_fractions = transform_fractions)
-
- # Parameters to be optimised:
- # Kinetic parameters in parms.ini whose names are not in fixed_parms
- parms.fixed <- parms.ini[fixed_parms]
- parms.optim <- parms.ini[setdiff(names(parms.ini), fixed_parms)]
-
- transparms.fixed <- transform_odeparms(parms.fixed, mkinmod,
- transform_rates = transform_rates,
- transform_fractions = transform_fractions)
- transparms.optim <- transform_odeparms(parms.optim, mkinmod,
- transform_rates = transform_rates,
- transform_fractions = transform_fractions)
-
- # Inital state variables in state.ini whose names are not in fixed_initials
- state.ini.fixed <- state.ini[fixed_initials]
- state.ini.optim <- state.ini[setdiff(names(state.ini), fixed_initials)]
-
- # Preserve names of state variables before renaming initial state variable
- # parameters
- state.ini.optim.boxnames <- names(state.ini.optim)
- state.ini.fixed.boxnames <- names(state.ini.fixed)
- if(length(state.ini.optim) > 0) {
- names(state.ini.optim) <- paste(names(state.ini.optim), "0", sep="_")
- }
- if(length(state.ini.fixed) > 0) {
- names(state.ini.fixed) <- paste(names(state.ini.fixed), "0", sep="_")
- }
-
- # Decide if the solution of the model can be based on a simple analytical
- # formula, the spectral decomposition of the matrix (fundamental system)
- # or a numeric ode solver from the deSolve package
- # Prefer deSolve over eigen if a compiled model is present and use_compiled
- # is not set to FALSE
- solution_type = match.arg(solution_type)
- if (solution_type == "analytical" && length(mkinmod$spec) > 1)
- stop("Analytical solution not implemented for models with metabolites.")
- if (solution_type == "eigen" && !is.matrix(mkinmod$coefmat))
- stop("Eigenvalue based solution not possible, coefficient matrix not present.")
- if (solution_type == "auto") {
- if (length(mkinmod$spec) == 1) {
- solution_type = "analytical"
- } else {
- if (!is.null(mkinmod$cf) & use_compiled[1] != FALSE) {
- solution_type = "deSolve"
- } else {
- if (is.matrix(mkinmod$coefmat)) {
- solution_type = "eigen"
- if (max(observed$value, na.rm = TRUE) < 0.1) {
- stop("The combination of small observed values (all < 0.1) and solution_type = eigen is error-prone")
- }
- } else {
- solution_type = "deSolve"
- }
- }
- }
- }
-
- # Get the error model and the algorithm for fitting
- err_mod <- match.arg(error_model)
- error_model_algorithm = match.arg(error_model_algorithm)
- if (error_model_algorithm == "OLS") {
- if (err_mod != "const") stop("OLS is only appropriate for constant variance")
- }
- if (error_model_algorithm == "auto") {
- error_model_algorithm = switch(err_mod,
- const = "OLS", obs = "d_3", tc = "d_3")
- }
- errparm_names <- switch(err_mod,
- "const" = "sigma",
- "obs" = paste0("sigma_", obs_vars),
- "tc" = c("sigma_low", "rsd_high"))
- errparm_names_optim <- if (error_model_algorithm == "OLS") NULL else errparm_names
-
- # Define starting values for the error model
- if (err.ini[1] != "auto") {
- if (!identical(names(err.ini), errparm_names)) {
- stop("Please supply initial values for error model components ", paste(errparm_names, collapse = ", "))
- } else {
- errparms = err.ini
- }
- } else {
- if (err_mod == "const") {
- errparms = 3
- }
- if (err_mod == "obs") {
- errparms = rep(3, length(obs_vars))
- }
- if (err_mod == "tc") {
- errparms <- c(sigma_low = 0.1, rsd_high = 0.1)
- }
- names(errparms) <- errparm_names
- }
- if (error_model_algorithm == "OLS") {
- errparms_optim <- NULL
- } else {
- errparms_optim <- errparms
- }
-
- # Define outtimes for model solution.
- # Include time points at which observed data are available
- outtimes = sort(unique(c(observed$time, seq(min(observed$time),
- max(observed$time),
- length.out = n.outtimes))))
-
- # Define the objective function for optimisation, including (back)transformations
- cost_function <- function(P, trans = TRUE, OLS = FALSE, fixed_degparms = FALSE, fixed_errparms = FALSE, update_data = TRUE, ...)
- {
- assign("calls", calls + 1, inherits = TRUE) # Increase the model solution counter
-
- # Trace parameter values if requested and if we are actually optimising
- if(trace_parms & update_data) cat(P, "\n")
-
- # Determine local parameter values for the cost estimation
- if (is.numeric(fixed_degparms)) {
- cost_degparms <- fixed_degparms
- cost_errparms <- P
- degparms_fixed = TRUE
- } else {
- degparms_fixed = FALSE
- }
-
- if (is.numeric(fixed_errparms)) {
- cost_degparms <- P
- cost_errparms <- fixed_errparms
- errparms_fixed = TRUE
- } else {
- errparms_fixed = FALSE
- }
-
- if (OLS) {
- cost_degparms <- P
- cost_errparms <- numeric(0)
- }
-
- if (!OLS & !degparms_fixed & !errparms_fixed) {
- cost_degparms <- P[1:(length(P) - length(errparms))]
- cost_errparms <- P[(length(cost_degparms) + 1):length(P)]
- }
-
- # Initial states for t0
- if(length(state.ini.optim) > 0) {
- odeini <- c(cost_degparms[1:length(state.ini.optim)], state.ini.fixed)
- names(odeini) <- c(state.ini.optim.boxnames, state.ini.fixed.boxnames)
- } else {
- odeini <- state.ini.fixed
- names(odeini) <- state.ini.fixed.boxnames
- }
-
- odeparms.optim <- cost_degparms[(length(state.ini.optim) + 1):length(cost_degparms)]
-
- if (trans == TRUE) {
- odeparms <- c(odeparms.optim, transparms.fixed)
- parms <- backtransform_odeparms(odeparms, mkinmod,
- transform_rates = transform_rates,
- transform_fractions = transform_fractions)
- } else {
- parms <- c(odeparms.optim, parms.fixed)
- }
-
- # Solve the system with current parameter values
- out <- mkinpredict(mkinmod, parms,
- odeini, outtimes,
- solution_type = solution_type,
- use_compiled = use_compiled,
- method.ode = method.ode,
- atol = atol, rtol = rtol, ...)
-
- out_long <- mkin_wide_to_long(out, time = "time")
-
- if (err_mod == "const") {
- observed$std <- if (OLS) NA else cost_errparms["sigma"]
- }
- if (err_mod == "obs") {
- std_names <- paste0("sigma_", observed$name)
- observed$std <- cost_errparms[std_names]
- }
- if (err_mod == "tc") {
- tmp <- merge(observed, out_long, by = c("time", "name"))
- tmp$name <- ordered(tmp$name, levels = obs_vars)
- tmp <- tmp[order(tmp$name, tmp$time), ]
- observed$std <- sqrt(cost_errparms["sigma_low"]^2 + tmp$value.y^2 * cost_errparms["rsd_high"]^2)
- }
-
- cost_data <- merge(observed[c("name", "time", "value", "std")], out_long,
- by = c("name", "time"), suffixes = c(".observed", ".predicted"))
-
- if (OLS) {
- # Cost is the sum of squared residuals
- cost <- with(cost_data, sum((value.observed - value.predicted)^2))
- } else {
- # Cost is the negative log-likelihood
- cost <- - with(cost_data,
- sum(dnorm(x = value.observed, mean = value.predicted, sd = std, log = TRUE)))
- }
-
- # We update the current cost and data during the optimisation, not
- # during hessian calculations
- if (update_data) {
-
- assign("out_predicted", out_long, inherits = TRUE)
- assign("current_data", cost_data, inherits = TRUE)
-
- if (cost < cost.current) {
- assign("cost.current", cost, inherits = TRUE)
- if (!quiet) cat(ifelse(OLS, "Sum of squared residuals", "Negative log-likelihood"),
- " at call ", calls, ": ", cost.current, "\n", sep = "")
- }
- }
- return(cost)
- }
-
- names_optim <- c(names(state.ini.optim),
- names(transparms.optim),
- errparm_names_optim)
- n_optim <- length(names_optim)
-
- # Define lower and upper bounds other than -Inf and Inf for parameters
- # for which no internal transformation is requested in the call to mkinfit
- # and for optimised error model parameters
- lower <- rep(-Inf, n_optim)
- upper <- rep(Inf, n_optim)
- names(lower) <- names(upper) <- names_optim
-
- # IORE exponents are not transformed, but need a lower bound
- index_N <- grep("^N", names(lower))
- lower[index_N] <- 0
-
- if (!transform_rates) {
- index_k <- grep("^k_", names(lower))
- lower[index_k] <- 0
- index_k__iore <- grep("^k__iore_", names(lower))
- lower[index_k__iore] <- 0
- other_rate_parms <- intersect(c("alpha", "beta", "k1", "k2", "tb", "r"), names(lower))
- lower[other_rate_parms] <- 0
- }
-
- if (!transform_fractions) {
- index_f <- grep("^f_", names(upper))
- lower[index_f] <- 0
- upper[index_f] <- 1
- other_fraction_parms <- intersect(c("g"), names(upper))
- lower[other_fraction_parms] <- 0
- upper[other_fraction_parms] <- 1
- }
-
- if (err_mod == "const") {
- if (error_model_algorithm != "OLS") {
- lower["sigma"] <- 0
- }
- }
- if (err_mod == "obs") {
- index_sigma <- grep("^sigma_", names(lower))
- lower[index_sigma] <- 0
- }
- if (err_mod == "tc") {
- lower["sigma_low"] <- 0
- lower["rsd_high"] <- 0
- }
-
- # Counter for cost function evaluations
- calls = 0
- cost.current <- Inf
- out_predicted <- NA
- current_data <- NA
-
- # Show parameter names if tracing is requested
- if(trace_parms) cat(names_optim, "\n")
-
- # browser()
-
- # Do the fit and take the time until the hessians are calculated
- fit_time <- system.time({
- degparms <- c(state.ini.optim, transparms.optim)
- n_degparms <- length(degparms)
- degparms_index <- seq(1, n_degparms)
- errparms_index <- seq(n_degparms + 1, length.out = length(errparms))
-
- if (error_model_algorithm == "d_3") {
- if (!quiet) message("Directly optimising the complete model")
- parms.start <- c(degparms, errparms)
- fit_direct <- nlminb(parms.start, cost_function,
- lower = lower[names(parms.start)],
- upper = upper[names(parms.start)],
- control = control, ...)
- fit_direct$logLik <- - cost.current
- if (error_model_algorithm == "direct") {
- degparms <- fit_direct$par[degparms_index]
- errparms <- fit_direct$par[errparms_index]
- } else {
- cost.current <- Inf # reset to avoid conflict with the OLS step
- }
- }
- if (error_model_algorithm != "direct") {
- if (!quiet) message("Ordinary least squares optimisation")
- fit <- nlminb(degparms, cost_function, control = control,
- lower = lower[names(degparms)],
- upper = upper[names(degparms)], OLS = TRUE, ...)
- degparms <- fit$par
-
- # Get the maximum likelihood estimate for sigma at the optimum parameter values
- current_data$residual <- current_data$value.observed - current_data$value.predicted
- sigma_mle <- sqrt(sum(current_data$residual^2)/nrow(current_data))
-
- # Use that estimate for the constant variance, or as first guess if err_mod = "obs"
- if (err_mod != "tc") {
- errparms[names(errparms)] <- sigma_mle
- }
- fit$par <- c(fit$par, errparms)
-
- cost.current <- cost_function(c(degparms, errparms), OLS = FALSE)
- fit$logLik <- - cost.current
- }
- if (error_model_algorithm %in% c("threestep", "fourstep", "d_3")) {
- if (!quiet) message("Optimising the error model")
- fit <- nlminb(errparms, cost_function, control = control,
- lower = lower[names(errparms)],
- upper = upper[names(errparms)],
- fixed_degparms = degparms, ...)
- errparms <- fit$par
- }
- if (error_model_algorithm == "fourstep") {
- if (!quiet) message("Optimising the degradation model")
- fit <- nlminb(degparms, cost_function, control = control,
- lower = lower[names(degparms)],
- upper = upper[names(degparms)],
- fixed_errparms = errparms, ...)
- degparms <- fit$par
- }
- if (error_model_algorithm %in%
- c("direct", "twostep", "threestep", "fourstep", "d_3")) {
- if (!quiet) message("Optimising the complete model")
- parms.start <- c(degparms, errparms)
- fit <- nlminb(parms.start, cost_function,
- lower = lower[names(parms.start)],
- upper = upper[names(parms.start)],
- control = control, ...)
- degparms <- fit$par[degparms_index]
- errparms <- fit$par[errparms_index]
- fit$logLik <- - cost.current
-
- if (error_model_algorithm == "d_3") {
- d_3_messages = c(
- same = "Direct fitting and three-step fitting yield approximately the same likelihood",
- threestep = "Three-step fitting yielded a higher likelihood than direct fitting",
- direct = "Direct fitting yielded a higher likelihood than three-step fitting")
- rel_diff <- abs((fit_direct$logLik - fit$logLik))/-mean(c(fit_direct$logLik, fit$logLik))
- if (rel_diff < 0.0001) {
- if (!quiet) message(d_3_messages["same"])
- fit$d_3_message <- d_3_messages["same"]
- } else {
- if (fit$logLik > fit_direct$logLik) {
- if (!quiet) message(d_3_messages["threestep"])
- fit$d_3_message <- d_3_messages["threestep"]
- } else {
- if (!quiet) message(d_3_messages["direct"])
- fit <- fit_direct
- fit$d_3_message <- d_3_messages["direct"]
- }
- }
- }
- }
- if (err_mod != "const" & error_model_algorithm == "IRLS") {
- reweight.diff <- 1
- n.iter <- 0
- errparms_last <- errparms
-
- while (reweight.diff > reweight.tol &
- n.iter < reweight.max.iter) {
-
- if (!quiet) message("Optimising the error model")
- fit <- nlminb(errparms, cost_function, control = control,
- lower = lower[names(errparms)],
- upper = upper[names(errparms)],
- fixed_degparms = degparms, ...)
- errparms <- fit$par
-
- if (!quiet) message("Optimising the degradation model")
- fit <- nlminb(degparms, cost_function, control = control,
- lower = lower[names(degparms)],
- upper = upper[names(degparms)],
- fixed_errparms = errparms, ...)
- degparms <- fit$par
-
- reweight.diff <- dist(rbind(errparms, errparms_last))
- errparms_last <- errparms
-
- fit$par <- c(fit$par, errparms)
- cost.current <- cost_function(c(degparms, errparms), OLS = FALSE)
- fit$logLik <- - cost.current
- }
- }
-
- fit$hessian <- try(numDeriv::hessian(cost_function, c(degparms, errparms), OLS = FALSE,
- update_data = FALSE), silent = TRUE)
-
- # Backtransform parameters
- bparms.optim = backtransform_odeparms(fit$par, mkinmod,
- transform_rates = transform_rates,
- transform_fractions = transform_fractions)
- bparms.fixed = c(state.ini.fixed, parms.fixed)
- bparms.all = c(bparms.optim, parms.fixed)
-
- fit$hessian_notrans <- try(numDeriv::hessian(cost_function, c(bparms.all, errparms),
- OLS = FALSE, trans = FALSE, update_data = FALSE), silent = TRUE)
- })
-
- fit$error_model_algorithm <- error_model_algorithm
-
- if (fit$convergence != 0) {
- fit$warning = paste0("Optimisation did not converge:\n", fit$message)
- warning(fit$warning)
- } else {
- if(!quiet) message("Optimisation successfully terminated.\n")
- }
-
- # We need to return some more data for summary and plotting
- fit$solution_type <- solution_type
- fit$transform_rates <- transform_rates
- fit$transform_fractions <- transform_fractions
- fit$reweight.tol <- reweight.tol
- fit$reweight.max.iter <- reweight.max.iter
- fit$control <- control
- fit$calls <- calls
- fit$time <- fit_time
-
- # We also need the model for summary and plotting
- fit$mkinmod <- mkinmod
-
- # We need data and predictions for summary and plotting
- fit$observed <- observed
- fit$obs_vars <- obs_vars
- fit$predicted <- out_predicted
-
- # Residual sum of squares as a function of the fitted parameters
- fit$rss <- function(P) cost_function(P, OLS = TRUE, update_data = FALSE)
-
- # Log-likelihood with possibility to fix degparms or errparms
- fit$ll <- function(P, fixed_degparms = FALSE, fixed_errparms = FALSE) {
- - cost_function(P, fixed_degparms = fixed_degparms,
- fixed_errparms = fixed_errparms, OLS = FALSE, update_data = FALSE)
- }
-
- # Collect initial parameter values in three dataframes
- fit$start <- data.frame(value = c(state.ini.optim,
- parms.optim, errparms_optim))
- fit$start$type = c(rep("state", length(state.ini.optim)),
- rep("deparm", length(parms.optim)),
- rep("error", length(errparms_optim)))
-
- fit$start_transformed = data.frame(
- value = c(state.ini.optim, transparms.optim, errparms_optim),
- lower = lower,
- upper = upper)
-
- fit$fixed <- data.frame(value = c(state.ini.fixed, parms.fixed))
- fit$fixed$type = c(rep("state", length(state.ini.fixed)),
- rep("deparm", length(parms.fixed)))
-
- # Sort observed, predicted and residuals
- current_data$name <- ordered(current_data$name, levels = obs_vars)
-
- ordered_data <- current_data[order(current_data$name, current_data$time), ]
-
- fit$data <- data.frame(time = ordered_data$time,
- variable = ordered_data$name,
- observed = ordered_data$value.observed,
- predicted = ordered_data$value.predicted)
-
- fit$data$residual <- fit$data$observed - fit$data$predicted
-
- fit$atol <- atol
- fit$rtol <- rtol
- fit$err_mod <- err_mod
-
- # Return different sets of backtransformed parameters for summary and plotting
- fit$bparms.optim <- bparms.optim
- fit$bparms.fixed <- bparms.fixed
-
- # Return ode and state parameters for further fitting
- fit$bparms.ode <- bparms.all[mkinmod$parms]
- fit$bparms.state <- c(bparms.all[setdiff(names(bparms.all), names(fit$bparms.ode))],
- state.ini.fixed)
- names(fit$bparms.state) <- gsub("_0$", "", names(fit$bparms.state))
-
- fit$errparms <- errparms
- fit$df.residual <- n_observed - length(c(degparms, errparms))
-
- fit$date <- date()
- fit$version <- as.character(utils::packageVersion("mkin"))
- fit$Rversion <- paste(R.version$major, R.version$minor, sep=".")
-
- class(fit) <- c("mkinfit", "modFit")
- return(fit)
-}
-
-summary.mkinfit <- function(object, data = TRUE, distimes = TRUE, alpha = 0.05, ...) {
- param <- object$par
- pnames <- names(param)
- bpnames <- names(object$bparms.optim)
- epnames <- names(object$errparms)
- p <- length(param)
- mod_vars <- names(object$mkinmod$diffs)
- covar <- try(solve(object$hessian), silent = TRUE)
- covar_notrans <- try(solve(object$hessian_notrans), silent = TRUE)
- rdf <- object$df.residual
-
- if (!is.numeric(covar) | is.na(covar[1])) {
- covar <- NULL
- se <- lci <- uci <- rep(NA, p)
- } else {
- rownames(covar) <- colnames(covar) <- pnames
- se <- sqrt(diag(covar))
- lci <- param + qt(alpha/2, rdf) * se
- uci <- param + qt(1-alpha/2, rdf) * se
- }
-
- beparms.optim <- c(object$bparms.optim, object$par[epnames])
- if (!is.numeric(covar_notrans) | is.na(covar_notrans[1])) {
- covar_notrans <- NULL
- se_notrans <- tval <- pval <- rep(NA, p)
- } else {
- rownames(covar_notrans) <- colnames(covar_notrans) <- c(bpnames, epnames)
- se_notrans <- sqrt(diag(covar_notrans))
- tval <- beparms.optim / se_notrans
- pval <- pt(abs(tval), rdf, lower.tail = FALSE)
- }
-
- names(se) <- pnames
-
- param <- cbind(param, se, lci, uci)
- dimnames(param) <- list(pnames, c("Estimate", "Std. Error", "Lower", "Upper"))
-
- bparam <- cbind(Estimate = beparms.optim, se_notrans,
- "t value" = tval, "Pr(>t)" = pval, Lower = NA, Upper = NA)
-
- # Transform boundaries of CI for one parameter at a time,
- # with the exception of sets of formation fractions (single fractions are OK).
- f_names_skip <- character(0)
- for (box in mod_vars) { # Figure out sets of fractions to skip
- f_names <- grep(paste("^f", box, sep = "_"), pnames, value = TRUE)
- n_paths <- length(f_names)
- if (n_paths > 1) f_names_skip <- c(f_names_skip, f_names)
- }
-
- for (pname in pnames) {
- if (!pname %in% f_names_skip) {
- par.lower <- param[pname, "Lower"]
- par.upper <- param[pname, "Upper"]
- names(par.lower) <- names(par.upper) <- pname
- bpl <- backtransform_odeparms(par.lower, object$mkinmod,
- object$transform_rates,
- object$transform_fractions)
- bpu <- backtransform_odeparms(par.upper, object$mkinmod,
- object$transform_rates,
- object$transform_fractions)
- bparam[names(bpl), "Lower"] <- bpl
- bparam[names(bpu), "Upper"] <- bpu
- }
- }
- bparam[epnames, c("Lower", "Upper")] <- param[epnames, c("Lower", "Upper")]
-
- ans <- list(
- version = as.character(utils::packageVersion("mkin")),
- Rversion = paste(R.version$major, R.version$minor, sep="."),
- date.fit = object$date,
- date.summary = date(),
- solution_type = object$solution_type,
- warning = object$warning,
- use_of_ff = object$mkinmod$use_of_ff,
- error_model_algorithm = object$error_model_algorithm,
- df = c(p, rdf),
- covar = covar,
- covar_notrans = covar_notrans,
- err_mod = object$err_mod,
- niter = object$iterations,
- calls = object$calls,
- time = object$time,
- par = param,
- bpar = bparam)
-
- if (!is.null(object$version)) {
- ans$fit_version <- object$version
- ans$fit_Rversion <- object$Rversion
- }
-
- ans$diffs <- object$mkinmod$diffs
- if(data) ans$data <- object$data
- ans$start <- object$start
- ans$start_transformed <- object$start_transformed
-
- ans$fixed <- object$fixed
-
- ans$errmin <- mkinerrmin(object, alpha = 0.05)
-
- if (object$calls > 0) {
- if (!is.null(ans$covar)){
- Corr <- cov2cor(ans$covar)
- rownames(Corr) <- colnames(Corr) <- rownames(ans$par)
- ans$Corr <- Corr
- } else {
- warning("Could not calculate correlation; no covariance matrix")
- }
- }
-
- ans$bparms.ode <- object$bparms.ode
- ep <- endpoints(object)
- if (length(ep$ff) != 0)
- ans$ff <- ep$ff
- if (distimes) ans$distimes <- ep$distimes
- if (length(ep$SFORB) != 0) ans$SFORB <- ep$SFORB
- if (!is.null(object$d_3_message)) ans$d_3_message <- object$d_3_message
- class(ans) <- c("summary.mkinfit", "summary.modFit")
- return(ans)
-}
-
-# Expanded from print.summary.modFit
-print.summary.mkinfit <- function(x, digits = max(3, getOption("digits") - 3), ...) {
- if (is.null(x$fit_version)) {
- cat("mkin version: ", x$version, "\n")
- cat("R version: ", x$Rversion, "\n")
- } else {
- cat("mkin version used for fitting: ", x$fit_version, "\n")
- cat("R version used for fitting: ", x$fit_Rversion, "\n")
- }
-
- cat("Date of fit: ", x$date.fit, "\n")
- cat("Date of summary:", x$date.summary, "\n")
-
- if (!is.null(x$warning)) cat("\n\nWarning:", x$warning, "\n\n")
-
- cat("\nEquations:\n")
- nice_diffs <- gsub("^(d.*) =", "\\1/dt =", x[["diffs"]])
- writeLines(strwrap(nice_diffs, exdent = 11))
- df <- x$df
- rdf <- df[2]
-
- cat("\nModel predictions using solution type", x$solution_type, "\n")
-
- cat("\nFitted using", x$calls, "model solutions performed in", x$time[["elapsed"]], "s\n")
-
- if (!is.null(x$err_mod)) {
- cat("\nError model: ")
- cat(switch(x$err_mod,
- const = "Constant variance",
- obs = "Variance unique to each observed variable",
- tc = "Two-component variance function"), "\n")
-
- cat("\nError model algorithm:", x$error_model_algorithm, "\n")
- if (!is.null(x$d_3_message)) cat(x$d_3_message, "\n")
- }
-
- cat("\nStarting values for parameters to be optimised:\n")
- print(x$start)
-
- cat("\nStarting values for the transformed parameters actually optimised:\n")
- print(x$start_transformed)
-
- cat("\nFixed parameter values:\n")
- if(length(x$fixed$value) == 0) cat("None\n")
- else print(x$fixed)
-
- cat("\nOptimised, transformed parameters with symmetric confidence intervals:\n")
- print(signif(x$par, digits = digits))
-
- if (x$calls > 0) {
- cat("\nParameter correlation:\n")
- if (!is.null(x$covar)){
- print(x$Corr, digits = digits, ...)
- } else {
- cat("No covariance matrix")
- }
- }
-
- cat("\nBacktransformed parameters:\n")
- cat("Confidence intervals for internally transformed parameters are asymmetric.\n")
- if ((x$version) < "0.9-36") {
- cat("To get the usual (questionable) t-test, upgrade mkin and repeat the fit.\n")
- print(signif(x$bpar, digits = digits))
- } else {
- cat("t-test (unrealistically) based on the assumption of normal distribution\n")
- cat("for estimators of untransformed parameters.\n")
- print(signif(x$bpar[, c(1, 3, 4, 5, 6)], digits = digits))
- }
-
- cat("\nFOCUS Chi2 error levels in percent:\n")
- x$errmin$err.min <- 100 * x$errmin$err.min
- print(x$errmin, digits=digits,...)
-
- printSFORB <- !is.null(x$SFORB)
- if(printSFORB){
- cat("\nEstimated Eigenvalues of SFORB model(s):\n")
- print(x$SFORB, digits=digits,...)
- }
-
- printff <- !is.null(x$ff)
- if(printff){
- cat("\nResulting formation fractions:\n")
- print(data.frame(ff = x$ff), digits=digits,...)
- }
-
- printdistimes <- !is.null(x$distimes)
- if(printdistimes){
- cat("\nEstimated disappearance times:\n")
- print(x$distimes, digits=digits,...)
- }
-
- printdata <- !is.null(x$data)
- if (printdata){
- cat("\nData:\n")
- print(format(x$data, digits = digits, ...), row.names = FALSE)
- }
-
- invisible(x)
-}
-# vim: set ts=2 sw=2 expandtab:
+if(getRversion() >= '2.15.1') utils::globalVariables(c("name", "time", "value"))
+
+#' Fit a kinetic model to data with one or more state variables
+#'
+#' This function maximises the likelihood of the observed data using the Port
+#' algorithm \code{\link{nlminb}}, and the specified initial or fixed
+#' parameters and starting values. In each step of the optimsation, the
+#' kinetic model is solved using the function \code{\link{mkinpredict}}. The
+#' parameters of the selected error model are fitted simultaneously with the
+#' degradation model parameters, as both of them are arguments of the
+#' likelihood function.
+#'
+#' Per default, parameters in the kinetic models are internally transformed in
+#' order to better satisfy the assumption of a normal distribution of their
+#' estimators.
+#'
+#' @param mkinmod A list of class \code{\link{mkinmod}}, containing the kinetic
+#' model to be fitted to the data, or one of the shorthand names ("SFO",
+#' "FOMC", "DFOP", "HS", "SFORB", "IORE"). If a shorthand name is given, a
+#' parent only degradation model is generated for the variable with the
+#' highest value in \code{observed}.
+#' @param observed A dataframe with the observed data. The first column called
+#' "name" must contain the name of the observed variable for each data point.
+#' The second column must contain the times of observation, named "time".
+#' The third column must be named "value" and contain the observed values.
+#' Zero values in the "value" column will be removed, with a warning, in
+#' order to avoid problems with fitting the two-component error model. This
+#' is not expected to be a problem, because in general, values of zero are
+#' not observed in degradation data, because there is a lower limit of
+#' detection.
+#' @param parms.ini A named vector of initial values for the parameters,
+#' including parameters to be optimised and potentially also fixed parameters
+#' as indicated by \code{fixed_parms}. If set to "auto", initial values for
+#' rate constants are set to default values. Using parameter names that are
+#' not in the model gives an error.
+#'
+#' It is possible to only specify a subset of the parameters that the model
+#' needs. You can use the parameter lists "bparms.ode" from a previously
+#' fitted model, which contains the differential equation parameters from
+#' this model. This works nicely if the models are nested. An example is
+#' given below.
+#' @param state.ini A named vector of initial values for the state variables of
+#' the model. In case the observed variables are represented by more than one
+#' model variable, the names will differ from the names of the observed
+#' variables (see \code{map} component of \code{\link{mkinmod}}). The default
+#' is to set the initial value of the first model variable to the mean of the
+#' time zero values for the variable with the maximum observed value, and all
+#' others to 0. If this variable has no time zero observations, its initial
+#' value is set to 100.
+#' @param err.ini A named vector of initial values for the error model
+#' parameters to be optimised. If set to "auto", initial values are set to
+#' default values. Otherwise, inital values for all error model parameters
+#' must be given.
+#' @param fixed_parms The names of parameters that should not be optimised but
+#' rather kept at the values specified in \code{parms.ini}.
+#' @param fixed_initials The names of model variables for which the initial
+#' state at time 0 should be excluded from the optimisation. Defaults to all
+#' state variables except for the first one.
+#' @param from_max_mean If this is set to TRUE, and the model has only one
+#' observed variable, then data before the time of the maximum observed value
+#' (after averaging for each sampling time) are discarded, and this time is
+#' subtracted from all remaining time values, so the time of the maximum
+#' observed mean value is the new time zero.
+#' @param solution_type If set to "eigen", the solution of the system of
+#' differential equations is based on the spectral decomposition of the
+#' coefficient matrix in cases that this is possible. If set to "deSolve", a
+#' numerical ode solver from package \code{\link{deSolve}} is used. If set to
+#' "analytical", an analytical solution of the model is used. This is only
+#' implemented for simple degradation experiments with only one state
+#' variable, i.e. with no metabolites. The default is "auto", which uses
+#' "analytical" if possible, otherwise "deSolve" if a compiler is present,
+#' and "eigen" if no compiler is present and the model can be expressed using
+#' eigenvalues and eigenvectors. This argument is passed on to the helper
+#' function \code{\link{mkinpredict}}.
+#' @param method.ode The solution method passed via \code{\link{mkinpredict}}
+#' to \code{\link{ode}} in case the solution type is "deSolve". The default
+#' "lsoda" is performant, but sometimes fails to converge.
+#' @param use_compiled If set to \code{FALSE}, no compiled version of the
+#' \code{\link{mkinmod}} model is used in the calls to
+#' \code{\link{mkinpredict}} even if a compiled version is present.
+#' @param control A list of control arguments passed to \code{\link{nlminb}}.
+#' @param transform_rates Boolean specifying if kinetic rate constants should
+#' be transformed in the model specification used in the fitting for better
+#' compliance with the assumption of normal distribution of the estimator. If
+#' TRUE, also alpha and beta parameters of the FOMC model are
+#' log-transformed, as well as k1 and k2 rate constants for the DFOP and HS
+#' models and the break point tb of the HS model. If FALSE, zero is used as
+#' a lower bound for the rates in the optimisation.
+#' @param transform_fractions Boolean specifying if formation fractions
+#' constants should be transformed in the model specification used in the
+#' fitting for better compliance with the assumption of normal distribution
+#' of the estimator. The default (TRUE) is to do transformations. If TRUE,
+#' the g parameter of the DFOP and HS models are also transformed, as they
+#' can also be seen as compositional data. The transformation used for these
+#' transformations is the \code{\link{ilr}} transformation.
+#' @param quiet Suppress printing out the current value of the negative
+#' log-likelihood after each improvement?
+#' @param atol Absolute error tolerance, passed to \code{\link{ode}}. Default
+#' is 1e-8, lower than in \code{\link{lsoda}}.
+#' @param rtol Absolute error tolerance, passed to \code{\link{ode}}. Default
+#' is 1e-10, much lower than in \code{\link{lsoda}}.
+#' @param n.outtimes The length of the dataseries that is produced by the model
+#' prediction function \code{\link{mkinpredict}}. This impacts the accuracy
+#' of the numerical solver if that is used (see \code{solution_type}
+#' argument. The default value is 100.
+#' @param error_model If the error model is "const", a constant standard
+#' deviation is assumed.
+#'
+#' If the error model is "obs", each observed variable is assumed to have its
+#' own variance.
+#'
+#' If the error model is "tc" (two-component error model), a two component
+#' error model similar to the one described by Rocke and Lorenzato (1995) is
+#' used for setting up the likelihood function. Note that this model
+#' deviates from the model by Rocke and Lorenzato, as their model implies
+#' that the errors follow a lognormal distribution for large values, not a
+#' normal distribution as assumed by this method.
+#' @param error_model_algorithm If "auto", the selected algorithm depends on
+#' the error model. If the error model is "const", unweighted nonlinear
+#' least squares fitting ("OLS") is selected. If the error model is "obs", or
+#' "tc", the "d_3" algorithm is selected.
+#'
+#' The algorithm "d_3" will directly minimize the negative log-likelihood and
+#' - independently - also use the three step algorithm described below. The
+#' fit with the higher likelihood is returned.
+#'
+#' The algorithm "direct" will directly minimize the negative log-likelihood.
+#'
+#' The algorithm "twostep" will minimize the negative log-likelihood after an
+#' initial unweighted least squares optimisation step.
+#'
+#' The algorithm "threestep" starts with unweighted least squares, then
+#' optimizes only the error model using the degradation model parameters
+#' found, and then minimizes the negative log-likelihood with free
+#' degradation and error model parameters.
+#'
+#' The algorithm "fourstep" starts with unweighted least squares, then
+#' optimizes only the error model using the degradation model parameters
+#' found, then optimizes the degradation model again with fixed error model
+#' parameters, and finally minimizes the negative log-likelihood with free
+#' degradation and error model parameters.
+#'
+#' The algorithm "IRLS" (Iteratively Reweighted Least Squares) starts with
+#' unweighted least squares, and then iterates optimization of the error
+#' model parameters and subsequent optimization of the degradation model
+#' using those error model parameters, until the error model parameters
+#' converge.
+#' @param reweight.tol Tolerance for the convergence criterion calculated from
+#' the error model parameters in IRLS fits.
+#' @param reweight.max.iter Maximum number of iterations in IRLS fits.
+#' @param trace_parms Should a trace of the parameter values be listed?
+#' @param \dots Further arguments that will be passed on to
+#' \code{\link{deSolve}}.
+#' @importFrom stats nlminb aggregate dist
+#' @return A list with "mkinfit" in the class attribute. A summary can be
+#' obtained by \code{\link{summary.mkinfit}}.
+#' @note When using the "IORE" submodel for metabolites, fitting with
+#' "transform_rates = TRUE" (the default) often leads to failures of the
+#' numerical ODE solver. In this situation it may help to switch off the
+#' internal rate transformation.
+#' @author Johannes Ranke
+#' @seealso Plotting methods \code{\link{plot.mkinfit}} and
+#' \code{\link{mkinparplot}}.
+#'
+#' Comparisons of models fitted to the same data can be made using
+#' \code{\link{AIC}} by virtue of the method \code{\link{logLik.mkinfit}}.
+#'
+#' Fitting of several models to several datasets in a single call to
+#' \code{\link{mmkin}}.
+#' @source Rocke, David M. und Lorenzato, Stefan (1995) A two-component model
+#' for measurement error in analytical chemistry. Technometrics 37(2), 176-184.
+#' @examples
+#'
+#' # Use shorthand notation for parent only degradation
+#' fit <- mkinfit("FOMC", FOCUS_2006_C, quiet = TRUE)
+#' summary(fit)
+#'
+#' # One parent compound, one metabolite, both single first order.
+#' # Use mkinsub for convenience in model formulation. Pathway to sink included per default.
+#' SFO_SFO <- mkinmod(
+#' parent = mkinsub("SFO", "m1"),
+#' m1 = mkinsub("SFO"))
+#' # Fit the model to the FOCUS example dataset D using defaults
+#' print(system.time(fit <- mkinfit(SFO_SFO, FOCUS_2006_D,
+#' solution_type = "eigen", quiet = TRUE)))
+#' coef(fit)
+#' endpoints(fit)
+#' \dontrun{
+#' # deSolve is slower when no C compiler (gcc) was available during model generation
+#' print(system.time(fit.deSolve <- mkinfit(SFO_SFO, FOCUS_2006_D,
+#' solution_type = "deSolve")))
+#' coef(fit.deSolve)
+#' endpoints(fit.deSolve)
+#' }
+#'
+#' # Use stepwise fitting, using optimised parameters from parent only fit, FOMC
+#' \dontrun{
+#' FOMC_SFO <- mkinmod(
+#' parent = mkinsub("FOMC", "m1"),
+#' m1 = mkinsub("SFO"))
+#' # Fit the model to the FOCUS example dataset D using defaults
+#' fit.FOMC_SFO <- mkinfit(FOMC_SFO, FOCUS_2006_D, quiet = TRUE)
+#' # Use starting parameters from parent only FOMC fit
+#' fit.FOMC = mkinfit("FOMC", FOCUS_2006_D, quiet = TRUE)
+#' fit.FOMC_SFO <- mkinfit(FOMC_SFO, FOCUS_2006_D, quiet = TRUE,
+#' parms.ini = fit.FOMC$bparms.ode)
+#'
+#' # Use stepwise fitting, using optimised parameters from parent only fit, SFORB
+#' SFORB_SFO <- mkinmod(
+#' parent = list(type = "SFORB", to = "m1", sink = TRUE),
+#' m1 = list(type = "SFO"))
+#' # Fit the model to the FOCUS example dataset D using defaults
+#' fit.SFORB_SFO <- mkinfit(SFORB_SFO, FOCUS_2006_D, quiet = TRUE)
+#' fit.SFORB_SFO.deSolve <- mkinfit(SFORB_SFO, FOCUS_2006_D, solution_type = "deSolve",
+#' quiet = TRUE)
+#' # Use starting parameters from parent only SFORB fit (not really needed in this case)
+#' fit.SFORB = mkinfit("SFORB", FOCUS_2006_D, quiet = TRUE)
+#' fit.SFORB_SFO <- mkinfit(SFORB_SFO, FOCUS_2006_D, parms.ini = fit.SFORB$bparms.ode, quiet = TRUE)
+#' }
+#'
+#' \dontrun{
+#' # Weighted fits, including IRLS
+#' SFO_SFO.ff <- mkinmod(parent = mkinsub("SFO", "m1"),
+#' m1 = mkinsub("SFO"), use_of_ff = "max")
+#' f.noweight <- mkinfit(SFO_SFO.ff, FOCUS_2006_D, quiet = TRUE)
+#' summary(f.noweight)
+#' f.obs <- mkinfit(SFO_SFO.ff, FOCUS_2006_D, error_model = "obs", quiet = TRUE)
+#' summary(f.obs)
+#' f.tc <- mkinfit(SFO_SFO.ff, FOCUS_2006_D, error_model = "tc", quiet = TRUE)
+#' summary(f.tc)
+#' }
+#'
+#'
+#' @export
+mkinfit <- function(mkinmod, observed,
+ parms.ini = "auto",
+ state.ini = "auto",
+ err.ini = "auto",
+ fixed_parms = NULL,
+ fixed_initials = names(mkinmod$diffs)[-1],
+ from_max_mean = FALSE,
+ solution_type = c("auto", "analytical", "eigen", "deSolve"),
+ method.ode = "lsoda",
+ use_compiled = "auto",
+ control = list(eval.max = 300, iter.max = 200),
+ transform_rates = TRUE,
+ transform_fractions = TRUE,
+ quiet = FALSE,
+ atol = 1e-8, rtol = 1e-10, n.outtimes = 100,
+ error_model = c("const", "obs", "tc"),
+ error_model_algorithm = c("auto", "d_3", "direct", "twostep", "threestep", "fourstep", "IRLS", "OLS"),
+ reweight.tol = 1e-8, reweight.max.iter = 10,
+ trace_parms = FALSE,
+ ...)
+{
+ # Check mkinmod and generate a model for the variable whith the highest value
+ # if a suitable string is given
+ parent_models_available = c("SFO", "FOMC", "DFOP", "HS", "SFORB", "IORE", "logistic")
+ if (class(mkinmod) != "mkinmod") {
+ presumed_parent_name = observed[which.max(observed$value), "name"]
+ if (mkinmod[[1]] %in% parent_models_available) {
+ speclist <- list(list(type = mkinmod, sink = TRUE))
+ names(speclist) <- presumed_parent_name
+ mkinmod <- mkinmod(speclist = speclist)
+ } else {
+ stop("Argument mkinmod must be of class mkinmod or a string containing one of\n ",
+ paste(parent_models_available, collapse = ", "))
+ }
+ }
+
+ # Get the names of the state variables in the model
+ mod_vars <- names(mkinmod$diffs)
+
+ # Get the names of observed variables
+ obs_vars <- names(mkinmod$spec)
+
+ # Subset observed data with names of observed data in the model and remove NA values
+ observed <- subset(observed, name %in% obs_vars)
+ observed <- subset(observed, !is.na(value))
+
+ # Also remove zero values to avoid instabilities (e.g. of the 'tc' error model)
+ if (any(observed$value == 0)) {
+ warning("Observations with value of zero were removed from the data")
+ observed <- subset(observed, value != 0)
+ }
+
+ # Obtain data for decline from maximum mean value if requested
+ if (from_max_mean) {
+ # This is only used for simple decline models
+ if (length(obs_vars) > 1)
+ stop("Decline from maximum is only implemented for models with a single observed variable")
+
+ means <- aggregate(value ~ time, data = observed, mean, na.rm=TRUE)
+ t_of_max <- means[which.max(means$value), "time"]
+ observed <- subset(observed, time >= t_of_max)
+ observed$time <- observed$time - t_of_max
+ }
+
+ # Number observations used for fitting
+ n_observed <- nrow(observed)
+
+ # Define starting values for parameters where not specified by the user
+ if (parms.ini[[1]] == "auto") parms.ini = vector()
+
+ # Warn for inital parameter specifications that are not in the model
+ wrongpar.names <- setdiff(names(parms.ini), mkinmod$parms)
+ if (length(wrongpar.names) > 0) {
+ warning("Initial parameter(s) ", paste(wrongpar.names, collapse = ", "),
+ " not used in the model")
+ parms.ini <- parms.ini[setdiff(names(parms.ini), wrongpar.names)]
+ }
+
+ # Warn that the sum of formation fractions may exceed one if they are not
+ # fitted in the transformed way
+ if (mkinmod$use_of_ff == "max" & transform_fractions == FALSE) {
+ warning("The sum of formation fractions may exceed one if you do not use ",
+ "transform_fractions = TRUE." )
+ for (box in mod_vars) {
+ # Stop if formation fractions are not transformed and we have no sink
+ if (mkinmod$spec[[box]]$sink == FALSE) {
+ stop("If formation fractions are not transformed during the fitting, ",
+ "it is not supported to turn off pathways to sink.\n ",
+ "Consider turning on the transformation of formation fractions or ",
+ "setting up a model with use_of_ff = 'min'.\n")
+ }
+ }
+ }
+
+ # Do not allow fixing formation fractions if we are using the ilr transformation,
+ # this is not supported
+ if (transform_fractions == TRUE && length(fixed_parms) > 0) {
+ if (any(grepl("^f_", fixed_parms))) {
+ stop("Fixing formation fractions is not supported when using the ilr ",
+ "transformation.")
+ }
+ }
+
+ # Set initial parameter values, including a small increment (salt)
+ # to avoid linear dependencies (singular matrix) in Eigenvalue based solutions
+ k_salt = 0
+ defaultpar.names <- setdiff(mkinmod$parms, names(parms.ini))
+ for (parmname in defaultpar.names) {
+ # Default values for rate constants, depending on the parameterisation
+ if (grepl("^k", parmname)) {
+ parms.ini[parmname] = 0.1 + k_salt
+ k_salt = k_salt + 1e-4
+ }
+ # Default values for rate constants for reversible binding
+ if (grepl("free_bound$", parmname)) parms.ini[parmname] = 0.1
+ if (grepl("bound_free$", parmname)) parms.ini[parmname] = 0.02
+ # Default values for IORE exponents
+ if (grepl("^N", parmname)) parms.ini[parmname] = 1.1
+ # Default values for the FOMC, DFOP and HS models
+ if (parmname == "alpha") parms.ini[parmname] = 1
+ if (parmname == "beta") parms.ini[parmname] = 10
+ if (parmname == "k1") parms.ini[parmname] = 0.1
+ if (parmname == "k2") parms.ini[parmname] = 0.01
+ if (parmname == "tb") parms.ini[parmname] = 5
+ if (parmname == "g") parms.ini[parmname] = 0.5
+ if (parmname == "kmax") parms.ini[parmname] = 0.1
+ if (parmname == "k0") parms.ini[parmname] = 0.0001
+ if (parmname == "r") parms.ini[parmname] = 0.2
+ }
+ # Default values for formation fractions in case they are present
+ for (box in mod_vars) {
+ f_names <- mkinmod$parms[grep(paste0("^f_", box), mkinmod$parms)]
+ if (length(f_names) > 0) {
+ # We need to differentiate between default and specified fractions
+ # and set the unspecified to 1 - sum(specified)/n_unspecified
+ f_default_names <- intersect(f_names, defaultpar.names)
+ f_specified_names <- setdiff(f_names, defaultpar.names)
+ sum_f_specified = sum(parms.ini[f_specified_names])
+ if (sum_f_specified > 1) {
+ stop("Starting values for the formation fractions originating from ",
+ box, " sum up to more than 1.")
+ }
+ if (mkinmod$spec[[box]]$sink) n_unspecified = length(f_default_names) + 1
+ else {
+ n_unspecified = length(f_default_names)
+ }
+ parms.ini[f_default_names] <- (1 - sum_f_specified) / n_unspecified
+ }
+ }
+
+ # Set default for state.ini if appropriate
+ parent_name = names(mkinmod$spec)[[1]]
+ if (state.ini[1] == "auto") {
+ parent_time_0 = subset(observed, time == 0 & name == parent_name)$value
+ parent_time_0_mean = mean(parent_time_0, na.rm = TRUE)
+ if (is.na(parent_time_0_mean)) {
+ state.ini = c(100, rep(0, length(mkinmod$diffs) - 1))
+ } else {
+ state.ini = c(parent_time_0_mean, rep(0, length(mkinmod$diffs) - 1))
+ }
+ }
+
+ # Name the inital state variable values if they are not named yet
+ if(is.null(names(state.ini))) names(state.ini) <- mod_vars
+
+ # Transform initial parameter values for fitting
+ transparms.ini <- transform_odeparms(parms.ini, mkinmod,
+ transform_rates = transform_rates,
+ transform_fractions = transform_fractions)
+
+ # Parameters to be optimised:
+ # Kinetic parameters in parms.ini whose names are not in fixed_parms
+ parms.fixed <- parms.ini[fixed_parms]
+ parms.optim <- parms.ini[setdiff(names(parms.ini), fixed_parms)]
+
+ transparms.fixed <- transform_odeparms(parms.fixed, mkinmod,
+ transform_rates = transform_rates,
+ transform_fractions = transform_fractions)
+ transparms.optim <- transform_odeparms(parms.optim, mkinmod,
+ transform_rates = transform_rates,
+ transform_fractions = transform_fractions)
+
+ # Inital state variables in state.ini whose names are not in fixed_initials
+ state.ini.fixed <- state.ini[fixed_initials]
+ state.ini.optim <- state.ini[setdiff(names(state.ini), fixed_initials)]
+
+ # Preserve names of state variables before renaming initial state variable
+ # parameters
+ state.ini.optim.boxnames <- names(state.ini.optim)
+ state.ini.fixed.boxnames <- names(state.ini.fixed)
+ if(length(state.ini.optim) > 0) {
+ names(state.ini.optim) <- paste(names(state.ini.optim), "0", sep="_")
+ }
+ if(length(state.ini.fixed) > 0) {
+ names(state.ini.fixed) <- paste(names(state.ini.fixed), "0", sep="_")
+ }
+
+ # Decide if the solution of the model can be based on a simple analytical
+ # formula, the spectral decomposition of the matrix (fundamental system)
+ # or a numeric ode solver from the deSolve package
+ # Prefer deSolve over eigen if a compiled model is present and use_compiled
+ # is not set to FALSE
+ solution_type = match.arg(solution_type)
+ if (solution_type == "analytical" && length(mkinmod$spec) > 1)
+ stop("Analytical solution not implemented for models with metabolites.")
+ if (solution_type == "eigen" && !is.matrix(mkinmod$coefmat))
+ stop("Eigenvalue based solution not possible, coefficient matrix not present.")
+ if (solution_type == "auto") {
+ if (length(mkinmod$spec) == 1) {
+ solution_type = "analytical"
+ } else {
+ if (!is.null(mkinmod$cf) & use_compiled[1] != FALSE) {
+ solution_type = "deSolve"
+ } else {
+ if (is.matrix(mkinmod$coefmat)) {
+ solution_type = "eigen"
+ if (max(observed$value, na.rm = TRUE) < 0.1) {
+ stop("The combination of small observed values (all < 0.1) and solution_type = eigen is error-prone")
+ }
+ } else {
+ solution_type = "deSolve"
+ }
+ }
+ }
+ }
+
+ # Get the error model and the algorithm for fitting
+ err_mod <- match.arg(error_model)
+ error_model_algorithm = match.arg(error_model_algorithm)
+ if (error_model_algorithm == "OLS") {
+ if (err_mod != "const") stop("OLS is only appropriate for constant variance")
+ }
+ if (error_model_algorithm == "auto") {
+ error_model_algorithm = switch(err_mod,
+ const = "OLS", obs = "d_3", tc = "d_3")
+ }
+ errparm_names <- switch(err_mod,
+ "const" = "sigma",
+ "obs" = paste0("sigma_", obs_vars),
+ "tc" = c("sigma_low", "rsd_high"))
+ errparm_names_optim <- if (error_model_algorithm == "OLS") NULL else errparm_names
+
+ # Define starting values for the error model
+ if (err.ini[1] != "auto") {
+ if (!identical(names(err.ini), errparm_names)) {
+ stop("Please supply initial values for error model components ", paste(errparm_names, collapse = ", "))
+ } else {
+ errparms = err.ini
+ }
+ } else {
+ if (err_mod == "const") {
+ errparms = 3
+ }
+ if (err_mod == "obs") {
+ errparms = rep(3, length(obs_vars))
+ }
+ if (err_mod == "tc") {
+ errparms <- c(sigma_low = 0.1, rsd_high = 0.1)
+ }
+ names(errparms) <- errparm_names
+ }
+ if (error_model_algorithm == "OLS") {
+ errparms_optim <- NULL
+ } else {
+ errparms_optim <- errparms
+ }
+
+ # Define outtimes for model solution.
+ # Include time points at which observed data are available
+ outtimes = sort(unique(c(observed$time, seq(min(observed$time),
+ max(observed$time),
+ length.out = n.outtimes))))
+
+ # Define the objective function for optimisation, including (back)transformations
+ cost_function <- function(P, trans = TRUE, OLS = FALSE, fixed_degparms = FALSE, fixed_errparms = FALSE, update_data = TRUE, ...)
+ {
+ assign("calls", calls + 1, inherits = TRUE) # Increase the model solution counter
+
+ # Trace parameter values if requested and if we are actually optimising
+ if(trace_parms & update_data) cat(P, "\n")
+
+ # Determine local parameter values for the cost estimation
+ if (is.numeric(fixed_degparms)) {
+ cost_degparms <- fixed_degparms
+ cost_errparms <- P
+ degparms_fixed = TRUE
+ } else {
+ degparms_fixed = FALSE
+ }
+
+ if (is.numeric(fixed_errparms)) {
+ cost_degparms <- P
+ cost_errparms <- fixed_errparms
+ errparms_fixed = TRUE
+ } else {
+ errparms_fixed = FALSE
+ }
+
+ if (OLS) {
+ cost_degparms <- P
+ cost_errparms <- numeric(0)
+ }
+
+ if (!OLS & !degparms_fixed & !errparms_fixed) {
+ cost_degparms <- P[1:(length(P) - length(errparms))]
+ cost_errparms <- P[(length(cost_degparms) + 1):length(P)]
+ }
+
+ # Initial states for t0
+ if(length(state.ini.optim) > 0) {
+ odeini <- c(cost_degparms[1:length(state.ini.optim)], state.ini.fixed)
+ names(odeini) <- c(state.ini.optim.boxnames, state.ini.fixed.boxnames)
+ } else {
+ odeini <- state.ini.fixed
+ names(odeini) <- state.ini.fixed.boxnames
+ }
+
+ odeparms.optim <- cost_degparms[(length(state.ini.optim) + 1):length(cost_degparms)]
+
+ if (trans == TRUE) {
+ odeparms <- c(odeparms.optim, transparms.fixed)
+ parms <- backtransform_odeparms(odeparms, mkinmod,
+ transform_rates = transform_rates,
+ transform_fractions = transform_fractions)
+ } else {
+ parms <- c(odeparms.optim, parms.fixed)
+ }
+
+ # Solve the system with current parameter values
+ out <- mkinpredict(mkinmod, parms,
+ odeini, outtimes,
+ solution_type = solution_type,
+ use_compiled = use_compiled,
+ method.ode = method.ode,
+ atol = atol, rtol = rtol, ...)
+
+ out_long <- mkin_wide_to_long(out, time = "time")
+
+ if (err_mod == "const") {
+ observed$std <- if (OLS) NA else cost_errparms["sigma"]
+ }
+ if (err_mod == "obs") {
+ std_names <- paste0("sigma_", observed$name)
+ observed$std <- cost_errparms[std_names]
+ }
+ if (err_mod == "tc") {
+ tmp <- merge(observed, out_long, by = c("time", "name"))
+ tmp$name <- ordered(tmp$name, levels = obs_vars)
+ tmp <- tmp[order(tmp$name, tmp$time), ]
+ observed$std <- sqrt(cost_errparms["sigma_low"]^2 + tmp$value.y^2 * cost_errparms["rsd_high"]^2)
+ }
+
+ cost_data <- merge(observed[c("name", "time", "value", "std")], out_long,
+ by = c("name", "time"), suffixes = c(".observed", ".predicted"))
+
+ if (OLS) {
+ # Cost is the sum of squared residuals
+ cost <- with(cost_data, sum((value.observed - value.predicted)^2))
+ } else {
+ # Cost is the negative log-likelihood
+ cost <- - with(cost_data,
+ sum(dnorm(x = value.observed, mean = value.predicted, sd = std, log = TRUE)))
+ }
+
+ # We update the current cost and data during the optimisation, not
+ # during hessian calculations
+ if (update_data) {
+
+ assign("out_predicted", out_long, inherits = TRUE)
+ assign("current_data", cost_data, inherits = TRUE)
+
+ if (cost < cost.current) {
+ assign("cost.current", cost, inherits = TRUE)
+ if (!quiet) cat(ifelse(OLS, "Sum of squared residuals", "Negative log-likelihood"),
+ " at call ", calls, ": ", cost.current, "\n", sep = "")
+ }
+ }
+ return(cost)
+ }
+
+ names_optim <- c(names(state.ini.optim),
+ names(transparms.optim),
+ errparm_names_optim)
+ n_optim <- length(names_optim)
+
+ # Define lower and upper bounds other than -Inf and Inf for parameters
+ # for which no internal transformation is requested in the call to mkinfit
+ # and for optimised error model parameters
+ lower <- rep(-Inf, n_optim)
+ upper <- rep(Inf, n_optim)
+ names(lower) <- names(upper) <- names_optim
+
+ # IORE exponents are not transformed, but need a lower bound
+ index_N <- grep("^N", names(lower))
+ lower[index_N] <- 0
+
+ if (!transform_rates) {
+ index_k <- grep("^k_", names(lower))
+ lower[index_k] <- 0
+ index_k__iore <- grep("^k__iore_", names(lower))
+ lower[index_k__iore] <- 0
+ other_rate_parms <- intersect(c("alpha", "beta", "k1", "k2", "tb", "r"), names(lower))
+ lower[other_rate_parms] <- 0
+ }
+
+ if (!transform_fractions) {
+ index_f <- grep("^f_", names(upper))
+ lower[index_f] <- 0
+ upper[index_f] <- 1
+ other_fraction_parms <- intersect(c("g"), names(upper))
+ lower[other_fraction_parms] <- 0
+ upper[other_fraction_parms] <- 1
+ }
+
+ if (err_mod == "const") {
+ if (error_model_algorithm != "OLS") {
+ lower["sigma"] <- 0
+ }
+ }
+ if (err_mod == "obs") {
+ index_sigma <- grep("^sigma_", names(lower))
+ lower[index_sigma] <- 0
+ }
+ if (err_mod == "tc") {
+ lower["sigma_low"] <- 0
+ lower["rsd_high"] <- 0
+ }
+
+ # Counter for cost function evaluations
+ calls = 0
+ cost.current <- Inf
+ out_predicted <- NA
+ current_data <- NA
+
+ # Show parameter names if tracing is requested
+ if(trace_parms) cat(names_optim, "\n")
+
+ # browser()
+
+ # Do the fit and take the time until the hessians are calculated
+ fit_time <- system.time({
+ degparms <- c(state.ini.optim, transparms.optim)
+ n_degparms <- length(degparms)
+ degparms_index <- seq(1, n_degparms)
+ errparms_index <- seq(n_degparms + 1, length.out = length(errparms))
+
+ if (error_model_algorithm == "d_3") {
+ if (!quiet) message("Directly optimising the complete model")
+ parms.start <- c(degparms, errparms)
+ fit_direct <- nlminb(parms.start, cost_function,
+ lower = lower[names(parms.start)],
+ upper = upper[names(parms.start)],
+ control = control, ...)
+ fit_direct$logLik <- - cost.current
+ if (error_model_algorithm == "direct") {
+ degparms <- fit_direct$par[degparms_index]
+ errparms <- fit_direct$par[errparms_index]
+ } else {
+ cost.current <- Inf # reset to avoid conflict with the OLS step
+ }
+ }
+ if (error_model_algorithm != "direct") {
+ if (!quiet) message("Ordinary least squares optimisation")
+ fit <- nlminb(degparms, cost_function, control = control,
+ lower = lower[names(degparms)],
+ upper = upper[names(degparms)], OLS = TRUE, ...)
+ degparms <- fit$par
+
+ # Get the maximum likelihood estimate for sigma at the optimum parameter values
+ current_data$residual <- current_data$value.observed - current_data$value.predicted
+ sigma_mle <- sqrt(sum(current_data$residual^2)/nrow(current_data))
+
+ # Use that estimate for the constant variance, or as first guess if err_mod = "obs"
+ if (err_mod != "tc") {
+ errparms[names(errparms)] <- sigma_mle
+ }
+ fit$par <- c(fit$par, errparms)
+
+ cost.current <- cost_function(c(degparms, errparms), OLS = FALSE)
+ fit$logLik <- - cost.current
+ }
+ if (error_model_algorithm %in% c("threestep", "fourstep", "d_3")) {
+ if (!quiet) message("Optimising the error model")
+ fit <- nlminb(errparms, cost_function, control = control,
+ lower = lower[names(errparms)],
+ upper = upper[names(errparms)],
+ fixed_degparms = degparms, ...)
+ errparms <- fit$par
+ }
+ if (error_model_algorithm == "fourstep") {
+ if (!quiet) message("Optimising the degradation model")
+ fit <- nlminb(degparms, cost_function, control = control,
+ lower = lower[names(degparms)],
+ upper = upper[names(degparms)],
+ fixed_errparms = errparms, ...)
+ degparms <- fit$par
+ }
+ if (error_model_algorithm %in%
+ c("direct", "twostep", "threestep", "fourstep", "d_3")) {
+ if (!quiet) message("Optimising the complete model")
+ parms.start <- c(degparms, errparms)
+ fit <- nlminb(parms.start, cost_function,
+ lower = lower[names(parms.start)],
+ upper = upper[names(parms.start)],
+ control = control, ...)
+ degparms <- fit$par[degparms_index]
+ errparms <- fit$par[errparms_index]
+ fit$logLik <- - cost.current
+
+ if (error_model_algorithm == "d_3") {
+ d_3_messages = c(
+ same = "Direct fitting and three-step fitting yield approximately the same likelihood",
+ threestep = "Three-step fitting yielded a higher likelihood than direct fitting",
+ direct = "Direct fitting yielded a higher likelihood than three-step fitting")
+ rel_diff <- abs((fit_direct$logLik - fit$logLik))/-mean(c(fit_direct$logLik, fit$logLik))
+ if (rel_diff < 0.0001) {
+ if (!quiet) message(d_3_messages["same"])
+ fit$d_3_message <- d_3_messages["same"]
+ } else {
+ if (fit$logLik > fit_direct$logLik) {
+ if (!quiet) message(d_3_messages["threestep"])
+ fit$d_3_message <- d_3_messages["threestep"]
+ } else {
+ if (!quiet) message(d_3_messages["direct"])
+ fit <- fit_direct
+ fit$d_3_message <- d_3_messages["direct"]
+ }
+ }
+ }
+ }
+ if (err_mod != "const" & error_model_algorithm == "IRLS") {
+ reweight.diff <- 1
+ n.iter <- 0
+ errparms_last <- errparms
+
+ while (reweight.diff > reweight.tol &
+ n.iter < reweight.max.iter) {
+
+ if (!quiet) message("Optimising the error model")
+ fit <- nlminb(errparms, cost_function, control = control,
+ lower = lower[names(errparms)],
+ upper = upper[names(errparms)],
+ fixed_degparms = degparms, ...)
+ errparms <- fit$par
+
+ if (!quiet) message("Optimising the degradation model")
+ fit <- nlminb(degparms, cost_function, control = control,
+ lower = lower[names(degparms)],
+ upper = upper[names(degparms)],
+ fixed_errparms = errparms, ...)
+ degparms <- fit$par
+
+ reweight.diff <- dist(rbind(errparms, errparms_last))
+ errparms_last <- errparms
+
+ fit$par <- c(fit$par, errparms)
+ cost.current <- cost_function(c(degparms, errparms), OLS = FALSE)
+ fit$logLik <- - cost.current
+ }
+ }
+
+ fit$hessian <- try(numDeriv::hessian(cost_function, c(degparms, errparms), OLS = FALSE,
+ update_data = FALSE), silent = TRUE)
+
+ # Backtransform parameters
+ bparms.optim = backtransform_odeparms(fit$par, mkinmod,
+ transform_rates = transform_rates,
+ transform_fractions = transform_fractions)
+ bparms.fixed = c(state.ini.fixed, parms.fixed)
+ bparms.all = c(bparms.optim, parms.fixed)
+
+ fit$hessian_notrans <- try(numDeriv::hessian(cost_function, c(bparms.all, errparms),
+ OLS = FALSE, trans = FALSE, update_data = FALSE), silent = TRUE)
+ })
+
+ fit$error_model_algorithm <- error_model_algorithm
+
+ if (fit$convergence != 0) {
+ fit$warning = paste0("Optimisation did not converge:\n", fit$message)
+ warning(fit$warning)
+ } else {
+ if(!quiet) message("Optimisation successfully terminated.\n")
+ }
+
+ # We need to return some more data for summary and plotting
+ fit$solution_type <- solution_type
+ fit$transform_rates <- transform_rates
+ fit$transform_fractions <- transform_fractions
+ fit$reweight.tol <- reweight.tol
+ fit$reweight.max.iter <- reweight.max.iter
+ fit$control <- control
+ fit$calls <- calls
+ fit$time <- fit_time
+
+ # We also need the model for summary and plotting
+ fit$mkinmod <- mkinmod
+
+ # We need data and predictions for summary and plotting
+ fit$observed <- observed
+ fit$obs_vars <- obs_vars
+ fit$predicted <- out_predicted
+
+ # Residual sum of squares as a function of the fitted parameters
+ fit$rss <- function(P) cost_function(P, OLS = TRUE, update_data = FALSE)
+
+ # Log-likelihood with possibility to fix degparms or errparms
+ fit$ll <- function(P, fixed_degparms = FALSE, fixed_errparms = FALSE) {
+ - cost_function(P, fixed_degparms = fixed_degparms,
+ fixed_errparms = fixed_errparms, OLS = FALSE, update_data = FALSE)
+ }
+
+ # Collect initial parameter values in three dataframes
+ fit$start <- data.frame(value = c(state.ini.optim,
+ parms.optim, errparms_optim))
+ fit$start$type = c(rep("state", length(state.ini.optim)),
+ rep("deparm", length(parms.optim)),
+ rep("error", length(errparms_optim)))
+
+ fit$start_transformed = data.frame(
+ value = c(state.ini.optim, transparms.optim, errparms_optim),
+ lower = lower,
+ upper = upper)
+
+ fit$fixed <- data.frame(value = c(state.ini.fixed, parms.fixed))
+ fit$fixed$type = c(rep("state", length(state.ini.fixed)),
+ rep("deparm", length(parms.fixed)))
+
+ # Sort observed, predicted and residuals
+ current_data$name <- ordered(current_data$name, levels = obs_vars)
+
+ ordered_data <- current_data[order(current_data$name, current_data$time), ]
+
+ fit$data <- data.frame(time = ordered_data$time,
+ variable = ordered_data$name,
+ observed = ordered_data$value.observed,
+ predicted = ordered_data$value.predicted)
+
+ fit$data$residual <- fit$data$observed - fit$data$predicted
+
+ fit$atol <- atol
+ fit$rtol <- rtol
+ fit$err_mod <- err_mod
+
+ # Return different sets of backtransformed parameters for summary and plotting
+ fit$bparms.optim <- bparms.optim
+ fit$bparms.fixed <- bparms.fixed
+
+ # Return ode and state parameters for further fitting
+ fit$bparms.ode <- bparms.all[mkinmod$parms]
+ fit$bparms.state <- c(bparms.all[setdiff(names(bparms.all), names(fit$bparms.ode))],
+ state.ini.fixed)
+ names(fit$bparms.state) <- gsub("_0$", "", names(fit$bparms.state))
+
+ fit$errparms <- errparms
+ fit$df.residual <- n_observed - length(c(degparms, errparms))
+
+ fit$date <- date()
+ fit$version <- as.character(utils::packageVersion("mkin"))
+ fit$Rversion <- paste(R.version$major, R.version$minor, sep=".")
+
+ class(fit) <- c("mkinfit", "modFit")
+ return(fit)
+}
diff --git a/R/mkinmod.R b/R/mkinmod.R
index 26148f18..a1ae0021 100644
--- a/R/mkinmod.R
+++ b/R/mkinmod.R
@@ -1,383 +1,483 @@
-# Copyright (C) 2010-2015,2019 Johannes Ranke {{{
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/> }}}
-
-mkinmod <- function(..., use_of_ff = "min", speclist = NULL, quiet = FALSE, verbose = FALSE)
-{
- if (is.null(speclist)) spec <- list(...)
- else spec <- speclist
- obs_vars <- names(spec)
-
- # Check if any of the names of the observed variables contains any other
- for (obs_var in obs_vars) {
- if (length(grep(obs_var, obs_vars)) > 1) stop("Sorry, variable names can not contain each other")
- if (grepl("_to_", obs_var)) stop("Sorry, names of observed variables can not contain _to_")
- if (obs_var == "sink") stop("Naming a compound 'sink' is not supported")
- }
-
- if (!use_of_ff %in% c("min", "max"))
- stop("The use of formation fractions 'use_of_ff' can only be 'min' or 'max'")
-
- # The returned model will be a list of character vectors, containing {{{
- # differential equations (if supported), parameter names and a mapping from
- # model variables to observed variables. If possible, a matrix representation
- # of the differential equations is included
- # Compiling the functions from the C code generated below only works if the
- # implicit assumption about differential equations specified below
- # is satisfied
- parms <- vector()
- # }}}
-
- # Do not return a coefficient matrix mat when FOMC, IORE, DFOP, HS or logistic is used for the parent {{{
- if(spec[[1]]$type %in% c("FOMC", "IORE", "DFOP", "HS", "logistic")) {
- mat = FALSE
- } else mat = TRUE
- #}}}
-
- # Establish a list of differential equations as well as a map from observed {{{
- # compartments to differential equations
- diffs <- vector()
- map <- list()
- for (varname in obs_vars)
- {
- # Check the type component of the compartment specification {{{
- if(is.null(spec[[varname]]$type)) stop(
- "Every part of the model specification must be a list containing a type component")
- if(!spec[[varname]]$type %in% c("SFO", "FOMC", "IORE", "DFOP", "HS", "SFORB", "logistic")) stop(
- "Available types are SFO, FOMC, IORE, DFOP, HS, SFORB and logistic only")
- if(spec[[varname]]$type %in% c("FOMC", "DFOP", "HS", "logistic") & match(varname, obs_vars) != 1) {
- stop(paste("Types FOMC, DFOP, HS and logistic are only implemented for the first compartment,",
- "which is assumed to be the source compartment"))
- }
- #}}}
- # New (sub)compartments (boxes) needed for the model type {{{
- new_boxes <- switch(spec[[varname]]$type,
- SFO = varname,
- FOMC = varname,
- IORE = varname,
- DFOP = varname,
- HS = varname,
- logistic = varname,
- SFORB = paste(varname, c("free", "bound"), sep = "_")
- )
- map[[varname]] <- new_boxes
- names(map[[varname]]) <- rep(spec[[varname]]$type, length(new_boxes)) #}}}
- # Start a new differential equation for each new box {{{
- new_diffs <- paste("d_", new_boxes, " =", sep = "")
- names(new_diffs) <- new_boxes
- diffs <- c(diffs, new_diffs) #}}}
- } #}}}
-
- # Create content of differential equations and build parameter list {{{
- for (varname in obs_vars)
- {
- # Get the name of the box(es) we are working on for the decline term(s)
- box_1 = map[[varname]][[1]] # This is the only box unless type is SFORB
- # Turn on sink if this is not explicitly excluded by the user by
- # specifying sink=FALSE
- if(is.null(spec[[varname]]$sink)) spec[[varname]]$sink <- TRUE
- if(spec[[varname]]$type %in% c("SFO", "IORE", "SFORB")) { # {{{ Add decline term
- if (use_of_ff == "min") { # Minimum use of formation fractions
- if(spec[[varname]]$type == "IORE" && length(spec[[varname]]$to) > 0) {
- stop("Transformation reactions from compounds modelled with IORE\n",
- "are only supported with formation fractions (use_of_ff = 'max')")
- }
- if(spec[[varname]]$sink) {
- # If sink is required, add first-order/IORE sink term
- k_compound_sink <- paste("k", box_1, "sink", sep = "_")
- if(spec[[varname]]$type == "IORE") {
- k_compound_sink <- paste("k__iore", box_1, "sink", sep = "_")
- }
- parms <- c(parms, k_compound_sink)
- decline_term <- paste(k_compound_sink, "*", box_1)
- if(spec[[varname]]$type == "IORE") {
- N <- paste("N", box_1, sep = "_")
- parms <- c(parms, N)
- decline_term <- paste0(decline_term, "^", N)
- }
- } else { # otherwise no decline term needed here
- decline_term = "0"
- }
- } else {
- k_compound <- paste("k", box_1, sep = "_")
- if(spec[[varname]]$type == "IORE") {
- k_compound <- paste("k__iore", box_1, sep = "_")
- }
- parms <- c(parms, k_compound)
- decline_term <- paste(k_compound, "*", box_1)
- if(spec[[varname]]$type == "IORE") {
- N <- paste("N", box_1, sep = "_")
- parms <- c(parms, N)
- decline_term <- paste0(decline_term, "^", N)
- }
- }
- } #}}}
- if(spec[[varname]]$type == "FOMC") { # {{{ Add FOMC decline term
- # From p. 53 of the FOCUS kinetics report, without the power function so it works in C
- decline_term <- paste("(alpha/beta) * 1/((time/beta) + 1) *", box_1)
- parms <- c(parms, "alpha", "beta")
- } #}}}
- if(spec[[varname]]$type == "DFOP") { # {{{ Add DFOP decline term
- # From p. 57 of the FOCUS kinetics report
- decline_term <- paste("((k1 * g * exp(-k1 * time) + k2 * (1 - g) * exp(-k2 * time)) / (g * exp(-k1 * time) + (1 - g) * exp(-k2 * time))) *", box_1)
- parms <- c(parms, "k1", "k2", "g")
- } #}}}
- HS_decline <- "ifelse(time <= tb, k1, k2)" # Used below for automatic translation to C
- if(spec[[varname]]$type == "HS") { # {{{ Add HS decline term
- # From p. 55 of the FOCUS kinetics report
- decline_term <- paste(HS_decline, "*", box_1)
- parms <- c(parms, "k1", "k2", "tb")
- } #}}}
- if(spec[[varname]]$type == "logistic") { # {{{ Add logistic decline term
- # From p. 67 of the FOCUS kinetics report (2014)
- decline_term <- paste("(k0 * kmax)/(k0 + (kmax - k0) * exp(-r * time)) *", box_1)
- parms <- c(parms, "kmax", "k0", "r")
- } #}}}
- # Add origin decline term to box 1 (usually the only box, unless type is SFORB)#{{{
- diffs[[box_1]] <- paste(diffs[[box_1]], "-", decline_term)#}}}
- if(spec[[varname]]$type == "SFORB") { # {{{ Add SFORB reversible binding terms
- box_2 = map[[varname]][[2]]
- if (use_of_ff == "min") { # Minimum use of formation fractions
- k_free_bound <- paste("k", varname, "free", "bound", sep = "_")
- k_bound_free <- paste("k", varname, "bound", "free", sep = "_")
- parms <- c(parms, k_free_bound, k_bound_free)
- reversible_binding_term_1 <- paste("-", k_free_bound, "*", box_1, "+",
- k_bound_free, "*", box_2)
- reversible_binding_term_2 <- paste("+", k_free_bound, "*", box_1, "-",
- k_bound_free, "*", box_2)
- } else { # Use formation fractions also for the free compartment
- stop("The maximum use of formation fractions is not supported for SFORB models")
- # The problems were: Calculation of dissipation times did not work in this case
- # and the coefficient matrix is not generated correctly by the code present
- # in this file in this case
- #f_free_bound <- paste("f", varname, "free", "bound", sep = "_")
- #k_bound_free <- paste("k", varname, "bound", "free", sep = "_")
- #parms <- c(parms, f_free_bound, k_bound_free)
- #reversible_binding_term_1 <- paste("+", k_bound_free, "*", box_2)
- #reversible_binding_term_2 <- paste("+", f_free_bound, "*", k_compound, "*", box_1, "-",
- # k_bound_free, "*", box_2)
- }
- diffs[[box_1]] <- paste(diffs[[box_1]], reversible_binding_term_1)
- diffs[[box_2]] <- paste(diffs[[box_2]], reversible_binding_term_2)
- } #}}}
-
- # Transfer between compartments#{{{
- to <- spec[[varname]]$to
- if(!is.null(to)) {
- # Name of box from which transfer takes place
- origin_box <- box_1
-
- # Number of targets
- n_targets = length(to)
-
- # Add transfer terms to listed compartments
- for (target in to) {
- if (!target %in% obs_vars) stop("You did not specify a submodel for target variable ", target)
- target_box <- switch(spec[[target]]$type,
- SFO = target,
- IORE = target,
- SFORB = paste(target, "free", sep = "_"))
- if (use_of_ff == "min" && spec[[varname]]$type %in% c("SFO", "SFORB"))
- {
- k_from_to <- paste("k", origin_box, target_box, sep = "_")
- parms <- c(parms, k_from_to)
- diffs[[origin_box]] <- paste(diffs[[origin_box]], "-",
- k_from_to, "*", origin_box)
- diffs[[target_box]] <- paste(diffs[[target_box]], "+",
- k_from_to, "*", origin_box)
- } else {
- # Do not introduce a formation fraction if this is the only target
- if (spec[[origin_box]]$sink == FALSE && n_targets == 1) {
- diffs[[target_box]] <- paste(diffs[[target_box]], "+",
- decline_term)
- } else {
- fraction_to_target = paste("f", origin_box, "to", target, sep = "_")
- parms <- c(parms, fraction_to_target)
- diffs[[target_box]] <- paste(diffs[[target_box]], "+",
- fraction_to_target, "*", decline_term)
- }
- }
- }
- } #}}}
- } #}}}
-
- model <- list(diffs = diffs, parms = parms, map = map, spec = spec, use_of_ff = use_of_ff)
-
- # Create coefficient matrix if appropriate#{{{
- if (mat) {
- boxes <- names(diffs)
- n <- length(boxes)
- m <- matrix(nrow=n, ncol=n, dimnames=list(boxes, boxes))
-
- if (use_of_ff == "min") { # {{{ Minimum use of formation fractions
- for (from in boxes) {
- for (to in boxes) {
- if (from == to) { # diagonal elements
- k.candidate = paste("k", from, c(boxes, "sink"), sep = "_")
- k.candidate = sub("free.*bound", "free_bound", k.candidate)
- k.candidate = sub("bound.*free", "bound_free", k.candidate)
- k.effective = intersect(model$parms, k.candidate)
- m[from,to] = ifelse(length(k.effective) > 0,
- paste("-", k.effective, collapse = " "), "0")
-
- } else { # off-diagonal elements
- k.candidate = paste("k", from, to, sep = "_")
- if (sub("_free$", "", from) == sub("_bound$", "", to)) {
- k.candidate = paste("k", sub("_free$", "_free_bound", from), sep = "_")
- }
- if (sub("_bound$", "", from) == sub("_free$", "", to)) {
- k.candidate = paste("k", sub("_bound$", "_bound_free", from), sep = "_")
- }
- k.effective = intersect(model$parms, k.candidate)
- m[to, from] = ifelse(length(k.effective) > 0,
- k.effective, "0")
- }
- }
- } # }}}
- } else { # {{{ Use formation fractions where possible
- for (from in boxes) {
- for (to in boxes) {
- if (from == to) { # diagonal elements
- k.candidate = paste("k", from, sep = "_")
- m[from,to] = ifelse(k.candidate %in% model$parms,
- paste("-", k.candidate), "0")
- if(grepl("_free", from)) { # add transfer to bound compartment for SFORB
- m[from,to] = paste(m[from,to], "-", paste("k", from, "bound", sep = "_"))
- }
- if(grepl("_bound", from)) { # add backtransfer to free compartment for SFORB
- m[from,to] = paste("- k", from, "free", sep = "_")
- }
- m[from,to] = m[from,to]
- } else { # off-diagonal elements
- f.candidate = paste("f", from, "to", to, sep = "_")
- k.candidate = paste("k", from, to, sep = "_")
- # SFORB with maximum use of formation fractions not implemented, see above
- m[to, from] = ifelse(f.candidate %in% model$parms,
- paste(f.candidate, " * k_", from, sep = ""),
- ifelse(k.candidate %in% model$parms, k.candidate, "0"))
- # Special case: singular pathway and no sink
- if (spec[[from]]$sink == FALSE && length(spec[[from]]$to) == 1 && to %in% spec[[from]]$to) {
- m[to, from] = paste("k", from, sep = "_")
- }
- }
- }
- }
- } # }}}
- model$coefmat <- m
- }#}}}
-
- # Try to create a function compiled from C code if more than one observed {{{
- # variable and gcc is available
- if (length(obs_vars) > 1) {
- if (Sys.which("gcc") != "") {
-
- # Translate the R code for the derivatives to C code
- diffs.C <- paste(diffs, collapse = ";\n")
- diffs.C <- paste0(diffs.C, ";")
-
- # HS
- diffs.C <- gsub(HS_decline, "(time <= tb ? k1 : k2)", diffs.C, fixed = TRUE)
-
- for (i in seq_along(diffs)) {
- state_var <- names(diffs)[i]
-
- # IORE
- if (state_var %in% obs_vars) {
- if (spec[[state_var]]$type == "IORE") {
- diffs.C <- gsub(paste0(state_var, "^N_", state_var),
- paste0("pow(y[", i - 1, "], N_", state_var, ")"),
- diffs.C, fixed = TRUE)
- }
- }
-
- # Replace d_... terms by f[i-1]
- # First line
- pattern <- paste0("^d_", state_var)
- replacement <- paste0("\nf[", i - 1, "]")
- diffs.C <- gsub(pattern, replacement, diffs.C)
- # Other lines
- pattern <- paste0("\\nd_", state_var)
- replacement <- paste0("\nf[", i - 1, "]")
- diffs.C <- gsub(pattern, replacement, diffs.C)
-
- # Replace names of observed variables by y[i],
- # making the implicit assumption that the observed variables only occur after "* "
- pattern <- paste0("\\* ", state_var)
- replacement <- paste0("* y[", i - 1, "]")
- diffs.C <- gsub(pattern, replacement, diffs.C)
- }
-
- derivs_sig <- signature(n = "integer", t = "numeric", y = "numeric",
- f = "numeric", rpar = "numeric", ipar = "integer")
-
- # Declare the time variable in the body of the function if it is used
- derivs_code <- if (spec[[1]]$type %in% c("FOMC", "DFOP", "HS")) {
- paste0("double time = *t;\n", diffs.C)
- } else {
- diffs.C
- }
-
- # Define the function initializing the parameters
- npar <- length(parms)
- initpar_code <- paste0(
- "static double parms [", npar, "];\n",
- paste0("#define ", parms, " parms[", 0:(npar - 1), "]\n", collapse = ""),
- "\n",
- "void initpar(void (* odeparms)(int *, double *)) {\n",
- " int N = ", npar, ";\n",
- " odeparms(&N, parms);\n",
- "}\n\n")
-
- # Try to build a shared library
- cf <- try(cfunction(list(func = derivs_sig), derivs_code,
- otherdefs = initpar_code,
- verbose = verbose,
- convention = ".C", language = "C"),
- silent = TRUE)
-
- if (!inherits(cf, "try-error")) {
- if (!quiet) message("Successfully compiled differential equation model from auto-generated C code.")
- model$cf <- cf
- }
- }
- }
- # }}}
-
- class(model) <- "mkinmod"
- return(model)
-}
-
-print.mkinmod <- function(x, ...) {
- cat("<mkinmod> model generated with\n")
- cat("Use of formation fractions $use_of_ff:", x$use_of_ff, "\n")
- cat("Specification $spec:\n")
- for (obs in names(x$spec)) {
- cat("$", obs, "\n", sep = "")
- spl <- x$spec[[obs]]
- cat("$type:", spl$type)
- if (!is.null(spl$to) && length(spl$to)) cat("; $to: ", paste(spl$to, collapse = ", "), sep = "")
- cat("; $sink: ", spl$sink, sep = "")
- if (!is.null(spl$full_name)) if (!is.na(spl$full_name)) cat("; $full_name:", spl$full_name)
- cat("\n")
- }
- if (is.matrix(x$coefmat)) cat("Coefficient matrix $coefmat available\n")
- if (!is.null(x$cf)) cat("Compiled model $cf available\n")
- cat("Differential equations:\n")
- nice_diffs <- gsub("^(d.*) =", "\\1/dt =", x[["diffs"]])
- writeLines(strwrap(nice_diffs, exdent = 11))
-}
-# vim: set foldmethod=marker ts=2 sw=2 expandtab:
+#' Function to set up a kinetic model with one or more state variables
+#'
+#' The function usually takes several expressions, each assigning a compound
+#' name to a list, specifying the kinetic model type and reaction or transfer
+#' to other observed compartments. Instead of specifying several expressions, a
+#' list of lists can be given in the speclist argument.
+#'
+#' For the definition of model types and their parameters, the equations given
+#' in the FOCUS and NAFTA guidance documents are used.
+#'
+#' @param ... For each observed variable, a list has to be specified as an
+#' argument, containing at least a component \code{type}, specifying the type
+#' of kinetics to use for the variable. Currently, single first order
+#' kinetics "SFO", indeterminate order rate equation kinetics "IORE", or
+#' single first order with reversible binding "SFORB" are implemented for all
+#' variables, while "FOMC", "DFOP" and "HS" can additionally be chosen for
+#' the first variable which is assumed to be the source compartment.
+#' Additionally, each component of the list can include a character vector
+#' \code{to}, specifying names of variables to which a transfer is to be
+#' assumed in the model. If the argument \code{use_of_ff} is set to "min"
+#' (default) and the model for the compartment is "SFO" or "SFORB", an
+#' additional component of the list can be "sink=FALSE" effectively fixing
+#' the flux to sink to zero.
+#' @param use_of_ff Specification of the use of formation fractions in the
+#' model equations and, if applicable, the coefficient matrix. If "min", a
+#' minimum use of formation fractions is made in order to avoid fitting the
+#' product of formation fractions and rate constants. If "max", formation
+#' fractions are always used.
+#' @param speclist The specification of the observed variables and their
+#' submodel types and pathways can be given as a single list using this
+#' argument. Default is NULL.
+#' @param quiet Should messages be suppressed?
+#' @param verbose If \code{TRUE}, passed to \code{\link{cfunction}} if
+#' applicable to give detailed information about the C function being built.
+#' @importFrom methods signature
+#' @importFrom inline cfunction
+#' @return A list of class \code{mkinmod} for use with \code{\link{mkinfit}},
+#' containing, among others,
+#' \item{diffs}{
+#' A vector of string representations of differential equations, one for
+#' each modelling variable.
+#' }
+#' \item{map}{
+#' A list containing named character vectors for each observed variable,
+#' specifying the modelling variables by which it is represented.
+#' }
+#' \item{use_of_ff}{
+#' The content of \code{use_of_ff} is passed on in this list component.
+#' }
+#' \item{coefmat}{
+#' The coefficient matrix, if the system of differential equations can be
+#' represented by one.
+#' }
+#' \item{ll}{
+#' The likelihood function, taking the parameter vector as the first argument.
+#' }
+#' @note The IORE submodel is not well tested for metabolites. When using this
+#' model for metabolites, you may want to read the second note in the help
+#' page to \code{\link{mkinfit}}.
+#' @author Johannes Ranke
+#' @references FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence
+#' and Degradation Kinetics from Environmental Fate Studies on Pesticides in
+#' EU Registration} Report of the FOCUS Work Group on Degradation Kinetics,
+#' EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
+#' \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+#'
+#' NAFTA Technical Working Group on Pesticides (not dated) Guidance for
+#' Evaluating and Calculating Degradation Kinetics in Environmental Media
+#' @examples
+#'
+#' # Specify the SFO model (this is not needed any more, as we can now mkinfit("SFO", ...)
+#' SFO <- mkinmod(parent = list(type = "SFO"))
+#'
+#' # One parent compound, one metabolite, both single first order
+#' SFO_SFO <- mkinmod(
+#' parent = mkinsub("SFO", "m1"),
+#' m1 = mkinsub("SFO"))
+#'
+#' \dontrun{
+#' # The above model used to be specified like this, before the advent of mkinsub()
+#' SFO_SFO <- mkinmod(
+#' parent = list(type = "SFO", to = "m1"),
+#' m1 = list(type = "SFO"))
+#'
+#' # Show details of creating the C function
+#' SFO_SFO <- mkinmod(
+#' parent = mkinsub("SFO", "m1"),
+#' m1 = mkinsub("SFO"), verbose = TRUE)
+#'
+#' # If we have several parallel metabolites
+#' # (compare tests/testthat/test_synthetic_data_for_UBA_2014.R)
+#' m_synth_DFOP_par <- mkinmod(parent = mkinsub("DFOP", c("M1", "M2")),
+#' M1 = mkinsub("SFO"),
+#' M2 = mkinsub("SFO"),
+#' use_of_ff = "max", quiet = TRUE)
+#'
+#' fit_DFOP_par_c <- mkinfit(m_synth_DFOP_par,
+#' synthetic_data_for_UBA_2014[[12]]$data,
+#' quiet = TRUE)
+#' }
+#'
+#' @export mkinmod
+mkinmod <- function(..., use_of_ff = "min", speclist = NULL, quiet = FALSE, verbose = FALSE)
+{
+ if (is.null(speclist)) spec <- list(...)
+ else spec <- speclist
+ obs_vars <- names(spec)
+
+ # Check if any of the names of the observed variables contains any other
+ for (obs_var in obs_vars) {
+ if (length(grep(obs_var, obs_vars)) > 1) stop("Sorry, variable names can not contain each other")
+ if (grepl("_to_", obs_var)) stop("Sorry, names of observed variables can not contain _to_")
+ if (obs_var == "sink") stop("Naming a compound 'sink' is not supported")
+ }
+
+ if (!use_of_ff %in% c("min", "max"))
+ stop("The use of formation fractions 'use_of_ff' can only be 'min' or 'max'")
+
+ # The returned model will be a list of character vectors, containing {{{
+ # differential equations (if supported), parameter names and a mapping from
+ # model variables to observed variables. If possible, a matrix representation
+ # of the differential equations is included
+ # Compiling the functions from the C code generated below only works if the
+ # implicit assumption about differential equations specified below
+ # is satisfied
+ parms <- vector()
+ # }}}
+
+ # Do not return a coefficient matrix mat when FOMC, IORE, DFOP, HS or logistic is used for the parent {{{
+ if(spec[[1]]$type %in% c("FOMC", "IORE", "DFOP", "HS", "logistic")) {
+ mat = FALSE
+ } else mat = TRUE
+ #}}}
+
+ # Establish a list of differential equations as well as a map from observed {{{
+ # compartments to differential equations
+ diffs <- vector()
+ map <- list()
+ for (varname in obs_vars)
+ {
+ # Check the type component of the compartment specification {{{
+ if(is.null(spec[[varname]]$type)) stop(
+ "Every part of the model specification must be a list containing a type component")
+ if(!spec[[varname]]$type %in% c("SFO", "FOMC", "IORE", "DFOP", "HS", "SFORB", "logistic")) stop(
+ "Available types are SFO, FOMC, IORE, DFOP, HS, SFORB and logistic only")
+ if(spec[[varname]]$type %in% c("FOMC", "DFOP", "HS", "logistic") & match(varname, obs_vars) != 1) {
+ stop(paste("Types FOMC, DFOP, HS and logistic are only implemented for the first compartment,",
+ "which is assumed to be the source compartment"))
+ }
+ #}}}
+ # New (sub)compartments (boxes) needed for the model type {{{
+ new_boxes <- switch(spec[[varname]]$type,
+ SFO = varname,
+ FOMC = varname,
+ IORE = varname,
+ DFOP = varname,
+ HS = varname,
+ logistic = varname,
+ SFORB = paste(varname, c("free", "bound"), sep = "_")
+ )
+ map[[varname]] <- new_boxes
+ names(map[[varname]]) <- rep(spec[[varname]]$type, length(new_boxes)) #}}}
+ # Start a new differential equation for each new box {{{
+ new_diffs <- paste("d_", new_boxes, " =", sep = "")
+ names(new_diffs) <- new_boxes
+ diffs <- c(diffs, new_diffs) #}}}
+ } #}}}
+
+ # Create content of differential equations and build parameter list {{{
+ for (varname in obs_vars)
+ {
+ # Get the name of the box(es) we are working on for the decline term(s)
+ box_1 = map[[varname]][[1]] # This is the only box unless type is SFORB
+ # Turn on sink if this is not explicitly excluded by the user by
+ # specifying sink=FALSE
+ if(is.null(spec[[varname]]$sink)) spec[[varname]]$sink <- TRUE
+ if(spec[[varname]]$type %in% c("SFO", "IORE", "SFORB")) { # {{{ Add decline term
+ if (use_of_ff == "min") { # Minimum use of formation fractions
+ if(spec[[varname]]$type == "IORE" && length(spec[[varname]]$to) > 0) {
+ stop("Transformation reactions from compounds modelled with IORE\n",
+ "are only supported with formation fractions (use_of_ff = 'max')")
+ }
+ if(spec[[varname]]$sink) {
+ # If sink is required, add first-order/IORE sink term
+ k_compound_sink <- paste("k", box_1, "sink", sep = "_")
+ if(spec[[varname]]$type == "IORE") {
+ k_compound_sink <- paste("k__iore", box_1, "sink", sep = "_")
+ }
+ parms <- c(parms, k_compound_sink)
+ decline_term <- paste(k_compound_sink, "*", box_1)
+ if(spec[[varname]]$type == "IORE") {
+ N <- paste("N", box_1, sep = "_")
+ parms <- c(parms, N)
+ decline_term <- paste0(decline_term, "^", N)
+ }
+ } else { # otherwise no decline term needed here
+ decline_term = "0"
+ }
+ } else {
+ k_compound <- paste("k", box_1, sep = "_")
+ if(spec[[varname]]$type == "IORE") {
+ k_compound <- paste("k__iore", box_1, sep = "_")
+ }
+ parms <- c(parms, k_compound)
+ decline_term <- paste(k_compound, "*", box_1)
+ if(spec[[varname]]$type == "IORE") {
+ N <- paste("N", box_1, sep = "_")
+ parms <- c(parms, N)
+ decline_term <- paste0(decline_term, "^", N)
+ }
+ }
+ } #}}}
+ if(spec[[varname]]$type == "FOMC") { # {{{ Add FOMC decline term
+ # From p. 53 of the FOCUS kinetics report, without the power function so it works in C
+ decline_term <- paste("(alpha/beta) * 1/((time/beta) + 1) *", box_1)
+ parms <- c(parms, "alpha", "beta")
+ } #}}}
+ if(spec[[varname]]$type == "DFOP") { # {{{ Add DFOP decline term
+ # From p. 57 of the FOCUS kinetics report
+ decline_term <- paste("((k1 * g * exp(-k1 * time) + k2 * (1 - g) * exp(-k2 * time)) / (g * exp(-k1 * time) + (1 - g) * exp(-k2 * time))) *", box_1)
+ parms <- c(parms, "k1", "k2", "g")
+ } #}}}
+ HS_decline <- "ifelse(time <= tb, k1, k2)" # Used below for automatic translation to C
+ if(spec[[varname]]$type == "HS") { # {{{ Add HS decline term
+ # From p. 55 of the FOCUS kinetics report
+ decline_term <- paste(HS_decline, "*", box_1)
+ parms <- c(parms, "k1", "k2", "tb")
+ } #}}}
+ if(spec[[varname]]$type == "logistic") { # {{{ Add logistic decline term
+ # From p. 67 of the FOCUS kinetics report (2014)
+ decline_term <- paste("(k0 * kmax)/(k0 + (kmax - k0) * exp(-r * time)) *", box_1)
+ parms <- c(parms, "kmax", "k0", "r")
+ } #}}}
+ # Add origin decline term to box 1 (usually the only box, unless type is SFORB)#{{{
+ diffs[[box_1]] <- paste(diffs[[box_1]], "-", decline_term)#}}}
+ if(spec[[varname]]$type == "SFORB") { # {{{ Add SFORB reversible binding terms
+ box_2 = map[[varname]][[2]]
+ if (use_of_ff == "min") { # Minimum use of formation fractions
+ k_free_bound <- paste("k", varname, "free", "bound", sep = "_")
+ k_bound_free <- paste("k", varname, "bound", "free", sep = "_")
+ parms <- c(parms, k_free_bound, k_bound_free)
+ reversible_binding_term_1 <- paste("-", k_free_bound, "*", box_1, "+",
+ k_bound_free, "*", box_2)
+ reversible_binding_term_2 <- paste("+", k_free_bound, "*", box_1, "-",
+ k_bound_free, "*", box_2)
+ } else { # Use formation fractions also for the free compartment
+ stop("The maximum use of formation fractions is not supported for SFORB models")
+ # The problems were: Calculation of dissipation times did not work in this case
+ # and the coefficient matrix is not generated correctly by the code present
+ # in this file in this case
+ #f_free_bound <- paste("f", varname, "free", "bound", sep = "_")
+ #k_bound_free <- paste("k", varname, "bound", "free", sep = "_")
+ #parms <- c(parms, f_free_bound, k_bound_free)
+ #reversible_binding_term_1 <- paste("+", k_bound_free, "*", box_2)
+ #reversible_binding_term_2 <- paste("+", f_free_bound, "*", k_compound, "*", box_1, "-",
+ # k_bound_free, "*", box_2)
+ }
+ diffs[[box_1]] <- paste(diffs[[box_1]], reversible_binding_term_1)
+ diffs[[box_2]] <- paste(diffs[[box_2]], reversible_binding_term_2)
+ } #}}}
+
+ # Transfer between compartments#{{{
+ to <- spec[[varname]]$to
+ if(!is.null(to)) {
+ # Name of box from which transfer takes place
+ origin_box <- box_1
+
+ # Number of targets
+ n_targets = length(to)
+
+ # Add transfer terms to listed compartments
+ for (target in to) {
+ if (!target %in% obs_vars) stop("You did not specify a submodel for target variable ", target)
+ target_box <- switch(spec[[target]]$type,
+ SFO = target,
+ IORE = target,
+ SFORB = paste(target, "free", sep = "_"))
+ if (use_of_ff == "min" && spec[[varname]]$type %in% c("SFO", "SFORB"))
+ {
+ k_from_to <- paste("k", origin_box, target_box, sep = "_")
+ parms <- c(parms, k_from_to)
+ diffs[[origin_box]] <- paste(diffs[[origin_box]], "-",
+ k_from_to, "*", origin_box)
+ diffs[[target_box]] <- paste(diffs[[target_box]], "+",
+ k_from_to, "*", origin_box)
+ } else {
+ # Do not introduce a formation fraction if this is the only target
+ if (spec[[origin_box]]$sink == FALSE && n_targets == 1) {
+ diffs[[target_box]] <- paste(diffs[[target_box]], "+",
+ decline_term)
+ } else {
+ fraction_to_target = paste("f", origin_box, "to", target, sep = "_")
+ parms <- c(parms, fraction_to_target)
+ diffs[[target_box]] <- paste(diffs[[target_box]], "+",
+ fraction_to_target, "*", decline_term)
+ }
+ }
+ }
+ } #}}}
+ } #}}}
+
+ model <- list(diffs = diffs, parms = parms, map = map, spec = spec, use_of_ff = use_of_ff)
+
+ # Create coefficient matrix if appropriate#{{{
+ if (mat) {
+ boxes <- names(diffs)
+ n <- length(boxes)
+ m <- matrix(nrow=n, ncol=n, dimnames=list(boxes, boxes))
+
+ if (use_of_ff == "min") { # {{{ Minimum use of formation fractions
+ for (from in boxes) {
+ for (to in boxes) {
+ if (from == to) { # diagonal elements
+ k.candidate = paste("k", from, c(boxes, "sink"), sep = "_")
+ k.candidate = sub("free.*bound", "free_bound", k.candidate)
+ k.candidate = sub("bound.*free", "bound_free", k.candidate)
+ k.effective = intersect(model$parms, k.candidate)
+ m[from,to] = ifelse(length(k.effective) > 0,
+ paste("-", k.effective, collapse = " "), "0")
+
+ } else { # off-diagonal elements
+ k.candidate = paste("k", from, to, sep = "_")
+ if (sub("_free$", "", from) == sub("_bound$", "", to)) {
+ k.candidate = paste("k", sub("_free$", "_free_bound", from), sep = "_")
+ }
+ if (sub("_bound$", "", from) == sub("_free$", "", to)) {
+ k.candidate = paste("k", sub("_bound$", "_bound_free", from), sep = "_")
+ }
+ k.effective = intersect(model$parms, k.candidate)
+ m[to, from] = ifelse(length(k.effective) > 0,
+ k.effective, "0")
+ }
+ }
+ } # }}}
+ } else { # {{{ Use formation fractions where possible
+ for (from in boxes) {
+ for (to in boxes) {
+ if (from == to) { # diagonal elements
+ k.candidate = paste("k", from, sep = "_")
+ m[from,to] = ifelse(k.candidate %in% model$parms,
+ paste("-", k.candidate), "0")
+ if(grepl("_free", from)) { # add transfer to bound compartment for SFORB
+ m[from,to] = paste(m[from,to], "-", paste("k", from, "bound", sep = "_"))
+ }
+ if(grepl("_bound", from)) { # add backtransfer to free compartment for SFORB
+ m[from,to] = paste("- k", from, "free", sep = "_")
+ }
+ m[from,to] = m[from,to]
+ } else { # off-diagonal elements
+ f.candidate = paste("f", from, "to", to, sep = "_")
+ k.candidate = paste("k", from, to, sep = "_")
+ # SFORB with maximum use of formation fractions not implemented, see above
+ m[to, from] = ifelse(f.candidate %in% model$parms,
+ paste(f.candidate, " * k_", from, sep = ""),
+ ifelse(k.candidate %in% model$parms, k.candidate, "0"))
+ # Special case: singular pathway and no sink
+ if (spec[[from]]$sink == FALSE && length(spec[[from]]$to) == 1 && to %in% spec[[from]]$to) {
+ m[to, from] = paste("k", from, sep = "_")
+ }
+ }
+ }
+ }
+ } # }}}
+ model$coefmat <- m
+ }#}}}
+
+ # Try to create a function compiled from C code if more than one observed {{{
+ # variable and gcc is available
+ if (length(obs_vars) > 1) {
+ if (Sys.which("gcc") != "") {
+
+ # Translate the R code for the derivatives to C code
+ diffs.C <- paste(diffs, collapse = ";\n")
+ diffs.C <- paste0(diffs.C, ";")
+
+ # HS
+ diffs.C <- gsub(HS_decline, "(time <= tb ? k1 : k2)", diffs.C, fixed = TRUE)
+
+ for (i in seq_along(diffs)) {
+ state_var <- names(diffs)[i]
+
+ # IORE
+ if (state_var %in% obs_vars) {
+ if (spec[[state_var]]$type == "IORE") {
+ diffs.C <- gsub(paste0(state_var, "^N_", state_var),
+ paste0("pow(y[", i - 1, "], N_", state_var, ")"),
+ diffs.C, fixed = TRUE)
+ }
+ }
+
+ # Replace d_... terms by f[i-1]
+ # First line
+ pattern <- paste0("^d_", state_var)
+ replacement <- paste0("\nf[", i - 1, "]")
+ diffs.C <- gsub(pattern, replacement, diffs.C)
+ # Other lines
+ pattern <- paste0("\\nd_", state_var)
+ replacement <- paste0("\nf[", i - 1, "]")
+ diffs.C <- gsub(pattern, replacement, diffs.C)
+
+ # Replace names of observed variables by y[i],
+ # making the implicit assumption that the observed variables only occur after "* "
+ pattern <- paste0("\\* ", state_var)
+ replacement <- paste0("* y[", i - 1, "]")
+ diffs.C <- gsub(pattern, replacement, diffs.C)
+ }
+
+ derivs_sig <- signature(n = "integer", t = "numeric", y = "numeric",
+ f = "numeric", rpar = "numeric", ipar = "integer")
+
+ # Declare the time variable in the body of the function if it is used
+ derivs_code <- if (spec[[1]]$type %in% c("FOMC", "DFOP", "HS")) {
+ paste0("double time = *t;\n", diffs.C)
+ } else {
+ diffs.C
+ }
+
+ # Define the function initializing the parameters
+ npar <- length(parms)
+ initpar_code <- paste0(
+ "static double parms [", npar, "];\n",
+ paste0("#define ", parms, " parms[", 0:(npar - 1), "]\n", collapse = ""),
+ "\n",
+ "void initpar(void (* odeparms)(int *, double *)) {\n",
+ " int N = ", npar, ";\n",
+ " odeparms(&N, parms);\n",
+ "}\n\n")
+
+ # Try to build a shared library
+ cf <- try(cfunction(list(func = derivs_sig), derivs_code,
+ otherdefs = initpar_code,
+ verbose = verbose,
+ convention = ".C", language = "C"),
+ silent = TRUE)
+
+ if (!inherits(cf, "try-error")) {
+ if (!quiet) message("Successfully compiled differential equation model from auto-generated C code.")
+ model$cf <- cf
+ }
+ }
+ }
+ # }}}
+
+ class(model) <- "mkinmod"
+ return(model)
+}
+
+#' Print mkinmod objects
+#'
+#' Print mkinmod objects in a way that the user finds his way to get to its
+#' components.
+#'
+#' @param x An \code{\link{mkinmod}} object.
+#' @param \dots Not used.
+#' @examples
+#'
+#' m_synth_SFO_lin <- mkinmod(parent = list(type = "SFO", to = "M1"),
+#' M1 = list(type = "SFO", to = "M2"),
+#' M2 = list(type = "SFO"), use_of_ff = "max")
+#'
+#' print(m_synth_SFO_lin)
+#'
+#' @export
+print.mkinmod <- function(x, ...) {
+ cat("<mkinmod> model generated with\n")
+ cat("Use of formation fractions $use_of_ff:", x$use_of_ff, "\n")
+ cat("Specification $spec:\n")
+ for (obs in names(x$spec)) {
+ cat("$", obs, "\n", sep = "")
+ spl <- x$spec[[obs]]
+ cat("$type:", spl$type)
+ if (!is.null(spl$to) && length(spl$to)) cat("; $to: ", paste(spl$to, collapse = ", "), sep = "")
+ cat("; $sink: ", spl$sink, sep = "")
+ if (!is.null(spl$full_name)) if (!is.na(spl$full_name)) cat("; $full_name:", spl$full_name)
+ cat("\n")
+ }
+ if (is.matrix(x$coefmat)) cat("Coefficient matrix $coefmat available\n")
+ if (!is.null(x$cf)) cat("Compiled model $cf available\n")
+ cat("Differential equations:\n")
+ nice_diffs <- gsub("^(d.*) =", "\\1/dt =", x[["diffs"]])
+ writeLines(strwrap(nice_diffs, exdent = 11))
+}
+# vim: set foldmethod=marker ts=2 sw=2 expandtab:
diff --git a/R/mkinparplot.R b/R/mkinparplot.R
index af28e3a8..f9abab5b 100644
--- a/R/mkinparplot.R
+++ b/R/mkinparplot.R
@@ -1,20 +1,23 @@
-# Copyright (C) 2014 Johannes Ranke
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
+#' Function to plot the confidence intervals obtained using mkinfit
+#'
+#' This function plots the confidence intervals for the parameters fitted using
+#' \code{\link{mkinfit}}.
+#'
+#' @param object A fit represented in an \code{\link{mkinfit}} object.
+#' @return Nothing is returned by this function, as it is called for its side
+#' effect, namely to produce a plot.
+#' @author Johannes Ranke
+#' @examples
+#'
+#' \dontrun{
+#' model <- mkinmod(
+#' T245 = mkinsub("SFO", to = c("phenol"), sink = FALSE),
+#' phenol = mkinsub("SFO", to = c("anisole")),
+#' anisole = mkinsub("SFO"), use_of_ff = "max")
+#' fit <- mkinfit(model, subset(mccall81_245T, soil == "Commerce"), quiet = TRUE)
+#' mkinparplot(fit)
+#' }
+#' @export
mkinparplot <- function(object) {
state.optim = rownames(subset(object$start, type == "state"))
deparms.optim = rownames(subset(object$start, type == "deparm"))
diff --git a/R/mkinplot.R b/R/mkinplot.R
deleted file mode 100644
index b9becfdf..00000000
--- a/R/mkinplot.R
+++ /dev/null
@@ -1,4 +0,0 @@
-mkinplot <- function(fit, ...)
-{
- plot(fit, ...)
-}
diff --git a/R/mkinpredict.R b/R/mkinpredict.R
index c36d724a..8949e800 100644
--- a/R/mkinpredict.R
+++ b/R/mkinpredict.R
@@ -1,22 +1,99 @@
-# Copyright (C) 2010-2016,2018,2019 Johannes Ranke
-# Some lines in this code are copyright (C) 2013 Eurofins Regulatory AG
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
-
+#' Produce predictions from a kinetic model using specific parameters
+#'
+#' This function produces a time series for all the observed variables in a
+#' kinetic model as specified by \code{\link{mkinmod}}, using a specific set of
+#' kinetic parameters and initial values for the state variables.
+#'
+#' @aliases mkinpredict mkinpredict.mkinmod mkinpredict.mkinfit
+#' @param x A kinetic model as produced by \code{\link{mkinmod}}, or a kinetic
+#' fit as fitted by \code{\link{mkinfit}}. In the latter case, the fitted
+#' parameters are used for the prediction.
+#' @param odeparms A numeric vector specifying the parameters used in the
+#' kinetic model, which is generally defined as a set of ordinary
+#' differential equations.
+#' @param odeini A numeric vectory containing the initial values of the state
+#' variables of the model. Note that the state variables can differ from the
+#' observed variables, for example in the case of the SFORB model.
+#' @param outtimes A numeric vector specifying the time points for which model
+#' predictions should be generated.
+#' @param solution_type The method that should be used for producing the
+#' predictions. This should generally be "analytical" if there is only one
+#' observed variable, and usually "deSolve" in the case of several observed
+#' variables. The third possibility "eigen" is faster but not applicable to
+#' some models e.g. using FOMC for the parent compound.
+#' @param method.ode The solution method passed via \code{\link{mkinpredict}}
+#' to \code{\link{ode}} in case the solution type is "deSolve". The default
+#' "lsoda" is performant, but sometimes fails to converge.
+#' @param use_compiled If set to \code{FALSE}, no compiled version of the
+#' \code{\link{mkinmod}} model is used, even if is present.
+#' @param atol Absolute error tolerance, passed to \code{\link{ode}}. Default
+#' is 1e-8, lower than in \code{\link{lsoda}}.
+#' @param rtol Absolute error tolerance, passed to \code{\link{ode}}. Default
+#' is 1e-10, much lower than in \code{\link{lsoda}}.
+#' @param map_output Boolean to specify if the output should list values for
+#' the observed variables (default) or for all state variables (if set to
+#' FALSE).
+#' @param \dots Further arguments passed to the ode solver in case such a
+#' solver is used.
+#' @import deSolve
+#' @importFrom inline getDynLib
+#' @return A matrix in the same format as the output of \code{\link{ode}}.
+#' @author Johannes Ranke
+#' @examples
+#'
+#' SFO <- mkinmod(degradinol = mkinsub("SFO"))
+#' # Compare solution types
+#' mkinpredict(SFO, c(k_degradinol_sink = 0.3), c(degradinol = 100), 0:20,
+#' solution_type = "analytical")
+#' mkinpredict(SFO, c(k_degradinol_sink = 0.3), c(degradinol = 100), 0:20,
+#' solution_type = "deSolve")
+#' mkinpredict(SFO, c(k_degradinol_sink = 0.3), c(degradinol = 100), 0:20,
+#' solution_type = "deSolve", use_compiled = FALSE)
+#' mkinpredict(SFO, c(k_degradinol_sink = 0.3), c(degradinol = 100), 0:20,
+#' solution_type = "eigen")
+#'
+#'
+#' # Compare integration methods to analytical solution
+#' mkinpredict(SFO, c(k_degradinol_sink = 0.3), c(degradinol = 100), 0:20,
+#' solution_type = "analytical")[21,]
+#' mkinpredict(SFO, c(k_degradinol_sink = 0.3), c(degradinol = 100), 0:20,
+#' method = "lsoda")[21,]
+#' mkinpredict(SFO, c(k_degradinol_sink = 0.3), c(degradinol = 100), 0:20,
+#' method = "ode45")[21,]
+#' mkinpredict(SFO, c(k_degradinol_sink = 0.3), c(degradinol = 100), 0:20,
+#' method = "rk4")[21,]
+#' # rk4 is not as precise here
+#'
+#' # The number of output times used to make a lot of difference until the
+#' # default for atol was adjusted
+#' mkinpredict(SFO, c(k_degradinol_sink = 0.3), c(degradinol = 100),
+#' seq(0, 20, by = 0.1))[201,]
+#' mkinpredict(SFO, c(k_degradinol_sink = 0.3), c(degradinol = 100),
+#' seq(0, 20, by = 0.01))[2001,]
+#'
+#' # Check compiled model versions - they are faster than the eigenvalue based solutions!
+#' SFO_SFO = mkinmod(parent = list(type = "SFO", to = "m1"),
+#' m1 = list(type = "SFO"))
+#' system.time(
+#' print(mkinpredict(SFO_SFO, c(k_parent_m1 = 0.05, k_parent_sink = 0.1, k_m1_sink = 0.01),
+#' c(parent = 100, m1 = 0), seq(0, 20, by = 0.1),
+#' solution_type = "eigen")[201,]))
+#' system.time(
+#' print(mkinpredict(SFO_SFO, c(k_parent_m1 = 0.05, k_parent_sink = 0.1, k_m1_sink = 0.01),
+#' c(parent = 100, m1 = 0), seq(0, 20, by = 0.1),
+#' solution_type = "deSolve")[201,]))
+#' system.time(
+#' print(mkinpredict(SFO_SFO, c(k_parent_m1 = 0.05, k_parent_sink = 0.1, k_m1_sink = 0.01),
+#' c(parent = 100, m1 = 0), seq(0, 20, by = 0.1),
+#' solution_type = "deSolve", use_compiled = FALSE)[201,]))
+#'
+#' \dontrun{
+#' # Predict from a fitted model
+#' f <- mkinfit(SFO_SFO, FOCUS_2006_C)
+#' head(mkinpredict(f))
+#' }
+#'
+#' @export
mkinpredict <- function(x, odeparms, odeini,
outtimes = seq(0, 120, by = 0.1),
solution_type = "deSolve",
@@ -27,6 +104,8 @@ mkinpredict <- function(x, odeparms, odeini,
UseMethod("mkinpredict", x)
}
+#' @rdname mkinpredict
+#' @export
mkinpredict.mkinmod <- function(x,
odeparms = c(k_parent_sink = 0.1),
odeini = c(parent = 100),
@@ -164,6 +243,8 @@ mkinpredict.mkinmod <- function(x,
}
}
+#' @rdname mkinpredict
+#' @export
mkinpredict.mkinfit <- function(x,
odeparms = x$bparms.ode,
odeini = x$bparms.state,
diff --git a/R/mkinresplot.R b/R/mkinresplot.R
index 974d0549..5377dbf2 100644
--- a/R/mkinresplot.R
+++ b/R/mkinresplot.R
@@ -1,65 +1,84 @@
-# Copyright (C) 2008-2014,2019 Johannes Ranke
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
-if(getRversion() >= '2.15.1') utils::globalVariables(c("variable", "residual"))
-
-mkinresplot <- function (object,
- obs_vars = names(object$mkinmod$map),
- xlim = c(0, 1.1 * max(object$data$time)),
- xlab = "Time", ylab = "Residual",
- maxabs = "auto", legend= TRUE, lpos = "topright",
- col_obs = "auto", pch_obs = "auto",
- frame = TRUE,
- ...)
-{
- obs_vars_all <- as.character(unique(object$data$variable))
-
- if (length(obs_vars) > 0){
- obs_vars <- intersect(obs_vars_all, obs_vars)
- } else obs_vars <- obs_vars_all
-
- residuals <- subset(object$data, variable %in% obs_vars, residual)
-
- if (maxabs == "auto") maxabs = max(abs(residuals), na.rm = TRUE)
-
- # Set colors and symbols
- if (col_obs[1] == "auto") {
- col_obs <- 1:length(obs_vars)
- }
-
- if (pch_obs[1] == "auto") {
- pch_obs <- 1:length(obs_vars)
- }
- names(col_obs) <- names(pch_obs) <- obs_vars
-
- plot(0, type = "n", frame = frame,
- xlab = xlab, ylab = ylab,
- xlim = xlim,
- ylim = c(-1.2 * maxabs, 1.2 * maxabs), ...)
-
- for(obs_var in obs_vars){
- residuals_plot <- subset(object$data, variable == obs_var, c("time", "residual"))
- points(residuals_plot, pch = pch_obs[obs_var], col = col_obs[obs_var])
- }
-
- abline(h = 0, lty = 2)
-
- if (legend == TRUE) {
- legend(lpos, inset = c(0.05, 0.05), legend = obs_vars,
- col = col_obs[obs_vars], pch = pch_obs[obs_vars])
- }
-}
+if(getRversion() >= '2.15.1') utils::globalVariables(c("variable", "residual"))
+
+#' Function to plot residuals stored in an mkin object
+#'
+#' This function plots the residuals for the specified subset of the observed
+#' variables from an mkinfit object. A combined plot of the fitted model and
+#' the residuals can be obtained using \code{\link{plot.mkinfit}} using the
+#' argument \code{show_residuals = TRUE}.
+#'
+#' @param object A fit represented in an \code{\link{mkinfit}} object.
+#' @param obs_vars A character vector of names of the observed variables for
+#' which residuals should be plotted. Defaults to all observed variables in
+#' the model
+#' @param xlim plot range in x direction.
+#' @param xlab Label for the x axis. Defaults to "Time [days]".
+#' @param ylab Label for the y axis. Defaults to "Residual [\% of applied
+#' radioactivity]".
+#' @param maxabs Maximum absolute value of the residuals. This is used for the
+#' scaling of the y axis and defaults to "auto".
+#' @param legend Should a legend be plotted? Defaults to "TRUE".
+#' @param lpos Where should the legend be placed? Default is "topright". Will
+#' be passed on to \code{\link{legend}}.
+#' @param col_obs Colors for the observed variables.
+#' @param pch_obs Symbols to be used for the observed variables.
+#' @param frame Should a frame be drawn around the plots?
+#' @param \dots further arguments passed to \code{\link{plot}}.
+#' @return Nothing is returned by this function, as it is called for its side
+#' effect, namely to produce a plot.
+#' @author Johannes Ranke
+#' @seealso \code{\link{mkinplot}}, for a way to plot the data and the fitted
+#' lines of the mkinfit object.
+#' @examples
+#'
+#' model <- mkinmod(parent = mkinsub("SFO", "m1"), m1 = mkinsub("SFO"))
+#' fit <- mkinfit(model, FOCUS_2006_D, quiet = TRUE)
+#' mkinresplot(fit, "m1")
+#'
+#' @export
+mkinresplot <- function (object,
+ obs_vars = names(object$mkinmod$map),
+ xlim = c(0, 1.1 * max(object$data$time)),
+ xlab = "Time", ylab = "Residual",
+ maxabs = "auto", legend= TRUE, lpos = "topright",
+ col_obs = "auto", pch_obs = "auto",
+ frame = TRUE,
+ ...)
+{
+ obs_vars_all <- as.character(unique(object$data$variable))
+
+ if (length(obs_vars) > 0){
+ obs_vars <- intersect(obs_vars_all, obs_vars)
+ } else obs_vars <- obs_vars_all
+
+ residuals <- subset(object$data, variable %in% obs_vars, residual)
+
+ if (maxabs == "auto") maxabs = max(abs(residuals), na.rm = TRUE)
+
+ # Set colors and symbols
+ if (col_obs[1] == "auto") {
+ col_obs <- 1:length(obs_vars)
+ }
+
+ if (pch_obs[1] == "auto") {
+ pch_obs <- 1:length(obs_vars)
+ }
+ names(col_obs) <- names(pch_obs) <- obs_vars
+
+ plot(0, type = "n", frame = frame,
+ xlab = xlab, ylab = ylab,
+ xlim = xlim,
+ ylim = c(-1.2 * maxabs, 1.2 * maxabs), ...)
+
+ for(obs_var in obs_vars){
+ residuals_plot <- subset(object$data, variable == obs_var, c("time", "residual"))
+ points(residuals_plot, pch = pch_obs[obs_var], col = col_obs[obs_var])
+ }
+
+ abline(h = 0, lty = 2)
+
+ if (legend == TRUE) {
+ legend(lpos, inset = c(0.05, 0.05), legend = obs_vars,
+ col = col_obs[obs_vars], pch = pch_obs[obs_vars])
+ }
+}
diff --git a/R/mkinsub.R b/R/mkinsub.R
index 99c3ea20..db91ca00 100644
--- a/R/mkinsub.R
+++ b/R/mkinsub.R
@@ -1,23 +1,39 @@
-# Copyright (C) 2014,2015 Johannes Ranke
-# Portions of this code are copyright (C) 2013 Eurofins Regulatory AG
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
+#' Function to set up a kinetic submodel for one state variable
+#'
+#' This is a convenience function to set up the lists used as arguments for
+#' \code{\link{mkinmod}}.
+#'
+#' @param submodel Character vector of length one to specify the submodel type.
+#' See \code{\link{mkinmod}} for the list of allowed submodel names.
+#' @param to Vector of the names of the state variable to which a
+#' transformation shall be included in the model.
+#' @param sink Should a pathway to sink be included in the model in addition to
+#' the pathways to other state variables?
+#' @param full_name An optional name to be used e.g. for plotting fits
+#' performed with the model. You can use non-ASCII characters here, but then
+#' your R code will not be portable, \emph{i.e.} may produce unintended plot
+#' results on other operating systems or system configurations.
+#' @return A list for use with \code{\link{mkinmod}}.
+#' @author Johannes Ranke
+#' @examples
+#'
+#' # One parent compound, one metabolite, both single first order.
+#' SFO_SFO <- mkinmod(
+#' parent = list(type = "SFO", to = "m1"),
+#' m1 = list(type = "SFO"))
+#'
+#' # The same model using mkinsub
+#' SFO_SFO.2 <- mkinmod(
+#' parent = mkinsub("SFO", "m1"),
+#' m1 = mkinsub("SFO"))
+#'
+#' # Now supplying full names
+#' SFO_SFO.2 <- mkinmod(
+#' parent = mkinsub("SFO", "m1", full_name = "Test compound"),
+#' m1 = mkinsub("SFO", full_name = "Metabolite M1"))
+#'
+#' @export
mkinsub <- function(submodel, to = NULL, sink = TRUE, full_name = NA)
{
return(list(type = submodel, to = to, sink = sink, full_name = full_name))
}
-# vim: set ts=2 sw=2 expandtab:
diff --git a/R/mmkin.R b/R/mmkin.R
index b713ae74..4f3f28a9 100644
--- a/R/mmkin.R
+++ b/R/mmkin.R
@@ -1,24 +1,65 @@
-# Copyright (C) 2015,2019 Johannes Ranke
-# Contact: jranke@uni-bremen.de
-# The summary function is an adapted and extended version of summary.modFit
-# from the FME package, v 1.1 by Soetart and Petzoldt, which was in turn
-# inspired by summary.nls.lm
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
-
+#' Fit one or more kinetic models with one or more state variables to one or
+#' more datasets
+#'
+#' This function calls \code{\link{mkinfit}} on all combinations of models and
+#' datasets specified in its first two arguments.
+#'
+#' @param models Either a character vector of shorthand names like
+#' \code{c("SFO", "FOMC", "DFOP", "HS", "SFORB")}, or an optionally named
+#' list of \code{\link{mkinmod}} objects.
+#' @param datasets An optionally named list of datasets suitable as observed
+#' data for \code{\link{mkinfit}}.
+#' @param cores The number of cores to be used for multicore processing. This
+#' is only used when the \code{cluster} argument is \code{NULL}. On Windows
+#' machines, cores > 1 is not supported, you need to use the \code{cluster}
+#' argument to use multiple logical processors.
+#' @param cluster A cluster as returned by \code{\link{makeCluster}} to be used
+#' for parallel execution.
+#' @param \dots Further arguments that will be passed to \code{\link{mkinfit}}.
+#' @importFrom parallel mclapply parLapply detectCores
+#' @return A matrix of \code{\link{mkinfit}} objects that can be indexed using
+#' the model and dataset names as row and column indices.
+#' @author Johannes Ranke
+#' @seealso \code{\link{[.mmkin}} for subsetting, \code{\link{plot.mmkin}} for
+#' plotting.
+#' @keywords optimize
+#' @examples
+#'
+#' \dontrun{
+#' m_synth_SFO_lin <- mkinmod(parent = mkinsub("SFO", "M1"),
+#' M1 = mkinsub("SFO", "M2"),
+#' M2 = mkinsub("SFO"), use_of_ff = "max")
+#'
+#' m_synth_FOMC_lin <- mkinmod(parent = mkinsub("FOMC", "M1"),
+#' M1 = mkinsub("SFO", "M2"),
+#' M2 = mkinsub("SFO"), use_of_ff = "max")
+#'
+#' models <- list(SFO_lin = m_synth_SFO_lin, FOMC_lin = m_synth_FOMC_lin)
+#' datasets <- lapply(synthetic_data_for_UBA_2014[1:3], function(x) x$data)
+#' names(datasets) <- paste("Dataset", 1:3)
+#'
+#' time_default <- system.time(fits.0 <- mmkin(models, datasets, quiet = TRUE))
+#' time_1 <- system.time(fits.4 <- mmkin(models, datasets, cores = 1, quiet = TRUE))
+#'
+#' time_default
+#' time_1
+#'
+#' endpoints(fits.0[["SFO_lin", 2]])
+#'
+#' # plot.mkinfit handles rows or columns of mmkin result objects
+#' plot(fits.0[1, ])
+#' plot(fits.0[1, ], obs_var = c("M1", "M2"))
+#' plot(fits.0[, 1])
+#' # Use double brackets to extract a single mkinfit object, which will be plotted
+#' # by plot.mkinfit and can be plotted using plot_sep
+#' plot(fits.0[[1, 1]], sep_obs = TRUE, show_residuals = TRUE, show_errmin = TRUE)
+#' plot_sep(fits.0[[1, 1]])
+#' # Plotting with mmkin (single brackets, extracting an mmkin object) does not
+#' # allow to plot the observed variables separately
+#' plot(fits.0[1, 1])
+#' }
+#'
+#' @export mmkin
mmkin <- function(models = c("SFO", "FOMC", "DFOP"), datasets,
cores = round(detectCores()/2), cluster = NULL, ...)
{
@@ -66,7 +107,35 @@ mmkin <- function(models = c("SFO", "FOMC", "DFOP"), datasets,
return(results)
}
-"[.mmkin" <- function(x, i, j, ..., drop = FALSE) {
+#' Subsetting method for mmkin objects
+#'
+#' Subsetting method for mmkin objects.
+#'
+#' @param x An \code{\link{mmkin} object}
+#' @param i Row index selecting the fits for specific models
+#' @param j Column index selecting the fits to specific datasets
+#' @param ... Not used, only there to satisfy the generic method definition
+#' @param drop If FALSE, the method always returns an mmkin object, otherwise
+#' either a list of mkinfit objects or a single mkinfit object.
+#' @return An object of class \code{\link{mmkin}}.
+#' @author Johannes Ranke
+#' @rdname Extract.mmkin
+#' @examples
+#'
+#' # Only use one core, to pass R CMD check --as-cran
+#' fits <- mmkin(c("SFO", "FOMC"), list(B = FOCUS_2006_B, C = FOCUS_2006_C),
+#' cores = 1, quiet = TRUE)
+#' fits["FOMC", ]
+#' fits[, "B"]
+#' fits["SFO", "B"]
+#'
+#' head(
+#' # This extracts an mkinfit object with lots of components
+#' fits[["FOMC", "B"]]
+#' )
+#'
+#' @export
+`[.mmkin` <- function(x, i, j, ..., drop = FALSE) {
class(x) <- NULL
x_sub <- x[i, j, drop = drop]
if (!drop) class(x_sub) <- "mmkin"
diff --git a/R/nafta.R b/R/nafta.R
index ef752e0c..7e5873d8 100644
--- a/R/nafta.R
+++ b/R/nafta.R
@@ -1,21 +1,40 @@
-# Copyright (C) 2019 Johannes Ranke
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
-
+#' Evaluate parent kinetics using the NAFTA guidance
+#'
+#' The function fits the SFO, IORE and DFOP models using \code{\link{mmkin}}
+#' and returns an object of class \code{nafta} that has methods for printing
+#' and plotting.
+#'
+#' @param ds A dataframe that must contain one variable called "time" with the
+#' time values specified by the \code{time} argument, one column called
+#' "name" with the grouping of the observed values, and finally one column of
+#' observed values called "value".
+#' @param title Optional title of the dataset
+#' @param quiet Should the evaluation text be shown?
+#' @param \dots Further arguments passed to \code{\link{mmkin}} (not for the
+#' printing method).
+#' @importFrom stats qf
+#' @return An list of class \code{nafta}. The list element named "mmkin" is the
+#' \code{\link{mmkin}} object containing the fits of the three models. The
+#' list element named "title" contains the title of the dataset used. The
+#' list element "data" contains the dataset used in the fits.
+#' @author Johannes Ranke
+#' @source NAFTA (2011) Guidance for evaluating and calculating degradation
+#' kinetics in environmental media. NAFTA Technical Working Group on
+#' Pesticides
+#' \url{https://www.epa.gov/pesticide-science-and-assessing-pesticide-risks/guidance-evaluating-and-calculating-degradation}
+#' accessed 2019-02-22
+#'
+#' US EPA (2015) Standard Operating Procedure for Using the NAFTA Guidance to
+#' Calculate Representative Half-life Values and Characterizing Pesticide
+#' Degradation
+#' \url{https://www.epa.gov/pesticide-science-and-assessing-pesticide-risks/standard-operating-procedure-using-nafta-guidance}
+#' @examples
+#'
+#' nafta_evaluation <- nafta(NAFTA_SOP_Appendix_D, cores = 1)
+#' print(nafta_evaluation)
+#' plot(nafta_evaluation)
+#'
+#' @export
nafta <- function(ds, title = NA, quiet = FALSE, ...) {
if (length(levels(ds$name)) > 1) {
stop("The NAFTA procedure is only defined for decline data for a single compound")
@@ -56,6 +75,20 @@ nafta <- function(ds, title = NA, quiet = FALSE, ...) {
return(result)
}
+#' Plot the results of the three models used in the NAFTA scheme.
+#'
+#' The plots are ordered with increasing complexity of the model in this
+#' function (SFO, then IORE, then DFOP).
+#'
+#' Calls \code{\link{plot.mmkin}}.
+#'
+#' @param x An object of class \code{\link{nafta}}.
+#' @param legend Should a legend be added?
+#' @param main Possibility to override the main title of the plot.
+#' @param \dots Further arguments passed to \code{\link{plot.mmkin}}.
+#' @return The function is called for its side effect.
+#' @author Johannes Ranke
+#' @export
plot.nafta <- function(x, legend = FALSE, main = "auto", ...) {
if (main == "auto") {
if (is.na(x$title)) main = ""
@@ -64,6 +97,16 @@ plot.nafta <- function(x, legend = FALSE, main = "auto", ...) {
plot(x$mmkin, ..., legend = legend, main = main)
}
+#' Print nafta objects
+#'
+#' Print nafta objects. The results for the three models are printed in the
+#' order of increasing model complexity, i.e. SFO, then IORE, and finally DFOP.
+#'
+#' @param x An \code{\link{nafta}} object.
+#' @param digits Number of digits to be used for printing parameters and
+#' dissipation times.
+#' @rdname nafta
+#' @export
print.nafta <- function(x, quiet = TRUE, digits = 3, ...) {
cat("Sums of squares:\n")
print(x$S)
diff --git a/R/plot.mkinfit.R b/R/plot.mkinfit.R
index e39da416..16415a3b 100644
--- a/R/plot.mkinfit.R
+++ b/R/plot.mkinfit.R
@@ -1,22 +1,88 @@
-# Copyright (C) 2010-2016,2019 Johannes Ranke
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
if(getRversion() >= '2.15.1') utils::globalVariables(c("type", "variable", "observed"))
+#' Plot the observed data and the fitted model of an mkinfit object
+#'
+#' Solves the differential equations with the optimised and fixed parameters
+#' from a previous successful call to \code{\link{mkinfit}} and plots the
+#' observed data together with the solution of the fitted model.
+#'
+#' If the current plot device is a \code{\link[tikzDevice]{tikz}} device, then
+#' latex is being used for the formatting of the chi2 error level, if
+#' \code{show_errmin = TRUE}.
+#'
+#' @aliases plot.mkinfit plot_sep plot_res plot_err
+#' @param x Alias for fit introduced for compatibility with the generic S3
+#' method.
+#' @param fit An object of class \code{\link{mkinfit}}.
+#' @param obs_vars A character vector of names of the observed variables for
+#' which the data and the model should be plotted. Defauls to all observed
+#' variables in the model.
+#' @param xlab Label for the x axis.
+#' @param ylab Label for the y axis.
+#' @param xlim Plot range in x direction.
+#' @param ylim Plot range in y direction.
+#' @param col_obs Colors used for plotting the observed data and the
+#' corresponding model prediction lines.
+#' @param pch_obs Symbols to be used for plotting the data.
+#' @param lty_obs Line types to be used for the model predictions.
+#' @param add Should the plot be added to an existing plot?
+#' @param legend Should a legend be added to the plot?
+#' @param show_residuals Should residuals be shown? If only one plot of the
+#' fits is shown, the residual plot is in the lower third of the plot.
+#' Otherwise, i.e. if "sep_obs" is given, the residual plots will be located
+#' to the right of the plots of the fitted curves.
+#' @param show_errplot Should squared residuals and the error model be shown?
+#' If only one plot of the fits is shown, this plot is in the lower third of
+#' the plot. Otherwise, i.e. if "sep_obs" is given, the residual plots will
+#' be located to the right of the plots of the fitted curves.
+#' @param maxabs Maximum absolute value of the residuals. This is used for the
+#' scaling of the y axis and defaults to "auto".
+#' @param sep_obs Should the observed variables be shown in separate subplots?
+#' If yes, residual plots requested by "show_residuals" will be shown next
+#' to, not below the plot of the fits.
+#' @param rel.height.middle The relative height of the middle plot, if more
+#' than two rows of plots are shown.
+#' @param row_layout Should we use a row layout where the residual plot or the
+#' error model plot is shown to the right?
+#' @param lpos Position(s) of the legend(s). Passed to \code{\link{legend}} as
+#' the first argument. If not length one, this should be of the same length
+#' as the obs_var argument.
+#' @param inset Passed to \code{\link{legend}} if applicable.
+#' @param show_errmin Should the FOCUS chi2 error value be shown in the upper
+#' margin of the plot?
+#' @param errmin_digits The number of significant digits for rounding the FOCUS
+#' chi2 error percentage.
+#' @param frame Should a frame be drawn around the plots?
+#' @param \dots Further arguments passed to \code{\link{plot}}.
+#' @import graphics
+#' @importFrom grDevices dev.cur
+#' @return The function is called for its side effect.
+#' @author Johannes Ranke
+#' @examples
+#'
+#' # One parent compound, one metabolite, both single first order, path from
+#' # parent to sink included
+#' \dontrun{
+#' SFO_SFO <- mkinmod(parent = mkinsub("SFO", "m1", full = "Parent"),
+#' m1 = mkinsub("SFO", full = "Metabolite M1" ))
+#' fit <- mkinfit(SFO_SFO, FOCUS_2006_D, quiet = TRUE, error_model = "tc")
+#' plot(fit)
+#' plot_res(fit)
+#' plot_err(fit)
+#'
+#' # Show the observed variables separately, with residuals
+#' plot(fit, sep_obs = TRUE, show_residuals = TRUE, lpos = c("topright", "bottomright"),
+#' show_errmin = TRUE)
+#'
+#' # The same can be obtained with less typing, using the convenience function plot_sep
+#' plot_sep(fit, lpos = c("topright", "bottomright"))
+#'
+#' # Show the observed variables separately, with the error model
+#' plot(fit, sep_obs = TRUE, show_errplot = TRUE, lpos = c("topright", "bottomright"),
+#' show_errmin = TRUE)
+#' }
+#'
+#' @export
plot.mkinfit <- function(x, fit = x,
obs_vars = names(fit$mkinmod$map),
xlab = "Time", ylab = "Observed",
@@ -206,17 +272,39 @@ plot.mkinfit <- function(x, fit = x,
}
if (do_layout) par(oldpar, no.readonly = TRUE)
}
-# Convenience function for switching on some features of mkinfit
-# that have not been made the default to keep compatibility
+
+#' @rdname plot.mkinfit
+#' @export
plot_sep <- function(fit, show_errmin = TRUE, ...) {
plot.mkinfit(fit, sep_obs = TRUE, show_residuals = TRUE,
show_errmin = show_errmin, ...)
}
+
+#' @rdname plot.mkinfit
+#' @export
plot_res <- function(fit, sep_obs = FALSE, show_errmin = sep_obs, ...) {
plot.mkinfit(fit, sep_obs = sep_obs, show_errmin = show_errmin,
show_residuals = TRUE, row_layout = TRUE, ...)
}
+
+#' @rdname plot.mkinfit
+#' @export
plot_err <- function(fit, sep_obs = FALSE, show_errmin = sep_obs, ...) {
plot.mkinfit(fit, sep_obs = sep_obs, show_errmin = show_errmin,
show_errplot = TRUE, row_layout = TRUE, ...)
}
+
+#' Plot the observed data and the fitted model of an mkinfit object
+#'
+#' Deprecated function. It now only calls the plot method
+#' \code{\link{plot.mkinfit}}.
+#'
+#' @param fit an object of class \code{\link{mkinfit}}.
+#' @param \dots further arguments passed to \code{\link{plot.mkinfit}}.
+#' @return The function is called for its side effect.
+#' @author Johannes Ranke
+#' @export
+mkinplot <- function(fit, ...)
+{
+ plot(fit, ...)
+}
diff --git a/R/plot.mmkin.R b/R/plot.mmkin.R
index ef80949c..eefafe12 100644
--- a/R/plot.mmkin.R
+++ b/R/plot.mmkin.R
@@ -1,21 +1,53 @@
-# Copyright (C) 2015-2016,2019 Johannes Ranke
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
-
+#' Plot model fits (observed and fitted) and the residuals for a row or column
+#' of an mmkin object
+#'
+#' When x is a row selected from an mmkin object (\code{\link{[.mmkin}}), the
+#' same model fitted for at least one dataset is shown. When it is a column,
+#' the fit of at least one model to the same dataset is shown.
+#'
+#' If the current plot device is a \code{\link[tikzDevice]{tikz}} device, then
+#' latex is being used for the formatting of the chi2 error level.
+#'
+#' @param x An object of class \code{\link{mmkin}}, with either one row or one
+#' column.
+#' @param main The main title placed on the outer margin of the plot.
+#' @param legends An index for the fits for which legends should be shown.
+#' @param resplot Should the residuals plotted against time, using
+#' \code{\link{mkinresplot}}, or as squared residuals against predicted
+#' values, with the error model, using \code{\link{mkinerrplot}}.
+#' @param show_errmin Should the chi2 error level be shown on top of the plots
+#' to the left?
+#' @param errmin_var The variable for which the FOCUS chi2 error value should
+#' be shown.
+#' @param errmin_digits The number of significant digits for rounding the FOCUS
+#' chi2 error percentage.
+#' @param cex Passed to the plot functions and \code{\link{mtext}}.
+#' @param rel.height.middle The relative height of the middle plot, if more
+#' than two rows of plots are shown.
+#' @param \dots Further arguments passed to \code{\link{plot.mkinfit}} and
+#' \code{\link{mkinresplot}}.
+#' @return The function is called for its side effect.
+#' @author Johannes Ranke
+#' @examples
+#'
+#' \dontrun{
+#' # Only use one core not to offend CRAN checks
+#' fits <- mmkin(c("FOMC", "HS"),
+#' list("FOCUS B" = FOCUS_2006_B, "FOCUS C" = FOCUS_2006_C), # named list for titles
+#' cores = 1, quiet = TRUE, error_model = "tc")
+#' plot(fits[, "FOCUS C"])
+#' plot(fits["FOMC", ])
+#'
+#' # We can also plot a single fit, if we like the way plot.mmkin works, but then the plot
+#' # height should be smaller than the plot width (this is not possible for the html pages
+#' # generated by pkgdown, as far as I know).
+#' plot(fits["FOMC", "FOCUS C"]) # same as plot(fits[1, 2])
+#'
+#' # Show the error models
+#' plot(fits["FOMC", ], resplot = "errmod")
+#' }
+#'
+#' @export
plot.mmkin <- function(x, main = "auto", legends = 1,
resplot = c("time", "errmod"),
show_errmin = TRUE,
diff --git a/R/sigma_twocomp.R b/R/sigma_twocomp.R
index b06816c1..c9a15aa8 100644
--- a/R/sigma_twocomp.R
+++ b/R/sigma_twocomp.R
@@ -1,3 +1,29 @@
+#' Two component error model
+#'
+#' Function describing the standard deviation of the measurement error in
+#' dependence of the measured value \eqn{y}:
+#'
+#' \deqn{\sigma = \sqrt{ \sigma_{low}^2 + y^2 * {rsd}_{high}^2}} sigma =
+#' sqrt(sigma_low^2 + y^2 * rsd_high^2)
+#'
+#' This is the error model used for example by Werner et al. (1978). The model
+#' proposed by Rocke and Lorenzato (1995) can be written in this form as well,
+#' but assumes approximate lognormal distribution of errors for high values of
+#' y.
+#'
+#' @param y The magnitude of the observed value
+#' @param sigma_low The asymptotic minimum of the standard deviation for low
+#' observed values
+#' @param rsd_high The coefficient describing the increase of the standard
+#' deviation with the magnitude of the observed value
+#' @return The standard deviation of the response variable.
+#' @references Werner, Mario, Brooks, Samuel H., and Knott, Lancaster B. (1978)
+#' Additive, Multiplicative, and Mixed Analytical Errors. Clinical Chemistry
+#' 24(11), 1895-1898.
+#'
+#' Rocke, David M. and Lorenzato, Stefan (1995) A two-component model for
+#' measurement error in analytical chemistry. Technometrics 37(2), 176-184.
+#' @export
sigma_twocomp <- function(y, sigma_low, rsd_high) {
sqrt(sigma_low^2 + y^2 * rsd_high^2)
}
diff --git a/R/summary.mkinfit.R b/R/summary.mkinfit.R
new file mode 100644
index 00000000..90f32da9
--- /dev/null
+++ b/R/summary.mkinfit.R
@@ -0,0 +1,272 @@
+#' Summary method for class "mkinfit"
+#'
+#' Lists model equations, initial parameter values, optimised parameters with
+#' some uncertainty statistics, the chi2 error levels calculated according to
+#' FOCUS guidance (2006) as defined therein, formation fractions, DT50 values
+#' and optionally the data, consisting of observed, predicted and residual
+#' values.
+#'
+#' @param object an object of class \code{\link{mkinfit}}.
+#' @param x an object of class \code{summary.mkinfit}.
+#' @param data logical, indicating whether the data should be included in the
+#' summary.
+#' @param distimes logical, indicating whether DT50 and DT90 values should be
+#' included.
+#' @param alpha error level for confidence interval estimation from t
+#' distribution
+#' @param digits Number of digits to use for printing
+#' @param \dots optional arguments passed to methods like \code{print}.
+#' @importFrom stats qt pt cov2cor
+#' @return The summary function returns a list with components, among others
+#' \item{version, Rversion}{The mkin and R versions used}
+#' \item{date.fit, date.summary}{The dates where the fit and the summary were
+#' produced}
+#' \item{diffs}{The differential equations used in the model}
+#' \item{use_of_ff}{Was maximum or minimum use made of formation fractions}
+#' \item{bpar}{Optimised and backtransformed
+#' parameters}
+#' \item{data}{The data (see Description above).}
+#' \item{start}{The starting values and bounds, if applicable, for optimised
+#' parameters.}
+#' \item{fixed}{The values of fixed parameters.}
+#' \item{errmin }{The chi2 error levels for
+#' each observed variable.}
+#' \item{bparms.ode}{All backtransformed ODE
+#' parameters, for use as starting parameters for related models.}
+#' \item{errparms}{Error model parameters.}
+#' \item{ff}{The estimated formation fractions derived from the fitted
+#' model.}
+#' \item{distimes}{The DT50 and DT90 values for each observed variable.}
+#' \item{SFORB}{If applicable, eigenvalues of SFORB components of the model.}
+#' The print method is called for its side effect, i.e. printing the summary.
+#' @author Johannes Ranke
+#' @references FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence
+#' and Degradation Kinetics from Environmental Fate Studies on Pesticides in
+#' EU Registration} Report of the FOCUS Work Group on Degradation Kinetics,
+#' EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
+#' \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+#' @examples
+#'
+#' summary(mkinfit(mkinmod(parent = mkinsub("SFO")), FOCUS_2006_A, quiet = TRUE))
+#'
+#' @export
+summary.mkinfit <- function(object, data = TRUE, distimes = TRUE, alpha = 0.05, ...) {
+ param <- object$par
+ pnames <- names(param)
+ bpnames <- names(object$bparms.optim)
+ epnames <- names(object$errparms)
+ p <- length(param)
+ mod_vars <- names(object$mkinmod$diffs)
+ covar <- try(solve(object$hessian), silent = TRUE)
+ covar_notrans <- try(solve(object$hessian_notrans), silent = TRUE)
+ rdf <- object$df.residual
+
+ if (!is.numeric(covar) | is.na(covar[1])) {
+ covar <- NULL
+ se <- lci <- uci <- rep(NA, p)
+ } else {
+ rownames(covar) <- colnames(covar) <- pnames
+ se <- sqrt(diag(covar))
+ lci <- param + qt(alpha/2, rdf) * se
+ uci <- param + qt(1-alpha/2, rdf) * se
+ }
+
+ beparms.optim <- c(object$bparms.optim, object$par[epnames])
+ if (!is.numeric(covar_notrans) | is.na(covar_notrans[1])) {
+ covar_notrans <- NULL
+ se_notrans <- tval <- pval <- rep(NA, p)
+ } else {
+ rownames(covar_notrans) <- colnames(covar_notrans) <- c(bpnames, epnames)
+ se_notrans <- sqrt(diag(covar_notrans))
+ tval <- beparms.optim / se_notrans
+ pval <- pt(abs(tval), rdf, lower.tail = FALSE)
+ }
+
+ names(se) <- pnames
+
+ param <- cbind(param, se, lci, uci)
+ dimnames(param) <- list(pnames, c("Estimate", "Std. Error", "Lower", "Upper"))
+
+ bparam <- cbind(Estimate = beparms.optim, se_notrans,
+ "t value" = tval, "Pr(>t)" = pval, Lower = NA, Upper = NA)
+
+ # Transform boundaries of CI for one parameter at a time,
+ # with the exception of sets of formation fractions (single fractions are OK).
+ f_names_skip <- character(0)
+ for (box in mod_vars) { # Figure out sets of fractions to skip
+ f_names <- grep(paste("^f", box, sep = "_"), pnames, value = TRUE)
+ n_paths <- length(f_names)
+ if (n_paths > 1) f_names_skip <- c(f_names_skip, f_names)
+ }
+
+ for (pname in pnames) {
+ if (!pname %in% f_names_skip) {
+ par.lower <- param[pname, "Lower"]
+ par.upper <- param[pname, "Upper"]
+ names(par.lower) <- names(par.upper) <- pname
+ bpl <- backtransform_odeparms(par.lower, object$mkinmod,
+ object$transform_rates,
+ object$transform_fractions)
+ bpu <- backtransform_odeparms(par.upper, object$mkinmod,
+ object$transform_rates,
+ object$transform_fractions)
+ bparam[names(bpl), "Lower"] <- bpl
+ bparam[names(bpu), "Upper"] <- bpu
+ }
+ }
+ bparam[epnames, c("Lower", "Upper")] <- param[epnames, c("Lower", "Upper")]
+
+ ans <- list(
+ version = as.character(utils::packageVersion("mkin")),
+ Rversion = paste(R.version$major, R.version$minor, sep="."),
+ date.fit = object$date,
+ date.summary = date(),
+ solution_type = object$solution_type,
+ warning = object$warning,
+ use_of_ff = object$mkinmod$use_of_ff,
+ error_model_algorithm = object$error_model_algorithm,
+ df = c(p, rdf),
+ covar = covar,
+ covar_notrans = covar_notrans,
+ err_mod = object$err_mod,
+ niter = object$iterations,
+ calls = object$calls,
+ time = object$time,
+ par = param,
+ bpar = bparam)
+
+ if (!is.null(object$version)) {
+ ans$fit_version <- object$version
+ ans$fit_Rversion <- object$Rversion
+ }
+
+ ans$diffs <- object$mkinmod$diffs
+ if(data) ans$data <- object$data
+ ans$start <- object$start
+ ans$start_transformed <- object$start_transformed
+
+ ans$fixed <- object$fixed
+
+ ans$errmin <- mkinerrmin(object, alpha = 0.05)
+
+ if (object$calls > 0) {
+ if (!is.null(ans$covar)){
+ Corr <- cov2cor(ans$covar)
+ rownames(Corr) <- colnames(Corr) <- rownames(ans$par)
+ ans$Corr <- Corr
+ } else {
+ warning("Could not calculate correlation; no covariance matrix")
+ }
+ }
+
+ ans$bparms.ode <- object$bparms.ode
+ ep <- endpoints(object)
+ if (length(ep$ff) != 0)
+ ans$ff <- ep$ff
+ if (distimes) ans$distimes <- ep$distimes
+ if (length(ep$SFORB) != 0) ans$SFORB <- ep$SFORB
+ if (!is.null(object$d_3_message)) ans$d_3_message <- object$d_3_message
+ class(ans) <- c("summary.mkinfit", "summary.modFit")
+ return(ans)
+}
+
+#' @rdname summary.mkinfit
+#' @export
+print.summary.mkinfit <- function(x, digits = max(3, getOption("digits") - 3), ...) {
+ if (is.null(x$fit_version)) {
+ cat("mkin version: ", x$version, "\n")
+ cat("R version: ", x$Rversion, "\n")
+ } else {
+ cat("mkin version used for fitting: ", x$fit_version, "\n")
+ cat("R version used for fitting: ", x$fit_Rversion, "\n")
+ }
+
+ cat("Date of fit: ", x$date.fit, "\n")
+ cat("Date of summary:", x$date.summary, "\n")
+
+ if (!is.null(x$warning)) cat("\n\nWarning:", x$warning, "\n\n")
+
+ cat("\nEquations:\n")
+ nice_diffs <- gsub("^(d.*) =", "\\1/dt =", x[["diffs"]])
+ writeLines(strwrap(nice_diffs, exdent = 11))
+ df <- x$df
+ rdf <- df[2]
+
+ cat("\nModel predictions using solution type", x$solution_type, "\n")
+
+ cat("\nFitted using", x$calls, "model solutions performed in", x$time[["elapsed"]], "s\n")
+
+ if (!is.null(x$err_mod)) {
+ cat("\nError model: ")
+ cat(switch(x$err_mod,
+ const = "Constant variance",
+ obs = "Variance unique to each observed variable",
+ tc = "Two-component variance function"), "\n")
+
+ cat("\nError model algorithm:", x$error_model_algorithm, "\n")
+ if (!is.null(x$d_3_message)) cat(x$d_3_message, "\n")
+ }
+
+ cat("\nStarting values for parameters to be optimised:\n")
+ print(x$start)
+
+ cat("\nStarting values for the transformed parameters actually optimised:\n")
+ print(x$start_transformed)
+
+ cat("\nFixed parameter values:\n")
+ if(length(x$fixed$value) == 0) cat("None\n")
+ else print(x$fixed)
+
+ cat("\nOptimised, transformed parameters with symmetric confidence intervals:\n")
+ print(signif(x$par, digits = digits))
+
+ if (x$calls > 0) {
+ cat("\nParameter correlation:\n")
+ if (!is.null(x$covar)){
+ print(x$Corr, digits = digits, ...)
+ } else {
+ cat("No covariance matrix")
+ }
+ }
+
+ cat("\nBacktransformed parameters:\n")
+ cat("Confidence intervals for internally transformed parameters are asymmetric.\n")
+ if ((x$version) < "0.9-36") {
+ cat("To get the usual (questionable) t-test, upgrade mkin and repeat the fit.\n")
+ print(signif(x$bpar, digits = digits))
+ } else {
+ cat("t-test (unrealistically) based on the assumption of normal distribution\n")
+ cat("for estimators of untransformed parameters.\n")
+ print(signif(x$bpar[, c(1, 3, 4, 5, 6)], digits = digits))
+ }
+
+ cat("\nFOCUS Chi2 error levels in percent:\n")
+ x$errmin$err.min <- 100 * x$errmin$err.min
+ print(x$errmin, digits=digits,...)
+
+ printSFORB <- !is.null(x$SFORB)
+ if(printSFORB){
+ cat("\nEstimated Eigenvalues of SFORB model(s):\n")
+ print(x$SFORB, digits=digits,...)
+ }
+
+ printff <- !is.null(x$ff)
+ if(printff){
+ cat("\nResulting formation fractions:\n")
+ print(data.frame(ff = x$ff), digits=digits,...)
+ }
+
+ printdistimes <- !is.null(x$distimes)
+ if(printdistimes){
+ cat("\nEstimated disappearance times:\n")
+ print(x$distimes, digits=digits,...)
+ }
+
+ printdata <- !is.null(x$data)
+ if (printdata){
+ cat("\nData:\n")
+ print(format(x$data, digits = digits, ...), row.names = FALSE)
+ }
+
+ invisible(x)
+}
diff --git a/R/transform_odeparms.R b/R/transform_odeparms.R
index f69f4ebd..28e58f87 100644
--- a/R/transform_odeparms.R
+++ b/R/transform_odeparms.R
@@ -1,180 +1,258 @@
-# Copyright (C) 2010-2014,2019 Johannes Ranke
-# Contact: jranke@uni-bremen.de
-
-# This file is part of the R package mkin
-
-# mkin is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-
-# You should have received a copy of the GNU General Public License along with
-# this program. If not, see <http://www.gnu.org/licenses/>
-
-transform_odeparms <- function(parms, mkinmod,
- transform_rates = TRUE,
- transform_fractions = TRUE)
-{
- # We need the model specification for the names of the model
- # variables and the information on the sink
- spec = mkinmod$spec
-
- # Set up container for transformed parameters
- transparms <- numeric(0)
-
- # Do not transform initial values for state variables
- state.ini.optim <- parms[grep("_0$", names(parms))]
- transparms[names(state.ini.optim)] <- state.ini.optim
-
- # Log transformation for rate constants if requested
- k <- parms[grep("^k_", names(parms))]
- k__iore <- parms[grep("^k__iore_", names(parms))]
- k <- c(k, k__iore)
- if (length(k) > 0) {
- if(transform_rates) {
- transparms[paste0("log_", names(k))] <- log(k)
- } else transparms[names(k)] <- k
- }
-
- # Do not transform exponents in IORE models
- N <- parms[grep("^N", names(parms))]
- transparms[names(N)] <- N
-
- # Go through state variables and apply isometric logratio transformation to
- # formation fractions if requested
- mod_vars = names(spec)
- for (box in mod_vars) {
- f <- parms[grep(paste("^f", box, sep = "_"), names(parms))]
-
- if (length(f) > 0) {
- if(transform_fractions) {
- if (spec[[box]]$sink) {
- trans_f <- ilr(c(f, 1 - sum(f)))
- trans_f_names <- paste("f", box, "ilr", 1:length(trans_f), sep = "_")
- transparms[trans_f_names] <- trans_f
- } else {
- if (length(f) > 1) {
- trans_f <- ilr(f)
- trans_f_names <- paste("f", box, "ilr", 1:length(trans_f), sep = "_")
- transparms[trans_f_names] <- trans_f
- }
- }
- } else {
- transparms[names(f)] <- f
- }
- }
- }
-
- # Transform also FOMC parameters alpha and beta, DFOP and HS rates k1 and k2
- # and HS parameter tb as well as logistic model parameters kmax, k0 and r if
- # transformation of rates is requested
- for (pname in c("alpha", "beta", "k1", "k2", "tb", "kmax", "k0", "r")) {
- if (!is.na(parms[pname])) {
- if (transform_rates) {
- transparms[paste0("log_", pname)] <- log(parms[pname])
- } else {
- transparms[pname] <- parms[pname]
- }
- }
- }
-
- # DFOP parameter g is treated as a fraction
- if (!is.na(parms["g"])) {
- g <- parms["g"]
- if (transform_fractions) {
- transparms["g_ilr"] <- ilr(c(g, 1 - g))
- } else {
- transparms["g"] <- g
- }
- }
-
- return(transparms)
-}
-
-backtransform_odeparms <- function(transparms, mkinmod,
- transform_rates = TRUE,
- transform_fractions = TRUE)
-{
- # We need the model specification for the names of the model
- # variables and the information on the sink
- spec = mkinmod$spec
-
- # Set up container for backtransformed parameters
- parms <- numeric(0)
-
- # Do not transform initial values for state variables
- state.ini.optim <- transparms[grep("_0$", names(transparms))]
- parms[names(state.ini.optim)] <- state.ini.optim
-
- # Exponential transformation for rate constants
- if(transform_rates) {
- trans_k <- transparms[grep("^log_k_", names(transparms))]
- trans_k__iore <- transparms[grep("^log_k__iore_", names(transparms))]
- trans_k = c(trans_k, trans_k__iore)
- if (length(trans_k) > 0) {
- k_names <- gsub("^log_k", "k", names(trans_k))
- parms[k_names] <- exp(trans_k)
- }
- } else {
- trans_k <- transparms[grep("^k_", names(transparms))]
- parms[names(trans_k)] <- trans_k
- trans_k__iore <- transparms[grep("^k__iore_", names(transparms))]
- parms[names(trans_k__iore)] <- trans_k__iore
- }
-
- # Do not transform exponents in IORE models
- N <- transparms[grep("^N", names(transparms))]
- parms[names(N)] <- N
-
- # Go through state variables and apply inverse isometric logratio transformation
- mod_vars = names(spec)
- for (box in mod_vars) {
- # Get the names as used in the model
- f_names = grep(paste("^f", box, sep = "_"), mkinmod$parms, value = TRUE)
- # Get the formation fraction parameters
- trans_f = transparms[grep(paste("^f", box, sep = "_"), names(transparms))]
- if (length(trans_f) > 0) {
- if(transform_fractions) {
- f <- invilr(trans_f)
- if (spec[[box]]$sink) {
- parms[f_names] <- f[1:length(f)-1]
- } else {
- parms[f_names] <- f
- }
- } else {
- parms[names(trans_f)] <- trans_f
- }
- }
- }
-
- # Transform parameters also for FOMC, DFOP, HS and logistic models
- for (pname in c("alpha", "beta", "k1", "k2", "tb", "kmax", "k0", "r")) {
- if (transform_rates) {
- pname_trans = paste0("log_", pname)
- if (!is.na(transparms[pname_trans])) {
- parms[pname] <- exp(transparms[pname_trans])
- }
- } else {
- if (!is.na(transparms[pname])) {
- parms[pname] <- transparms[pname]
- }
- }
- }
-
- # DFOP parameter g is treated as a fraction
- if (!is.na(transparms["g_ilr"])) {
- g_ilr <- transparms["g_ilr"]
- parms["g"] <- invilr(g_ilr)[1]
- }
- if (!is.na(transparms["g"])) {
- parms["g"] <- transparms["g"]
- }
-
- return(parms)
-}
-# vim: set ts=2 sw=2 expandtab:
+#' Functions to transform and backtransform kinetic parameters for fitting
+#'
+#' The transformations are intended to map parameters that should only take on
+#' restricted values to the full scale of real numbers. For kinetic rate
+#' constants and other paramters that can only take on positive values, a
+#' simple log transformation is used. For compositional parameters, such as the
+#' formations fractions that should always sum up to 1 and can not be negative,
+#' the \code{\link{ilr}} transformation is used.
+#'
+#' The transformation of sets of formation fractions is fragile, as it supposes
+#' the same ordering of the components in forward and backward transformation.
+#' This is no problem for the internal use in \code{\link{mkinfit}}.
+#'
+#' @aliases transform_odeparms backtransform_odeparms
+#' @param parms Parameters of kinetic models as used in the differential
+#' equations.
+#' @param transparms Transformed parameters of kinetic models as used in the
+#' fitting procedure.
+#' @param mkinmod The kinetic model of class \code{\link{mkinmod}}, containing
+#' the names of the model variables that are needed for grouping the
+#' formation fractions before \code{\link{ilr}} transformation, the parameter
+#' names and the information if the pathway to sink is included in the model.
+#' @param transform_rates Boolean specifying if kinetic rate constants should
+#' be transformed in the model specification used in the fitting for better
+#' compliance with the assumption of normal distribution of the estimator. If
+#' TRUE, also alpha and beta parameters of the FOMC model are
+#' log-transformed, as well as k1 and k2 rate constants for the DFOP and HS
+#' models and the break point tb of the HS model.
+#' @param transform_fractions Boolean specifying if formation fractions
+#' constants should be transformed in the model specification used in the
+#' fitting for better compliance with the assumption of normal distribution
+#' of the estimator. The default (TRUE) is to do transformations. The g
+#' parameter of the DFOP and HS models are also transformed, as they can also
+#' be seen as compositional data. The transformation used for these
+#' transformations is the \code{\link{ilr}} transformation.
+#' @return A vector of transformed or backtransformed parameters with the same
+#' names as the original parameters.
+#' @author Johannes Ranke
+#' @examples
+#'
+#' SFO_SFO <- mkinmod(
+#' parent = list(type = "SFO", to = "m1", sink = TRUE),
+#' m1 = list(type = "SFO"))
+#' # Fit the model to the FOCUS example dataset D using defaults
+#' fit <- mkinfit(SFO_SFO, FOCUS_2006_D, quiet = TRUE)
+#' fit.s <- summary(fit)
+#' # Transformed and backtransformed parameters
+#' print(fit.s$par, 3)
+#' print(fit.s$bpar, 3)
+#'
+#' \dontrun{
+#' # Compare to the version without transforming rate parameters
+#' fit.2 <- mkinfit(SFO_SFO, FOCUS_2006_D, transform_rates = FALSE, quiet = TRUE)
+#' fit.2.s <- summary(fit.2)
+#' print(fit.2.s$par, 3)
+#' print(fit.2.s$bpar, 3)
+#' }
+#'
+#' initials <- fit$start$value
+#' names(initials) <- rownames(fit$start)
+#' transformed <- fit$start_transformed$value
+#' names(transformed) <- rownames(fit$start_transformed)
+#' transform_odeparms(initials, SFO_SFO)
+#' backtransform_odeparms(transformed, SFO_SFO)
+#'
+#' \dontrun{
+#' # The case of formation fractions
+#' SFO_SFO.ff <- mkinmod(
+#' parent = list(type = "SFO", to = "m1", sink = TRUE),
+#' m1 = list(type = "SFO"),
+#' use_of_ff = "max")
+#'
+#' fit.ff <- mkinfit(SFO_SFO.ff, FOCUS_2006_D, quiet = TRUE)
+#' fit.ff.s <- summary(fit.ff)
+#' print(fit.ff.s$par, 3)
+#' print(fit.ff.s$bpar, 3)
+#' initials <- c("f_parent_to_m1" = 0.5)
+#' transformed <- transform_odeparms(initials, SFO_SFO.ff)
+#' backtransform_odeparms(transformed, SFO_SFO.ff)
+#'
+#' # And without sink
+#' SFO_SFO.ff.2 <- mkinmod(
+#' parent = list(type = "SFO", to = "m1", sink = FALSE),
+#' m1 = list(type = "SFO"),
+#' use_of_ff = "max")
+#'
+#'
+#' fit.ff.2 <- mkinfit(SFO_SFO.ff.2, FOCUS_2006_D, quiet = TRUE)
+#' fit.ff.2.s <- summary(fit.ff.2)
+#' print(fit.ff.2.s$par, 3)
+#' print(fit.ff.2.s$bpar, 3)
+#' }
+#'
+#' @export transform_odeparms
+transform_odeparms <- function(parms, mkinmod,
+ transform_rates = TRUE,
+ transform_fractions = TRUE)
+{
+ # We need the model specification for the names of the model
+ # variables and the information on the sink
+ spec = mkinmod$spec
+
+ # Set up container for transformed parameters
+ transparms <- numeric(0)
+
+ # Do not transform initial values for state variables
+ state.ini.optim <- parms[grep("_0$", names(parms))]
+ transparms[names(state.ini.optim)] <- state.ini.optim
+
+ # Log transformation for rate constants if requested
+ k <- parms[grep("^k_", names(parms))]
+ k__iore <- parms[grep("^k__iore_", names(parms))]
+ k <- c(k, k__iore)
+ if (length(k) > 0) {
+ if(transform_rates) {
+ transparms[paste0("log_", names(k))] <- log(k)
+ } else transparms[names(k)] <- k
+ }
+
+ # Do not transform exponents in IORE models
+ N <- parms[grep("^N", names(parms))]
+ transparms[names(N)] <- N
+
+ # Go through state variables and apply isometric logratio transformation to
+ # formation fractions if requested
+ mod_vars = names(spec)
+ for (box in mod_vars) {
+ f <- parms[grep(paste("^f", box, sep = "_"), names(parms))]
+
+ if (length(f) > 0) {
+ if(transform_fractions) {
+ if (spec[[box]]$sink) {
+ trans_f <- ilr(c(f, 1 - sum(f)))
+ trans_f_names <- paste("f", box, "ilr", 1:length(trans_f), sep = "_")
+ transparms[trans_f_names] <- trans_f
+ } else {
+ if (length(f) > 1) {
+ trans_f <- ilr(f)
+ trans_f_names <- paste("f", box, "ilr", 1:length(trans_f), sep = "_")
+ transparms[trans_f_names] <- trans_f
+ }
+ }
+ } else {
+ transparms[names(f)] <- f
+ }
+ }
+ }
+
+ # Transform also FOMC parameters alpha and beta, DFOP and HS rates k1 and k2
+ # and HS parameter tb as well as logistic model parameters kmax, k0 and r if
+ # transformation of rates is requested
+ for (pname in c("alpha", "beta", "k1", "k2", "tb", "kmax", "k0", "r")) {
+ if (!is.na(parms[pname])) {
+ if (transform_rates) {
+ transparms[paste0("log_", pname)] <- log(parms[pname])
+ } else {
+ transparms[pname] <- parms[pname]
+ }
+ }
+ }
+
+ # DFOP parameter g is treated as a fraction
+ if (!is.na(parms["g"])) {
+ g <- parms["g"]
+ if (transform_fractions) {
+ transparms["g_ilr"] <- ilr(c(g, 1 - g))
+ } else {
+ transparms["g"] <- g
+ }
+ }
+
+ return(transparms)
+}
+
+#' @describeIn transform_odeparms Backtransform the set of transformed parameters
+#' @export backtransform_odeparms
+backtransform_odeparms <- function(transparms, mkinmod,
+ transform_rates = TRUE,
+ transform_fractions = TRUE)
+{
+ # We need the model specification for the names of the model
+ # variables and the information on the sink
+ spec = mkinmod$spec
+
+ # Set up container for backtransformed parameters
+ parms <- numeric(0)
+
+ # Do not transform initial values for state variables
+ state.ini.optim <- transparms[grep("_0$", names(transparms))]
+ parms[names(state.ini.optim)] <- state.ini.optim
+
+ # Exponential transformation for rate constants
+ if(transform_rates) {
+ trans_k <- transparms[grep("^log_k_", names(transparms))]
+ trans_k__iore <- transparms[grep("^log_k__iore_", names(transparms))]
+ trans_k = c(trans_k, trans_k__iore)
+ if (length(trans_k) > 0) {
+ k_names <- gsub("^log_k", "k", names(trans_k))
+ parms[k_names] <- exp(trans_k)
+ }
+ } else {
+ trans_k <- transparms[grep("^k_", names(transparms))]
+ parms[names(trans_k)] <- trans_k
+ trans_k__iore <- transparms[grep("^k__iore_", names(transparms))]
+ parms[names(trans_k__iore)] <- trans_k__iore
+ }
+
+ # Do not transform exponents in IORE models
+ N <- transparms[grep("^N", names(transparms))]
+ parms[names(N)] <- N
+
+ # Go through state variables and apply inverse isometric logratio transformation
+ mod_vars = names(spec)
+ for (box in mod_vars) {
+ # Get the names as used in the model
+ f_names = grep(paste("^f", box, sep = "_"), mkinmod$parms, value = TRUE)
+ # Get the formation fraction parameters
+ trans_f = transparms[grep(paste("^f", box, sep = "_"), names(transparms))]
+ if (length(trans_f) > 0) {
+ if(transform_fractions) {
+ f <- invilr(trans_f)
+ if (spec[[box]]$sink) {
+ parms[f_names] <- f[1:length(f)-1]
+ } else {
+ parms[f_names] <- f
+ }
+ } else {
+ parms[names(trans_f)] <- trans_f
+ }
+ }
+ }
+
+ # Transform parameters also for FOMC, DFOP, HS and logistic models
+ for (pname in c("alpha", "beta", "k1", "k2", "tb", "kmax", "k0", "r")) {
+ if (transform_rates) {
+ pname_trans = paste0("log_", pname)
+ if (!is.na(transparms[pname_trans])) {
+ parms[pname] <- exp(transparms[pname_trans])
+ }
+ } else {
+ if (!is.na(transparms[pname])) {
+ parms[pname] <- transparms[pname]
+ }
+ }
+ }
+
+ # DFOP parameter g is treated as a fraction
+ if (!is.na(transparms["g_ilr"])) {
+ g_ilr <- transparms["g_ilr"]
+ parms["g"] <- invilr(g_ilr)[1]
+ }
+ if (!is.na(transparms["g"])) {
+ parms["g"] <- transparms["g"]
+ }
+
+ return(parms)
+}
+# vim: set ts=2 sw=2 expandtab:
diff --git a/man/AIC.mmkin.Rd b/man/AIC.mmkin.Rd
index ca3fcf20..42c9a73b 100644
--- a/man/AIC.mmkin.Rd
+++ b/man/AIC.mmkin.Rd
@@ -1,31 +1,29 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/AIC.mmkin.R
\name{AIC.mmkin}
\alias{AIC.mmkin}
-\title{
- Calculated the AIC for a column of an mmkin object
-}
-\description{
- Provides a convenient way to compare different kineti models fitted to the
- same dataset.
-}
+\title{Calculated the AIC for a column of an mmkin object}
\usage{
- \method{AIC}{mmkin}(object, ..., k = 2)
+\method{AIC}{mmkin}(object, ..., k = 2)
}
\arguments{
- \item{object}{
- An object of class \code{\link{mmkin}}, containing only one column.
- }
- \item{\dots}{
- For compatibility with the generic method
- }
- \item{k}{
- As in the generic method
- }
+\item{object}{An object of class \code{\link{mmkin}}, containing only one
+column.}
+
+\item{\dots}{For compatibility with the generic method}
+
+\item{k}{As in the generic method}
}
\value{
- As in the generic method (a numeric value for single fits, or a dataframe if
- there are several fits in the column).
+As in the generic method (a numeric value for single fits, or a
+ dataframe if there are several fits in the column).
+}
+\description{
+Provides a convenient way to compare different kinetic models fitted to the
+same dataset.
}
\examples{
+
\dontrun{ # skip, as it takes > 10 s on winbuilder
f <- mmkin(c("SFO", "FOMC", "DFOP"),
list("FOCUS A" = FOCUS_2006_A,
@@ -40,7 +38,8 @@
# For FOCUS C, the more complex models fit better
AIC(f[, "FOCUS C"])
}
+
}
\author{
- Johannes Ranke
+Johannes Ranke
}
diff --git a/man/CAKE_export.Rd b/man/CAKE_export.Rd
index c7111bc8..142b4a75 100644
--- a/man/CAKE_export.Rd
+++ b/man/CAKE_export.Rd
@@ -1,73 +1,55 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/CAKE_export.R
\name{CAKE_export}
\alias{CAKE_export}
-\title{
- Export a list of datasets format to a CAKE study file
-}
-\description{
- In addition to the datasets, the pathways in the degradation
- model can be specified as well.
-}
+\title{Export a list of datasets format to a CAKE study file}
\usage{
-CAKE_export(ds, map = c(parent = "Parent"),
- links = NA,
+CAKE_export(ds, map = c(parent = "Parent"), links = NA,
filename = "CAKE_export.csf", path = ".", overwrite = FALSE,
- study = "Codlemone aerobic soil degradation",
- description = "",
- time_unit = "days",
- res_unit = "\% AR",
- comment = "Created using mkin::CAKE_export",
- date = Sys.Date(),
+ study = "Codlemone aerobic soil degradation", description = "",
+ time_unit = "days", res_unit = "\% AR",
+ comment = "Created using mkin::CAKE_export", date = Sys.Date(),
optimiser = "IRLS")
}
\arguments{
- \item{ds}{
- A named list of datasets in long format as compatible with
- \code{\link{mkinfit}}.
- }
- \item{map}{
- A character vector with CAKE compartment names (Parent, A1, ...),
- named with the names used in the list of datasets.
- }
- \item{links}{
- An optional character vector of target compartments, named with
- the names of the source compartments. In order to make this
- easier, the names are used as in the datasets supplied.
- }
- \item{filename}{
- Where to write the result. Should end in .csf in order to be compatible
- with CAKE.
- }
- \item{path}{
- An optional path to the output file.
- }
- \item{overwrite}{
- If TRUE, existing files are overwritten.
- }
- \item{study}{
- The name of the study.
- }
- \item{description}{
- An optional description.
- }
- \item{time_unit}{
- The time unit for the residue data.
- }
- \item{res_unit}{
- The unit used for the residues.
- }
- \item{comment}{
- An optional comment.
- }
- \item{date}{
- The date of file creation.
- }
- \item{optimiser}{
- Can be OLS or IRLS.
- }
+\item{ds}{A named list of datasets in long format as compatible with
+\code{\link{mkinfit}}.}
+
+\item{map}{A character vector with CAKE compartment names (Parent, A1, ...),
+named with the names used in the list of datasets.}
+
+\item{links}{An optional character vector of target compartments, named with
+the names of the source compartments. In order to make this easier, the
+names are used as in the datasets supplied.}
+
+\item{filename}{Where to write the result. Should end in .csf in order to be
+compatible with CAKE.}
+
+\item{path}{An optional path to the output file.}
+
+\item{overwrite}{If TRUE, existing files are overwritten.}
+
+\item{study}{The name of the study.}
+
+\item{description}{An optional description.}
+
+\item{time_unit}{The time unit for the residue data.}
+
+\item{res_unit}{The unit used for the residues.}
+
+\item{comment}{An optional comment.}
+
+\item{date}{The date of file creation.}
+
+\item{optimiser}{Can be OLS or IRLS.}
}
\value{
- The function is called for its side effect.
+The function is called for its side effect.
+}
+\description{
+In addition to the datasets, the pathways in the degradation model can be
+specified as well.
}
\author{
- Johannes Ranke
+Johannes Ranke
}
diff --git a/man/DFOP.solution.Rd b/man/DFOP.solution.Rd
index 50c4dce1..b145984a 100644
--- a/man/DFOP.solution.Rd
+++ b/man/DFOP.solution.Rd
@@ -1,35 +1,39 @@
-\name{DFOP.solution}
-\alias{DFOP.solution}
-\title{
-Double First-Order in Parallel kinetics
-}
-\description{
- Function describing decline from a defined starting value using the sum
- of two exponential decline functions.
-}
-\usage{
-DFOP.solution(t, parent.0, k1, k2, g)
-}
-\arguments{
- \item{t}{ Time. }
- \item{parent.0}{ Starting value for the response variable at time zero. }
- \item{k1}{ First kinetic constant. }
- \item{k2}{ Second kinetic constant. }
- \item{g}{ Fraction of the starting value declining according to the
- first kinetic constant.
- }
-}
-\value{
- The value of the response variable at time \code{t}.
-}
-\references{
- FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence and
- Degradation Kinetics from Environmental Fate Studies on Pesticides in EU
- Registration} Report of the FOCUS Work Group on Degradation Kinetics,
- EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
- \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
-}
-\examples{
- plot(function(x) DFOP.solution(x, 100, 5, 0.5, 0.3), 0, 4, ylim=c(0,100))
-}
-\keyword{ manip }
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/DFOP.solution.R
+\name{DFOP.solution}
+\alias{DFOP.solution}
+\title{Double First-Order in Parallel kinetics}
+\usage{
+DFOP.solution(t, parent.0, k1, k2, g)
+}
+\arguments{
+\item{t}{Time.}
+
+\item{parent.0}{Starting value for the response variable at time zero.}
+
+\item{k1}{First kinetic constant.}
+
+\item{k2}{Second kinetic constant.}
+
+\item{g}{Fraction of the starting value declining according to the first
+kinetic constant.}
+}
+\value{
+The value of the response variable at time \code{t}.
+}
+\description{
+Function describing decline from a defined starting value using the sum of
+two exponential decline functions.
+}
+\examples{
+
+ plot(function(x) DFOP.solution(x, 100, 5, 0.5, 0.3), 0, 4, ylim = c(0,100))
+
+}
+\references{
+FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence
+ and Degradation Kinetics from Environmental Fate Studies on Pesticides in
+ EU Registration} Report of the FOCUS Work Group on Degradation Kinetics,
+ EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
+ \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+}
diff --git a/man/Extract.mmkin.Rd b/man/Extract.mmkin.Rd
index 973dc28f..7677bdba 100644
--- a/man/Extract.mmkin.Rd
+++ b/man/Extract.mmkin.Rd
@@ -1,12 +1,11 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/mmkin.R
\name{[.mmkin}
\alias{[.mmkin}
\title{Subsetting method for mmkin objects}
\usage{
\method{[}{mmkin}(x, i, j, ..., drop = FALSE)
}
-\description{
- Subsetting method for mmkin objects.
-}
\arguments{
\item{x}{An \code{\link{mmkin} object}}
@@ -16,16 +15,17 @@
\item{...}{Not used, only there to satisfy the generic method definition}
-\item{drop}{If FALSE, the method always returns an mmkin object, otherwise either
- a list of mkinfit objects or a single mkinfit object.}
+\item{drop}{If FALSE, the method always returns an mmkin object, otherwise
+either a list of mkinfit objects or a single mkinfit object.}
}
\value{
- An object of class \code{\link{mmkin}}.
+An object of class \code{\link{mmkin}}.
}
-\author{
- Johannes Ranke
+\description{
+Subsetting method for mmkin objects.
}
\examples{
+
# Only use one core, to pass R CMD check --as-cran
fits <- mmkin(c("SFO", "FOMC"), list(B = FOCUS_2006_B, C = FOCUS_2006_C),
cores = 1, quiet = TRUE)
@@ -35,6 +35,10 @@
head(
# This extracts an mkinfit object with lots of components
- fits[["FOMC", "B"]]
+ fits[["FOMC", "B"]]
)
+
+}
+\author{
+Johannes Ranke
}
diff --git a/man/FOMC.solution.Rd b/man/FOMC.solution.Rd
index 55d89709..54430dd1 100644
--- a/man/FOMC.solution.Rd
+++ b/man/FOMC.solution.Rd
@@ -1,48 +1,51 @@
-\name{FOMC.solution}
-\alias{FOMC.solution}
-\title{ First-Order Multi-Compartment kinetics }
-\description{
- Function describing exponential decline from a defined starting value, with
- a decreasing rate constant.
-
- The form given here differs slightly from the original reference by Gustafson
- and Holden (1990). The parameter \code{beta} corresponds to 1/beta in the
- original equation.
-}
-\usage{
-FOMC.solution(t, parent.0, alpha, beta)
-}
-\arguments{
- \item{t}{ Time. }
- \item{parent.0}{ Starting value for the response variable at time zero. }
- \item{alpha}{
- Shape parameter determined by coefficient of variation of rate constant
- values. }
- \item{beta}{
- Location parameter.
-}
-}
-\note{
- The solution of the FOMC kinetic model reduces to the
- \code{\link{SFO.solution}} for large values of \code{alpha} and
- \code{beta} with
- \eqn{k = \frac{\beta}{\alpha}}{k = beta/alpha}.
-}
-\value{
- The value of the response variable at time \code{t}.
-}
-\references{
- FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence and
- Degradation Kinetics from Environmental Fate Studies on Pesticides in EU
- Registration} Report of the FOCUS Work Group on Degradation Kinetics,
- EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
- \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
-
- Gustafson DI and Holden LR (1990) Nonlinear pesticide dissipation in soil: A
- new model based on spatial variability. \emph{Environmental Science and
- Technology} \bold{24}, 1032-1038
-}
-\examples{
- plot(function(x) FOMC.solution(x, 100, 10, 2), 0, 2, ylim = c(0, 100))
-}
-\keyword{ manip }
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/FOMC.solution.R
+\name{FOMC.solution}
+\alias{FOMC.solution}
+\title{First-Order Multi-Compartment kinetics}
+\usage{
+FOMC.solution(t, parent.0, alpha, beta)
+}
+\arguments{
+\item{t}{Time.}
+
+\item{parent.0}{Starting value for the response variable at time zero.}
+
+\item{alpha}{Shape parameter determined by coefficient of variation of rate
+constant values.}
+
+\item{beta}{Location parameter.}
+}
+\value{
+The value of the response variable at time \code{t}.
+}
+\description{
+Function describing exponential decline from a defined starting value, with
+a decreasing rate constant.
+}
+\details{
+The form given here differs slightly from the original reference by
+Gustafson and Holden (1990). The parameter \code{beta} corresponds to 1/beta
+in the original equation.
+}
+\note{
+The solution of the FOMC kinetic model reduces to the
+ \code{\link{SFO.solution}} for large values of \code{alpha} and
+ \code{beta} with \eqn{k = \frac{\beta}{\alpha}}{k = beta/alpha}.
+}
+\examples{
+
+ plot(function(x) FOMC.solution(x, 100, 10, 2), 0, 2, ylim = c(0, 100))
+
+}
+\references{
+FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence
+ and Degradation Kinetics from Environmental Fate Studies on Pesticides in
+ EU Registration} Report of the FOCUS Work Group on Degradation Kinetics,
+ EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
+ \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+
+ Gustafson DI and Holden LR (1990) Nonlinear pesticide dissipation in soil:
+ A new model based on spatial variability. \emph{Environmental Science and
+ Technology} \bold{24}, 1032-1038
+}
diff --git a/man/HS.solution.Rd b/man/HS.solution.Rd
index 41e36c68..ba96b139 100644
--- a/man/HS.solution.Rd
+++ b/man/HS.solution.Rd
@@ -1,33 +1,40 @@
-\name{HS.solution}
-\alias{HS.solution}
-\title{ Hockey-Stick kinetics }
-\description{
- Function describing two exponential decline functions with a break point
- between them.
-}
-\usage{
-HS.solution(t, parent.0, k1, k2, tb)
-}
-\arguments{
- \item{t}{ Time. }
- \item{parent.0}{ Starting value for the response variable at time zero. }
- \item{k1}{ First kinetic constant. }
- \item{k2}{ Second kinetic constant. }
- \item{tb}{ Break point. Before this time, exponential decline according
- to \code{k1} is calculated, after this time, exponential decline proceeds
- according to \code{k2}. }
-}
-\value{
- The value of the response variable at time \code{t}.
-}
-\references{
- FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence and
- Degradation Kinetics from Environmental Fate Studies on Pesticides in EU
- Registration} Report of the FOCUS Work Group on Degradation Kinetics,
- EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
- \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
-}
-\examples{
- plot(function(x) HS.solution(x, 100, 2, 0.3, 0.5), 0, 2, ylim=c(0,100))
-}
-\keyword{ manip }
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/HS.solution.R
+\name{HS.solution}
+\alias{HS.solution}
+\title{Hockey-Stick kinetics}
+\usage{
+HS.solution(t, parent.0, k1, k2, tb)
+}
+\arguments{
+\item{t}{Time.}
+
+\item{parent.0}{Starting value for the response variable at time zero.}
+
+\item{k1}{First kinetic constant.}
+
+\item{k2}{Second kinetic constant.}
+
+\item{tb}{Break point. Before this time, exponential decline according to
+\code{k1} is calculated, after this time, exponential decline proceeds
+according to \code{k2}.}
+}
+\value{
+The value of the response variable at time \code{t}.
+}
+\description{
+Function describing two exponential decline functions with a break point
+between them.
+}
+\examples{
+
+ plot(function(x) HS.solution(x, 100, 2, 0.3, 0.5), 0, 2, ylim=c(0,100))
+
+}
+\references{
+FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence
+ and Degradation Kinetics from Environmental Fate Studies on Pesticides in
+ EU Registration} Report of the FOCUS Work Group on Degradation Kinetics,
+ EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
+ \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+}
diff --git a/man/IORE.solution.Rd b/man/IORE.solution.Rd
index 65760f95..ad2df3df 100644
--- a/man/IORE.solution.Rd
+++ b/man/IORE.solution.Rd
@@ -1,44 +1,51 @@
-\name{IORE.solution}
-\alias{IORE.solution}
-\title{ Indeterminate order rate equation kinetics }
-\description{
- Function describing exponential decline from a defined starting value, with
- a concentration dependent rate constant.
-}
-\usage{
- IORE.solution(t, parent.0, k__iore, N)
-}
-\arguments{
- \item{t}{ Time. }
- \item{parent.0}{ Starting value for the response variable at time zero. }
- \item{k__iore}{ Rate constant. Note that this depends on the concentration units used. }
- \item{N}{ Exponent describing the nonlinearity of the rate equation }
-}
-\note{
- The solution of the IORE kinetic model reduces to the
- \code{\link{SFO.solution}} if N = 1.
- The parameters of the IORE model can be transformed to equivalent parameters
- of the FOMC mode - see the NAFTA guidance for details.
-}
-\value{
- The value of the response variable at time \code{t}.
-}
-\references{
- NAFTA Technical Working Group on Pesticides (not dated) Guidance for
- Evaluating and Calculating Degradation Kinetics in Environmental
- Media
-}
-\examples{
- plot(function(x) IORE.solution(x, 100, 0.2, 1.3), 0, 2, ylim = c(0, 100))
- \dontrun{
- fit.fomc <- mkinfit("FOMC", FOCUS_2006_C, quiet = TRUE)
- fit.iore <- mkinfit("IORE", FOCUS_2006_C, quiet = TRUE)
- fit.iore.deS <- mkinfit("IORE", FOCUS_2006_C, solution_type = "deSolve", quiet = TRUE)
-
- print(data.frame(fit.fomc$par, fit.iore$par, fit.iore.deS$par,
- row.names = paste("model par", 1:4)))
- print(rbind(fomc = endpoints(fit.fomc)$distimes, iore = endpoints(fit.iore)$distimes,
- iore.deS = endpoints(fit.iore)$distimes))
- }
-}
-\keyword{ manip }
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/IORE.solution.R
+\name{IORE.solution}
+\alias{IORE.solution}
+\title{Indeterminate order rate equation kinetics}
+\usage{
+IORE.solution(t, parent.0, k__iore, N)
+}
+\arguments{
+\item{t}{Time.}
+
+\item{parent.0}{Starting value for the response variable at time zero.}
+
+\item{k__iore}{Rate constant. Note that this depends on the concentration
+units used.}
+
+\item{N}{Exponent describing the nonlinearity of the rate equation}
+}
+\value{
+The value of the response variable at time \code{t}.
+}
+\description{
+Function describing exponential decline from a defined starting value, with
+a concentration dependent rate constant.
+}
+\note{
+The solution of the IORE kinetic model reduces to the
+ \code{\link{SFO.solution}} if N = 1. The parameters of the IORE model can
+ be transformed to equivalent parameters of the FOMC mode - see the NAFTA
+ guidance for details.
+}
+\examples{
+
+ plot(function(x) IORE.solution(x, 100, 0.2, 1.3), 0, 2, ylim = c(0, 100))
+ \dontrun{
+ fit.fomc <- mkinfit("FOMC", FOCUS_2006_C, quiet = TRUE)
+ fit.iore <- mkinfit("IORE", FOCUS_2006_C, quiet = TRUE)
+ fit.iore.deS <- mkinfit("IORE", FOCUS_2006_C, solution_type = "deSolve", quiet = TRUE)
+
+ print(data.frame(fit.fomc$par, fit.iore$par, fit.iore.deS$par,
+ row.names = paste("model par", 1:4)))
+ print(rbind(fomc = endpoints(fit.fomc)$distimes, iore = endpoints(fit.iore)$distimes,
+ iore.deS = endpoints(fit.iore)$distimes))
+ }
+
+}
+\references{
+NAFTA Technical Working Group on Pesticides (not dated) Guidance
+ for Evaluating and Calculating Degradation Kinetics in Environmental Media
+}
+\keyword{manip}
diff --git a/man/SFO.solution.Rd b/man/SFO.solution.Rd
index 5853d566..03c0dce8 100644
--- a/man/SFO.solution.Rd
+++ b/man/SFO.solution.Rd
@@ -1,28 +1,33 @@
-\name{SFO.solution}
-\alias{SFO.solution}
-\title{ Single First-Order kinetics }
-\description{
- Function describing exponential decline from a defined starting value.
-}
-\usage{
- SFO.solution(t, parent.0, k)
-}
-\arguments{
- \item{t}{ Time. }
- \item{parent.0}{ Starting value for the response variable at time zero. }
- \item{k}{ Kinetic constant. }
-}
-\value{
- The value of the response variable at time \code{t}.
-}
-\references{
- FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence and
- Degradation Kinetics from Environmental Fate Studies on Pesticides in EU
- Registration} Report of the FOCUS Work Group on Degradation Kinetics,
- EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
- \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
-}
-\examples{
- \dontrun{plot(function(x) SFO.solution(x, 100, 3), 0, 2)}
-}
-\keyword{ manip }
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/SFO.solution.R
+\name{SFO.solution}
+\alias{SFO.solution}
+\title{Single First-Order kinetics}
+\usage{
+SFO.solution(t, parent.0, k)
+}
+\arguments{
+\item{t}{Time.}
+
+\item{parent.0}{Starting value for the response variable at time zero.}
+
+\item{k}{Kinetic constant.}
+}
+\value{
+The value of the response variable at time \code{t}.
+}
+\description{
+Function describing exponential decline from a defined starting value.
+}
+\examples{
+
+ \dontrun{plot(function(x) SFO.solution(x, 100, 3), 0, 2)}
+
+}
+\references{
+FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence
+ and Degradation Kinetics from Environmental Fate Studies on Pesticides in
+ EU Registration} Report of the FOCUS Work Group on Degradation Kinetics,
+ EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
+ \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+}
diff --git a/man/SFORB.solution.Rd b/man/SFORB.solution.Rd
index 67c4c3f2..ce9dce73 100644
--- a/man/SFORB.solution.Rd
+++ b/man/SFORB.solution.Rd
@@ -1,35 +1,43 @@
-\name{SFORB.solution}
-\alias{SFORB.solution}
-\title{ Single First-Order Reversible Binding kinetics }
-\description{
- Function describing the solution of the differential equations describing
- the kinetic model with first-order terms for a two-way transfer from a free
- to a bound fraction, and a first-order degradation term for the free
- fraction. The initial condition is a defined amount in the free fraction and
- no substance in the bound fraction.
-}
-\usage{
- SFORB.solution(t, parent.0, k_12, k_21, k_1output)
-}
-\arguments{
- \item{t}{ Time. }
- \item{parent.0}{ Starting value for the response variable at time zero. }
- \item{k_12}{ Kinetic constant describing transfer from free to bound. }
- \item{k_21}{ Kinetic constant describing transfer from bound to free. }
- \item{k_1output}{ Kinetic constant describing degradation of the free fraction. }
-}
-\value{
- The value of the response variable, which is the sum of free and bound
- fractions at time \code{t}.
-}
-\references{
- FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence and
- Degradation Kinetics from Environmental Fate Studies on Pesticides in EU
- Registration} Report of the FOCUS Work Group on Degradation Kinetics,
- EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
- \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
-}
-\examples{
- \dontrun{plot(function(x) SFORB.solution(x, 100, 0.5, 2, 3), 0, 2)}
-}
-\keyword{ manip }
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/SFORB.solution.R
+\name{SFORB.solution}
+\alias{SFORB.solution}
+\title{Single First-Order Reversible Binding kinetics}
+\usage{
+SFORB.solution(t, parent.0, k_12, k_21, k_1output)
+}
+\arguments{
+\item{t}{Time.}
+
+\item{parent.0}{Starting value for the response variable at time zero.}
+
+\item{k_12}{Kinetic constant describing transfer from free to bound.}
+
+\item{k_21}{Kinetic constant describing transfer from bound to free.}
+
+\item{k_1output}{Kinetic constant describing degradation of the free
+fraction.}
+}
+\value{
+The value of the response variable, which is the sum of free and
+ bound fractions at time \code{t}.
+}
+\description{
+Function describing the solution of the differential equations describing
+the kinetic model with first-order terms for a two-way transfer from a free
+to a bound fraction, and a first-order degradation term for the free
+fraction. The initial condition is a defined amount in the free fraction
+and no substance in the bound fraction.
+}
+\examples{
+
+ \dontrun{plot(function(x) SFORB.solution(x, 100, 0.5, 2, 3), 0, 2)}
+
+}
+\references{
+FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence
+ and Degradation Kinetics from Environmental Fate Studies on Pesticides in
+ EU Registration} Report of the FOCUS Work Group on Degradation Kinetics,
+ EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
+ \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+}
diff --git a/man/add_err.Rd b/man/add_err.Rd
index 00b50878..36b98be9 100644
--- a/man/add_err.Rd
+++ b/man/add_err.Rd
@@ -1,61 +1,46 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/add_err.R
\name{add_err}
\alias{add_err}
-\title{
- Add normally distributed errors to simulated kinetic degradation data
-}
-\description{
- Normally distributed errors are added to data predicted for a specific
- degradation model using \code{\link{mkinpredict}}. The variance of the error
- may depend on the predicted value and is specified as a standard deviation.
-}
+\title{Add normally distributed errors to simulated kinetic degradation data}
\usage{
- add_err(prediction, sdfunc, secondary = c("M1", "M2"),
- n = 1000, LOD = 0.1, reps = 2,
- digits = 1, seed = NA)
+add_err(prediction, sdfunc, secondary = c("M1", "M2"), n = 1000,
+ LOD = 0.1, reps = 2, digits = 1, seed = NA)
}
\arguments{
- \item{prediction}{
- A prediction from a kinetic model as produced by \code{\link{mkinpredict}}.
- }
- \item{sdfunc}{
- A function taking the predicted value as its only argument and returning
- a standard deviation that should be used for generating the random error
- terms for this value.
- }
- \item{secondary}{
- The names of state variables that should have an initial value of zero
- }
- \item{n}{
- The number of datasets to be generated.
- }
- \item{LOD}{
- The limit of detection (LOD). Values that are below the LOD after adding
- the random error will be set to NA.
- }
- \item{reps}{
- The number of replicates to be generated within the datasets.
- }
- \item{digits}{
- The number of digits to which the values will be rounded.
- }
- \item{seed}{
- The seed used for the generation of random numbers. If NA, the seed
- is not set.
- }
+\item{prediction}{A prediction from a kinetic model as produced by
+\code{\link{mkinpredict}}.}
+
+\item{sdfunc}{A function taking the predicted value as its only argument and
+returning a standard deviation that should be used for generating the
+random error terms for this value.}
+
+\item{secondary}{The names of state variables that should have an initial
+value of zero}
+
+\item{n}{The number of datasets to be generated.}
+
+\item{LOD}{The limit of detection (LOD). Values that are below the LOD after
+adding the random error will be set to NA.}
+
+\item{reps}{The number of replicates to be generated within the datasets.}
+
+\item{digits}{The number of digits to which the values will be rounded.}
+
+\item{seed}{The seed used for the generation of random numbers. If NA, the
+seed is not set.}
}
\value{
- A list of datasets compatible with \code{\link{mmkin}}, i.e.
- the components of the list are datasets compatible with
- \code{\link{mkinfit}}.
+A list of datasets compatible with \code{\link{mmkin}}, i.e. the
+ components of the list are datasets compatible with \code{\link{mkinfit}}.
}
-\references{
- Ranke J and Lehmann R (2015) To t-test or not to t-test, that is the question. XV Symposium on Pesticide Chemistry 2-4 September 2015, Piacenza, Italy
- http://chem.uft.uni-bremen.de/ranke/posters/piacenza_2015.pdf
-}
-\author{
- Johannes Ranke
+\description{
+Normally distributed errors are added to data predicted for a specific
+degradation model using \code{\link{mkinpredict}}. The variance of the error
+may depend on the predicted value and is specified as a standard deviation.
}
\examples{
+
# The kinetic model
m_SFO_SFO <- mkinmod(parent = mkinsub("SFO", "M1"),
M1 = mkinsub("SFO"), use_of_ff = "max")
@@ -97,5 +82,14 @@ plot(f_SFO_SFO[[3]], show_residuals = TRUE)
# and plot.mmkin is used
plot(f_SFO_SFO[1, 3])
}
+
+}
+\references{
+Ranke J and Lehmann R (2015) To t-test or not to t-test, that is
+the question. XV Symposium on Pesticide Chemistry 2-4 September 2015,
+Piacenza, Italy
+http://chem.uft.uni-bremen.de/ranke/posters/piacenza_2015.pdf
+}
+\author{
+Johannes Ranke
}
-\keyword{ manip }
diff --git a/man/endpoints.Rd b/man/endpoints.Rd
index 55a4cb0a..13182369 100644
--- a/man/endpoints.Rd
+++ b/man/endpoints.Rd
@@ -1,33 +1,35 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/endpoints.R
\name{endpoints}
\alias{endpoints}
-\title{
-Function to calculate endpoints for further use from kinetic models fitted with mkinfit
-}
-\description{
-This function calculates DT50 and DT90 values as well as formation fractions from kinetic models
-fitted with mkinfit. If the SFORB model was specified for one of the parents or metabolites,
-the Eigenvalues are returned. These are equivalent to the rate constantes of the DFOP model, but
-with the advantage that the SFORB model can also be used for metabolites.
-}
+\title{Function to calculate endpoints for further use from kinetic models fitted
+with mkinfit}
\usage{
endpoints(fit)
}
\arguments{
- \item{fit}{
- An object of class \code{\link{mkinfit}}.
- }
-}
-\note{
- The function is used internally by \code{\link{summary.mkinfit}}.
+\item{fit}{An object of class \code{\link{mkinfit}}.}
}
\value{
- A list with the components mentioned above.
+A list with the components mentioned above.
+}
+\description{
+This function calculates DT50 and DT90 values as well as formation fractions
+from kinetic models fitted with mkinfit. If the SFORB model was specified
+for one of the parents or metabolites, the Eigenvalues are returned. These
+are equivalent to the rate constantes of the DFOP model, but with the
+advantage that the SFORB model can also be used for metabolites.
+}
+\note{
+The function is used internally by \code{\link{summary.mkinfit}}.
}
\examples{
+
fit <- mkinfit("FOMC", FOCUS_2006_C, quiet = TRUE)
endpoints(fit)
+
}
\author{
- Johannes Ranke
+Johannes Ranke
}
-\keyword{ manip }
+\keyword{manip}
diff --git a/man/ilr.Rd b/man/ilr.Rd
index 29bf7d87..0cbd7e2c 100644
--- a/man/ilr.Rd
+++ b/man/ilr.Rd
@@ -1,36 +1,29 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/ilr.R
\name{ilr}
\alias{ilr}
\alias{invilr}
-\title{
- Function to perform isometric log-ratio transformation
-}
-\description{
- This implementation is a special case of the class of isometric log-ratio transformations.
-}
+\title{Function to perform isometric log-ratio transformation}
\usage{
- ilr(x)
- invilr(x)
+ilr(x)
+
+invilr(x)
}
\arguments{
- \item{x}{
- A numeric vector. Naturally, the forward transformation is only sensible for
- vectors with all elements being greater than zero.
- }
+\item{x}{A numeric vector. Naturally, the forward transformation is only
+sensible for vectors with all elements being greater than zero.}
}
\value{
- The result of the forward or backward transformation. The returned components always
- sum to 1 for the case of the inverse log-ratio transformation.
-}
-\references{
- Peter Filzmoser, Karel Hron (2008) Outlier Detection for Compositional Data Using Robust Methods. Math Geosci 40 233-248
-}
-\author{
- René Lehmann and Johannes Ranke
+The result of the forward or backward transformation. The returned
+ components always sum to 1 for the case of the inverse log-ratio
+ transformation.
}
-\seealso{
- Another implementation can be found in R package \code{robCompositions}.
+\description{
+This implementation is a special case of the class of isometric log-ratio
+transformations.
}
\examples{
+
# Order matters
ilr(c(0.1, 1, 10))
ilr(c(10, 1, 0.1))
@@ -51,6 +44,17 @@ a <- c(0.1, 0.3, 0.5)
b <- invilr(a)
length(b) # Four elements
ilr(c(b[1:3], 1 - sum(b[1:3]))) # Gives c(0.1, 0.3, 0.5)
-}
-\keyword{ manip }
+}
+\references{
+Peter Filzmoser, Karel Hron (2008) Outlier Detection for
+ Compositional Data Using Robust Methods. Math Geosci 40 233-248
+}
+\seealso{
+Another implementation can be found in R package
+ \code{robCompositions}.
+}
+\author{
+René Lehmann and Johannes Ranke
+}
+\keyword{manip}
diff --git a/man/logLik.mkinfit.Rd b/man/logLik.mkinfit.Rd
index 5e910c2e..bb2c2957 100644
--- a/man/logLik.mkinfit.Rd
+++ b/man/logLik.mkinfit.Rd
@@ -1,39 +1,34 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/logLik.mkinfit.R
\name{logLik.mkinfit}
\alias{logLik.mkinfit}
-\title{
- Calculated the log-likelihood of a fitted mkinfit object
-}
-\description{
- This function simply calculates the product of the likelihood densities
- calculated using \code{\link{dnorm}}, i.e. assuming normal distribution,
- with of the mean predicted by the degradation model, and the
- standard deviation predicted by the error model.
-
- The total number of estimated parameters returned with the value
- of the likelihood is calculated as the sum of fitted degradation
- model parameters and the fitted error model parameters.
-}
+\title{Calculated the log-likelihood of a fitted mkinfit object}
\usage{
- \method{logLik}{mkinfit}(object, ...)
+\method{logLik}{mkinfit}(object, ...)
}
\arguments{
- \item{object}{
- An object of class \code{\link{mkinfit}}.
- }
- \item{\dots}{
- For compatibility with the generic method
- }
+\item{object}{An object of class \code{\link{mkinfit}}.}
+
+\item{\dots}{For compatibility with the generic method}
}
\value{
- An object of class \code{\link{logLik}} with the number of
- estimated parameters (degradation model parameters plus variance
- model parameters) as attribute.
+An object of class \code{\link{logLik}} with the number of estimated
+ parameters (degradation model parameters plus variance model parameters)
+ as attribute.
}
-\seealso{
- Compare the AIC of columns of \code{\link{mmkin}} objects using
- \code{\link{AIC.mmkin}}.
+\description{
+This function simply calculates the product of the likelihood densities
+calculated using \code{\link{dnorm}}, i.e. assuming normal distribution,
+with of the mean predicted by the degradation model, and the standard
+deviation predicted by the error model.
+}
+\details{
+The total number of estimated parameters returned with the value of the
+likelihood is calculated as the sum of fitted degradation model parameters
+and the fitted error model parameters.
}
\examples{
+
\dontrun{
sfo_sfo <- mkinmod(
parent = mkinsub("SFO", to = "m1"),
@@ -45,7 +40,12 @@
f_tc <- mkinfit(sfo_sfo, d_t, error_model = "tc", quiet = TRUE)
AIC(f_nw, f_obs, f_tc)
}
+
+}
+\seealso{
+Compare the AIC of columns of \code{\link{mmkin}} objects using
+ \code{\link{AIC.mmkin}}.
}
\author{
- Johannes Ranke
+Johannes Ranke
}
diff --git a/man/logistic.solution.Rd b/man/logistic.solution.Rd
index 05b6c0aa..def776aa 100644
--- a/man/logistic.solution.Rd
+++ b/man/logistic.solution.Rd
@@ -1,36 +1,35 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/logistic.solution.R
\name{logistic.solution}
\alias{logistic.solution}
-\title{ Logistic kinetics }
-\description{
- Function describing exponential decline from a defined starting value, with
- an increasing rate constant, supposedly caused by microbial growth
-}
+\title{Logistic kinetics}
\usage{
logistic.solution(t, parent.0, kmax, k0, r)
}
\arguments{
- \item{t}{ Time. }
- \item{parent.0}{ Starting value for the response variable at time zero. }
- \item{kmax}{ Maximum rate constant. }
- \item{k0}{ Minumum rate constant effective at time zero. }
- \item{r}{ Growth rate of the increase in the rate constant. }
-}
-\note{
- The solution of the logistic model reduces to the
- \code{\link{SFO.solution}} if \code{k0} is equal to
- \code{kmax}.
+\item{t}{Time.}
+
+\item{parent.0}{Starting value for the response variable at time zero.}
+
+\item{kmax}{Maximum rate constant.}
+
+\item{k0}{Minumum rate constant effective at time zero.}
+
+\item{r}{Growth rate of the increase in the rate constant.}
}
\value{
- The value of the response variable at time \code{t}.
+The value of the response variable at time \code{t}.
}
-\references{
- FOCUS (2014) \dQuote{Generic guidance for Estimating Persistence and
- Degradation Kinetics from Environmental Fate Studies on Pesticides in EU
- Registration} Report of the FOCUS Work Group on Degradation Kinetics,
- Version 1.1, 18 December 2014
- \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+\description{
+Function describing exponential decline from a defined starting value, with
+an increasing rate constant, supposedly caused by microbial growth
+}
+\note{
+The solution of the logistic model reduces to the
+ \code{\link{SFO.solution}} if \code{k0} is equal to \code{kmax}.
}
\examples{
+
# Reproduce the plot on page 57 of FOCUS (2014)
plot(function(x) logistic.solution(x, 100, 0.08, 0.0001, 0.2),
from = 0, to = 100, ylim = c(0, 100),
@@ -64,5 +63,12 @@ logistic.solution(t, parent.0, kmax, k0, r)
plot_sep(m)
summary(m)$bpar
endpoints(m)$distimes
+
+}
+\references{
+FOCUS (2014) \dQuote{Generic guidance for Estimating Persistence
+ and Degradation Kinetics from Environmental Fate Studies on Pesticides in
+ EU Registration} Report of the FOCUS Work Group on Degradation Kinetics,
+ Version 1.1, 18 December 2014
+ \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
}
-\keyword{ manip }
diff --git a/man/max_twa_parent.Rd b/man/max_twa_parent.Rd
index c601b768..7c9f4861 100644
--- a/man/max_twa_parent.Rd
+++ b/man/max_twa_parent.Rd
@@ -1,80 +1,76 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/max_twa_parent.R
\name{max_twa_parent}
\alias{max_twa_parent}
\alias{max_twa_sfo}
\alias{max_twa_fomc}
\alias{max_twa_dfop}
\alias{max_twa_hs}
-\title{
- Function to calculate maximum time weighted average concentrations from kinetic models fitted with mkinfit
-}
-\description{
-This function calculates maximum moving window time weighted average concentrations
-(TWAs) for kinetic models fitted with \code{\link{mkinfit}}. Currently, only
-calculations for the parent are implemented for the SFO, FOMC, DFOP and HS models,
-using the analytical formulas given in the PEC soil section of the FOCUS
-guidance.}
+\title{Function to calculate maximum time weighted average concentrations from
+kinetic models fitted with mkinfit}
\usage{
- max_twa_parent(fit, windows)
- max_twa_sfo(M0 = 1, k, t)
- max_twa_fomc(M0 = 1, alpha, beta, t)
- max_twa_dfop(M0 = 1, k1, k2, g, t)
- max_twa_hs(M0 = 1, k1, k2, tb, t)
+max_twa_parent(fit, windows)
+
+max_twa_sfo(M0 = 1, k, t)
+
+max_twa_fomc(M0 = 1, alpha, beta, t)
+
+max_twa_dfop(M0 = 1, k1, k2, g, t)
+
+max_twa_hs(M0 = 1, k1, k2, tb, t)
}
\arguments{
- \item{fit}{
- An object of class \code{\link{mkinfit}}.
- }
- \item{windows}{
- The width of the time windows for which the TWAs should be calculated.
- }
- \item{M0}{
- The initial concentration for which the maximum time weighted
- average over the decline curve should be calculated. The default
- is to use a value of 1, which means that a relative maximum time
- weighted average factor (f_twa) is calculated.
- }
- \item{k}{
- The rate constant in the case of SFO kinetics.
- }
- \item{t}{
- The width of the time window.
- }
- \item{alpha}{
- Parameter of the FOMC model.
- }
- \item{beta}{
- Parameter of the FOMC model.
- }
- \item{k1}{
- The first rate constant of the DFOP or the HS kinetics.
- }
- \item{k2}{
- The second rate constant of the DFOP or the HS kinetics.
- }
- \item{g}{
- Parameter of the DFOP model.
- }
- \item{tb}{
- Parameter of the HS model.
- }
+\item{fit}{An object of class \code{\link{mkinfit}}.}
+
+\item{windows}{The width of the time windows for which the TWAs should be
+calculated.}
+
+\item{M0}{The initial concentration for which the maximum time weighted
+average over the decline curve should be calculated. The default is to use
+a value of 1, which means that a relative maximum time weighted average
+factor (f_twa) is calculated.}
+
+\item{k}{The rate constant in the case of SFO kinetics.}
+
+\item{t}{The width of the time window.}
+
+\item{alpha}{Parameter of the FOMC model.}
+
+\item{beta}{Parameter of the FOMC model.}
+
+\item{k1}{The first rate constant of the DFOP or the HS kinetics.}
+
+\item{k2}{The second rate constant of the DFOP or the HS kinetics.}
+
+\item{g}{Parameter of the DFOP model.}
+
+\item{tb}{Parameter of the HS model.}
}
\value{
- For \code{max_twa_parent}, a numeric vector, named using the \code{windows} argument.
- For the other functions, a numeric vector of length one (also known as 'a
- number').
+For \code{max_twa_parent}, a numeric vector, named using the
+ \code{windows} argument. For the other functions, a numeric vector of
+ length one (also known as 'a number').
+}
+\description{
+This function calculates maximum moving window time weighted average
+concentrations (TWAs) for kinetic models fitted with \code{\link{mkinfit}}.
+Currently, only calculations for the parent are implemented for the SFO,
+FOMC, DFOP and HS models, using the analytical formulas given in the PEC
+soil section of the FOCUS guidance.
}
\examples{
+
fit <- mkinfit("FOMC", FOCUS_2006_C, quiet = TRUE)
max_twa_parent(fit, c(7, 21))
+
}
\references{
- FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence and
- Degradation Kinetics from Environmental Fate Studies on Pesticides in EU
- Registration} Report of the FOCUS Work Group on Degradation Kinetics,
+FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence
+ and Degradation Kinetics from Environmental Fate Studies on Pesticides in
+ EU Registration} Report of the FOCUS Work Group on Degradation Kinetics,
EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
\url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
}
\author{
- Johannes Ranke
+Johannes Ranke
}
-\keyword{ manip }
diff --git a/man/mkin_long_to_wide.Rd b/man/mkin_long_to_wide.Rd
index c83f7c78..e76709b9 100644
--- a/man/mkin_long_to_wide.Rd
+++ b/man/mkin_long_to_wide.Rd
@@ -1,36 +1,34 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/mkin_long_to_wide.R
\name{mkin_long_to_wide}
\alias{mkin_long_to_wide}
-\title{
- Convert a dataframe from long to wide format
-}
+\title{Convert a dataframe from long to wide format}
\usage{
mkin_long_to_wide(long_data, time = "time", outtime = "time")
}
-\description{
- This function takes a dataframe in the long form, i.e. with a row
- for each observed value, and converts it into a dataframe with one
- independent variable and several dependent variables as columns.
-}
\arguments{
- \item{long_data}{
- The dataframe must contain one variable called "time" with the time values specified by the
- \code{time} argument, one column called "name" with the grouping of the observed values, and
- finally one column of observed values called "value".
-}
- \item{time}{
- The name of the time variable in the long input data.
-}
- \item{outtime}{
- The name of the time variable in the wide output data.
-}
+\item{long_data}{The dataframe must contain one variable called "time" with
+the time values specified by the \code{time} argument, one column called
+"name" with the grouping of the observed values, and finally one column of
+observed values called "value".}
+
+\item{time}{The name of the time variable in the long input data.}
+
+\item{outtime}{The name of the time variable in the wide output data.}
}
\value{
- Dataframe in wide format.
+Dataframe in wide format.
}
-\author{
- Johannes Ranke
+\description{
+This function takes a dataframe in the long form, i.e. with a row for each
+observed value, and converts it into a dataframe with one independent
+variable and several dependent variables as columns.
}
\examples{
+
mkin_long_to_wide(FOCUS_2006_D)
+
+}
+\author{
+Johannes Ranke
}
-\keyword{ manip }
diff --git a/man/mkin_wide_to_long.Rd b/man/mkin_wide_to_long.Rd
index dc523755..402911d7 100644
--- a/man/mkin_wide_to_long.Rd
+++ b/man/mkin_wide_to_long.Rd
@@ -1,32 +1,33 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/mkin_wide_to_long.R
\name{mkin_wide_to_long}
\alias{mkin_wide_to_long}
-\title{
- Convert a dataframe with observations over time into long format
-}
+\title{Convert a dataframe with observations over time into long format}
\usage{
mkin_wide_to_long(wide_data, time = "t")
}
-\description{
- This function simply takes a dataframe with one independent variable and several
- dependent variable and converts it into the long form as required by \code{\link{mkinfit}}.
-}
\arguments{
- \item{wide_data}{
- The dataframe must contain one variable with the time values specified by the
- \code{time} argument and usually more than one column of observed values.
-}
- \item{time}{
- The name of the time variable.
-}
+\item{wide_data}{The dataframe must contain one variable with the time
+values specified by the \code{time} argument and usually more than one
+column of observed values.}
+
+\item{time}{The name of the time variable.}
}
\value{
- Dataframe in long format as needed for \code{\link{mkinfit}}.
+Dataframe in long format as needed for \code{\link{mkinfit}}.
}
-\author{
- Johannes Ranke
+\description{
+This function simply takes a dataframe with one independent variable and
+several dependent variable and converts it into the long form as required by
+\code{\link{mkinfit}}.
}
\examples{
+
wide <- data.frame(t = c(1,2,3), x = c(1,4,7), y = c(3,4,5))
mkin_wide_to_long(wide)
+
+}
+\author{
+Johannes Ranke
}
-\keyword{ manip }
+\keyword{manip}
diff --git a/man/mkinds.Rd b/man/mkinds.Rd
index 239ab328..0ea562ed 100644
--- a/man/mkinds.Rd
+++ b/man/mkinds.Rd
@@ -1,3 +1,5 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/mkinds.R
\docType{class}
\name{mkinds}
\alias{mkinds}
@@ -11,24 +13,26 @@ A dataset class for mkin
}
\section{Fields}{
-\describe{
-\item{\code{title}}{A full title for the dataset}
-\item{\code{sampling}}{times The sampling times}
+\describe{ \item{list("title")}{A full title for the dataset}
-\item{\code{time_unit}}{The time unit}
+\item{list("sampling")}{times The sampling times}
-\item{\code{observed}}{Names of the observed compounds}
+\item{list("time_unit")}{The time unit}
-\item{\code{unit}}{The unit of the observations}
+\item{list("observed")}{Names of the observed compounds}
-\item{\code{replicates}}{The number of replicates}
+\item{list("unit")}{The unit of the observations}
+
+\item{list("replicates")}{The number of replicates}
+
+\item{list("data")}{A dataframe with at least the columns name, time and
+value in order to be compatible with mkinfit} }
+}
-\item{\code{data}}{A dataframe with at least the columns name, time and value
-in order to be compatible with mkinfit}
-}}
\examples{
+
mds <- mkinds$new("FOCUS A", FOCUS_2006_A)
+
}
\keyword{datasets}
-
diff --git a/man/mkinerrmin.Rd b/man/mkinerrmin.Rd
index 25aba7c0..be929130 100644
--- a/man/mkinerrmin.Rd
+++ b/man/mkinerrmin.Rd
@@ -1,54 +1,52 @@
-\name{mkinerrmin}
-\alias{mkinerrmin}
-\title{
-Calculate the minimum error to assume in order to pass the variance test
-}
-\description{
-This function finds the smallest relative error still resulting in passing the
-chi-squared test as defined in the FOCUS kinetics report from 2006.
-}
-\usage{
-mkinerrmin(fit, alpha = 0.05)
-}
-\arguments{
- \item{fit}{
- an object of class \code{\link{mkinfit}}.
- }
- \item{alpha}{
- The confidence level chosen for the chi-squared test.
-}
-}
-\value{
- A dataframe with the following components:
- \item{err.min}{The relative error, expressed as a fraction.}
- \item{n.optim}{The number of optimised parameters attributed to the data series.}
- \item{df}{The number of remaining degrees of freedom for the chi2 error level
- calculations. Note that mean values are used for the chi2 statistic and
- therefore every time point with observed values in the series only counts
- one time.}
- The dataframe has one row for the total dataset and one further row for
- each observed state variable in the model.
-}
-\details{
- This function is used internally by \code{\link{summary.mkinfit}}.
-}
-\examples{
-SFO_SFO = mkinmod(parent = mkinsub("SFO", to = "m1"),
- m1 = mkinsub("SFO"),
- use_of_ff = "max")
-
-fit_FOCUS_D = mkinfit(SFO_SFO, FOCUS_2006_D, quiet = TRUE)
-round(mkinerrmin(fit_FOCUS_D), 4)
-\dontrun{
- fit_FOCUS_E = mkinfit(SFO_SFO, FOCUS_2006_E, quiet = TRUE)
- round(mkinerrmin(fit_FOCUS_E), 4)
-}
-}
-\references{
- FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence and
- Degradation Kinetics from Environmental Fate Studies on Pesticides in EU
- Registration} Report of the FOCUS Work Group on Degradation Kinetics,
- EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
- \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
-}
-\keyword{ manip }
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/mkinerrmin.R
+\name{mkinerrmin}
+\alias{mkinerrmin}
+\title{Calculate the minimum error to assume in order to pass the variance test}
+\usage{
+mkinerrmin(fit, alpha = 0.05)
+}
+\arguments{
+\item{fit}{an object of class \code{\link{mkinfit}}.}
+
+\item{alpha}{The confidence level chosen for the chi-squared test.}
+}
+\value{
+A dataframe with the following components: \item{err.min}{The
+relative error, expressed as a fraction.} \item{n.optim}{The number of
+optimised parameters attributed to the data series.} \item{df}{The number of
+remaining degrees of freedom for the chi2 error level calculations. Note
+that mean values are used for the chi2 statistic and therefore every time
+point with observed values in the series only counts one time.} The
+dataframe has one row for the total dataset and one further row for each
+observed state variable in the model.
+}
+\description{
+This function finds the smallest relative error still resulting in passing
+the chi-squared test as defined in the FOCUS kinetics report from 2006.
+}
+\details{
+This function is used internally by \code{\link{summary.mkinfit}}.
+}
+\examples{
+
+SFO_SFO = mkinmod(parent = mkinsub("SFO", to = "m1"),
+ m1 = mkinsub("SFO"),
+ use_of_ff = "max")
+
+fit_FOCUS_D = mkinfit(SFO_SFO, FOCUS_2006_D, quiet = TRUE)
+round(mkinerrmin(fit_FOCUS_D), 4)
+\dontrun{
+ fit_FOCUS_E = mkinfit(SFO_SFO, FOCUS_2006_E, quiet = TRUE)
+ round(mkinerrmin(fit_FOCUS_E), 4)
+}
+
+}
+\references{
+FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence
+and Degradation Kinetics from Environmental Fate Studies on Pesticides in EU
+Registration} Report of the FOCUS Work Group on Degradation Kinetics, EC
+Document Reference Sanco/10058/2005 version 2.0, 434 pp,
+\url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+}
+\keyword{manip}
diff --git a/man/mkinerrplot.Rd b/man/mkinerrplot.Rd
index 37338d01..3c53e7f8 100644
--- a/man/mkinerrplot.Rd
+++ b/man/mkinerrplot.Rd
@@ -1,81 +1,69 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/mkinerrplot.R
\name{mkinerrplot}
\alias{mkinerrplot}
-\title{
- Function to plot squared residuals and the error model for an mkin object
-}
-\description{
- This function plots the squared residuals for the specified subset of the
- observed variables from an mkinfit object. In addition, one or more
- dashed line(s) show the fitted error model.
- A combined plot of the fitted model and this error model plot can be
- obtained with \code{\link{plot.mkinfit}}
- using the argument \code{show_errplot = TRUE}.
-}
+\title{Function to plot squared residuals and the error model for an mkin object}
\usage{
- mkinerrplot(object,
- obs_vars = names(object$mkinmod$map),
- xlim = c(0, 1.1 * max(object$data$predicted)),
- xlab = "Predicted", ylab = "Squared residual",
- maxy = "auto", legend= TRUE, lpos = "topright",
- col_obs = "auto", pch_obs = "auto",
- frame = TRUE,
- ...)
+mkinerrplot(object, obs_vars = names(object$mkinmod$map), xlim = c(0,
+ 1.1 * max(object$data$predicted)), xlab = "Predicted",
+ ylab = "Squared residual", maxy = "auto", legend = TRUE,
+ lpos = "topright", col_obs = "auto", pch_obs = "auto",
+ frame = TRUE, ...)
}
\arguments{
- \item{object}{
- A fit represented in an \code{\link{mkinfit}} object.
- }
- \item{obs_vars}{
- A character vector of names of the observed variables for which residuals
- should be plotted. Defaults to all observed variables in the model
- }
- \item{xlim}{
- plot range in x direction.
- }
- \item{xlab}{
- Label for the x axis.
- }
- \item{ylab}{
- Label for the y axis.
- }
- \item{maxy}{
- Maximum value of the residuals. This is used for the scaling of
- the y axis and defaults to "auto".
- }
- \item{legend}{
- Should a legend be plotted?
- }
- \item{lpos}{
- Where should the legend be placed? Default is "topright". Will be passed on to
- \code{\link{legend}}.
- }
- \item{col_obs}{
- Colors for the observed variables.
- }
- \item{pch_obs}{
- Symbols to be used for the observed variables.
- }
- \item{frame}{
- Should a frame be drawn around the plots?
- }
- \item{\dots}{
- further arguments passed to \code{\link{plot}}.
- }
+\item{object}{A fit represented in an \code{\link{mkinfit}} object.}
+
+\item{obs_vars}{A character vector of names of the observed variables for
+which residuals should be plotted. Defaults to all observed variables in
+the model}
+
+\item{xlim}{plot range in x direction.}
+
+\item{xlab}{Label for the x axis.}
+
+\item{ylab}{Label for the y axis.}
+
+\item{maxy}{Maximum value of the residuals. This is used for the scaling of
+the y axis and defaults to "auto".}
+
+\item{legend}{Should a legend be plotted?}
+
+\item{lpos}{Where should the legend be placed? Default is "topright". Will
+be passed on to \code{\link{legend}}.}
+
+\item{col_obs}{Colors for the observed variables.}
+
+\item{pch_obs}{Symbols to be used for the observed variables.}
+
+\item{frame}{Should a frame be drawn around the plots?}
+
+\item{\dots}{further arguments passed to \code{\link{plot}}.}
}
\value{
- Nothing is returned by this function, as it is called for its side effect, namely to produce a plot.
+Nothing is returned by this function, as it is called for its side
+ effect, namely to produce a plot.
}
-\author{
- Johannes Ranke
+\description{
+This function plots the squared residuals for the specified subset of the
+observed variables from an mkinfit object. In addition, one or more dashed
+line(s) show the fitted error model. A combined plot of the fitted model
+and this error model plot can be obtained with \code{\link{plot.mkinfit}}
+using the argument \code{show_errplot = TRUE}.
}
-\seealso{
- \code{\link{mkinplot}}, for a way to plot the data and the fitted lines of the
- mkinfit object. }
\examples{
+
\dontrun{
model <- mkinmod(parent = mkinsub("SFO", "m1"), m1 = mkinsub("SFO"))
fit <- mkinfit(model, FOCUS_2006_D, error_model = "tc", quiet = TRUE)
mkinerrplot(fit)
}
+
+}
+\seealso{
+\code{\link{mkinplot}}, for a way to plot the data and the fitted
+ lines of the mkinfit object.
+}
+\author{
+Johannes Ranke
}
-\keyword{ hplot }
+\keyword{hplot}
diff --git a/man/mkinfit.Rd b/man/mkinfit.Rd
index 09af4918..d9afb753 100644
--- a/man/mkinfit.Rd
+++ b/man/mkinfit.Rd
@@ -1,253 +1,214 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/mkinfit.R
\name{mkinfit}
\alias{mkinfit}
-\title{
- Fit a kinetic model to data with one or more state variables
-}
-\description{
- This function maximises the likelihood of the observed data using
- the Port algorithm \code{\link{nlminb}}, and the specified initial or fixed
- parameters and starting values. In each step of the optimsation, the kinetic
- model is solved using the function \code{\link{mkinpredict}}. The parameters
- of the selected error model are fitted simultaneously with the degradation
- model parameters, as both of them are arguments of the likelihood function.
-
- Per default, parameters in the kinetic models are internally transformed in
- order to better satisfy the assumption of a normal distribution of their
- estimators.
+\title{Fit a kinetic model to data with one or more state variables}
+\source{
+Rocke, David M. und Lorenzato, Stefan (1995) A two-component model
+ for measurement error in analytical chemistry. Technometrics 37(2), 176-184.
}
\usage{
-mkinfit(mkinmod, observed,
- parms.ini = "auto",
- state.ini = "auto",
- err.ini = "auto",
- fixed_parms = NULL, fixed_initials = names(mkinmod$diffs)[-1],
- from_max_mean = FALSE,
+mkinfit(mkinmod, observed, parms.ini = "auto", state.ini = "auto",
+ err.ini = "auto", fixed_parms = NULL,
+ fixed_initials = names(mkinmod$diffs)[-1], from_max_mean = FALSE,
solution_type = c("auto", "analytical", "eigen", "deSolve"),
- method.ode = "lsoda",
- use_compiled = "auto",
+ method.ode = "lsoda", use_compiled = "auto",
control = list(eval.max = 300, iter.max = 200),
- transform_rates = TRUE,
- transform_fractions = TRUE,
- quiet = FALSE,
- atol = 1e-8, rtol = 1e-10, n.outtimes = 100,
+ transform_rates = TRUE, transform_fractions = TRUE, quiet = FALSE,
+ atol = 1e-08, rtol = 1e-10, n.outtimes = 100,
error_model = c("const", "obs", "tc"),
- error_model_algorithm = c("auto", "d_3", "direct", "twostep", "threestep",
- "fourstep", "IRLS", "OLS"),
- reweight.tol = 1e-8, reweight.max.iter = 10,
- trace_parms = FALSE, ...)
+ error_model_algorithm = c("auto", "d_3", "direct", "twostep",
+ "threestep", "fourstep", "IRLS", "OLS"), reweight.tol = 1e-08,
+ reweight.max.iter = 10, trace_parms = FALSE, ...)
}
\arguments{
- \item{mkinmod}{
- A list of class \code{\link{mkinmod}}, containing the kinetic model to be
- fitted to the data, or one of the shorthand names ("SFO", "FOMC", "DFOP",
- "HS", "SFORB", "IORE"). If a shorthand name is given, a parent only degradation
- model is generated for the variable with the highest value in
- \code{observed}.
- }
- \item{observed}{
- A dataframe with the observed data. The first column called "name" must
- contain the name of the observed variable for each data point. The second
- column must contain the times of observation, named "time". The third
- column must be named "value" and contain the observed values. Zero values
- in the "value" column will be removed, with a warning, in order to
- avoid problems with fitting the two-component error model. This is not
- expected to be a problem, because in general, values of zero are not
- observed in degradation data, because there is a lower limit of detection.
- }
- \item{parms.ini}{
- A named vector of initial values for the parameters, including parameters
- to be optimised and potentially also fixed parameters as indicated by
- \code{fixed_parms}. If set to "auto", initial values for rate constants
- are set to default values. Using parameter names that are not in the model
- gives an error.
-
- It is possible to only specify a subset of the parameters that the model
- needs. You can use the parameter lists "bparms.ode" from a previously
- fitted model, which contains the differential equation parameters from this
- model. This works nicely if the models are nested. An example is given
- below.
- }
- \item{state.ini}{
- A named vector of initial values for the state variables of the model. In
- case the observed variables are represented by more than one model
- variable, the names will differ from the names of the observed variables
- (see \code{map} component of \code{\link{mkinmod}}). The default is to set
- the initial value of the first model variable to the mean of the time zero
- values for the variable with the maximum observed value, and all others to 0.
- If this variable has no time zero observations, its initial value is set to 100.
- }
- \item{err.ini}{
- A named vector of initial values for the error model parameters to be
- optimised. If set to "auto", initial values are set to default values.
- Otherwise, inital values for all error model parameters must be
- given.
- }
- \item{fixed_parms}{
- The names of parameters that should not be optimised but rather kept at the
- values specified in \code{parms.ini}.
- }
- \item{fixed_initials}{
- The names of model variables for which the initial state at time 0 should
- be excluded from the optimisation. Defaults to all state variables except
- for the first one.
- }
- \item{from_max_mean}{
- If this is set to TRUE, and the model has only one observed variable, then
- data before the time of the maximum observed value (after averaging for each
- sampling time) are discarded, and this time is subtracted from all
- remaining time values, so the time of the maximum observed mean value is
- the new time zero.
- }
- \item{solution_type}{
- If set to "eigen", the solution of the system of differential equations is
- based on the spectral decomposition of the coefficient matrix in cases that
- this is possible. If set to "deSolve", a numerical ode solver from package
- \code{\link{deSolve}} is used. If set to "analytical", an analytical
- solution of the model is used. This is only implemented for simple
- degradation experiments with only one state variable, i.e. with no
- metabolites. The default is "auto", which uses "analytical" if possible,
- otherwise "deSolve" if a compiler is present, and "eigen" if no
- compiler is present and the model can be expressed using eigenvalues and
- eigenvectors. This argument is passed on to the helper function
- \code{\link{mkinpredict}}.
- }
- \item{method.ode}{
- The solution method passed via \code{\link{mkinpredict}} to
- \code{\link{ode}} in case the solution type is "deSolve". The default
- "lsoda" is performant, but sometimes fails to converge.
- }
- \item{use_compiled}{
- If set to \code{FALSE}, no compiled version of the \code{\link{mkinmod}}
- model is used in the calls to \code{\link{mkinpredict}} even if a compiled
- version is present.
- }
- \item{control}{
- A list of control arguments passed to \code{\link{nlminb}}.
- }
- \item{transform_rates}{
- Boolean specifying if kinetic rate constants should be transformed in the
- model specification used in the fitting for better compliance with the
- assumption of normal distribution of the estimator. If TRUE, also
- alpha and beta parameters of the FOMC model are log-transformed, as well
- as k1 and k2 rate constants for the DFOP and HS models and the break point
- tb of the HS model. If FALSE, zero is used as a lower bound for the rates
- in the optimisation.
- }
- \item{transform_fractions}{
- Boolean specifying if formation fractions constants should be transformed in the
- model specification used in the fitting for better compliance with the
- assumption of normal distribution of the estimator. The default (TRUE) is
- to do transformations. If TRUE, the g parameter of the DFOP and HS
- models are also transformed, as they can also be seen as compositional
- data. The transformation used for these transformations is the
- \code{\link{ilr}} transformation.
- }
- \item{quiet}{
- Suppress printing out the current value of the negative log-likelihood
- after each improvement?
- }
- \item{atol}{
- Absolute error tolerance, passed to \code{\link{ode}}. Default is 1e-8,
- lower than in \code{\link{lsoda}}.
- }
- \item{rtol}{
- Absolute error tolerance, passed to \code{\link{ode}}. Default is 1e-10,
- much lower than in \code{\link{lsoda}}.
- }
- \item{n.outtimes}{
- The length of the dataseries that is produced by the model prediction
- function \code{\link{mkinpredict}}. This impacts the accuracy of
- the numerical solver if that is used (see \code{solution_type} argument.
- The default value is 100.
- }
- \item{error_model}{
- If the error model is "const", a constant standard deviation
- is assumed.
-
- If the error model is "obs", each observed variable is assumed to have its
- own variance.
-
- If the error model is "tc" (two-component error model), a two component
- error model similar to the one described by Rocke and Lorenzato (1995) is
- used for setting up the likelihood function. Note that this model deviates
- from the model by Rocke and Lorenzato, as their model implies that the
- errors follow a lognormal distribution for large values, not a normal
- distribution as assumed by this method.
- }
- \item{error_model_algorithm}{
- If "auto", the selected algorithm depends on the error model.
- If the error model is "const", unweighted nonlinear least squares fitting
- ("OLS") is selected. If the error model is "obs", or "tc", the "d_3"
- algorithm is selected.
-
- The algorithm "d_3" will directly minimize the negative
- log-likelihood and - independently - also use the three step algorithm
- described below. The fit with the higher likelihood is returned.
-
- The algorithm "direct" will directly minimize the negative
- log-likelihood.
-
- The algorithm "twostep" will minimize the negative log-likelihood
- after an initial unweighted least squares optimisation step.
-
- The algorithm "threestep" starts with unweighted least squares,
- then optimizes only the error model using the degradation model
- parameters found, and then minimizes the negative log-likelihood
- with free degradation and error model parameters.
-
- The algorithm "fourstep" starts with unweighted least squares,
- then optimizes only the error model using the degradation model
- parameters found, then optimizes the degradation model again
- with fixed error model parameters, and finally minimizes the negative
- log-likelihood with free degradation and error model parameters.
-
- The algorithm "IRLS" (Iteratively Reweighted Least Squares) starts with
- unweighted least squares, and then iterates optimization of the error model
- parameters and subsequent
- optimization of the degradation model using those error model parameters,
- until the error model parameters converge.
- }
- \item{reweight.tol}{
- Tolerance for the convergence criterion calculated from the error model
- parameters in IRLS fits.
- }
- \item{reweight.max.iter}{
- Maximum number of iterations in IRLS fits.
- }
- \item{trace_parms}{
- Should a trace of the parameter values be listed?
- }
- \item{\dots}{
- Further arguments that will be passed on to \code{\link{deSolve}}.
- }
+\item{mkinmod}{A list of class \code{\link{mkinmod}}, containing the kinetic
+model to be fitted to the data, or one of the shorthand names ("SFO",
+"FOMC", "DFOP", "HS", "SFORB", "IORE"). If a shorthand name is given, a
+parent only degradation model is generated for the variable with the
+highest value in \code{observed}.}
+
+\item{observed}{A dataframe with the observed data. The first column called
+"name" must contain the name of the observed variable for each data point.
+The second column must contain the times of observation, named "time".
+The third column must be named "value" and contain the observed values.
+Zero values in the "value" column will be removed, with a warning, in
+order to avoid problems with fitting the two-component error model. This
+is not expected to be a problem, because in general, values of zero are
+not observed in degradation data, because there is a lower limit of
+detection.}
+
+\item{parms.ini}{A named vector of initial values for the parameters,
+ including parameters to be optimised and potentially also fixed parameters
+ as indicated by \code{fixed_parms}. If set to "auto", initial values for
+ rate constants are set to default values. Using parameter names that are
+ not in the model gives an error.
+
+ It is possible to only specify a subset of the parameters that the model
+ needs. You can use the parameter lists "bparms.ode" from a previously
+ fitted model, which contains the differential equation parameters from
+ this model. This works nicely if the models are nested. An example is
+ given below.}
+
+\item{state.ini}{A named vector of initial values for the state variables of
+the model. In case the observed variables are represented by more than one
+model variable, the names will differ from the names of the observed
+variables (see \code{map} component of \code{\link{mkinmod}}). The default
+is to set the initial value of the first model variable to the mean of the
+time zero values for the variable with the maximum observed value, and all
+others to 0. If this variable has no time zero observations, its initial
+value is set to 100.}
+
+\item{err.ini}{A named vector of initial values for the error model
+parameters to be optimised. If set to "auto", initial values are set to
+default values. Otherwise, inital values for all error model parameters
+must be given.}
+
+\item{fixed_parms}{The names of parameters that should not be optimised but
+rather kept at the values specified in \code{parms.ini}.}
+
+\item{fixed_initials}{The names of model variables for which the initial
+state at time 0 should be excluded from the optimisation. Defaults to all
+state variables except for the first one.}
+
+\item{from_max_mean}{If this is set to TRUE, and the model has only one
+observed variable, then data before the time of the maximum observed value
+(after averaging for each sampling time) are discarded, and this time is
+subtracted from all remaining time values, so the time of the maximum
+observed mean value is the new time zero.}
+
+\item{solution_type}{If set to "eigen", the solution of the system of
+differential equations is based on the spectral decomposition of the
+coefficient matrix in cases that this is possible. If set to "deSolve", a
+numerical ode solver from package \code{\link{deSolve}} is used. If set to
+"analytical", an analytical solution of the model is used. This is only
+implemented for simple degradation experiments with only one state
+variable, i.e. with no metabolites. The default is "auto", which uses
+"analytical" if possible, otherwise "deSolve" if a compiler is present,
+and "eigen" if no compiler is present and the model can be expressed using
+eigenvalues and eigenvectors. This argument is passed on to the helper
+function \code{\link{mkinpredict}}.}
+
+\item{method.ode}{The solution method passed via \code{\link{mkinpredict}}
+to \code{\link{ode}} in case the solution type is "deSolve". The default
+"lsoda" is performant, but sometimes fails to converge.}
+
+\item{use_compiled}{If set to \code{FALSE}, no compiled version of the
+\code{\link{mkinmod}} model is used in the calls to
+\code{\link{mkinpredict}} even if a compiled version is present.}
+
+\item{control}{A list of control arguments passed to \code{\link{nlminb}}.}
+
+\item{transform_rates}{Boolean specifying if kinetic rate constants should
+be transformed in the model specification used in the fitting for better
+compliance with the assumption of normal distribution of the estimator. If
+TRUE, also alpha and beta parameters of the FOMC model are
+log-transformed, as well as k1 and k2 rate constants for the DFOP and HS
+models and the break point tb of the HS model. If FALSE, zero is used as
+a lower bound for the rates in the optimisation.}
+
+\item{transform_fractions}{Boolean specifying if formation fractions
+constants should be transformed in the model specification used in the
+fitting for better compliance with the assumption of normal distribution
+of the estimator. The default (TRUE) is to do transformations. If TRUE,
+the g parameter of the DFOP and HS models are also transformed, as they
+can also be seen as compositional data. The transformation used for these
+transformations is the \code{\link{ilr}} transformation.}
+
+\item{quiet}{Suppress printing out the current value of the negative
+log-likelihood after each improvement?}
+
+\item{atol}{Absolute error tolerance, passed to \code{\link{ode}}. Default
+is 1e-8, lower than in \code{\link{lsoda}}.}
+
+\item{rtol}{Absolute error tolerance, passed to \code{\link{ode}}. Default
+is 1e-10, much lower than in \code{\link{lsoda}}.}
+
+\item{n.outtimes}{The length of the dataseries that is produced by the model
+prediction function \code{\link{mkinpredict}}. This impacts the accuracy
+of the numerical solver if that is used (see \code{solution_type}
+argument. The default value is 100.}
+
+\item{error_model}{If the error model is "const", a constant standard
+ deviation is assumed.
+
+ If the error model is "obs", each observed variable is assumed to have its
+ own variance.
+
+ If the error model is "tc" (two-component error model), a two component
+ error model similar to the one described by Rocke and Lorenzato (1995) is
+ used for setting up the likelihood function. Note that this model
+ deviates from the model by Rocke and Lorenzato, as their model implies
+ that the errors follow a lognormal distribution for large values, not a
+ normal distribution as assumed by this method.}
+
+\item{error_model_algorithm}{If "auto", the selected algorithm depends on
+ the error model. If the error model is "const", unweighted nonlinear
+ least squares fitting ("OLS") is selected. If the error model is "obs", or
+ "tc", the "d_3" algorithm is selected.
+
+ The algorithm "d_3" will directly minimize the negative log-likelihood and
+ - independently - also use the three step algorithm described below. The
+ fit with the higher likelihood is returned.
+
+ The algorithm "direct" will directly minimize the negative log-likelihood.
+
+ The algorithm "twostep" will minimize the negative log-likelihood after an
+ initial unweighted least squares optimisation step.
+
+ The algorithm "threestep" starts with unweighted least squares, then
+ optimizes only the error model using the degradation model parameters
+ found, and then minimizes the negative log-likelihood with free
+ degradation and error model parameters.
+
+ The algorithm "fourstep" starts with unweighted least squares, then
+ optimizes only the error model using the degradation model parameters
+ found, then optimizes the degradation model again with fixed error model
+ parameters, and finally minimizes the negative log-likelihood with free
+ degradation and error model parameters.
+
+ The algorithm "IRLS" (Iteratively Reweighted Least Squares) starts with
+ unweighted least squares, and then iterates optimization of the error
+ model parameters and subsequent optimization of the degradation model
+ using those error model parameters, until the error model parameters
+ converge.}
+
+\item{reweight.tol}{Tolerance for the convergence criterion calculated from
+the error model parameters in IRLS fits.}
+
+\item{reweight.max.iter}{Maximum number of iterations in IRLS fits.}
+
+\item{trace_parms}{Should a trace of the parameter values be listed?}
+
+\item{\dots}{Further arguments that will be passed on to
+\code{\link{deSolve}}.}
}
\value{
- A list with "mkinfit" in the class attribute. A summary can be obtained by
- \code{\link{summary.mkinfit}}.
+A list with "mkinfit" in the class attribute. A summary can be
+ obtained by \code{\link{summary.mkinfit}}.
}
-\seealso{
- Plotting methods \code{\link{plot.mkinfit}} and \code{\link{mkinparplot}}.
-
- Comparisons of models fitted to the same data can be made using \code{\link{AIC}}
- by virtue of the method \code{\link{logLik.mkinfit}}.
-
- Fitting of several models to several datasets in a single call to
- \code{\link{mmkin}}.
+\description{
+This function maximises the likelihood of the observed data using the Port
+algorithm \code{\link{nlminb}}, and the specified initial or fixed
+parameters and starting values. In each step of the optimsation, the
+kinetic model is solved using the function \code{\link{mkinpredict}}. The
+parameters of the selected error model are fitted simultaneously with the
+degradation model parameters, as both of them are arguments of the
+likelihood function.
+}
+\details{
+Per default, parameters in the kinetic models are internally transformed in
+order to better satisfy the assumption of a normal distribution of their
+estimators.
}
\note{
- When using the "IORE" submodel for metabolites, fitting with
+When using the "IORE" submodel for metabolites, fitting with
"transform_rates = TRUE" (the default) often leads to failures of the
numerical ODE solver. In this situation it may help to switch off the
internal rate transformation.
}
-\source{
- Rocke, David M. und Lorenzato, Stefan (1995) A two-component model for
- measurement error in analytical chemistry. Technometrics 37(2), 176-184.
-}
-\author{
- Johannes Ranke
-}
\examples{
+
# Use shorthand notation for parent only degradation
fit <- mkinfit("FOMC", FOCUS_2006_C, quiet = TRUE)
summary(fit)
@@ -307,5 +268,18 @@ f.tc <- mkinfit(SFO_SFO.ff, FOCUS_2006_D, error_model = "tc", quiet = TRUE)
summary(f.tc)
}
+
+}
+\seealso{
+Plotting methods \code{\link{plot.mkinfit}} and
+ \code{\link{mkinparplot}}.
+
+ Comparisons of models fitted to the same data can be made using
+ \code{\link{AIC}} by virtue of the method \code{\link{logLik.mkinfit}}.
+
+ Fitting of several models to several datasets in a single call to
+ \code{\link{mmkin}}.
+}
+\author{
+Johannes Ranke
}
-\keyword{ optimize }
diff --git a/man/mkinmod.Rd b/man/mkinmod.Rd
index 62b02775..91f285e2 100644
--- a/man/mkinmod.Rd
+++ b/man/mkinmod.Rd
@@ -1,115 +1,123 @@
-\name{mkinmod}
-\alias{mkinmod}
-\title{
- Function to set up a kinetic model with one or more state variables
-}
-\description{
- The function usually takes several expressions, each assigning a compound name to
- a list, specifying the kinetic model type and reaction or transfer to other
- observed compartments. Instead of specifying several expressions, a list
- of lists can be given in the speclist argument.
-
- For the definition of model types and their parameters, the equations given
- in the FOCUS and NAFTA guidance documents are used.
-}
-\usage{
-mkinmod(..., use_of_ff = "min", speclist = NULL, quiet = FALSE, verbose = FALSE)
-}
-\arguments{
- \item{...}{
- For each observed variable, a list has to be specified as an argument, containing
- at least a component \code{type}, specifying the type of kinetics to use
- for the variable. Currently, single first order kinetics "SFO",
- indeterminate order rate equation kinetics "IORE", or
- single first order with reversible binding "SFORB" are implemented for all
- variables, while
- "FOMC", "DFOP" and "HS" can additionally be chosen for the first
- variable which is assumed to be the source compartment.
- Additionally, each component of the list can include a character vector \code{to},
- specifying names of variables to which a transfer is to be assumed in the
- model.
- If the argument \code{use_of_ff} is set to "min" (default) and the model for
- the compartment is "SFO" or "SFORB", an additional component of the list
- can be "sink=FALSE" effectively fixing the flux to sink to zero.
- }
- \item{use_of_ff}{
- Specification of the use of formation fractions in the model equations and, if
- applicable, the coefficient matrix. If "min", a minimum use of formation
- fractions is made in order to avoid fitting the product of formation fractions
- and rate constants. If "max", formation fractions are always used.
- }
- \item{speclist}{
- The specification of the observed variables and their submodel types and
- pathways can be given as a single list using this argument. Default is NULL.
- }
- \item{quiet}{
- Should messages be suppressed?
- }
- \item{verbose}{
- If \code{TRUE}, passed to \code{\link{cfunction}} if applicable to give
- detailed information about the C function being built.
- }
-}
-\value{
- A list of class \code{mkinmod} for use with \code{\link{mkinfit}}, containing
- \item{diffs}{ A vector of string representations of differential equations,
- one for each modelling variable. }
- \item{parms}{ A vector of parameter names occurring in the differential equations. }
- \item{map}{ A list containing named character vectors for each observed variable, specifying
- the modelling variables by which it is represented. }
- \item{use_of_ff}{ The content of \code{use_of_ff} is passed on in this list component. }
- \item{coefmat}{ The coefficient matrix, if the system of differential equations can be
- represented by one. }
-}
-\note{
- The IORE submodel is not well tested (yet). When using this model for metabolites,
- you may want to read the second note in the help page to
- \code{\link{mkinfit}}.
-}
-\references{
- FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence and
- Degradation Kinetics from Environmental Fate Studies on Pesticides in EU
- Registration} Report of the FOCUS Work Group on Degradation Kinetics,
- EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
- \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
-
- NAFTA Technical Working Group on Pesticides (not dated) Guidance for
- Evaluating and Calculating Degradation Kinetics in Environmental
- Media
-}
-\author{
- Johannes Ranke
-}
-\examples{
-# Specify the SFO model (this is not needed any more, as we can now mkinfit("SFO", ...)
-SFO <- mkinmod(parent = list(type = "SFO"))
-
-# One parent compound, one metabolite, both single first order
-SFO_SFO <- mkinmod(
- parent = mkinsub("SFO", "m1"),
- m1 = mkinsub("SFO"))
-
-\dontrun{
-# The above model used to be specified like this, before the advent of mkinsub()
-SFO_SFO <- mkinmod(
- parent = list(type = "SFO", to = "m1"),
- m1 = list(type = "SFO"))
-
-# Show details of creating the C function
-SFO_SFO <- mkinmod(
- parent = mkinsub("SFO", "m1"),
- m1 = mkinsub("SFO"), verbose = TRUE)
-
-# If we have several parallel metabolites
-# (compare tests/testthat/test_synthetic_data_for_UBA_2014.R)
-m_synth_DFOP_par <- mkinmod(parent = mkinsub("DFOP", c("M1", "M2")),
- M1 = mkinsub("SFO"),
- M2 = mkinsub("SFO"),
- use_of_ff = "max", quiet = TRUE)
-
-fit_DFOP_par_c <- mkinfit(m_synth_DFOP_par,
- synthetic_data_for_UBA_2014[[12]]$data,
- quiet = TRUE)
-}
-}
-\keyword{ models }
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/mkinmod.R
+\name{mkinmod}
+\alias{mkinmod}
+\title{Function to set up a kinetic model with one or more state variables}
+\usage{
+mkinmod(..., use_of_ff = "min", speclist = NULL, quiet = FALSE,
+ verbose = FALSE)
+}
+\arguments{
+\item{...}{For each observed variable, a list has to be specified as an
+argument, containing at least a component \code{type}, specifying the type
+of kinetics to use for the variable. Currently, single first order
+kinetics "SFO", indeterminate order rate equation kinetics "IORE", or
+single first order with reversible binding "SFORB" are implemented for all
+variables, while "FOMC", "DFOP" and "HS" can additionally be chosen for
+the first variable which is assumed to be the source compartment.
+Additionally, each component of the list can include a character vector
+\code{to}, specifying names of variables to which a transfer is to be
+assumed in the model. If the argument \code{use_of_ff} is set to "min"
+(default) and the model for the compartment is "SFO" or "SFORB", an
+additional component of the list can be "sink=FALSE" effectively fixing
+the flux to sink to zero.}
+
+\item{use_of_ff}{Specification of the use of formation fractions in the
+model equations and, if applicable, the coefficient matrix. If "min", a
+minimum use of formation fractions is made in order to avoid fitting the
+product of formation fractions and rate constants. If "max", formation
+fractions are always used.}
+
+\item{speclist}{The specification of the observed variables and their
+submodel types and pathways can be given as a single list using this
+argument. Default is NULL.}
+
+\item{quiet}{Should messages be suppressed?}
+
+\item{verbose}{If \code{TRUE}, passed to \code{\link{cfunction}} if
+applicable to give detailed information about the C function being built.}
+}
+\value{
+A list of class \code{mkinmod} for use with \code{\link{mkinfit}},
+ containing, among others,
+ \item{diffs}{
+ A vector of string representations of differential equations, one for
+ each modelling variable.
+ }
+ \item{map}{
+ A list containing named character vectors for each observed variable,
+ specifying the modelling variables by which it is represented.
+ }
+ \item{use_of_ff}{
+ The content of \code{use_of_ff} is passed on in this list component.
+ }
+ \item{coefmat}{
+ The coefficient matrix, if the system of differential equations can be
+ represented by one.
+ }
+ \item{ll}{
+ The likelihood function, taking the parameter vector as the first argument.
+ }
+}
+\description{
+The function usually takes several expressions, each assigning a compound
+name to a list, specifying the kinetic model type and reaction or transfer
+to other observed compartments. Instead of specifying several expressions, a
+list of lists can be given in the speclist argument.
+}
+\details{
+For the definition of model types and their parameters, the equations given
+in the FOCUS and NAFTA guidance documents are used.
+}
+\note{
+The IORE submodel is not well tested for metabolites. When using this
+ model for metabolites, you may want to read the second note in the help
+ page to \code{\link{mkinfit}}.
+}
+\examples{
+
+# Specify the SFO model (this is not needed any more, as we can now mkinfit("SFO", ...)
+SFO <- mkinmod(parent = list(type = "SFO"))
+
+# One parent compound, one metabolite, both single first order
+SFO_SFO <- mkinmod(
+ parent = mkinsub("SFO", "m1"),
+ m1 = mkinsub("SFO"))
+
+\dontrun{
+# The above model used to be specified like this, before the advent of mkinsub()
+SFO_SFO <- mkinmod(
+ parent = list(type = "SFO", to = "m1"),
+ m1 = list(type = "SFO"))
+
+# Show details of creating the C function
+SFO_SFO <- mkinmod(
+ parent = mkinsub("SFO", "m1"),
+ m1 = mkinsub("SFO"), verbose = TRUE)
+
+# If we have several parallel metabolites
+# (compare tests/testthat/test_synthetic_data_for_UBA_2014.R)
+m_synth_DFOP_par <- mkinmod(parent = mkinsub("DFOP", c("M1", "M2")),
+ M1 = mkinsub("SFO"),
+ M2 = mkinsub("SFO"),
+ use_of_ff = "max", quiet = TRUE)
+
+fit_DFOP_par_c <- mkinfit(m_synth_DFOP_par,
+ synthetic_data_for_UBA_2014[[12]]$data,
+ quiet = TRUE)
+}
+
+}
+\references{
+FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence
+ and Degradation Kinetics from Environmental Fate Studies on Pesticides in
+ EU Registration} Report of the FOCUS Work Group on Degradation Kinetics,
+ EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
+ \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+
+ NAFTA Technical Working Group on Pesticides (not dated) Guidance for
+ Evaluating and Calculating Degradation Kinetics in Environmental Media
+}
+\author{
+Johannes Ranke
+}
diff --git a/man/mkinparplot.Rd b/man/mkinparplot.Rd
index a880151d..975a0203 100644
--- a/man/mkinparplot.Rd
+++ b/man/mkinparplot.Rd
@@ -1,34 +1,33 @@
-\name{mkinparplot}
-\alias{mkinparplot}
-\title{
- Function to plot the confidence intervals obtained using mkinfit
-}
-\description{
- This function plots the confidence intervals for the parameters
- fitted using \code{\link{mkinfit}}.
-}
-\usage{
- mkinparplot(object)
-}
-\arguments{
- \item{object}{
- A fit represented in an \code{\link{mkinfit}} object.
- }
-}
-\value{
- Nothing is returned by this function, as it is called for its side effect, namely to produce a plot.
-}
-\author{
- Johannes Ranke
-}
-
-\examples{
-\dontrun{
-model <- mkinmod(
- T245 = mkinsub("SFO", to = c("phenol"), sink = FALSE),
- phenol = mkinsub("SFO", to = c("anisole")),
- anisole = mkinsub("SFO"), use_of_ff = "max")
-fit <- mkinfit(model, subset(mccall81_245T, soil == "Commerce"), quiet = TRUE)
-mkinparplot(fit)
-}}
-\keyword{ hplot }
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/mkinparplot.R
+\name{mkinparplot}
+\alias{mkinparplot}
+\title{Function to plot the confidence intervals obtained using mkinfit}
+\usage{
+mkinparplot(object)
+}
+\arguments{
+\item{object}{A fit represented in an \code{\link{mkinfit}} object.}
+}
+\value{
+Nothing is returned by this function, as it is called for its side
+ effect, namely to produce a plot.
+}
+\description{
+This function plots the confidence intervals for the parameters fitted using
+\code{\link{mkinfit}}.
+}
+\examples{
+
+\dontrun{
+model <- mkinmod(
+ T245 = mkinsub("SFO", to = c("phenol"), sink = FALSE),
+ phenol = mkinsub("SFO", to = c("anisole")),
+ anisole = mkinsub("SFO"), use_of_ff = "max")
+fit <- mkinfit(model, subset(mccall81_245T, soil == "Commerce"), quiet = TRUE)
+mkinparplot(fit)
+}
+}
+\author{
+Johannes Ranke
+}
diff --git a/man/mkinplot.Rd b/man/mkinplot.Rd
index 50654004..3eade395 100644
--- a/man/mkinplot.Rd
+++ b/man/mkinplot.Rd
@@ -1,25 +1,23 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/plot.mkinfit.R
\name{mkinplot}
\alias{mkinplot}
-\title{
- Plot the observed data and the fitted model of an mkinfit object
-}
-\description{
- Deprecated function. It now only calls the plot method \code{\link{plot.mkinfit}}.
-}
+\title{Plot the observed data and the fitted model of an mkinfit object}
\usage{
- mkinplot(fit, ...)
+mkinplot(fit, ...)
}
\arguments{
- \item{fit}{
- an object of class \code{\link{mkinfit}}.
- }
- \item{\dots}{
- further arguments passed to \code{\link{plot.mkinfit}}.
-}
+\item{fit}{an object of class \code{\link{mkinfit}}.}
+
+\item{\dots}{further arguments passed to \code{\link{plot.mkinfit}}.}
}
\value{
- The function is called for its side effect.
+The function is called for its side effect.
+}
+\description{
+Deprecated function. It now only calls the plot method
+\code{\link{plot.mkinfit}}.
}
\author{
- Johannes Ranke
+Johannes Ranke
}
diff --git a/man/mkinpredict.Rd b/man/mkinpredict.Rd
index 24b918dc..53f02dea 100644
--- a/man/mkinpredict.Rd
+++ b/man/mkinpredict.Rd
@@ -1,78 +1,80 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/mkinpredict.R
\name{mkinpredict}
\alias{mkinpredict}
\alias{mkinpredict.mkinmod}
\alias{mkinpredict.mkinfit}
-\title{
- Produce predictions from a kinetic model using specific parameters
-}
-\description{
- This function produces a time series for all the observed variables in a
- kinetic model as specified by \code{\link{mkinmod}}, using a specific set of
- kinetic parameters and initial values for the state variables.
-}
+\title{Produce predictions from a kinetic model using specific parameters}
\usage{
- mkinpredict(x, odeparms, odeini, outtimes = seq(0, 120, by = 0.1),
- solution_type = "deSolve", use_compiled = "auto", method.ode = "lsoda",
- atol = 1e-08, rtol = 1e-10, map_output = TRUE, ...)
+mkinpredict(x, odeparms, odeini, outtimes = seq(0, 120, by = 0.1),
+ solution_type = "deSolve", use_compiled = "auto",
+ method.ode = "lsoda", atol = 1e-08, rtol = 1e-10,
+ map_output = TRUE, ...)
+
+\method{mkinpredict}{mkinmod}(x, odeparms = c(k_parent_sink = 0.1),
+ odeini = c(parent = 100), outtimes = seq(0, 120, by = 0.1),
+ solution_type = "deSolve", use_compiled = "auto",
+ method.ode = "lsoda", atol = 1e-08, rtol = 1e-10,
+ map_output = TRUE, ...)
+
+\method{mkinpredict}{mkinfit}(x, odeparms = x$bparms.ode,
+ odeini = x$bparms.state, outtimes = seq(0, 120, by = 0.1),
+ solution_type = "deSolve", use_compiled = "auto",
+ method.ode = "lsoda", atol = 1e-08, rtol = 1e-10,
+ map_output = TRUE, ...)
}
\arguments{
- \item{x}{
- A kinetic model as produced by \code{\link{mkinmod}}, or a kinetic
- fit as fitted by \code{\link{mkinfit}}. In the latter case, the fitted
- parameters are used for the prediction.
- }
- \item{odeparms}{
- A numeric vector specifying the parameters used in the kinetic model, which
- is generally defined as a set of ordinary differential equations.
- }
- \item{odeini}{
- A numeric vectory containing the initial values of the state variables of
- the model. Note that the state variables can differ from the observed
- variables, for example in the case of the SFORB model.
- }
- \item{outtimes}{
- A numeric vector specifying the time points for which model predictions
- should be generated.
- }
- \item{solution_type}{
- The method that should be used for producing the predictions. This should
- generally be "analytical" if there is only one observed variable, and
- usually "deSolve" in the case of several observed variables. The third
- possibility "eigen" is faster but not applicable to some models e.g.
- using FOMC for the parent compound.
- }
- \item{method.ode}{
- The solution method passed via \code{\link{mkinpredict}} to
- \code{\link{ode}} in case the solution type is "deSolve". The default
- "lsoda" is performant, but sometimes fails to converge.
- }
- \item{use_compiled}{
- If set to \code{FALSE}, no compiled version of the \code{\link{mkinmod}}
- model is used, even if is present.
- }
- \item{atol}{
- Absolute error tolerance, passed to \code{\link{ode}}. Default is 1e-8,
- lower than in \code{\link{lsoda}}.
- }
- \item{rtol}{
- Absolute error tolerance, passed to \code{\link{ode}}. Default is 1e-10,
- much lower than in \code{\link{lsoda}}.
- }
- \item{map_output}{
- Boolean to specify if the output should list values for the observed
- variables (default) or for all state variables (if set to FALSE).
- }
- \item{\dots}{
- Further arguments passed to the ode solver in case such a solver is used.
- }
+\item{x}{A kinetic model as produced by \code{\link{mkinmod}}, or a kinetic
+fit as fitted by \code{\link{mkinfit}}. In the latter case, the fitted
+parameters are used for the prediction.}
+
+\item{odeparms}{A numeric vector specifying the parameters used in the
+kinetic model, which is generally defined as a set of ordinary
+differential equations.}
+
+\item{odeini}{A numeric vectory containing the initial values of the state
+variables of the model. Note that the state variables can differ from the
+observed variables, for example in the case of the SFORB model.}
+
+\item{outtimes}{A numeric vector specifying the time points for which model
+predictions should be generated.}
+
+\item{solution_type}{The method that should be used for producing the
+predictions. This should generally be "analytical" if there is only one
+observed variable, and usually "deSolve" in the case of several observed
+variables. The third possibility "eigen" is faster but not applicable to
+some models e.g. using FOMC for the parent compound.}
+
+\item{use_compiled}{If set to \code{FALSE}, no compiled version of the
+\code{\link{mkinmod}} model is used, even if is present.}
+
+\item{method.ode}{The solution method passed via \code{\link{mkinpredict}}
+to \code{\link{ode}} in case the solution type is "deSolve". The default
+"lsoda" is performant, but sometimes fails to converge.}
+
+\item{atol}{Absolute error tolerance, passed to \code{\link{ode}}. Default
+is 1e-8, lower than in \code{\link{lsoda}}.}
+
+\item{rtol}{Absolute error tolerance, passed to \code{\link{ode}}. Default
+is 1e-10, much lower than in \code{\link{lsoda}}.}
+
+\item{map_output}{Boolean to specify if the output should list values for
+the observed variables (default) or for all state variables (if set to
+FALSE).}
+
+\item{\dots}{Further arguments passed to the ode solver in case such a
+solver is used.}
}
\value{
- A matrix in the same format as the output of \code{\link{ode}}.
+A matrix in the same format as the output of \code{\link{ode}}.
}
-\author{
- Johannes Ranke
+\description{
+This function produces a time series for all the observed variables in a
+kinetic model as specified by \code{\link{mkinmod}}, using a specific set of
+kinetic parameters and initial values for the state variables.
}
\examples{
+
SFO <- mkinmod(degradinol = mkinsub("SFO"))
# Compare solution types
mkinpredict(SFO, c(k_degradinol_sink = 0.3), c(degradinol = 100), 0:20,
@@ -124,5 +126,8 @@
f <- mkinfit(SFO_SFO, FOCUS_2006_C)
head(mkinpredict(f))
}
+
+}
+\author{
+Johannes Ranke
}
-\keyword{ manip }
diff --git a/man/mkinresplot.Rd b/man/mkinresplot.Rd
index e788d836..27e1322f 100644
--- a/man/mkinresplot.Rd
+++ b/man/mkinresplot.Rd
@@ -1,76 +1,65 @@
-\name{mkinresplot}
-\alias{mkinresplot}
-\title{
- Function to plot residuals stored in an mkin object
-}
-\description{
- This function plots the residuals for the specified subset of the
- observed variables from an mkinfit object. A combined plot of the fitted
- model and the residuals can be obtained using \code{\link{plot.mkinfit}}
- using the argument \code{show_residuals = TRUE}.
-}
-\usage{
- mkinresplot(object,
- obs_vars = names(object$mkinmod$map),
- xlim = c(0, 1.1 * max(object$data$time)),
- xlab = "Time", ylab = "Residual",
- maxabs = "auto", legend = TRUE, lpos = "topright",
- col_obs = "auto", pch_obs = "auto",
- frame = TRUE,
- ...)
-}
-\arguments{
- \item{object}{
- A fit represented in an \code{\link{mkinfit}} object.
- }
- \item{obs_vars}{
- A character vector of names of the observed variables for which residuals
- should be plotted. Defaults to all observed variables in the model
- }
- \item{xlim}{
- plot range in x direction.
- }
- \item{xlab}{
- Label for the x axis. Defaults to "Time [days]".
- }
- \item{ylab}{
- Label for the y axis. Defaults to "Residual [\% of applied radioactivity]".
- }
- \item{maxabs}{
- Maximum absolute value of the residuals. This is used for the scaling of
- the y axis and defaults to "auto".
- }
- \item{legend}{
- Should a legend be plotted? Defaults to "TRUE".
- }
- \item{lpos}{
- Where should the legend be placed? Default is "topright". Will be passed on to
- \code{\link{legend}}. }
- \item{col_obs}{
- Colors for the observed variables.
- }
- \item{pch_obs}{
- Symbols to be used for the observed variables.
- }
- \item{frame}{
- Should a frame be drawn around the plots?
- }
- \item{\dots}{
- further arguments passed to \code{\link{plot}}.
- }
-}
-\value{
- Nothing is returned by this function, as it is called for its side effect, namely to produce a plot.
-}
-\author{
- Johannes Ranke
-}
-\seealso{
- \code{\link{mkinplot}}, for a way to plot the data and the fitted lines of the
- mkinfit object. }
-\examples{
-model <- mkinmod(parent = mkinsub("SFO", "m1"), m1 = mkinsub("SFO"))
-fit <- mkinfit(model, FOCUS_2006_D, quiet = TRUE)
-mkinresplot(fit, "m1")
-}
-\keyword{ hplot }
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/mkinresplot.R
+\name{mkinresplot}
+\alias{mkinresplot}
+\title{Function to plot residuals stored in an mkin object}
+\usage{
+mkinresplot(object, obs_vars = names(object$mkinmod$map), xlim = c(0,
+ 1.1 * max(object$data$time)), xlab = "Time", ylab = "Residual",
+ maxabs = "auto", legend = TRUE, lpos = "topright",
+ col_obs = "auto", pch_obs = "auto", frame = TRUE, ...)
+}
+\arguments{
+\item{object}{A fit represented in an \code{\link{mkinfit}} object.}
+
+\item{obs_vars}{A character vector of names of the observed variables for
+which residuals should be plotted. Defaults to all observed variables in
+the model}
+
+\item{xlim}{plot range in x direction.}
+
+\item{xlab}{Label for the x axis. Defaults to "Time [days]".}
+
+\item{ylab}{Label for the y axis. Defaults to "Residual [\% of applied
+radioactivity]".}
+
+\item{maxabs}{Maximum absolute value of the residuals. This is used for the
+scaling of the y axis and defaults to "auto".}
+
+\item{legend}{Should a legend be plotted? Defaults to "TRUE".}
+
+\item{lpos}{Where should the legend be placed? Default is "topright". Will
+be passed on to \code{\link{legend}}.}
+
+\item{col_obs}{Colors for the observed variables.}
+
+\item{pch_obs}{Symbols to be used for the observed variables.}
+
+\item{frame}{Should a frame be drawn around the plots?}
+
+\item{\dots}{further arguments passed to \code{\link{plot}}.}
+}
+\value{
+Nothing is returned by this function, as it is called for its side
+ effect, namely to produce a plot.
+}
+\description{
+This function plots the residuals for the specified subset of the observed
+variables from an mkinfit object. A combined plot of the fitted model and
+the residuals can be obtained using \code{\link{plot.mkinfit}} using the
+argument \code{show_residuals = TRUE}.
+}
+\examples{
+
+model <- mkinmod(parent = mkinsub("SFO", "m1"), m1 = mkinsub("SFO"))
+fit <- mkinfit(model, FOCUS_2006_D, quiet = TRUE)
+mkinresplot(fit, "m1")
+
+}
+\seealso{
+\code{\link{mkinplot}}, for a way to plot the data and the fitted
+ lines of the mkinfit object.
+}
+\author{
+Johannes Ranke
+}
diff --git a/man/mkinsub.Rd b/man/mkinsub.Rd
index 84e38e21..6522a37e 100644
--- a/man/mkinsub.Rd
+++ b/man/mkinsub.Rd
@@ -1,42 +1,35 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/mkinsub.R
\name{mkinsub}
\alias{mkinsub}
-\title{
- Function to set up a kinetic submodel for one state variable
-}
-\description{
- This is a convenience function to set up the lists used as arguments for
- \code{\link{mkinmod}}.
-}
+\title{Function to set up a kinetic submodel for one state variable}
\usage{
mkinsub(submodel, to = NULL, sink = TRUE, full_name = NA)
}
\arguments{
- \item{submodel}{
- Character vector of length one to specify the submodel type. See
- \code{\link{mkinmod}} for the list of allowed submodel names.
- }
- \item{to}{
- Vector of the names of the state variable to which a transformation
- shall be included in the model.
- }
- \item{sink}{
- Should a pathway to sink be included in the model in addition to the
- pathways to other state variables?
- }
- \item{full_name}{
- An optional name to be used e.g. for plotting fits performed with the model.
- You can use non-ASCII characters here, but then your R code will not be
- portable, \emph{i.e.} may produce unintended plot results on other
- operating systems or system configurations.
- }
+\item{submodel}{Character vector of length one to specify the submodel type.
+See \code{\link{mkinmod}} for the list of allowed submodel names.}
+
+\item{to}{Vector of the names of the state variable to which a
+transformation shall be included in the model.}
+
+\item{sink}{Should a pathway to sink be included in the model in addition to
+the pathways to other state variables?}
+
+\item{full_name}{An optional name to be used e.g. for plotting fits
+performed with the model. You can use non-ASCII characters here, but then
+your R code will not be portable, \emph{i.e.} may produce unintended plot
+results on other operating systems or system configurations.}
}
\value{
- A list for use with \code{\link{mkinmod}}.
+A list for use with \code{\link{mkinmod}}.
}
-\author{
- Johannes Ranke
+\description{
+This is a convenience function to set up the lists used as arguments for
+\code{\link{mkinmod}}.
}
\examples{
+
# One parent compound, one metabolite, both single first order.
SFO_SFO <- mkinmod(
parent = list(type = "SFO", to = "m1"),
@@ -51,5 +44,8 @@ SFO_SFO.2 <- mkinmod(
SFO_SFO.2 <- mkinmod(
parent = mkinsub("SFO", "m1", full_name = "Test compound"),
m1 = mkinsub("SFO", full_name = "Metabolite M1"))
-}
+}
+\author{
+Johannes Ranke
+}
diff --git a/man/mmkin.Rd b/man/mmkin.Rd
index e871d78b..a763fcdf 100644
--- a/man/mmkin.Rd
+++ b/man/mmkin.Rd
@@ -1,51 +1,41 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/mmkin.R
\name{mmkin}
\alias{mmkin}
-\title{
- Fit one or more kinetic models with one or more state variables to one or more datasets
-}
-\description{
- This function calls \code{\link{mkinfit}} on all combinations of models and datasets
- specified in its first two arguments.
-}
+\title{Fit one or more kinetic models with one or more state variables to one or
+more datasets}
\usage{
-mmkin(models, datasets,
- cores = round(detectCores()/2), cluster = NULL, ...)
+mmkin(models = c("SFO", "FOMC", "DFOP"), datasets,
+ cores = round(detectCores()/2), cluster = NULL, ...)
}
\arguments{
- \item{models}{
- Either a character vector of shorthand names ("SFO", "FOMC", "DFOP",
- "HS", "SFORB"), or an optionally named list of \code{\link{mkinmod}}
- objects.
- }
- \item{datasets}{
- An optionally named list of datasets suitable as observed data for
- \code{\link{mkinfit}}.
- }
- \item{cores}{
- The number of cores to be used for multicore processing. This is only
- used when the \code{cluster} argument is \code{NULL}. On Windows machines,
- cores > 1 is not supported, you need to use the \code{cluster} argument
- to use multiple logical processors.
- }
- \item{cluster}{
- A cluster as returned by \code{\link{makeCluster}} to be used for parallel
- execution.
- }
- \item{\dots}{
- Further arguments that will be passed to \code{\link{mkinfit}}.
- }
+\item{models}{Either a character vector of shorthand names like
+\code{c("SFO", "FOMC", "DFOP", "HS", "SFORB")}, or an optionally named
+list of \code{\link{mkinmod}} objects.}
+
+\item{datasets}{An optionally named list of datasets suitable as observed
+data for \code{\link{mkinfit}}.}
+
+\item{cores}{The number of cores to be used for multicore processing. This
+is only used when the \code{cluster} argument is \code{NULL}. On Windows
+machines, cores > 1 is not supported, you need to use the \code{cluster}
+argument to use multiple logical processors.}
+
+\item{cluster}{A cluster as returned by \code{\link{makeCluster}} to be used
+for parallel execution.}
+
+\item{\dots}{Further arguments that will be passed to \code{\link{mkinfit}}.}
}
\value{
- A matrix of \code{\link{mkinfit}} objects that can be indexed using the model
- and dataset names as row and column indices.
-}
-\seealso{
- \code{\link{[.mmkin}} for subsetting, \code{\link{plot.mmkin}} for plotting.
+A matrix of \code{\link{mkinfit}} objects that can be indexed using
+ the model and dataset names as row and column indices.
}
-\author{
- Johannes Ranke
+\description{
+This function calls \code{\link{mkinfit}} on all combinations of models and
+datasets specified in its first two arguments.
}
\examples{
+
\dontrun{
m_synth_SFO_lin <- mkinmod(parent = mkinsub("SFO", "M1"),
M1 = mkinsub("SFO", "M2"),
@@ -79,5 +69,13 @@ plot_sep(fits.0[[1, 1]])
# allow to plot the observed variables separately
plot(fits.0[1, 1])
}
+
+}
+\seealso{
+\code{\link{[.mmkin}} for subsetting, \code{\link{plot.mmkin}} for
+ plotting.
+}
+\author{
+Johannes Ranke
}
-\keyword{ optimize }
+\keyword{optimize}
diff --git a/man/nafta.Rd b/man/nafta.Rd
index 6917d0e9..49c13afc 100644
--- a/man/nafta.Rd
+++ b/man/nafta.Rd
@@ -1,52 +1,65 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/nafta.R
\name{nafta}
\alias{nafta}
-\title{
-Evaluate parent kinetics using the NAFTA guidance
+\alias{print.nafta}
+\title{Evaluate parent kinetics using the NAFTA guidance}
+\source{
+NAFTA (2011) Guidance for evaluating and calculating degradation
+ kinetics in environmental media. NAFTA Technical Working Group on
+ Pesticides
+ \url{https://www.epa.gov/pesticide-science-and-assessing-pesticide-risks/guidance-evaluating-and-calculating-degradation}
+ accessed 2019-02-22
+
+ US EPA (2015) Standard Operating Procedure for Using the NAFTA Guidance to
+ Calculate Representative Half-life Values and Characterizing Pesticide
+ Degradation
+ \url{https://www.epa.gov/pesticide-science-and-assessing-pesticide-risks/standard-operating-procedure-using-nafta-guidance}
}
\usage{
-nafta(ds, title = NA, quiet = FALSE, \dots)
-}
-\description{
- The function fits the SFO, IORE and DFOP models using
- \code{\link{mmkin}} and returns an object of class
- \code{nafta} that has methods for printing and plotting.
+nafta(ds, title = NA, quiet = FALSE, ...)
+
+\method{print}{nafta}(x, quiet = TRUE, digits = 3, ...)
}
\arguments{
- \item{ds}{
- A dataframe that must contain one variable called "time" with the time
- values specified by the \code{time} argument, one column called "name" with
- the grouping of the observed values, and finally one column of observed
- values called "value".
- }
- \item{title}{ Optional title of the dataset }
- \item{quiet}{ Should the evaluation text be shown? }
- \item{\dots}{
- Further arguments passed to \code{\link{mmkin}}.
- }
+\item{ds}{A dataframe that must contain one variable called "time" with the
+time values specified by the \code{time} argument, one column called
+"name" with the grouping of the observed values, and finally one column of
+observed values called "value".}
+
+\item{title}{Optional title of the dataset}
+
+\item{quiet}{Should the evaluation text be shown?}
+\item{\dots}{Further arguments passed to \code{\link{mmkin}} (not for the
+printing method).}
+
+\item{x}{An \code{\link{nafta}} object.}
+
+\item{digits}{Number of digits to be used for printing parameters and
+dissipation times.}
}
\value{
- An list of class \code{nafta}. The list element named "mmkin" is the
- \code{\link{mmkin}} object containing the fits of the three models.
- The list element named "title" contains the title of the dataset used.
- The list element "data" contains the dataset used in the fits.
+An list of class \code{nafta}. The list element named "mmkin" is the
+ \code{\link{mmkin}} object containing the fits of the three models. The
+ list element named "title" contains the title of the dataset used. The
+ list element "data" contains the dataset used in the fits.
}
-\source{
- NAFTA (2011) Guidance for evaluating and calculating degradation kinetics
- in environmental media. NAFTA Technical Working Group on Pesticides
- \url{https://www.epa.gov/pesticide-science-and-assessing-pesticide-risks/guidance-evaluating-and-calculating-degradation}
- accessed 2019-02-22
+\description{
+The function fits the SFO, IORE and DFOP models using \code{\link{mmkin}}
+and returns an object of class \code{nafta} that has methods for printing
+and plotting.
- US EPA (2015) Standard Operating Procedure for Using the NAFTA Guidance to
- Calculate Representative Half-life Values and Characterizing Pesticide
- Degradation
- \url{https://www.epa.gov/pesticide-science-and-assessing-pesticide-risks/standard-operating-procedure-using-nafta-guidance}
+Print nafta objects. The results for the three models are printed in the
+order of increasing model complexity, i.e. SFO, then IORE, and finally DFOP.
}
\examples{
+
nafta_evaluation <- nafta(NAFTA_SOP_Appendix_D, cores = 1)
print(nafta_evaluation)
plot(nafta_evaluation)
+
}
\author{
- Johannes Ranke
+Johannes Ranke
}
diff --git a/man/plot.mkinfit.Rd b/man/plot.mkinfit.Rd
index fac5663a..3834eaf5 100644
--- a/man/plot.mkinfit.Rd
+++ b/man/plot.mkinfit.Rd
@@ -1,130 +1,110 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/plot.mkinfit.R
\name{plot.mkinfit}
\alias{plot.mkinfit}
\alias{plot_sep}
\alias{plot_res}
\alias{plot_err}
-\title{
- Plot the observed data and the fitted model of an mkinfit object
-}
-\description{
- Solves the differential equations with the optimised and fixed parameters
- from a previous successful call to \code{\link{mkinfit}} and plots
- the observed data together with the solution of the fitted model.
-
- If the current plot device is a \code{\link[tikzDevice]{tikz}} device,
- then latex is being used for the formatting of the chi2 error level,
- if \code{show_errmin = TRUE}.
-}
+\title{Plot the observed data and the fitted model of an mkinfit object}
\usage{
-\method{plot}{mkinfit}(x, fit = x,
- obs_vars = names(fit$mkinmod$map),
- xlab = "Time", ylab = "Observed",
- xlim = range(fit$data$time),
- ylim = "default",
- col_obs = 1:length(obs_vars), pch_obs = col_obs,
- lty_obs = rep(1, length(obs_vars)),
- add = FALSE, legend = !add,
- show_residuals = FALSE,
- show_errplot = FALSE,
- maxabs = "auto",
- sep_obs = FALSE, rel.height.middle = 0.9,
- row_layout = FALSE,
- lpos = "topright", inset = c(0.05, 0.05),
- show_errmin = FALSE, errmin_digits = 3, frame = TRUE, \dots)
-plot_sep(fit, show_errmin = TRUE, \dots)
-plot_res(fit, sep_obs = FALSE, show_errmin = sep_obs, \dots)
-plot_err(fit, sep_obs = FALSE, show_errmin = sep_obs, \dots)
+\method{plot}{mkinfit}(x, fit = x, obs_vars = names(fit$mkinmod$map),
+ xlab = "Time", ylab = "Observed", xlim = range(fit$data$time),
+ ylim = "default", col_obs = 1:length(obs_vars), pch_obs = col_obs,
+ lty_obs = rep(1, length(obs_vars)), add = FALSE, legend = !add,
+ show_residuals = FALSE, show_errplot = FALSE, maxabs = "auto",
+ sep_obs = FALSE, rel.height.middle = 0.9, row_layout = FALSE,
+ lpos = "topright", inset = c(0.05, 0.05), show_errmin = FALSE,
+ errmin_digits = 3, frame = TRUE, ...)
+
+plot_sep(fit, show_errmin = TRUE, ...)
+
+plot_res(fit, sep_obs = FALSE, show_errmin = sep_obs, ...)
+
+plot_err(fit, sep_obs = FALSE, show_errmin = sep_obs, ...)
}
\arguments{
- \item{x}{
- Alias for fit introduced for compatibility with the generic S3 method.
- }
- \item{fit}{
- An object of class \code{\link{mkinfit}}.
- }
- \item{obs_vars}{
- A character vector of names of the observed variables for which the
- data and the model should be plotted. Defauls to all observed variables
- in the model.
- }
- \item{xlab}{
- Label for the x axis.
- }
- \item{ylab}{
- Label for the y axis.
- }
- \item{xlim}{
- Plot range in x direction.
- }
- \item{ylim}{
- Plot range in y direction.
- }
- \item{col_obs}{
- Colors used for plotting the observed data and the corresponding model prediction lines.
- }
- \item{pch_obs}{
- Symbols to be used for plotting the data.
- }
- \item{lty_obs}{
- Line types to be used for the model predictions.
- }
- \item{add}{
- Should the plot be added to an existing plot?
- }
- \item{legend}{
- Should a legend be added to the plot?
- }
- \item{show_residuals}{
- Should residuals be shown? If only one plot of the fits is shown, the
- residual plot is in the lower third of the plot. Otherwise, i.e. if
- "sep_obs" is given, the residual plots will be located to the right of
- the plots of the fitted curves.
- }
- \item{show_errplot}{
- Should squared residuals and the error model be shown? If only one plot of
- the fits is shown, this plot is in the lower third of the plot.
- Otherwise, i.e. if "sep_obs" is given, the residual plots will be located
- to the right of the plots of the fitted curves.
- }
- \item{maxabs}{
- Maximum absolute value of the residuals. This is used for the scaling of
- the y axis and defaults to "auto".
- }
- \item{sep_obs}{
- Should the observed variables be shown in separate subplots? If yes, residual plots
- requested by "show_residuals" will be shown next to, not below the plot of the fits.
- }
- \item{rel.height.middle}{
- The relative height of the middle plot, if more than two rows of plots are shown.
- }
- \item{row_layout}{
- Should we use a row layout where the residual plot or the error model plot is shown
- to the right?
- }
- \item{lpos}{
- Position(s) of the legend(s). Passed to \code{\link{legend}} as the first argument.
- If not length one, this should be of the same length as the obs_var argument.
- }
- \item{inset}{
- Passed to \code{\link{legend}} if applicable.
- }
- \item{show_errmin}{
- Should the FOCUS chi2 error value be shown in the upper margin of the plot?
- }
- \item{errmin_digits}{
- The number of significant digits for rounding the FOCUS chi2 error percentage.
- }
- \item{frame}{
- Should a frame be drawn around the plots?
- }
- \item{\dots}{
- Further arguments passed to \code{\link{plot}}.
- }
+\item{x}{Alias for fit introduced for compatibility with the generic S3
+method.}
+
+\item{fit}{An object of class \code{\link{mkinfit}}.}
+
+\item{obs_vars}{A character vector of names of the observed variables for
+which the data and the model should be plotted. Defauls to all observed
+variables in the model.}
+
+\item{xlab}{Label for the x axis.}
+
+\item{ylab}{Label for the y axis.}
+
+\item{xlim}{Plot range in x direction.}
+
+\item{ylim}{Plot range in y direction.}
+
+\item{col_obs}{Colors used for plotting the observed data and the
+corresponding model prediction lines.}
+
+\item{pch_obs}{Symbols to be used for plotting the data.}
+
+\item{lty_obs}{Line types to be used for the model predictions.}
+
+\item{add}{Should the plot be added to an existing plot?}
+
+\item{legend}{Should a legend be added to the plot?}
+
+\item{show_residuals}{Should residuals be shown? If only one plot of the
+fits is shown, the residual plot is in the lower third of the plot.
+Otherwise, i.e. if "sep_obs" is given, the residual plots will be located
+to the right of the plots of the fitted curves.}
+
+\item{show_errplot}{Should squared residuals and the error model be shown?
+If only one plot of the fits is shown, this plot is in the lower third of
+the plot. Otherwise, i.e. if "sep_obs" is given, the residual plots will
+be located to the right of the plots of the fitted curves.}
+
+\item{maxabs}{Maximum absolute value of the residuals. This is used for the
+scaling of the y axis and defaults to "auto".}
+
+\item{sep_obs}{Should the observed variables be shown in separate subplots?
+If yes, residual plots requested by "show_residuals" will be shown next
+to, not below the plot of the fits.}
+
+\item{rel.height.middle}{The relative height of the middle plot, if more
+than two rows of plots are shown.}
+
+\item{row_layout}{Should we use a row layout where the residual plot or the
+error model plot is shown to the right?}
+
+\item{lpos}{Position(s) of the legend(s). Passed to \code{\link{legend}} as
+the first argument. If not length one, this should be of the same length
+as the obs_var argument.}
+
+\item{inset}{Passed to \code{\link{legend}} if applicable.}
+
+\item{show_errmin}{Should the FOCUS chi2 error value be shown in the upper
+margin of the plot?}
+
+\item{errmin_digits}{The number of significant digits for rounding the FOCUS
+chi2 error percentage.}
+
+\item{frame}{Should a frame be drawn around the plots?}
+
+\item{\dots}{Further arguments passed to \code{\link{plot}}.}
}
\value{
- The function is called for its side effect.
+The function is called for its side effect.
+}
+\description{
+Solves the differential equations with the optimised and fixed parameters
+from a previous successful call to \code{\link{mkinfit}} and plots the
+observed data together with the solution of the fitted model.
+}
+\details{
+If the current plot device is a \code{\link[tikzDevice]{tikz}} device, then
+latex is being used for the formatting of the chi2 error level, if
+\code{show_errmin = TRUE}.
}
\examples{
+
# One parent compound, one metabolite, both single first order, path from
# parent to sink included
\dontrun{
@@ -146,7 +126,8 @@ plot_sep(fit, lpos = c("topright", "bottomright"))
plot(fit, sep_obs = TRUE, show_errplot = TRUE, lpos = c("topright", "bottomright"),
show_errmin = TRUE)
}
+
}
\author{
- Johannes Ranke
+Johannes Ranke
}
diff --git a/man/plot.mmkin.Rd b/man/plot.mmkin.Rd
index 90b92d27..333998da 100644
--- a/man/plot.mmkin.Rd
+++ b/man/plot.mmkin.Rd
@@ -1,62 +1,58 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/plot.mmkin.R
\name{plot.mmkin}
\alias{plot.mmkin}
-\title{
- Plot model fits (observed and fitted) and the residuals for a row or column of an mmkin object
-}
-\description{
- When x is a row selected from an mmkin object (\code{\link{[.mmkin}}), the same model
- fitted for at least one dataset is shown. When it is a column, the fit of at least one model
- to the same dataset is shown.
-
- If the current plot device is a \code{\link[tikzDevice]{tikz}} device,
- then latex is being used for the formatting of the chi2 error level.
-}
+\title{Plot model fits (observed and fitted) and the residuals for a row or column
+of an mmkin object}
\usage{
\method{plot}{mmkin}(x, main = "auto", legends = 1,
- resplot = c("time", "errmod"), show_errmin = TRUE, errmin_var = "All data",
- errmin_digits = 3, cex = 0.7, rel.height.middle = 0.9, ...)
+ resplot = c("time", "errmod"), show_errmin = TRUE,
+ errmin_var = "All data", errmin_digits = 3, cex = 0.7,
+ rel.height.middle = 0.9, ...)
}
\arguments{
- \item{x}{
- An object of class \code{\link{mmkin}}, with either one row or one column.
-}
- \item{main}{
- The main title placed on the outer margin of the plot.
-}
- \item{legends}{
- An index for the fits for which legends should be shown.
-}
- \item{resplot}{
- Should the residuals plotted against time, using \code{\link{mkinresplot}},
- or as squared residuals against predicted values, with the error model,
- using \code{\link{mkinerrplot}}.
-}
- \item{show_errmin}{
- Should the chi2 error level be shown on top of the plots to the left?
- }
- \item{errmin_var}{
- The variable for which the FOCUS chi2 error value should be shown.
-}
- \item{errmin_digits}{
- The number of significant digits for rounding the FOCUS chi2 error percentage.
-}
- \item{cex}{
- Passed to the plot functions and \code{\link{mtext}}.
-}
- \item{rel.height.middle}{
- The relative height of the middle plot, if more than two rows of plots are shown.
-}
- \item{\dots}{
- Further arguments passed to \code{\link{plot.mkinfit}} and \code{\link{mkinresplot}}.
-}
+\item{x}{An object of class \code{\link{mmkin}}, with either one row or one
+column.}
+
+\item{main}{The main title placed on the outer margin of the plot.}
+
+\item{legends}{An index for the fits for which legends should be shown.}
+
+\item{resplot}{Should the residuals plotted against time, using
+\code{\link{mkinresplot}}, or as squared residuals against predicted
+values, with the error model, using \code{\link{mkinerrplot}}.}
+
+\item{show_errmin}{Should the chi2 error level be shown on top of the plots
+to the left?}
+
+\item{errmin_var}{The variable for which the FOCUS chi2 error value should
+be shown.}
+
+\item{errmin_digits}{The number of significant digits for rounding the FOCUS
+chi2 error percentage.}
+
+\item{cex}{Passed to the plot functions and \code{\link{mtext}}.}
+
+\item{rel.height.middle}{The relative height of the middle plot, if more
+than two rows of plots are shown.}
+
+\item{\dots}{Further arguments passed to \code{\link{plot.mkinfit}} and
+\code{\link{mkinresplot}}.}
}
\value{
- The function is called for its side effect.
+The function is called for its side effect.
}
-\author{
- Johannes Ranke
+\description{
+When x is a row selected from an mmkin object (\code{\link{[.mmkin}}), the
+same model fitted for at least one dataset is shown. When it is a column,
+the fit of at least one model to the same dataset is shown.
+}
+\details{
+If the current plot device is a \code{\link[tikzDevice]{tikz}} device, then
+latex is being used for the formatting of the chi2 error level.
}
\examples{
+
\dontrun{
# Only use one core not to offend CRAN checks
fits <- mmkin(c("FOMC", "HS"),
@@ -73,4 +69,8 @@
# Show the error models
plot(fits["FOMC", ], resplot = "errmod")
}
+
+}
+\author{
+Johannes Ranke
}
diff --git a/man/plot.nafta.Rd b/man/plot.nafta.Rd
index 62bbcddf..e7a57de3 100644
--- a/man/plot.nafta.Rd
+++ b/man/plot.nafta.Rd
@@ -1,33 +1,30 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/nafta.R
\name{plot.nafta}
\alias{plot.nafta}
-\title{
- Plot the results of the three models used in the NAFTA scheme. The plots
- are ordered with increasing complexity of the model in this function
- (SFO, then IORE, then DFOP).
-}
-\description{
- Calls \code{\link{plot.mmkin}}.
-}
+\title{Plot the results of the three models used in the NAFTA scheme.}
\usage{
-\method{plot}{nafta}(x, legend = FALSE, main = "auto", \dots)
+\method{plot}{nafta}(x, legend = FALSE, main = "auto", ...)
}
\arguments{
- \item{x}{
- An object of class \code{\link{nafta}}.
- }
- \item{legend}{
- Should a legend be added?
- }
- \item{main}{
- Possibility to override the main title of the plot.
- }
- \item{\dots}{
- Further arguments passed to \code{\link{plot.mmkin}}.
- }
+\item{x}{An object of class \code{\link{nafta}}.}
+
+\item{legend}{Should a legend be added?}
+
+\item{main}{Possibility to override the main title of the plot.}
+
+\item{\dots}{Further arguments passed to \code{\link{plot.mmkin}}.}
}
\value{
- The function is called for its side effect.
+The function is called for its side effect.
+}
+\description{
+The plots are ordered with increasing complexity of the model in this
+function (SFO, then IORE, then DFOP).
+}
+\details{
+Calls \code{\link{plot.mmkin}}.
}
\author{
- Johannes Ranke
+Johannes Ranke
}
diff --git a/man/print.mkinds.Rd b/man/print.mkinds.Rd
index e7acf30d..54dc5a12 100644
--- a/man/print.mkinds.Rd
+++ b/man/print.mkinds.Rd
@@ -1,19 +1,16 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/mkinds.R
\name{print.mkinds}
\alias{print.mkinds}
-\title{
- Print mkinds objects
-}
-\description{
- Print mkinds objects.
-}
+\title{Print mkinds objects}
\usage{
\method{print}{mkinds}(x, ...)
}
\arguments{
- \item{x}{
- An \code{\link{mkinds}} object.
- }
- \item{\dots}{
- Not used.
- }
+\item{x}{An \code{\link{mkinds}} object.}
+
+\item{\dots}{Not used.}
+}
+\description{
+Print mkinds objects.
}
diff --git a/man/print.mkinmod.Rd b/man/print.mkinmod.Rd
index 24555def..4e44cde6 100644
--- a/man/print.mkinmod.Rd
+++ b/man/print.mkinmod.Rd
@@ -1,26 +1,26 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/mkinmod.R
\name{print.mkinmod}
\alias{print.mkinmod}
-\title{
- Print mkinmod objects
-}
-\description{
- Print mkinmod objects in a way that the user finds his way to get to its components.
-}
+\title{Print mkinmod objects}
\usage{
- \method{print}{mkinmod}(x, ...)
+\method{print}{mkinmod}(x, ...)
}
\arguments{
- \item{x}{
- An \code{\link{mkinmod}} object.
- }
- \item{\dots}{
- Not used.
- }
+\item{x}{An \code{\link{mkinmod}} object.}
+
+\item{\dots}{Not used.}
+}
+\description{
+Print mkinmod objects in a way that the user finds his way to get to its
+components.
}
\examples{
+
m_synth_SFO_lin <- mkinmod(parent = list(type = "SFO", to = "M1"),
M1 = list(type = "SFO", to = "M2"),
M2 = list(type = "SFO"), use_of_ff = "max")
-
+
print(m_synth_SFO_lin)
+
}
diff --git a/man/print.nafta.Rd b/man/print.nafta.Rd
deleted file mode 100644
index e42a619d..00000000
--- a/man/print.nafta.Rd
+++ /dev/null
@@ -1,27 +0,0 @@
-\name{print.nafta}
-\alias{print.nafta}
-\title{
- Print nafta objects
-}
-\description{
- Print nafta objects. The results for the three models
- are printed in the order of increasing model complexity,
- i.e. SFO, then IORE, and finally DFOP.
-}
-\usage{
- \method{print}{nafta}(x, quiet = TRUE, digits = 3, ...)
-}
-\arguments{
- \item{x}{
- An \code{\link{nafta}} object.
- }
- \item{quiet}{
- Should the evaluation text be shown?
- }
- \item{digits}{
- Number of digits to be used for printing parameters and dissipation times.
- }
- \item{\dots}{
- Not used.
- }
-}
diff --git a/man/sigma_twocomp.Rd b/man/sigma_twocomp.Rd
index 9e91fe78..3e7854f1 100644
--- a/man/sigma_twocomp.Rd
+++ b/man/sigma_twocomp.Rd
@@ -1,31 +1,38 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/sigma_twocomp.R
\name{sigma_twocomp}
\alias{sigma_twocomp}
\title{Two component error model}
-\description{
- Function describing the standard deviation of the measurement error
- in dependence of the measured value \eqn{y}:
-
- \deqn{\sigma = \sqrt{ \sigma_{low}^2 + y^2 * {rsd}_{high}^2}}
- {sigma = sqrt(sigma_low^2 + y^2 * rsd_high^2)}
-
- This is the error model used for example by Werner et al. (1978). The model
- proposed by Rocke and Lorenzato (1995) can be written in this form as well,
- but assumes approximate lognormal distribution of errors for high values of y.
-}
\usage{
sigma_twocomp(y, sigma_low, rsd_high)
}
\arguments{
- \item{y}{ The magnitude of the observed value }
- \item{sigma_low}{ The asymptotic minimum of the standard deviation for low observed values }
- \item{rsd_high}{ The coefficient describing the increase of the standard deviation with
- the magnitude of the observed value }
+\item{y}{The magnitude of the observed value}
+
+\item{sigma_low}{The asymptotic minimum of the standard deviation for low
+observed values}
+
+\item{rsd_high}{The coefficient describing the increase of the standard
+deviation with the magnitude of the observed value}
}
\value{
- The standard deviation of the response variable.
+The standard deviation of the response variable.
+}
+\description{
+Function describing the standard deviation of the measurement error in
+dependence of the measured value \eqn{y}:
+}
+\details{
+\deqn{\sigma = \sqrt{ \sigma_{low}^2 + y^2 * {rsd}_{high}^2}} sigma =
+sqrt(sigma_low^2 + y^2 * rsd_high^2)
+
+This is the error model used for example by Werner et al. (1978). The model
+proposed by Rocke and Lorenzato (1995) can be written in this form as well,
+but assumes approximate lognormal distribution of errors for high values of
+y.
}
\references{
- Werner, Mario, Brooks, Samuel H., and Knott, Lancaster B. (1978)
+Werner, Mario, Brooks, Samuel H., and Knott, Lancaster B. (1978)
Additive, Multiplicative, and Mixed Analytical Errors. Clinical Chemistry
24(11), 1895-1898.
diff --git a/man/summary.mkinfit.Rd b/man/summary.mkinfit.Rd
index cbc9098c..fcc1295f 100644
--- a/man/summary.mkinfit.Rd
+++ b/man/summary.mkinfit.Rd
@@ -1,75 +1,77 @@
-\name{summary.mkinfit}
-\alias{summary.mkinfit}
-\alias{print.summary.mkinfit}
-\title{
- Summary method for class "mkinfit"
-}
-\description{
- Lists model equations, initial parameter values, optimised parameters with some
- uncertainty statistics, the chi2 error levels calculated according to FOCUS
- guidance (2006) as defined therein, formation fractions, DT50 values and
- optionally the data, consisting of observed, predicted and residual values.
-}
-\usage{
-\method{summary}{mkinfit}(object, data = TRUE, distimes = TRUE, alpha = 0.05, ...)
-\method{print}{summary.mkinfit}(x, digits = max(3, getOption("digits") - 3), ...)
-}
-
-\arguments{
- \item{object}{
- an object of class \code{\link{mkinfit}}.
-}
- \item{x}{
- an object of class \code{summary.mkinfit}.
-}
- \item{data}{
- logical, indicating whether the data should be included in the summary.
-}
- \item{distimes}{
- logical, indicating whether DT50 and DT90 values should be included.
-}
- \item{alpha}{
- error level for confidence interval estimation from t distribution
-}
- \item{digits}{
- Number of digits to use for printing
-}
- \item{\dots}{
- optional arguments passed to methods like \code{print}.
-}
-}
-\value{
- The summary function returns a list with components, among others
- \item{version, Rversion}{The mkin and R versions used}
- \item{date.fit, date.summary}{The dates where the fit and the summary were produced}
- \item{use_of_ff}{Was maximum or minimum use made of formation fractions}
- \item{residuals, residualVariance, sigma, modVariance, df}{As in summary.modFit}
- \item{cov.unscaled, cov.scaled, info, niter, stopmess, par}{As in summary.modFit}
- \item{bpar}{Optimised and backtransformed parameters}
- \item{diffs }{The differential equations used in the model}
- \item{data }{The data (see Description above).}
- \item{start }{The starting values and bounds, if applicable, for optimised parameters.}
- \item{fixed }{The values of fixed parameters.}
- \item{errmin }{The chi2 error levels for each observed variable.}
- \item{bparms.ode }{All backtransformed ODE parameters, for use as starting parameters for
- related models.}
- \item{errparms }{Error model parameters. }
- \item{ff }{The estimated formation fractions derived from the fitted model.}
- \item{distimes }{The DT50 and DT90 values for each observed variable.}
- \item{SFORB}{If applicable, eigenvalues of SFORB components of the model.}
- The print method is called for its side effect, i.e. printing the summary.
-}
-\references{
- FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence and
- Degradation Kinetics from Environmental Fate Studies on Pesticides in EU
- Registration} Report of the FOCUS Work Group on Degradation Kinetics,
- EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
- \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
-}
-\author{
- Johannes Ranke
-}
-\examples{
- summary(mkinfit(mkinmod(parent = mkinsub("SFO")), FOCUS_2006_A, quiet = TRUE))
-}
-\keyword{ utilities }
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/summary.mkinfit.R
+\name{summary.mkinfit}
+\alias{summary.mkinfit}
+\alias{print.summary.mkinfit}
+\title{Summary method for class "mkinfit"}
+\usage{
+\method{summary}{mkinfit}(object, data = TRUE, distimes = TRUE,
+ alpha = 0.05, ...)
+
+\method{print}{summary.mkinfit}(x, digits = max(3, getOption("digits") -
+ 3), ...)
+}
+\arguments{
+\item{object}{an object of class \code{\link{mkinfit}}.}
+
+\item{data}{logical, indicating whether the data should be included in the
+summary.}
+
+\item{distimes}{logical, indicating whether DT50 and DT90 values should be
+included.}
+
+\item{alpha}{error level for confidence interval estimation from t
+distribution}
+
+\item{\dots}{optional arguments passed to methods like \code{print}.}
+
+\item{x}{an object of class \code{summary.mkinfit}.}
+
+\item{digits}{Number of digits to use for printing}
+}
+\value{
+The summary function returns a list with components, among others
+ \item{version, Rversion}{The mkin and R versions used}
+ \item{date.fit, date.summary}{The dates where the fit and the summary were
+ produced}
+ \item{diffs}{The differential equations used in the model}
+ \item{use_of_ff}{Was maximum or minimum use made of formation fractions}
+ \item{bpar}{Optimised and backtransformed
+ parameters}
+ \item{data}{The data (see Description above).}
+ \item{start}{The starting values and bounds, if applicable, for optimised
+ parameters.}
+ \item{fixed}{The values of fixed parameters.}
+ \item{errmin }{The chi2 error levels for
+ each observed variable.}
+ \item{bparms.ode}{All backtransformed ODE
+ parameters, for use as starting parameters for related models.}
+ \item{errparms}{Error model parameters.}
+ \item{ff}{The estimated formation fractions derived from the fitted
+ model.}
+ \item{distimes}{The DT50 and DT90 values for each observed variable.}
+ \item{SFORB}{If applicable, eigenvalues of SFORB components of the model.}
+ The print method is called for its side effect, i.e. printing the summary.
+}
+\description{
+Lists model equations, initial parameter values, optimised parameters with
+some uncertainty statistics, the chi2 error levels calculated according to
+FOCUS guidance (2006) as defined therein, formation fractions, DT50 values
+and optionally the data, consisting of observed, predicted and residual
+values.
+}
+\examples{
+
+ summary(mkinfit(mkinmod(parent = mkinsub("SFO")), FOCUS_2006_A, quiet = TRUE))
+
+}
+\references{
+FOCUS (2006) \dQuote{Guidance Document on Estimating Persistence
+ and Degradation Kinetics from Environmental Fate Studies on Pesticides in
+ EU Registration} Report of the FOCUS Work Group on Degradation Kinetics,
+ EC Document Reference Sanco/10058/2005 version 2.0, 434 pp,
+ \url{http://esdac.jrc.ec.europa.eu/projects/degradation-kinetics}
+}
+\author{
+Johannes Ranke
+}
diff --git a/man/transform_odeparms.Rd b/man/transform_odeparms.Rd
index 006897d6..5c8c90ba 100644
--- a/man/transform_odeparms.Rd
+++ b/man/transform_odeparms.Rd
@@ -1,66 +1,67 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/transform_odeparms.R
\name{transform_odeparms}
\alias{transform_odeparms}
\alias{backtransform_odeparms}
-\title{
- Functions to transform and backtransform kinetic parameters for fitting
-}
-\description{
- The transformations are intended to map parameters that should only take
- on restricted values to the full scale of real numbers. For kinetic rate
- constants and other paramters that can only take on positive values, a
- simple log transformation is used. For compositional parameters, such as
- the formations fractions that should always sum up to 1 and can not be
- negative, the \code{\link{ilr}} transformation is used.
-
- The transformation of sets of formation fractions is fragile, as it supposes
- the same ordering of the components in forward and backward transformation.
- This is no problem for the internal use in \code{\link{mkinfit}}.
-}
+\title{Functions to transform and backtransform kinetic parameters for fitting}
\usage{
-transform_odeparms(parms, mkinmod,
- transform_rates = TRUE, transform_fractions = TRUE)
-backtransform_odeparms(transparms, mkinmod,
- transform_rates = TRUE, transform_fractions = TRUE)
+transform_odeparms(parms, mkinmod, transform_rates = TRUE,
+ transform_fractions = TRUE)
+
+backtransform_odeparms(transparms, mkinmod, transform_rates = TRUE,
+ transform_fractions = TRUE)
}
\arguments{
- \item{parms}{
- Parameters of kinetic models as used in the differential equations.
- }
- \item{transparms}{
- Transformed parameters of kinetic models as used in the fitting procedure.
- }
- \item{mkinmod}{
- The kinetic model of class \code{\link{mkinmod}}, containing the names of
- the model variables that are needed for grouping the formation fractions
- before \code{\link{ilr}} transformation, the parameter names and
- the information if the pathway to sink is included in the model.
- }
- \item{transform_rates}{
- Boolean specifying if kinetic rate constants should be transformed in the
- model specification used in the fitting for better compliance with the
- assumption of normal distribution of the estimator. If TRUE, also
- alpha and beta parameters of the FOMC model are log-transformed, as well
- as k1 and k2 rate constants for the DFOP and HS models and the break point tb
- of the HS model.
- }
- \item{transform_fractions}{
- Boolean specifying if formation fractions constants should be transformed in the
- model specification used in the fitting for better compliance with the
- assumption of normal distribution of the estimator. The default (TRUE) is
- to do transformations. The g parameter of the DFOP and HS models are also
- transformed, as they can also be seen as compositional data. The
- transformation used for these transformations is the \code{\link{ilr}}
- transformation.
- }
+\item{parms}{Parameters of kinetic models as used in the differential
+equations.}
+
+\item{mkinmod}{The kinetic model of class \code{\link{mkinmod}}, containing
+the names of the model variables that are needed for grouping the
+formation fractions before \code{\link{ilr}} transformation, the parameter
+names and the information if the pathway to sink is included in the model.}
+
+\item{transform_rates}{Boolean specifying if kinetic rate constants should
+be transformed in the model specification used in the fitting for better
+compliance with the assumption of normal distribution of the estimator. If
+TRUE, also alpha and beta parameters of the FOMC model are
+log-transformed, as well as k1 and k2 rate constants for the DFOP and HS
+models and the break point tb of the HS model.}
+
+\item{transform_fractions}{Boolean specifying if formation fractions
+constants should be transformed in the model specification used in the
+fitting for better compliance with the assumption of normal distribution
+of the estimator. The default (TRUE) is to do transformations. The g
+parameter of the DFOP and HS models are also transformed, as they can also
+be seen as compositional data. The transformation used for these
+transformations is the \code{\link{ilr}} transformation.}
+
+\item{transparms}{Transformed parameters of kinetic models as used in the
+fitting procedure.}
}
\value{
- A vector of transformed or backtransformed parameters with the same names
- as the original parameters.
+A vector of transformed or backtransformed parameters with the same
+ names as the original parameters.
}
-\author{
- Johannes Ranke
+\description{
+The transformations are intended to map parameters that should only take on
+restricted values to the full scale of real numbers. For kinetic rate
+constants and other paramters that can only take on positive values, a
+simple log transformation is used. For compositional parameters, such as the
+formations fractions that should always sum up to 1 and can not be negative,
+the \code{\link{ilr}} transformation is used.
}
+\details{
+The transformation of sets of formation fractions is fragile, as it supposes
+the same ordering of the components in forward and backward transformation.
+This is no problem for the internal use in \code{\link{mkinfit}}.
+}
+\section{Functions}{
+\itemize{
+\item \code{backtransform_odeparms}: Backtransform the set of transformed parameters
+}}
+
\examples{
+
SFO_SFO <- mkinmod(
parent = list(type = "SFO", to = "m1", sink = TRUE),
m1 = list(type = "SFO"))
@@ -113,5 +114,8 @@ fit.ff.2.s <- summary(fit.ff.2)
print(fit.ff.2.s$par, 3)
print(fit.ff.2.s$bpar, 3)
}
+
+}
+\author{
+Johannes Ranke
}
-\keyword{ manip }
diff --git a/test.log b/test.log
index 5fedc55e..7e3f1c4e 100644
--- a/test.log
+++ b/test.log
@@ -3,16 +3,16 @@ Testing mkin
✔ | OK F W S | Context
✔ | 2 | Export dataset for reading into CAKE
✔ | 3 | Confidence intervals and p-values
-✔ | 10 | Error model fitting [37.2 s]
+✔ | 10 | Error model fitting [37.1 s]
✔ | 5 | Calculation of FOCUS chi2 error levels [3.5 s]
-✔ | 13 | Results for FOCUS D established in expertise for UBA (Ranke 2014) [3.4 s]
+✔ | 13 | Results for FOCUS D established in expertise for UBA (Ranke 2014) [3.5 s]
✔ | 6 | Test fitting the decline of metabolites from their maximum [0.9 s]
✔ | 1 | Fitting the logistic model [0.9 s]
✔ | 1 | Test dataset class mkinds used in gmkin
✔ | 12 | Special cases of mkinfit calls [2.7 s]
✔ | 9 | mkinmod model generation and printing [0.2 s]
✔ | 3 | Model predictions with mkinpredict [0.3 s]
-✔ | 16 | Evaluations according to 2015 NAFTA guidance [4.0 s]
+✔ | 16 | Evaluations according to 2015 NAFTA guidance [4.1 s]
✔ | 4 | Calculation of maximum time weighted average concentrations (TWAs) [2.2 s]
✔ | 3 | Summary
✔ | 11 | Plotting [0.6 s]
@@ -20,7 +20,7 @@ Testing mkin
✔ | 2 | Complex test case from Schaefer et al. (2007) Piacenza paper [5.3 s]
✔ | 4 | Fitting the SFORB model [1.7 s]
✔ | 1 | Summaries of old mkinfit objects
-✔ | 4 | Results for synthetic data established in expertise for UBA (Ranke 2014) [7.1 s]
+✔ | 4 | Results for synthetic data established in expertise for UBA (Ranke 2014) [7.2 s]
══ Results ═════════════════════════════════════════════════════════════════════
Duration: 70.2 s
diff --git a/tests/testthat/FOCUS_2006_D.csf b/tests/testthat/FOCUS_2006_D.csf
index 638acd88..e3d2a303 100644
--- a/tests/testthat/FOCUS_2006_D.csf
+++ b/tests/testthat/FOCUS_2006_D.csf
@@ -5,7 +5,7 @@ Description:
MeasurementUnits: % AR
TimeUnits: days
Comments: Created using mkin::CAKE_export
-Date: 2019-10-22
+Date: 2019-10-25
Optimiser: IRLS
[Data]

Contact - Imprint