diff options
| -rw-r--r-- | DESCRIPTION | 2 | ||||
| -rw-r--r-- | R/mkinfit.R | 4 | ||||
| -rw-r--r-- | R/mkinmod.R | 60 | ||||
| -rw-r--r-- | R/mkinpredict.R | 9 | ||||
| -rw-r--r-- | man/mkinmod.Rd | 27 | ||||
| -rw-r--r-- | test.log | 12 | ||||
| -rw-r--r-- | vignettes/mkin.html | 4 | 
7 files changed, 67 insertions, 51 deletions
| diff --git a/DESCRIPTION b/DESCRIPTION index 0953d07e..f1e4f169 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -17,7 +17,7 @@ Description: Calculation routines based on the FOCUS Kinetics Report (2006,    note that no warranty is implied for correctness of results or fitness for a    particular purpose.  Depends: R (>= 2.15.1), parallel -Imports: stats, graphics, methods, deSolve, R6, inline (>= 0.3.17), numDeriv, +Imports: stats, graphics, methods, deSolve, R6, inline (>= 0.3.16.2), numDeriv,    lmtest, pkgbuild, nlme (>= 3.1-150.1), purrr, saemix (>= 3.1.9000)  Suggests: knitr, rbenchmark, tikzDevice, testthat, rmarkdown, covr, vdiffr,    benchmarkme, tibble, stats4 diff --git a/R/mkinfit.R b/R/mkinfit.R index e482285d..a6efc858 100644 --- a/R/mkinfit.R +++ b/R/mkinfit.R @@ -479,10 +479,6 @@ mkinfit <- function(mkinmod, observed,        solution_type = "analytical"      } else {        if (!is.null(mkinmod$cf) & use_compiled[1] != FALSE) { -        try_dynlib <- try(inline::getDynLib(mkinmod$cf)[["path"]]) -        if (inherits(try_dynlib, "try-error")) { -          mkinmod$cf <- inline::readDynLib(mkinmod$cf_name, mkinmod$cf_dir) -        }          solution_type = "deSolve"        } else {          if (is.matrix(mkinmod$coefmat)) { diff --git a/R/mkinmod.R b/R/mkinmod.R index 434282fd..a7353e81 100644 --- a/R/mkinmod.R +++ b/R/mkinmod.R @@ -11,6 +11,7 @@  #' of the system of differential equations is included in the resulting  #' mkinmod object in some cases, speeding up the solution.  #' +#' If a C compiler is found by [pkgbuild::has_compiler()] and there  #' is more than one observed variable in the specification, C code is generated  #' for evaluating the differential equations, compiled using  #' [inline::cfunction()] and added to the resulting mkinmod object. @@ -34,15 +35,21 @@  #'   formation fractions are always used (default).  If "min", a minimum use of  #'   formation fractions is made, i.e. each pathway to a metabolite has its  #'   own rate constant. -#' @param name A name for the model. Should be a valid R object name.  #' @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 [inline::cfunction()] if  #'   applicable to give detailed information about the C function being built. -#' @param cf_dir Directory where CFunc objects should be saved. Specifying -#'   'cf_dir' without specifying a 'name' for the object is an error. +#' @param name A name for the model. Should be a valid R object name. +#' @param dll_dir Directory where an DLL object, if generated internally by +#'   [inline::cfunction()], should be saved.  The DLL will only be stored in a +#'   permanent location for use in future sessions, if 'dll_dir' and 'name' +#'   are specified. +#' @param unload If a DLL from the target location in 'dll_dir' is already +#'   loaded, should that be unloaded first? +#' @param overwrite If a file exists at the target DLL location in 'dll_dir', +#'   should this be overwritten?  #' @importFrom methods signature  #' @return A list of class \code{mkinmod} for use with [mkinfit()],  #'   containing, among others, @@ -95,12 +102,20 @@  #' \dontrun{  #'  fit_sfo_sfo <- mkinfit(SFO_SFO, FOCUS_2006_D, quiet = TRUE, solution_type = "deSolve")  #' -#'  # Now supplying full names used for plotting, and write to user defined location +#'  # Now supplying compound names used for plotting, and write to user defined location +#'  # We need to choose a path outside the session tempdir because this gets removed +#'  DLL_dir <- "~/.local/share/mkin" +#'  if (!dir.exists(DLL_dir)) dir.create(DLL_dir)  #'  SFO_SFO.2 <- mkinmod(  #'    parent = mkinsub("SFO", "m1", full_name = "Test compound"),  #'    m1 = mkinsub("SFO", full_name = "Metabolite M1"), -#'    name = "SFOSFO", cf_dir = tempdir()) -#' fit_sfo_sfo <- mkinfit(SFO_SFO.2, FOCUS_2006_D, quiet = TRUE, solution_type = "deSolve") +#'    name = "SFO_SFO", dll_dir = DLL_dir, unload = TRUE, overwrite = TRUE) +#' # Now we can save the model and restore it in a new session +#' saveRDS(SFO_SFO.2, file = "~/SFO_SFO.rds") +#' # Terminate the R session here if you would like to check, and then do +#' library(mkin) +#' SFO_SFO.3 <- readRDS("~/SFO_SFO.rds") +#' fit_sfo_sfo <- mkinfit(SFO_SFO.3, FOCUS_2006_D, quiet = TRUE, solution_type = "deSolve")  #'  #' # Show details of creating the C function  #' SFO_SFO <- mkinmod( @@ -126,15 +141,17 @@  #'  #' @export mkinmod  mkinmod <- function(..., use_of_ff = "max", name = NULL, -  speclist = NULL, quiet = FALSE, verbose = FALSE, cf_dir = NULL) +  speclist = NULL, quiet = FALSE, verbose = FALSE, dll_dir = NULL, +  unload = FALSE, overwrite = FALSE)  {    if (is.null(speclist)) spec <- list(...)    else spec <- speclist    obs_vars <- names(spec) -  if (!is.null(cf_dir)) { -    if (!dir.exists(cf_dir)) stop(cf_dir, " does not exist") -    if (is.null(name)) stop("You must give a name if you want to use 'cf_dir'") +  save_msg <- "You need to specify both 'name' and 'dll_dir' to save a model DLL" +  if (!is.null(dll_dir)) { +    if (!dir.exists(dll_dir)) stop(dll_dir, " does not exist") +    if (is.null(name)) stop(save_msg)    }    # Check if any of the names of the observed variables contains any other @@ -310,7 +327,7 @@ mkinmod <- function(..., use_of_ff = "max", name = NULL,      } #}}}    } #}}} -  model <- list(diffs = diffs, parms = parms, map = map, spec = spec, use_of_ff = use_of_ff) +  model <- list(diffs = diffs, parms = parms, map = map, spec = spec, use_of_ff = use_of_ff, name = name)    # Create coefficient matrix if possible #{{{    if (mat) { @@ -438,26 +455,19 @@ mkinmod <- function(..., use_of_ff = "max", name = NULL,        "}\n\n")      # Try to build a shared library -    cf <- try(inline::cfunction(derivs_sig, derivs_code, +    model$cf <- try(inline::cfunction(derivs_sig, derivs_code,        otherdefs = initpar_code, -      verbose = verbose, +      verbose = verbose, name = "diffs",        convention = ".C", language = "C"),        silent = TRUE) -    if (!inherits(cf, "try-error")) { -      if (is.null(cf_dir)) { -        model$cf <- cf +    if (!inherits(model$cf, "try-error")) { +      if (is.null(dll_dir)) {          if (!quiet) message("Temporary DLL for differentials generated and loaded") +        dll_info <- inline::getDynLib(model$cf)        } else { -        cf_file <- inline::writeDynLib(cf, name, cf_dir) -        model$cf <- inline::readDynLib(name, cf_dir) -        model$cf_name <- name -        model$cf_dir <- cf_dir -        fileDLL <- inline::getDynLib(model$cf)[["path"]] -        if (!quiet) { -          message("CFunc object written to ", cf_file) -          message("DLL written to ", fileDLL) -        } +        dll_info <- inline::moveDLL(model$cf, name, dll_dir, +          unload = unload, overwrite = overwrite, verbose = !quiet)        }      }    } diff --git a/R/mkinpredict.R b/R/mkinpredict.R index a294a114..277c3604 100644 --- a/R/mkinpredict.R +++ b/R/mkinpredict.R @@ -169,18 +169,13 @@ mkinpredict.mkinmod <- function(x,    if (solution_type == "deSolve") {      if (!is.null(x$cf) & use_compiled[1] != FALSE) { -      DLL <- try(inline::getDynLib(x$cf)) -      if (inherits(DLL, "try-error")) { -        x$cf <- inline::readDynLib(x$cf_name, x$cf_dir) -      } -      cf_env <- environment(x$cf)        out <- deSolve::ode(          y = odeini,          times = outtimes, -        func = cf_env$name, +        func = "diffs",          initfunc = "initpar", -        dllname = cf_env$f, +        dllname = inline::getDynLib(x$cf)[["name"]],          parms = odeparms[x$parms], # Order matters when using compiled models          method = method.ode,          atol = atol, diff --git a/man/mkinmod.Rd b/man/mkinmod.Rd index f71ebfb3..77319aac 100644 --- a/man/mkinmod.Rd +++ b/man/mkinmod.Rd @@ -13,7 +13,9 @@ mkinmod(    speclist = NULL,    quiet = FALSE,    verbose = FALSE, -  cf_dir = NULL +  dll_dir = NULL, +  unload = FALSE, +  overwrite = FALSE  )  \method{print}{mkinmod}(x, ...) @@ -53,8 +55,16 @@ argument. Default is NULL.}  \item{verbose}{If \code{TRUE}, passed to \code{\link[inline:cfunction]{inline::cfunction()}} if  applicable to give detailed information about the C function being built.} -\item{cf_dir}{Directory where CFunc objects should be saved. Specifying -'cf_dir' without specifying a 'name' for the object is an error.} +\item{dll_dir}{Directory where an DLL object, if generated internally by +\code{\link[inline:cfunction]{inline::cfunction()}}, should be saved.  The DLL will only be stored in a +permanent location for use in future sessions, if 'dll_dir' and 'name' +are specified.} + +\item{unload}{If a DLL from the target location in 'dll_dir' is already +loaded, should that be unloaded first?} + +\item{overwrite}{If a file exists at the target DLL location in 'dll_dir', +should this be overwritten?}  \item{x}{An \code{\link{mkinmod}} object.} @@ -120,6 +130,7 @@ For kinetic models with more than one observed variable, a symbolic solution  of the system of differential equations is included in the resulting  mkinmod object in some cases, speeding up the solution. +If a C compiler is found by \code{\link[pkgbuild:has_compiler]{pkgbuild::has_compiler()}} and there  is more than one observed variable in the specification, C code is generated  for evaluating the differential equations, compiled using  \code{\link[inline:cfunction]{inline::cfunction()}} and added to the resulting mkinmod object. @@ -143,12 +154,16 @@ print(SFO_SFO)  \dontrun{   fit_sfo_sfo <- mkinfit(SFO_SFO, FOCUS_2006_D, quiet = TRUE, solution_type = "deSolve") - # Now supplying full names used for plotting, and write to user defined location + # Now supplying compound names used for plotting, and write to user defined location   SFO_SFO.2 <- mkinmod(     parent = mkinsub("SFO", "m1", full_name = "Test compound"),     m1 = mkinsub("SFO", full_name = "Metabolite M1"), -   name = "SFOSFO", cf_dir = tempdir()) -fit_sfo_sfo <- mkinfit(SFO_SFO.2, FOCUS_2006_D, quiet = TRUE, solution_type = "deSolve") +   name = "SFO_SFO", dll_dir = "~/dll", unload = TRUE, overwrite = TRUE) +# Now we can save the model and restore it in a new session +saveRDS(SFO_SFO.2, file = "~/SFO_SFO.rds") +# Terminate the R session here if you would like to check, and then do +SFO_SFO.3 <- readRDS("~/SFO_SFO.rds") +fit_sfo_sfo <- mkinfit(SFO_SFO.3, FOCUS_2006_D, quiet = TRUE, solution_type = "deSolve")  # Show details of creating the C function  SFO_SFO <- mkinmod( @@ -6,8 +6,8 @@ Testing mkin  ✔ |   2       | Export dataset for reading into CAKE  ✔ |  14       | Results for FOCUS D established in expertise for UBA (Ranke 2014) [0.9 s]  ✔ |   4       | Calculation of FOCUS chi2 error levels [0.4 s] -✔ |   7       | Fitting the SFORB model [3.4 s] -✔ |   5       | Analytical solutions for coupled models [3.1 s] +✔ |   7       | Fitting the SFORB model [3.2 s] +✔ |   5       | Analytical solutions for coupled models [2.9 s]  ✔ |   5       | Calculation of Akaike weights  ✔ |  10       | Confidence intervals and p-values [1.0 s]  ✔ |  14       | Error model fitting [4.3 s] @@ -33,15 +33,15 @@ Skip (test_plot.R:25:3): Plotting mkinfit and mmkin objects is reproducible  Reason: getRversion() < "4.1.0"  is TRUE  ────────────────────────────────────────────────────────────────────────────────  ✔ |   4       | Residuals extracted from mkinfit models -✔ |   2       | Complex test case from Schaefer et al. (2007) Piacenza paper [1.5 s] +✔ |   2       | Complex test case from Schaefer et al. (2007) Piacenza paper [1.4 s]  ✔ |   4       | Summary [0.1 s]  ✔ |   1       | Summaries of old mkinfit objects -✔ |   4       | Results for synthetic data established in expertise for UBA (Ranke 2014) [2.2 s] -✔ |   9       | Hypothesis tests [7.1 s] +✔ |   4       | Results for synthetic data established in expertise for UBA (Ranke 2014) [2.0 s] +✔ |   9       | Hypothesis tests [6.4 s]  ✔ |   4       | Calculation of maximum time weighted average concentrations (TWAs) [2.4 s]  ══ Results ═════════════════════════════════════════════════════════════════════ -Duration: 38.5 s +Duration: 36.9 s  ── Skipped tests  ──────────────────────────────────────────────────────────────  ● getRversion() < "4.1.0"  is TRUE (3) diff --git a/vignettes/mkin.html b/vignettes/mkin.html index 43481d8f..1f696c37 100644 --- a/vignettes/mkin.html +++ b/vignettes/mkin.html @@ -11,7 +11,7 @@  <meta name="author" content="Johannes Ranke" /> -<meta name="date" content="2020-11-24" /> +<meta name="date" content="2020-11-27" />  <title>Introduction to mkin</title> @@ -1631,7 +1631,7 @@ div.tocify {  <h1 class="title toc-ignore">Introduction to mkin</h1>  <h4 class="author">Johannes Ranke</h4> -<h4 class="date">2020-11-24</h4> +<h4 class="date">2020-11-27</h4>  </div> | 
