From d518c4cfa22994db5ba81a6b01c6cb4c4186872e Mon Sep 17 00:00:00 2001
From: Johannes Ranke
Date: Wed, 15 Apr 2020 20:42:29 +0200
Subject: Adapt endpoint() to also work for nlme.mmkin objects
---
NEWS.md | 2 +-
R/endpoints.R | 39 +++++++++++++++++++++++++++++++--------
R/nlme.mmkin.R | 5 +++++
docs/news/index.html | 2 +-
docs/reference/endpoints.html | 29 ++++++++++++++++++++++-------
docs/reference/nlme.mmkin.html | 29 ++++++++++++++++++++++++++---
man/endpoints.Rd | 12 ++++++++++--
man/nlme.mmkin.Rd | 5 +++++
8 files changed, 101 insertions(+), 22 deletions(-)
diff --git a/NEWS.md b/NEWS.md
index a4976488..37800e6d 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,6 +1,6 @@
# mkin 0.9.49.10 (unreleased)
-- 'nlme.mmkin': An nlme method for mmkin row objects and an associated class with plot method
+- 'nlme.mmkin': An nlme method for mmkin row objects and an associated S3 class with print, plot, anova and endpoint methods
- 'mean_degparms, nlme_data, nlme_function': Three new functions to facilitate building nlme models from mmkin row objects
diff --git a/R/endpoints.R b/R/endpoints.R
index f7ee483a..586ef9ff 100644
--- a/R/endpoints.R
+++ b/R/endpoints.R
@@ -7,9 +7,13 @@
#' 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}}.
+#' @param fit An object of class \code{\link{mkinfit}} or
+#' \code{\link{nlme.mmkin}}
#' @importFrom stats optimize
-#' @return A list with the components mentioned above.
+#' @return A list with a matrix of dissipation times named distimes,
+#' and, if applicable, a vector of formation fractions named ff
+#' and, if the SFORB model was in use, a vector of eigenvalues
+#' of these SFORB models, equivalent to DFOP rate constants
#' @note The function is used internally by \code{\link{summary.mkinfit}}.
#' @author Johannes Ranke
#' @keywords manip
@@ -17,6 +21,10 @@
#'
#' fit <- mkinfit("FOMC", FOCUS_2006_C, quiet = TRUE)
#' endpoints(fit)
+#' \dontrun{
+#' fit_2 <- mkinfit("SFORB", FOCUS_2006_C, quiet = TRUE)
+#' endpoints(fit_2)
+#' }
#'
#' @export
endpoints <- function(fit) {
@@ -25,8 +33,22 @@ endpoints <- function(fit) {
# 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)
+ if (inherits(fit, "mkinfit")) {
+ mkinmod <- fit$mkinmod
+ parms.all <- c(fit$bparms.optim, fit$bparms.fixed)
+ } else {
+ if (inherits(fit, "nlme.mmkin")) {
+ mkinmod <- fit$mmkin_orig[[1]]$mkinmod
+ bparms.optim <- backtransform_odeparms(fit$coefficients$fixed,
+ mkinmod,
+ transform_rates = fit$mmkin_orig[[1]]$transform_rates,
+ transform_fractions = fit$mmkin_orig[[1]]$transform_fractions)
+ parms.all <- c(bparms.optim, fit$bparms.fixed)
+ } else {
+ stop("Only implemented for mkinfit and nlme.mmkin objects")
+ }
+ }
+ obs_vars <- names(mkinmod$spec)
ep$ff <- vector()
ep$SFORB <- vector()
ep$distimes <- data.frame(
@@ -34,7 +56,7 @@ endpoints <- function(fit) {
DT90 = rep(NA, length(obs_vars)),
row.names = obs_vars)
for (obs_var in obs_vars) {
- type = names(fit$mkinmod$map[[obs_var]])[1]
+ type = names(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)
@@ -56,7 +78,7 @@ endpoints <- function(fit) {
k_tot = sum(parms.all[k_names])
DT50 = log(2)/k_tot
DT90 = log(10)/k_tot
- if (fit$mkinmod$use_of_ff == "min") {
+ if (mkinmod$use_of_ff == "min" && length(obs_vars) > 1) {
for (k_name in k_names)
{
ep$ff[[sub("k_", "", k_name)]] = parms.all[[k_name]] / k_tot
@@ -78,7 +100,7 @@ endpoints <- function(fit) {
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]]
+ source_name = mkinmod$map[[1]][[1]]
c0 = parms.all[paste(source_name, "0", sep = "_")]
alpha = 1 / (n - 1)
beta = (c0^(1 - n))/(k * (n - 1))
@@ -86,7 +108,7 @@ endpoints <- function(fit) {
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") {
+ if (mkinmod$use_of_ff == "min") {
for (k_name in k_names)
{
ep$ff[[sub("k_", "", k_name)]] = parms.all[[k_name]] / k_tot
@@ -196,6 +218,7 @@ endpoints <- function(fit) {
}
ep$distimes[obs_var, c("DT50", "DT90")] = c(DT50, DT90)
}
+ if (length(ep$ff) == 0) ep$ff <- NULL
if (length(ep$SFORB) == 0) ep$SFORB <- NULL
return(ep)
}
diff --git a/R/nlme.mmkin.R b/R/nlme.mmkin.R
index 6e3467ed..1d6c2e75 100644
--- a/R/nlme.mmkin.R
+++ b/R/nlme.mmkin.R
@@ -31,8 +31,10 @@
#' function(x) subset(x$data[c("name", "time", "value")], name == "parent"))
#' f <- mmkin("SFO", ds, quiet = TRUE, cores = 1)
#' library(nlme)
+#' endpoints(f[[1]])
#' f_nlme <- nlme(f)
#' print(f_nlme)
+#' endpoints(f_nlme)
#' f_nlme_2 <- nlme(f, start = c(parent_0 = 100, log_k_parent_sink = 0.1))
#' update(f_nlme_2, random = parent_0 ~ 1)
#' \dontrun{
@@ -77,6 +79,9 @@
#'
#' anova(f_nlme_dfop_sfo, f_nlme_fomc_sfo, f_nlme_sfo_sfo)
#' anova(f_nlme_dfop_sfo, f_nlme_sfo_sfo) # if we ignore FOMC
+#'
+#' endpoints(f_nlme_sfo_sfo)
+#' endpoints(f_nlme_dfop_sfo)
#' }
# Code inspired by nlme.nlsList
nlme.mmkin <- function(model, data = sys.frame(sys.parent()),
diff --git a/docs/news/index.html b/docs/news/index.html
index 5fd97344..cb18664e 100644
--- a/docs/news/index.html
+++ b/docs/news/index.html
@@ -134,7 +134,7 @@
mkin 0.9.49.10 (unreleased) Unreleased
-‘nlme.mmkin’: An nlme method for mmkin row objects and an associated class with plot method
+‘nlme.mmkin’: An nlme method for mmkin row objects and an associated S3 class with print, plot, anova and endpoint methods
‘mean_degparms, nlme_data, nlme_function’: Three new functions to facilitate building nlme models from mmkin row objects
‘endpoints’: Don’t return the SFORB list component if it’s empty. This reduces distraction and complies with the documentation
Article in compiled models: Add some platform specific code and suppress warnings about zero values being removed from the FOCUS D dataset
diff --git a/docs/reference/endpoints.html b/docs/reference/endpoints.html
index 68af5fcf..ef38c521 100644
--- a/docs/reference/endpoints.html
+++ b/docs/reference/endpoints.html
@@ -154,13 +154,17 @@ advantage that the SFORB model can also be used for metabolites.
fit |
- An object of class mkinfit . |
+ An object of class mkinfit or
+nlme.mmkin |
Value
- A list with the components mentioned above.
+ A list with a matrix of dissipation times named distimes,
+ and, if applicable, a vector of formation fractions named ff
+ and, if the SFORB model was in use, a vector of eigenvalues
+ of these SFORB models, equivalent to DFOP rate constants
Note
The function is used internally by summary.mkinfit
.
@@ -168,13 +172,24 @@ advantage that the SFORB model can also be used for metabolites.
Examples
#> $ff
-#> logical(0)
-#>
-#> $distimes
+ endpoints(fit)
#> $distimes
#> DT50 DT90 DT50back
#> parent 1.785233 15.1479 4.559973
-#>
+#>
#> $ff
+#> parent_free_sink
+#> 1
+#>
+#> $SFORB
+#> parent_b1 parent_b2
+#> 0.4595574 0.0178488
+#>
+#> $distimes
+#> DT50 DT90 DT50_parent_b1 DT50_parent_b2
+#> parent 1.886925 21.25106 1.508293 38.83438
+#>
# }
+
#> $distimes
+#> DT50 DT90
+#> parent 11.96183 39.73634
+#>
#> Nonlinear mixed-effects model fit by maximum likelihood
#> Model: value ~ deg_func(name, time, parent_0, log_k_parent_sink)
#> Data: "Not shown"
@@ -270,7 +273,10 @@ parameters taken from the mmkin object are used
#> StdDev: 1.30857 1.288591 6.304906
#>
#> Number of Observations: 90
-#> Number of Groups: 5
#> $distimes
+#> DT50 DT90
+#> parent 17.51545 58.18505
+#>
#> Nonlinear mixed-effects model fit by maximum likelihood
#> Model: value ~ deg_func(name, time, parent_0, log_k_parent_sink)
#> Data: "Not shown"
@@ -410,7 +416,24 @@ parameters taken from the mmkin object are used
#> f_nlme_fomc_sfo 2 11 818.5149 853.0087 -398.2575 1 vs 2 21.33913 <.0001
#> f_nlme_sfo_sfo 3 9 1085.1821 1113.4042 -533.5910 2 vs 3 270.66712 <.0001
#> Model df AIC BIC logLik Test L.Ratio p-value
#> f_nlme_dfop_sfo 1 13 843.8541 884.6194 -408.927
-#> f_nlme_sfo_sfo 2 9 1085.1821 1113.4042 -533.591 1 vs 2 249.328 <.0001
# }
+#> f_nlme_sfo_sfo 2 9 1085.1821 1113.4042 -533.591 1 vs 2 249.328 <.0001
#> $ff
+#> parent_sink parent_A1 A1_sink
+#> 0.5912435 0.4087565 1.0000000
+#>
+#> $distimes
+#> DT50 DT90
+#> parent 19.13517 63.56565
+#> A1 66.02149 219.31865
+#>
#> $ff
+#> parent_A1 parent_sink A1_sink
+#> 0.2768571 0.7231429 1.0000000
+#>
+#> $distimes
+#> DT50 DT90 DT50_k1 DT50_k2
+#> parent 11.07092 104.6325 4.462389 46.2085
+#> A1 162.30937 539.1801 NA NA
+#>
# }