diff --git a/DESCRIPTION b/DESCRIPTION
index a40a74ed2..e6c7995b1 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,7 +1,7 @@
Type: Package
Package: mrgsolve
Title: Simulate from ODE-Based Models
-Version: 0.11.1
+Version: 0.11.2
Authors@R:
c(person(given = "Kyle T", family = "Baron",
role = c("aut", "cre"),
diff --git a/NEWS.md b/NEWS.md
index 2546d1dfd..61820f83b 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,3 +1,23 @@
+# mrgsolve 0.11.2
+
+- In `pk2iv`, change scaling volume for `CENT` from `V2` (incorrect) to
+ `V1` (#831, #832, #833)
+
+- Fix bug collating multiple `$OMEGA` or `$SIGMA` matrices when parsing a
+ model (#863)
+
+- Refactor how debugging information is processed when using the `recover`
+ argument to `mread()` (#853)
+
+- Fix typo in documentation for `as_cmat()`; the off-diagonals are assumed
+ to contain correlations (#856)
+
+- Wrote a `as.data.frame.matrix()` function in Rcpp; all simulation results
+ return from the C++ simulation code as a data frame (#857)
+
+- Fix bug where dynamic capture (via `mread()`) was not allowed for variables
+ declared in `$GLOBAL` (#868)
+
# mrgsolve 0.11.1
- `mrgsim()` will now periodically check for user interrupt signal so that
diff --git a/R/class_build.R b/R/class_build.R
index 0c13dd9ce..fcf5aeb39 100644
--- a/R/class_build.R
+++ b/R/class_build.R
@@ -209,20 +209,26 @@ build_output_cleanup <- function(x,build) {
patt <- "^ *In function .*void _model.*:$"
errr <- msub(pattern = patt, replacement = "", x = errr)
x[["stderr"]] <- errr
- x <- structure(x, class = "mrgsolve-build-error")
+ x <- structure(x, class = c("mrgsolve-build-error", "list"))
x
}
-
-build_failed <- function(out,build,mod,ignore.stdout) {
- outt <- list(out)
- names(outt) <- paste0("mrgsolve.build.", build[["model"]])
- options(outt)
+build_failed <- function(out,build,mod,spec,ignore.stdout) {
out <- build_output_cleanup(out,build)
- if(build[["recover"]]) {
+ if(isTRUE(build[["recover"]])) {
warning("returning object for debugging purposes only.")
- ans <- list(build = build, mod = as.list(mod), shlib=list(compiled=FALSE), out=out)
- return(structure(ans,class = "mrgsolve-build-recover"))
+ build <- as.list(build)
+ mod <- as.list(mod)
+ mod[["envir"]] <- as.list(mod[["envir"]])
+ mod[["shlib"]][["version"]] <- unlist(mod[["shlib"]][["version"]])
+ mod[["shlib"]][["compiled"]] <- FALSE
+ ans <- list(
+ out = out,
+ build = build,
+ mod = mod,
+ spec = spec
+ )
+ return(structure(ans, class = c("mrgsolve-build-recover", "list")))
}
if(!ignore.stdout) {
msg <- divider_msg("stdout")
@@ -241,22 +247,16 @@ build_failed <- function(out,build,mod,ignore.stdout) {
stop("the model build step failed.",call.=FALSE)
}
-
-build_save_output <- function(out) {
- out[["date"]] <- date()
- path <- file.path(tempdir(), "mrgsolve-build-result.RDS")
- saveRDS(out, file=path)
- return(invisible(path))
-}
-
-build_get_output <- function() {
- file <- file.path(tempdir(),"mrgsolve-build-result.RDS")
- file <- normalizePath(file,mustWork=FALSE)
- if(!file.exists(file)) {
- message("No build output was found.")
- return(invisible(list()))
+build_format_recover <- function(data, path = NULL) {
+ if(!requireNamespace("yaml")) {
+ stop("please install the yaml package to format recovery data", call.=FALSE)
+ }
+ ans <- yaml::as.yaml(data)
+ if(is.character(path)) {
+ writeLines(text = ans, con = path)
+ return(invisible(ans))
}
- return(readRDS(file))
+ ans
}
build_handle_127 <- function(out) {
diff --git a/R/class_matlist.R b/R/class_matlist.R
index 470d55991..ab8e52015 100644
--- a/R/class_matlist.R
+++ b/R/class_matlist.R
@@ -47,7 +47,7 @@ valid.matlist <- function(object) {
}
if(!x4) {
- y <- which(sapply(object@data, det) < 0)
+ y <- which(!sapply(object@data, det) > 0)
message("Problem with this matrix:")
print(object@data[y])
out <- c(out, "Invalid matrix: determinant is less than 0.")
diff --git a/R/funset.R b/R/funset.R
index ac5d979b0..d7bcddd1c 100644
--- a/R/funset.R
+++ b/R/funset.R
@@ -19,10 +19,10 @@
FUNSET_ERROR__ <-
'
There was a problem accessing the model shared object.
- Either the model object is corrupted or the model was
+ Either the model object was corrupted or the model was
not properly compiled and/or loaded. If the model is
- not loaded, use loadso(mod) to do so. This is usually
- required for parallel simuilation on a worker node that
+ not loaded, use `loadso(mod)` to do so. This is usually
+ required for parallel simulation on a worker node that
was not forked (e.g. when using future::multisession).
Also check mrgsolve:::funset(mod) for more information.
'
diff --git a/R/matlist.R b/R/matlist.R
index 52ea03b67..fff1d7cd6 100644
--- a/R/matlist.R
+++ b/R/matlist.R
@@ -200,7 +200,6 @@ setMethod("smat", "mrgsims", function(.x,make=FALSE,...) {
as.matrix(mod(.x)@sigma)
})
-
#' Zero out random effects in a model object
#'
#' Sets all elements of the OMEGA or SIGMA matrix to zero
@@ -260,7 +259,9 @@ setMethod("as.list", "matlist", function(x, ...) x@data)
#' @rdname matlist
#' @export
setMethod("as.matrix", "matlist", function(x, ...) {
- if(length(x@data)==0) return(matrix(nrow=0,ncol=0))
+ if(length(x@data)==0) {
+ return(matrix(nrow = 0, ncol = 0))
+ }
SUPERMATRIX(x@data, ...)
})
@@ -335,13 +336,14 @@ cumoffset <- function(x) {
##' @rdname matlist_ops
##' @export
setMethod("c", "matlist", function(x,...,recursive=FALSE) {
- what <- c(list(x),list(...))
- stopifnot(all(sapply(what,is.matlist)))
+ what <- c(list(x), list(...))
+ stopifnot(all(sapply(what, is.matlist)))
+ what <- what[sapply(what, slot, name = "n") > 0]
if(length(what)==1) return(x)
- d <- lapply(what,as.matrix)
- d <- setNames(d,sapply(what,names))
+ d <- lapply(what, as.matrix)
+ d <- setNames(d, sapply(what, names))
l <- sapply(unname(what), labels)
- create_matlist(d,labels=l, class=class(x)[1])
+ create_matlist(d, labels = l, class = class(x)[1])
})
collapse_matrix <- function(x,class) {
diff --git a/R/matrix.R b/R/matrix.R
index 876188167..a8feb18de 100644
--- a/R/matrix.R
+++ b/R/matrix.R
@@ -1,5 +1,4 @@
-# Copyright (C) 2013 - 2019 Metrum Research Group, LLC
-#
+# Copyright (C) 2013 - 2021 Metrum Research Group
# This file is part of mrgsolve.
#
# mrgsolve is free software: you can redistribute it and/or modify it
@@ -15,9 +14,10 @@
# You should have received a copy of the GNU General Public License
# along with mrgsolve. If not, see .
-
-SUPERMATRIX <- function(x,keep_names=FALSE) {
- x <- .Call(`_mrgsolve_SUPERMATRIX`,x,keep_names,PACKAGE="mrgsolve")
+SUPERMATRIX <- function(x, keep_names = FALSE) {
+ stopifnot(is.list(x))
+ stopifnot(all(sapply(x, is.matrix)))
+ x <- .Call(`_mrgsolve_SUPERMATRIX`, x, keep_names, PACKAGE = "mrgsolve")
if(nrow(x) > 0 & !keep_names) {
dimnames(x) <- list(paste0(seq_len(nrow(x)), ": "), NULL)
}
@@ -132,7 +132,7 @@ Diag <- function(x) {
##' Create matrices from vector input
##'
##' @param ... matrix data
-##' @param correlation logical; if TRUE, off diagonal elements are assumed
+##' @param correlation logical; if TRUE, off-diagonal elements are assumed
##' to be correlations and converted to covariances
##' @param digits if greater than zero, matrix is passed to signif (along
##' with digits) prior to returning
@@ -192,7 +192,7 @@ dmat <- function(...) {
##' @details
##' Use \code{as_dmat} to create a diagonal matrix, \code{as_bmat}
##' to create a block matrix, and \code{as_cmat} to create a block
-##' matrix where diagonal elements are understood to be correlations
+##' matrix where off-diagonal elements are understood to be correlations
##' rather than covariances. \code{as_cmat} uses \code{as_bmat} to
##' form the matrix and then converts off-diagonal elements to
##' covariances before returning.
diff --git a/R/modspec.R b/R/modspec.R
index fde6b4720..fd9e774a5 100644
--- a/R/modspec.R
+++ b/R/modspec.R
@@ -328,7 +328,7 @@ get_c_vars2 <- function(y,context) {
if(length(regm)==0) return(data.frame())
vars <- gsub(pattern="\\s*=$", replacement = "", x = regm, perl=TRUE)
vars <- token_space(vars)
- ans <- as.data.frame(do.call(rbind,vars),stringsAsFactors = FALSE)
+ ans <- as.data.frame(do.call(rbind,vars), stringsAsFactors = FALSE)
names(ans) <- c("type", "var")
if(nrow(ans) > 0) ans$context <- context
ans
@@ -354,7 +354,12 @@ pp_defs <- function(x,context) {
code <- s_pick(x, 3)
list(
vars = vars, code = code, n = length(x),
- tab = data.frame(type = "define", var = vars, context = "global")
+ tab = data.frame(
+ type = "define",
+ var = vars,
+ context = "global",
+ stringsAsFactors = FALSE
+ )
)
}
diff --git a/R/mread.R b/R/mread.R
index ce6fab32c..4ec0d0b3a 100644
--- a/R/mread.R
+++ b/R/mread.R
@@ -48,8 +48,9 @@ NULL
#' @param quiet don't print messages when compiling
#' @param preclean logical; if \code{TRUE}, compilation artifacts are
#' cleaned up first
-#' @param recover if \code{TRUE}, an object will be returned in case
-#' the model shared object fails to build
+#' @param recover if \code{TRUE}, a list of build will be returned in case
+#' the model shared object fails to compile; use this option to and
+#' the returned object to collect information assist in debugging
#' @param capture a character vector or comma-separated string of additional
#' model variables to capture; these variables will be added to the capture
#' list for the current call to \code{\link{mread}} only
@@ -282,8 +283,7 @@ mread <- function(model, project = getOption("mrgsolve.project", getwd()),
unlist(labels(sigma)),
.eta,
.eps,
- mread.env[["move_global"]],
- mread.env[["defines"]]
+ build[["cpp_variables"]][["var"]]
)
unique(ans)
}
@@ -539,7 +539,7 @@ mread <- function(model, project = getOption("mrgsolve.project", getwd()),
if(!comp_success) {
if(ignore.stdout) message("error.\n", appendLF=FALSE)
- return(build_failed(out,build,x,ignore.stdout))
+ return(build_failed(out,build,x,spec,ignore.stdout))
}
if(ignore.stdout) {
diff --git a/R/mrgsim_q.R b/R/mrgsim_q.R
index 92e0995ad..4ef16b3a9 100644
--- a/R/mrgsim_q.R
+++ b/R/mrgsim_q.R
@@ -157,20 +157,21 @@ mrgsim_q <- function(x,
PACKAGE = "mrgsolve"
)[["data"]]
- dimnames(out) <- list(NULL, c("ID", tcol,x@cmtL,x@capL))
+ names(out) <- c("ID", tcol, x@cmtL, x@capL)
if(output=="df") {
- return(as.data.frame(out))
+ return(out)
}
+
if(output=="matrix") {
- return(out)
+ return(as.matrix(out))
}
new(
"mrgsims",
- request=x@cmtL,
- data=as.data.frame(out),
- outnames=x@capL,
- mod=x
+ request = x@cmtL,
+ data = out,
+ outnames = x@capL,
+ mod = x
)
}
diff --git a/R/mrgsolve.R b/R/mrgsolve.R
index 813286766..33d4695d0 100644
--- a/R/mrgsolve.R
+++ b/R/mrgsolve.R
@@ -637,7 +637,7 @@ do_mrgsim <- function(x,
capture.output(file=capture, append=TRUE, print(data))
capture.output(file=capture, append=TRUE, print(carry_out))
}
-
+
out <- .Call(
`_mrgsolve_DEVTRAN`,
parin,
@@ -654,11 +654,10 @@ do_mrgsim <- function(x,
PACKAGE = "mrgsolve"
)
-
# out$trannames always comes back lower case in a specific order
# need to rename to get back to requested case
# Then, rename again for user-supplied renaming
- carry.tran <- .ren.rename(rename.carry.tran,out[["trannames"]])
+ carry.tran <- .ren.rename(rename.carry.tran, out[["trannames"]])
if(tad) tcol <- c(tcol,"tad")
@@ -686,51 +685,50 @@ do_mrgsim <- function(x,
}
cnames <- new_names
}
-
- dimnames(out[["data"]]) <- list(NULL, cnames)
-
- ans <- as.data.frame.matrix(
- out[["data"]],
- stringsAsFactors = FALSE
- )
+
+ names(out[["data"]]) <- cnames
if(do_recover_data || do_recover_idata) {
if(do_recover_data) {
if(!rename.recov$identical) {
names(join_data) <- .ren.rename(rename.recov,names(join_data))
}
- ans <- left_join(ans,join_data,by=".data_row.",suffix=c("", ".recov"))
- ans$.data_row. <- NULL
+ out[["data"]] <- left_join(out[["data"]],join_data,by=".data_row.",suffix=c("", ".recov"))
+ out[["data"]][[".data_row."]] <- NULL
}
if(do_recover_idata) {
if(!rename.recov$identical) {
names(join_idata) <- .ren.rename(rename.recov,names(join_idata))
}
- ans <- left_join(ans,join_idata,by="ID",suffix=c("", ".recov"))
+ out[["data"]] <- left_join(out[["data"]],join_idata,by="ID",suffix=c("", ".recov"))
}
}
if(!is.null(output)) {
if(output=="df") {
- return(ans)
+ return(out[["data"]])
}
if(output=="matrix") {
- return(out[["data"]])
+ if(!all(sapply(out[["data"]], is.numeric))) {
+ stop("can't return matrix because non-numeric data was found.", call.=FALSE)
+ }
+ return(data.matrix(out[["data"]]))
}
}
new(
"mrgsims",
request = x@cmtL,
- data=ans,
- outnames=x@capL,
- mod=x
+ data = out[["data"]],
+ outnames = x@capL,
+ mod = x
)
}
#' Basic, simple simulation from model object
#'
-#' This is just a lighter version of [mrgsim], with fewer options. See `Details`.
+#' This is just a lighter version of [mrgsim()], with fewer options.
+#' See `Details`.
#'
#' @inheritParams mrgsim
#'
@@ -758,7 +756,7 @@ do_mrgsim <- function(x,
#'
#' out <- qsim(mod,dose)
#'
-#' @seealso [mrgsim_q], [mrgsim], [mrgsim_variants]
+#' @seealso [mrgsim_q()], [mrgsim()], [mrgsim_variants]
#'
#' @md
#'
@@ -846,19 +844,19 @@ qsim <- function(x,
)
if(tad) tcol <- c(tcol,"tad")
-
- dimnames(out[["data"]]) <- list(NULL, c("ID", tcol, x@cmtL, x@capL))
+
+ names(out[["data"]]) <- c("ID", tcol, x@cmtL, x@capL)
if(output=="df") {
- return(as.data.frame.matrix(out[["data"]]))
+ return(out[["data"]])
}
new(
"mrgsims",
- request=x@cmtL,
- data=as.data.frame.matrix(out[["data"]]),
- outnames=x@capL,
- mod=x
+ request = x@cmtL,
+ data = out[["data"]],
+ outnames = x@capL,
+ mod = x
)
}
diff --git a/R/utils.R b/R/utils.R
index 80bdacb82..aff79b965 100644
--- a/R/utils.R
+++ b/R/utils.R
@@ -570,7 +570,13 @@ system4 <- function(cmd, args=character(0), pattern, path) {
files <- file.path(path, paste0("system4__",c("stdout","stderr"),"__", pattern))
x <- list(status=system2(cmd, args, stdout = files[1], stderr = files[2]))
x[["stdout"]] <- readLines(files[1])
+ if(length(x[["stdout"]])==0) {
+ x[["stdout"]] <- "stdout could not be recovered after system4 call"
+ }
x[["stderr"]] <- readLines(files[2])
+ if(length(x[["stderr"]])==0) {
+ x[["stderr"]] <- "stderr could not be recovered after system4 call"
+ }
x
}
diff --git a/inst/include/mrgsolve.h b/inst/include/mrgsolve.h
index 857d04f51..ddf91c5da 100644
--- a/inst/include/mrgsolve.h
+++ b/inst/include/mrgsolve.h
@@ -61,6 +61,8 @@ Rcpp::NumericMatrix EXPAND_EVENTS(const Rcpp::IntegerVector& idcol_,
const Rcpp::NumericMatrix& events,
const Rcpp::NumericVector& id);
+Rcpp::List mat2df(Rcpp::NumericMatrix const& x);
+
// Rcpp::NumericMatrix recdata(Rcpp::NumericMatrix& dose,
// Rcpp::NumericMatrix& obs,
// Rcpp::IntegerVector& cols,
diff --git a/inst/maintenance/unit/test-capture.R b/inst/maintenance/unit/test-capture.R
index 618fca698..914896191 100644
--- a/inst/maintenance/unit/test-capture.R
+++ b/inst/maintenance/unit/test-capture.R
@@ -52,6 +52,8 @@ test_that("error if cmt in capture issue-555", {
code <- '
$PARAM CL=1, V2=20,Q=30,V3=200,KA=1
+$GLOBAL
+double z = 5;
$MAIN double b = 2;
$OMEGA 1
$OMEGA @labels OGA2
@@ -60,15 +62,15 @@ $CAPTURE CL VP = V2
'
test_that("capture via mread", {
- mod <- mcode("capture-mread", code, capture = "Q,a=b,OGA2")
+ mod <- mcode("capture-mread", code, capture = "Q,a=b,OGA2,z")
out <- outvars(mod)
- expect_equal(out$capture, c("CL", "VP", "Q", "a", "OGA2"))
+ expect_equal(out$capture, c("CL", "VP", "Q", "a", "OGA2", "z"))
expect_error(
- mread("pk1",modlib(),capture = "mrgsolve"),
+ mread("pk1", modlib(), capture = "mrgsolve"),
msg = "all requested `capture` variables must exist in the model"
)
- mod <- mcode("capture-mread", code, capture="(everything)", compile=FALSE)
- res <- c("CL","VP", "Q", "V3", "KA", "OGA2", "ETA_1", "ETA_2", "b")
+ mod <- mcode("capture-mread", code, capture="(everything)", compile = FALSE)
+ res <- c("CL","VP", "Q", "V3", "KA", "OGA2", "ETA_1", "ETA_2", "z", "b")
expect_equal(outvars(mod)$capture, res)
})
@@ -76,4 +78,3 @@ test_that("capture pp directive via mread", {
mod <- modlib("irm3", capture = "STIM", compile = FALSE)
expect_equal(outvars(mod)$capture, c("CP", "STIM"))
})
-
diff --git a/inst/maintenance/unit/test-modlib.R b/inst/maintenance/unit/test-modlib.R
index 4cfea92d7..2369a3493 100644
--- a/inst/maintenance/unit/test-modlib.R
+++ b/inst/maintenance/unit/test-modlib.R
@@ -100,3 +100,8 @@ test_that("all modlib models", {
expect_is(x[[1]],"mrgmod")
expect_is(x[[2]],"mrgsims")
})
+
+test_that("pk2iv uses V1 to scale CENT", {
+ x <- readLines(file.path(modlib(), "pk2iv.cpp"))
+ expect_match(x, "#define CP (CENT/V1)", fixed = TRUE, all = FALSE)
+})
diff --git a/inst/maintenance/unit/test-mread.R b/inst/maintenance/unit/test-mread.R
index 15415547c..414c1de57 100644
--- a/inst/maintenance/unit/test-mread.R
+++ b/inst/maintenance/unit/test-mread.R
@@ -1,4 +1,4 @@
-# Copyright (C) 2013 - 2019 Metrum Research Group, LLC
+# Copyright (C) 2013 - 2021 Metrum Research Group
#
# This file is part of mrgsolve.
#
@@ -70,7 +70,7 @@ $SIGMA @block
'
-mod <- suppressWarnings(mcode("test2",code, warn=TRUE, soloc = '.'))
+mod <- suppressWarnings(mcode("test2",code, warn=TRUE))
test_that("Parameters are parsed properly with mread", {
expect_equal(param(mod)$CL,1)
@@ -116,20 +116,18 @@ test_that("Sigma matrices are properly parsed", {
expect_equivalent(mat[3,2],0.002)
})
-
test_that("EPS values have proper variance", {
set.seed(8282)
out <- mrgsim(mod,end=100000, delta=1, init = list(GUT = 0, CENT = 0))
expect_equal(round(var(out$EPS1),2),0.55)
})
-
test_that("Error when code is passed as project", {
expect_error(suppressWarnings(mread("hey",code)))
})
test_that("Model name with spaces is error", {
- expect_error(mcode("ab cd", ""))
+ expect_error(mcode("ab cd", ""))
})
test_that("Error with duplicate blocks", {
@@ -137,3 +135,20 @@ test_that("Error with duplicate blocks", {
expect_error(mcode("a", "$SET \n $SET",compile = FALSE))
})
+test_that("Recover data when compile fails", {
+ code <- '[main] double a = 2\n[param] b = 5\n'
+ expect_warning(
+ mod <- mcode("fail", code, recover = TRUE),
+ regexp = "returning object for debugging purposes only"
+ )
+ expect_is(mod, "list")
+ expect_named(mod)
+ expect_true("mod" %in% names(mod))
+ expect_true("build" %in% names(mod))
+ expect_true("out" %in% names(mod))
+ expect_true("spec" %in% names(mod))
+ recov <- mrgsolve:::build_format_recover(mod)
+ expect_is(recov, "character")
+ recov_list <- yaml::yaml.load(recov)
+ expect_is(recov_list, "list")
+})
diff --git a/inst/models/pk2iv.cpp b/inst/models/pk2iv.cpp
index c5291b3dc..e8d0a20bd 100644
--- a/inst/models/pk2iv.cpp
+++ b/inst/models/pk2iv.cpp
@@ -9,10 +9,9 @@ CENT : Central compartment (mass)
PERIPH : Peripheral compartment (mass)
$GLOBAL
-#define CP (CENT/V2)
+#define CP (CENT/V1)
$PKMODEL ncmt = 2, depot = FALSE
$CAPTURE @annotated
CP : Plasma concentration (mass/time)
-
diff --git a/man/matrix_converters.Rd b/man/matrix_converters.Rd
index 94b818ae4..22939bb8e 100644
--- a/man/matrix_converters.Rd
+++ b/man/matrix_converters.Rd
@@ -58,7 +58,7 @@ matrix (\code{c}).
\details{
Use \code{as_dmat} to create a diagonal matrix, \code{as_bmat}
to create a block matrix, and \code{as_cmat} to create a block
-matrix where diagonal elements are understood to be correlations
+matrix where off-diagonal elements are understood to be correlations
rather than covariances. \code{as_cmat} uses \code{as_bmat} to
form the matrix and then converts off-diagonal elements to
covariances before returning.
diff --git a/man/matrix_helpers.Rd b/man/matrix_helpers.Rd
index 2fbc08103..9759c037c 100644
--- a/man/matrix_helpers.Rd
+++ b/man/matrix_helpers.Rd
@@ -16,7 +16,7 @@ dmat(...)
\arguments{
\item{...}{matrix data}
-\item{correlation}{logical; if TRUE, off diagonal elements are assumed
+\item{correlation}{logical; if TRUE, off-diagonal elements are assumed
to be correlations and converted to covariances}
\item{digits}{if greater than zero, matrix is passed to signif (along
diff --git a/man/mread.Rd b/man/mread.Rd
index aab5223d4..4f8a2503b 100644
--- a/man/mread.Rd
+++ b/man/mread.Rd
@@ -81,8 +81,9 @@ list for the current call to \code{\link{mread}} only}
\item{preclean}{logical; if \code{TRUE}, compilation artifacts are
cleaned up first}
-\item{recover}{if \code{TRUE}, an object will be returned in case
-the model shared object fails to build}
+\item{recover}{if \code{TRUE}, a list of build will be returned in case
+the model shared object fails to compile; use this option to and
+the returned object to collect information assist in debugging}
\item{...}{passed to \code{\link[mrgsolve]{update}}; also arguments passed
to mread from \code{\link{mread_cache}}.}
diff --git a/man/qsim.Rd b/man/qsim.Rd
index c0382c218..2ece85726 100644
--- a/man/qsim.Rd
+++ b/man/qsim.Rd
@@ -64,7 +64,8 @@ default output object; other options include \code{df} (for data.frame) or
\code{matrix}}
}
\description{
-This is just a lighter version of \link{mrgsim}, with fewer options. See \code{Details}.
+This is just a lighter version of \code{\link[=mrgsim]{mrgsim()}}, with fewer options.
+See \code{Details}.
}
\details{
There is no pipeline interface for this function; all configuration options
@@ -84,5 +85,5 @@ out <- qsim(mod,dose)
}
\seealso{
-\link{mrgsim_q}, \link{mrgsim}, \link{mrgsim_variants}
+\code{\link[=mrgsim_q]{mrgsim_q()}}, \code{\link[=mrgsim]{mrgsim()}}, \link{mrgsim_variants}
}
diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp
index 7b6b645d7..e64d5bdec 100644
--- a/src/RcppExports.cpp
+++ b/src/RcppExports.cpp
@@ -7,6 +7,11 @@
using namespace Rcpp;
+#ifdef RCPP_USE_GLOBAL_ROSTREAM
+Rcpp::Rostream& Rcpp::Rcout = Rcpp::Rcpp_cout_get();
+Rcpp::Rostream& Rcpp::Rcerr = Rcpp::Rcpp_cerr_get();
+#endif
+
// DEVTRAN
Rcpp::List DEVTRAN(const Rcpp::List parin, const Rcpp::NumericVector& inpar, const Rcpp::CharacterVector& parnames, const Rcpp::NumericVector& init, Rcpp::CharacterVector& cmtnames, const Rcpp::IntegerVector& capture, const Rcpp::List& funs, const Rcpp::NumericMatrix& data, const Rcpp::NumericMatrix& idata, Rcpp::NumericMatrix& OMEGA, Rcpp::NumericMatrix& SIGMA, Rcpp::Environment envir);
RcppExport SEXP _mrgsolve_DEVTRAN(SEXP parinSEXP, SEXP inparSEXP, SEXP parnamesSEXP, SEXP initSEXP, SEXP cmtnamesSEXP, SEXP captureSEXP, SEXP funsSEXP, SEXP dataSEXP, SEXP idataSEXP, SEXP OMEGASEXP, SEXP SIGMASEXP, SEXP envirSEXP) {
diff --git a/src/devtran.cpp b/src/devtran.cpp
index 8c8dfb58c..1458f67e7 100644
--- a/src/devtran.cpp
+++ b/src/devtran.cpp
@@ -640,6 +640,6 @@ Rcpp::List DEVTRAN(const Rcpp::List parin,
if((tscale != 1) && (tscale >= 0)) {
ans(Rcpp::_,1) = ans(Rcpp::_,1) * tscale;
}
- return Rcpp::List::create(Rcpp::Named("data") = ans,
+ return Rcpp::List::create(Rcpp::Named("data") = mat2df(ans),
Rcpp::Named("trannames") = tran_names);
}
diff --git a/src/mrgsolve.cpp b/src/mrgsolve.cpp
index 42cd032da..3e92f1260 100644
--- a/src/mrgsolve.cpp
+++ b/src/mrgsolve.cpp
@@ -150,6 +150,10 @@ void dcorr(Rcpp::NumericMatrix& x) {
//[[Rcpp::export]]
Rcpp::NumericMatrix SUPERMATRIX(const Rcpp::List& a, bool keep_names) {
+ if(a.size()==1) {
+ return a[0];
+ }
+
int j,k;
Rcpp::NumericMatrix mat;
@@ -388,6 +392,19 @@ Rcpp::List EXPAND_OBSERVATIONS(
Rcpp::Named("index") = index);
}
+Rcpp::List mat2df(Rcpp::NumericMatrix const& x) {
+ Rcpp::List ret(x.ncol());
+ for(int i = 0; i < x.ncol(); ++i) {
+ ret[i] = x(Rcpp::_,i);
+ }
+ Rcpp::IntegerVector rn(2);
+ rn[0] = NA_INTEGER;
+ rn[1] = x.nrow()*-1;
+ ret.attr("class") = "data.frame";
+ ret.attr("row.names") = rn;
+ return ret;
+}
+
#endif
diff --git a/tests/testthat/test-carry_out.R b/tests/testthat/test-carry_out.R
index d18de26af..3fd3b68ba 100644
--- a/tests/testthat/test-carry_out.R
+++ b/tests/testthat/test-carry_out.R
@@ -106,3 +106,12 @@ test_that("recover input idata-set items", {
expect_is(out$b,"character")
expect_error(mrgsim_e(mod,idata,recover="b",carry_out="b"))
})
+
+test_that("error to request matrix and recover character data", {
+ data <- expand.ev(amt = 100, group = "A")
+ expect_is(mrgsim(mod, data, recover = "group"), "mrgsims")
+ expect_error(
+ mrgsim(mod, data, recover = "group", output = "matrix"),
+ msg = "can't return matrix because non-numeric data was found"
+ )
+})
diff --git a/tests/testthat/test-matlist.R b/tests/testthat/test-matlist.R
index dde2031d8..273792b5b 100644
--- a/tests/testthat/test-matlist.R
+++ b/tests/testthat/test-matlist.R
@@ -49,10 +49,10 @@ test_that("Indexing SIGMA matrix elements", {
expect_equivalent(as.matrix(smat(mod))[3,3],0.3)
})
-o1 <-
- omat(diag(c(1.1, 2.2, 3.3)),
- diag(c(4.4, 5.5, 6.6)),
- matrix(seq(91,99),nrow=3, byrow=TRUE))
+a <- diag(c(1.1, 2.2, 3.3))
+b <- diag(c(4.4, 5.5, 6.6))
+c <- matrix(seq(91,99),nrow = 3, byrow = TRUE)
+o1 <- omat(a,b,c)
mat <- as.matrix(o1)
diff --git a/tests/testthat/test-matrix.R b/tests/testthat/test-matrix.R
index c810e5f6e..81b1642db 100644
--- a/tests/testthat/test-matrix.R
+++ b/tests/testthat/test-matrix.R
@@ -31,7 +31,22 @@ test_that("Testing modMATRIX", {
expect_equal(modMATRIX("0 0 0", use=FALSE), matrix(0,nrow=3,ncol=3))
})
-
-
-
-
+test_that("SUPERMATRIX", {
+ ml <- list(matrix(1, 2, 2), matrix(3, 4, 4))
+ dimnames(ml[[1]]) <- list(c("a", "b"), c("A", "B"))
+ ans <- mrgsolve:::SUPERMATRIX(ml)
+ expect_is(ans, "matrix")
+ expect_equal(dim(ans), c(6, 6))
+ ml$a <- "a"
+ expect_error(mrgsolve:::SUPERMATRIX(ml), msg = "is not TRUE")
+ expect_error(mrgsolve:::SUPERMATRIX(ml[[1]]), msg = "is not TRUE")
+ ml$a <- NULL
+ ans <- mrgsolve:::SUPERMATRIX(ml[2])
+ expect_identical(unname(ml[[2]]),unname(ans))
+ ans <- mrgsolve:::SUPERMATRIX(ml[1], keep_names = TRUE)
+ expect_identical(ans, ml[[1]])
+ ans1 <- mrgsolve:::SUPERMATRIX(list())
+ expect_identical(ans1, matrix(0, nrow = 0, ncol = 0))
+ ans2 <- mrgsolve:::SUPERMATRIX(omat()@data)
+ expect_identical(ans1, ans2)
+})