From 6308e7d7898d4f064d321d97d162c6752c22b362 Mon Sep 17 00:00:00 2001 From: Johannes Ranke Date: Mon, 11 May 2020 15:00:25 +0200 Subject: Add analytical solution for DFOP-SFO This is about twice as fast as deSolve compiled in the case of FOCUS D --- DESCRIPTION | 4 ++-- NEWS.md | 2 ++ R/create_deg_func.R | 24 +++++++++++++++++++++++- build.log | 2 +- check.log | 5 +++-- docs/404.html | 2 +- docs/articles/index.html | 2 +- docs/authors.html | 2 +- docs/index.html | 2 +- docs/news/index.html | 3 ++- docs/pkgdown.yml | 2 +- docs/reference/create_deg_func.html | 16 +++++++++++++--- docs/reference/index.html | 2 +- man/create_deg_func.Rd | 9 ++++++++- test.log | 16 ++++++++-------- tests/testthat/setup_script.R | 11 +++++++---- tests/testthat/test_analytical.R | 14 +++++++++++++- 17 files changed, 88 insertions(+), 30 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 5f38d12c..0facf77e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Package: mkin Type: Package Title: Kinetic Evaluation of Chemical Degradation Data -Version: 0.9.50 -Date: 2020-05-07 +Version: 0.9.50.1 +Date: 2020-05-11 Authors@R: c(person("Johannes", "Ranke", role = c("aut", "cre", "cph"), email = "jranke@uni-bremen.de", comment = c(ORCID = "0000-0003-4371-6538")), diff --git a/NEWS.md b/NEWS.md index 2512f361..49828447 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,8 @@ - 'mkinmod': Make 'use_of_ff' = "max" the default +- Improve performance by a) avoiding expensive calls in the cost function like merge() and data.frame(), and b) by implementing analytical solutions for SFO-SFO and DFOP-SFO + # mkin 0.9.49.11 (2020-04-20) - Increase a test tolerance to make it pass on all CRAN check machines diff --git a/R/create_deg_func.R b/R/create_deg_func.R index 11559799..b29a11f7 100644 --- a/R/create_deg_func.R +++ b/R/create_deg_func.R @@ -16,7 +16,14 @@ #' benchmark( #' analytical = mkinfit(SFO_SFO, FOCUS_D, solution_type = "analytical", quiet = TRUE), #' deSolve = mkinfit(SFO_SFO, FOCUS_D, solution_type = "deSolve", quiet = TRUE), -#' replications = 1) +#' replications = 2) +#' DFOP_SFO <- mkinmod( +#' parent = mkinsub("DFOP", "m1"), +#' m1 = mkinsub("SFO")) +#' benchmark( +#' analytical = mkinfit(DFOP_SFO, FOCUS_D, solution_type = "analytical", quiet = TRUE), +#' deSolve = mkinfit(DFOP_SFO, FOCUS_D, solution_type = "deSolve", quiet = TRUE), +#' replications = 2) #' } create_deg_func <- function(spec, use_of_ff = c("min", "max")) { @@ -94,6 +101,21 @@ create_deg_func <- function(spec, use_of_ff = c("min", "max")) { "(((", k2, "-", k12, "-", k10, ")*", n20, "-", k12, "*", n10, ")*exp(-", k2, "*t)+", k12, "*", n10, "*exp(-(", k_parent, ")*t))/(", k2, "-(", k_parent, "))") } + + # dfop_f12_sfo + if (all(use_of_ff == "max", spec[[1]]$sink == TRUE, length(obs_vars) == 2, + spec[[1]]$type == "DFOP", spec[[2]]$type == "SFO")) { + supported <- TRUE + f12 <- paste0("f_", n1, "_to_", n2) + k2 <- paste0("k_", n2) + predicted_text[n2] <- paste0( + "((", f12, "* g - ", f12, ") * k2 * ", n10, " * exp(- k2 * t))/(k2 - ", k2, ") - ", + "((", f12, "* g) * k1 * ", n10, " * exp(- k1 * t))/(k1 - ", k2, ") + ", + "(((k1 - ", k2, ") * k2 - ", k2, "* k1 + ", k2, "^2) * ", n20, "+", + "((", f12, "* k1 + (", f12, "*g - ", f12, ") * ", k2, ") * k2 - ", f12, " * g * ", k2, " * k1) * ", n10, ") * ", + "exp( - ", k2, " * t)/((k1 - ", k2, ") * k2 - ", k2, " * k1 + ", k2, "^2)") + } + } diff --git a/build.log b/build.log index b3df3235..4c64021a 100644 --- a/build.log +++ b/build.log @@ -5,5 +5,5 @@ * creating vignettes ... OK * checking for LF line-endings in source and make files and shell scripts * checking for empty or unneeded directories -* building ‘mkin_0.9.50.tar.gz’ +* building ‘mkin_0.9.50.1.tar.gz’ diff --git a/check.log b/check.log index 8064f9a6..99cb6f86 100644 --- a/check.log +++ b/check.log @@ -1,11 +1,11 @@ * using log directory ‘/home/jranke/git/mkin/mkin.Rcheck’ -* using R Under development (unstable) (2020-05-10 r78402) +* using R version 4.0.0 (2020-04-24) * using platform: x86_64-pc-linux-gnu (64-bit) * using session charset: UTF-8 * using options ‘--no-tests --as-cran’ * checking for file ‘mkin/DESCRIPTION’ ... OK * checking extension type ... Package -* this is package ‘mkin’ version ‘0.9.50’ +* this is package ‘mkin’ version ‘0.9.50.1’ * package encoding: UTF-8 * checking CRAN incoming feasibility ... Note_to_CRAN_maintainers Maintainer: ‘Johannes Ranke ’ @@ -35,6 +35,7 @@ Maintainer: ‘Johannes Ranke ’ * checking whether the package can be unloaded cleanly ... OK * checking whether the namespace can be loaded with stated dependencies ... OK * checking whether the namespace can be unloaded cleanly ... OK +* checking loading without being on the library search path ... OK * checking use of S3 registration ... OK * checking dependencies in R code ... OK * checking S3 generic/method consistency ... OK diff --git a/docs/404.html b/docs/404.html index c6da911d..afb82b3f 100644 --- a/docs/404.html +++ b/docs/404.html @@ -71,7 +71,7 @@ mkin - 0.9.50 + 0.9.50.1 diff --git a/docs/articles/index.html b/docs/articles/index.html index 7091d4c9..5179c1bc 100644 --- a/docs/articles/index.html +++ b/docs/articles/index.html @@ -71,7 +71,7 @@ mkin - 0.9.50 + 0.9.50.1 diff --git a/docs/authors.html b/docs/authors.html index bc170e49..5ec134d6 100644 --- a/docs/authors.html +++ b/docs/authors.html @@ -71,7 +71,7 @@ mkin - 0.9.50 + 0.9.50.1 diff --git a/docs/index.html b/docs/index.html index 5c4a0a9b..37ed972a 100644 --- a/docs/index.html +++ b/docs/index.html @@ -37,7 +37,7 @@ mkin - 0.9.50 + 0.9.50.1 diff --git a/docs/news/index.html b/docs/news/index.html index 1e13041d..3965df70 100644 --- a/docs/news/index.html +++ b/docs/news/index.html @@ -71,7 +71,7 @@ mkin - 0.9.50 + 0.9.50.1 @@ -145,6 +145,7 @@
  • Support SFORB with formation fractions

  • ‘mkinmod’: Make ‘use_of_ff’ = “max” the default

  • +
  • Improve performance by a) avoiding expensive calls in the cost function like merge() and data.frame(), and b) by implementing analytical solutions for SFO-SFO and DFOP-SFO

diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml index b3cd3d30..aa796e47 100644 --- a/docs/pkgdown.yml +++ b/docs/pkgdown.yml @@ -10,7 +10,7 @@ articles: NAFTA_examples: web_only/NAFTA_examples.html benchmarks: web_only/benchmarks.html compiled_models: web_only/compiled_models.html -last_built: 2020-05-11T03:18Z +last_built: 2020-05-11T13:20Z urls: reference: https://pkgdown.jrwb.de/mkin/reference article: https://pkgdown.jrwb.de/mkin/articles diff --git a/docs/reference/create_deg_func.html b/docs/reference/create_deg_func.html index 67016be0..6d05e811 100644 --- a/docs/reference/create_deg_func.html +++ b/docs/reference/create_deg_func.html @@ -175,9 +175,19 @@ benchmark( analytical = mkinfit(SFO_SFO, FOCUS_D, solution_type = "analytical", quiet = TRUE), deSolve = mkinfit(SFO_SFO, FOCUS_D, solution_type = "deSolve", quiet = TRUE), - replications = 1)
#> Lade nötiges Paket: rbenchmark
#> test replications elapsed relative user.self sys.self user.child -#> 1 analytical 1 0.198 1.000 0.198 0.000 0 -#> 2 deSolve 1 0.350 1.768 0.348 0.001 0 + replications = 2)
#> Lade nötiges Paket: rbenchmark
#> test replications elapsed relative user.self sys.self user.child +#> 1 analytical 2 0.395 1.000 0.393 0.002 0 +#> 2 deSolve 2 0.693 1.754 0.692 0.000 0 +#> sys.child +#> 1 0 +#> 2 0
DFOP_SFO <- mkinmod( + parent = mkinsub("DFOP", "m1"), + m1 = mkinsub("SFO"))
#> Successfully compiled differential equation model from auto-generated C code.
benchmark( + analytical = mkinfit(DFOP_SFO, FOCUS_D, solution_type = "analytical", quiet = TRUE), + deSolve = mkinfit(DFOP_SFO, FOCUS_D, solution_type = "deSolve", quiet = TRUE), + replications = 2)
#> test replications elapsed relative user.self sys.self user.child +#> 1 analytical 2 0.870 1.000 0.870 0 0 +#> 2 deSolve 2 1.678 1.929 1.677 0 0 #> sys.child #> 1 0 #> 2 0
# } diff --git a/docs/reference/index.html b/docs/reference/index.html index 7e7fff29..ed6debdd 100644 --- a/docs/reference/index.html +++ b/docs/reference/index.html @@ -71,7 +71,7 @@ mkin - 0.9.50 + 0.9.50.1
diff --git a/man/create_deg_func.Rd b/man/create_deg_func.Rd index 178661ff..69058038 100644 --- a/man/create_deg_func.Rd +++ b/man/create_deg_func.Rd @@ -30,6 +30,13 @@ if (require(rbenchmark)) benchmark( analytical = mkinfit(SFO_SFO, FOCUS_D, solution_type = "analytical", quiet = TRUE), deSolve = mkinfit(SFO_SFO, FOCUS_D, solution_type = "deSolve", quiet = TRUE), - replications = 1) + replications = 2) + DFOP_SFO <- mkinmod( + parent = mkinsub("DFOP", "m1"), + m1 = mkinsub("SFO")) + benchmark( + analytical = mkinfit(DFOP_SFO, FOCUS_D, solution_type = "analytical", quiet = TRUE), + deSolve = mkinfit(DFOP_SFO, FOCUS_D, solution_type = "deSolve", quiet = TRUE), + replications = 2) } } diff --git a/test.log b/test.log index f2f9ff85..54f61d9b 100644 --- a/test.log +++ b/test.log @@ -4,19 +4,19 @@ Testing mkin ✔ | 2 | Export dataset for reading into CAKE ✔ | 13 | Results for FOCUS D established in expertise for UBA (Ranke 2014) [1.1 s] ✔ | 4 | Calculation of FOCUS chi2 error levels [0.4 s] -✔ | 7 | Fitting the SFORB model [3.4 s] -✔ | 4 | Analytical solutions for coupled models [1.7 s] +✔ | 7 | Fitting the SFORB model [3.2 s] +✔ | 5 | Analytical solutions for coupled models [3.0 s] ✔ | 5 | Calculation of Akaike weights ✔ | 10 | Confidence intervals and p-values [1.0 s] -✔ | 14 | Error model fitting [4.0 s] +✔ | 14 | Error model fitting [3.8 s] ✔ | 4 | Test fitting the decline of metabolites from their maximum [0.2 s] ✔ | 1 | Fitting the logistic model [0.2 s] ✔ | 1 | Test dataset class mkinds used in gmkin ✔ | 12 | Special cases of mkinfit calls [0.6 s] ✔ | 8 | mkinmod model generation and printing [0.2 s] -✔ | 3 | Model predictions with mkinpredict [0.4 s] +✔ | 3 | Model predictions with mkinpredict [0.3 s] ✔ | 16 | Evaluations according to 2015 NAFTA guidance [1.4 s] -✔ | 9 | Nonlinear mixed-effects models [7.6 s] +✔ | 9 | Nonlinear mixed-effects models [7.5 s] ✔ | 4 | Calculation of maximum time weighted average concentrations (TWAs) [2.4 s] ✔ | 3 | Summary ✔ | 14 | Plotting [1.4 s] @@ -24,13 +24,13 @@ Testing mkin ✔ | 4 | Residuals extracted from mkinfit models ✔ | 2 | Complex test case from Schaefer et al. (2007) Piacenza paper [1.4 s] ✔ | 1 | Summaries of old mkinfit objects -✔ | 4 | Results for synthetic data established in expertise for UBA (Ranke 2014) [2.3 s] +✔ | 4 | Results for synthetic data established in expertise for UBA (Ranke 2014) [2.4 s] ✔ | 9 | Hypothesis tests [6.5 s] ══ Results ═════════════════════════════════════════════════════════════════════ -Duration: 36.4 s +Duration: 37.3 s -OK: 158 +OK: 159 Failed: 0 Warnings: 0 Skipped: 0 diff --git a/tests/testthat/setup_script.R b/tests/testthat/setup_script.R index 58e328cd..def52697 100644 --- a/tests/testthat/setup_script.R +++ b/tests/testthat/setup_script.R @@ -40,16 +40,19 @@ fits <- mmkin(models, # One metabolite SFO_SFO <- mkinmod(parent = mkinsub("SFO", to = "m1"), - m1 = mkinsub("SFO"), - use_of_ff = "min", quiet = TRUE) + m1 = mkinsub("SFO"), + use_of_ff = "min", quiet = TRUE) SFO_SFO.ff <- mkinmod(parent = mkinsub("SFO", to = "m1"), - m1 = mkinsub("SFO"), - use_of_ff = "max", quiet = TRUE) + m1 = mkinsub("SFO"), + use_of_ff = "max", quiet = TRUE) SFO_SFO.ff.nosink <- mkinmod( parent = mkinsub("SFO", "m1", sink = FALSE), m1 = mkinsub("SFO"), quiet = TRUE, use_of_ff = "max") FOMC_SFO <- mkinmod(parent = mkinsub("FOMC", to = "m1"), m1 = mkinsub("SFO"), quiet = TRUE) +DFOP_SFO <- mkinmod(parent = mkinsub("DFOP", to = "m1"), + m1 = mkinsub("SFO"), + use_of_ff = "max", quiet = TRUE) # Avoid warning when fitting a dataset where zero value is removed FOCUS_D <- subset(FOCUS_2006_D, value != 0) diff --git a/tests/testthat/test_analytical.R b/tests/testthat/test_analytical.R index 5972a18a..578258d3 100644 --- a/tests/testthat/test_analytical.R +++ b/tests/testthat/test_analytical.R @@ -1,6 +1,6 @@ context("Analytical solutions for coupled models") -test_that("The analytical solutions of SFO-SFO are correct", { +test_that("The analytical solutions for SFO-SFO are correct", { # No sink, no formation fractions SFO_SFO_nosink <- mkinmod( parent = mkinsub("SFO", to = "m1", sink = FALSE), @@ -44,3 +44,15 @@ test_that("The analytical solutions of SFO-SFO are correct", { ) }) + +test_that("The analytical solution for DFOP-SFO are correct", { + # With formation fraction + f_dfop_sfo_analytical <- mkinfit(DFOP_SFO, FOCUS_D, + solution_type = "analytical", quiet = TRUE) + f_dfop_sfo_desolve <- mkinfit(DFOP_SFO, FOCUS_D, + solution_type = "deSolve", quiet = TRUE) + expect_equal( + parms(f_dfop_sfo_analytical), + parms(f_dfop_sfo_desolve) + ) +}) -- cgit v1.2.1