diff --git a/DESCRIPTION b/DESCRIPTION index 615bea907..0f5ae7833 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,5 +1,5 @@ Package: rxode2 -Version: 2.0.13.9000 +Version: 2.0.14.9000 Title: Facilities for Simulating from ODE-Based Models Authors@R: c( person("Matthew L.","Fidler", @@ -7,7 +7,7 @@ Authors@R: c( comment=c(ORCID="0000-0001-8538-6691")), person("Melissa", "Hallow", role = "aut", email = "hallowkm@uga.edu"), - person("Wenping", "Wang", + person("Wenping", "Wang", role = c("aut"), email = "wwang8198@gmail.com"), person("Zufar", "Mulyukov", role="ctb", email="zufar.mulyukov@novartis.com"), person("Alan", "Hindmarsh",role="ctb"), @@ -77,7 +77,7 @@ Imports: backports, cli (>= 2.0.0), checkmate, - ggplot2, + ggplot2 (>= 3.4.0), inline, lotri (>= 0.4.0), magrittr, @@ -104,16 +104,16 @@ Description: Facilities for running simulations from ordinary Section 6.3, Appendix A, and Appendix D in the "R Administration and Installation" manual. Also the code is mostly released under GPL. The 'VODE' and 'LSODA' are in the public domain. The information is available - in the inst/COPYRIGHTS. + in the inst/COPYRIGHTS. BugReports: https://github.com/nlmixr2/rxode2/issues/ NeedsCompilation: yes VignetteBuilder: knitr -License: GPL (>= 3) +License: GPL (>= 3) URL: https://nlmixr2.github.io/rxode2/, https://github.com/nlmixr2/rxode2/ RoxygenNote: 7.2.3 Biarch: true -LinkingTo: +LinkingTo: rxode2parse (>= 2.0.12), rxode2random, PreciseSums (>= 0.3), diff --git a/NAMESPACE b/NAMESPACE index a56557c2d..d3f312655 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -8,6 +8,7 @@ S3method("$",rxSymInvCholEnv) S3method("$",rxUi) S3method("$<-",rxSolve) S3method("$<-",rxSymInvCholEnv) +S3method("$<-",rxUi) S3method("+",rxSolve) S3method("+",solveRxDll) S3method("[",rxSolve) @@ -41,6 +42,7 @@ S3method(as.rxUi,rxModelVars) S3method(as.rxUi,rxUi) S3method(as.rxUi,rxode2) S3method(as.rxUi,rxode2tos) +S3method(binomProbs,default) S3method(coef,rxode2) S3method(confint,rxSolve) S3method(dimnames,rxSolve) @@ -138,6 +140,7 @@ S3method(rxUiGet,lhsTheta) S3method(rxUiGet,lhsVar) S3method(rxUiGet,lstChr) S3method(rxUiGet,md5) +S3method(rxUiGet,model) S3method(rxUiGet,modelDesc) S3method(rxUiGet,modelFun) S3method(rxUiGet,muRefTable) @@ -194,6 +197,7 @@ export(.copyUi) export(.expandPars) export(.getLastIdLvl) export(.handleSingleErrTypeNormOrTFoceiBase) +export(.iniGetAppendArg) export(.iniHandleFixOrUnfix) export(.iniHandleLine) export(.malert) @@ -246,6 +250,7 @@ export(assertRxUiPrediction) export(assertRxUiRandomOnIdOnly) export(assertRxUiSingleEndpoint) export(assertRxUiTransformNormal) +export(binomProbs) export(cvPost) export(erf) export(et) @@ -469,6 +474,7 @@ export(scale_y_discrete) export(setRxThreads) export(stat_amt) export(stat_cens) +export(toTrialDuration) export(uppergamma) export(waiver) export(write.template.server) @@ -529,6 +535,7 @@ importFrom(rxode2et,rxEvid) importFrom(rxode2et,rxRateDur) importFrom(rxode2et,rxReq) importFrom(rxode2et,rxStack) +importFrom(rxode2et,toTrialDuration) importFrom(rxode2parse,.getLastIdLvl) importFrom(rxode2parse,forderForceBase) importFrom(rxode2parse,rxDerived) diff --git a/NEWS.md b/NEWS.md index 825e20cb9..607dab26f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,8 +11,15 @@ - "dop853" now uses the `hmax`/`h0` values from the `rxControl()` or `rxSolve()`. This may change some ODE solving using "dop853" +- When not specified (and xgxr is available), the x axis is no longer + assumed to be in hours + ## New features +- User defined functions can now be R functions. For many of these R + functions they can be converted to C with `rxFun()` (you can see the + C code afterwards with `rxC("funName")`) + - Parallel solving of models that require sorting (like modeled lag times, modeled duration etc) now solve in parallel instead of downgrading to single threaded solving @@ -90,18 +97,80 @@ mu-referencing style to run the optimization. your own `ci=0.99` for instance - A new function was introduced `meanProbs()` which calculates the - mean and expected quantiles under either the normal or t + mean and expected confidence bands under either the normal or t distribution +- A related new function was introduced that calculates the mean and + confidence bands under the Bernoulli/Binomial distribution + (`binomProbs()`) + - When calculating the intervals for `rxode2` simulated objects you can also use `mean=TRUE` to use the mean for the first level of - confidence using `meanProbs()` + confidence using `meanProbs()`. For this confidence interval you can + override the `n` used in the confidence interval by using `n=#`. You + can also change this to a prediction interval instead using + `pred=TRUE`. + +- Also when calculating the intervals for `rxode2` simulated object + you can also use `mean="binom"` to use the binomial distributional + information (and ci) for the first level of confidence using + `binomProbs()`. For this confidence interval you can override the + `n` used in the confidence interval by using `n=#`. You can also + change this to a prediction interval instead using `pred=TRUE`. With + `pred=TRUE` you can override the number of predicted samples with + `m=#` - When plotting the `confint` derived intervals from an `rxode2` simulation, you can now subset based on a simulated value like `plot(ci, Cc)` which will only plot the variable `Cc` that you summarized even if you also summarized `eff` (for instance). +- When the rxode2 ui is a compressed ui object, you can modify the ini + block with `$ini <-` or modify the model block with `$model <-`. + These are equivalent to `ini(model) <-` and `model(model) <-`, + respectively. Otherwise, the object is added to the user defined + components in the function (ie `$meta`). When the object is + uncompressed, it simply assigns it to the environment instead (just + like before). + +- When printing meta information that happens to be a `lotri` + compatible matrix, use `lotri` to express it instead of the default + R expression. + +- Allow character vectors to be converted to expressions for piping + (#552) + +- `rxAppendModel()` will now take an arbitrary number of models and + append them together; It also has better handling of models with + duplicate parameters and models without `ini()` blocks (#617 / #573 + / #575). + +- `keep` will now also keep attributes of the input data (with special + handling for `levels`); This means a broader variety of classes will + be kept carrying more information with it (for example ordered + factors, data frame columns with unit information, etc) + +- Piping arguments `append` for `ini()` and `model()` have been + aligned to perform similarly. Therefore `ini(append=)` now can take + expressions instead of simply strings and `model(append=)` can also + take strings. Also model piping now can specify the integer line + number to be modified just like the `ini()` could. Also + `model(append=FALSE)` has been changed to `model(append=NULL)`. + While the behavior is the same when you don't specify the argument, + the behavior has changed to align with `ini()` when piping. Hence + `model(append=TRUE)` will append and `model(append=FALSE)` will now + pre-pend to the model. `model(append=NULL)` will modify lines like + the behavior of `ini(append=NULL)`. The default of `model(line)` + modifying a line in-place still applies. While this is a breaking + change, most code will perform the same. + +- Labels can now be dropped by `ini(param=label(NULL))`. Also + parameters can be dropped with the idiom `model(param=NULL)` or + `ini(param=NULL)` changes the parameter to a covariate to align with + this idiom of dropping parameters + +- `rxRename` has been refactored to run faster + ## Internal new features - Add `as.model()` for list expressions, which implies `model(ui) <- @@ -121,6 +190,9 @@ mu-referencing style to run the optimization. ## Bug fixes +- Simulating/solving from functions/ui now prefers params over `omega` + and `sigma` in the model (#632) + - Piping does not add constants to the initial estimates - When constants are specified in the `model({})` block (like `k <- 1`), they will not @@ -131,6 +203,19 @@ mu-referencing style to run the optimization. - Bug fix for some covariate updates that may affect multiple compartment models (like issue #581) +## Maintenance fixes + +- Modify plot code to work with development `xgxr` + +# rxode2 2.0.14 + +- CRAN requested that FORTRAN `kind` be changed as it was not portable; + This was commented code, and simply removed the comment. + +- Bug-fix for `geom_amt()`; also now uses `linewidth` and at least `ggplot2 3.4.0` + +- Some documentation was cleaned up from `rxode2` 2.0.13 + # rxode2 2.0.13 ## Bug fixes diff --git a/R/RcppExports.R b/R/RcppExports.R index 30cc3e92f..3f76db423 100644 --- a/R/RcppExports.R +++ b/R/RcppExports.R @@ -40,7 +40,7 @@ etTrans <- function(inData, obj, addCmt = FALSE, dropUnits = FALSE, allTimeVar = #' @param c1 character vector of items to be expanded #' @param c2 second character vector of items to be expanded #' @param type 0 for a typical data frame, 1 for symengine sensitivity expansion -#' @return data frame (when type = 0) or symengine string (when type=1) +#' @return data frame (when type = 0) or symengine string (when type=1) #' @export #' @keywords internal rxExpandGrid_ <- function(c1, c2, type) { @@ -74,17 +74,18 @@ rxExpandSens2_ <- function(state, s1, s2) { #' #' @param state is the state to expand #' @param neta is the number of etas -#' @param pred type of prediction +#' @param pred type of prediction +#' @param isTheta logical, is the expansion actually for thetas instead of etas #' @keywords internal #' @return String of symengine expressions to evaluate to calculate df/deta #' @export -rxExpandFEta_ <- function(state, neta, pred) { - .Call(`_rxode2_rxExpandFEta_`, state, neta, pred) +rxExpandFEta_ <- function(state, neta, pred, isTheta = FALSE) { + .Call(`_rxode2_rxExpandFEta_`, state, neta, pred, isTheta) } #' Rep R0 for foce #' -#' @param number ETA to substitute +#' @param neta ETA to substitute #' #' @return Returns a string of R code to substitute the rx_r expression in the symengine environment .s #' @@ -260,7 +261,7 @@ rxSetupIni <- function(obj, inits = NULL) { #' #' @param obj rxode2 object #' -#' @param inits A numeric vector of initial conditions. +#' @param scale A numeric vector scales #' #' @param extraArgs A list of extra args to parse for initial conditions. #' @@ -589,7 +590,15 @@ rxErf <- function(v) { .Call(`_rxode2_rxErf`, v) } -meanProbs_ <- function(x, probs, naRm, useT) { - .Call(`_rxode2_meanProbs_`, x, probs, naRm, useT) +binomProbsPredVec_ <- function(n, m, Y, M, doP = TRUE, tol = 1e-7) { + .Call(`_rxode2_binomProbsPredVec_`, n, m, Y, M, doP, tol) +} + +binomProbs_ <- function(x, probs, naRm, nIn, cont) { + .Call(`_rxode2_binomProbs_`, x, probs, naRm, nIn, cont) +} + +meanProbs_ <- function(x, probs, naRm, useT, pred, nIn) { + .Call(`_rxode2_meanProbs_`, x, probs, naRm, useT, pred, nIn) } diff --git a/R/confint.R b/R/confint.R index 8094f9d58..d5fa45c68 100644 --- a/R/confint.R +++ b/R/confint.R @@ -32,11 +32,57 @@ confint.rxSolve <- function(object, parm = NULL, level = 0.95, ...) { } } .mean <- FALSE + .binom <- FALSE + .m <- 0L + .nC <- 0L + .pred <- FALSE + .useT <- TRUE + .M <- 500000 + .tol <- .Machine$double.eps^0.25 + if (any(names(.args) == "useT")) { + .useT <- .args$useT + checkmate::assertLogical(.useT, len=1, any.missing=FALSE, .var.name="useT") + } if (any(names(.args) == "mean")) { .mean <- .args$mean - checkmate::assertLogical(.mean, len=1, any.missing=FALSE, .var.name="mean") + if (inherits(.mean, "character") && + length(.mean) == 1L && + .mean == "binom") { + .binom <- TRUE + .mean <- FALSE + } else { + checkmate::assertLogical(.mean, len=1, any.missing=FALSE, .var.name="mean") + } + } + if (any(names(.args) == "pred")) { + .pred <- .args$pred + checkmate::assertLogical(.pred, len=1, any.missing=FALSE, .var.name="pred") + } + if (any(names(.args) == "n")) { + .nC <- unique(.args$n) + checkmate::assertIntegerish(.nC, len=1, any.missing=FALSE, lower=0L, .var.name="n") + } + if (any(names(.args) == "m")) { + .m <- unique(.args$m) + checkmate::assertIntegerish(.m, len=1, any.missing=FALSE, lower=0L, .var.name="m") + } + if (any(names(.args) == "M")) { + .M <- unique(.args$M) + checkmate::assertIntegerish(.M, len=1, any.missing=FALSE, lower=1000L, .var.name="M") + } + if (any(names(.args) == "tol")) { + .tol <- unique(.args$tol) + checkmate::assertNumeric(.tol, len=1, any.missing=FALSE, lower=.Machine$double.eps, .var.name="tol") + } + .ciMethod <- "wald" + if (any(names(.args) == "ciMethod")) { + .ciMethod <- .args$method } .stk <- rxStack(object, parm, doSim=.doSim) + if (!any(names(.stk) == "id") && + any(names(.stk) == "sim.id")) { + names(.stk) <- gsub("sim.id", "id", names(.stk)) + } for(.v in .by) { .stk[[.v]] <- object[[.v]] } @@ -50,7 +96,8 @@ confint.rxSolve <- function(object, parm = NULL, level = 0.95, ...) { ci = paste0("p", .p2 * 100), parm = levels(.stk$trt), by = .by, - mean = .mean + mean = .mean, + binom=.binom ) class(.lst) <- "rxHidden" if (.ci ==0 || !any(names(.stk) == "sim.id")) { @@ -71,11 +118,21 @@ confint.rxSolve <- function(object, parm = NULL, level = 0.95, ...) { message("summarizing data...", appendLF = FALSE) if (.mean) { .stk <- .stk[, list( - p1 = .p, eff = rxode2::meanProbs(.SD$value, probs = .p, na.rm = TRUE), + p1 = .p, eff = rxode2::meanProbs(.SD$value, probs = .p, na.rm = TRUE, useT=.useT, + n=.nC, pred=.pred), Percentile = sprintf("%s%%", .p * 100) ), by = c("time", "trt", .by) - ] + ] + } else if (.binom) { + .stk <- .stk[, list( + p1 = .p, eff = rxode2::binomProbs(.SD$value, probs = .p, na.rm = TRUE, + n=.nC, m=.m, M=.m, tol=.tol, + pred=.pred, ciMethod=.ciMethod), + Percentile = sprintf("%s%%", .p * 100) + ), + by = c("time", "trt", .by) + ] } else { .stk <- .stk[, list( p1 = .p, eff = stats::quantile(.SD$value, probs = .p, na.rm = TRUE), @@ -105,12 +162,19 @@ confint.rxSolve <- function(object, parm = NULL, level = 0.95, ...) { .ret <- .stk[, id := sim.id %% .n] if (.mean) { .ret <- .ret[, list(p1 = .p, - eff = rxode2::meanProbs(.SD$value, probs = .p, na.rm = TRUE)), + eff = rxode2::meanProbs(.SD$value, probs = .p, na.rm = TRUE, n=.nC, + useT=.useT, + pred=.pred)), + by = c("id", "time", "trt", .by)] + } else if (.binom) { + .ret <- .ret[, list(p1 = .p, + eff = rxode2::binomProbs(.SD$value, probs = .p, na.rm = TRUE, + n=.nC, m=.m, M=.m, tol=.tol, + pred=.pred, ciMethod=.ciMethod)), by = c("id", "time", "trt", .by)] } else { .ret <- .ret[, list(p1 = .p, eff = stats::quantile(.SD$value, probs = .p, na.rm = TRUE)), by = c("id", "time", "trt", .by)] - } .ret <- .ret[, setNames(as.list(stats::quantile(.SD$eff, probs = .p2, na.rm = TRUE)), sprintf("p%s", .p2 * 100)), diff --git a/R/err.R b/R/err.R index b039e4696..00e61ad01 100644 --- a/R/err.R +++ b/R/err.R @@ -46,8 +46,8 @@ "f"=2:3, "dgeom"=1, "geom"=1, -# "dhyper"=3, -# "hyper"=3, + # "dhyper"=3, + # "hyper"=3, "dunif"=0:2, "unif"=0:2, "dweibull"=1:2, @@ -233,7 +233,7 @@ rxPreferredDistributionName <- function(dist) { } .rxTransformHasBounds <- function(distribution) { - (as.integer(distribution) %in% 5:14) + (as.integer(distribution) %in% 5:14) } .rxAddPropLevels <- c( @@ -336,7 +336,7 @@ rxDemoteAddErr <- function(errType) { .incompatibleErr <- function(err1, err2) { .errs <- sort(c(err1, err2)) - paste0("`", .errs[1], "` and `", .errs[2], "` are incompatible") + paste0("`", .errs[1], "` and `", .errs[2], "` are incompatible") } #' Combine error types to get the model F type #' @@ -545,12 +545,11 @@ rxDemoteAddErr <- function(errType) { #' `oldErrType` to zero assuming that there is no prior #' distribution. #' -#' @param newTransform This is the new distribution that is being +#' @param newErrType This is the new distribution that is being #' "added" to the current transformation. These assumes the inputs #' are in the preferred distribution name, as determined by #' `rxPreferredDistributionName()` #' -#' #' @return The new transformation as a factor #' #' @author Matthew Fidler @@ -598,7 +597,7 @@ rxErrTypeCombine <- function(oldErrType, newErrType) { env$.numeric <- -(expression[[2]]) return(TRUE) } else if (identical(expression[[1]], quote(`+`)) && - is.numeric(expression[[2]])) { + is.numeric(expression[[2]])) { env$.numeric <- expression[[2]] return(TRUE) } @@ -627,7 +626,7 @@ rxErrTypeCombine <- function(oldErrType, newErrType) { dexp=c("a"), #7 f=c("a", "b", "c"), #8 geom=c("a"), #9 -# hyper=c("a", "b", "c"), #10 + # hyper=c("a", "b", "c"), #10 unif=c("a", "b"), #11 weibull=c("a", "b"), #12 cauchy=c("a", "b"), @@ -1183,7 +1182,7 @@ rxErrTypeCombine <- function(oldErrType, newErrType) { setNames( c("linCmtA" = 1L, "linCmtB" = 2L, "linCmtC" = 3L - )[match.arg(linCmtSens)], + )[match.arg(linCmtSens)], NULL ), verbose )) @@ -1257,8 +1256,8 @@ rxErrTypeCombine <- function(oldErrType, newErrType) { } .mod <- eval(parse(text=paste0("quote({", .var, "=1+2\n", deparse1(expr), "})"))) .ini <- as.data.frame(eval(parse(text=paste0("lotri({\n", - paste(paste(allNames(expr[[3]]), "<- 1"), collapse="\n"), - "\n})")))) + paste(paste(allNames(expr[[3]]), "<- 1"), collapse="\n"), + "\n})")))) .env <- try(.errProcessExpression(.mod, .ini, checkMissing=FALSE), silent=TRUE) if (inherits(.env, "try-error")) return(FALSE) if (uiEnv) return(.env) @@ -1267,7 +1266,7 @@ rxErrTypeCombine <- function(oldErrType, newErrType) { #' Is Normal, Cauchy or t distribution model specification? #' #' @param expr Expression -#' +#' #' @return TRUE if this is a normal/t/cauchy model, FALSE otherwise #' @author Matthew L. Fidler #' @noRd diff --git a/R/genShinyApp.template.R b/R/genShinyApp.template.R index 93ce9d838..ed3e58bcc 100644 --- a/R/genShinyApp.template.R +++ b/R/genShinyApp.template.R @@ -43,7 +43,7 @@ #' dosing regimen simulation web application. Users may want to #' modify the code to experiment creating shiny applications for #' their specific `rxode2` models. -#' @seealso [rxode2()],[eventTable()], and the package \pkg{shiny} (). +#' @seealso [rxode2()],[eventTable()], and the package \pkg{shiny} (). #' #' @examples #' \donttest{ diff --git a/R/geom-amt.R b/R/geom-amt.R index bf3f914e7..6f95da4bc 100644 --- a/R/geom-amt.R +++ b/R/geom-amt.R @@ -3,8 +3,7 @@ stop("need 'amt' aesthetic") } else if (!any(names(data) == "x") && any(names(data) == "time")) { data$x <- data$time - } else if (any(names(data) == "x")) { - } else { + } else if (!any(names(data) == "x")) { stop("need 'x' aesthetic") } ret <- data[!is.na(data$amt), c("x", "amt")] @@ -88,7 +87,7 @@ StatAmt <- ggplot2::ggproto("StatAmt", ggplot2::Stat, #' # of course you can make it a bit more visible #' #' plot(bidQd, C2) + geom_amt(aes(amt=amt), col="red", lty=1, linewidth=1.2) -#' +#' #' } #' @export #' @inheritParams ggplot2::stat_identity diff --git a/R/piping-ini.R b/R/piping-ini.R index 7cc279c62..eb9802ead 100644 --- a/R/piping-ini.R +++ b/R/piping-ini.R @@ -321,20 +321,67 @@ #' #' @inheritParams .iniHandleLine #' @return Nothing, called for side effects +#' @author Bill Denney & Matthew Fidler #' @keywords internal #' @noRd .iniHandleLabel <- function(expr, rxui, envir) { - lhs <- as.character(expr[[2]]) - newLabel <- expr[[3]][[2]] - ini <- rxui$ini - .w <- which(ini$name == lhs) + .lhs <- as.character(expr[[2]]) + .newLabel <- expr[[3]][[2]] + .ini <- rxui$ini + .w <- which(.ini$name == .lhs) if (length(.w) != 1) { - stop("cannot find parameter '", lhs, "'", call.=FALSE) - } else if (!is.character(newLabel) || !(length(newLabel) == 1)) { - stop("the new label for '", lhs, "' must be a character string") + stop("cannot find parameter '", .lhs, "'", call.=FALSE) + } else if (is.null(.newLabel)) { + .newLabel <- NA_character_ + } else if (!is.character(.newLabel) || !(length(.newLabel) == 1)) { + stop("the new label for '", .lhs, "' must be a character string", + call.=FALSE) + } + .ini$label[.w] <- .newLabel + assign("iniDf", .ini, envir=rxui) + invisible() +} +#' This handles the backTransform() piping calls +#' +#' @param expr expression for backTransform() in `ini()` piping +#' @param rxui rxode2 ui function +#' @param envir evaluation environment +#' @return nothing, called for side effects +#' @noRd +#' @author Matthew L. Fidler +.iniHandleBackTransform <- function(expr, rxui, envir) { + .lhs <- as.character(expr[[2]]) + .newExpr <- expr[[3]][[2]] + .ini <- rxui$ini + .w <- which(.ini$name == .lhs) + .good <- TRUE + if (length(.w) != 1) { + stop("cannot find parameter '", .lhs, "'", call.=FALSE) + } else if (is.null(.newExpr)) { + .newExpr <- NA_character_ + } else if (checkmate::testCharacter(.newExpr, len=1, any.missing=FALSE, + pattern="^[.]*[a-zA-Z]+[a-zA-Z0-9._]*$", + min.chars = 1)) { + } else { + .newExpr <- deparse1(.newExpr) + if (!checkmate::testCharacter(.newExpr, len=1, any.missing=FALSE, + pattern="^[.]*[a-zA-Z]+[a-zA-Z0-9._]*$", + min.chars = 1)) { + .good <- FALSE + } } - ini$label[.w] <- newLabel - assign("iniDf", ini, envir=rxui) + if (!.good) { + stop("backTransform specification malformed", + call.=FALSE) + } + if (!is.na(.newExpr)) { + if (!exists(.newExpr, envir=envir, mode="function")) { + stop("tried use a backTransform(\"", .newExpr, "\") when the function does not exist", + call.=FALSE) + } + } + .ini$backTransform[.w] <- .newExpr + assign("iniDf", .ini, envir=rxui) invisible() } @@ -355,21 +402,22 @@ # Do nothing return() } else if (is.logical(append)) { - checkmate::assert_logical(append, any.missing = FALSE, len = 1) + checkmate::assertLogical(append, any.missing = FALSE, len = 1) if (isTRUE(append)) { appendClean <- Inf } else if (isFALSE(append)) { appendClean <- 0 } } else if (is.numeric(append)) { - checkmate::assert_number(append, null.ok = FALSE, na.ok = FALSE) + checkmate::assertNumber(append, null.ok = FALSE, na.ok = FALSE) appendClean <- append } else if (is.character(append)) { - checkmate::assert_character(append, any.missing = FALSE, len = 1, null.ok = FALSE) - checkmate::assert_choice(append, choices = ini$name) + checkmate::assertCharacter(append, any.missing = FALSE, len = 1, null.ok = FALSE) + checkmate::assertChoice(append, choices = ini$name) appendClean <- which(ini$name == append) } else { - stop("'append' must be NULL, logical, numeric, or character", call. = FALSE) + stop("'append' must be NULL, logical, numeric, or character/expression of variable in model", + call. = FALSE) } lhs <- as.character(expr[[2]]) @@ -409,6 +457,126 @@ invisible() } +.iniHandleRecalc <- function(rxui) { + .fun <- rxUiDecompress(rxui$fun()) + for (.i in ls(.fun, all=TRUE)) { + if (.i != "meta") { + assign(.i, get(.i, envir=.fun), envir=rxui) + } + } + invisible() +} + +#' Handle switching theta to eta and vice versa +#' +#' This is coded as model |> ini(~par) +#' +#' @param expr Expression, this would be the ~par expression +#' @param rxui rxui uncompressed environment +#' @param envir Environment for evaluation (if needed) +#' @return Nothing, called for side effects +#' @noRd +#' @author Matthew L. Fidler +.iniHandleSwitchType <- function(expr, rxui, envir=parent.frame()) { + .var <- as.character(expr[[2]]) + .iniDf <- rxui$iniDf + .w <- which(.iniDf$name == .var) + if (length(.w) != 1L) stop("cannot switch parameter type for '", .var, "'", call.=FALSE) + .theta <- .iniDf[!is.na(.iniDf$ntheta),, drop = FALSE] + .eta <- .iniDf[is.na(.iniDf$ntheta),, drop = FALSE] + if (is.na(.iniDf$ntheta[.w])) { + # switch eta to theta + .neta <- .iniDf$neta1[.w] + .eta <- .eta[.eta$neta1 != .neta,, drop = FALSE] + .eta <- .eta[.eta$neta2 != .neta,, drop = FALSE] + .eta$neta1 <- .eta$neta1 - ifelse(.eta$neta1 < .neta, 0L, 1L) + .eta$neta2 <- .eta$neta2 - ifelse(.eta$neta2 < .neta, 0L, 1L) + .newTheta <- .iniDf[.w, ] + .newTheta$neta1 <- NA_integer_ + .newTheta$neta2 <- NA_integer_ + if (length(.theta$ntheta) == 0L) { + .newTheta$ntheta <- 1L + } else { + .newTheta$ntheta <- max(.theta$ntheta) + 1L + } + .minfo(paste0("convert '", .var, "' from between subject variability to population parameter")) + .theta <- rbind(.theta, .newTheta) + } else { + # switch theta to eta + if (!is.na(.iniDf$err[.w])) { + stop("cannot switch error parameter '", .var, + "' to a different type", call. = FALSE) + } + .ntheta <- .iniDf$ntheta[.w] + .theta <- .theta[.theta$ntheta != .ntheta,, drop = FALSE] + .theta$ntheta <- .theta$ntheta - ifelse(.theta$ntheta < .ntheta, 0L, 1L) + .newEta <- .iniDf[.w, ] + .newEta$ntheta <- NA_integer_ + if (length(.eta$neta1) == 0L) { + .newEta$neta1 <- .newEta$neta2 <- 1L + } else { + .newEta$neta1 <- .newEta$neta2 <- max(.eta$neta1) + 1L + } + .minfo(paste0("convert '", .var, "' from population parameter to between subject variability")) + if (.newEta$est == 0) { + .minfo("old initial estimate is zero, changing to 1") + .newEta$est <- 1 + } else if (.newEta$est < 0) { + .minfo("old initial estimate was negative, changing to positive") + .newEta$est <- -.newEta$est + } + .newEta$lower <- -Inf + .newEta$upper <- Inf + .newEta$condition <- "id" + .eta <- rbind(.eta, .newEta) + } + .ini <- rbind(.theta, .eta) + assign("iniDf", .ini, envir=rxui) + .iniHandleRecalc(rxui) + invisible() +} + +#' Handle dropping parameter and treating as if it is a covariate +#' +#' This is coded as model |> ini(-par) +#' +#' @param expr Expression, this would be the ~par expression +#' @param rxui rxui uncompressed environment +#' @param envir Environment for evaluation (if needed) +#' @return Nothing, called for side effects +#' @noRd +#' @author Matthew L. Fidler +.iniHandleDropType <- function(expr, rxui, envir=parent.frame()) { + .var <- as.character(expr[[2]]) + .iniDf <- rxui$iniDf + .w <- which(.iniDf$name == .var) + if (length(.w) != 1L) stop("no initial estimates for '", .var, "', cannot change to covariate", call.=FALSE) + .theta <- .iniDf[!is.na(.iniDf$ntheta),, drop = FALSE] + .eta <- .iniDf[is.na(.iniDf$ntheta),, drop = FALSE] + if (is.na(.iniDf$ntheta[.w])) { + .minfo(paste0("changing between subject variability parameter '", .var, "' to covariate parameter")) + .neta <- .iniDf$neta1[.w] + .eta <- .eta[.eta$neta1 != .neta,, drop = FALSE] + .eta <- .eta[.eta$neta2 != .neta,, drop = FALSE] + .eta$neta1 <- .eta$neta1 - ifelse(.eta$neta1 < .neta, 0L, 1L) + .eta$neta2 <- .eta$neta2 - ifelse(.eta$neta2 < .neta, 0L, 1L) + } else { + if (!is.na(.iniDf$err[.w])) { + stop("cannot switch error parameter '", .var, + "' to a covariate", call. = FALSE) + } + .minfo(paste0("changing population parameter '", .var, "' to covariate parameter")) + .ntheta <- .iniDf$ntheta[.w] + .theta <- .theta[.theta$ntheta != .ntheta,, drop = FALSE] + .theta$ntheta <- .theta$ntheta - ifelse(.theta$ntheta < .ntheta, 0L, 1L) + } + .ini <- rbind(.theta, .eta) + assign("iniDf", .ini, envir=rxui) + # This will change covariates, recalculate everything + .iniHandleRecalc(rxui) + invisible() +} + #' Update the iniDf of a model #' #' @param expr Expression for parsing @@ -427,10 +595,10 @@ # downstream operations expr <- .iniSimplifyAssignArrow(expr) - # Capture errors if (.matchesLangTemplate(expr, str2lang(".name <- NULL"))) { - stop("a NULL value for '", as.character(expr[[2]]), "' piping does not make sense", - call. = FALSE) + expr <- as.call(list(quote(`-`), expr[[2]])) + } else if (.matchesLangTemplate(expr, str2lang(".name ~ NULL"))) { + expr <- as.call(list(quote(`-`), expr[[2]])) } # Convert fix(name) or unfix(name) to name <- fix or name <- unfix @@ -442,6 +610,8 @@ if (.matchesLangTemplate(expr, str2lang(".name <- label(.)"))) { .iniHandleLabel(expr=expr, rxui=rxui, envir=envir) + } else if (.matchesLangTemplate(expr, str2lang(".name <- backTransform(.)"))) { + .iniHandleBackTransform(expr=expr, rxui=rxui, envir=envir) } else if (.isAssignment(expr) && is.character(expr[[3]])) { stop( sprintf( @@ -464,6 +634,10 @@ expr[[3]] <- eval(as.call(list(quote(`lotri`), as.call(list(quote(`{`), expr)))), envir=envir)[1, 1] .iniHandleFixOrUnfixEqual(expr=expr, rxui=rxui, envir=envir, maxLen=1L) + } else if (.isTildeExpr(expr)) { + .iniHandleSwitchType(expr=expr, rxui=rxui, envir=envir) + } else if (.isIniDropExpression(expr)) { + .iniHandleDropType(expr=expr, rxui=rxui, envir=envir) } else { # Can this error be improved to clarify what is the expression causing the # issue? It needs a single character string representation of something @@ -474,6 +648,24 @@ # (Maybe) update parameter order; this must be at the end so that the # parameter exists in case it is promoted from a covariate .iniHandleAppend(expr = expr, rxui = rxui, envir = envir, append = append) + + # now take out ETAs that no longer exist + .iniDf <- get("iniDf", envir=rxui) + .w <- which(is.na(.iniDf$neta1) & !is.na(.iniDf$neta2)) + .reassign <- FALSE + if (length(.w) > 0) { + .iniDf <- .iniDf[-.w, ] + .reassign <- TRUE + } + .iniDf <- get("iniDf", envir=rxui) + .w <- which(!is.na(.iniDf$neta1) & is.na(.iniDf$neta2)) + if (length(.w) > 0) { + .iniDf <- .iniDf[-.w, ] + .reassign <- TRUE + } + if (.reassign) { + assign("iniDf", .iniDf, envir=rxui) + } } # TODO: while nlmixr2est is changed @@ -525,16 +717,59 @@ } expr } +#' This gets the append arg for the ini({}) piping +#' +#' @param f this is the `try(force(append))` argument, +#' @param s this is the `as.character(substitute(append))` argument +#' @return corrected ini piping argument +#' +#' This is exported for creating new ini methods that have the same +#' requirements for piping +#' +#' @export +#' @author Matthew L. Fidler +#' @keywords internal +.iniGetAppendArg <- function(f, s) { + if (inherits(f, "try-error") && + checkmate::testCharacter(s, len=1, any.missing=FALSE, + pattern="^[.]*[a-zA-Z]+[a-zA-Z0-9._]*$", + min.chars = 1)) { + return(s) + } + if (is.null(f)) { + return(NULL) + } else if (checkmate::testCharacter(f, len=1, any.missing=FALSE, + pattern="^[.]*[a-zA-Z]+[a-zA-Z0-9._]*$", + min.chars = 1)) { + return(f) + } else if (is.infinite(f)) { + return(f) + } else if (checkmate::testIntegerish(f, len=1, any.missing=FALSE)) { + if (f < 0) { + stop("'append' cannot be a negative integer", call.=FALSE) + } + return(f) + } else if (checkmate::testLogical(f, len=1)) { + # NA for model piping prepends + if (is.na(f)) return(FALSE) + return(f) + } + stop("'append' must be NULL, logical, numeric, or character/expression of variable in model", + call.=FALSE) +} #' @export #' @rdname ini ini.rxUi <- function(x, ..., envir=parent.frame(), append = NULL) { + .s <- as.character(substitute(append)) + .f <- try(force(append), silent=TRUE) + append <- .iniGetAppendArg(.f, .s) .ret <- rxUiDecompress(.copyUi(x)) # copy so (as expected) old UI isn't affected by the call .iniDf <- .ret$iniDf .iniLines <- .quoteCallInfoLines(match.call(expand.dots = TRUE)[-(1:2)], envir=envir, iniDf= .iniDf) if (length(.iniLines) == 0L) return(.ret$iniFun) lapply(.iniLines, function(line) { - .iniHandleLine(expr = line, rxui = .ret, envir = envir, append = append) + .iniHandleLine(expr = line, rxui = .ret, envir = envir, append=append) }) if (inherits(x, "rxUi")) { .x <- rxUiDecompress(x) @@ -553,6 +788,9 @@ ini.rxUi <- function(x, ..., envir=parent.frame(), append = NULL) { #' @rdname ini #' @export ini.default <- function(x, ..., envir=parent.frame(), append = NULL) { + .s <- as.character(substitute(append)) + .f <- try(force(append), silent=TRUE) + append <- .iniGetAppendArg(.f, .s) .ret <- try(as.rxUi(x), silent = TRUE) if (inherits(.ret, "try-error")) { stop("cannot figure out what to do with the ini({}) function", call.=FALSE) diff --git a/R/piping-model.R b/R/piping-model.R index 20066d00c..d6c63fe01 100644 --- a/R/piping-model.R +++ b/R/piping-model.R @@ -1,6 +1,7 @@ #' @export #' @rdname model -model.function <- function(x, ..., append=FALSE, auto=TRUE, cov=NULL, envir=parent.frame()) { +model.function <- function(x, ..., append=NULL, auto=getOption("rxode2.autoVarPiping", TRUE), + cov=NULL, envir=parent.frame()) { .modelLines <- .quoteCallInfoLines(match.call(expand.dots = TRUE)[-(1:2)], envir=envir) .ret <- rxUiDecompress(rxode2(x)) if (length(.modelLines) == 0) return(.ret$modelFun) @@ -10,7 +11,8 @@ model.function <- function(x, ..., append=FALSE, auto=TRUE, cov=NULL, envir=pare #' @export #' @rdname model -model.rxUi <- function(x, ..., append=FALSE, auto=TRUE, cov=NULL, envir=parent.frame()) { +model.rxUi <- function(x, ..., append=NULL, auto=getOption("rxode2.autoVarPiping", TRUE), + cov=NULL, envir=parent.frame()) { .modelLines <- .quoteCallInfoLines(match.call(expand.dots = TRUE)[-(1:2)], envir=envir) .ret <- rxUiDecompress(.copyUi(x)) # copy so (as expected) old UI isn't affected by the call if (length(.modelLines) == 0) return(.ret$modelFun) @@ -30,7 +32,8 @@ model.rxUi <- function(x, ..., append=FALSE, auto=TRUE, cov=NULL, envir=parent.f #' @export #' @rdname model -model.rxode2 <- function(x, ..., append=FALSE, auto=TRUE, cov=NULL, envir=parent.frame()) { +model.rxode2 <- function(x, ..., append=NULL, auto=getOption("rxode2.autoVarPiping", TRUE), + cov=NULL, envir=parent.frame()) { .modelLines <- .quoteCallInfoLines(match.call(expand.dots = TRUE)[-(1:2)], envir=envir) x <- as.function(x) .ret <- suppressMessages(rxUiDecompress(rxode2(x))) @@ -53,7 +56,8 @@ model.rxModelVars <- model.rxode2 #' @return New UI #' @author Matthew L. Fidler #' @export -.modelHandleModelLines <- function(modelLines, rxui, modifyIni=FALSE, append=FALSE, auto=TRUE, +.modelHandleModelLines <- function(modelLines, rxui, modifyIni=FALSE, append=NULL, + auto=getOption("rxode2.autoVarPiping", TRUE), cov=NULL, envir) { checkmate::assertLogical(modifyIni, any.missing=FALSE, len=1) ## checkmate::assertLogical(append, any.missing=TRUE, len=1) @@ -62,8 +66,34 @@ model.rxModelVars <- model.rxode2 .varSelect$cov <- cov .doAppend <- FALSE rxui <- rxUiDecompress(rxui) + .ll <- length(rxui$lstExpr) if (!is.null(.nsEnv$.quoteCallInfoLinesAppend)) { - .ll <- length(rxui$lstExpr) + if (identical(.nsEnv$.quoteCallInfoLinesAppend, quote(Inf))) { + .nsEnv$.quoteCallInfoLinesAppend <- NULL + append <- TRUE + } else if (identical(.nsEnv$.quoteCallInfoLinesAppend, quote(-Inf))) { + .nsEnv$.quoteCallInfoLinesAppend <- NULL + append <- NA + } else if (identical(.nsEnv$.quoteCallInfoLinesAppend, quote(0))) { + .nsEnv$.quoteCallInfoLinesAppend <- NULL + append <- NA + } else if (checkmate::testIntegerish(.nsEnv$.quoteCallInfoLinesAppend, lower=.ll)) { + .nsEnv$.quoteCallInfoLinesAppend <- NULL + append <- TRUE + } + } + if (!is.null(.nsEnv$.quoteCallInfoLinesAppend)) { + if (checkmate::testIntegerish(.nsEnv$.quoteCallInfoLinesAppend, lower=0, upper=.ll)) { + .nsEnv$.quoteCallInfoLinesAppend <- .getLhs(rxui$lstExpr[[.nsEnv$.quoteCallInfoLinesAppend]]) + } else if (checkmate::testCharacter(.nsEnv$.quoteCallInfoLinesAppend, len=1, any.missing=FALSE, + min.chars = 1)) { + .tmp <- try(str2lang(.nsEnv$.quoteCallInfoLinesAppend), silent=TRUE) + if (inherits(.tmp, "try-error")) { + stop("'append' must refer to a LHS model line when a character", + call. = FALSE) + } + .nsEnv$.quoteCallInfoLinesAppend <- .tmp + } .w <- which(vapply(seq_len(.ll), function(i) { .lhs <- .getLhs(rxui$lstExpr[[i]]) @@ -108,7 +138,7 @@ model.rxModelVars <- model.rxode2 envir=rxui) } .doAppend <- TRUE - } else if (is.logical(append) && length(append) == 1L && is.na(append)) { + } else if (is.logical(append) && length(append) == 1L && (is.na(append) || !append)) { assign("lstExpr", c(modelLines, rxui$lstExpr), envir=rxui) .doAppend <- TRUE } else if (isTRUE(append)) { @@ -117,18 +147,27 @@ model.rxModelVars <- model.rxode2 } if (.doAppend) { # in pre-pending or appending, lines are only added - .lhs <- character() - .rhs <- character() + .lhs <- character(0) + .rhs <- character(0) + .lhs0 <- c(rxui$mv0$lhs, rxui$mv0$state, rxui$allCovs, rxui$iniDf$name) for (x in modelLines) { .isTilde <- .isEndpoint(x) if (.isTilde || .isAssignment(x)) { .rhs <- unique(c(.getVariablesFromExpression(.getRhs(x), ignorePipe=.isTilde), .rhs)) .lhs <- unique(c(.getVariablesFromExpression(.getLhs(x)), .lhs)) } - .rhs <- setdiff(.rhs, c(.lhs, rxui$mv0$lhs, rxui$mv0$state, rxui$allCovs, rxui$iniDf$name)) + .rhs <- setdiff(.rhs, c(.lhs, .lhs0)) if (isTRUE(auto)) { for (v in .rhs) { - .addVariableToIniDf(v, rxui, promote=ifelse(.isTilde,NA, TRUE)) + .isCov <- grepl(.varSelect$covariateExceptions, tolower(v)) + .isTheta <- !.isCov && grepl(.varSelect$thetaModelReg, v) + .isEta <- !.isCov && grepl(.varSelect$etaModelReg, v) + if (.isTilde || .isTheta || .isEta) { + .addVariableToIniDf(v, rxui, + promote=ifelse(.isTilde,NA, + TRUE)) + .lhs <- c(.lhs, v) + } } } } @@ -167,6 +206,14 @@ model.rxModelVars <- model.rxode2 .matchesLangTemplate(expr, str2lang(". = .")) } +.isTildeExpr <- function(expr) { + .matchesLangTemplate(expr, str2lang("~ .")) +} + +.isIniDropExpression <- function(expr) { + .matchesLangTemplate(expr, str2lang("- .")) +} + # get the left hand side of an assignment or endpoint; returns NULL if the input # is not an assignment or endpoint .getLhs <- function(expr) { @@ -189,7 +236,8 @@ model.rxModelVars <- model.rxode2 ret <- NULL if (.isEndpoint(expr)) { lhs <- .getLhs(expr) - if (.matchesLangTemplate(lhs, str2lang("-."))) { + if (.matchesLangTemplate(lhs, str2lang("-.")) || + .matchesLangTemplate(lhs, str2lang(". <- NULL"))) { # If it is a drop expression with a minus sign, grab the non-minus part ret <- lhs[[2]] } @@ -199,7 +247,8 @@ model.rxModelVars <- model.rxode2 .getModelLineEquivalentLhsExpressionDropDdt <- function(expr) { .expr3 <- NULL - if (.matchesLangTemplate(x = expr, template = str2lang("-d/dt(.name)"))) { + if (.matchesLangTemplate(x = expr, template = str2lang("-d/dt(.name)")) || + .matchesLangTemplate(x = expr, template = str2lang("d/dt(.name) <- NULL"))) { .expr3 <- expr # remove the minus sign from the numerator .expr3[[2]] <- .expr3[[2]][[2]] @@ -474,6 +523,48 @@ attr(rxUiGet.mvFromExpression, "desc") <- "Calculate model variables from stored } NULL } +#' This checks the different types of drop assignments +#' +#' +#' @param prefix The prefix of the drop assignment +#' @param line The line expression to check +#' @return logical to say if this matches the prefix +#' @author Matthew L. Fidler +#' @noRd +.isDropNullType <- function(prefix, line) { + .e1 <- str2lang(paste0(prefix, " <- NULL")) + .e2 <- str2lang(paste0(prefix, " = NULL")) + .e3 <- str2lang(paste0(prefix, " ~ NULL")) + if (.matchesLangTemplate(line, .e1)) return(TRUE) + if (.matchesLangTemplate(line, .e3)) return(TRUE) + if (.matchesLangTemplate(line, .e2)) return(TRUE) + FALSE +} +#' This changes NULL assignment line to a -drop line +#' +#' @param line Line to change if necessary +#' @return Drop line normalized to be `-line` instead of `line <- NULL` +#' @author Matthew L. Fidler +#' @noRd +.changeDropNullLine <- function(line) { + if (.isDropNullType("d/dt(.name)", line)) { + .ret <- line[[2]] + .ret[[2]] <- as.call(list(quote(`-`), .ret[[2]])) + return(.ret) + } + if (.isDropNullType(".name", line) || + .isDropNullType("lag(.name)", line) || + .isDropNullType("alag(.name)", line) || + .isDropNullType("f(.name)", line) || + .isDropNullType("F(.name)", line) || + .isDropNullType("rate(.name)", line) || + .isDropNullType("dur(.name)", line) || + .isDropNullType(".name(0)", line) + ) { + return(as.call(list(quote(`-`), line[[2]]))) + } + line +} #' Modify the error lines/expression #' @@ -488,6 +579,7 @@ attr(rxUiGet.mvFromExpression, "desc") <- "Calculate model variables from stored .err <- NULL .env <- environment() lapply(lines, function(line) { + line <- .changeDropNullLine(line) if (modifyIni && .isQuotedLineRhsModifiesEstimates(line, rxui)) { .iniHandleFixOrUnfix(line, rxui, envir=envir) } else { @@ -693,7 +785,7 @@ attr(rxUiGet.errParams, "desc") <- "Get the error-associated variables" #' rxSetPipingAuto <- function(thetamodelVars=rex::rex(or("tv", "t", "pop", "POP", "Pop", "TV", "T", "cov", "err", "eff")), - covariateExceptions = rex::rex(start, or("wt", "sex", "crcl"), end), + covariateExceptions = rex::rex(start, or("wt", "sex", "crcl", "kout"), end), etaParts=c("eta", "ETA", "Eta", "ppv", "PPV", "Ppv", "iiv", "Iiv", "bsv", "Bsv", "BSV","bpv", "Bpv", "BPV", "psv", "PSV", "Psv") @@ -902,7 +994,6 @@ rxSetCovariateNamesForPiping <- function(covariates=NULL) { } } } - if (all(is.na(.iniDf$ntheta))) { .theta <- 1 } else { diff --git a/R/piping.R b/R/piping.R index 0288e82a9..b75984aeb 100644 --- a/R/piping.R +++ b/R/piping.R @@ -1,4 +1,4 @@ -#' This copies the rxode2 UI object so it can be modified +#' This copies the rxode2 UI object so it can be modified #' #' @param ui Original UI object #' @return Copied UI object @@ -141,9 +141,22 @@ .cur <- NULL if (length(.bracketExpression) == 1) { # evaulate expression - .cur <- eval(.bracketExpression, envir=envir) - if (length(.cur) > 1) { - if (identical(.cur[[1]], quote(`{`))) { + .cur <- try(eval(.bracketExpression, envir=envir), silent=TRUE) + if (inherits(.cur, "try-error")) { + } else if (length(.cur) > 1) { + if (inherits(.cur, "character")) { + if (is.null(names(.cur))) { + .cur <- lapply(.cur, function(x) { + str2lang(x) + }) + } else { + .cur <- lapply(names(.cur), function(x) { + str2lang(paste0(x, "<-", .cur[[x]])) + }) + } + .cur <- as.call(c(list(quote(`{`)),.cur)) + .bracketExpression <- .cur + } else if (identical(.cur[[1]], quote(`{`))) { .bracketExpression <- .cur } } @@ -282,10 +295,12 @@ } else if (identical(.quoted[[1]], quote(`as.formula`))) { .quoted <- .quoted[[2]] } else if (identical(.quoted[[1]], quote(`~`))) { - .quoted[[3]] <- .iniSimplifyFixUnfix(.quoted[[3]]) - if (identical(.quoted[[3]], quote(`fix`)) || - identical(.quoted[[3]], quote(`unfix`))) { - .quoted <- as.call(list(quote(`<-`), .quoted[[2]], .quoted[[3]])) + if (length(.quoted) == 3L) { + .quoted[[3]] <- .iniSimplifyFixUnfix(.quoted[[3]]) + if (identical(.quoted[[3]], quote(`fix`)) || + identical(.quoted[[3]], quote(`unfix`))) { + .quoted <- as.call(list(quote(`<-`), .quoted[[2]], .quoted[[3]])) + } } } else if (identical(.quoted[[1]], quote(`$`))) { .tmp <- try(eval(.quoted), silent=TRUE) diff --git a/R/plot.R b/R/plot.R index 54512602b..f6cc66a2d 100644 --- a/R/plot.R +++ b/R/plot.R @@ -121,6 +121,9 @@ rxTheme <- function(base_size = 11, base_family = "", if (!.xgxr) { return(NULL) } + if (is.null(.unit)) { + return(NULL) + } .timex <- xgxr::xgx_scale_x_time_units(.unit) if (inherits(.timex, "list")) { .w <- which(sapply(seq_along(.timex), function(x) { @@ -134,11 +137,34 @@ rxTheme <- function(base_size = 11, base_family = "", } if (inherits(.dat$time, "units")) { .unit <- as.character(units(.dat$time)) + .unitNames <- c(s="second", + sec="second", + second="second", + min="minute", + minute="minute", + h="hour", + hr="hour", + hour="hour", + d="day", + day="day", + days="day", + week="week", + weeks="week", + month="month", + months="month", + year="year", + years="year", + yr="year") + .unit <- setNames(.unitNames[.unit], NULL) + if (is.na(.unit)) { + .timex <- .xgxrT(NULL) + .xlab <- xlab(xlab) + } .dat$time <- .dropUnits(.dat$time) .timex <- .xgxrT(.unit) .xlab <- xlab(sprintf("%s [%s]", xlab, .unit)) } else { - .timex <- .xgxrT("h") + .timex <- .xgxrT(NULL) .xlab <- xlab(xlab) } list(timex=.timex, xlab=.xlab, dat=.dat) @@ -150,8 +176,8 @@ rxTheme <- function(base_size = 11, base_family = "", stopifnot(length(log) == 1) stopifnot(is.character(log)) stopifnot(log %in% c("", "x", "y", "xy", "yx")) - useLogX <- nchar(log) == 2 | log == "x" - useLogY <- nchar(log) == 2 | log == "y" + useLogX <- nchar(log) == 2L || log == "x" + useLogY <- nchar(log) == 2L || log == "y" useXgxr <- getOption("rxode2.xgxr", TRUE) && requireNamespace("xgxr", quietly = TRUE) diff --git a/R/reexport.R b/R/reexport.R index 3dd96e1a6..3b65d4e47 100644 --- a/R/reexport.R +++ b/R/reexport.R @@ -272,3 +272,7 @@ rxode2parse::.getLastIdLvl #' @importFrom rxode2random .expandPars #' @export rxode2random::.expandPars + +#' @importFrom rxode2et toTrialDuration +#' @export +rxode2et::toTrialDuration diff --git a/R/rxUiGet.R b/R/rxUiGet.R index 9d26a76db..8393dae70 100644 --- a/R/rxUiGet.R +++ b/R/rxUiGet.R @@ -24,6 +24,12 @@ #' @export `$.rxUi` <- function(obj, arg, exact = TRUE) { + # need to assign environment correctly for UDF + # + # The model() and rxode2() assign the parent environments for UDF + # parsing, if the object is in that environment lock it and then + # unlock on exit + rxode2parse::.udfEnvSet(list(parent.frame(1), parent.frame(2))) rxUiGet(.uiToRxUiGet(obj=obj, arg=arg, exact=exact)) } @@ -179,7 +185,22 @@ rxUiGet.funPrint <- function(x, ...) { .ret <- vector("list", length(.ls) + ifelse(.hasIni, 3, 2)) .ret[[1]] <- quote(`{`) for (.i in seq_along(.ls)) { - .ret[[.i + 1]] <- eval(parse(text=paste("quote(", .ls[.i], "<-", deparse1(.x$meta[[.ls[.i]]]), ")"))) + .var <- .ls[.i] + .val <- .x$meta[[.ls[.i]]] + .isLotri <- FALSE + if (checkmate::testMatrix(.val, any.missing=FALSE, row.names="strict", col.names="strict")) { + .dn <- dimnames(.val) + if (identical(.dn[[1]], .dn[[2]]) && isSymmetric(.val)) { + class(.val) <- c("lotriFix", class(.val)) + .val <- as.expression(.val) + .val <- bquote(.(str2lang(.var)) <- .(.val)) + .ret[[.i + 1]] <- .val + .isLotri <- TRUE + } + } + if (!.isLotri) { + .ret[[.i + 1]] <- eval(parse(text=paste("quote(", .var, "<-", deparse1(.val), ")"))) + } } .theta <- x$theta .omega <- x$omega @@ -200,7 +221,7 @@ attr(rxUiGet.funPrint, "desc") <- "Normalized, quoted model function (for printi rxUiGet.fun <- function(x, ...) { .ret <- rxUiGet.funPrint(x, ...) .ret2 <- function() { - + } body(.ret2) <- as.call(.ret) .ret2 @@ -229,6 +250,7 @@ rxUiGet.iniFun <- function(x, ...) { } attr(rxUiGet.iniFun, "desc") <- "normalized, quoted `ini()` block" + #' @export #' @rdname rxUiGet rxUiGet.modelFun <- function(x, ...) { @@ -237,6 +259,11 @@ rxUiGet.modelFun <- function(x, ...) { } attr(rxUiGet.modelFun, "desc") <- "normalized, quoted `model()` block" +#' @export +#' @rdname rxUiGet +rxUiGet.model <- rxUiGet.modelFun + + #' @export #' @rdname rxUiGet rxUiGet.modelDesc <- function(x, ...) { @@ -359,8 +386,15 @@ attr(rxUiGet.covLhs, "desc") <- "cov->lhs translation" #' @rdname rxUiGet rxUiGet.default <- function(x, ...) { .arg <- class(x)[1] - if (!exists(.arg, envir=x[[1]])) return(NULL) - get(.arg, x[[1]]) + .ui <- x[[1]] + if (!exists(.arg, envir=.ui)) { + .meta <- get("meta", envir=.ui) + if (exists(.arg, envir=.meta)) { + return(get(.arg, envir=.meta)) + } + return(NULL) + } + get(.arg, .ui) } .rxUiGetEnvInfo <- c("model"="Original Model (with comments if available)", diff --git a/R/rxValidate.R b/R/rxValidate.R index 84ed0b9b6..3743e303b 100644 --- a/R/rxValidate.R +++ b/R/rxValidate.R @@ -1,3 +1,4 @@ + #' Validate rxode2 #' This allows easy validation/qualification of nlmixr by running the #' testing suite on your system. @@ -53,5 +54,3 @@ rxValidate <- function(type = NULL, skipOnCran=TRUE) { #' @rdname rxValidate #' @export rxTest <- rxValidate - - diff --git a/R/rxode2.R b/R/rxode2.R index edcaa3822..ab880b93a 100644 --- a/R/rxode2.R +++ b/R/rxode2.R @@ -83,6 +83,8 @@ NA_LOGICAL <- NA # nolint #' print on every step (except ME/indLin), otherwise when `FALSE` #' print only when calculating the `d/dt` #' +#' @inheritParams rxode2parse::rxode2parse +#' #' @details #' #' The `Rx` in the name `rxode2` is meant to suggest the @@ -96,7 +98,7 @@ NA_LOGICAL <- NA # nolint #' @includeRmd man/rmdhunks/rxode2-create-models.Rmd #' #' @includeRmd man/rmdhunks/rxode2-syntax-hunk.Rmd -#' +#' #' @return An object (environment) of class `rxode2` (see Chambers and Temple Lang (2001)) #' consisting of the following list of strings and functions: #' @@ -142,7 +144,7 @@ NA_LOGICAL <- NA # nolint #' #' `atol`: a numeric absolute tolerance (1e-08 by default); #' -#' `rtol`: a numeric relative tolerance (1e-06 by default).e +#' `rtol`: a numeric relative tolerance (1e-06 by default). #' #' The output of \dQuote{solve} is a matrix with as many rows as there #' are sampled time points and as many columns as system variables @@ -273,7 +275,9 @@ rxode2 <- # nolint linCmtSens = c("linCmtA", "linCmtB", "linCmtC"), indLin = FALSE, verbose = FALSE, - fullPrint=getOption("rxode2.fullPrint", FALSE)) { + fullPrint=getOption("rxode2.fullPrint", FALSE), + envir=parent.frame()) { + rxode2parse::.udfEnvSet(envir) assignInMyNamespace(".rxFullPrint", fullPrint) rxSuppressMsg() rxode2parse::rxParseSuppressMsg() @@ -411,7 +415,7 @@ rxode2 <- # nolint .rx$.clearME() }) .rx$.rxWithWd(wd, { - .rx$.extraC(extraC) + rxode2parse::.extraC(extraC) if (missing.modName) { .rxDll <- .rx$rxCompile(.mv, debug = debug, @@ -432,7 +436,7 @@ rxode2 <- # nolint }) }) })) - .extraC(extraC) + rxode2parse::.extraC(extraC) .env$compile() .env$get.modelVars <- eval(bquote(function() { with(.(.env), { @@ -633,23 +637,28 @@ rxGetModel <- function(model, calcSens = NULL, calcJac = NULL, collapseModel = N model <- model[-length(model)] } model <- paste(model, collapse = "\n") - } else if (is(model, "function") || is(model, "call")) { + } else if (inherits(model, "function") || inherits(model, "call")) { model <- deparse(body(model)) if (model[1] == "{") { model <- model[-1] model <- model[-length(model)] } model <- paste(model, collapse = "\n") - } else if (is(model, "name")) { + } else if (inherits(model, "name")) { model <- eval(model) - } else if (is(model, "character") || is(model, "rxModelText")) { + } else if (inherits(model, "character") || inherits(model, "rxModelText")) { model <- as.vector(model) - } else if (is(model, "rxode2")) { + } else if (inherits(model, "rxode2")) { model <- rxModelVars(model) ## class(model) <- NULL; - } else if (is(model, "rxModelVars")) { + } else if (inherits(model, "rxModelVars")) { + } else if (inherits(model, "rxDll")) { + model <- model$args$model } else { - stop("cannot figure out how to handle the model argument", call. = FALSE) + model <- rxModelVars(model) + if (!inherits(model, "rxModelVars")) { + stop("cannot figure out how to handle the model argument", call. = FALSE) + } } .ret <- rxModelVars(model) if (!is.null(calcSens)) { @@ -1039,7 +1048,7 @@ rxMd5 <- function(model, # Model File rxode2.calculate.sensitivity) .ret <- c( .ret, .tmp, .rxIndLinStrategy, .rxIndLinState, - .linCmtSens, ls(.symengineFs), .rxFullPrint + .linCmtSens, rxode2parse::.udfMd5Info(), .rxFullPrint ) if (is.null(.md5Rx)) { .tmp <- getLoadedDLLs()$rxode2 @@ -1235,13 +1244,13 @@ rxDllLoaded <- rxIsLoaded #' #' @return An rxDll object that has the following components #' -#' * `dll`{DLL path} -#' * `model`{model specification} -#' * `.c`{A function to call C code in the correct context from the DLL -#' using the [.C()] function.} -#' * `.call`{A function to call C code in the correct context from the DLL -#' using the [.Call()] function.} -#' * `args`{A list of the arguments used to create the rxDll object.} +#' * `dll` DLL path +#' * `model` model specification +#' * `.c` A function to call C code in the correct context from the DLL +#' using the [.C()] function. +#' * `.call` A function to call C code in the correct context from the DLL +#' using the [.Call()] function. +#' * `args` A list of the arguments used to create the rxDll object. #' @inheritParams rxode2 #' @seealso [rxode2()] #' @author Matthew L.Fidler @@ -1275,6 +1284,7 @@ rxCompile <- function(model, dir, prefix, force = FALSE, modName = NULL, .cc <- gsub("\n", "", .cc) .cflags <- rawToChar(sys::exec_internal(file.path(R.home("bin"), "R"), c("CMD", "config", "CFLAGS"))$stdout) .cflags <- gsub("\n", "", .cflags) + .cflags <- paste0(.cflags, " -O", getOption("rxode2.compile.O", "2")) .shlibCflags <- rawToChar(sys::exec_internal(file.path(R.home("bin"), "R"), c("CMD", "config", "SHLIB_CFLAGS"))$stdout) .shlibCflags <- gsub("\n", "", .shlibCflags) .cpicflags <- rawToChar(sys::exec_internal(file.path(R.home("bin"), "R"), c("CMD", "config", "CPICFLAGS"))$stdout) @@ -1461,7 +1471,7 @@ rxCompile.rxModelVars <- function(model, # Model cat(.ret) sink() sink(.normalizePath(file.path(.dir, "extraC.h"))) - cat(.extraCnow) + cat(rxode2parse::.extraCnow()) sink() try(dyn.unload(.cDllFile), silent = TRUE) try(unlink(.cDllFile)) @@ -1766,17 +1776,17 @@ rxModels_ <- # nolint #' #' @return A list of rxode2 model properties including: #' -#' * `params`{ a character vector of names of the model parameters} -#' * `lhs`{ a character vector of the names of the model calculated parameters} -#' * `state`{ a character vector of the compartments in rxode2 object} -#' * `trans`{ a named vector of translated model properties +#' * `params` a character vector of names of the model parameters +#' * `lhs` a character vector of the names of the model calculated parameters +#' * `state` a character vector of the compartments in rxode2 object +#' * `trans` a named vector of translated model properties #' including what type of jacobian is specified, the `C` function prefixes, -#' as well as the `C` functions names to be called through the compiled model.} -#' * `md5`{a named vector that gives the digest of the model (`file_md5`) and the parsed model -#' (`parsed_md5`)} -#' * `model`{ a named vector giving the input model (`model`), +#' as well as the `C` functions names to be called through the compiled model. +#' * `md5` a named vector that gives the digest of the model (`file_md5`) and the parsed model +#' (`parsed_md5`) +#' * `model` a named vector giving the input model (`model`), #' normalized model (no comments and standard syntax for parsing, `normModel`), -#' and interim code that is used to generate the final C file `parseModel`} +#' and interim code that is used to generate the final C file `parseModel` #' #' @keywords internal #' @family Query model information diff --git a/R/rxrandom.R b/R/rxrandom.R index 1adf71b69..0cf3005a7 100644 --- a/R/rxrandom.R +++ b/R/rxrandom.R @@ -118,7 +118,7 @@ rxpois <- function(lambda, n = 1L, ncores = 1L) { #' et <- et(1, id = 1:2) #' #' s <- rxSolve(rx, et) -#' +#' #' } #' @export rxt <- function(df, n = 1L, ncores = 1L) { @@ -312,7 +312,7 @@ rxbeta <- function(shape1, shape2, n = 1L, ncores = 1L) { #' @return gamma random deviates #' #' @examples -#' +#' #' \donttest{ #' #' ## Use threefry engine @@ -725,8 +725,9 @@ rxnbinomMu <- function(size, mu, n = 1L, ncores = 1L) { #' ## This uses an arbitrary function to sample a non-homogenous Poisson process #' #' rxPp(10, 1 / 10, prob = function(x) { -#' 1 / x +#' 1/(1+abs(x)) #' }) +#' rxPp <- function(n, lambda, gamma = 1.0, prob = NULL, t0 = 0.0, tmax = Inf, randomOrder = FALSE) { checkmate::assertNumeric(t0, len = 1, any.missing = FALSE) checkmate::assertNumeric(tmax, len = 1, any.missing = FALSE, lower = t0) diff --git a/R/rxsolve.R b/R/rxsolve.R index 34a52723e..f6aacc4a1 100644 --- a/R/rxsolve.R +++ b/R/rxsolve.R @@ -1,4 +1,4 @@ - #' Options, Solving & Simulation of an ODE/solved system +#' Options, Solving & Simulation of an ODE/solved system #' #' This uses rxode2 family of objects, file, or model specification to #' solve a ODE system. There are many options for a solved rxode2 @@ -575,6 +575,8 @@ #' #' @inheritParams odeMethodToInt #' +#' @inheritParams rxode2parse::rxode2parse +#' #' @param useStdPow This uses C's `pow` for exponentiation instead of #' R's `R_pow` or `R_pow_di`. By default this is `FALSE` #' @@ -720,7 +722,9 @@ rxSolve <- function(object, params = NULL, events = NULL, inits = NULL, addlKeepsCov=FALSE, addlDropSs=TRUE, ssAtDoseTime=TRUE, - ss2cancelAllPending=FALSE) { + ss2cancelAllPending=FALSE, + envir=parent.frame()) { + rxode2parse::.udfEnvSet(list(envir, parent.frame(1))) if (is.null(object)) { .xtra <- list(...) .nxtra <- names(.xtra) @@ -1123,6 +1127,7 @@ rxSolve <- function(object, params = NULL, events = NULL, inits = NULL, ssAtDoseTime=ssAtDoseTime, ss2cancelAllPending=ss2cancelAllPending, .zeros=unique(.zeros) + ) class(.ret) <- "rxControl" return(.ret) @@ -1133,17 +1138,46 @@ rxSolve <- function(object, params = NULL, events = NULL, inits = NULL, #' @rdname rxSolve #' @export rxSolve.function <- function(object, params = NULL, events = NULL, inits = NULL, ..., - theta = NULL, eta = NULL) { + theta = NULL, eta = NULL, envir=parent.frame()) { + rxode2parse::.udfEnvSet(list(envir, parent.frame(1))) .object <- rxode2(object) do.call("rxSolve", c(list(object=.object, params = params, events = events, inits = inits), list(...), - list(theta = theta, eta = eta))) + list(theta = theta, eta = eta, envir=envir))) +} + +.uiRxControl <- function(ui, params = NULL, events = NULL, inits = NULL, ..., + theta = NULL, eta = NULL) { + .ctl <- rxControl() + if (exists("meta", envir=ui)) { + .meta <- get("meta", ui) + } else { + .meta <- new.env(parent=emptyenv()) + } + .lst <- list(...) + .nlst <- names(.lst) + .w <- which(vapply(names(.ctl), function(x) { + !(x %in% .nlst) && exists(x, envir=.meta) + }, logical(1), USE.NAMES=FALSE)) + .extra <- NULL + if (length(.w) > 0) { + .v <- names(.ctl)[.w] + .minfo(paste0("rxControl items read from fun: '", + paste(.v, collapse="', '"), "'")) + .extra <- setNames(lapply(.v, function(x) { + get(x, envir=.meta) + }), .v) + + } + do.call(rxSolve, c(list(NULL, params = NULL, events = NULL, inits = NULL), + .lst, .extra, + list(theta=theta, eta=eta))) } .rxSolveFromUi <- function(object, params = NULL, events = NULL, inits = NULL, ..., theta = NULL, eta = NULL) { - .rxControl <- rxSolve(NULL, params = params, events = events, inits = inits, ..., - theta = theta, eta = eta) + .rxControl <- .uiRxControl(object, params = params, events = events, inits = inits, ..., + theta = theta, eta=eta) if (rxIs(params, "rx.event")) { if (!is.null(events)) { .tmp <- events @@ -1187,6 +1221,24 @@ rxSolve.function <- function(object, params = NULL, events = NULL, inits = NULL, .rxControl$omega <- NULL } } + if (inherits(.rxControl$omega, "matrix")) { + .omega <- .rxControl$omega + .v <- vapply(dimnames(.omega)[[1]], + function(v) { + !(v %in% names(params)) + }, logical(1), USE.NAMES = FALSE) + if (length(.v) == 1L) { + if (!.v) .rxControl$omega <- NULL + } else { + .omega <- .omega[.v, .v] + if (all(dim(.omega) == c(0L, 0L))) { + .rxControl$omega <- NULL + } else { + .rxControl$omega <- .omega + } + } + + } if (inherits(.rxControl$omega, "matrix") && all(dim(.rxControl$omega) == c(0,0))) { .rxControl$omega <- NULL @@ -1202,6 +1254,24 @@ rxSolve.function <- function(object, params = NULL, events = NULL, inits = NULL, .rxControl$sigma <- NULL } } + if (inherits(.rxControl$sigma, "matrix")) { + .sigma <- .rxControl$sigma + .v <- vapply(dimnames(.sigma)[[1]], + function(v) { + !(v %in% names(params)) + }, logical(1), USE.NAMES = FALSE) + if (length(.v) == 1L) { + if (!.v) .rxControl$sigma <- NULL + } else { + .sigma <- .sigma[.v, .v, drop = FALSE] + if (all(dim(.sigma) == c(0L, 0L))) { + .rxControl$sigma <- NULL + } else { + .rxControl$sigma <- .sigma + } + } + + } if (inherits(.rxControl$sigma, "matrix") && all(dim(.rxControl$sigma) == c(0,0))) { .rxControl$sigma <- NULL @@ -1219,7 +1289,8 @@ rxSolve.function <- function(object, params = NULL, events = NULL, inits = NULL, #' @rdname rxSolve #' @export rxSolve.rxUi <- function(object, params = NULL, events = NULL, inits = NULL, ..., - theta = NULL, eta = NULL) { + theta = NULL, eta = NULL, envir=parent.frame()) { + rxode2parse::.udfEnvSet(list(object$meta, envir, parent.frame(1))) if (inherits(object, "rxUi")) { object <- rxUiDecompress(object) } @@ -1238,7 +1309,7 @@ rxSolve.rxUi <- function(object, params = NULL, events = NULL, inits = NULL, ... if (is.null(.lst$omega) && is.null(.lst$sigma)) { .pred <- TRUE if (!.hasIpred && any(rxModelVars(.lst[[1]])$lhs == "ipredSim")) { - .lst$drop <- c(.lst$drop, "ipredSim") + .lst$drop <- c(.lst$drop, "ipredSim") } } .ret <- do.call("rxSolve.default", .lst) @@ -1266,7 +1337,8 @@ rxSolve.rxode2tos <- rxSolve.rxUi #' @rdname rxSolve #' @export rxSolve.nlmixr2FitData <- function(object, params = NULL, events = NULL, inits = NULL, ..., - theta = NULL, eta = NULL) { + theta = NULL, eta = NULL, envir=parent.frame()) { + rxode2parse::.udfEnvSet(list(envir, parent.frame(1))) .lst <- .rxSolveFromUi(object, params = params, events = events, inits = inits, ..., theta = theta, eta = eta) .rxControl <- .lst[[2]] .env <- object$env @@ -1300,7 +1372,8 @@ rxSolve.nlmixr2FitCore <- rxSolve.nlmixr2FitData #' @rdname rxSolve #' @export rxSolve.default <- function(object, params = NULL, events = NULL, inits = NULL, ..., - theta = NULL, eta = NULL) { + theta = NULL, eta = NULL, envir=parent.frame()) { + rxode2parse::.udfEnvSet(list(envir, parent.frame(1))) on.exit({ .clearPipe() .asFunctionEnv$rx <- NULL @@ -1671,6 +1744,7 @@ rxSolve.default <- function(object, params = NULL, events = NULL, inits = NULL, } .minfo(sprintf("omega/sigma items treated as zero: '%s'", paste(.ctl$.zeros, collapse="', '"))) } + if (rxode2.debug) { .envReset$ret <- .collectWarnings(rxSolveSEXP(object, .ctl, .nms, .xtra, params, events, inits, @@ -1754,6 +1828,7 @@ predict.function <- function(object, ...) { #' @rdname rxSolve #' @export predict.rxUi <- function(object, ...) { + rxode2parse::.udfEnvSet(list(object$meta, parent.frame(1))) rxSolve(object, ...) } @@ -2004,8 +2079,9 @@ drop_units.rxSolve <- function(x) { #' @rdname rxSolve #' @export -rxControl <- function(..., params = NULL, events = NULL, inits = NULL) { - rxSolve(object = NULL, params = params, events = events, inits = inits, ...) +rxControl <- function(..., params = NULL, events = NULL, inits = NULL, envir=parent.frame()) { + rxSolve(object = NULL, params = params, events = events, inits = inits, ..., + envir=envir) } #' @export @@ -2053,6 +2129,7 @@ odeMethodToInt <- function(method = c("liblsoda", "lsoda", "dop853", "indLin")) } + #' This updates the tolerances based on the sensitivity equations #' #' This assumes the normal ODE equations are the first equations and diff --git a/R/symengine.R b/R/symengine.R index 6c56c9bca..b15c31253 100644 --- a/R/symengine.R +++ b/R/symengine.R @@ -67,7 +67,11 @@ regIfOrElse <- rex::rex(or(regIf, regElse)) "rxGt" = c("(", ">", ")"), "rxLt" = c("(", "<", ")"), "rxAnd" = c("(", "&&", ")"), - "rxOr" = c("(", "||", ")") + "rxOr" = c("(", "||", ")"), + "R_pow"=c("(", ")^(", ")"), + "R_pow_di"=c("(", ")^(", ")"), + "Rx_pow"=c("(", ")^(", ")"), + "Rx_pow_di"=c("(", ")^(", ")") ) ## atan2 @@ -260,52 +264,29 @@ regIfOrElse <- rex::rex(or(regIf, regElse)) "rt" = 1 ) -.rxSEeqUsr <- NULL - -.rxCcode <- NULL -.symengineFs <- new.env(parent = emptyenv()) - -.extraCnow <- "" -.extraC <- function(extraC = NULL) { - if (!is.null(extraC)) { - if (file.exists(extraC)) { - .ret <- sprintf("#include \"%s\"\n", extraC) - } else { - .ret <- paste(extraC, collapse = "\n") - } - } else { - .ret <- "" - } - if (length(.rxCcode) > 0L) { - .ret <- sprintf("%s\n%s\n", .ret, paste(.rxCcode, collapse = "\n")) - } - assignInMyNamespace(".extraCnow", .ret) - return(invisible()) -} - -#' Add user function to rxode2 +#' Add/Create C functions for use in rxode2 #' -#' This adds a user function to rxode2 that can be called. If needed, -#' these functions can be differentiated by numerical differences or -#' by adding the derivatives to rxode2's internal derivative table -#' with [rxD()] +#' @inheritParams rxode2parse::rxFunParse #' -#' @param name This gives the name of the user function -#' @param args This gives the arguments of the user function -#' @param cCode This is the C-code for the new function -#' @return nothing -#' @author Matthew L. Fidler +#' @param name This can either give the name of the user function or +#' be a simple R function that you wish to convert to C. If you +#' have rxode2 convert the R function to C, the name of the function +#' will match the function name provided and the number of arguments +#' will match the R function provided. Hence, if you are providing +#' an R function for conversion to C, the rest of the arguments are +#' implied. +#' @export #' @examples #' \donttest{ -#' ## Right now rxode2 is not aware of the function f +#' ## Right now rxode2 is not aware of the function fun #' ## Therefore it cannot translate it to symengine or #' ## Compile a model with it. #' #' try(rxode2("a=fun(a,b,c)")) #' #' ## Note for this approach to work, it cannot interfere with C -#' ## function names or reserved rxode2 specical terms. Therefore -#' ## f(x) would not work since f is an alias for bioaviability. +#' ## function names or reserved rxode2 special terms. Therefore +#' ## f(x) would not work since f is an alias for bioavailability. #' #' fun <- " #' double fun(double a, double b, double c) { @@ -341,44 +322,98 @@ regIfOrElse <- rex::rex(or(regIf, regElse)) #' # You can also remove the functions by `rxRmFun` #' #' rxRmFun("fun") +#' +#' # you can also use R functions directly in rxode2 +#' +#' +#' gg <- function(x, y) { +#' x + y +#' } +#' +#' f <- rxode2({ +#' z = gg(x, y) +#' }) +#' +#' +#' e <- et(1:10) |> as.data.frame() +#' +#' e$x <- 1:10 +#' e$y <- 21:30 +#' +#' rxSolve(f, e) +#' +#' # Note that since it touches R, it can only run single-threaded. +#' # There are also requirements for the function: +#' # +#' # 1. It accepts one value per argument (numeric) +#' # +#' # 2. It returns one numeric value +#' +#' # If it is a simple function (like gg) you can also convert it to C +#' # using rxFun and load it into rxode2 +#' +#' rxFun(gg) +#' +#' rxSolve(f, e) +#' +#' # to stop the recompile simply reassign the function +#' f <- rxode2(f) +#' +#' rxSolve(f, e) +#' +#' rxRmFun("gg") +#' rm(gg) +#' rm(f) +#' +#' +#' # You can also automatically convert a R function to R code (and +#' # calculate first derivatives) +#' +#' fun <- function(a, b, c) { +#' a^2+b*a+c +#' } +#' +#' rxFun(fun) +#' +#' # You can see the R code if you want with rxC +#' +#' message(rxC("fun")) +#' +#' # you can also remove both the function and the +#' # derivatives with rxRmFun("fun") +#' +#' rxRmFun("fun") +#' +#' #' } -#' @export rxFun <- function(name, args, cCode) { - if (!is.character(name) || length(name) != 1L) { - stop("name argument must be a length-one character vector", call. = FALSE) - } - if (missing(cCode)) stop("a new function requires a C function so it can be used in rxode2", call. = FALSE) - if (any(name == names(.rxSEeqUsr))) { - stop("already defined user function '", name, "', remove it fist ('rxRmFun')", - call. = FALSE - ) + if (missing(args) && missing(cCode)) { + .funName <- as.character(substitute(name)) + .lst <- rxFun2c(name, name=.funName) + .env <- new.env(parent=emptyenv()) + .env$d <- list() + lapply(seq_along(.lst), function(i) { + .cur <- .lst[[i]] + do.call(rxode2parse::rxFunParse, .cur[1:3]) + message("converted R function '", .cur$name, "' to C (will now use in rxode2)") + ## message(.cur$cCode) + if (length(.cur) == 4L) { + .env$d <- c(.env$d, list(.cur[[4]])) + } + }) + if (length(.env$d) > 0) { + message("Added derivative table for '", .lst[[1]]$name, "'") + rxD(.lst[[1]]$name, .env$d) + } + return(invisible()) } - suppressWarnings(rxRmFun(name)) - assignInMyNamespace(".rxSEeqUsr", c(.rxSEeqUsr, setNames(length(args), name))) - assignInMyNamespace(".rxCcode", c(.rxCcode, setNames(cCode, name))) - assign(name, symengine::Function(name), envir = .symengineFs) - return(invisible()) + rxode2parse::rxFunParse(name, args, cCode) } #' @rdname rxFun #' @export rxRmFun <- function(name) { - if (!is.character(name) || length(name) != 1L) { - stop("name argument must be a length-one character vector", - call. = FALSE - ) - } - if (!any(name == names(.rxSEeqUsr))) { - warning("no user function '", name, "' to remove", call. = FALSE) - } - .w <- which(name == names(.rxSEeqUsr)) - if (length(.w) == 1L) assignInMyNamespace(".rxSEeqUsr", .rxSEeqUsr[-.w]) - .w <- which(name == names(.rxCcode)) - if (length(.w) == 1L) assignInMyNamespace(".rxCcode", .rxCcode[-.w]) - .rxD <- rxode2parse::rxode2parseD() - if (exists(name, envir = .rxD)) rm(list = name, envir = .rxD) - if (exists(name, envir = .symengineFs)) rm(list = name, envir = .symengineFs) - return(invisible()) + rxode2parse::rxRmFunParse(name) } .SE1p <- c( @@ -467,6 +502,9 @@ rxD <- function(name, derivatives) { } +.rxToSE.envir <- new.env(parent=emptyenv()) +.rxToSE.envir$envir <- NULL + .promoteLinB <- FALSE #' rxode2 to symengine environment #' @@ -487,11 +525,16 @@ rxD <- function(name, derivatives) { #' - `forward` for forward differences #' - `central` for central differences #' - `error` for throwing an error for unknown derivatives +#' +#' @param parent is the parent environment to look for R-based user functions +#' #' @return An rxode2 symengine environment #' @author Matthew L. Fidler #' @export rxToSE <- function(x, envir = NULL, progress = FALSE, - promoteLinSens = TRUE) { + promoteLinSens = TRUE, parent = parent.frame()) { + rxode2parse::.udfEnvSet(parent) + .rxToSE.envir$parent <- parent assignInMyNamespace(".promoteLinB", promoteLinSens) assignInMyNamespace(".rxIsLhs", FALSE) assignInMyNamespace(".rxLastAssignedDdt", "") @@ -1188,7 +1231,7 @@ rxToSE <- function(x, envir = NULL, progress = FALSE, } .ret0 <- c(list(as.character(x[[1]])), lapply(x[-1], .rxToSE, envir = envir)) if (isEnv) envir$..curCall <- .lastCall - .SEeq <- c(.rxSEeq, .rxSEeqUsr) + .SEeq <- c(.rxSEeq, rxode2parse::.rxSEeqUsr()) .curName <- paste(.ret0[[1]]) .nargs <- .SEeq[.curName] if (.promoteLinB && .curName == "linCmtA") { @@ -1334,9 +1377,33 @@ rxToSE <- function(x, envir = NULL, progress = FALSE, ) } } else { - stop(sprintf(gettext("function '%s' or its derivatives are not supported in rxode2"), .fun), - call. = FALSE - ) + .udf <- try(get(.fun, envir = .rxToSE.envir$parent, mode="function"), silent =TRUE) + if (inherits(.udf, "try-error")) { + .udf <- try(get(.fun, envir = rxode2parse::.udfEnvSet(NULL), mode="function"), silent =TRUE) + } + if (inherits(.udf, "try-error")) { + stop(sprintf(gettext("function '%s' or its derivatives are not supported in rxode2"), .fun), + call. = FALSE + ) + } else { + .f <- formals(.udf) + if (any(names(.f) == "...")) { + stop(sprintf(gettext("R user function '%s' has variable number of arguments with'...' and is not supported in rxode2"), .fun), + call. = FALSE + ) + } else if (length(.ret0) == length(.f)) { + if (is.environment(envir)) { + assign(.fun, .rxFunction(.fun), envir = envir) + } + .ret0 <- unlist(.ret0) + .ret <- paste0(.fun, "(",paste(.ret0, collapse=", "), ")") + } else { + stop(sprintf(gettext("user function '%s' requires %d arguments (supplied %d)"), .fun, + length(.f), length(.ret0)), + call. = FALSE + ) + } + } } } } @@ -1367,11 +1434,16 @@ rxToSE <- function(x, envir = NULL, progress = FALSE, .rxFromNumDer <- 0L .rxDelta <- (.Machine$double.eps)^(1 / 3) +.rxFromSE.envir <- new.env(parent=emptyenv()) +.rxFromSE.envir$parent <- NULL #' @rdname rxToSE #' @export -rxFromSE <- function(x, unknownDerivatives = c("forward", "central", "error")) { +rxFromSE <- function(x, unknownDerivatives = c("forward", "central", "error"), + parent=parent.frame()) { rxReq("symengine") + rxode2parse::.udfEnvSet(parent) + .rxFromSE.envir$parent <- parent .unknown <- c("central" = 2L, "forward" = 1L, "error" = 0L) assignInMyNamespace(".rxFromNumDer", .unknown[match.arg(unknownDerivatives)]) if (is(substitute(x), "character")) { @@ -1855,7 +1927,7 @@ rxFromSE <- function(x, unknownDerivatives = c("forward", "central", "error")) { } } .ret0 <- lapply(lapply(x, .stripP), .rxFromSE) - .SEeq <- c(.rxSEeq, .rxSEeqUsr) + .SEeq <- c(.rxSEeq, rxode2parse::.rxSEeqUsr()) .nargs <- .SEeq[paste(.ret0[[1]])] if (!is.na(.nargs)) { if (.nargs == length(.ret0) - 1) { @@ -2101,9 +2173,34 @@ rxFromSE <- function(x, unknownDerivatives = c("forward", "central", "error")) { } stop(paste0(.ret0[[1]], "() takes 0-1 arguments")) } else { - stop(sprintf(gettext("'%s' not supported in symengine->rxode2"), paste(.ret0[[1]])), - call. = FALSE - ) + .fun <- paste(.ret0[[1]]) + .g <- try(get(.fun, envir=.rxFromSE.envir$parent, mode="function"), silent=TRUE) + if (inherits(.g, "try-error")) { + .g <- try(get(.fun, envir=rxode2parse::.udfEnvSet(NULL), + mode="function"), silent=TRUE) + } + if (inherits(.g, "try-error")) { + stop(sprintf(gettext("'%s' not supported in symengine->rxode2"), .fun), + call. = FALSE + ) + } else { + .f <- formals(.g) + if (any(names(.f) == "...")) { + stop(sprintf(gettext("R user function '%s' has variable number of arguments with'...' and is not supported in rxode2"), .fun), + call. = FALSE + ) + } else if (length(.ret0) - 1 == length(.f)) { + .ret <- unlist(.ret0) + .fun <- .ret[1] + .args <- .ret[-1] + return(paste0(.fun, "(", paste(.args, collapse = ", "), ")")) + } else { + stop(sprintf(gettext("user function '%s' requires %d arguments (supplied %d)"), .fun, + length(.f), length(.ret0) - 1), + call. = FALSE) + + } + } } } } else { @@ -2133,7 +2230,8 @@ rxFromSE <- function(x, unknownDerivatives = c("forward", "central", "error")) { #' @return rxode2/symengine environment #' @author Matthew Fidler #' @export -rxS <- function(x, doConst = TRUE, promoteLinSens = FALSE) { +rxS <- function(x, doConst = TRUE, promoteLinSens = FALSE, envir=parent.frame()) { + rxode2parse::.udfEnvSet(envir) rxReq("symengine") .cnst <- names(.rxSEreserved) .env <- new.env(parent = loadNamespace("symengine")) @@ -2149,12 +2247,14 @@ rxS <- function(x, doConst = TRUE, promoteLinSens = FALSE) { .env$..doConst <- doConst .rxD <- rxode2parse::rxode2parseD() for (.f in c( + ls(rxode2parse::.symengineFs()), ls(.rxD), "linCmtA", "linCmtB", "rxEq", "rxNeq", "rxGeq", "rxLeq", "rxLt", "rxGt", "rxAnd", "rxOr", "rxNot", "rxTBS", "rxTBSd", "rxTBSd2", "lag", "lead", "rxTBSi" )) { assign(.f, .rxFunction(.f), envir = .env) } + for (.v in seq_along(.rxSEreserved)) { assign(names(.rxSEreserved)[.v], .rxSEreserved[[.v]], envir = .env) } @@ -2178,9 +2278,9 @@ rxS <- function(x, doConst = TRUE, promoteLinSens = FALSE) { .env$rx_yj_ <- symengine::S("2") .env$rx_low_ <- symengine::S("0") .env$rx_hi_ <- symengine::S("1") - if (!is.null(.rxSEeqUsr)) { - sapply(names(.rxSEeqUsr), function(x) { - assign(.rxFunction(x), x, envir = .env) + if (!is.null(rxode2parse::.rxSEeqUsr())) { + sapply(names(rxode2parse::.rxSEeqUsr()), function(x) { + assign(x, .rxFunction(x), envir = .env) }) } ## EulerGamma=0.57721566490153286060651209008240243104215933593992 @@ -2484,7 +2584,7 @@ rxErrEnvF$probitNorm <- function(est, low = "0", hi = "1") { stop("'probitNorm' can only be in an error function", call. = FALSE) } if (!is.null(rxErrEnv.lambda)) { - if (rxErrEnv.yj != "1") { + if (rxErrEenv.yj != "1") { if (rxErrEnv.yj != "6" &&rxErrEnv.yj != "7") { print(rxErrEnv.yj) stop("'probitNorm' cannot be used with other data transformations", call. = FALSE) @@ -3059,7 +3159,7 @@ rxSplitPlusQ <- function(x, level = 0, mult = FALSE) { .rxSupportedFuns <- function(extra = .rxSupportedFunsExtra) { .ret <- c( names(.rxSEsingle), names(.rxSEdouble), names(.rxSEeq), - "linCmt", names(.rxOnly), ls(.symengineFs) + "linCmt", names(.rxOnly), ls(rxode2parse::.symengineFs()) ) if (extra) { .ret <- c(.ret, c( @@ -3084,3 +3184,433 @@ rxSplitPlusQ <- function(x, level = 0, mult = FALSE) { rxSupportedFuns <- function() { .rxSupportedFuns(FALSE) } + +.rxFunEq <- c( + "Rx_pow_di"=2, + "Rx_pow"=2, + "R_pow_di"=2, + "R_pow"=2, + "lgamma" = 1, + "abs" = 1, + "acos" = 1, + "acosh" = 1, + "asin" = 1, + "asinh" = 1, + "atan" = 1, + "atan2" = 2, + "atanh" = 1, + "beta" = 2, + "cos" = 1, + "cosh" = 1, + "erf" = 1, + "erfc" = 1, + "exp" = 1, + "log" = 1, + "sin" = 1, + "sinh" = 1, + "sqrt" = 1, + "tan" = 1, + "tanh" = 1, + ## C's math.h library + "floor" = 1, + "round" = 1, + "ceil" = 1, + "trunc" = 1, + ## Special R functions + "bessel_i" = 3, + "bessel_j" = 2, + "bessel_k" = 3, + "bessel_y" = 2, + "logspace_add" = 2, + "logspace_sub" = 2, + "fmax2" = 2, + "fmin2" = 2, + "sign" = 1, + "fsign" = 2, + "fprec" = 2, + "fround" = 2, + "ftrunc" = 2, + "transit" = NA, + "gammaq" = 2, + "gammapDer" = 2, + "gammapInv" = 2, + "gammapInva" = 2, + "gammaqInv" = 2, + "gammaqInva" = 2, + "lowergamma" = 2, + "uppergamma" = 2) + +.rxOnly <- c( + ## Now random number generators + "rnorm" = NA, + "rxnorm" = NA, + "rxbinom" = 2, + "rbinom" = 2, + "rxcauchy" = NA, + "rcauchy" = NA, + "rchisq" = 1, + "rxchisq" = 1, + "rexp" = 1, + "rxexp" = 1, + "rbeta" = 2, + "rxbeta" = 2, + "rgeom" = 1, + "rxgeom" = 1, + "rxpois" = 1, + "rpois" = 1, + "rxt" = 1, + "rt" = 1 +) + + +.rxFun2cNameOrAtomic <- function(x, envir) { + # see if it is a reserved rxode2 name/function for name clashes + x <- as.character(x) + if (!exists("res", envir=envir)) { + envir$res <- c(rxSupportedFuns(), + rxode2::rxReservedKeywords[, 1], + strsplit(paste(rxode2::rxReservedKeywords[, 3],collapse=","),"[,]+")[[1]]) + } + if (x %in% envir$funs) { + return(paste0("_qf_", x)) + } + x +} + +.rxFun2cArithmeticOperators <- function(x, envir) { + if (length(x) == 3) { + if (identical(x[[1]], quote(`/`))) { + .x2 <- x[[2]] + .x3 <- x[[3]] + ## df(%s)/dy(%s) + if (identical(.x2, quote(`d`)) && + identical(.x3[[1]], quote(`dt`))) { + if (length(.x3[[2]]) == 1) { + .state <- as.character(.x3[[2]]) # .rxToSE(.x3[[2]], envir = envir) + } else { + .state <- .rxFun2c(.x3[[2]], envir = envir) + } + stop("d/dt(", .state, ") not supported in functions for translation") + } else { + if (length(.x2) == 2 && length(.x3) == 2) { + if (identical(.x2[[1]], quote(`df`)) && + identical(.x3[[1]], quote(`dy`))) { + if (length(.x2[[2]]) == 1) { + .state <- as.character(.x2[[2]]) + } else { + .state <- .rxFun2c(.x2[[2]], envir = envir) + } + if (length(.x3[[2]]) == 1) { + .var <- as.character(.x3[[2]]) + } else { + .var <- .rxFun2c(.x3[[2]], envir = envir) + } + stop("df(", .state, ")/dy(", .var, ") statements are not supported in translation", + call. = FALSE) + } + } + .ret <- paste0( + .rxFun2c(.x2, envir = envir), + as.character(x[[1]]), + .rxFun2c(.x3, envir = envir) + ) + } + } else if (identical(x[[1]], quote(`^`)) || + identical(x[[1]], quote(`**`))) { + if (is.numeric(x[[3]]) && + checkmate::checkIntegerish(x[[3]])) { + return(paste0("R_pow_di(", .rxFun2c(x[[2]], envir = envir), ",", + as.character(x[[3]]), ")")) + } else { + return(paste0("R_pow(", .rxFun2c(x[[2]], envir=envir), ",", + .rxFun2c(x[[3]], envir=envir), ")")) + } + } else { + .ret <- paste0( + .rxFun2c(x[[2]], envir = envir), + as.character(x[[1]]), + .rxFun2c(x[[3]], envir = envir) + ) + } + return(.ret) + } else { + ## Unary Operators + return(paste( + as.character(x[[1]]), + .rxFun2c(x[[2]], envir = envir) + )) + } +} +.rxFun2cAssignOperators <- function(x, envir = envir) { + ## if (!envir$isRx && identical(x[[1]], quote(`~`))) { + ## stop("formulas or other expressions with '~` are not supported in translation", + ## call.=FALSE) + ## } + if (as.character(x[[2]]) %in% envir$args) { + stop("cannot assign argument '", as.character(x[[2]]), + "' in functions converted to C", + call.=FALSE) + } + .lhs <- .rxFun2cNameOrAtomic(x[[2]], envir=envir) + if (!(.lhs %in% envir$args)) { + envir$vars <- c(envir$vars, .lhs) + } + envir$didAssign <- TRUE + .pre <- paste0(rep(" ", envir$n), collapse="") + if (envir$isRx) { + paste0(.lhs, " <- ", + .rxFun2c(x[[3]], envir=envir), "\n", + "rxLastValue <-", .lhs, "\n") + } else { + paste0(.pre, "_lastValue = ", .lhs, " = ", + .rxFun2c(x[[3]], envir=envir), ";\n") + } +} + +.rxFun2cSquareBracket <- function(x, envir) { + stop("bracket expressions (ie ret[3]) are not supported in translation", + call. = FALSE) +} + +.rxFun2cLogic <- function(x, envir) { + if (identical(x[[1]], quote(`!`))) { + return(paste0("!(", .rxFun2c(x[[2]], envir=envir), ")")) + } else if (identical(x[[1]], quote(`&`))) { + return(paste0(.rxFun2c(x[[2]], envir=envir), " && ", + .rxFun2c(x[[3]], envir=envir))) + } else if (identical(x[[1]], quote(`|`))) { + return(paste0(.rxFun2c(x[[2]], envir=envir), " || ", + .rxFun2c(x[[3]], envir=envir))) + } else { + return(paste0(.rxFun2c(x[[2]], envir=envir), " ", as.character(x[[1]]), " ", + .rxFun2c(x[[3]], envir=envir))) + } +} + +.rxFun2cIf <- function(x, envir) { + .logic <- .rxFun2c(x[[2]], envir=envir) + .pre <- paste0(rep(" ", envir$n), collapse="") + .ret <- paste(.pre, "if (", .logic, ") ") + .ret <- paste0(.ret, .rxFun2c(x[[3]], envir=envir)) + + if (length(x) == 3) { + envir$isExpr <- TRUE + return(.ret) + } + .ret <- sub("else +if", "else if", paste0(.ret, .pre, "else ", .rxFun2c(x[[4]], envir=envir))) + envir$isExpr <- TRUE + return(.ret) +} + +.rxFun2cCall <- function(x, envir) { + if (identical(x[[1]], quote(`{`))) { + .ret <- "{\n" + envir$n <- envir$n + 2 + .ret <- paste0(.ret, + paste(vapply(seq_along(x)[-1], + function(i) { + .cur <- x[[i]] + .last <- envir$didAssign + .expr <- envir$isExpr + on.exit({ + assign("isExpr", .expr, envir=envir) + assign("didAssign", .last, envir=envir) + }) + envir$didAssign <- FALSE + .cur <- .rxFun2c(.cur, envir=envir) + if(!envir$didAssign && !envir$isExpr) { + .pre <- paste0(rep(" ", envir$n), collapse="") + if (envir$isRx) { + return(paste0(.pre, "rxLastValue <- ", .cur, "\n")) + } else { + return(paste0(.pre, "_lastValue = ", .cur, ";\n")) + } + } + .cur + }, character(1), USE.NAMES = FALSE), + collapse="")) + envir$n <- envir$n - 2 + .pre <- paste0(rep(" ", envir$n), collapse="") + .ret <- paste0(.ret, .pre, "}\n") + return(.ret) + } else if (identical(x[[1]], quote(`(`))) { + return(paste0("(", .rxFun2c(x[[2]], envir = envir), ")")) + } else if (identical(x[[1]], quote(`&`)) || + identical(x[[1]], quote(`&&`)) || + identical(x[[1]], quote(`==`)) || + identical(x[[1]], quote(`||`)) || + identical(x[[1]], quote(`|`)) || + identical(x[[1]], quote(`>`)) || + identical(x[[1]], quote(`<`)) || + identical(x[[1]], quote(`<=`)) || + identical(x[[1]], quote(`>=`)) || + identical(x[[1]], quote(`!=`)) || + identical(x[[1]], quote(`!`)) + ) { + return(.rxFun2cLogic(x, envir=envir)) + } else if (identical(x[[1]], quote(`*`)) || + identical(x[[1]], quote(`**`)) || + identical(x[[1]], quote(`^`)) || + identical(x[[1]], quote(`+`)) || + identical(x[[1]], quote(`-`)) || + identical(x[[1]], quote(`/`))) { + return(.rxFun2cArithmeticOperators(x, envir = envir)) + } else if (identical(x[[1]], quote(`=`)) || + identical(x[[1]], quote(`<-`)) || + identical(x[[1]], quote(`~`))) { + return(.rxFun2cAssignOperators(x, envir)) + } else if (identical(x[[1]], quote(`[`))) { + return(.rxFun2cSquareBracket(x, envir = envir)) + } else if (identical(x[[1]], quote(`if`))) { + return(.rxFun2cIf(x, envir = envir)) + } else { + # supported functions + if (identical(x[[1]], quote(`return`))) { + envir$hasReturn <- TRUE + .pre <- paste0(rep(" ", envir$n), collapse="") + envir$didAssign <- TRUE + return(paste0(.pre, "return (", .rxFun2c(x[[2]], envir=envir), ");\n")) + } + .ret0 <- lapply(x, .stripP) + .FunEq <- c(.rxFunEq, rxode2parse::.rxSEeqUsr()) + .curName <- paste(.ret0[[1]]) + .nargs <- .FunEq[.curName] + if (!is.na(.nargs)) { + if (.nargs == length(.ret0) - 1) { + return(paste0(.curName, "(", + paste(vapply(seq_along(.ret0)[-1], + function(i) { + .rxFun2c(.ret0[[i]], envir=envir) + }, character(1), USE.NAMES=FALSE), + collapse=","), + ")")) + } + } + stop("cannot translate function '", .curName, "'", + call.=FALSE) + } +} + +.rxFun2c <- function(x, envir) { + if (is.name(x) || is.atomic(x)) { + return(.rxFun2cNameOrAtomic(x, envir=envir)) + } else if (is.call(x)) { + return(.rxFun2cCall(x, envir = envir)) + } else { + stop("unsupported expression", call. = FALSE) + } +} + +#' Calculate derivatives/C code from a R function +#' +#' @param fun Function to convert to C +#' +#' @param name function name to convert to C, implied if needed +#' +#' @param onlyF Only calculate the C for the function, don't calculate the derivatives +#' +#' @return A list with C code and derivative information +#' +#' @keywords internal +#' +#' @noRd +rxFun2c <- function(fun, name, onlyF=FALSE) { + .env <- new.env(parent=emptyenv()) + .env$vars <- character(0) + if (!missing(name)) { + .funName <- name + } else { + .funName <- as.character(substitute(fun)) + } + .f <- formals(fun) + .env$args <- names(.f) + .env$n <- 2 + .env$isExpr <- FALSE + .env$isRx <- FALSE + .env$hasReturn <- FALSE + if (any(.env$args == "...")) { + stop("functions with ... in them are not supported", + call. =FALSE) + } + .start <- paste0("double ", .funName, "(", paste(paste("double ", .env$args), collapse=", "), + ") {\n") + + .body <- as.list(body(fun)) + .body <- paste(vapply(seq_along(.body)[-1], function(i) { + .extra <- .extra2 <- "" + .cur <- .body[[i]] + .env$didAssign <- FALSE + .cur <- .rxFun2c(.cur, envir=.env) + if(!.env$didAssign && !.env$isExpr) { + .pre <- paste0(rep(" ", .env$n), collapse="") + if (.env$isRx) { + return(paste0(.pre, "rxLastValue <- ", .cur, "\n")) + } else { + return(paste0(.pre, "_lastValue = ", .cur, ";\n")) + } + } + .env$isExpr <- FALSE + .cur + }, + character(1), USE.NAMES=FALSE), collapse="") + + .start <- paste0(.start, + paste0(" double ", + paste(paste0(c("_lastValue", unique(.env$vars)), "=NA_REAL"), collapse=","), + ";\n")) + .stop <- " return _lastValue;\n}\n" + .cCode <- paste0(.start, .body, .stop) + .ret <- list(name=.funName, + args=.env$args, + cCode=.cCode) + + if (onlyF) { + return(.ret) + } + if (!.env$hasReturn) { + # Can calculate derivatives + # Firs create an rxode2 like model: + .env <- new.env(parent=emptyenv()) + .env$isRx <- TRUE + .env$args <- names(.f) + .env$n <- 2 + .env$isExpr <- FALSE + .env$hasReturn <- FALSE + .body <- as.list(body(fun)) + .body <- paste(vapply(seq_along(.body)[-1], function(i) { + .extra <- .extra2 <- "" + .cur <- .body[[i]] + .env$didAssign <- FALSE + .cur <- .rxFun2c(.cur, envir=.env) + if(!.env$didAssign && !.env$isExpr) { + .pre <- paste0(rep(" ", .env$n), collapse="") + return(paste0(.pre, "rxLastValue = ", .cur, ";\n")) + } + .env$isExpr <- FALSE + .cur + }, + character(1), USE.NAMES=FALSE), collapse="") + # take out if/else + .body <- rxPrune(.body) + .s <- rxS(.body) + .lastValue <- .s$rxLastValue + return(c(list(.ret), + lapply(.env$args, function(v) { + .v <- symengine::D(.lastValue, symengine::S(v)) + .v <- paste0("function(", paste(.env$args, collapse=", "), ") {\n", rxOptExpr(paste0("rxLastValue=", rxFromSE(.v)), msg=paste0("d(", .funName, ")/d(", v, ")")), + "\nrxLastValue}") + .v <- eval(str2lang(.v)) + .dName <- paste0("rx_", .funName, "_d_", v) + .v <- rxFun2c(.v, .dName, onlyF=TRUE) + .v2 <- paste0("function(", paste(.env$args, collapse=", "), "){\n", + "paste0(\"", .dName, "(\", ", + paste(.env$args, collapse=", \", \", "), ", \")\")", + "}") + .v2 <- eval(str2lang(.v2)) + c(.v, list(.v2)) + }))) + } else { + message("function contains return statement; derivatives not calculated") + } + return(list(.ret)) +} diff --git a/R/ui-assign-parts.R b/R/ui-assign-parts.R index 19e4863b3..057a860eb 100644 --- a/R/ui-assign-parts.R +++ b/R/ui-assign-parts.R @@ -291,3 +291,30 @@ `RxODE<-` <- function(x, envir=environment(x), value) { UseMethod("rxode2<-") } + +#' @export +`$<-.rxUi` <- function(x, name, value) { + .raw <- inherits(x, "raw") + if (!.raw) { + assign(name, value, envir=x) + return(x) + } + .x <- x + if (name %in% c("ini", "iniDf")) { + ini(x) <- value + return(x) + } + if (name == "model") { + model(x) <- value + return(x) + } + .x <- rxUiDecompress(.x) + if (exists(name, .x)) { + stop("'", name, "' is a fixed UI component and should not be overwritten", + call.=FALSE) + } + .meta <- get("meta", .x) + assign(name, value, envir=.meta) + .x <- rxUiCompress(.x) + .x +} diff --git a/R/ui-bind.R b/R/ui-bind.R index 95de55da3..789d9b57a 100644 --- a/R/ui-bind.R +++ b/R/ui-bind.R @@ -1,14 +1,119 @@ +#' Combine Model Lines +#' +#' @param model1 rxUi model1 +#' @param model2 rxUi model2 +#' @param ini Final ini for model +#' @return new model with both models appended together and ini from input +#' @noRd +#' @author Matthew L. Fidler +.combineModelLines <- function(model1, model2, ini) { + # Add the meta information from model2 into the meta information of new model + .ls <- ls(model2$meta, all.names=TRUE) + for (.i in seq_along(.ls)) { + assign(.ls[.i], model2$meta[[.ls[.i]]], envir=model1$meta) + } + model1$iniDf <- ini + model1$lstExpr <- c(model1$lstExpr, model2$lstExpr) + model1$fun() +} +#' Append 2 models +#' +#' +#' @param model1 rxUi type of model +#' @param model2 rxUi type of model +#' @param common boolean; when `TRUE` require models to have variables in common +#' @return rxUi combined model of model1 and model2 +#' @noRd +#' @author Matthew L. Fidler +rxAppendModel_ <- function(model1, model2, common=TRUE) { + model1 <- assertRxUi(model1) + model1 <- .copyUi(model1) # so modifications do not affect first model + model2 <- assertRxUi(model2) + model2 <- .copyUi(model2) + .ini1 <- model1$iniDf + .ini2 <- model2$iniDf + .bind <- intersect(c(model1$mv0$lhs, model1$mv0$state), model2$allCovs) + if (common && length(.bind) == 0) { + stop("not all the models have variables in common (use `common=FALSE` to allow this)", + call.=FALSE) + } + if (is.null(.ini1) && is.null(.ini2)) { + return(.combineModelLines(model1, model2, NULL)) + } + if (!is.null(.ini1) && is.null(.ini2)) { + return(.combineModelLines(model1, model2, .ini1)) + } + if (is.null(.ini1) && !is.null(.ini2)) { + return(.combineModelLines(model1, model2, .ini2)) + } + # both exist + .ini1theta <- .ini1[!is.na(.ini1$ntheta),, drop = FALSE] + .ini2theta <- .ini2[!is.na(.ini2$ntheta),, drop = FALSE] + .both <- intersect(.ini1theta$name, .ini2theta$name) + if (length(.both) > 0) { + .minfo("duplicated population parameters when combining 2 models") + .minfo(paste0("keeping initialization from first model: '", + paste(.both, collapse="', '"), "'")) + .ini2theta <- .ini2theta[!(.ini2theta$name %in% .both),, drop =FALSE] + } + .ini2theta$ntheta <- length(.ini1theta$ntheta) + seq_along(.ini2theta$ntheta) + .iniT <- rbind(.ini1theta, .ini2theta) + # now look at the etas + .ini1eta <- .ini1[is.na(.ini1$ntheta),, drop = FALSE] + .ini2eta <- .ini2[is.na(.ini2$ntheta),, drop = FALSE] + .both <- intersect(.ini1eta$name, .ini2eta$name) + if (length(.both) > 0) { + # See if any of the items have covariances defined + .complex1 <- which(vapply(.both, function(v) { + .eta <- .ini1eta[.ini1eta$name == v, "neta1"] + any((.ini1eta$neta1 == .eta & .ini1eta$neta2 != .eta) | + (.ini1eta$neta2 == .eta & .ini1eta$neta1 != .eta)) + }, logical(1), USE.NAMES = FALSE)) + .complex2 <- which(vapply(.both, function(v) { + .eta <- .ini2eta[.ini2eta$name == v, "neta1"] + any((.ini2eta$neta1 == .eta & .ini2eta$neta2 != .eta) | + (.ini2eta$neta2 == .eta & .ini2eta$neta1 != .eta) ) + }, logical(1), USE.NAMES = FALSE)) + .err <- unique(c(.both[.complex1], .both[.complex2])) + if (length(.err) > 0) { + stop("duplicated parameter has covariance, will not append models: '", + paste0(.err, collapse="', '"), "'", + call.=FALSE) + } else { + # drop in the second + .minfo("duplicated eta parameters when combining 2 models") + .minfo(paste0("keeping initialization from first model: '", + paste(.both, collapse="', '"), "'")) + + .ini2eta <- .ini2eta[!(.ini2eta$name %in% .both),, drop =FALSE] + } + } + .maxEta <- suppressWarnings(max(.ini1eta$neta1)) + if (is.finite(.maxEta)) { + .ini2eta$neta1 <- .ini2eta$neta1 + .maxEta + .ini2eta$neta2 <- .ini2eta$neta2 + .maxEta + } + .iniE <- rbind(.ini1eta, .ini2eta) + if (length(.iniE$name) > 0) { + .iniE <- .iniE[order(.iniE$neta1, .iniE$neta2), ] + .ini <- rbind(.iniT, .iniE) + } else { + .ini <- .iniT[order(.iniT$ntheta), ] + } + .combineModelLines(model1, model2, .ini) +} + #' Append two rxui models together #' -#' @param model1 rxUi model 1 -#' @param model2 rxUi model 2 +#' @param ... models to append together +#' @param common boolean that determines if you need a common value to bind #' @return New model with both models appended together #' @author Matthew L. Fidler #' @export #' @examples -#' +#' #' \donttest{ -#' +#' #' ocmt <- function() { #' ini({ #' tka <- exp(0.45) # Ka @@ -46,49 +151,20 @@ #' } #' #' rxAppendModel(ocmt %>% model(ceff=cp,append=TRUE), idr) -#' +#' #' } #' -rxAppendModel <- function(model1, model2) { - model1 <- assertRxUi(model1) - model1 <- .copyUi(model1) # so modifications do not affect first model - model2 <- assertRxUi(model2) - model2 <- .copyUi(model2) - .ini1 <- model1$iniDf - .ini2 <- model2$iniDf - .bind <- intersect(c(model1$mv0$lhs, model1$mv0$state), model2$allCovs) - if (length(.bind) == 0) { - stop("the first model does not have variables that are used by the second model", - call.=FALSE) - } - .maxTheta <- suppressWarnings(max(.ini1$ntheta, na.rm=TRUE)) - if (!is.finite(.maxTheta)) { - stop("there needs to be at least one population parameter in 'model1'", - call.=FALSE) - } - .ini2$ntheta <- .ini2$ntheta + .maxTheta - .maxEta <- suppressWarnings(max(.ini1$neta1, na.rm=TRUE)) - if (is.finite(.maxEta)) { - .ini2$neta1 <- .ini2$neta1 + .maxEta - .ini2$neta2 <- .ini2$neta2 + .maxEta - } - .ini <- rbind(.ini1, .ini2) - .etas <- which(is.na(.ini$ntheta)) - if (length(.etas) > 0) { - .iniT <- .ini[-.etas, ] - .iniT <- .iniT[order(.iniT$ntheta), ] - .iniE <- .ini[.etas, ] - .iniE <- .iniE[order(.iniE$neta1, .iniE$neta2), ] - .ini <- rbind(.iniT, .iniE) - } else { - .ini <- .ini[order(.ini$ntheta), ] - } - # Add the meta information from model2 into the meta information of new model - .ls <- ls(model2$meta, all.names=TRUE) - for (.i in seq_along(.ls)) { - assign(.ls[.i], model2$meta[[.ls[.i]]], envir=model1$meta) - } - model1$iniDf <- .ini - model1$lstExpr <- c(model1$lstExpr, model2$lstExpr) - model1$fun() +rxAppendModel <- function(..., common=TRUE) { + .env <- new.env(parent=emptyenv()) + .env$ret <- NULL + .lst <- list(...) + lapply(seq_along(.lst), function(i) { + .m <- .lst[[i]] + if (is.null(.env$ret)) { + .env$ret <- .m + } else { + .env$ret <- rxAppendModel_(.env$ret, .m, common=common) + } + }) + .env$ret } diff --git a/R/ui-rename.R b/R/ui-rename.R index 8dca1ff1a..b376d144e 100644 --- a/R/ui-rename.R +++ b/R/ui-rename.R @@ -41,68 +41,149 @@ } list(line[[2]], line[[3]], .var.name, .var.name2) } - -#' Rename variables in the expression +#' Renames everything in one function #' -#' @param item Expression to recursively rename -#' @param new New name -#' @param old Old name -#' @return new expression with variable renamed -#' @author Matthew L. Fidler +#' @param item language item to process +#' @param lst list of renaming from .assertRenameErrorModelLine, ie list(new, old, newChar, oldChar) +#' @param isLhs is the expression the left handed side of the equation +#' @return expression renamed #' @noRd -.rxRenameRecursive <- function(item, new, old, isLhs=FALSE) { +#' @author Matthew L. Fidler +.rxRenameRecursiveAll <- function(item, lst, isLhs=FALSE) { if (is.atomic(item)) { return(item) } if (is.name(item)) { - if (identical(item, old)) { - return(new) - } else { - return(item) + .env <- new.env(parent=emptyenv()) + .env$new <- NULL + lapply(seq_along(lst), function(i) { + if (!is.null(.env$new)) return(NULL) + .curLst <- lst[[i]] + .old <- .curLst[[2]] + if (identical(item, .old)) { + .env$new <- .curLst[[1]] + } + return(NULL) + }) + if (!is.null(.env$new)) { + return(.env$new) } + return(item) } else if (is.call(item)) { if (isLhs && identical(item[[1]], quote(`/`))) { # handle d/dt() differently so that d doesn't get renamed .num <- item[[2]] .denom <- item[[3]] - if (is.call(.num)) .num <- as.call(lapply(.num, .rxRenameRecursive, new=new, old=old, isLhs=TRUE)) - if (is.call(.denom)) .denom <- as.call(lapply(.denom, .rxRenameRecursive, new=new, old=old, isLhs=TRUE)) + if (is.call(.num)) .num <- as.call(lapply(.num, .rxRenameRecursiveAll, lst=lst, isLhs=TRUE)) + if (is.call(.denom)) .denom <- as.call(lapply(.denom, .rxRenameRecursiveAll, lst=lst, isLhs=TRUE)) return(as.call(c(list(item[[1]]), .num, .denom))) - } else if (isLhs && identical(item[[1]], old) && length(item) == 2L && + } else if (isLhs && length(item) == 2L && is.numeric(item[[2]])) { - # handle x(0) = items - return(as.call(c(new, lapply(item[-1], .rxRenameRecursive, new=new, old=old, isLhs=isLhs)))) + .env <- new.env(parent=emptyenv()) + .env$new <- NULL + lapply(seq_along(lst), + function(i) { + if (!is.null(.env$new)) return(NULL) + .curLst <- lst[[i]] + .old <- .curLst[[2]] + if (identical(item[[1]], .old)) { + .env$new <- .curLst[[1]] + } + return(NULL) + }) + if (!is.null(.env$new)) { + # handle x(0) = items + return(as.call(c(.env$new, lapply(item[-1], .rxRenameRecursiveAll, lst=lst, isLhs=isLhs)))) + } } if (identical(item[[1]], quote(`=`)) || identical(item[[1]], quote(`<-`)) || identical(item[[1]], quote(`~`))) { - .elhs <- lapply(item[c(-1, -3)], .rxRenameRecursive, new=new, old=old, isLhs=TRUE) - .erhs <- lapply(item[c(-1, -2)], .rxRenameRecursive, new=new, old=old, isLhs=FALSE) + .elhs <- lapply(item[c(-1, -3)], .rxRenameRecursiveAll, lst=lst, isLhs=TRUE) + .erhs <- lapply(item[c(-1, -2)], .rxRenameRecursiveAll, lst=lst, isLhs=FALSE) return(as.call(c(item[[1]], .elhs, .erhs))) } else { - return(as.call(c(list(item[[1]]), lapply(item[-1], .rxRenameRecursive, new=new, old=old, isLhs=isLhs)))) + return(as.call(c(list(item[[1]]), lapply(item[-1], .rxRenameRecursiveAll, lst=lst, isLhs=isLhs)))) } } else { stop("unknown expression", call.=FALSE) } } -#' Rename one item in the rxui +#' Rename all items in matrix dimnames #' -#' @param rxui rxui for renaming -#' @param lst list with (new, old, newChr, oldChr) -#' @return Nothing, called for side effects +#' @param mat matrix +#' @param lst list for renaming +#' @return renamed matrix +#' @noRd #' @author Matthew L. Fidler +.rxRenameAllMat <- function(mat, lst) { + .d <- dimnames(mat)[[1]] + .d <- vapply(seq_along(.d), function(i) { + .env <- new.env(parent=emptyenv()) + .env$new <- NULL + .cur <- .d[i] + lapply(seq_along(lst), + function(j) { + if (!is.null(.env$new)) return(NULL) + .curLst <- lst[[j]] + .old <- .curLst[[4]] + if (.cur == .old) { + .env$new <- .curLst[[3]] + } + }) + if (!is.null(.env$new)) return(.env$new) + return(.cur) + }, character(1), USE.NAMES=FALSE) + dimnames(mat) <- list(.d, .d) + mat +} + +#' Rename all the items in the initialization data frame and model +#' +#' @param rxui the ui to process +#' @param lst the list of old and new expressions (like above) +#' @return Called for side effects #' @noRd -.rxRename1 <- function(rxui, lst) { +#' @author Matthew L. Fidler +.rxRenameAll <- function(rxui, lst) { + rxui <- rxUiDecompress(rxui) .iniDf <- rxui$iniDf - .w <- which(.iniDf$name == lst[[4]]) - if (length(.w) == 1) { - .iniDf$name[.w] <- lst[[3]] - rxui$iniDf <- .iniDf + .iniDf$name <- vapply(seq_along(.iniDf$name), + function(i) { + .env <- new.env(parent=emptyenv()) + .env$new <- NULL + .cur <- .iniDf$name[i] + lapply(seq_along(lst), + function(j) { + if (!is.null(.env$new)) return(NULL) + .curLst <- lst[[j]] + .old <- .curLst[[4]] + if (.cur == .old) { + .env$new <- .curLst[[3]] + } + }) + if (!is.null(.env$new)) return(.env$new) + return(.cur) + }, character(1), USE.NAMES=FALSE) + rxui$iniDf <- .iniDf + if (exists("sigma", rxui)) { + assign("sigma", .rxRenameAllMat(get("sigma", envir=rxui), lst), envir=rxui) + } + if (exists("thetaMat", rxui)) { + assign("thetaMat", .rxRenameAllMat(get("thetaMat", envir=rxui), lst), envir=rxui) + } + if (exists("meta", rxui)) { + .meta <- get("meta", rxui) + if (exists("sigma", .meta)) { + assign("sigma", .rxRenameAllMat(get("sigma", envir=.meta), lst), envir=.meta) + } + if (exists("thetaMat", .meta)) { + assign("thetaMat", .rxRenameAllMat(get("thetaMat", envir=.meta), lst), envir=.meta) + } } rxui$lstExpr <- lapply(seq_along(rxui$lstExpr), function(i) { - .rxRenameRecursive(rxui$lstExpr[[i]], new=lst[[1]], old=lst[[2]]) + .rxRenameRecursiveAll(rxui$lstExpr[[i]], lst=lst) }) } @@ -164,21 +245,29 @@ rxRename <- function(.data, ..., envir=parent.frame()) { #' @rdname rxRename #' @export .rxRename <- function(.data, ..., envir=parent.frame()) { + .inCompress <- FALSE + if (inherits(.data, "rxUi") && + inherits(.data, "raw")) { + .inCompress <- TRUE + } rxui <- assertRxUi(.data) + if (inherits(rxui, "raw")) { + rxui <- rxUiDecompress(rxui) + } .vars <- unique(c(rxui$mv0$state, rxui$mv0$params, rxui$mv0$lhs, rxui$predDf$var, rxui$predDf$cond, rxui$iniDf$name)) .modelLines <- .quoteCallInfoLines(match.call(expand.dots = TRUE)[-(1:2)], envir=envir) .lst <- lapply(seq_along(.modelLines), function(i) { .assertRenameErrorModelLine(.modelLines[[i]], .vars) }) rxui <- .copyUi(rxui) # copy ui so effects do not affect original - lapply(seq_along(.lst), function(i) { - .rxRename1(rxui, .lst[[i]]) - }) + .rxRenameAll(rxui, .lst) .ret <- rxui$fun() if (inherits(.data, "rxUi")) { - .x <- rxUiDecompress(.data) - .ret <- .newModelAdjust(.ret, .x, rename=TRUE) - .ret <- rxUiCompress(.ret) + ## .x <- rxUiDecompress(.data) + .ret <- .newModelAdjust(.ret, rxui, rename=TRUE) + if (.inCompress) { + .ret <- rxUiCompress(.ret) + } .cls <- setdiff(class(.data), class(.ret)) if (length(.cls) > 0) { class(.ret) <- c(.cls, class(.ret)) @@ -218,4 +307,4 @@ rxRename.default <- function(.data, ...) { .lst <- as.list(match.call()[-1]) .lst$.data <- .data do.call(.rxRename, c(.lst, list(envir=parent.frame(2)))) -} +} diff --git a/R/ui.R b/R/ui.R index 2cb51aa18..a3c91cf2a 100644 --- a/R/ui.R +++ b/R/ui.R @@ -276,7 +276,11 @@ model <- function(x, ..., append=FALSE, auto=getOption("rxode2.autoVarPiping", T cov=NULL, envir=parent.frame()) { if (is(substitute(x), "{")) { .funName <- try(as.character(as.list(with(envir, match.call()))[[1]]), silent=TRUE) - if (inherits(.funName, "try-error")) .funName <- NULL + if (inherits(.funName, "try-error")) { + .funName <- NULL + } else if (length(.funName) == 1L && exists(.funName, envir=parent.env(envir))) { + rxode2parse::.udfEnvSet(parent.env(envir)) + } .ini <- .lastIni .iniQ <- .lastIniQ if (is.null(.ini)) { @@ -427,7 +431,7 @@ print.rxUi <-function(x, ...) { #' f <- rxUiCompress(f) #' print(class(f)) #' print(is.environment(f)) -#' +#' rxUiDecompress <- function(ui) { if (!inherits(ui, "rxUi")) return(ui) if (is.environment(ui)) return(ui) diff --git a/R/utils.R b/R/utils.R index b7694a96c..839e81e73 100644 --- a/R/utils.R +++ b/R/utils.R @@ -747,7 +747,7 @@ is.latex <- function() { ret } #' Print out a table in the documentation -#' +#' #' @param table data frame #' @param caption a character vector representing the caption for the latex table #' @return based on the `knitr` context: @@ -755,7 +755,7 @@ is.latex <- function() { #' - output a `DT::datatable` for html output #' - otherwise output a `knitr::kable` #' @keywords internal -#' @export +#' @export #' @author Matthew L. Fidler #' @examples #' .rxDocTable(rxReservedKeywords) @@ -773,11 +773,12 @@ is.latex <- function() { } } -#' Calculate expected quantiles with normal or t sampling distribution +#' Calculate expected confidence bands or prediction intreval with normal or t sampling distribution #' -#' The generic function `meanProbs` produces expected quantiles under -#' either the t distribution or the normal sampling distribution. This -#' uses `qnorm()` or `qt()` with the mean and standard deviation. +#' The generic function `meanProbs` produces expected confidence bands +#' under either the t distribution or the normal sampling +#' distribution. This uses `qnorm()` or `qt()` with the mean and +#' standard deviation. #' #' For a single probability, p, it uses either: #' @@ -796,19 +797,27 @@ is.latex <- function() { #' This is meant to perform in the same way as `quantile()` so it can #' be a drop in replacement for code using `quantile()` but using #' distributional assumptions. -#' +#' #' @param x numeric vector whose mean and probability based confidence #' values are wanted, NA and NaN values are not allowed in numeric #' vectors unless ‘na.rm’ is ‘TRUE’. -#' @param probs numeric vector of probabilities with values in [0,1]. +#' @param probs numeric vector of probabilities with values in the +#' interval from 0 to 1 . #' @param na.rm logical; if true, any NA and NaN's are removed from #' `x` before the quantiles are computed. #' @param names logical; if true, the result has a names attribute. #' @param useT logical; if true, use the t-distribution to calculate #' the confidence-based estimates. If false use the normal #' distribution to calculate the confidence based estimates. -#' @param onlyProbs logical; if true, only return the probability based -#' confidence interval estimates, otherwise return +#' @param onlyProbs logical; if true, only return the probability +#' based confidence interval estimates, otherwise return +#' @param pred logical; if true use the prediction interval instead of +#' the confidence interval +#' @param n integer/integerish; this is the n used to calculate the +#' prediction or confidence interval. When `n=0` (default) use the +#' number of non-`NA` observations. +#' @param ... Arguments passed to default method, allows many +#' different methods to be applied. #' @return By default the return has the probabilities as names (if #' named) with the points where the expected distribution are #' located given the sampling mean and standard deviation. If @@ -831,9 +840,9 @@ is.latex <- function() { #' quantile(x<- rnorm(42)) #' #' meanProbs(x) -#' +#' #' meanProbs(x, useT=FALSE) -#' +#' meanProbs <- function(x, ...) { UseMethod("meanProbs") } @@ -841,14 +850,18 @@ meanProbs <- function(x, ...) { #' @rdname meanProbs #' @export meanProbs.default <- function(x, probs=seq(0, 1, 0.25), na.rm=FALSE, - names=TRUE, useT=TRUE, onlyProbs=TRUE) { + names=TRUE, useT=TRUE, onlyProbs=TRUE, pred=FALSE, + n=0L, ...) { checkmate::assertNumeric(x) checkmate::assertNumeric(probs, min.len=1, any.missing = FALSE, lower=0.0, upper=1.0) checkmate::assertLogical(na.rm, any.missing=FALSE, len=1) checkmate::assertLogical(names, any.missing=FALSE, len=1) checkmate::assertLogical(useT, any.missing=FALSE, len=1) checkmate::assertLogical(onlyProbs, any.missing=FALSE, len=1) - .ret <- .Call(`_rxode2_meanProbs_`, x, probs, na.rm, useT) + checkmate::assertLogical(pred, any.missing=FALSE, len=1) + checkmate::assertIntegerish(n, min.len=1, max.len=1, any.missing=FALSE, lower=0) + n <- as.integer(n) + .ret <- .Call(`_rxode2_meanProbs_`, x, probs, na.rm, useT, pred, n) .names <- NULL if (names) { .names <- paste0(probs*100, "%") @@ -864,3 +877,178 @@ meanProbs.default <- function(x, probs=seq(0, 1, 0.25), na.rm=FALSE, .ret } +#' Calculate expected confidence bands with binomial sampling distribution +#' +#' This is meant to perform in the same way as `quantile()` so it can +#' be a drop in replacement for code using `quantile()` but using +#' distributional assumptions. +#' +#' It is used for confidence intervals with rxode2 solved objects using +#' `confint(mean="binom")` +#' +#' @param x numeric vector whose mean and probability based confidence +#' values are wanted, NA and NaN values are not allowed in numeric +#' vectors unless `na.rm` is `TRUE`. +#' +#' @param probs numeric vector of probabilities with values in the +#' interval 0 to 1, inclusive. When 0, it represents the maximum +#' observed, when 1, it represents the maximum observed. When 0.5 it +#' represents the expected probability (mean). +#' +#' @param na.rm logical; if true, any NA and NaN's are removed from +#' `x` before the quantiles are computed. +#' +#' @param names logical; if true, the result has a names attribute. +#' +#' @param onlyProbs logical; if true, only return the probability +#' based confidence interval/prediction interval estimates, +#' otherwise return extra statistics. +#' +#' @param n integer/integerish; this is the n used to calculate the +#' prediction or confidence interval. When `n=0` (default) use the +#' number of non-`NA` observations. When calculating the prediction +#' interval, this represents the number of observations used in the +#' input ("true") distribution. +#' +#' @param pred Use a prediction interval instead of a confidence +#' interval. By default this is `FALSE`. +#' +#' @param m integer. When using the prediction interval this +#' represents the number of samples that will be observed in the +#' future for the prediction interval. +#' +#' @param piMethod gives the prediction interval method (currently only lim) from Lu 2020 +#' +#' @param M number of simulations to run for the LIM PI. +#' +#' @param tol tolerance of root finding in the LIM prediction interval +#' +#' @param ciMethod gives the method for calculating the confidence +#' interval. +#' +#' Can be: +#' +#' - "argestiCoull" or "ac" -- Agresti-Coull method. For a 95\% confidence +#' interval, this method does not use the concept of "adding 2 +#' successes and 2 failures," but rather uses the formulas explicitly +#' described in the following link: +#' +#' https://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Agresti-Coull_Interval. +#' +#' - "wilson" -- Wilson Method +#' +#' - "wilsonCorrect" or "wc" -- Wilson method with continuity correction +#' +#' - "wald" -- Wald confidence interval or standard z approximation. +#' +#' @param ... Arguments passed to default method, allows many +#' different methods to be applied. +#' +#' @return By default the return has the probabilities as names (if +#' named) with the points where the expected distribution are +#' located given the sampling mean and standard deviation. If +#' `onlyProbs=FALSE` then it would prepend mean, variance, standard +#' deviation, minimum, maximum and number of non-NA observations. +#' +#' @export +#' @author Matthew L. Fidler +#' @references +#' +#' - Newcombe, R. G. (1998). "Two-sided confidence intervals for the single +#' proportion: comparison of seven methods". Statistics +#' in Medicine. 17 (8): +#' 857–872. doi:10.1002/(SICI)1097-0258(19980430)17:8<857::AID-SIM777>3.0.CO;2-E. PMID +#' 9595616. +#' +#' - Hezhi Lu, Hua Jin, +#' A new prediction interval for binomial random variable based on inferential models, +#' Journal of Statistical Planning and Inference, +#' Volume 205, +#' 2020, +#' Pages 156-174, +#' ISSN 0378-3758, +#' https://doi.org/10.1016/j.jspi.2019.07.001. +#' @examples +#' +#' x<- rbinom(7001, p=0.375, size=1) +#' binomProbs(x) +#' +#' # you can also use the prediction interval +#' \donttest{ +#' binomProbs(x, pred=TRUE) +#' } +#' +#' # Can get some extra statistics if you request onlyProbs=FALSE +#' binomProbs(x, onlyProbs=FALSE) +#' +#' x[2] <- NA_real_ +#' +#' binomProbs(x, onlyProbs=FALSE) +#' +#' binomProbs(x, na.rm=TRUE) +#' +binomProbs <- function(x, ...) { + UseMethod("binomProbs") +} + +#' @rdname binomProbs +#' @export +binomProbs.default <- function(x, probs=c(0.025, 0.05, 0.5, 0.95, 0.975), na.rm=FALSE, + names=TRUE, onlyProbs=TRUE, n=0L, m=0L, + pred=FALSE, + piMethod=c("lim"), M=500000, + tol=.Machine$double.eps^0.25, + ciMethod=c("wilson", "wilsonCorrect", "agrestiCoull", "wald", "wc", "ac"), ...) { + checkmate::assertNumeric(x, min.len=1, lower=0.0, upper=1.0) + x <- as.double(x) + checkmate::assertIntegerish(n, min.len=1, lower=0, any.missing=FALSE) + n <- as.integer(n) + checkmate::assertIntegerish(m, min.len=1, lower=0, any.missing=FALSE) + m <- as.integer(m) + checkmate::assertNumeric(probs, min.len=1, any.missing = FALSE, lower=0.0, upper=1.0) + checkmate::assertLogical(na.rm, any.missing=FALSE, len=1) + checkmate::assertLogical(names, any.missing=FALSE, len=1) + checkmate::assertLogical(onlyProbs, any.missing=FALSE, len=1) + if (pred) { + .m <- mean(x, na.rm=na.rm) + if (is.na(.m)) { + .ret <- stats::quantile(NULL,probs=probs) + if (!onlyProbs) { + .ret <- c("mean"=NA_real_,"var"=NA_real_, "sd"=NA_real_, "n"=NA_real_, + .ret) + } + } else { + .nC <- sum(!is.na(x)) + if (n == 0L) n <- as.integer(.nC) + if (m == 0L) m <- as.integer(.nC) + .Y <- round(.nC * .m) # number of successes + .ret <- stats::quantile(.Call(`_rxode2_binomProbsPredVec_`, n, m, .Y, M, TRUE, tol), + probs=probs) + if (!onlyProbs) { + .ret <- c("mean"=.m,"var"=.m * (1.0 - .m), "sd"=sqrt(.m * (1.0 - .m)), "n"=.nC, + .ret) + } + } + if (!names) { + names(.ret) <- NULL + } + return(.ret) + } else { + ciMethod <- match.arg(ciMethod) + ciMethod <- setNames(c("wilson"=1L, "wilsonCorrect"=0L, "agrestiCoull"=3L, "wald"=2L, "ac"=3L, "wc"=0L)[ciMethod], NULL) + .ret <- .Call(`_rxode2_binomProbs_`, x, probs, na.rm, n, ciMethod) + .names <- NULL + if (names) { + .names <- paste0(probs*100, "%") + } + if (onlyProbs) { + .ret <- .ret[-1L:-4L] + if (names) { + names(.ret) <- .names + } + } else if (names) { + names(.ret) <- c("mean","var", "sd", "n", .names) + } + .ret + } +} diff --git a/_pkgdown.yml b/_pkgdown.yml index 7e52e5c23..da8be4eda 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -65,7 +65,9 @@ reference: - rxPkg - title: Specialized Simulation functions contents: + - binomProbs - cvPost + - meanProbs - rinvchisq - rxGetSeed - rxPp @@ -205,7 +207,9 @@ navbar: - text: "Getting started" - text: "rxode2 mini language syntax" href: articles/rxode2-syntax.html - - text: "rxode2 with piping ie %>%" + - text: "rxode2 model modification %>%" + href: articles/Modifying-Models.html + - text: "rxode2 pipeline ie %>%" href: articles/rxode2-pipeline.html - text: "Speeding up rxode2 ODE solving" href: articles/rxode2-speed.html diff --git a/data/rxReservedKeywords.rda b/data/rxReservedKeywords.rda index 9e7cff144..80fc13cd1 100644 Binary files a/data/rxReservedKeywords.rda and b/data/rxReservedKeywords.rda differ diff --git a/data/rxResidualError.rda b/data/rxResidualError.rda index 41b46e2c7..df63ee3a5 100644 Binary files a/data/rxResidualError.rda and b/data/rxResidualError.rda differ diff --git a/data/rxSyntaxFunctions.rda b/data/rxSyntaxFunctions.rda index 189135d96..bb46aebcc 100644 Binary files a/data/rxSyntaxFunctions.rda and b/data/rxSyntaxFunctions.rda differ diff --git a/inst/include/rxode2_RcppExports.h b/inst/include/rxode2_RcppExports.h index cc821793b..5b79439d4 100644 --- a/inst/include/rxode2_RcppExports.h +++ b/inst/include/rxode2_RcppExports.h @@ -89,17 +89,17 @@ namespace rxode2 { return Rcpp::as(rcpp_result_gen); } - inline List rxExpandFEta_(CharacterVector state, int neta, int pred) { - typedef SEXP(*Ptr_rxExpandFEta_)(SEXP,SEXP,SEXP); + inline List rxExpandFEta_(CharacterVector state, int neta, int pred, bool isTheta = false) { + typedef SEXP(*Ptr_rxExpandFEta_)(SEXP,SEXP,SEXP,SEXP); static Ptr_rxExpandFEta_ p_rxExpandFEta_ = NULL; if (p_rxExpandFEta_ == NULL) { - validateSignature("List(*rxExpandFEta_)(CharacterVector,int,int)"); + validateSignature("List(*rxExpandFEta_)(CharacterVector,int,int,bool)"); p_rxExpandFEta_ = (Ptr_rxExpandFEta_)R_GetCCallable("rxode2", "_rxode2_rxExpandFEta_"); } RObject rcpp_result_gen; { RNGScope RCPP_rngScope_gen; - rcpp_result_gen = p_rxExpandFEta_(Shield(Rcpp::wrap(state)), Shield(Rcpp::wrap(neta)), Shield(Rcpp::wrap(pred))); + rcpp_result_gen = p_rxExpandFEta_(Shield(Rcpp::wrap(state)), Shield(Rcpp::wrap(neta)), Shield(Rcpp::wrap(pred)), Shield(Rcpp::wrap(isTheta))); } if (rcpp_result_gen.inherits("interrupted-error")) throw Rcpp::internal::InterruptedException(); @@ -1073,17 +1073,59 @@ namespace rxode2 { return Rcpp::as(rcpp_result_gen); } - inline NumericVector meanProbs_(NumericVector x, NumericVector probs, bool naRm, bool useT) { - typedef SEXP(*Ptr_meanProbs_)(SEXP,SEXP,SEXP,SEXP); + inline NumericVector binomProbsPredVec_(int n, int m, int Y, int M, bool doP = true, double tol = 1e-7) { + typedef SEXP(*Ptr_binomProbsPredVec_)(SEXP,SEXP,SEXP,SEXP,SEXP,SEXP); + static Ptr_binomProbsPredVec_ p_binomProbsPredVec_ = NULL; + if (p_binomProbsPredVec_ == NULL) { + validateSignature("NumericVector(*binomProbsPredVec_)(int,int,int,int,bool,double)"); + p_binomProbsPredVec_ = (Ptr_binomProbsPredVec_)R_GetCCallable("rxode2", "_rxode2_binomProbsPredVec_"); + } + RObject rcpp_result_gen; + { + RNGScope RCPP_rngScope_gen; + rcpp_result_gen = p_binomProbsPredVec_(Shield(Rcpp::wrap(n)), Shield(Rcpp::wrap(m)), Shield(Rcpp::wrap(Y)), Shield(Rcpp::wrap(M)), Shield(Rcpp::wrap(doP)), Shield(Rcpp::wrap(tol))); + } + if (rcpp_result_gen.inherits("interrupted-error")) + throw Rcpp::internal::InterruptedException(); + if (Rcpp::internal::isLongjumpSentinel(rcpp_result_gen)) + throw Rcpp::LongjumpException(rcpp_result_gen); + if (rcpp_result_gen.inherits("try-error")) + throw Rcpp::exception(Rcpp::as(rcpp_result_gen).c_str()); + return Rcpp::as(rcpp_result_gen); + } + + inline NumericVector binomProbs_(NumericVector x, NumericVector probs, bool naRm, int nIn, int cont) { + typedef SEXP(*Ptr_binomProbs_)(SEXP,SEXP,SEXP,SEXP,SEXP); + static Ptr_binomProbs_ p_binomProbs_ = NULL; + if (p_binomProbs_ == NULL) { + validateSignature("NumericVector(*binomProbs_)(NumericVector,NumericVector,bool,int,int)"); + p_binomProbs_ = (Ptr_binomProbs_)R_GetCCallable("rxode2", "_rxode2_binomProbs_"); + } + RObject rcpp_result_gen; + { + RNGScope RCPP_rngScope_gen; + rcpp_result_gen = p_binomProbs_(Shield(Rcpp::wrap(x)), Shield(Rcpp::wrap(probs)), Shield(Rcpp::wrap(naRm)), Shield(Rcpp::wrap(nIn)), Shield(Rcpp::wrap(cont))); + } + if (rcpp_result_gen.inherits("interrupted-error")) + throw Rcpp::internal::InterruptedException(); + if (Rcpp::internal::isLongjumpSentinel(rcpp_result_gen)) + throw Rcpp::LongjumpException(rcpp_result_gen); + if (rcpp_result_gen.inherits("try-error")) + throw Rcpp::exception(Rcpp::as(rcpp_result_gen).c_str()); + return Rcpp::as(rcpp_result_gen); + } + + inline NumericVector meanProbs_(NumericVector x, NumericVector probs, bool naRm, bool useT, bool pred, int nIn) { + typedef SEXP(*Ptr_meanProbs_)(SEXP,SEXP,SEXP,SEXP,SEXP,SEXP); static Ptr_meanProbs_ p_meanProbs_ = NULL; if (p_meanProbs_ == NULL) { - validateSignature("NumericVector(*meanProbs_)(NumericVector,NumericVector,bool,bool)"); + validateSignature("NumericVector(*meanProbs_)(NumericVector,NumericVector,bool,bool,bool,int)"); p_meanProbs_ = (Ptr_meanProbs_)R_GetCCallable("rxode2", "_rxode2_meanProbs_"); } RObject rcpp_result_gen; { RNGScope RCPP_rngScope_gen; - rcpp_result_gen = p_meanProbs_(Shield(Rcpp::wrap(x)), Shield(Rcpp::wrap(probs)), Shield(Rcpp::wrap(naRm)), Shield(Rcpp::wrap(useT))); + rcpp_result_gen = p_meanProbs_(Shield(Rcpp::wrap(x)), Shield(Rcpp::wrap(probs)), Shield(Rcpp::wrap(naRm)), Shield(Rcpp::wrap(useT)), Shield(Rcpp::wrap(pred)), Shield(Rcpp::wrap(nIn))); } if (rcpp_result_gen.inherits("interrupted-error")) throw Rcpp::internal::InterruptedException(); diff --git a/inst/po/en@quot/LC_MESSAGES/R-rxode2.mo b/inst/po/en@quot/LC_MESSAGES/R-rxode2.mo new file mode 100644 index 000000000..a435430fe Binary files /dev/null and b/inst/po/en@quot/LC_MESSAGES/R-rxode2.mo differ diff --git a/man-roxygen/rmdhunks/speed.Rmdh b/man-roxygen/rmdhunks/speed.Rmdh index 9fa84489b..20f879fe7 100644 --- a/man-roxygen/rmdhunks/speed.Rmdh +++ b/man-roxygen/rmdhunks/speed.Rmdh @@ -29,7 +29,7 @@ mod1 <- function() { d/dt(peri) = Q*C2 - Q*C3 d/dt(eff) = Kin - Kout*(1-C2/(EC50+C2))*eff eff(0) = 1 - }) + }) } ``` @@ -37,7 +37,7 @@ Or you can also specify the end-points for simulation/estimation just like `nlmixr2`: ```{r mod2speed} -mod2 <- function() { +mod2f <- function() { ini({ TKA <- 0.3 TCL <- 7 @@ -53,7 +53,7 @@ mod2 <- function() { eff.add.sd <- 0.1 }) model({ - KA <- TKA + KA <- TKA CL <- TCL*exp(eta.cl) V2 <- TV2*exp(eta.v) Q <- TQ @@ -70,7 +70,7 @@ mod2 <- function() { eff(0) = 1 C2 ~ prop(c2.prop.sd) eff ~ add(eff.add.sd) - }) + }) } ``` @@ -86,7 +86,7 @@ The first step can be done by `rxode2(mod1)` or `mod1()` (or for the second mode ```{r mod3eval} mod1 <- mod1() -mod2 <- rxode2(mod2) +mod2f <- rxode2(mod2f) ``` The second step is to create the underlying "classic" `rxode2` model, @@ -100,8 +100,8 @@ You can see the differences below: ```{r modSimModel} summary(mod1$simulationModel) summary(mod1$simulationIniModel) -summary(mod2$simulationModel) -summary(mod2$simulationIniModel) +summary(mod2f$simulationModel) +summary(mod2f$simulationIniModel) ``` If you wish to speed up multiple simualtions from the `rxode2` @@ -110,7 +110,7 @@ functions, you need to pre-calculate care of the steps above: ```{r simModel2} mod1 <- mod1$simulationModel -mod2 <- mod2$simulationModel +mod2 <- mod2f$simulationModel ``` These functions then can act like a normal ui model to be solved. You @@ -180,7 +180,7 @@ runFor <- function(){ return(res) } ``` -## Running with apply +## Running with apply In general for R, the `apply` types of functions perform better than a `for` loop, so the tutorial also suggests this speed enhancement @@ -209,7 +209,7 @@ runSingleThread <- function(){ rxode2 supports multi-threaded solves, so another option is to have `2` threads (called `cores` in the solve options, you can see the options -in `rxControl()` or `rxSolve()`). +in `rxControl()` or `rxSolve()`). ```{r} run2Thread <- function(){ @@ -260,9 +260,103 @@ threads. 4 threads is a good number to use without any prior knowledge because most systems these days have at least 4 threads (or 2 processors with 4 threads). +# Increasing speed with compiler options + +One of the way that allows faster ODE solving is to make some +approximations that make some math operators like `exp()` faster but +not technically accurate enough to follow the IEEE standard for the +math functions values (there are other implications that I will not +cover here). + +While these are optimizations are [opt-in for +Julia](https://github.com/JuliaLang/julia/blob/master/base/fastmath.jl) +since they compile everything each session, CRAN has a more +conservative approach since individuals do not compile each R function +before running it. + +Still, `rxode2` models can be compiled with this option without +disturbing CRAN policies. The key is to set an option. Here is an +example: + +```{r} +# Using the first example subset to PK +mod2f <- function() { + ini({ + TKA <- 0.3 + TCL <- 7 + TV2 <- 40 + TQ <- 10 + TV3 <- 300 + TKin <- 0.2 + TKout <- 0.2 + TEC50 <- 8 + eta.cl + eta.v ~ c(0.09, + 0.08, 0.25) + c2.prop.sd <- 0.1 + }) + model({ + KA <- TKA + CL <- TCL*exp(eta.cl) + V2 <- TV2*exp(eta.v) + Q <- TQ + V3 <- TV3 + Kin <- TKin + Kout <- TKout + EC50 <- TEC50 + C2 = centr/V2 + C3 = peri/V3 + d/dt(depot) = -KA*depot + d/dt(centr) = KA*depot - CL*C2 - Q*C2 + Q*C3 + d/dt(peri) = Q*C2 - Q*C3 + C2 ~ prop(c2.prop.sd) + }) +} + +mod2f <- mod2f() + +mod2s <- mod2f$simulationIniModel + +ev <- et(amountUnits="mg", timeUnits="hours") %>% + et(amt=10000, addl=9,ii=12,cmt="depot") %>% + et(time=120, amt=2000, addl=4, ii=14, cmt="depot") %>% + et(0:240) # Add sampling + +bench1 <- microbenchmark(standardCompile=rxSolve(mod2s, ev, nSub=1000)) + +# Now clear the cache of models so we can change the compile options for the same model +rxClean() + +# Use withr to preserve the options +withr::with_options(list(rxode2.compile.O="fast"), { + mod2s <- mod2f$simulationIniModel +}) + +bench2 <- microbenchmark(fastCompile=rxSolve(mod2s, ev, nSub=1000)) + +bench <- rbind(bench1, bench2) + +print(bench) + +autoplot(bench) +``` + +Note compiler settings can be tricky and if you setup your system wide +`Makevars` it may interact with this setting. For example if you use +`ccache` the compile may not be produced with the same options since +it was cached with the other options. + +For example, on the github runner (which generates this page), there +is no advantage to the `"fast"` compile. However, on my development +laptop there is [some minimal speed +increase](https://github.com/nlmixr2/rxode2/issues/583#issuecomment-1834468627). +You should probably check before using this yourself. + +This is disabled by default since there is only minimum increase in +speed. + # A real life example -Before some of the parallel solving was implemented, the fastest way +cBefore some of the parallel solving was implemented, the fastest way to run `rxode2` was with `lapply`. This is how Rik Schoemaker created the data-set for `nlmixr` comparisons, but reduced to run faster automatic building of the pkgdown website. @@ -277,7 +371,7 @@ library(data.table) d/dt(centr) = KA*abs-(CL/V)*centr; C2=centr/V; " - + #Create the rxode2 simulation object mod1 <- rxode2(model = ode1) @@ -310,7 +404,7 @@ mod1 <- rxode2(model = ode1) params.all[, AMT := rep(100 * doses,nsubg)] Startlapply <- Sys.time() - + #Run the simulations using lapply for speed s = lapply(1:nsub, function(i) { #selects the parameters associated with the subject to be simulated @@ -331,12 +425,12 @@ Startlapply <- Sys.time() #merges the parameters and ID number to the simulation output x[, names(params) := params] }) - + #runs the entire sequence of 100 subjects and binds the results to the object res res = as.data.table(do.call("rbind", s)) - + Stoplapply <- Sys.time() - + print(Stoplapply - Startlapply) ``` @@ -374,7 +468,7 @@ ev <- do.call("rbind", et(id=seq(1, nsubg) + (i - 1) * nsubg) %>% ## Convert to data frame to skip sorting the data ## When binding the data together - as.data.frame + as.data.frame })) ## To better compare, use the same output, that is data.table res <- rxSolve(rx, ev, omega=omega, returnType="data.table") @@ -388,12 +482,12 @@ things to keep in mind: - `rxode2` use the thread-safe sitmo `threefry` routines for simulation of `eta` values. Therefore the results are expected to be different (also the random samples are taken in a different order which would be different) - + - This prior simulation was run in R 3.5, which has a different random number generator so the results in this simulation will be different from the actual nlmixr comparison when using the slower simulation. - + - This speed comparison used `data.table`. `rxode2` uses `data.table` internally (when available) try to speed up sorting, so this would be different than installations where `data.table` is not diff --git a/man/binomProbs.Rd b/man/binomProbs.Rd new file mode 100644 index 000000000..b86760a7b --- /dev/null +++ b/man/binomProbs.Rd @@ -0,0 +1,140 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{binomProbs} +\alias{binomProbs} +\alias{binomProbs.default} +\title{Calculate expected confidence bands with binomial sampling distribution} +\usage{ +binomProbs(x, ...) + +\method{binomProbs}{default}( + x, + probs = c(0.025, 0.05, 0.5, 0.95, 0.975), + na.rm = FALSE, + names = TRUE, + onlyProbs = TRUE, + n = 0L, + m = 0L, + pred = FALSE, + piMethod = c("lim"), + M = 5e+05, + tol = .Machine$double.eps^0.25, + ciMethod = c("wilson", "wilsonCorrect", "agrestiCoull", "wald", "wc", "ac"), + ... +) +} +\arguments{ +\item{x}{numeric vector whose mean and probability based confidence +values are wanted, NA and NaN values are not allowed in numeric +vectors unless \code{na.rm} is \code{TRUE}.} + +\item{...}{Arguments passed to default method, allows many +different methods to be applied.} + +\item{probs}{numeric vector of probabilities with values in the +interval 0 to 1, inclusive. When 0, it represents the maximum +observed, when 1, it represents the maximum observed. When 0.5 it +represents the expected probability (mean).} + +\item{na.rm}{logical; if true, any NA and NaN's are removed from +\code{x} before the quantiles are computed.} + +\item{names}{logical; if true, the result has a names attribute.} + +\item{onlyProbs}{logical; if true, only return the probability +based confidence interval/prediction interval estimates, +otherwise return extra statistics.} + +\item{n}{integer/integerish; this is the n used to calculate the +prediction or confidence interval. When \code{n=0} (default) use the +number of non-\code{NA} observations. When calculating the prediction +interval, this represents the number of observations used in the +input ("true") distribution.} + +\item{m}{integer. When using the prediction interval this +represents the number of samples that will be observed in the +future for the prediction interval.} + +\item{pred}{Use a prediction interval instead of a confidence +interval. By default this is \code{FALSE}.} + +\item{piMethod}{gives the prediction interval method (currently only lim) from Lu 2020} + +\item{M}{number of simulations to run for the LIM PI.} + +\item{tol}{tolerance of root finding in the LIM prediction interval} + +\item{ciMethod}{gives the method for calculating the confidence +interval. + +Can be: +\itemize{ +\item "argestiCoull" or "ac" -- Agresti-Coull method. For a 95\\% confidence +interval, this method does not use the concept of "adding 2 +successes and 2 failures," but rather uses the formulas explicitly +described in the following link: +} + +https://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Agresti-Coull_Interval. +\itemize{ +\item "wilson" -- Wilson Method +\item "wilsonCorrect" or "wc" -- Wilson method with continuity correction +\item "wald" -- Wald confidence interval or standard z approximation. +}} +} +\value{ +By default the return has the probabilities as names (if +named) with the points where the expected distribution are +located given the sampling mean and standard deviation. If +\code{onlyProbs=FALSE} then it would prepend mean, variance, standard +deviation, minimum, maximum and number of non-NA observations. +} +\description{ +This is meant to perform in the same way as \code{quantile()} so it can +be a drop in replacement for code using \code{quantile()} but using +distributional assumptions. +} +\details{ +It is used for confidence intervals with rxode2 solved objects using +\code{confint(mean="binom")} +} +\examples{ + +x<- rbinom(7001, p=0.375, size=1) +binomProbs(x) + +# you can also use the prediction interval +\donttest{ +binomProbs(x, pred=TRUE) +} + +# Can get some extra statistics if you request onlyProbs=FALSE +binomProbs(x, onlyProbs=FALSE) + +x[2] <- NA_real_ + +binomProbs(x, onlyProbs=FALSE) + +binomProbs(x, na.rm=TRUE) + +} +\references{ +\itemize{ +\item Newcombe, R. G. (1998). "Two-sided confidence intervals for the single +proportion: comparison of seven methods". Statistics +in Medicine. 17 (8): +857–872. doi:10.1002/(SICI)1097-0258(19980430)17:8<857::AID-SIM777>3.0.CO;2-E. PMID +9595616. +\item Hezhi Lu, Hua Jin, +A new prediction interval for binomial random variable based on inferential models, +Journal of Statistical Planning and Inference, +Volume 205, +2020, +Pages 156-174, +ISSN 0378-3758, +https://doi.org/10.1016/j.jspi.2019.07.001. +} +} +\author{ +Matthew L. Fidler +} diff --git a/man/dot-iniGetAppendArg.Rd b/man/dot-iniGetAppendArg.Rd new file mode 100644 index 000000000..14d2fd49c --- /dev/null +++ b/man/dot-iniGetAppendArg.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/piping-ini.R +\name{.iniGetAppendArg} +\alias{.iniGetAppendArg} +\title{This gets the append arg for the ini({}) piping} +\usage{ +.iniGetAppendArg(f, s) +} +\arguments{ +\item{f}{this is the \code{try(force(append))} argument,} + +\item{s}{this is the \code{as.character(substitute(append))} argument} +} +\value{ +corrected ini piping argument + +This is exported for creating new ini methods that have the same +requirements for piping +} +\description{ +This gets the append arg for the ini({}) piping +} +\author{ +Matthew L. Fidler +} +\keyword{internal} diff --git a/man/dot-modelHandleModelLines.Rd b/man/dot-modelHandleModelLines.Rd index d8deaad5f..a60da6ef4 100644 --- a/man/dot-modelHandleModelLines.Rd +++ b/man/dot-modelHandleModelLines.Rd @@ -8,8 +8,8 @@ modelLines, rxui, modifyIni = FALSE, - append = FALSE, - auto = TRUE, + append = NULL, + auto = getOption("rxode2.autoVarPiping", TRUE), cov = NULL, envir ) diff --git a/man/genShinyApp.template.Rd b/man/genShinyApp.template.Rd index 1c4bf9533..6730b373a 100644 --- a/man/genShinyApp.template.Rd +++ b/man/genShinyApp.template.Rd @@ -77,7 +77,7 @@ if (requireNamespace("shiny", quietly=TRUE)) { } } \seealso{ -\code{\link[=rxode2]{rxode2()}},\code{\link[=eventTable]{eventTable()}}, and the package \pkg{shiny} (\url{https://shiny.rstudio.com}). +\code{\link[=rxode2]{rxode2()}},\code{\link[=eventTable]{eventTable()}}, and the package \pkg{shiny} (\url{https://shiny.posit.co}). } \concept{PK/PD} \concept{pharmacometrics} diff --git a/man/meanProbs.Rd b/man/meanProbs.Rd index 0dcec476a..1da85c567 100644 --- a/man/meanProbs.Rd +++ b/man/meanProbs.Rd @@ -3,7 +3,7 @@ \name{meanProbs} \alias{meanProbs} \alias{meanProbs.default} -\title{Calculate expected quantiles with normal or t sampling distribution} +\title{Calculate expected confidence bands or prediction intreval with normal or t sampling distribution} \usage{ meanProbs(x, ...) @@ -13,7 +13,10 @@ meanProbs(x, ...) na.rm = FALSE, names = TRUE, useT = TRUE, - useProbs = FALSE + onlyProbs = TRUE, + pred = FALSE, + n = 0L, + ... ) } \arguments{ @@ -21,7 +24,11 @@ meanProbs(x, ...) values are wanted, NA and NaN values are not allowed in numeric vectors unless ‘na.rm’ is ‘TRUE’.} -\item{probs}{numeric vector of probabilities with values in \link{0,1}.} +\item{...}{Arguments passed to default method, allows many +different methods to be applied.} + +\item{probs}{numeric vector of probabilities with values in the +interval from 0 to 1 .} \item{na.rm}{logical; if true, any NA and NaN's are removed from \code{x} before the quantiles are computed.} @@ -32,13 +39,28 @@ vectors unless ‘na.rm’ is ‘TRUE’.} the confidence-based estimates. If false use the normal distribution to calculate the confidence based estimates.} -\item{useProbs}{logical; if true, only return the probability +\item{onlyProbs}{logical; if true, only return the probability based confidence interval estimates, otherwise return} + +\item{pred}{logical; if true use the prediction interval instead of +the confidence interval} + +\item{n}{integer/integerish; this is the n used to calculate the +prediction or confidence interval. When \code{n=0} (default) use the +number of non-\code{NA} observations.} +} +\value{ +By default the return has the probabilities as names (if +named) with the points where the expected distribution are +located given the sampling mean and standard deviation. If +\code{onlyProbs=FALSE} then it would prepend mean, variance, standard +deviation, minimum, maximum and number of non-NA observations. } \description{ -The generic function \code{meanProbs} produces expected quantiles under -either the t distribution or the normal sampling distribution. This -uses \code{qnorm()} or \code{qt()} with the mean and standard deviation. +The generic function \code{meanProbs} produces expected confidence bands +under either the t distribution or the normal sampling +distribution. This uses \code{qnorm()} or \code{qt()} with the mean and +standard deviation. } \details{ For a single probability, p, it uses either: @@ -53,11 +75,29 @@ The smallest observation corresponds to a probability of 0 and the largest to a probability of 1 and the mean corresponds to 0.5. The mean and standard deviation of the sample is calculated based -on Welford's method for a single pass +on Welford's method for a single pass. + +This is meant to perform in the same way as \code{quantile()} so it can +be a drop in replacement for code using \code{quantile()} but using +distributional assumptions. } \examples{ -meanProbs(x <- rnorm(1001)) +quantile(x<- rnorm(1001)) +meanProbs(x) + +# Can get some extra statistics if you request onlyProbs=FALSE +meanProbs(x, onlyProbs=FALSE) + +x[2] <- NA_real_ + +meanProbs(x, onlyProbs=FALSE) + +quantile(x<- rnorm(42)) + +meanProbs(x) + +meanProbs(x, useT=FALSE) } \author{ diff --git a/man/model.Rd b/man/model.Rd index eb6b18fa8..bc081d0a9 100644 --- a/man/model.Rd +++ b/man/model.Rd @@ -9,13 +9,41 @@ \alias{model.default} \title{Model block for rxode2/nlmixr models} \usage{ -\method{model}{`function`}(x, ..., append = FALSE, auto = TRUE, cov = NULL, envir = parent.frame()) +\method{model}{`function`}( + x, + ..., + append = NULL, + auto = getOption("rxode2.autoVarPiping", TRUE), + cov = NULL, + envir = parent.frame() +) -\method{model}{rxUi}(x, ..., append = FALSE, auto = TRUE, cov = NULL, envir = parent.frame()) +\method{model}{rxUi}( + x, + ..., + append = NULL, + auto = getOption("rxode2.autoVarPiping", TRUE), + cov = NULL, + envir = parent.frame() +) -\method{model}{rxode2}(x, ..., append = FALSE, auto = TRUE, cov = NULL, envir = parent.frame()) +\method{model}{rxode2}( + x, + ..., + append = NULL, + auto = getOption("rxode2.autoVarPiping", TRUE), + cov = NULL, + envir = parent.frame() +) -\method{model}{rxModelVars}(x, ..., append = FALSE, auto = TRUE, cov = NULL, envir = parent.frame()) +\method{model}{rxModelVars}( + x, + ..., + append = NULL, + auto = getOption("rxode2.autoVarPiping", TRUE), + cov = NULL, + envir = parent.frame() +) model( x, diff --git a/man/reexports.Rd b/man/reexports.Rd index 365c14ab7..d6ab11a0c 100644 --- a/man/reexports.Rd +++ b/man/reexports.Rd @@ -62,6 +62,7 @@ \alias{rxSetIni0} \alias{.getLastIdLvl} \alias{.expandPars} +\alias{toTrialDuration} \title{Objects exported from other packages} \keyword{internal} \description{ @@ -75,7 +76,7 @@ below to see their documentation. \item{magrittr}{\code{\link[magrittr:pipe]{\%>\%}}} - \item{rxode2et}{\code{\link[rxode2et:dot-clearPipe]{.clearPipe}}, \code{\link[rxode2et:dot-collectWarnings]{.collectWarnings}}, \code{\link[rxode2et:dot-s3register]{.s3register}}, \code{\link[rxode2et]{add.dosing}}, \code{\link[rxode2et]{add.sampling}}, \code{\link[rxode2et]{as.et}}, \code{\link[rxode2et:rxEvid]{as.rxEvid}}, \code{\link[rxode2et:rxRateDur]{as.rxRateDur}}, \code{\link[rxode2et]{et}}, \code{\link[rxode2et]{etExpand}}, \code{\link[rxode2et]{etRbind}}, \code{\link[rxode2et]{etRep}}, \code{\link[rxode2et]{etSeq}}, \code{\link[rxode2et]{eventTable}}, \code{\link[rxode2et]{rxCbindStudyIndividual}}, \code{\link[rxode2et]{rxEtDispatchSolve}}, \code{\link[rxode2et]{rxEvid}}, \code{\link[rxode2et]{rxRateDur}}, \code{\link[rxode2et]{rxReq}}, \code{\link[rxode2et]{rxStack}}} + \item{rxode2et}{\code{\link[rxode2et:dot-clearPipe]{.clearPipe}}, \code{\link[rxode2et:dot-collectWarnings]{.collectWarnings}}, \code{\link[rxode2et:dot-s3register]{.s3register}}, \code{\link[rxode2et]{add.dosing}}, \code{\link[rxode2et]{add.sampling}}, \code{\link[rxode2et]{as.et}}, \code{\link[rxode2et:rxEvid]{as.rxEvid}}, \code{\link[rxode2et:rxRateDur]{as.rxRateDur}}, \code{\link[rxode2et]{et}}, \code{\link[rxode2et]{etExpand}}, \code{\link[rxode2et]{etRbind}}, \code{\link[rxode2et]{etRep}}, \code{\link[rxode2et]{etSeq}}, \code{\link[rxode2et]{eventTable}}, \code{\link[rxode2et]{rxCbindStudyIndividual}}, \code{\link[rxode2et]{rxEtDispatchSolve}}, \code{\link[rxode2et]{rxEvid}}, \code{\link[rxode2et]{rxRateDur}}, \code{\link[rxode2et]{rxReq}}, \code{\link[rxode2et]{rxStack}}, \code{\link[rxode2et]{toTrialDuration}}} \item{rxode2parse}{\code{\link[rxode2parse:dot-getLastIdLvl]{.getLastIdLvl}}, \code{\link[rxode2parse]{forderForceBase}}, \code{\link[rxode2parse]{rxDerived}}, \code{\link[rxode2parse]{rxSetIni0}}} diff --git a/man/rxAppendModel.Rd b/man/rxAppendModel.Rd index 3896adddf..d403f4a91 100644 --- a/man/rxAppendModel.Rd +++ b/man/rxAppendModel.Rd @@ -4,12 +4,12 @@ \alias{rxAppendModel} \title{Append two rxui models together} \usage{ -rxAppendModel(model1, model2) +rxAppendModel(..., common = TRUE) } \arguments{ -\item{model1}{rxUi model 1} +\item{...}{models to append together} -\item{model2}{rxUi model 2} +\item{common}{boolean that determines if you need a common value to bind} } \value{ New model with both models appended together diff --git a/man/rxCompile.Rd b/man/rxCompile.Rd index 25685936e..f9cf56615 100644 --- a/man/rxCompile.Rd +++ b/man/rxCompile.Rd @@ -92,13 +92,13 @@ function.} \value{ An rxDll object that has the following components \itemize{ -\item \code{dll}{DLL path} -\item \code{model}{model specification} -\item \code{.c}{A function to call C code in the correct context from the DLL -using the \code{\link[=.C]{.C()}} function.} -\item \code{.call}{A function to call C code in the correct context from the DLL -using the \code{\link[=.Call]{.Call()}} function.} -\item \code{args}{A list of the arguments used to create the rxDll object.} +\item \code{dll} DLL path +\item \code{model} model specification +\item \code{.c} A function to call C code in the correct context from the DLL +using the \code{\link[=.C]{.C()}} function. +\item \code{.call} A function to call C code in the correct context from the DLL +using the \code{\link[=.Call]{.Call()}} function. +\item \code{args} A list of the arguments used to create the rxDll object. } } \description{ diff --git a/man/rxErrTypeCombine.Rd b/man/rxErrTypeCombine.Rd index c2b5f3484..1b6ed455b 100644 --- a/man/rxErrTypeCombine.Rd +++ b/man/rxErrTypeCombine.Rd @@ -15,7 +15,7 @@ swaps \code{oldErrType} and \code{addTransform} and assigns \code{oldErrType} to zero assuming that there is no prior distribution.} -\item{newTransform}{This is the new distribution that is being +\item{newErrType}{This is the new distribution that is being "added" to the current transformation. These assumes the inputs are in the preferred distribution name, as determined by \code{rxPreferredDistributionName()}} diff --git a/man/rxExpandFEta_.Rd b/man/rxExpandFEta_.Rd index 5bad0135b..6daba896a 100644 --- a/man/rxExpandFEta_.Rd +++ b/man/rxExpandFEta_.Rd @@ -4,7 +4,7 @@ \alias{rxExpandFEta_} \title{Expand d(f)/d(eta)} \usage{ -rxExpandFEta_(state, neta, pred) +rxExpandFEta_(state, neta, pred, isTheta = FALSE) } \arguments{ \item{state}{is the state to expand} @@ -12,6 +12,8 @@ rxExpandFEta_(state, neta, pred) \item{neta}{is the number of etas} \item{pred}{type of prediction} + +\item{isTheta}{logical, is the expansion actually for thetas instead of etas} } \value{ String of symengine expressions to evaluate to calculate df/deta diff --git a/man/rxFun.Rd b/man/rxFun.Rd index 2a8ddbad3..2228d3a55 100644 --- a/man/rxFun.Rd +++ b/man/rxFun.Rd @@ -3,39 +3,39 @@ \name{rxFun} \alias{rxFun} \alias{rxRmFun} -\title{Add user function to rxode2} +\title{Add/Create C functions for use in rxode2} \usage{ rxFun(name, args, cCode) rxRmFun(name) } \arguments{ -\item{name}{This gives the name of the user function} +\item{name}{This can either give the name of the user function or +be a simple R function that you wish to convert to C. If you +have rxode2 convert the R function to C, the name of the function +will match the function name provided and the number of arguments +will match the R function provided. Hence, if you are providing +an R function for conversion to C, the rest of the arguments are +implied.} \item{args}{This gives the arguments of the user function} \item{cCode}{This is the C-code for the new function} } -\value{ -nothing -} \description{ -This adds a user function to rxode2 that can be called. If needed, -these functions can be differentiated by numerical differences or -by adding the derivatives to rxode2's internal derivative table -with \code{\link[=rxD]{rxD()}} +Add/Create C functions for use in rxode2 } \examples{ \donttest{ -## Right now rxode2 is not aware of the function f +## Right now rxode2 is not aware of the function fun ## Therefore it cannot translate it to symengine or ## Compile a model with it. try(rxode2("a=fun(a,b,c)")) ## Note for this approach to work, it cannot interfere with C -## function names or reserved rxode2 specical terms. Therefore -## f(x) would not work since f is an alias for bioaviability. +## function names or reserved rxode2 special terms. Therefore +## f(x) would not work since f is an alias for bioavailability. fun <- " double fun(double a, double b, double c) { @@ -71,8 +71,68 @@ rxFromSE("Derivative(fun(a,b,c),a)") # You can also remove the functions by `rxRmFun` rxRmFun("fun") + +# you can also use R functions directly in rxode2 + + +gg <- function(x, y) { + x + y +} + +f <- rxode2({ + z = gg(x, y) +}) + + +e <- et(1:10) |> as.data.frame() + +e$x <- 1:10 +e$y <- 21:30 + +rxSolve(f, e) + +# Note that since it touches R, it can only run single-threaded. +# There are also requirements for the function: +# +# 1. It accepts one value per argument (numeric) +# +# 2. It returns one numeric value + +# If it is a simple function (like gg) you can also convert it to C +# using rxFun and load it into rxode2 + +rxFun(gg) + +rxSolve(f, e) + +# to stop the recompile simply reassign the function +f <- rxode2(f) + +rxSolve(f, e) + +rxRmFun("gg") +rm(gg) +rm(f) + + +# You can also automatically convert a R function to R code (and +# calculate first derivatives) + +fun <- function(a, b, c) { + a^2+b*a+c } + +rxFun(fun) + +# You can see the R code if you want with rxC + +message(rxC("fun")) + +# you can also remove both the function and the +# derivatives with rxRmFun("fun") + +rxRmFun("fun") + + } -\author{ -Matthew L. Fidler } diff --git a/man/rxModelVars.Rd b/man/rxModelVars.Rd index 8666a7baa..1b0f2b68f 100644 --- a/man/rxModelVars.Rd +++ b/man/rxModelVars.Rd @@ -21,17 +21,17 @@ rxModelVarsS3(obj) \value{ A list of rxode2 model properties including: \itemize{ -\item \code{params}{ a character vector of names of the model parameters} -\item \code{lhs}{ a character vector of the names of the model calculated parameters} -\item \code{state}{ a character vector of the compartments in rxode2 object} -\item \code{trans}{ a named vector of translated model properties +\item \code{params} a character vector of names of the model parameters +\item \code{lhs} a character vector of the names of the model calculated parameters +\item \code{state} a character vector of the compartments in rxode2 object +\item \code{trans} a named vector of translated model properties including what type of jacobian is specified, the \code{C} function prefixes, -as well as the \code{C} functions names to be called through the compiled model.} -\item \code{md5}{a named vector that gives the digest of the model (\code{file_md5}) and the parsed model -(\code{parsed_md5})} -\item \code{model}{ a named vector giving the input model (\code{model}), +as well as the \code{C} functions names to be called through the compiled model. +\item \code{md5} a named vector that gives the digest of the model (\code{file_md5}) and the parsed model +(\code{parsed_md5}) +\item \code{model} a named vector giving the input model (\code{model}), normalized model (no comments and standard syntax for parsing, \code{normModel}), -and interim code that is used to generate the final C file \code{parseModel}} +and interim code that is used to generate the final C file \code{parseModel} } } \description{ diff --git a/man/rxPp.Rd b/man/rxPp.Rd index 3b742bc24..426af9761 100644 --- a/man/rxPp.Rd +++ b/man/rxPp.Rd @@ -68,8 +68,9 @@ rxPp(10, 1 / 10, gamma = 2, tmax = 10, randomOrder = TRUE) ## This uses an arbitrary function to sample a non-homogenous Poisson process rxPp(10, 1 / 10, prob = function(x) { - 1 / x + 1/(1+abs(x)) }) + } \author{ Matthew Fidler diff --git a/man/rxRepR0_.Rd b/man/rxRepR0_.Rd index c0b7b8ecf..6175734e6 100644 --- a/man/rxRepR0_.Rd +++ b/man/rxRepR0_.Rd @@ -7,7 +7,7 @@ rxRepR0_(neta) } \arguments{ -\item{number}{ETA to substitute} +\item{neta}{ETA to substitute} } \value{ Returns a string of R code to substitute the rx_r expression in the symengine environment .s diff --git a/man/rxS.Rd b/man/rxS.Rd index 898eca1ff..b55404472 100644 --- a/man/rxS.Rd +++ b/man/rxS.Rd @@ -4,7 +4,7 @@ \alias{rxS} \title{Load a model into a symengine environment} \usage{ -rxS(x, doConst = TRUE, promoteLinSens = FALSE) +rxS(x, doConst = TRUE, promoteLinSens = FALSE, envir = parent.frame()) } \arguments{ \item{x}{rxode2 object} @@ -13,6 +13,9 @@ rxS(x, doConst = TRUE, promoteLinSens = FALSE) \item{promoteLinSens}{Promote solved linear compartment systems to sensitivity-based solutions.} + +\item{envir}{default is \code{NULL}; Environment to put symengine +variables in.} } \value{ rxode2/symengine environment diff --git a/man/rxSetPipingAuto.Rd b/man/rxSetPipingAuto.Rd index 28225894b..c48a282e9 100644 --- a/man/rxSetPipingAuto.Rd +++ b/man/rxSetPipingAuto.Rd @@ -7,7 +7,7 @@ rxSetPipingAuto( thetamodelVars = rex::rex(or("tv", "t", "pop", "POP", "Pop", "TV", "T", "cov", "err", "eff")), - covariateExceptions = rex::rex(start, or("wt", "sex", "crcl"), end), + covariateExceptions = rex::rex(start, or("wt", "sex", "crcl", "kout"), end), etaParts = c("eta", "ETA", "Eta", "ppv", "PPV", "Ppv", "iiv", "Iiv", "bsv", "Bsv", "BSV", "bpv", "Bpv", "BPV", "psv", "PSV", "Psv") ) diff --git a/man/rxSetupScale.Rd b/man/rxSetupScale.Rd index 005282f1e..e3cc32a56 100644 --- a/man/rxSetupScale.Rd +++ b/man/rxSetupScale.Rd @@ -9,9 +9,9 @@ rxSetupScale(obj, scale = NULL, extraArgs = NULL) \arguments{ \item{obj}{rxode2 object} -\item{extraArgs}{A list of extra args to parse for initial conditions.} +\item{scale}{A numeric vector scales} -\item{inits}{A numeric vector of initial conditions.} +\item{extraArgs}{A list of extra args to parse for initial conditions.} } \value{ setup scale for changing compartment values diff --git a/man/rxSolve.Rd b/man/rxSolve.Rd index 965c99fb6..4bd3d557a 100644 --- a/man/rxSolve.Rd +++ b/man/rxSolve.Rd @@ -133,7 +133,8 @@ rxSolve( addlKeepsCov = FALSE, addlDropSs = TRUE, ssAtDoseTime = TRUE, - ss2cancelAllPending = FALSE + ss2cancelAllPending = FALSE, + envir = parent.frame() ) \method{rxSolve}{`function`}( @@ -143,7 +144,8 @@ rxSolve( inits = NULL, ..., theta = NULL, - eta = NULL + eta = NULL, + envir = parent.frame() ) \method{rxSolve}{rxUi}( @@ -153,7 +155,8 @@ rxSolve( inits = NULL, ..., theta = NULL, - eta = NULL + eta = NULL, + envir = parent.frame() ) \method{rxSolve}{rxode2tos}( @@ -163,7 +166,8 @@ rxSolve( inits = NULL, ..., theta = NULL, - eta = NULL + eta = NULL, + envir = parent.frame() ) \method{rxSolve}{nlmixr2FitData}( @@ -173,7 +177,8 @@ rxSolve( inits = NULL, ..., theta = NULL, - eta = NULL + eta = NULL, + envir = parent.frame() ) \method{rxSolve}{nlmixr2FitCore}( @@ -183,7 +188,8 @@ rxSolve( inits = NULL, ..., theta = NULL, - eta = NULL + eta = NULL, + envir = parent.frame() ) \method{rxSolve}{default}( @@ -193,7 +199,8 @@ rxSolve( inits = NULL, ..., theta = NULL, - eta = NULL + eta = NULL, + envir = parent.frame() ) \method{update}{rxSolve}(object, ...) @@ -228,7 +235,13 @@ rxSolve( \method{solve}{rxEt}(a, b, ...) -rxControl(..., params = NULL, events = NULL, inits = NULL) +rxControl( + ..., + params = NULL, + events = NULL, + inits = NULL, + envir = parent.frame() +) } \arguments{ \item{object}{is a either a rxode2 family of objects, or a file-name @@ -803,6 +816,9 @@ cancels all pending doses like \code{SS=1}. When \code{FALSE} the pending doses not canceled with \code{SS=2} (the infusions started before \code{SS=2} occurred are canceled, though).} +\item{envir}{is the environment to look for R user functions +(defaults to parent environment)} + \item{a}{when using \code{solve()}, this is equivalent to the \code{object} argument. If you specify \code{object} later in the argument list it overwrites this parameter.} diff --git a/man/rxToSE.Rd b/man/rxToSE.Rd index fd636ff4b..85c1f4076 100644 --- a/man/rxToSE.Rd +++ b/man/rxToSE.Rd @@ -7,11 +7,21 @@ \alias{.rxFromSE} \title{rxode2 to symengine environment} \usage{ -rxToSE(x, envir = NULL, progress = FALSE, promoteLinSens = TRUE) +rxToSE( + x, + envir = NULL, + progress = FALSE, + promoteLinSens = TRUE, + parent = parent.frame() +) .rxToSE(x, envir = NULL, progress = FALSE) -rxFromSE(x, unknownDerivatives = c("forward", "central", "error")) +rxFromSE( + x, + unknownDerivatives = c("forward", "central", "error"), + parent = parent.frame() +) .rxFromSE(x) } @@ -26,6 +36,8 @@ variables in.} \item{promoteLinSens}{Promote solved linear compartment systems to sensitivity-based solutions.} +\item{parent}{is the parent environment to look for R-based user functions} + \item{unknownDerivatives}{When handling derivatives from unknown functions, the translator will translate into different types of numeric derivatives. The currently supported methods are: diff --git a/man/rxUiGet.Rd b/man/rxUiGet.Rd index 0b012c9d2..0f297005c 100644 --- a/man/rxUiGet.Rd +++ b/man/rxUiGet.Rd @@ -23,6 +23,7 @@ \alias{rxUiGet.ini} \alias{rxUiGet.iniFun} \alias{rxUiGet.modelFun} +\alias{rxUiGet.model} \alias{rxUiGet.modelDesc} \alias{rxUiGet.thetaLower} \alias{rxUiGet.thetaUpper} @@ -81,6 +82,8 @@ rxUiGet(x, ...) \method{rxUiGet}{modelFun}(x, ...) +\method{rxUiGet}{model}(x, ...) + \method{rxUiGet}{modelDesc}(x, ...) \method{rxUiGet}{thetaLower}(x, ...) diff --git a/man/rxode2.Rd b/man/rxode2.Rd index 2d8108f38..b2d6cb892 100644 --- a/man/rxode2.Rd +++ b/man/rxode2.Rd @@ -21,7 +21,8 @@ rxode2( linCmtSens = c("linCmtA", "linCmtB", "linCmtC"), indLin = FALSE, verbose = FALSE, - fullPrint = getOption("rxode2.fullPrint", FALSE) + fullPrint = getOption("rxode2.fullPrint", FALSE), + envir = parent.frame() ) RxODE( @@ -39,7 +40,8 @@ RxODE( linCmtSens = c("linCmtA", "linCmtB", "linCmtC"), indLin = FALSE, verbose = FALSE, - fullPrint = getOption("rxode2.fullPrint", FALSE) + fullPrint = getOption("rxode2.fullPrint", FALSE), + envir = parent.frame() ) rxode( @@ -57,7 +59,8 @@ rxode( linCmtSens = c("linCmtA", "linCmtB", "linCmtC"), indLin = FALSE, verbose = FALSE, - fullPrint = getOption("rxode2.fullPrint", FALSE) + fullPrint = getOption("rxode2.fullPrint", FALSE), + envir = parent.frame() ) } \arguments{ @@ -127,6 +130,9 @@ compartmental model} \item{fullPrint}{When using \code{printf} within the model, if \code{TRUE} print on every step (except ME/indLin), otherwise when \code{FALSE} print only when calculating the \code{d/dt}} + +\item{envir}{is the environment to look for R user functions +(defaults to parent environment)} } \value{ An object (environment) of class \code{rxode2} (see Chambers and Temple Lang (2001)) @@ -174,7 +180,7 @@ consisting of the following list of strings and functions: `atol`: a numeric absolute tolerance (1e-08 by default); - `rtol`: a numeric relative tolerance (1e-06 by default).e + `rtol`: a numeric relative tolerance (1e-06 by default). The output of \\dQuote\{solve\} is a matrix with as many rows as there are sampled time points and as many columns as system variables @@ -226,9 +232,6 @@ mod <- rxode2(\{ d/dt(centr) <- F*KA*depot - CL*C2 - Q*C2 + Q*C3; \}) }\if{html}{\out{}} - -\if{html}{\out{
}}\preformatted{## using C compiler: ‘gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0’ -}\if{html}{\out{
}} \itemize{ \item Inside a \code{rxode2("")} string statement: }\if{html}{\out{ @@ -244,9 +247,6 @@ mod <- rxode2(\{ d/dt(centr) <- F*KA*depot - CL*C2 - Q*C2 + Q*C3; ") }\if{html}{\out{}} - -\if{html}{\out{
}}\preformatted{## using C compiler: ‘gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0’ -}\if{html}{\out{
}} \itemize{ \item In a file name to be loaded by rxode2: }\if{html}{\out{ @@ -325,9 +325,7 @@ compilation model. \if{html}{\out{
}}\preformatted{mod$simulationModel }\if{html}{\out{
}} -\if{html}{\out{
}}\preformatted{## using C compiler: ‘gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0’ - -## rxode2 2.0.13.9000 model named rx_a80a19966fa254e55fa958b934a783f9 model (ready). +\if{html}{\out{
}}\preformatted{## rxode2 2.0.14.9000 model named rx_22699ef487579a63baec999e5bee4f82 model (ready). ## x$state: depot, center ## x$stateExtra: cp ## x$params: tka, tcl, tv, add.sd, eta.ka, eta.cl, eta.v, rxerr.cp @@ -338,9 +336,7 @@ compilation model. mod$simulationIniModel }\if{html}{\out{
}} -\if{html}{\out{
}}\preformatted{## using C compiler: ‘gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0’ - -## rxode2 2.0.13.9000 model named rx_efba4df1b26a5a9e54ae25cd8fe7247f model (ready). +\if{html}{\out{
}}\preformatted{## rxode2 2.0.14.9000 model named rx_85bfff7e67355fe5de08b65b7a424b1e model (ready). ## x$state: depot, center ## x$stateExtra: cp ## x$params: tka, tcl, tv, add.sd, eta.ka, eta.cl, eta.v, rxerr.cp diff --git a/po/R-rxode2.pot b/po/R-rxode2.pot index 74c05d35c..f519349d8 100644 --- a/po/R-rxode2.pot +++ b/po/R-rxode2.pot @@ -1,184 +1,190 @@ msgid "" msgstr "" -"Project-Id-Version: Rxode2 1.1.0\n" -"POT-Creation-Date: 2021-05-26 10:39\n" +"Project-Id-Version: rxode2 2.0.14.9000\n" +"POT-Creation-Date: 2023-10-30 08:03\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" - -msgid "Rxode2 requires 'rtools' for custom models\nPlease download from http://cran.r-project.org/bin/windows/Rtools/,\ninstall and restart your R session before proceeding" +msgid "unsupported expression for ini({}) block" msgstr "" -msgid "'modName' has to be a single length character" +msgid "unsupported expression of ini({}) block" msgstr "" -msgid "'extraC' needs to point to a file that exists and is readable" +msgid "do not know how to convert this to an `ini` expression" msgstr "" -msgid "'collapseModel' needs to be logical" +msgid "error converting character vector to model({}) expression" msgstr "" -msgid "'indLin' needs to be logical" +msgid "unsupported expression of model({}) block" msgstr "" -msgid "'debug' needs to be logical" +msgid "do not know how to convert this to an `model` expression" msgstr "" -msgid "'package' needs to a single character for the package name" +msgid "cannot convert to rxUi object" msgstr "" -msgid "with packages 'modName' is required" +msgid "could not convert to rxUi object" msgstr "" -msgid "must specify exactly one of 'model' or 'filename'" +msgid "'" msgstr "" -msgid "cannot delete Dll in package" +msgid "' needs to be a rxUi model" msgstr "" -msgid "'$parse' is no longer supported" +msgid "there must be at least one prediction in the model({}) block" msgstr "" -msgid "cannot update package model" +msgid ". Use `~` for predictions" msgstr "" -msgid "cannot figure out how to handle the model argument" +msgid "' needs to be a single endpoint model" msgstr "" -msgid "sensitivities do not make sense for models without ODEs" +msgid "' needs to be a (transformably) normal model" msgstr "" -msgid "Jacobians do not make sense for models without ODEs" +msgid "' needs to be a normal model" msgstr "" -msgid "Do not know how to add %s to Rxode2 solved object %s" +msgid "' needs to be a completely mu-referenced model (ie tcl+eta.cl)" msgstr "" -msgid "unknown model" +msgid "' residual parameters cannot depend on the model calculated parameters" msgstr "" -msgid "model" +msgid "' can only have population estimates" msgstr "" -msgid "cannot create Rxode2 model" +msgid "' needs to be a mixed effect model" msgstr "" -msgid "Rxode2 already building model, waiting for lock file removal" +msgid "' can only have random effects on ID" msgstr "" -msgid "lock file: \"%s\"" +msgid "generate defines" msgstr "" -msgid "." +msgid "Copy header to inst directory" msgstr "" -msgid "error building model on another thread" +msgid "generate rxResidualError and update documentation" msgstr "" -msgid "do not need to recompile, minimal change to model detected" +msgid "done" msgstr "" -msgid "unloaded all Rxode2 dlls before loading the current DLL" +msgid "generate rxReservedKeywords and update documentation" msgstr "" -msgid "something went wrong in compilation" +msgid "generate rxSyntaxFunctions and update documentation" msgstr "" -msgid "'removeJac' is no longer supported" +msgid "generate rxode2_control.h" msgstr "" -msgid "'removeSens' is no longer supported" +msgid "querying default rxode2 object contents" msgstr "" -msgid "simulation summaries must be between 0 and 1" +msgid "saved!" msgstr "" msgid "summarizing data..." msgstr "" -msgid "done" +msgid "rxode2 doesn't support '%s' translation for 'omega' translation" msgstr "" -msgid "Rxode2 doesn't support '%s' translation for 'omega' translation" +msgid "do not know how to handle type '%s'" msgstr "" -msgid "do not know how to handle type '%s'" +msgid "rxode2 only supports THETA[#] and ETA[#] numbers" msgstr "" -msgid "Rxode2 only supports THETA[#] and ETA[#] numbers" +msgid "cannot find lambda" msgstr "" -msgid "cannot supply both 'by' and 'length.out'" +msgid "cannot find additive standard deviation for '" msgstr "" -msgid "improper arguments to 'et'" +msgid "; this parameter could be estimated by another endpoint, to fix move outside of error expression." msgstr "" -msgid "when supplying vectors of 'time', 'amt' they need to be the same size" +msgid "for propF() or powF(), f must be part of the model and not estimated" msgstr "" -msgid "only a single evid 'evid' can be specified ('%s')" +msgid "cannot find proportional standard deviation" msgstr "" -msgid "', '" +msgid "cannot find power standard deviation" msgstr "" -msgid "only a single compartment 'cmt' can be specified ('%s')" +msgid "cannot find exponent of power expression" msgstr "" -msgid "only a single rate 'rate' can be specified ('%s')" +msgid "cannot find additive standard deviation" msgstr "" -msgid "only a single duration 'dur' can be specified ('%s')" +msgid "cannot find pow standard deviation" msgstr "" -msgid "'nsim' is ignored when simulating event tables" +msgid "cannot find pow exponent" msgstr "" -msgid "requires package 'units'" +msgid "t distribution needs a proper degrees of freedom specified" msgstr "" -msgid "the only valid number defining a unit is '1', signifying a unitless unit" +msgid "last element in ordinal simulation of c(p1=0, p2=0.5, ...) must be a number, not a named number" msgstr "" -msgid "clearing both amount and time units\nfor more precise control use 'et(amountUnits=\"\")' or 'et(timeUnits=\"\")'" +msgid "names for ordinal simulation incorrect" msgstr "" -msgid "'deparse.level' not used with Rxode2 event tables" +msgid "not enough categories to estimate" msgstr "" -msgid "'length.out' makes no sense with event tables" +msgid "uiModel must be a evaluated UI model by rxode2(modelFunction) or modelFunction()" msgstr "" -msgid "'each' makes no sense with event tables" +msgid "old transform not in the proper format" msgstr "" -msgid "'evid' is unitless" +msgid "you cannot combine 't' and 'cauchy' distributions" msgstr "" -msgid "there are no individuals left to solve in %s data" +msgid "you cannot combine 't' and 'dnorm' distributions" msgstr "" -msgid "'ID' missing in '%s' dataset\nindividual parameters are assumed to have the same order as the event dataset" +msgid "you cannot combine 'dnorm' and 'cauchy' distributions" msgstr "" -msgid "unable to detect 'ID' correctly in '%s' dataset\nindividual parameters are assumed to have the same order as the dataset" +msgid "you cannot combine 'cauchy' and 'dnorm' distributions" msgstr "" -msgid "dates can only be specified by one of: 'DATE', 'DAT1', 'DAT2', 'DAT3' / 'TIME'" +msgid "the left handed side of the error expression (function: '" msgstr "" -msgid "dates formatted as MONTH-DAY or DAY alone are not supported in this conversion" +msgid "') can only be functions with 'linCmt' or 'll'" msgstr "" -msgid "date/time format was not correctly specified" +msgid "endpoint parameter(s) missing, duplicated, or defined with '~':" msgstr "" -msgid "cannot figure out numeric time" +msgid "," +msgstr "" + +msgid "a rxode2 ui model must have more than error definition(s) in the `model({})` block" +msgstr "" + +msgid "install.packages('shiny') to use genShinyApp.template()" msgstr "" msgid "need 'amt' aesthetic" @@ -193,52 +199,166 @@ msgstr "" msgid "stat_cens requires the following aesthetics: upper, lower or cens (and optionally limit)" msgstr "" +msgid "unknown variable expression:" +msgstr "" + +msgid "rxode2 does not know how to handle this modelExtract object" +msgstr "" + +msgid "out" +msgstr "" + +msgid "could not build model for inclusion in package" +msgstr "" + msgid "'package' needs to be specified" msgstr "" -msgid "'log=\"%s\"' not supported" +msgid "some etas defaulted to non-mu referenced, possible parsing error:" msgstr "" -msgid "needs units" +msgid "as a work-around try putting the mu-referenced expression on a simple line" msgstr "" -msgid "needs \"ggplot2\" 3.3.0" +msgid "currently do not support IOV etc" msgstr "" -msgid "this is only used in 'data.table'" +msgid "syntax/parsing errors (see above) and additionally:" msgstr "" -msgid "'rxIndLinState' list element '%s' must be a unnamed character vector" +msgid "syntax/parsing errors:" msgstr "" -msgid "'%s' is from '%s' and cannot be used in this context" +msgid "syntax/parsing errors, see above" msgstr "" -msgid "specified %s initial conditions when there are only %s states" +msgid "cannot find parameter '" msgstr "" -msgid "only one 'initCondition=' supported" +msgid "trying to fix '" msgstr "" -msgid "this was not generated from nlmixr, loading into symengine" +msgid "', but already fixed" msgstr "" -msgid "cannot identify parameters for sensitivity analysis\n with nlmixr an 'eta' initial estimate must use '~'" +msgid "trying to unfix '" msgstr "" -msgid "none of the predictions depend on 'ETA'" +msgid "', but already unfixed" msgstr "" -msgid "some of the predictions do not depend on 'ETA'" +msgid "piping for '" msgstr "" -msgid "parameters:" +msgid "' failed, the estimate should only be 1 value" msgstr "" -msgid "," +msgid "the '" +msgstr "" + +msgid "' piping lower, estimate, and/or upper estimate is in the wrong order" +msgstr "" + +msgid "the new label for '" +msgstr "" + +msgid "' must be a character string" +msgstr "" + +msgid "'append' must be NULL, logical, numeric, or character" +msgstr "" + +msgid "Cannot find parameter '" +msgstr "" + +msgid "parameter '" +msgstr "" + +msgid "' set to be moved after itself, no change in order made" +msgstr "" + +msgid "only theta parameters can be moved. '" +msgstr "" + +msgid "' is not a theta parameter" +msgstr "" + +msgid "a NULL value for '" +msgstr "" + +msgid "' piping does not make sense" +msgstr "" + +msgid "to assign a new label, use '%s <- label(\"%s\")'" +msgstr "" + +msgid "invalid expr for ini() modification" +msgstr "" + +msgid "cannot figure out what to do with the ini({}) function" msgstr "" -msgid "cannot figure out PK parameters to convert" +msgid "cannot find '" +msgstr "" + +msgid "' in lhs model, cannot append" +msgstr "" + +msgid "the variable '" +msgstr "" + +msgid "' must be in the defined the model for piping this: '" +msgstr "" + +msgid "with single endpoint model prediction '" +msgstr "" + +msgid "' is changed to '" +msgstr "" + +msgid "the error '" +msgstr "" + +msgid "' is not in the multiple-endpoint model and cannot be modified" +msgstr "" + +msgid "do not know where to put label" +msgstr "" + +msgid "cannot figure out what to do with the unnamed vector" +msgstr "" + +msgid "cannot figure out what to do with the unnamed list" +msgstr "" + +msgid "one of the list items supplied to piping is non-numeric" +msgstr "" + +msgid "vectors and list need to be named numeric expression" +msgstr "" + +msgid "the `sim` endpoints requested in the plot do not exist in the solved object:" +msgstr "" + +msgid "some `sim` requested items do not exist in the solved object and were ignored:" +msgstr "" + +msgid "sim." +msgstr "" + +msgid "the items requested in the plot do not exist in the solved object:" +msgstr "" + +msgid "some requested items do not exist in the solved object and were ignored:" +msgstr "" + +msgid "needs \"ggplot2\" 3.3.0" +msgstr "" + +msgid "'rxIndLinState' list element '%s' must be a unnamed character vector" +msgstr "" + +msgid "'%s' is from '%s' and cannot be used in this context" msgstr "" msgid "unsupported lhs in optimize expression" @@ -277,28 +397,22 @@ msgstr "" msgid "calculate symbolic inverse: t(chol.mat) %*% chol.mat ..." msgstr "" -msgid "initial 'omega' matrix inverse is non-positive definite" -msgstr "" - -msgid "zero matrix" -msgstr "" - -msgid "================================================================================" +msgid "." msgstr "" -msgid "Rxode2 compiled with dparser '" +msgid "initial 'omega' matrix inverse is non-positive definite" msgstr "" -msgid "' but dparser '" +msgid "zero matrix" msgstr "" -msgid "dparser" +msgid "object is wrong type for `rxUiGet`" msgstr "" -msgid "' is loaded\nRecompile Rxode2 with the this version of dparser" +msgid "================================================================================" msgstr "" -msgid "Rxode2 compiled with PreciseSums '" +msgid "rxode2 compiled with PreciseSums '" msgstr "" msgid "' but PreciseSums '" @@ -307,13 +421,16 @@ msgstr "" msgid "PreciseSums" msgstr "" -msgid "' is loaded\nRecompile Rxode2 with the this version of PreciseSums" +msgid "' is loaded\nRecompile rxode2 with the this version of PreciseSums" +msgstr "" + +msgid "rxode2 compiled with rxode2parse with a different solving structure" msgstr "" -msgid "Rtools is not set up correctly!\n\nYou need a working Rtools installation for Rxode2 to compile models" +msgid "can try: install.packages('rxode2', type='source')" msgstr "" -msgid "Rxode2" +msgid "rxode2" msgstr "" msgid "using" @@ -328,7 +445,7 @@ msgstr "" msgid "========================================" msgstr "" -msgid "Rxode2 has not detected OpenMP support and will run in single-threaded mode" +msgid "rxode2 has not detected OpenMP support and will run in single-threaded mode" msgstr "" msgid "sysname" @@ -346,7 +463,94 @@ msgstr "" msgid "; To get best performance enable OpenMP" msgstr "" -msgid "detected new version of Rxode2, cleaning cache" +msgid "detected new version of rxode2, cleaning cache" +msgstr "" + +msgid "'modName' has to be a single length character" +msgstr "" + +msgid "'extraC' needs to point to a file that exists and is readable" +msgstr "" + +msgid "'collapseModel' needs to be logical" +msgstr "" + +msgid "'indLin' needs to be logical" +msgstr "" + +msgid "'debug' needs to be logical" +msgstr "" + +msgid "'package' needs to a single character for the package name" +msgstr "" + +msgid "with packages 'modName' is required" +msgstr "" + +msgid "must specify exactly one of 'model' or 'filename'" +msgstr "" + +msgid "model functions can only be called with one argument" +msgstr "" + +msgid "cannot delete Dll in package" +msgstr "" + +msgid "'$parse' is no longer supported" +msgstr "" + +msgid "cannot update package model" +msgstr "" + +msgid "cannot figure out how to handle the model argument" +msgstr "" + +msgid "sensitivities do not make sense for models without ODEs" +msgstr "" + +msgid "Jacobians do not make sense for models without ODEs" +msgstr "" + +msgid "Do not know how to add %s to rxode2 solved object %s" +msgstr "" + +msgid "unknown model" +msgstr "" + +msgid "model" +msgstr "" + +msgid "cannot create rxode2 model" +msgstr "" + +msgid "cannot seem to remove '" +msgstr "" + +msgid "rxode2 already building model, waiting for lock file removal" +msgstr "" + +msgid "lock file: \"%s\"" +msgstr "" + +msgid "error building model on another thread" +msgstr "" + +msgid "do not need to recompile, minimal change to model detected" +msgstr "" + +msgid "unloaded all rxode2 dlls before loading the current DLL" +msgstr "" + +msgid "something went wrong in compilation" +msgstr "" + +msgid "'removeJac' is no longer supported" +msgstr "" + +msgid "'removeSens' is no longer supported" +msgstr "" + +msgid "need an rxode2-type object to extract model variables" msgstr "" msgid "'df' must be greater than 0" @@ -361,10 +565,7 @@ msgstr "" msgid "'shape' cannot be 0" msgstr "" -msgid "'rate'/'scale' cannot be 0" -msgstr "" - -msgid "specify 'rate' or 'scale' but not both" +msgid "'rate' cannot be 0" msgstr "" msgid "'df1' cannot be 0" @@ -373,9 +574,6 @@ msgstr "" msgid "'df2' cannot be 0" msgstr "" -msgid "'rate' cannot be 0" -msgstr "" - msgid "'df' cannot be 0" msgstr "" @@ -385,19 +583,25 @@ msgstr "" msgid "when 'gamma' is not 1, 'tmax' cannot be infinite" msgstr "" -msgid "duplicate arguments do not make sense" +msgid "'transitAbs' is no longer supported, use 'evid=7' instead" +msgstr "" + +msgid "unused argument:" msgstr "" msgid "covariates can no longer be specified by 'covs' include them in the event dataset" msgstr "" +msgid "'maxSS' must be larger than 'minSS'" +msgstr "" + msgid "events can be pipeline or solving arguments not both" msgstr "" -msgid "need an Rxode2 compiled model as the start of the pipeline" +msgid "need an rxode2 compiled model as the start of the pipeline" msgstr "" -msgid "need an Rxode2 events as a part of the pipeline" +msgid "need an rxode2 events as a part of the pipeline" msgstr "" msgid "'events' in pipeline AND in solving arguments, please provide just one" @@ -409,12 +613,18 @@ msgstr "" msgid "'inits' in pipeline AND in solving arguments, please provide just one" msgstr "" +msgid "duplicate arguments do not make sense" +msgstr "" + msgid "covariates can no longer be specified by 'covs'\n include them in the event dataset\n\nindividual covariates: Can be specified by a 'iCov' dataset\n each each individual covariate has a value\n\ntime varying covariates: modify input event data-frame or\n 'eventTable' to include covariates(https://tinyurl.com/y52wfc2y)\n\nEach approach needs the covariates named to match the variable in the model" msgstr "" msgid "'iCov' has information contained in parameters/event data\nduplicate columns: '%s'" msgstr "" +msgid "', '" +msgstr "" + msgid "'theta' cannot be a data.frame" msgstr "" @@ -457,10 +667,19 @@ msgstr "" msgid "'iCov' must be an input dataset" msgstr "" +msgid "Unsupported type of model trying to be solved" +msgstr "" + +msgid "'sensCmt' must be lower than the number of compartments 'ncmt'" +msgstr "" + +msgid "'rxControl' must be a rxode2 control options list" +msgstr "" + msgid "name argument must be a length-one character vector" msgstr "" -msgid "a new function requires a C function so it can be used in Rxode2" +msgid "a new function requires a C function so it can be used in rxode2" msgstr "" msgid "already defined user function '" @@ -475,12 +694,6 @@ msgstr "" msgid "' to remove" msgstr "" -msgid "cannot take a second derivative" -msgstr "" - -msgid "bad 'linCmtB' derivative" -msgstr "" - msgid "derivatives must be a list of functions with at least 1 element" msgstr "" @@ -526,7 +739,7 @@ msgstr "" msgid "'transit' can only take 2-3 arguments" msgstr "" -msgid "'%s' only acceps 1 argument" +msgid "'%s' only accepts 1 argument" msgstr "" msgid "'%s' only acceps 2 arguments" @@ -547,7 +760,13 @@ msgstr "" msgid "'expit' requires 1-3 arguments" msgstr "" -msgid "function '%s' or its derivatives are not supported in Rxode2" +msgid "function '%s' or its derivatives are not supported in rxode2" +msgstr "" + +msgid "R user function '%s' has variable number of arguments with'...' and is not supported in rxode2" +msgstr "" + +msgid "user function '%s' requires %d arguments (supplied %d)" msgstr "" msgid "[...] expressions not supported" @@ -556,6 +775,9 @@ msgstr "" msgid "'polygamma' takes 2 arguments" msgstr "" +msgid "'%s' only acceps 1 argument" +msgstr "" + msgid "'%s' takes %s arguments" msgstr "" @@ -571,7 +793,7 @@ msgstr "" msgid "' using numerical differences instead" msgstr "" -msgid "Rxode2/symengine does not know how to take a derivative of '%s'" +msgid "rxode2/symengine does not know how to take a derivative of '%s'" msgstr "" msgid "'Derivative' conversion only takes one function and one argument" @@ -580,10 +802,10 @@ msgstr "" msgid "() takes 0-1 arguments" msgstr "" -msgid "'%s' not supported in symengine->Rxode2" +msgid "'%s' not supported in symengine->rxode2" msgstr "" -msgid "Rxode2 doesn't support '%s' translation for 'Omega' translation" +msgid "rxode2 doesn't support '%s' translation for 'Omega' translation" msgstr "" msgid "do not know how to handle type" @@ -655,7 +877,82 @@ msgstr "" msgid "'." msgstr "" -msgid "package \"%s\" needed for this function to work" +msgid "cannot figure out what to do with model assignment" +msgstr "" + +msgid "cannot figure out what to do with ini assignment" +msgstr "" + +msgid "wrong input for 'x' in .bodySetRxUi" +msgstr "" + +msgid "cannot figure out how to assign this to the with rxode()<-" +msgstr "" + +msgid "do not know how to assign this" +msgstr "" + +msgid "the first model does not have variables that are used by the second model" +msgstr "" + +msgid "there needs to be at least one population parameter in 'model1'" +msgstr "" + +msgid "cannot remove from compressed 'rxUi'\nfirst decompress with `rxode2::rxUiDecompress()'" +msgstr "" + +msgid "control must be a list-like object" +msgstr "" + +msgid "cannot assign value to compressed 'rxUi'\nfirst decompress with `rxode2::rxUiDecompress()'" +msgstr "" + +msgid "to rename a variable you need to use 'newName=oldName' syntax" +msgstr "" + +msgid "to rename a variable you need to use '" +msgstr "" + +msgid "=oldName' syntax" +msgstr "" + +msgid "=oldName' syntax, where oldName is a variable" +msgstr "" + +msgid "the new variable '" +msgstr "" + +msgid "' is already present in the model; cannot replace '" +msgstr "" + +msgid "' with '" +msgstr "" + +msgid "the old variable '" +msgstr "" + +msgid "' is not present in the model and cannot be renamed to '" +msgstr "" + +msgid "unknown expression" +msgstr "" + +msgid "rxode2 model function can only have one 'ini({})' block" +msgstr "" + +msgid "rxode2 model function requires one 'model({})' block" +msgstr "" + +msgid "'model({})' is not on the last line of the function, rearranging; function cannot be called directly to produce model object" +msgstr "" + +msgid "the parameter(s) '" +msgstr "" + +msgid "' cannot be an error and between subject variability" +msgstr "" + +msgid "rxode2 does not know how to handle this model statement" msgstr "" msgid "'wd' is depreciated" diff --git a/po/R-zh_CN.po b/po/R-zh_CN.po index a8bd303d7..ff8ce0742 100644 --- a/po/R-zh_CN.po +++ b/po/R-zh_CN.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: rxode2 1.1.0\n" -"POT-Creation-Date: 2021-05-26 10:39\n" +"POT-Creation-Date: 2023-10-30 08:03\n" "PO-Revision-Date: 2023-07-03 00:00\n" "Last-Translator: FuYongchao <3212418315@qq.com>\n" "Language-Team: FuYongchao <3212418315@qq.com>\n" @@ -10,429 +10,661 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" +#, fuzzy +msgid "unsupported expression for ini({}) block" +msgstr "" -msgid "rxode2 requires 'rtools' for custom models\n" -"Please download from http://cran.r-project.org/bin/windows/Rtools/,\n" -"install and restart your R session before proceeding" -msgstr "rxode2的自定义模型“rtools”\n" -"请从http://cran.r-project.org/bin/windows/Rtools/下载rtools,\n" -"在完成rtools安装与重新启动R会话后,继续之前流程" - -msgid "'modName' has to be a single length character" -msgstr "“modName”必须是字符串类型的标量或单个长度的字符型向量" +#, fuzzy +msgid "unsupported expression of ini({}) block" +msgstr "" -msgid "'extraC' needs to point to a file that exists and is readable" -msgstr "“extraC”需要指向一个存在并且可读的文件" +#, fuzzy +msgid "do not know how to convert this to an `ini` expression" +msgstr "\"(errors)\"/\"(PRED)\"" -msgid "'collapseModel' needs to be logical" -msgstr "“collapseModel”需要合乎逻辑" +msgid "error converting character vector to model({}) expression" +msgstr "" -msgid "'indLin' needs to be logical" -msgstr "“indLin”需要合乎逻辑" +#, fuzzy +msgid "unsupported expression of model({}) block" +msgstr "" -msgid "'debug' needs to be logical" -msgstr "“调试(debug)”需要合乎逻辑" +#, fuzzy +msgid "do not know how to convert this to an `model` expression" +msgstr "" -msgid "'package' needs to a single character for the package name" -msgstr "“添加包”需要一个字符作为添加包的名称" +msgid "cannot convert to rxUi object" +msgstr "" -msgid "with packages 'modName' is required" -msgstr "“modName”添加包是必需的" +msgid "could not convert to rxUi object" +msgstr "" -msgid "must specify exactly one of 'model' or 'filename'" -msgstr "必须准确指定“model”(模型)或“filename”(文件名)之一" +#, fuzzy +msgid "'" +msgstr "'." -msgid "cannot delete Dll in package" -msgstr "无法删除添加包中的 Dll" +#, fuzzy +msgid "' needs to be a rxUi model" +msgstr "(debug)" -msgid "'$parse' is no longer supported" -msgstr "“$parse”不再被支持" +msgid "there must be at least one prediction in the model({}) block" +msgstr "" -msgid "cannot update package model" -msgstr "无法更新添加包模型" +msgid ". Use `~` for predictions" +msgstr "" -msgid "cannot figure out how to handle the model argument" -msgstr "无法弄清楚如何处理模型参数" +msgid "' needs to be a single endpoint model" +msgstr "" -msgid "sensitivities do not make sense for models without ODEs" -msgstr "灵敏度对于没有常微分方程的模型没有意义" +msgid "' needs to be a (transformably) normal model" +msgstr "" -msgid "Jacobians do not make sense for models without ODEs" -msgstr "雅可比算法对于没有常微分方程的模型没有意义" +#, fuzzy +msgid "' needs to be a normal model" +msgstr "(debug)" -msgid "Do not know how to add %s to rxode2 solved object %s" -msgstr "不知道如何将 %s 添加到 rxode2 已求解对象 %s" +msgid "' needs to be a completely mu-referenced model (ie tcl+eta.cl)" +msgstr "" -msgid "unknown model" -msgstr "未知的模型" +msgid "' residual parameters cannot depend on the model calculated parameters" +msgstr "" -msgid "model" -msgstr "模型" +msgid "' can only have population estimates" +msgstr "" -msgid "cannot create rxode2 model" -msgstr "无法创建 rxode2 模型" +msgid "' needs to be a mixed effect model" +msgstr "" -msgid "rxode2 already building model, waiting for lock file removal" -msgstr "rxode2 已经构建模型,正在等待锁定文件删除" +msgid "' can only have random effects on ID" +msgstr "" -msgid "lock file: \"%s\"" -msgstr "锁定文件:“%s”" +msgid "generate defines" +msgstr "" -msgid "." -msgstr "." +msgid "Copy header to inst directory" +msgstr "" -msgid "error building model on another thread" -msgstr "在另一个线程上构建模型时出错" +msgid "generate rxResidualError and update documentation" +msgstr "" -msgid "do not need to recompile, minimal change to model detected" -msgstr "无需重新编译,检测到对模型的最小更改" +msgid "done" +msgstr "" -msgid "unloaded all rxode2 dlls before loading the current DLL" -msgstr "在加载当前 DLL 之前卸载了所有 rxode2 dll" +msgid "generate rxReservedKeywords and update documentation" +msgstr "" -msgid "something went wrong in compilation" -msgstr "编译时出错" +msgid "generate rxSyntaxFunctions and update documentation" +msgstr "" -msgid "'removeJac' is no longer supported" -msgstr "“removeJac”不再被支持" +msgid "generate rxode2_control.h" +msgstr "" -msgid "'removeSens' is no longer supported" -msgstr "“removeSens”不再被支持" +msgid "querying default rxode2 object contents" +msgstr "" -msgid "simulation summaries must be between 0 and 1" -msgstr "模拟摘要必须介于 0 和 1 之间" +msgid "saved!" +msgstr "" msgid "summarizing data..." -msgstr "汇总数据..." - -msgid "done" -msgstr "已做完" +msgstr "..." msgid "rxode2 doesn't support '%s' translation for 'omega' translation" -msgstr "rxode2 不支持对的'omega'转换的'%s'转换" +msgstr "rxode2 'omega''%s'" msgid "do not know how to handle type '%s'" -msgstr "不知道如何处理类型 '%s'" +msgstr " '%s'" msgid "rxode2 only supports THETA[#] and ETA[#] numbers" -msgstr "rxode2 仅支持 THETA[#] 和 ETA[#] 数字" +msgstr "rxode2 THETA[#] ETA[#] " + +msgid "cannot find lambda" +msgstr "" + +msgid "cannot find additive standard deviation for '" +msgstr "" + +msgid "" +"; this parameter could be estimated by another endpoint, to fix move outside " +"of error expression." +msgstr "" -msgid "cannot supply both 'by' and 'length.out'" -msgstr "不能同时提供“by”和“length.out”" +msgid "for propF() or powF(), f must be part of the model and not estimated" +msgstr "" -msgid "improper arguments to 'et'" -msgstr "对“et”的不当参数" +msgid "cannot find proportional standard deviation" +msgstr "" -msgid "when supplying vectors of 'time', 'amt' they need to be the same size" -msgstr "当提供“time”、“amt”的向量时,它们需要具有相同的大小" +msgid "cannot find power standard deviation" +msgstr "" -msgid "only a single evid 'evid' can be specified ('%s')" -msgstr "只有一个 evid 'evid'能用于描述('%s')" +msgid "cannot find exponent of power expression" +msgstr "" -msgid "', '" -msgstr "', '" +msgid "cannot find additive standard deviation" +msgstr "" -msgid "only a single compartment 'cmt' can be specified ('%s')" -msgstr "只有单个房室“cmt”能用于描述(“%s”)" +msgid "cannot find pow standard deviation" +msgstr "" -msgid "only a single rate 'rate' can be specified ('%s')" -msgstr "只有单个速率“rate”能用于描述(“%s”)" +msgid "cannot find pow exponent" +msgstr "" -msgid "only a single duration 'dur' can be specified ('%s')" -msgstr "只有单个持续时间“dur”能用于描述(“%s”)" +msgid "t distribution needs a proper degrees of freedom specified" +msgstr "" -msgid "'nsim' is ignored when simulating event tables" -msgstr "模拟事件表时“nsim”被忽略" +msgid "" +"last element in ordinal simulation of c(p1=0, p2=0.5, ...) must be a number, " +"not a named number" +msgstr "" -msgid "requires package 'units'" -msgstr "需要“unites”添加包" +msgid "names for ordinal simulation incorrect" +msgstr "" -msgid "the only valid number defining a unit is '1', signifying a unitless unit" -msgstr "唯一有效的作为单位的数字是“1”,表示单位是没有单位" +msgid "not enough categories to estimate" +msgstr "" -msgid "clearing both amount and time units\n" -"for more precise control use 'et(amountUnits=\"\")' or 'et(timeUnits=\"\")'" -msgstr "清除\"amout(药量)\"和\"time(时间)\"的单位\n" -"要进行更精确的控制,请使用“et(amountUnits=\"\")”或“et(timeUnits=\"\")”" +msgid "" +"uiModel must be a evaluated UI model by rxode2(modelFunction) or " +"modelFunction()" +msgstr "" -msgid "'deparse.level' not used with rxode2 event tables" -msgstr "“deparse.level”未与 rxode2 事件表一起使用" +msgid "old transform not in the proper format" +msgstr "" -msgid "'length.out' makes no sense with event tables" -msgstr "“length.out”对事件表毫无意义" +msgid "you cannot combine 't' and 'cauchy' distributions" +msgstr "" -msgid "'each' makes no sense with event tables" -msgstr "“each”对于事件表毫无意义" +msgid "you cannot combine 't' and 'dnorm' distributions" +msgstr "" -msgid "'evid' is unitless" -msgstr "“evid”是无单位的" +msgid "you cannot combine 'dnorm' and 'cauchy' distributions" +msgstr "" -msgid "there are no individuals left to solve in %s data" -msgstr "%s 数据中没有需要求解的个体" +msgid "you cannot combine 'cauchy' and 'dnorm' distributions" +msgstr "" -msgid "'ID' missing in '%s' dataset\n" -"individual parameters are assumed to have the same order as the event dataset" -msgstr "“%s”数据集中缺少“ID”\n" -"假定各个参数的顺序与事件数据集的顺序相同" +msgid "the left handed side of the error expression (function: '" +msgstr "" -msgid "unable to detect 'ID' correctly in '%s' dataset\n" -"individual parameters are assumed to have the same order as the dataset" -msgstr "无法正确检测“%s”数据集中的“ID”\n" -"假定各个参数的顺序与数据集相同" +msgid "') can only be functions with 'linCmt' or 'll'" +msgstr "" -msgid "dates can only be specified by one of: 'DATE', 'DAT1', 'DAT2', 'DAT3' / 'TIME'" -msgstr "日期只能由以下之一指定:“DATE”、“DAT1”、“DAT2”、“DAT3”/“TIME”" +msgid "endpoint parameter(s) missing, duplicated, or defined with '~':" +msgstr "" -msgid "dates formatted as MONTH-DAY or DAY alone are not supported in this conversion" -msgstr "此转换不支持日期格式化为月-日或仅日" +msgid "," +msgstr "," -msgid "date/time format was not correctly specified" -msgstr "未正确指定日期/时间格式" +msgid "" +"a rxode2 ui model must have more than error definition(s) in the `model({})` " +"block" +msgstr "" -msgid "cannot figure out numeric time" -msgstr "无法计算数字时间" +msgid "install.packages('shiny') to use genShinyApp.template()" +msgstr "" msgid "need 'amt' aesthetic" -msgstr "需要“amt”的美学" +msgstr "amt" msgid "need 'x' aesthetic" -msgstr "需要“x”的美学" +msgstr "x" msgid "stat_cens cannot have lower aesthetic with cens aesthetic" -msgstr "stat_cens有cens的美学不允许存在lower的美学" +msgstr "stat_censcenslower" -msgid "stat_cens requires the following aesthetics: upper, lower or cens (and optionally limit)" -msgstr "stat_cens需要以下的美学:\"上限(upper)\"、\"下限(lower)\"或\"删失(cens)\"(以及可选的\"定量限(limit)\")" +msgid "" +"stat_cens requires the following aesthetics: upper, lower or cens (and " +"optionally limit)" +msgstr "stat_cens\"(upper)\"\"(lower)\"\"(cens)\"\"(limit)\"" + +#, fuzzy +msgid "unknown variable expression:" +msgstr "" + +#, fuzzy +msgid "rxode2 does not know how to handle this modelExtract object" +msgstr "\"(errors)\"/\"(PRED)\"" + +msgid "out" +msgstr "" + +msgid "could not build model for inclusion in package" +msgstr "" msgid "'package' needs to be specified" -msgstr "需要指定“package”(添加包)" +msgstr "package()" + +msgid "some etas defaulted to non-mu referenced, possible parsing error:" +msgstr "" + +msgid "" +"as a work-around try putting the mu-referenced expression on a simple line" +msgstr "" -msgid "'log=\"%s\"' not supported" -msgstr "“log=”%s“'不被支持" +msgid "currently do not support IOV etc" +msgstr "" -msgid "needs units" -msgstr "需要单位" +msgid "syntax/parsing errors (see above) and additionally:" +msgstr "" -msgid "needs \"ggplot2\" 3.3.0" -msgstr "需要“ggplot2” 3.3.0" +msgid "syntax/parsing errors:" +msgstr "" -msgid "this is only used in 'data.table'" -msgstr "这仅在“data.table”中使用" +msgid "syntax/parsing errors, see above" +msgstr "" -msgid "'rxIndLinState' list element '%s' must be a unnamed character vector" -msgstr "'rxIndLinState' 列表元素 '%s' 必须是未命名的字符向量" +#, fuzzy +msgid "cannot find parameter '" +msgstr "PK" -msgid "'%s' is from '%s' and cannot be used in this context" -msgstr "“%s”来自“%s”,不能在此上下文中使用" +msgid "trying to fix '" +msgstr "" -msgid "specified %s initial conditions when there are only %s states" -msgstr "当这些是仅%s状态时,描述 %s 初始条件" +msgid "', but already fixed" +msgstr "" -msgid "only one 'initCondition=' supported" -msgstr "仅支持一个“initCondition=”" +msgid "trying to unfix '" +msgstr "" -msgid "this was not generated from nlmixr, loading into symengine" -msgstr "这不是由nlmixr生成的,加载到Symengine中" +msgid "', but already unfixed" +msgstr "" -msgid "cannot identify parameters for sensitivity analysis\n" -" with nlmixr an 'eta' initial estimate must use '~'" -msgstr "无法识别灵敏度分析的参数\n" -" 使用nlmixr时,“eta”初始估计必须使用“~”" +msgid "piping for '" +msgstr "" + +msgid "' failed, the estimate should only be 1 value" +msgstr "" -msgid "none of the predictions depend on 'ETA'" -msgstr "没有一个预测依赖于“ETA”" +msgid "the '" +msgstr "" -msgid "some of the predictions do not depend on 'ETA'" -msgstr "一些预测不依赖于“ETA”" +msgid "' piping lower, estimate, and/or upper estimate is in the wrong order" +msgstr "" -msgid "parameters:" -msgstr "参数:" +msgid "the new label for '" +msgstr "" -msgid "," -msgstr "," +#, fuzzy +msgid "' must be a character string" +msgstr "df 0" + +msgid "'append' must be NULL, logical, numeric, or character" +msgstr "" + +msgid "Cannot find parameter '" +msgstr "" + +#, fuzzy +msgid "parameter '" +msgstr ":" + +msgid "' set to be moved after itself, no change in order made" +msgstr "" + +msgid "only theta parameters can be moved. '" +msgstr "" + +msgid "' is not a theta parameter" +msgstr "" + +msgid "a NULL value for '" +msgstr "" + +#, fuzzy +msgid "' piping does not make sense" +msgstr "\"duplicate()\"" + +msgid "to assign a new label, use '%s <- label(\"%s\")'" +msgstr "" + +msgid "invalid expr for ini() modification" +msgstr "" + +#, fuzzy +msgid "cannot figure out what to do with the ini({}) function" +msgstr "" + +msgid "cannot find '" +msgstr "" + +msgid "' in lhs model, cannot append" +msgstr "" + +msgid "the variable '" +msgstr "" + +msgid "' must be in the defined the model for piping this: '" +msgstr "" + +msgid "with single endpoint model prediction '" +msgstr "" + +msgid "' is changed to '" +msgstr "" + +msgid "the error '" +msgstr "" + +msgid "' is not in the multiple-endpoint model and cannot be modified" +msgstr "" + +#, fuzzy +msgid "do not know where to put label" +msgstr "" + +#, fuzzy +msgid "cannot figure out what to do with the unnamed vector" +msgstr "" + +#, fuzzy +msgid "cannot figure out what to do with the unnamed list" +msgstr "" -msgid "cannot figure out PK parameters to convert" -msgstr "无法找出要转换的PK参数" +msgid "one of the list items supplied to piping is non-numeric" +msgstr "" + +msgid "vectors and list need to be named numeric expression" +msgstr "" + +msgid "" +"the `sim` endpoints requested in the plot do not exist in the solved object:" +msgstr "" + +msgid "" +"some `sim` requested items do not exist in the solved object and were " +"ignored:" +msgstr "" + +msgid "sim." +msgstr "" + +msgid "the items requested in the plot do not exist in the solved object:" +msgstr "" + +msgid "" +"some requested items do not exist in the solved object and were ignored:" +msgstr "" + +msgid "needs \"ggplot2\" 3.3.0" +msgstr "ggplot2 3.3.0" + +msgid "'rxIndLinState' list element '%s' must be a unnamed character vector" +msgstr "'rxIndLinState' '%s' " + +msgid "'%s' is from '%s' and cannot be used in this context" +msgstr "%s%s" msgid "unsupported lhs in optimize expression" -msgstr "优化表达式中不支持lhs" +msgstr "lhs" msgid "cannot divide by zero" -msgstr "不能除以零" +msgstr "" msgid "error optimizing expression, try 'optExpression=FALSE'" -msgstr "优化表达式时出错,请尝试“optExpression=FALSE”" +msgstr "optExpression=FALSE" msgid "'iCov' in a pipline is no longer supported" -msgstr "管道中的“iCov”不再被支持" +msgstr "iCov" msgid "unknown arguments in 'rxParams'" -msgstr "在“rxParams”中由未知的参数" +msgstr "rxParams" -msgid "unknown arguments in 'rxParams': %s\n" +msgid "" +"unknown arguments in 'rxParams': %s\n" "try piping to 'rxSolve'" -msgstr "在“rxParams”中由未知的参数: %s\n" -"尝试管道连接到“rxSolve”" +msgstr "" +"rxParams %s\n" +"rxSolve" msgid "unsupported expression" -msgstr "不支持的表达式" +msgstr "" msgid "using the first solved parameters for rxShiny" -msgstr "使用 rxShiny 的第一个已求解参数" +msgstr " rxShiny " msgid "this has to be a matrix of all 1s or 0s" -msgstr "这必须是一个全是1或0的矩阵" +msgstr "10" msgid "diagonal elements must be non-zero" -msgstr "对角线元素必须不为零" +msgstr "" msgid "diagonal form:" -msgstr "对角线形式:" +msgstr ":" msgid "calculate symbolic inverse: t(chol.mat) %*% chol.mat ..." -msgstr "计算符号逆: t(chol.mat) %*% chol.mat ..." +msgstr " t(chol.mat) %*% chol.mat ..." + +msgid "." +msgstr "." msgid "initial 'omega' matrix inverse is non-positive definite" -msgstr "初始“omega”矩阵逆是非正定的" +msgstr "omega" msgid "zero matrix" -msgstr "零矩阵" +msgstr "" + +msgid "object is wrong type for `rxUiGet`" +msgstr "" msgid "================================================================================" msgstr "================================================================================" -msgid "rxode2 compiled with dparser '" -msgstr "rxode2编译自dparser '" - -msgid "' but dparser '" -msgstr "'但是dparser'" - -msgid "dparser" -msgstr "dparser" - -msgid "' is loaded\n" -"Recompile rxode2 with the this version of dparser" -msgstr "' 已加载\n" -"使用此版本的 dparser 重新编译 rxode2" - msgid "rxode2 compiled with PreciseSums '" -msgstr "rxode2编译自PrecisionSums '" +msgstr "rxode2PrecisionSums '" msgid "' but PreciseSums '" -msgstr "'但是PreciseSums'" +msgstr "'PreciseSums'" msgid "PreciseSums" msgstr "PreciseSums" -msgid "' is loaded\n" +msgid "" +"' is loaded\n" "Recompile rxode2 with the this version of PreciseSums" -msgstr "' 已加载\n" -"使用此版本的 PrecisionSums 重新编译 rxode2" +msgstr "" +"' \n" +" PrecisionSums rxode2" -msgid "Rtools is not set up correctly!\n" -"\n" -"You need a working Rtools installation for rxode2 to compile models" -msgstr "Rtools设置不正确!\n" -"\n" -"您需要一个有效的 Rtools 安装来编译模型" +msgid "rxode2 compiled with rxode2parse with a different solving structure" +msgstr "" + +msgid "can try: install.packages('rxode2', type='source')" +msgstr "" msgid "rxode2" msgstr "rxode2" msgid "using" -msgstr "使用" +msgstr "" msgid "threads (see ?getRxThreads)" -msgstr "线程(请参阅?getRxThreads)" +msgstr "?getRxThreads" msgid "no cache: create with `rxCreateCache()`" -msgstr "无缓存:使用 'rxCreateCache()' 创建" +msgstr " 'rxCreateCache()' " msgid "========================================" msgstr "========================================" -msgid "rxode2 has not detected OpenMP support and will run in single-threaded mode" -msgstr "rxode2 未检测到 OpenMP 支持,将在单线程模式下运行" +msgid "" +"rxode2 has not detected OpenMP support and will run in single-threaded mode" +msgstr "rxode2 OpenMP " msgid "sysname" -msgstr "系统名称" +msgstr "" msgid "Darwin" msgstr "Darwin" msgid "This is a Mac. Please read https://mac.r-project.org/openmp/" -msgstr "这是一台Mac。请阅读 https://mac.r-project.org/openmp/" +msgstr "Mac https://mac.r-project.org/openmp/" msgid "The system is" -msgstr "该系统是" +msgstr "" msgid "; To get best performance enable OpenMP" -msgstr ";要获得最佳性能,请启用 OpenMP" +msgstr "; OpenMP" msgid "detected new version of rxode2, cleaning cache" -msgstr "检测到新版本的 rxode2,正在清理缓存" +msgstr " rxode2" + +msgid "'modName' has to be a single length character" +msgstr "modName" + +msgid "'extraC' needs to point to a file that exists and is readable" +msgstr "extraC" + +msgid "'collapseModel' needs to be logical" +msgstr "collapseModel" + +msgid "'indLin' needs to be logical" +msgstr "indLin" + +msgid "'debug' needs to be logical" +msgstr "(debug)" + +msgid "'package' needs to a single character for the package name" +msgstr "" + +msgid "with packages 'modName' is required" +msgstr "modName" + +msgid "must specify exactly one of 'model' or 'filename'" +msgstr "model()filename()" + +msgid "model functions can only be called with one argument" +msgstr "" + +msgid "cannot delete Dll in package" +msgstr " Dll" + +msgid "'$parse' is no longer supported" +msgstr "$parse" + +msgid "cannot update package model" +msgstr "" + +msgid "cannot figure out how to handle the model argument" +msgstr "" + +msgid "sensitivities do not make sense for models without ODEs" +msgstr "" + +msgid "Jacobians do not make sense for models without ODEs" +msgstr "" + +msgid "Do not know how to add %s to rxode2 solved object %s" +msgstr " %s rxode2 %s" + +msgid "unknown model" +msgstr "" + +msgid "model" +msgstr "" + +msgid "cannot create rxode2 model" +msgstr " rxode2 " + +#, fuzzy +msgid "cannot seem to remove '" +msgstr " rxode2 " + +msgid "rxode2 already building model, waiting for lock file removal" +msgstr "rxode2 " + +msgid "lock file: \"%s\"" +msgstr "%s" + +msgid "error building model on another thread" +msgstr "" + +msgid "do not need to recompile, minimal change to model detected" +msgstr "" + +msgid "unloaded all rxode2 dlls before loading the current DLL" +msgstr " DLL rxode2 dll" + +msgid "something went wrong in compilation" +msgstr "" + +msgid "'removeJac' is no longer supported" +msgstr "removeJac" + +msgid "'removeSens' is no longer supported" +msgstr "removeSens" + +msgid "need an rxode2-type object to extract model variables" +msgstr "" msgid "'df' must be greater than 0" -msgstr "“df”必须大于 0" +msgstr "df 0" msgid "'shape1' cannot be 0" -msgstr "“shape1”不能为 0" +msgstr "shape1 0" msgid "'shape2' cannot be 0" -msgstr "“shape2”不能为 0" +msgstr "shape2 0" msgid "'shape' cannot be 0" -msgstr "“shape”不能为 0" +msgstr "shape 0" -msgid "'rate'/'scale' cannot be 0" -msgstr "“rate”(输注速率)/“scale”(缩放)不能为 0" - -msgid "specify 'rate' or 'scale' but not both" -msgstr "描述“rate”或“scale”,但不能同时描述两者" +msgid "'rate' cannot be 0" +msgstr "rate 0" msgid "'df1' cannot be 0" -msgstr "“df1”不能为 0" +msgstr "df1 0" msgid "'df2' cannot be 0" -msgstr "“df2”不能为 0" - -msgid "'rate' cannot be 0" -msgstr "“rate”不能为 0" +msgstr "df2 0" msgid "'df' cannot be 0" -msgstr "“df”不能为 0" +msgstr "df 0" msgid "'scale' cannot be 0" -msgstr "“scale”不能为 0" +msgstr "scale 0" msgid "when 'gamma' is not 1, 'tmax' cannot be infinite" -msgstr "当“Gamma”不是1时,“tmax”不能是无穷大" +msgstr "Gamma1tmax" -msgid "duplicate arguments do not make sense" -msgstr "\"duplicate(创建副本)\"的参数没有意义" +#, fuzzy +msgid "'transitAbs' is no longer supported, use 'evid=7' instead" +msgstr "$parse" -msgid "covariates can no longer be specified by 'covs' include them in the event dataset" -msgstr "协变量不能再由“covs”描述,将它们包含在事件数据集中" +msgid "unused argument:" +msgstr "" + +msgid "" +"covariates can no longer be specified by 'covs' include them in the event " +"dataset" +msgstr "covs" + +#, fuzzy +msgid "'maxSS' must be larger than 'minSS'" +msgstr "df 0" msgid "events can be pipeline or solving arguments not both" -msgstr "事件可以是管道或求解参数,而不是两者兼而有之" +msgstr "" msgid "need an rxode2 compiled model as the start of the pipeline" -msgstr "需要一个已编译的rxode2模型作为管道的开始" +msgstr "rxode2" msgid "need an rxode2 events as a part of the pipeline" -msgstr "需要 rxode2 事件作为管道的一部分" +msgstr " rxode2 " msgid "'events' in pipeline AND in solving arguments, please provide just one" -msgstr "管道中的“事件”(events)和求解参数,请只提供一个" +msgstr "(events)" msgid "'params' in pipeline AND in solving arguments, please provide just one" -msgstr "管道中的“参数”(params)和求解参数,请只提供一个" +msgstr "(params)" msgid "'inits' in pipeline AND in solving arguments, please provide just one" -msgstr "管道中的“inits”和求解参数,请只提供一个" +msgstr "inits" + +msgid "duplicate arguments do not make sense" +msgstr "\"duplicate()\"" -msgid "covariates can no longer be specified by 'covs'\n" +msgid "" +"covariates can no longer be specified by 'covs'\n" " include them in the event dataset\n" "\n" "individual covariates: Can be specified by a 'iCov' dataset\n" @@ -442,286 +674,310 @@ msgid "covariates can no longer be specified by 'covs'\n" " 'eventTable' to include covariates(https://tinyurl.com/y52wfc2y)\n" "\n" "Each approach needs the covariates named to match the variable in the model" -msgstr "协变量不能再由“covs”描述\n" -" 将它们包含在事件数据集中\n" +msgstr "" +"covs\n" +" \n" +"\n" +"iCov\n" +" \n" "\n" -"单个协变量:可由“iCov”数据集指定\n" -" 每个协变量都有一个值\n" "\n" -"时变协变量:修改输入事件数据框或\n" -" 包含协变量的“事件表”(https://tinyurl.com/y52wfc2y)\n" +" https://tinyurl.com/y52wfc2y\n" "\n" -"每种方法都需要命名的协变量来匹配模型中的变量" +"" -msgid "'iCov' has information contained in parameters/event data\n" +msgid "" +"'iCov' has information contained in parameters/event data\n" "duplicate columns: '%s'" -msgstr "“iCov”包含参数/事件数据中包含的信息\n" -"创建列的副本:“%s”" +msgstr "" +"iCov/\n" +"%s" + +msgid "', '" +msgstr "', '" msgid "'theta' cannot be a data.frame" -msgstr "“theta”不能是一个\"数据帧(data.frame)\"" +msgstr "theta\"(data.frame)\"" msgid "'theta' can only have 1 row" -msgstr "“theta”只能有 1 行" +msgstr "theta 1 " msgid "name specification for 'theta' is ignored" -msgstr "“theta”的名称描述已被丢弃" +msgstr "theta" msgid "'eta' cannot be a data.frame" -msgstr "“eta”不能是一个\"数据帧(data.frame)\"" +msgstr "eta\"(data.frame)\"" msgid "'eta' can only have 1 row" -msgstr "“eta”只能有 1 行" +msgstr "eta 1 " msgid "name specification for 'eta' is ignored" -msgstr "“eta”的名称描述已被丢弃" +msgstr "eta" msgid "cannot specify 'params' and 'theta'/'eta' at the same time" -msgstr "不能同时指定“params”和“theta”/“eta”" +msgstr "paramstheta/eta" msgid "Cannot detect an event data frame to merge 'iCov'" -msgstr "无法检测到要合并“iCov”的事件数据框" +msgstr "iCov" msgid "to use 'iCov' you must have an id in your event table" -msgstr "要使用“iCov”,您必须在事件表中有一个 id" +msgstr "iCov id" msgid "'iCov' and 'id' mismatch" -msgstr "“iCov”和“id”不匹配" +msgstr "iCovid" msgid "iCov has duplicate IDs, cannot continue" -msgstr "iCov 有重复的 ID,无法继续" +msgstr "iCov ID" msgid "combining iCov and events dropped some event information" -msgstr "结合iCov和事件丢弃了一些事件信息" +msgstr "iCov" msgid "combining iCov and events dropped some iCov information" -msgstr "结合iCov和事件丢弃了一些iCov信息" +msgstr "iCoviCov" msgid "'iCov' must be an input dataset" -msgstr "“iCov”必须是输入数据集" +msgstr "iCov" + +msgid "Unsupported type of model trying to be solved" +msgstr "" + +msgid "'sensCmt' must be lower than the number of compartments 'ncmt'" +msgstr "" + +msgid "'rxControl' must be a rxode2 control options list" +msgstr "" msgid "name argument must be a length-one character vector" -msgstr "\"名称(name)\"参数必须是长度为一的字符向量" +msgstr "\"(name)\"" msgid "a new function requires a C function so it can be used in rxode2" -msgstr "一个新函数需要一个C函数,这样它就能在 rxode2 中使用" +msgstr "C rxode2 " msgid "already defined user function '" -msgstr "已定义的用户函数”" +msgstr "" msgid "', remove it fist ('rxRmFun')" -msgstr "',应首先移除它('rxRmFun')" +msgstr "''rxRmFun'" msgid "no user function '" -msgstr "无用户函数 '" +msgstr " '" msgid "' to remove" -msgstr "'要移除" - -msgid "cannot take a second derivative" -msgstr "不能取二阶导数" - -msgid "bad 'linCmtB' derivative" -msgstr "坏的“linCmtB”衍生" +msgstr "'" msgid "derivatives must be a list of functions with at least 1 element" -msgstr "导数必须是至少包含 1 个元素的函数列表" +msgstr " 1 " msgid "replacing defined derivatives for '%s'" -msgstr "替换 '%s' 的定义导数" +msgstr " '%s' " msgid "only 'THETA[#]' or 'ETA[#]' are supported" -msgstr "仅支持“THETA[#]”或“ETA[#]”" +msgstr "THETA[#]ETA[#]" msgid "() must be used with a state" -msgstr "() 必须与状态一起使用" +msgstr "() " msgid "() can have 0-1 arguments" -msgstr "() 可以有 0-1 个参数" +msgstr "() 0-1 " msgid "() takes 1-2 arguments" -msgstr "() 需要 1-2 个参数" +msgstr "() 1-2 " msgid "() must be used with a variable" -msgstr "() 必须与变量一起使用" +msgstr "() " msgid "(" msgstr "(" msgid ", #) must have an integer for the number of lagged doses" -msgstr ", #) 必须有一个整数用于滞后的给药" +msgstr " #) " msgid "'psigamma' takes 2 arguments" -msgstr "“psigamma”接收 2 个参数" +msgstr "psigamma 2 " msgid "'log1pmx' only takes 1 argument" -msgstr "'log1pmx' 只接收 1 个参数" +msgstr "'log1pmx' 1 " msgid "'choose' takes 2 arguments" -msgstr "“choose”接收 2 个参数" +msgstr "choose 2 " msgid "'lchoose' takes 2 arguments" -msgstr "'lchoose' 接收 2 个参数" +msgstr "'lchoose' 2 " msgid "'pnorm' can only take 1-3 arguments" -msgstr "“pnorm”只接收1-3个参数" +msgstr "pnorm1-3" msgid "'transit' can only take 2-3 arguments" -msgstr "“transit”只接收2-3 个参数" +msgstr "transit2-3 " -msgid "'%s' only acceps 1 argument" -msgstr "'%s' 仅接受 1 个参数" +#, fuzzy +msgid "'%s' only accepts 1 argument" +msgstr "'%s' 1 " msgid "'%s' only acceps 2 arguments" -msgstr "'%s' 仅接受 2 个参数" +msgstr "'%s' 2 " msgid "'%s' takes %s arguments (has %s)" -msgstr "'%s' 接收 %s 参数(具有 %s)" +msgstr "'%s' %s %s" msgid "'probitInv' requires 1-3 arguments" -msgstr "“probitInv”需要 1-3 个参数" +msgstr "probitInv 1-3 " msgid "'probit' requires 1-3 arguments" -msgstr "“probit”需要 1-3 个参数" +msgstr "probit 1-3 " msgid "'logit' requires 1-3 arguments" -msgstr "“logit”需要 1-3 个参数" +msgstr "logit 1-3 " msgid "'expit' requires 1-3 arguments" -msgstr "“expit”需要 1-3 个参数" +msgstr "expit 1-3 " msgid "function '%s' or its derivatives are not supported in rxode2" -msgstr "函数 '%s' 或其导数在 rxode2 中不受支持" +msgstr " '%s' rxode2 " + +#, fuzzy +msgid "" +"R user function '%s' has variable number of arguments with'...' and is not " +"supported in rxode2" +msgstr " '%s' rxode2 " + +msgid "user function '%s' requires %d arguments (supplied %d)" +msgstr "" msgid "[...] expressions not supported" -msgstr "[...]不支持的表达式" +msgstr "[...]" msgid "'polygamma' takes 2 arguments" -msgstr "“polygamma”接收 2 个参数" +msgstr "polygamma 2 " + +msgid "'%s' only acceps 1 argument" +msgstr "'%s' 1 " msgid "'%s' takes %s arguments" -msgstr "'%s' 接收 %s 参数" +msgstr "'%s' %s " msgid "only forward and central differences are supported" -msgstr "仅支持前向和中心差分" +msgstr "" msgid "cannot figure out the '%s' derivative with respect to '%s'" -msgstr "无法计算出相对于“%s”的“%s”导数" +msgstr "%s%s" msgid "an error occurred looking up the derivative for '" -msgstr "查找'" +msgstr "'" msgid "' using numerical differences instead" -msgstr "'导数时遇到一个错误,因此改用数值差分" +msgstr "'" msgid "rxode2/symengine does not know how to take a derivative of '%s'" -msgstr "rxode2/symengine 不知道如何取 '%s' 的导数" +msgstr "rxode2/symengine '%s' " msgid "'Derivative' conversion only takes one function and one argument" -msgstr "“Derivative”转换只需要一个函数和一个参数" +msgstr "Derivative" msgid "() takes 0-1 arguments" -msgstr "() 接收 0-1 个参数" +msgstr "() 0-1 " msgid "'%s' not supported in symengine->rxode2" -msgstr "“%s”在符号引擎>rxode2 中不受支持" +msgstr "%s>rxode2 " msgid "rxode2 doesn't support '%s' translation for 'Omega' translation" -msgstr "rxode2 不支持对的'Omega'转换的'%s'转换" +msgstr "rxode2 'Omega''%s'" msgid "do not know how to handle type" -msgstr "不知道如何处理类型" +msgstr "" msgid "'lnorm' can only be in an error function" -msgstr "“lnorm”只能在误差函数中" +msgstr "lnorm" msgid "'lnorm' cannot be used with other data transformations" -msgstr "“lnorm”不能与其他数据转换一起使用" +msgstr "lnorm" msgid "'logitNorm' can only be in an error function" -msgstr "“logitNorm”只能在误差函数中" +msgstr "logitNorm" msgid "'logitNorm' cannot be used with other data transformations" -msgstr "“logitNorm”不能与其他数据转换一起使用" +msgstr "logitNorm" msgid "'probitNorm' can only be in an error function" -msgstr "“probitNorm”只能在误差函数中" +msgstr "probitNorm" msgid "'probitNorm' cannot be used with other data transformations" -msgstr "“probitNorm”不能与其他数据转换一起使用" +msgstr "probitNorm" msgid "'boxCox' can only be in an error function" -msgstr "“boxCox”只能在误差函数中" +msgstr "boxCox" msgid "'boxCox' cannot be used with other data transformations" -msgstr "“boxCox”不能与其他数据转换一起使用" +msgstr "boxCox" msgid "'yeoJohnson' can only be in an error function" -msgstr "“yeoJohnson”只能在误差函数中" +msgstr "yeoJohnson" msgid "'yeoJohnson' cannot be used with other data transformations" -msgstr "“yeoJohnson”不能与其他数据转换一起使用" +msgstr "yeoJohnson" msgid "'add' can only be in an error function" -msgstr "“add”只能在误差函数中" +msgstr "add" msgid "'for' is not supported" -msgstr "“for”不被支持" +msgstr "for" msgid "The PK function should not return anything" -msgstr "PK 函数不应返回任何内容" +msgstr "PK " msgid "'prop' can only be in an error function" -msgstr "“prop”只能在误差函数中" +msgstr "prop" msgid "'propT' can only be in an error function" -msgstr "“propT”只能在误差函数中" +msgstr "propT" msgid "'pow' can only be in an error function" -msgstr "“pow”只能在误差函数中" +msgstr "pow" msgid "'powT' can only be in an error function" -msgstr "“powT”只能在误差函数中" +msgstr "powT" msgid "use 'return' for errors" -msgstr "对\"误差(errors)\"使用“return”" +msgstr "\"(errors)\"return" -msgid "errors and predictions need to have the same conditions ('if'/'then' statements)" -msgstr "误差和预测需要具有相同的条件(“if”/“then”语句)" +msgid "" +"errors and predictions need to have the same conditions ('if'/'then' " +"statements)" +msgstr "if/then" msgid "do not know how to handle this error/pred combination" -msgstr "不知道如何处理此\"误差(errors)\"/\"预测(PRED)\"组合" +msgstr "\"(errors)\"/\"(PRED)\"" msgid "Don't know how to handle type '" -msgstr "不知道如何处理类型 '" +msgstr " '" msgid "'." msgstr "'." -msgid "package \"%s\" needed for this function to work" -msgstr "此函数正常工作需要的添加包“%s”" - -msgid "'wd' is depreciated" -msgstr "“wd”已折旧(此处指清理的意思)" - -msgid "'rxSetSum' has been moved to rxSolve(...,sum=)" -msgstr "'rxSetSum' 已移至rxSolve(...,sum=)" +#, fuzzy +msgid "cannot figure out what to do with model assignment" +msgstr "" -msgid "'rxSetProd' has been moved to rxSolve(...,sum=)" -msgstr "'rxSetProd' 已移至rxSolve(...,sum=)" +#, fuzzy +msgid "cannot figure out what to do with ini assignment" +msgstr "" -msgid "provide either threads= or percent= but not both" -msgstr "提供threads=或percent=,但不能同时提供两者" +msgid "wrong input for 'x' in .bodySetRxUi" +msgstr "" -msgid "percent= is provided but is length" -msgstr "提供百分比=,但是长度" +#, fuzzy +msgid "cannot figure out how to assign this to the with rxode()<-" +msgstr "" -msgid "percent==" -msgstr "百分比==" +#, fuzzy +msgid "do not know how to assign this" +msgstr "" -msgid "but should be a number between 2 and 100" -msgstr "但应该是 2 到 100 之间的数字" +msgid "" +"the first model does not have variables that are used by the second model" +msgstr "" -msgid "%s%s" -msgstr "%s%s" +msgid "there needs to be at least one population parameter in 'model1'" +msgstr "" +msgid "" \ No newline at end of file diff --git a/po/rxode2.pot b/po/rxode2.pot index bf835be77..36b6d273d 100644 --- a/po/rxode2.pot +++ b/po/rxode2.pot @@ -1,14 +1,14 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the RxODE package. +# This file is distributed under the same license as the rxode2 package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: RxODE 1.1.0\n" +"Project-Id-Version: rxode2 2.0.14.9000\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-26 10:39-0500\n" +"POT-Creation-Date: 2023-10-30 08:03-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,1515 +17,716 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: cvPost.cpp:148 -msgid "'shape' must be non-negative" -msgstr "" - -#: cvPost.cpp:169 -msgid "dimension, 'd' of correlation matrix must be > 1" -msgstr "" - -#: cvPost.cpp:172 -msgid "'eta' must be >= 1" -msgstr "" - -#: cvPost.cpp:217 -msgid "" -"log standard deviation size needs to be the same size as the log standard " -"error of the estimate" -msgstr "" - -#: cvPost.cpp:243 -msgid "'nu' must be greater than 'd'-1" -msgstr "" - -#: cvPost.cpp:316 -msgid "unknown 'diagXformType' transformation" -msgstr "" - -#: cvPost.cpp:368 -#, c-format -msgid "variable 'type': Unrecognized cvPost type='%s'" -msgstr "" - -#: cvPost.cpp:371 -msgid "variable 'type': Can only use type string or integer[1,3]" -msgstr "" - -#: cvPost.cpp:472 -#, c-format -msgid "variable 'diagXformType': Unrecognized transformation '%s'" -msgstr "" - -#: cvPost.cpp:477 -msgid "" -"variable 'diagXformType': Can only use transformation string or integer[1,6]" -msgstr "" - -#: cvPost.cpp:483 -msgid "" -"'n' is determined by the 'omega' argument which contains the simulated " -"standard deviations" -msgstr "" - -#: cvPost.cpp:496 -msgid "" -"when sampling from correlation priors to create covariance matrices, the " -"input must be a matrix of standard deviations" -msgstr "" - -#: cvPost.cpp:500 -msgid "" -"'omega' needs to be a matrix or a numeric vector that can be converted to a " -"matrix" -msgstr "" - -#: cvPost.cpp:520 -msgid "'thetaMat' needs 'params' to be non-NULL" -msgstr "" - -#: cvPost.cpp:535 -msgid "" -"when specifying 'thetaMat', 'omega', or 'sigma' the parameters cannot be a " -"'data.frame'/'matrix'" -msgstr "" - -#: cvPost.cpp:546 -msgid "'thetaMat' must be a symmetric, positive definite matrix" -msgstr "" - -#: cvPost.cpp:593 -msgid "'theta' must be the same size as 'thetaMat'" -msgstr "" - -#: cvPost.cpp:716 -msgid "'omega' must be symmetric, positive definite" -msgstr "" - -#: cvPost.cpp:735 -msgid "'omega' needs to be a matrix or lotri matrix" -msgstr "" - -#: cvPost.cpp:773 cvPost.cpp:814 rxData.cpp:2840 -#, c-format -msgid "" -"provided multi-subject data (n=%d) trying to simulate a different number of " -"subjects (n=%d)" -msgstr "" - -#: cvPost.cpp:935 -msgid "'sigma' must be symmetric, positive definite" -msgstr "" - -#: cvPost.cpp:950 -msgid "'sigma' needs to be a matrix or lotri matrix" -msgstr "" - -#: cvPost.cpp:1087 -msgid "un-handled nesting information" -msgstr "" - -#: cvPost.cpp:1111 -msgid "cannot find 'id' column in dataset" -msgstr "" - -#: cvPost.cpp:1124 -msgid "'omega' must be a list/lotri/matrix" -msgstr "" - -#: dop853.c:401 dop853.c:668 -#, c-format -msgid "exit of dop853 at x = %.16e\n" -msgstr "" - -#: dop853.c:412 -#, c-format -msgid "exit of dop853 at x = %.16e, more than nmax = %li are needed\n" -msgstr "" - -#: dop853.c:421 -#, c-format -msgid "exit of dop853 at x = %.16e, step size too small h = %.16e\n" -msgstr "" - -#: dop853.c:553 -#, c-format -msgid "the problem seems to become stiff at x = %.16e\n" -msgstr "" - -#: dop853.c:724 -#, c-format -msgid "system too big, max. n = %u\n" -msgstr "" - -#: dop853.c:734 -#, c-format -msgid "wrong input, nmax = %li\n" -msgstr "" - -#: dop853.c:744 -#, c-format -msgid "curious input, meth = %i\n" -msgstr "" - -#: dop853.c:758 -#, c-format -msgid "wrong input, iout = %i\n" -msgstr "" - -#: dop853.c:766 -#, c-format -msgid "curious input, nrdens = %u\n" -msgstr "" - -#: dop853.c:787 -msgid "not enough free memory for rcont12345678&indir\n" -msgstr "" - -#: dop853.c:795 -msgid "" -"warning : when nrdens = n there is no need allocating memory for icont\n" -msgstr "" - -#: dop853.c:801 -#, c-format -msgid "insufficient storage for icont, min. licont = %u\n" -msgstr "" - -#: dop853.c:974 -#, c-format -msgid "no dense output available for %uth component" -msgstr "" - -#: et.cpp:142 rxData.cpp:5164 -#, c-format -msgid "partial match of '%s' to '%s'" -msgstr "" - -#: et.cpp:403 -msgid "event table was not updated (no dose/sampling windows)" -msgstr "" - -#: et.cpp:480 -msgid "" -"windows need to be a list of observation windows, each of 2 elements e.g. " -"list(c(0,2), c(2,7))" -msgstr "" - -#: et.cpp:482 -msgid "windows need to be ordered list(c(2,0)) is invalid" -msgstr "" - -#: et.cpp:881 et.cpp:898 -#, c-format -msgid "unknown method: '%s'" -msgstr "" - -#: et.cpp:939 etTran.cpp:451 -msgid "can only specify either 'amt' or 'value'" -msgstr "" - -#: et.cpp:943 etTran.cpp:455 -msgid "can only specify either 'cmt', 'ytype', 'state' or 'var'" -msgstr "" - -#: et.cpp:951 -msgid "can only specify either 'duration' or 'dur'" -msgstr "" - -#: et.cpp:959 -msgid "need a 'time' column" -msgstr "" - -#: et.cpp:969 -msgid "using 'mdv' instead of 'method'" -msgstr "" - -#: et.cpp:979 -msgid "using 'evid' instead of 'mdv'" -msgstr "" - -#: et.cpp:994 -msgid "'ID' type is unknown" -msgstr "" - -#: et.cpp:1081 -msgid "can not figure out how to import the compartment variable" -msgstr "" - -#: et.cpp:1152 et.cpp:1154 -msgid "replacement/multiplication events cannot be combined with infusions" -msgstr "" - -#: et.cpp:1168 -msgid "old RxODE 'evid' values are not supported with string compartments" -msgstr "" - -#: et.cpp:1381 -msgid "" -"'amt'/'time' needs units to convert the rate to the right units to import " -"the data" -msgstr "" - -#: et.cpp:1636 -msgid "'do.sampling' is not supported with dose windows" -msgstr "" - -#: et.cpp:1658 -msgid "" -"dosing window you need to specify window in order, e.g. " -"'et(time=list(c(0,2)),amt=3)'" -msgstr "" - -#: et.cpp:1661 -msgid "dosing time or time windows must only be 1-2 elements" -msgstr "" - -#: et.cpp:1922 -msgid "cannot mix named compartments and integer compartments" -msgstr "" - -#: et.cpp:2026 et.cpp:2188 -msgid "cannot add more 'ID's to this event table" -msgstr "" - -#: et.cpp:2256 -msgid "can only have one of the following: 'amt', 'dose'" -msgstr "" - -#: et.cpp:2263 -msgid "" -"can only have one of the following: 'ii', 'dosing.interval', " -"'dosingInterval' or 'dosing_interval'" -msgstr "" - -#: et.cpp:2283 -msgid "" -"can only have one of the following: 'cmt', 'dosing.to', 'dose.to', 'state'" -msgstr "" - -#: et.cpp:2292 -msgid "" -"can only have one of the following: 'amount.units', 'amt.units', 'dose.units'" -msgstr "" - -#: et.cpp:2299 -msgid "" -"can only have one of the following: 'time.units', 'timeUnits', 'time_units'" -msgstr "" - -#: et.cpp:2307 -msgid "can only have one of the following: 'add.sampling', 'do.sampling'" -msgstr "" - -#: et.cpp:2315 -msgid "can only have one of the following: 'time', 'start.time', 'from'" -msgstr "" - -#: et.cpp:2321 -msgid "can only have one of the following: 'nbrDoses', 'nbr.doses'" -msgstr "" - -#: et.cpp:2336 -msgid "can only have one of the following: 'dur', 'duration'" -msgstr "" - -#: et.cpp:2343 -#, c-format -msgid "unused argument '%s'" -msgstr "" - -#: et.cpp:2354 et.cpp:2359 et.cpp:2374 et.cpp:2379 -msgid "" -"multiple event tables supplied, not sure what to do; try 'c', 'rbind', 'seq' " -"or 'rep'" -msgstr "" - -#: et.cpp:2397 et.cpp:2405 et.cpp:2650 et.cpp:2673 et.cpp:2708 et.cpp:2729 -#: et.cpp:2736 et.cpp:2747 et.cpp:2766 et.cpp:2831 et.cpp:2859 et.cpp:2882 -#: et.cpp:2895 et.cpp:2924 et.cpp:2928 et.cpp:2937 et.cpp:3061 et.cpp:3069 -#, c-format -msgid "'%s' cannot be a vector" -msgstr "" - -#: et.cpp:2561 et.cpp:2565 -msgid "nothing done" -msgstr "" - -#: et.cpp:2611 -#, c-format -msgid "cannot mix named and integer compartments in '%s'" -msgstr "" - -#: et.cpp:2619 -#, c-format -msgid "'%s' compartment cannot be a vector" -msgstr "" - -#: et.cpp:2631 -#, c-format -msgid "'%s' cannot be zero" -msgstr "" - -#: et.cpp:2635 -#, c-format -msgid "'%s' cannot be an vector" -msgstr "" - -#: et.cpp:2638 -#, c-format -msgid "'%s' must be an integer or a character" -msgstr "" - -#: et.cpp:2677 -#, c-format -msgid "turning off compartments can only be done when '%s'=2" -msgstr "" - -#: et.cpp:2680 -#, c-format -msgid "zero '%s' cannot be used with '%s'" -msgstr "" - -#: et.cpp:2683 -#, c-format -msgid "'%s' requires an '%s'" -msgstr "" - -#: et.cpp:2687 -#, c-format -msgid "'%s' is ignored when '%s'=2 or '%s'=3" -msgstr "" - -#: et.cpp:2710 et.cpp:2717 et.cpp:2720 et.cpp:2731 et.cpp:2738 -#, c-format -msgid "'%s' needs a '%s'" -msgstr "" - -#: et.cpp:2725 -#, c-format -msgid "can not specify '%s' and '%s' for a dose, please pick one" -msgstr "" - -#: et.cpp:2749 -msgid "'ii' needs a 'dose'/'amt'" -msgstr "" - -#: et.cpp:2760 -msgid "dosing interval of zero makes no sense with multiple dose events" -msgstr "" - -#: et.cpp:2768 et.cpp:2900 -#, c-format -msgid "non-zero '%s' needs a '%s'" -msgstr "" - -#: et.cpp:2805 et.cpp:2808 et.cpp:2811 -#, c-format -msgid "can only specify '%s' or '%s', not both" -msgstr "" - -#: et.cpp:2817 -#, c-format -msgid "'%s' can only have one item" -msgstr "" - -#: et.cpp:2820 -#, c-format -msgid "'%s' must be logical" -msgstr "" - -#: et.cpp:2827 -#, c-format -msgid "cannot specify '%s' and '%s' for a dose, please pick one" -msgstr "" - -#: et.cpp:2838 -msgid "-1 and -2 rates do not make sense with units" -msgstr "" - -#: et.cpp:2843 -#, c-format -msgid "'%s' is cannot be converted and added to this table" -msgstr "" - -#: et.cpp:2850 -#, c-format -msgid "" -"steady state constant infusion dosing records must have '%s=-1' or positive " -"rate" -msgstr "" - -#: et.cpp:2869 -#, c-format -msgid "'%s' cannot be converted and added to this table" -msgstr "" - -#: et.cpp:2930 -#, c-format -msgid "number of doses must be at least one ('%s': %d)" -msgstr "" - -#: et.cpp:2939 -#, c-format -msgid "'%s' can only be used with positive inter-dose intervals ('%s')" -msgstr "" - -#: et.cpp:2949 -#, c-format -msgid "'%s' does not make sense with multiple dosing times" -msgstr "" - -#: et.cpp:2978 -msgid "dosing windows can only have 1-2 items in them" -msgstr "" - -#: et.cpp:2987 -#, c-format -msgid "" -"'%s' requires non zero additional doses ('%s') or steady state dosing ('%s': " -"%f, '%s': %d; '%s': %d), reset '%s' to zero." -msgstr "" - -#: et.cpp:2993 -#, c-format -msgid "'%s' must be 1 when specifying a steady-state constant infusion" -msgstr "" - -#: et.cpp:2996 -#, c-format -msgid "'%s' must be 0, 1 or 2" -msgstr "" - -#: et.cpp:2999 -#, c-format -msgid "'%s' required with '%s'" -msgstr "" - -#: et.cpp:3003 -#, c-format -msgid "'%s' cannot be used with steady state constant infusion" -msgstr "" - -#: et.cpp:3006 -#, c-format -msgid "steady state ('%s') is not supported with dosing windows" -msgstr "" - -#: et.cpp:3009 -#, c-format -msgid "additional doses must be positive ('%s'=%d)" -msgstr "" - -#: et.cpp:3012 -#, c-format -msgid "additional doses require an inter-dose interval ('%s')" -msgstr "" - -#: et.cpp:3017 -#, c-format -msgid "for steady state infusions, you need %s=0, %s>0, %s=1, %s=0" -msgstr "" - -#: et.cpp:3030 -msgid "dosing time window lists can have 1-2 numeric entries in them" -msgstr "" - -#: et.cpp:3035 -msgid "dosing window list needs to be numeric values only" -msgstr "" - -#: et.cpp:3088 -msgid "cannot figure out what type of 'EventTable' you are trying to create" -msgstr "" - -#: et.cpp:3173 et.cpp:3176 -msgid "cannot have event tables with integer and character 'cmt'" -msgstr "" - -#: et.cpp:3261 -#, c-format -msgid "" -"assumed a dose interval of %.1f between event tables; use 'ii' to adjust" -msgstr "" - -#: et.cpp:3347 -msgid "no events table found for 'seq'/'rep'/'rbind'/'c'" -msgstr "" - -#: et.cpp:3468 -msgid "'wait' cannot be a vector" -msgstr "" - -#: etTran.cpp:141 -#, c-format -msgid "" -"negative compartments on non-ode 'cmt' (%s) does not make sense (id: %s, " -"row: %d)" -msgstr "" - -#: etTran.cpp:276 etTran.cpp:286 -#, c-format -msgid "" -"negative compartments on non-ode 'cmt' (%s) does not make sense (id: %s row: " -"%d)" -msgstr "" - -#: etTran.cpp:307 -msgid "should not reach here" -msgstr "" - -#: etTran.cpp:471 -msgid "cannot keep 'evid'; try 'addDosing'" -msgstr "" - -#: etTran.cpp:616 -msgid "'time' is required in dataset" -msgstr "" - -#: etTran.cpp:708 -msgid "steady state column ('ss') needs to be an integer" -msgstr "" - -#: etTran.cpp:719 -msgid "event id ('evid') needs to be an integer" -msgstr "" - -#: etTran.cpp:728 -msgid "missing DV ('mdv') needs to be an integer" -msgstr "" - -#: etTran.cpp:742 -msgid "missing dependent variable ('mdv') needs to be an integer" -msgstr "" - -#: etTran.cpp:750 -msgid "'rate' needs to be a number" -msgstr "" - -#: etTran.cpp:759 -msgid "'dur' needs to be a number" -msgstr "" - -#: etTran.cpp:774 -msgid "amount ('amt') needs to be a number" -msgstr "" - -#: etTran.cpp:782 -msgid "inter-dose interval ('ii') needs to be a number" -msgstr "" - -#: etTran.cpp:790 -msgid "number of additional doses ('addl') needs to be an integer" -msgstr "" - -#: etTran.cpp:798 -msgid "dependent variable ('dv') needs to be a number" -msgstr "" - -#: etTran.cpp:806 -msgid "censoring variable ('cens') needs to be a number" -msgstr "" - -#: etTran.cpp:814 -msgid "limit variable ('limit') needs to be a number" -msgstr "" - -#: etTran.cpp:863 -#, c-format -msgid "censoring column can only be -1, 0 or 1 (id: %s, row: %d)" -msgstr "" - -#: etTran.cpp:888 -#, c-format -msgid "infinite times are not allowed (id: %s, row: %d)" -msgstr "" - -#: etTran.cpp:946 -#, c-format -msgid "" -"steady state records cannot be on negative compartments (id: %s, row: %d)" -msgstr "" - -#: etTran.cpp:976 -#, c-format -msgid "" -"when using steady state constant infusion modeling duration does not make " -"sense (id: %s, row: %d)" +#: approx.c:181 +msgid "solve data is not loaded" msgstr "" -#: etTran.cpp:995 +#: dop853.c:403 dop853.c:670 #, c-format -msgid "" -"specifying duration with a steady state constant infusion makes no sense " -"(id: %s row: %d)" +msgid "exit of dop853 at x = %.16e\n" msgstr "" -#: etTran.cpp:1001 etTran.cpp:1007 +#: dop853.c:414 #, c-format -msgid "" -"specifying duration with a steady state constant infusion makes no sense " -"(id: %d row: %d)" +msgid "exit of dop853 at x = %.16e, more than nmax = %li are needed\n" msgstr "" -#: etTran.cpp:1018 +#: dop853.c:423 #, c-format -msgid "'rate' and/or 'dur' are not specified correctly (id: %d row: %d)" +msgid "exit of dop853 at x = %.16e, step size too small h = %.16e\n" msgstr "" -#: etTran.cpp:1036 +#: dop853.c:555 #, c-format -msgid "" -"'amt' or 'dur'/'rate' are non-zero therefore MDV cannot = 0 (id: %s row: %d)" -msgstr "" - -#: etTran.cpp:1074 -msgid "'addl' is ignored with observations" +msgid "the problem seems to become stiff at x = %.16e\n" msgstr "" -#: etTran.cpp:1096 etTran.cpp:1180 +#: dop853.c:726 #, c-format -msgid "'limit' (%f) cannot equal 'dv' (%f) id: %s row: %d" +msgid "system too big, max. n = %u\n" msgstr "" -#: etTran.cpp:1129 +#: dop853.c:736 #, c-format -msgid "'cmt' and 'dvid' specify different compartments (id: %s row: %d)" -msgstr "" - -#: etTran.cpp:1150 -msgid "'DVID'/'CMT' translation:\n" +msgid "wrong input, nmax = %li\n" msgstr "" -#: etTran.cpp:1156 +#: dop853.c:746 #, c-format -msgid "" -"'dvid'->'cmt' or 'cmt' on observation record on a undefined compartment (use " -"'cmt()' 'dvid()') id: %s row: %d" +msgid "curious input, meth = %i\n" msgstr "" -#: etTran.cpp:1195 +#: dop853.c:760 #, c-format -msgid "'mdv' cannot be 0 when 'evid'=1 id: %s row: %d" -msgstr "" - -#: etTran.cpp:1212 -msgid "'addl' is ignored with 'EVID=2'" -msgstr "" - -#: etTran.cpp:1215 -msgid "'ss' is ignored with 'EVID=2'" -msgstr "" - -#: etTran.cpp:1257 -msgid "'addl' is ignored with 'EVID=3'" -msgstr "" - -#: etTran.cpp:1260 -msgid "'ss' is ignored with 'EVID=3'" +msgid "wrong input, iout = %i\n" msgstr "" -#: etTran.cpp:1284 +#: dop853.c:768 #, c-format -msgid "'mdv' cannot be 0 when 'evid'=4 id: %s row: %d" +msgid "curious input, nrdens = %u\n" msgstr "" -#: etTran.cpp:1310 -#, c-format -msgid "cannot have an infusion event with a replacement event (id: %s row: %d)" +#: dop853.c:789 +msgid "not enough free memory for rcont12345678&indir\n" msgstr "" -#: etTran.cpp:1317 -#, c-format +#: dop853.c:797 msgid "" -"cannot have an infusion event with a multiplication event (id: %s row: %d)" -msgstr "" - -#: etTran.cpp:1328 -msgid "'rate' or 'dur' is ignored with classic RxODE 'EVID's" -msgstr "" - -#: etTran.cpp:1332 -msgid "'ss' is ignored with classic RxODE 'EVID's" -msgstr "" - -#: etTran.cpp:1353 -#, c-format -msgid "'ss' with 'addl' not supported (id: %s row: %d)" +"warning : when nrdens = n there is no need allocating memory for icont\n" msgstr "" -#: etTran.cpp:1364 +#: dop853.c:803 #, c-format -msgid "'amt' value NA or 0 for dose event (id: %s row: %d)" +msgid "insufficient storage for icont, min. licont = %u\n" msgstr "" -#: etTran.cpp:1402 +#: dop853.c:976 #, c-format -msgid "" -"'amt' value NA for dose event; (id: %s, amt: %f, evid: %d RxODE evid: %d, " -"row: %d)" -msgstr "" - -#: etTran.cpp:1480 -msgid "" -"there are evid=3/4 records in an incorrectly sorted dataset, system is " -"reset, but time is not reset" -msgstr "" - -#: etTran.cpp:1537 -msgid "censoring missing 'DV' values do not make sense" -msgstr "" - -#: etTran.cpp:1590 -msgid "no rows in event table or input data" -msgstr "" - -#: etTran.cpp:1612 -msgid "empty data" -msgstr "" - -#: etTran.cpp:1628 -msgid "while censoring is included in dataset, no observations are censored" -msgstr "" - -#: etTran.cpp:1632 -msgid "'dv' and 'limit' swapped since 'limit' > 'dv'" -msgstr "" - -#: etTran.cpp:1753 -msgid "number of individuals not calculated correctly" -msgstr "" - -#: etTran.cpp:1908 -msgid "corrupted event table" -msgstr "" - -#: etTran.cpp:2022 -msgid "" -"\n" -"with negative times, compartments initialize at first negative observed " -"time\n" -"with positive times, compartments initialize at time zero\n" -"use 'rxSetIni0(FALSE)' to initialize at first observed time\n" -"this warning is displayed once per session" +msgid "no dense output available for %uth component" msgstr "" -#: expandGrid.cpp:73 +#: expandGrid.cpp:83 msgid "unanticipated input for rxExpandGrid_" msgstr "" -#: expm.cpp:211 +#: expm.cpp:215 msgid "requested tolerance is too high" msgstr "" -#: expm.cpp:410 +#: expm.cpp:413 #, c-format msgid "unsupported indLin code: %d" msgstr "" -#: forder.cpp:62 +#: forder.cpp:44 #, c-format msgid "" "ignoring invalid %s==\"%s\"\n" " not an integer >= 1\n" "remove any characters that are not a digit [0-9]\n" -" See ?RxODE::setDTthreads" +" See ?rxode2::setDTthreads" msgstr "" -#: forder.cpp:88 +#: forder.cpp:70 #, c-format msgid "" -"ignoring invalid RXODE_NUM_PROCS_PERCENT==%d.\n" +"ignoring invalid rxode2_NUM_PROCS_PERCENT==%d.\n" "If used it must be an integer between 2 and 100. Default is 50. See ?" "rxSetThreads" msgstr "" -#: forder.cpp:124 +#: forder.cpp:106 msgid "'verbose' must be TRUE or FALSE" msgstr "" -#: forder.cpp:127 +#: forder.cpp:109 msgid "" "This installation of data.table has not been compiled with OpenMP support.\n" msgstr "" -#: forder.cpp:132 +#: forder.cpp:114 #, c-format msgid " omp_get_num_procs() %d\n" msgstr "" -#: forder.cpp:133 +#: forder.cpp:115 #, c-format -msgid " RXODE_NUM_PROCS_PERCENT %s\n" +msgid " rxode2_NUM_PROCS_PERCENT %s\n" msgstr "" -#: forder.cpp:134 +#: forder.cpp:116 #, c-format -msgid " RXODE_NUM_THREADS %s\n" +msgid " rxode2_NUM_THREADS %s\n" msgstr "" -#: forder.cpp:135 +#: forder.cpp:117 #, c-format -msgid " RXODE_THROTTLE %s\n" +msgid " rxode2_THROTTLE %s\n" msgstr "" -#: forder.cpp:136 +#: forder.cpp:118 #, c-format msgid " omp_get_thread_limit() %d\n" msgstr "" -#: forder.cpp:137 +#: forder.cpp:119 #, c-format msgid " omp_get_max_threads() %d\n" msgstr "" -#: forder.cpp:138 +#: forder.cpp:120 #, c-format msgid " OMP_THREAD_LIMIT %s\n" msgstr "" -#: forder.cpp:139 +#: forder.cpp:121 #, c-format msgid " OMP_NUM_THREADS %s\n" msgstr "" -#: forder.cpp:141 +#: forder.cpp:123 #, c-format -msgid " RxODE is using %d threads with throttle==%d. See ?setRxthreads.\n" +msgid " rxode2 is using %d threads with throttle==%d. See ?setRxthreads.\n" msgstr "" -#: forder.cpp:149 +#: forder.cpp:131 msgid "'throttle' must be a single number, non-NA, and >=1" msgstr "" -#: forder.cpp:163 +#: forder.cpp:145 msgid "threads= must be either NULL or a single number >= 0 See ?setRxthreads" msgstr "" -#: forder.cpp:167 +#: forder.cpp:149 msgid "internal error: percent= must be TRUE or FALSE at C level" msgstr "" -#: forder.cpp:170 +#: forder.cpp:152 #, c-format msgid "" "internal error: threads==%d should be between 2 and 100 (percent=TRUE at C " "level)" msgstr "" -#: intdy.c:50 -#, c-format -msgid "[intdy] k = %d illegal\n" -msgstr "" - -#: intdy.c:55 -#, c-format -msgid "intdy -- t = %g illegal. t not in interval tcur - _rxC(hu) to tcur\n" +#: handle_evid.c:44 +msgid "could not find a start to the infusion #1" msgstr "" -#: lincmt.c:39 lincmt.c:46 -msgid "could not find a start to the infusion" +#: handle_evid.c:51 +msgid "could not find a start to the infusion #2" msgstr "" -#: lincmt.c:51 lincmt.c:58 +#: handle_evid.c:57 handle_evid.c:65 msgid "could not find an end to the infusion" msgstr "" -#: lincmt.c:200 -msgid "solve data is not loaded" -msgstr "" - -#: lincmt.c:1879 -msgid "not an integer/real" -msgstr "" - -#: lincmt.c:1897 lincmt.c:2007 lincmt.c:2179 -msgid "The dimensions of the parameters must match" -msgstr "" - -#: lincmt.c:2394 -msgid "'ncmt' needs to be 1-3" -msgstr "" - -#: lincmt.c:2397 -msgid "'inp' needs to be list/data frame" +#: intdy.c:52 +#, c-format +msgid "[intdy] k = %d illegal\n" msgstr "" -#: lincmtB.cpp:181 +#: intdy.c:57 #, c-format -msgid "invalid trans (2 cmt trans %d)\n" +msgid "intdy -- t = %g illegal. t not in interval tcur - _rxC(hu) to tcur\n" msgstr "" -#: lsoda.c:221 +#: lsoda.c:223 #, c-format msgid "[lsoda] illegal itask = %d\n" msgstr "" -#: lsoda.c:226 +#: lsoda.c:228 #, c-format msgid "[lsoda] ixpr = %d is illegal\n" msgstr "" -#: lsoda.c:230 +#: lsoda.c:232 msgid "[lsoda] mxstep < 0\n" msgstr "" -#: lsoda.c:235 +#: lsoda.c:237 msgid "[lsoda] mxhnil < 0\n" msgstr "" -#: lsoda.c:240 +#: lsoda.c:242 #, c-format msgid "[lsoda] mxordn = %d is less than 0\n" msgstr "" -#: lsoda.c:246 +#: lsoda.c:248 #, c-format msgid "[lsoda] mxords = %d is less than 0\n" msgstr "" -#: lsoda.c:253 +#: lsoda.c:255 msgid "[lsoda] hmax < 0.\n" msgstr "" -#: lsoda.c:260 +#: lsoda.c:262 msgid "[lsoda] hmin < 0.\n" msgstr "" -#: lsoda.c:490 +#: lsoda.c:492 #, c-format msgid "unhandled error message: %s\n" msgstr "" -#: lsoda.c:768 +#: lsoda.c:770 #, c-format msgid "lsoda -- warning..internal t = %g and _rxC(h) = %g are\n" msgstr "" -#: lsoda.c:769 +#: lsoda.c:771 msgid " such that in the machine, t + _rxC(h) = t on the next step\n" msgstr "" -#: lsoda.c:770 +#: lsoda.c:772 msgid " solver will continue anyway.\n" msgstr "" -#: lsoda.c:772 +#: lsoda.c:774 #, c-format msgid "lsoda -- above warning has been issued %d times,\n" msgstr "" -#: lsoda.c:773 +#: lsoda.c:775 msgid " it will not be issued again for this problem\n" msgstr "" -#: lsoda.c:805 +#: lsoda.c:807 msgid "[lsoda] a switch to the stiff method has occurred " msgstr "" -#: lsoda.c:807 +#: lsoda.c:809 msgid "[lsoda] a switch to the nonstiff method has occurred" msgstr "" -#: lsoda.c:808 +#: lsoda.c:810 #, c-format msgid "at t = %g, tentative step size _rxC(h) = %g, step _rxC(nst) = %d\n" msgstr "" -#: par_solve.cpp:2729 -msgid "'alag(.)'/'rate(.)'/'dur(.)' cannot depend on the state values" -msgstr "" - -#: par_solve.cpp:2733 -msgid "could not solve the system" -msgstr "" - -#: par_solve.cpp:2735 -msgid "" -"some ID(s) could not solve the ODEs correctly; These values are replaced " -"with 'NA'" -msgstr "" - -#: par_solve.cpp:2807 -#, c-format -msgid "one or more covariates were all 'NA' for subject 'id=%d'" -msgstr "" - -#: par_solve.cpp:3230 -#, c-format -msgid "dose to compartment %d ignored (not in system; 'id=%d')" -msgstr "" - -#: parseLinCmt.c:39 -msgid " with first order absorption\n" -msgstr "" - -#: prja.c:42 +#: prja.c:44 msgid "[prja] _rxC(miter) != 2\n" msgstr "" -#: rxData.cpp:296 +#: rxData.cpp:298 msgid "column(s) in 'drop' were not in solved data" msgstr "" -#: rxData.cpp:444 +#: rxData.cpp:453 #, c-format msgid "refusing to simulate %d items" msgstr "" -#: rxData.cpp:451 +#: rxData.cpp:466 rxData.cpp:470 +msgid "'sigma' is not a matrix" +msgstr "" + +#: rxData.cpp:474 msgid "matrix must be a square matrix" msgstr "" -#: rxData.cpp:459 +#: rxData.cpp:482 msgid "matrix must have named dimensions (try 'lotri')" msgstr "" -#: rxData.cpp:491 +#: rxData.cpp:514 msgid "" "lower bounds needs to be a named vector, a single value or exactly the same " "size" msgstr "" -#: rxData.cpp:511 +#: rxData.cpp:534 msgid "" "upper bounds needs to be a named vector, a single value or exactly the same " "size" msgstr "" -#: rxData.cpp:527 +#: rxData.cpp:550 msgid "t distribution not yet supported" msgstr "" -#: rxData.cpp:807 -msgid "cannot figure out the model variables" -msgstr "" - -#: rxData.cpp:837 rxData.cpp:855 -msgid "class:\t" -msgstr "" - -#: rxData.cpp:843 rxData.cpp:861 -msgid "need an RxODE-type object to extract model variables" -msgstr "" - -#: rxData.cpp:851 -msgid "a NULL object does not have any RxODE model variables" +#: rxData.cpp:884 +msgid "a NULL object does not have any rxode2 model variables" msgstr "" -#: rxData.cpp:896 +#: rxData.cpp:919 msgid "can only lookup one state at a time" msgstr "" -#: rxData.cpp:899 +#: rxData.cpp:922 msgid "only one state variable should be input" msgstr "" -#: rxData.cpp:909 +#: rxData.cpp:932 #, c-format msgid "cannot locate compartment \"%s\"" msgstr "" -#: rxData.cpp:1148 +#: rxData.cpp:1177 msgid "" "only one estimate per named list item; use 'list(x=1)' instead of " "'list(x=1:2)'" msgstr "" -#: rxData.cpp:1155 +#: rxData.cpp:1184 msgid "incompatible initial estimate" msgstr "" -#: rxData.cpp:1210 +#: rxData.cpp:1239 #, c-format msgid "" "trying to scale the same compartment by 'scale=c(%s=%f,...)' and 'S%d=%f' " "choose one" msgstr "" -#: rxData.cpp:1221 +#: rxData.cpp:1250 #, c-format msgid "" "trying to scale the same compartment by 'scale=c(%s=%f,...)' and 's%d=%f' " "choose one" msgstr "" -#: rxData.cpp:1245 -msgid "scaled a compartment that is not defined by the RxODE model" +#: rxData.cpp:1274 +msgid "scaled a compartment that is not defined by the rxode2 model" msgstr "" -#: rxData.cpp:1374 +#: rxData.cpp:1521 msgid "could not allocate memory for solving parameters" msgstr "" -#: rxData.cpp:1418 +#: rxData.cpp:1565 msgid "memory for residual errors could not be allocated" msgstr "" -#: rxData.cpp:1425 +#: rxData.cpp:1572 msgid "cannot allocate memory to simulate the residuals" msgstr "" -#: rxData.cpp:1484 +#: rxData.cpp:1638 rxData.cpp:3030 msgid "'thetaMat' must be a named matrix" msgstr "" -#: rxData.cpp:1492 rxData.cpp:2868 +#: rxData.cpp:1646 rxData.cpp:3255 msgid "'thetaMat' must be symmetric" msgstr "" -#: rxData.cpp:1513 -msgid "'thetaMat' is ignored since nStud <= 1" +#: rxData.cpp:1668 +msgid "" +"'thetaMat' is ignored since nStud <= 1\n" +"use 'simVariability = TRUE' to override." msgstr "" -#: rxData.cpp:1553 +#: rxData.cpp:1715 #, c-format msgid "parameter '%s' was not simulated in 'thetaMat'" msgstr "" -#: rxData.cpp:1562 +#: rxData.cpp:1726 rxData.cpp:1738 #, c-format msgid "'%s' must be a named matrix" msgstr "" -#: rxData.cpp:1572 +#: rxData.cpp:1747 +#, c-format +msgid "error calculating 'chol(%s)'" +msgstr "" + +#: rxData.cpp:1750 #, c-format -msgid "'%s' must be symmetric" +msgid "" +"error trying to correct '%s' to be a symmetric, positive definite matrix" msgstr "" -#: rxData.cpp:1692 -msgid "requires 'params'" +#: rxData.cpp:1754 +#, c-format +msgid "corrected '%s' to be a symmetric, positive definite matrix" msgstr "" -#: rxData.cpp:1697 +#: rxData.cpp:1948 msgid "'params' must be a named vector" msgstr "" -#: rxData.cpp:1718 +#: rxData.cpp:1969 msgid "multi-subject simulation without without 'omega'" msgstr "" -#: rxData.cpp:2069 +#: rxData.cpp:2325 msgid "ran out of memory during 'updateSolveEnvPost'" msgstr "" -#: rxData.cpp:2399 +#: rxData.cpp:2728 msgid "No additional parameters were specified, returning original object" msgstr "" -#: rxData.cpp:2478 +#: rxData.cpp:2807 msgid "can not update object" msgstr "" -#: rxData.cpp:2525 +#: rxData.cpp:2859 msgid "'from' must be of length 1" msgstr "" -#: rxData.cpp:2533 +#: rxData.cpp:2867 msgid "'to' must be of length 1" msgstr "" -#: rxData.cpp:2543 +#: rxData.cpp:2877 msgid "'by' must be of length 1" msgstr "" -#: rxData.cpp:2551 +#: rxData.cpp:2885 msgid "'length.out' must be of length 1" msgstr "" -#: rxData.cpp:2557 -msgid "cannot use both 'by' and 'length.out' for RxODE simulations" +#: rxData.cpp:2891 +msgid "cannot use both 'by' and 'length.out' for rxode2 simulations" +msgstr "" + +#: rxData.cpp:2991 +msgid "rxode2 only supports 500 factors" +msgstr "" + +#: rxData.cpp:3039 +msgid "error calculating 'chol(thetaMat)'" +msgstr "" + +#: rxData.cpp:3042 +msgid "" +"error trying to correct 'thetaMat' to be a symmetric, positive definite " +"matrix" +msgstr "" + +#: rxData.cpp:3045 +msgid "corrected 'thetaMat' to be a symmetric, positive definite matrix" msgstr "" -#: rxData.cpp:2654 -msgid "RxODE only supports 500 factors" +#: rxData.cpp:3181 +msgid "" +"when specifying 'thetaMat' the parameters cannot be a 'data.frame'/'matrix'." msgstr "" -#: rxData.cpp:2797 +#: rxData.cpp:3227 +#, c-format msgid "" -"when specifying 'thetaMat', 'omega', or 'sigma' the parameters cannot be a " -"'data.frame'/'matrix'." +"provided multi-subject data (n=%d) trying to simulate a different number of " +"subjects (n=%d)" msgstr "" -#: rxData.cpp:2920 rxData.cpp:2943 rxData.cpp:2952 +#: rxData.cpp:3314 rxData.cpp:3332 rxData.cpp:3341 msgid "" "if parameters are not named, they must match the order and size of the " "parameters in the model" msgstr "" -#: rxData.cpp:3030 +#: rxData.cpp:3420 msgid "can not allocate enough memory to load 'evid'" msgstr "" -#: rxData.cpp:3074 +#: rxData.cpp:3463 msgid "nothing to solve" msgstr "" -#: rxData.cpp:3128 +#: rxData.cpp:3516 msgid "can not allocate memory for the covariates" msgstr "" -#: rxData.cpp:3215 +#: rxData.cpp:3604 msgid "data must be ordered by 'ID' and 'TIME' variables" msgstr "" -#: rxData.cpp:3285 +#: rxData.cpp:3674 msgid "cannot allocate enough memory to sort input parameters" msgstr "" -#: rxData.cpp:3416 +#: rxData.cpp:3804 msgid "'resample' must be NULL or a character vector" msgstr "" -#: rxData.cpp:3525 +#: rxData.cpp:3913 msgid "nPopPar != 1 but parameters are specified as a NumericVector" msgstr "" -#: rxData.cpp:3636 +#: rxData.cpp:3957 rxData.cpp:4924 rxData.cpp:4933 rxData.cpp:4941 +#: rxData.cpp:4949 rxData.cpp:4957 rxData.cpp:4966 rxData.cpp:4974 +#: rxData.cpp:4981 rxData.cpp:4988 rxData.cpp:4995 rxData.cpp:5002 +#: rxData.cpp:5009 rxData.cpp:5018 rxData.cpp:5028 rxData.cpp:5037 +#: rxData.cpp:5043 rxData.cpp:5050 rxData.cpp:5057 +msgid "ran out of memory" +msgstr "" + +#: rxData.cpp:4027 msgid "Something is wrong" msgstr "" -#: rxData.cpp:3699 +#: rxData.cpp:4045 msgid "aborted solve" msgstr "" -#: rxData.cpp:3723 +#: rxData.cpp:4069 #, c-format msgid "" "exited from at least one while after %d iterations, (increase with " "`rxSolve(..., maxwhile=#)`)" msgstr "" -#: rxData.cpp:4066 +#: rxData.cpp:4411 msgid "zero 'thetaMat' specified, no uncertainty in fixed effects" msgstr "" -#: rxData.cpp:4069 +#: rxData.cpp:4414 msgid "zero 'omega', no variability from random-effects" msgstr "" -#: rxData.cpp:4072 +#: rxData.cpp:4417 msgid "zero 'sigma', no unexplained variability" msgstr "" -#: rxData.cpp:4090 +#: rxData.cpp:4435 msgid "" "dropped key column, returning data.frame instead of special solved data.frame" msgstr "" -#: rxData.cpp:4285 +#: rxData.cpp:4629 msgid "control list not setup correctly" msgstr "" -#: rxData.cpp:4348 -msgid "cannot solve without event information" +#: rxData.cpp:4691 +msgid "" +"cannot solve without event information\n" +"this can occur when the data frame you are providing does not have the " +"column 'time'" msgstr "" -#: rxData.cpp:4358 +#: rxData.cpp:4701 msgid "cannot update this object" msgstr "" -#: rxData.cpp:4414 -msgid "cannot load RxODE dlls for this model" -msgstr "" - -#: rxData.cpp:4467 -msgid "" -"thread safe method, but results may depend on system/load, using 1 core (can " -"change with `cores=`)" +#: rxData.cpp:4759 +msgid "cannot load rxode2 dlls for this model" msgstr "" -#: rxData.cpp:4478 rxData.cpp:4495 +#: rxData.cpp:4828 rxData.cpp:4847 msgid "not thread safe method, using 1 core" msgstr "" -#: rxData.cpp:4487 -msgid "thread safe method, but results may depend on system/load" +#: rxData.cpp:4856 +msgid "since throwing warning with NA time, change to single threaded" msgstr "" -#: rxData.cpp:4551 +#: rxData.cpp:5123 msgid "'infSSstep' needs to be positive" msgstr "" -#: rxData.cpp:4599 -msgid "assumed transit compartment model since 'podo' is in the model" -msgstr "" - -#: rxData.cpp:4635 +#: rxData.cpp:5194 msgid "unknown covariate interpolation specified" msgstr "" -#: rxData.cpp:4726 +#: rxData.cpp:5292 #, c-format msgid "" -"number of parameters (%d) solved by RxODE for multi-subject data needs to be " -"a multiple of the number of subjects (%d)" +"number of parameters (%d) solved by rxode2 for multi-subject data needs to " +"be a multiple of the number of subjects (%d)" msgstr "" -#: rxData.cpp:4844 +#: rxData.cpp:5415 msgid "could not allocate enough memory for solving" msgstr "" -#: rxData.cpp:5237 +#: rxData.cpp:5740 +#, c-format +msgid "partial match of '%s' to '%s'" +msgstr "" + +#: rxData.cpp:5813 msgid "cannot update nonexistent parameters" msgstr "" -#: rxData.cpp:5492 -msgid "Can not figure out the RxODE object" +#: rxData.cpp:6068 +msgid "Can not figure out the rxode2 object" msgstr "" -#: rxData.cpp:5597 rxData.cpp:5640 +#: rxData.cpp:6182 rxData.cpp:6225 msgid "can not figure out the DLL for this object" msgstr "" -#: rxData.cpp:5828 +#: rxData.cpp:6426 msgid "package-based models cannot be unloaded" msgstr "" -#: rxData.cpp:5875 +#: rxData.cpp:6473 msgid "package-based models cannot be deleted" msgstr "" -#: rxInv.cpp:34 +#: rxInv.cpp:36 msgid "matrix seems singular; Using pseudo-inverse\n" msgstr "" -#: rxInv.cpp:55 rxInv.cpp:59 +#: rxInv.cpp:57 rxInv.cpp:61 msgid "can not invert in 'rxToCholOmega'" msgstr "" -#: rxInv.cpp:126 +#: rxInv.cpp:128 msgid "theta number must be positive for 'd(omegaInv)'" msgstr "" -#: rxInv.cpp:130 +#: rxInv.cpp:132 msgid "theta number must be positive for 'd(D)'" msgstr "" -#: rxInv.cpp:163 +#: rxInv.cpp:165 msgid "error in 'rxSymInvCholEnvCalculate' environment" msgstr "" -#: rxInv.cpp:176 +#: rxInv.cpp:178 msgid "theta for omega calculations not setup yet" msgstr "" -#: rxInv.cpp:274 +#: rxInv.cpp:276 #, c-format msgid "theta has to have %d elements" msgstr "" -#: rxInv.cpp:277 +#: rxInv.cpp:279 msgid "Can only assign 'theta' in this environment" msgstr "" -#: sbuf.c:165 -#, c-format -msgid "encoding error in 'addLine' format: '%s' n: %d; errno: %d" -msgstr "" - -#: threefry.cpp:46 threefry.cpp:118 threefry.cpp:701 -msgid "n should be a positive integer" -msgstr "" - -#: threefry.cpp:47 threefry.cpp:119 threefry.cpp:626 threefry.cpp:702 -msgid "'ncores' has to be greater than one" -msgstr "" - -#: threefry.cpp:480 +#: rxode2_df.cpp:143 #, c-format -msgid "dimension wrong in 'gradpsi' (d=%d)" -msgstr "" - -#: threefry.cpp:582 -msgid "covariance matrix is ill-conditioned and method failed (truncated mvn)" -msgstr "" - -#: threefry.cpp:628 -msgid "'lower' and 'upper' must have the same number of elements." -msgstr "" - -#: threefry.cpp:629 msgid "" -"'sigma' must be a square matrix with the same dimension as 'upper' and " -"'lower'" -msgstr "" - -#: threefry.cpp:631 -msgid "'lower' is bigger than 'upper' for at least one item" +"The simulated residual errors do not match the model specification (%d=%d)" msgstr "" -#: threefry.cpp:641 -msgid "truncated multivariate normal may fail as covariance matrix is singular" +#: rxode2_df.cpp:217 +msgid "'alag(.)'/'rate(.)'/'dur(.)' cannot depend on the state values" msgstr "" -#: threefry.cpp:678 -msgid "acceptance probability smaller than 0.001" +#: rxode2_df.cpp:227 +msgid "could not solve the system" msgstr "" -#: threefry.cpp:681 -msgid "could not sample from truncated normal" +#: rxode2_df.cpp:229 +msgid "" +"some ID(s) could not solve the ODEs correctly; These values are replaced " +"with 'NA'" msgstr "" -#: threefry.cpp:683 +#: rxode2_df.cpp:782 #, c-format -msgid "sample of size %d which is smaller than requested 'n' returned" -msgstr "" - -#: threefry.cpp:1447 -msgid "when 'sigma' is a list, it has to have at least 1 element" -msgstr "" - -#: threefry.cpp:1450 -msgid "'sigma' must be a list of square symmetric matrices" +msgid "dose to compartment %d ignored (not in system; 'id=%d')" msgstr "" -#: threefry.cpp:1461 +#: sbuf.c:182 #, c-format -msgid "'sigma' list element %d does not match dimension of first matrix" -msgstr "" - -#: threefry.cpp:1499 -msgid "'mu' length must match 'sigma' dimensions" -msgstr "" - -#: threefry.cpp:1649 -msgid "'prob' function should return a vector the same length as the input" -msgstr "" - -#: utilc.c:60 utilc.c:88 -msgid "'n' must be greater than 0" -msgstr "" - -#: utilc.c:178 -msgid "'phi' requires numeric values" +msgid "encoding error in 'addLine' format: '%s' n: %d; errno: %d" msgstr "" -#: utilc.c:201 utilc.c:256 utilc.c:311 utilc.c:366 utilc.c:423 utilc.c:479 -#: utilc.c:535 utilc.c:593 utilc.c:655 +#: utilc.c:70 utilc.c:125 utilc.c:180 utilc.c:235 utilc.c:292 utilc.c:348 +#: utilc.c:404 utilc.c:462 utilc.c:524 msgid "'a' needs to be a number" msgstr "" -#: utilc.c:209 utilc.c:264 utilc.c:319 utilc.c:374 utilc.c:431 utilc.c:487 -#: utilc.c:543 utilc.c:601 utilc.c:663 +#: utilc.c:78 utilc.c:133 utilc.c:188 utilc.c:243 utilc.c:300 utilc.c:356 +#: utilc.c:412 utilc.c:470 utilc.c:532 msgid "'z' needs to be a number" msgstr "" -#: utilc.c:233 utilc.c:288 utilc.c:343 utilc.c:399 utilc.c:456 utilc.c:512 -#: utilc.c:568 utilc.c:629 utilc.c:691 +#: utilc.c:102 utilc.c:157 utilc.c:212 utilc.c:268 utilc.c:325 utilc.c:381 +#: utilc.c:437 utilc.c:498 utilc.c:560 msgid "inconsistent sizes" msgstr "" -#: utilc.c:719 utilc.c:729 utilc.c:772 utilc.c:782 utilc.c:825 utilc.c:835 -#: utilc.c:879 utilc.c:889 +#: utilc.c:588 utilc.c:598 utilc.c:641 utilc.c:651 utilc.c:694 utilc.c:704 +#: utilc.c:748 utilc.c:758 msgid "'low' must be a numeric of length 1" msgstr "" -#: utilc.c:722 utilc.c:736 utilc.c:775 utilc.c:789 utilc.c:828 utilc.c:842 -#: utilc.c:882 utilc.c:896 +#: utilc.c:591 utilc.c:605 utilc.c:644 utilc.c:658 utilc.c:697 utilc.c:711 +#: utilc.c:751 utilc.c:765 msgid "'high' must be a numeric of length 1" msgstr "" -#: utilc.c:739 utilc.c:792 utilc.c:845 utilc.c:899 +#: utilc.c:608 utilc.c:661 utilc.c:714 utilc.c:768 msgid "'high' must be greater than 'low'" msgstr "" diff --git a/po/zh_CN.po b/po/zh_CN.po index 34dbb3c04..6f80c0612 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Rxode2 1.1.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-26 10:39-0500\n" +"POT-Creation-Date: 2023-10-30 08:03-0500\n" "PO-Revision-Date: 2023-07-03 00:00\n" "Last-Translator: FuYongchao <3212418315@qq.com>\n" "Language-Team: FuYongchao <3212418315@qq.com>\n" @@ -17,1440 +17,1420 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: cvPost.cpp:148 -msgid "'shape' must be non-negative" -msgstr "“shape(形状因子)”参数的值必须是非负数的" +#: approx.c:181 +msgid "solve data is not loaded" +msgstr "" -#: cvPost.cpp:169 -msgid "dimension, 'd' of correlation matrix must be > 1" -msgstr "维度数,相关矩阵的维度数“d”必须> 1" +#: dop853.c:403 dop853.c:670 +#, c-format +msgid "exit of dop853 at x = %.16e\n" +msgstr " x = %.16e,dop853\n" -#: cvPost.cpp:172 -msgid "'eta' must be >= 1" -msgstr "“eta”必须>= 1" +#: dop853.c:414 +#, c-format +msgid "exit of dop853 at x = %.16e, more than nmax = %li are needed\n" +msgstr " x = %.16edop853 nmax = %li\n" -#: cvPost.cpp:217 -msgid "log standard deviation size needs to be the same size as the log standard error of the estimate" -msgstr "对数标准差的数量需要与估计值的对数标准误的数量相同" +#: dop853.c:423 +#, c-format +msgid "exit of dop853 at x = %.16e, step size too small h = %.16e\n" +msgstr " x = %.16edop853 h = %.16e\n" -#: cvPost.cpp:243 -msgid "'nu' must be greater than 'd'-1" -msgstr "Wishart分布的自由度“nu”必须大于“d(维数)”-1" +#: dop853.c:555 +#, c-format +msgid "the problem seems to become stiff at x = %.16e\n" +msgstr " x = %.16e \n" -#: cvPost.cpp:316 -msgid "unknown 'diagXformType' transformation" -msgstr "未知的“diagXformType(对角线矩阵X的实现类型)”转换" +#: dop853.c:726 +#, c-format +msgid "system too big, max. n = %u\n" +msgstr " n = %u\n" -#: cvPost.cpp:368 +#: dop853.c:736 #, c-format -msgid "variable 'type': Unrecognized cvPost type='%s'" -msgstr "变量 'type': 无法识别的cvPost类型='%s'" +msgid "wrong input, nmax = %li\n" +msgstr "nmax = %li\n" -#: cvPost.cpp:371 -msgid "variable 'type': Can only use type string or integer[1,3]" -msgstr "变量 'type':只能使用字符串或整数[1,3]" +#: dop853.c:746 +#, c-format +msgid "curious input, meth = %i\n" +msgstr "meth = %i\n" -#: cvPost.cpp:472 +#: dop853.c:760 #, c-format -msgid "variable 'diagXformType': Unrecognized transformation '%s'" -msgstr "变量 'diagXformType(对角线矩阵X的实现类型)':无法识别的实现类型 '%s'" +msgid "wrong input, iout = %i\n" +msgstr "iout = %i\n" -#: cvPost.cpp:477 -msgid "variable 'diagXformType': Can only use transformation string or integer[1,6]" -msgstr "变量 'diagXformType(对角线矩阵X的实现类型)':只能使用字符串或整数[1,6]表示实现类型" +#: dop853.c:768 +#, c-format +msgid "curious input, nrdens = %u\n" +msgstr "nrdens = %u\n" -#: cvPost.cpp:483 -msgid "'n' is determined by the 'omega' argument which contains the simulated standard deviations" -msgstr "‘n’由包含模拟标准差的‘omega’参数确定" +#: dop853.c:789 +msgid "not enough free memory for rcont12345678&indir\n" +msgstr " rcont12345678indir\n" -#: cvPost.cpp:496 -msgid "when sampling from correlation priors to create covariance matrices, the input must be a matrix of standard deviations" -msgstr "从相关性先验中抽样以创建协方差矩阵时,输入必须是一个标准差矩阵" +#: dop853.c:797 +msgid "" +"warning : when nrdens = n there is no need allocating memory for icont\n" +msgstr "nrdens = n icont \n" -#: cvPost.cpp:500 -msgid "'omega' needs to be a matrix or a numeric vector that can be converted to a matrix" -msgstr "‘n’由包含模拟标准差的‘omega’参数确定" +#: dop853.c:803 +#, c-format +msgid "insufficient storage for icont, min. licont = %u\n" +msgstr "icont licont = %u\n" -#: cvPost.cpp:520 -msgid "'thetaMat' needs 'params' to be non-NULL" -msgstr "“thetaMat”需要“参数”为\"非空(non-NULL)\"" +#: dop853.c:976 +#, c-format +msgid "no dense output available for %uth component" +msgstr " %u " -#: cvPost.cpp:535 -msgid "when specifying 'thetaMat', 'omega', or 'sigma' the parameters cannot be a 'data.frame'/'matrix'" -msgstr "指定“thetaMat”、“omega”或“sigma”时,参数不能是一个“data.frame”/“matrix”" +#: expandGrid.cpp:83 +msgid "unanticipated input for rxExpandGrid_" +msgstr "rxExpandGrid_" -#: cvPost.cpp:546 -msgid "'thetaMat' must be a symmetric, positive definite matrix" -msgstr "“thetaMat”必须是对称的正定矩阵" +#: expm.cpp:215 +msgid "requested tolerance is too high" +msgstr "(tolerance)" -#: cvPost.cpp:593 -msgid "'theta' must be the same size as 'thetaMat'" -msgstr "“theta”必须与“thetaMat”大小相同" +#: expm.cpp:413 +#, c-format +msgid "unsupported indLin code: %d" +msgstr "indLin %d" -#: cvPost.cpp:716 -msgid "'omega' must be symmetric, positive definite" -msgstr "“omega”必须是对称的、正定的" +#: forder.cpp:44 +#, fuzzy, c-format +msgid "" +"ignoring invalid %s==\"%s\"\n" +" not an integer >= 1\n" +"remove any characters that are not a digit [0-9]\n" +" See ?rxode2::setDTthreads" +msgstr "" +" %s==%s\n" +" >= 1\n" +"[0-9]\n" +"?Rxode2::setDTthreads" -#: cvPost.cpp:735 -msgid "'omega' needs to be a matrix or lotri matrix" -msgstr "“omega”需要是\"矩阵(matrix)\"或\"lotri matrix\"类型" +#: forder.cpp:70 +#, fuzzy, c-format +msgid "" +"ignoring invalid rxode2_NUM_PROCS_PERCENT==%d.\n" +"If used it must be an integer between 2 and 100. Default is 50. See ?" +"rxSetThreads" +msgstr "" +"RXODE2_NUM_PROCS_PERCENT==%d\n" +" 2 100 50?rxSetThreads" -#: cvPost.cpp:773 cvPost.cpp:814 rxData.cpp:2840 -#, c-format -msgid "provided multi-subject data (n=%d) trying to simulate a different number of subjects (n=%d)" -msgstr "提供多个体数据(n=%d)尝试模拟不同数量的受试者 (n=%d)" +#: forder.cpp:106 +msgid "'verbose' must be TRUE or FALSE" +msgstr "verbose(TRUE)(FALSE)" -#: cvPost.cpp:935 -msgid "'sigma' must be symmetric, positive definite" -msgstr "“sigma”必须是对称的、正定的" +#: forder.cpp:109 +msgid "" +"This installation of data.table has not been compiled with OpenMP support.\n" +msgstr "data.tableOpenMP\n" -#: cvPost.cpp:950 -msgid "'sigma' needs to be a matrix or lotri matrix" -msgstr "“sigma”需要是\"矩阵(matrix)\"或\"lotri matrix\"类型" +#: forder.cpp:114 +#, c-format +msgid " omp_get_num_procs() %d\n" +msgstr " omp_get_num_procs() %d\n" -#: cvPost.cpp:1087 -msgid "un-handled nesting information" -msgstr "未处理的嵌套信息" +#: forder.cpp:115 +#, fuzzy, c-format +msgid " rxode2_NUM_PROCS_PERCENT %s\n" +msgstr " RXODE2_NUM_PROCS_PERCENT %s\n" -#: cvPost.cpp:1111 -msgid "cannot find 'id' column in dataset" -msgstr "在数据集中找不到“id”列" +#: forder.cpp:116 +#, fuzzy, c-format +msgid " rxode2_NUM_THREADS %s\n" +msgstr " RXODE2_NUM_THREADS %s\n" -#: cvPost.cpp:1124 -msgid "'omega' must be a list/lotri/matrix" -msgstr "“omega”必须是\"列表(list)\"/lotri/\"矩阵(matrix)\"类型" +#: forder.cpp:117 +#, fuzzy, c-format +msgid " rxode2_THROTTLE %s\n" +msgstr " RXODE2_THROTTLE %s\n" -#: dop853.c:401 dop853.c:668 +#: forder.cpp:118 #, c-format -msgid "exit of dop853 at x = %.16e\n" -msgstr "在 x = %.16e处,退出dop853\n" +msgid " omp_get_thread_limit() %d\n" +msgstr " omp_get_thread_limit() %d\n" -#: dop853.c:412 +#: forder.cpp:119 #, c-format -msgid "exit of dop853 at x = %.16e, more than nmax = %li are needed\n" -msgstr "在 x = %.16e处退出dop853,需要超过 nmax = %li\n" +msgid " omp_get_max_threads() %d\n" +msgstr " omp_get_max_threads() %d\n" -#: dop853.c:421 +#: forder.cpp:120 #, c-format -msgid "exit of dop853 at x = %.16e, step size too small h = %.16e\n" -msgstr "在 x = %.16e处退出dop853,步长太小 h = %.16e\n" +msgid " OMP_THREAD_LIMIT %s\n" +msgstr " OMP_THREAD_LIMIT %s\n" -#: dop853.c:553 +#: forder.cpp:121 #, c-format -msgid "the problem seems to become stiff at x = %.16e\n" -msgstr "问题似乎在 x = %.16e 时变得刚性\n" +msgid " OMP_NUM_THREADS %s\n" +msgstr " OMP_NUM_THREADS %s\n" -#: dop853.c:724 -#, c-format -msgid "system too big, max. n = %u\n" -msgstr "系统太大,最大值 n = %u\n" +#: forder.cpp:123 +#, fuzzy, c-format +msgid " rxode2 is using %d threads with throttle==%d. See ?setRxthreads.\n" +msgstr " Rxode2 %dthrottle==%d?setRxthreads\n" -#: dop853.c:734 -#, c-format -msgid "wrong input, nmax = %li\n" -msgstr "错误的输入,nmax = %li\n" +#: forder.cpp:131 +msgid "'throttle' must be a single number, non-NA, and >=1" +msgstr "throttleNA >=1" -#: dop853.c:744 -#, c-format -msgid "curious input, meth = %i\n" -msgstr "奇异的输入,meth = %i\n" +#: forder.cpp:145 +msgid "threads= must be either NULL or a single number >= 0 See ?setRxthreads" +msgstr "threads=NULL>=0?setRxthreads" -#: dop853.c:758 -#, c-format -msgid "wrong input, iout = %i\n" -msgstr "错误的输入,iout = %i\n" +#: forder.cpp:149 +msgid "internal error: percent= must be TRUE or FALSE at C level" +msgstr "percent()= CTRUEFALSE" -#: dop853.c:766 +#: forder.cpp:152 #, c-format -msgid "curious input, nrdens = %u\n" -msgstr "奇异的输入,nrdens = %u\n" +msgid "" +"internal error: threads==%d should be between 2 and 100 (percent=TRUE at C " +"level)" +msgstr "threads==%d 2 100 C percent()=TRUE" -#: dop853.c:787 -msgid "not enough free memory for rcont12345678&indir\n" -msgstr "没有足够的可用内存用于 rcont12345678和indir\n" +#: handle_evid.c:44 +#, fuzzy +msgid "could not find a start to the infusion #1" +msgstr "" + +#: handle_evid.c:51 +#, fuzzy +msgid "could not find a start to the infusion #2" +msgstr "" -#: dop853.c:795 -msgid "warning : when nrdens = n there is no need allocating memory for icont\n" -msgstr "警告:当nrdens = n时,不需要为 icont 分配内存\n" +#: handle_evid.c:57 handle_evid.c:65 +msgid "could not find an end to the infusion" +msgstr "" -#: dop853.c:801 +#: intdy.c:52 #, c-format -msgid "insufficient storage for icont, min. licont = %u\n" -msgstr "icont的存储空间不足,最小 licont = %u\n" +msgid "[intdy] k = %d illegal\n" +msgstr "[intdy] k = %d \n" -#: dop853.c:974 +#: intdy.c:57 #, c-format -msgid "no dense output available for %uth component" -msgstr "没有可用于第 %u 分量的密集输出" +msgid "intdy -- t = %g illegal. t not in interval tcur - _rxC(hu) to tcur\n" +msgstr "intdy -- t = %g ttcur - _rxChutcur\n" -#: et.cpp:142 rxData.cpp:5164 +#: lsoda.c:223 #, c-format -msgid "partial match of '%s' to '%s'" -msgstr "“%s”与“%s”部分匹配" +msgid "[lsoda] illegal itask = %d\n" +msgstr "[lsoda]itask = %d\n" -#: et.cpp:403 -msgid "event table was not updated (no dose/sampling windows)" -msgstr "事件表未更新(无给药/采样时间窗)" +#: lsoda.c:228 +#, c-format +msgid "[lsoda] ixpr = %d is illegal\n" +msgstr "[lsoda] ixpr = %d\n" -#: et.cpp:480 -msgid "windows need to be a list of observation windows, each of 2 elements e.g. list(c(0,2), c(2,7))" -msgstr "时间窗必须是观测的时间窗的\"列表(list)\",每个时间窗有两个元素,例如列表(C(0,2)、C(2,7))" +#: lsoda.c:232 +msgid "[lsoda] mxstep < 0\n" +msgstr "[lsoda]mxstep< 0\n" -#: et.cpp:482 -msgid "windows need to be ordered list(c(2,0)) is invalid" -msgstr "Windows需要排序,list(c(2,0))无效" +#: lsoda.c:237 +msgid "[lsoda] mxhnil < 0\n" +msgstr "[lsoda] mxhnil < 0\n" -#: et.cpp:881 et.cpp:898 +#: lsoda.c:242 #, c-format -msgid "unknown method: '%s'" -msgstr "未知的方法:“%s”" - -#: et.cpp:939 etTran.cpp:451 -msgid "can only specify either 'amt' or 'value'" -msgstr "只能指定“amt”或“value”" +msgid "[lsoda] mxordn = %d is less than 0\n" +msgstr "[lsoda] mxordn = %d0\n" -#: et.cpp:943 etTran.cpp:455 -msgid "can only specify either 'cmt', 'ytype', 'state' or 'var'" -msgstr "只能指定“cmt”、“ytype”、“state”或“var”" +#: lsoda.c:248 +#, c-format +msgid "[lsoda] mxords = %d is less than 0\n" +msgstr "[lsoda] mxords = %d0\n" -#: et.cpp:951 -msgid "can only specify either 'duration' or 'dur'" -msgstr "只能指定“duration”或“dur”" +#: lsoda.c:255 +msgid "[lsoda] hmax < 0.\n" +msgstr "[lsoda] hmax < 0.\n" -#: et.cpp:959 -msgid "need a 'time' column" -msgstr "需要一个“time(时间)”列" +#: lsoda.c:262 +msgid "[lsoda] hmin < 0.\n" +msgstr "[lsoda] hmin < 0.\n" -#: et.cpp:969 -msgid "using 'mdv' instead of 'method'" -msgstr "应使用“mdv”而不是“method”" +#: lsoda.c:492 +#, c-format +msgid "unhandled error message: %s\n" +msgstr " %s\n" -#: et.cpp:979 -msgid "using 'evid' instead of 'mdv'" -msgstr "应使用“evid”而不是“mdv”" +#: lsoda.c:770 +#, c-format +msgid "lsoda -- warning..internal t = %g and _rxC(h) = %g are\n" +msgstr "lsoda -- .. t = %g _rxCh = %g \n" -#: et.cpp:994 -msgid "'ID' type is unknown" -msgstr "“ID”的类型未知" +#: lsoda.c:771 +msgid " such that in the machine, t + _rxC(h) = t on the next step\n" +msgstr " t _rxCh = t\n" -#: et.cpp:1081 -msgid "can not figure out how to import the compartment variable" -msgstr "无法弄清楚如何导入\"compartment(房室)\"变量" +#: lsoda.c:772 +msgid " solver will continue anyway.\n" +msgstr " \n" -#: et.cpp:1152 et.cpp:1154 -msgid "replacement/multiplication events cannot be combined with infusions" -msgstr "\"替换(replacement)\"/\"倍数(multiplication)\"事件不能与输注联合使用" +#: lsoda.c:774 +#, c-format +msgid "lsoda -- above warning has been issued %d times,\n" +msgstr "lsoda -- %d \n" -#: et.cpp:1168 -msgid "old Rxode2 'evid' values are not supported with string compartments" -msgstr "文本型房室不支持旧版 Rxode2的“evid”值" +#: lsoda.c:775 +msgid " it will not be issued again for this problem\n" +msgstr " \n" -#: et.cpp:1381 -msgid "'amt'/'time' needs units to convert the rate to the right units to import the data" -msgstr "“amt”/“time”需要单位将速率转换为正确的单位以导入数据" +#: lsoda.c:807 +msgid "[lsoda] a switch to the stiff method has occurred " +msgstr "[LSODA] " -#: et.cpp:1636 -msgid "'do.sampling' is not supported with dose windows" -msgstr "给药时间窗不支持\"do.sampling\"" +#: lsoda.c:809 +msgid "[lsoda] a switch to the nonstiff method has occurred" +msgstr "[LSODA] " -#: et.cpp:1658 -msgid "dosing window you need to specify window in order, e.g. 'et(time=list(c(0,2)),amt=3)'" -msgstr "给药时间窗您需要按顺序指定时间窗,例如'et(time=list(c(0,2)),amt=3)'" +#: lsoda.c:810 +#, c-format +msgid "at t = %g, tentative step size _rxC(h) = %g, step _rxC(nst) = %d\n" +msgstr " t = %g _rxCh = %g _rxCnst = %d\n" -#: et.cpp:1661 -msgid "dosing time or time windows must only be 1-2 elements" -msgstr "给药时间或时间时间窗只能是1~2个元素" +#: prja.c:44 +msgid "[prja] _rxC(miter) != 2\n" +msgstr "[prja] _rxC(miter) != 2\n" -#: et.cpp:1922 -msgid "cannot mix named compartments and integer compartments" -msgstr "不能混合使用命名的房室和整数房室" +#: rxData.cpp:298 +msgid "column(s) in 'drop' were not in solved data" +msgstr "drop()" -#: et.cpp:2026 et.cpp:2188 -msgid "cannot add more 'ID's to this event table" -msgstr "无法向此事件表添加更多“ID”" +#: rxData.cpp:453 +#, c-format +msgid "refusing to simulate %d items" +msgstr " %d " -#: et.cpp:2256 -msgid "can only have one of the following: 'amt', 'dose'" -msgstr "只能具有以下其中一项:“amt”、“dose”" +#: rxData.cpp:466 rxData.cpp:470 +#, fuzzy +msgid "'sigma' is not a matrix" +msgstr "'%s' " -#: et.cpp:2263 -msgid "can only have one of the following: 'ii', 'dosing.interval', 'dosingInterval' or 'dosing_interval'" -msgstr "只能具有以下其中一项:“ii”、“dosing.interval”、“dosingInterva”或“dosing_interval”" +#: rxData.cpp:474 +msgid "matrix must be a square matrix" +msgstr "" -#: et.cpp:2283 -msgid "can only have one of the following: 'cmt', 'dosing.to', 'dose.to', 'state'" -msgstr "只能具有以下其中一项:“cmt”、“dosing.to”、“dose.to”、“state”" +#: rxData.cpp:482 +msgid "matrix must have named dimensions (try 'lotri')" +msgstr "lotri" -#: et.cpp:2292 -msgid "can only have one of the following: 'amount.units', 'amt.units', 'dose.units'" -msgstr "只能具有以下之一:“'amount.units”、“'amt.units”、“dose.units”" +#: rxData.cpp:514 +msgid "" +"lower bounds needs to be a named vector, a single value or exactly the same " +"size" +msgstr "" -#: et.cpp:2299 -msgid "can only have one of the following: 'time.units', 'timeUnits', 'time_units'" -msgstr "只能具有以下其中一项:“time.units”、“timeUnits”、“time_units”" +#: rxData.cpp:534 +msgid "" +"upper bounds needs to be a named vector, a single value or exactly the same " +"size" +msgstr "" -#: et.cpp:2307 -msgid "can only have one of the following: 'add.sampling', 'do.sampling'" -msgstr "只能具有以下其中一项:“add.sampling”、“do.sampling”" +#: rxData.cpp:550 +msgid "t distribution not yet supported" +msgstr "t" -#: et.cpp:2315 -msgid "can only have one of the following: 'time', 'start.time', 'from'" -msgstr "只能具有以下其中一项:“time”、“start.time”、“from”" +#: rxData.cpp:884 +#, fuzzy +msgid "a NULL object does not have any rxode2 model variables" +msgstr "NULL Rxode2 " -#: et.cpp:2321 -msgid "can only have one of the following: 'nbrDoses', 'nbr.doses'" -msgstr "只能具有以下其中一项:“nbrDoses”、“nbr.doses”" +#: rxData.cpp:919 +msgid "can only lookup one state at a time" +msgstr "" -#: et.cpp:2336 -msgid "can only have one of the following: 'dur', 'duration'" -msgstr "只能具有以下其中一项:“dur”、“duration”" +#: rxData.cpp:922 +msgid "only one state variable should be input" +msgstr "" -#: et.cpp:2343 +#: rxData.cpp:932 #, c-format -msgid "unused argument '%s'" -msgstr "未使用的参数 '%s'" - -#: et.cpp:2354 et.cpp:2359 et.cpp:2374 et.cpp:2379 -msgid "multiple event tables supplied, not sure what to do; try 'c', 'rbind', 'seq' or 'rep'" -msgstr "提供了多个事件表,不知道该如何使用;尝试“c”、“rbind”、“seq”或“rep”" +msgid "cannot locate compartment \"%s\"" +msgstr "%s" -#: et.cpp:2397 et.cpp:2405 et.cpp:2650 et.cpp:2673 et.cpp:2708 et.cpp:2729 -#: et.cpp:2736 et.cpp:2747 et.cpp:2766 et.cpp:2831 et.cpp:2859 et.cpp:2882 -#: et.cpp:2895 et.cpp:2924 et.cpp:2928 et.cpp:2937 et.cpp:3061 et.cpp:3069 -#, c-format -msgid "'%s' cannot be a vector" -msgstr "'%s' 不能是一个向量" +#: rxData.cpp:1177 +msgid "" +"only one estimate per named list item; use 'list(x=1)' instead of " +"'list(x=1:2)'" +msgstr "\"list()\";'list(x=1)'list(x=1:2)" -#: et.cpp:2561 et.cpp:2565 -msgid "nothing done" -msgstr "什么也没做" +#: rxData.cpp:1184 +msgid "incompatible initial estimate" +msgstr "" -#: et.cpp:2611 +#: rxData.cpp:1239 #, c-format -msgid "cannot mix named and integer compartments in '%s'" -msgstr "不能在 '%s' 中混合使用命名的房室和整数房室" +msgid "" +"trying to scale the same compartment by 'scale=c(%s=%f,...)' and 'S%d=%f' " +"choose one" +msgstr "\"(scale)\"scale=c%s=%f,...S%d=%f" -#: et.cpp:2619 +#: rxData.cpp:1250 #, c-format -msgid "'%s' compartment cannot be a vector" -msgstr "“%s”房室不能是一个向量" +msgid "" +"trying to scale the same compartment by 'scale=c(%s=%f,...)' and 's%d=%f' " +"choose one" +msgstr "\"(scale)\"scale=c%s=%f,...s%d=%f" -#: et.cpp:2631 -#, c-format -msgid "'%s' cannot be zero" -msgstr "'%s' 不能为零" +#: rxData.cpp:1274 +#, fuzzy +msgid "scaled a compartment that is not defined by the rxode2 model" +msgstr "\"(scale)\" Rxode2 " -#: et.cpp:2635 -#, c-format -msgid "'%s' cannot be an vector" -msgstr "'%s' 不能是一个向量" +#: rxData.cpp:1521 +msgid "could not allocate memory for solving parameters" +msgstr "" -#: et.cpp:2638 -#, c-format -msgid "'%s' must be an integer or a character" -msgstr "'%s' 必须是\"整数型(integer)\"或\"字符型(character)\"" +#: rxData.cpp:1565 +msgid "memory for residual errors could not be allocated" +msgstr "" -#: et.cpp:2677 -#, c-format -msgid "turning off compartments can only be done when '%s'=2" -msgstr "仅能在 '%s' = 2 时才能关闭房室" +#: rxData.cpp:1572 +msgid "cannot allocate memory to simulate the residuals" +msgstr "" -#: et.cpp:2680 -#, c-format -msgid "zero '%s' cannot be used with '%s'" -msgstr "零个“%s”不能与“%s”一起使用" +#: rxData.cpp:1638 rxData.cpp:3030 +msgid "'thetaMat' must be a named matrix" +msgstr "thetaMat" -#: et.cpp:2683 -#, c-format -msgid "'%s' requires an '%s'" -msgstr "“%s”需要是一个“%s”" +#: rxData.cpp:1646 rxData.cpp:3255 +msgid "'thetaMat' must be symmetric" +msgstr "thetaMat" -#: et.cpp:2687 +#: rxData.cpp:1668 +#, fuzzy +msgid "" +"'thetaMat' is ignored since nStud <= 1\n" +"use 'simVariability = TRUE' to override." +msgstr "'thetaMat' nStud <= 1" + +#: rxData.cpp:1715 #, c-format -msgid "'%s' is ignored when '%s'=2 or '%s'=3" -msgstr "当“%s”=2 或“%s”=3 时,将忽略“%s”" +msgid "parameter '%s' was not simulated in 'thetaMat'" +msgstr " '%s' 'thetaMat' " -#: et.cpp:2710 et.cpp:2717 et.cpp:2720 et.cpp:2731 et.cpp:2738 +#: rxData.cpp:1726 rxData.cpp:1738 #, c-format -msgid "'%s' needs a '%s'" -msgstr "“%s”需要一个“%s”" +msgid "'%s' must be a named matrix" +msgstr "'%s' " -#: et.cpp:2725 +#: rxData.cpp:1747 #, c-format -msgid "can not specify '%s' and '%s' for a dose, please pick one" -msgstr "不能指定“%s”和“%s”作为给药,请选择一个" +msgid "error calculating 'chol(%s)'" +msgstr "" -#: et.cpp:2749 -msgid "'ii' needs a 'dose'/'amt'" -msgstr "“ii(给药间隔)”需要“dose(给药)”/“amt(药量)”" +#: rxData.cpp:1750 +#, fuzzy, c-format +msgid "" +"error trying to correct '%s' to be a symmetric, positive definite matrix" +msgstr "thetaMat" -#: et.cpp:2760 -msgid "dosing interval of zero makes no sense with multiple dose events" -msgstr "给药间隔为零对于多次给药事件毫无意义" +#: rxData.cpp:1754 +#, fuzzy, c-format +msgid "corrected '%s' to be a symmetric, positive definite matrix" +msgstr "thetaMat" -#: et.cpp:2768 et.cpp:2900 -#, c-format -msgid "non-zero '%s' needs a '%s'" -msgstr "非零'%s' 需要一个'%s'" +#: rxData.cpp:1948 +msgid "'params' must be a named vector" +msgstr "params()" -#: et.cpp:2805 et.cpp:2808 et.cpp:2811 -#, c-format -msgid "can only specify '%s' or '%s', not both" -msgstr "只能指定“%s”或“%s”,不能同时指定两者" +#: rxData.cpp:1969 +msgid "multi-subject simulation without without 'omega'" +msgstr "'omega'" -#: et.cpp:2817 -#, c-format -msgid "'%s' can only have one item" -msgstr "'%s' 只能有一个项目" +#: rxData.cpp:2325 +msgid "ran out of memory during 'updateSolveEnvPost'" +msgstr "updateSolveEnvPost" -#: et.cpp:2820 -#, c-format -msgid "'%s' must be logical" -msgstr "'%s' 必须是逻辑的" +#: rxData.cpp:2728 +msgid "No additional parameters were specified, returning original object" +msgstr "" -#: et.cpp:2827 -#, c-format -msgid "cannot specify '%s' and '%s' for a dose, please pick one" -msgstr "不能为给药指定“%s”和“%s”,请选择一个" +#: rxData.cpp:2807 +msgid "can not update object" +msgstr "" -#: et.cpp:2838 -msgid "-1 and -2 rates do not make sense with units" -msgstr "-1 和 -2 速率(rate)对单位没有意义" +#: rxData.cpp:2859 +msgid "'from' must be of length 1" +msgstr "from 1" -#: et.cpp:2843 -#, c-format -msgid "'%s' is cannot be converted and added to this table" -msgstr "“%s”是无法被转换并添加到此表中" +#: rxData.cpp:2867 +msgid "'to' must be of length 1" +msgstr "to 1" -#: et.cpp:2850 -#, c-format -msgid "steady state constant infusion dosing records must have '%s=-1' or positive rate" -msgstr "稳态恒速输注给药记录必须具有“%s=-1”或正数的速率(rate)" +#: rxData.cpp:2877 +msgid "'by' must be of length 1" +msgstr "by 1" -#: et.cpp:2869 -#, c-format -msgid "'%s' cannot be converted and added to this table" -msgstr "“%s”无法被转换并添加到此表中" +#: rxData.cpp:2885 +msgid "'length.out' must be of length 1" +msgstr "length.out 1" -#: et.cpp:2930 -#, c-format -msgid "number of doses must be at least one ('%s': %d)" -msgstr "给药数必须至少为一(“%s”: %d)" +#: rxData.cpp:2891 +#, fuzzy +msgid "cannot use both 'by' and 'length.out' for rxode2 simulations" +msgstr "bylength.outRxode2" -#: et.cpp:2939 -#, c-format -msgid "'%s' can only be used with positive inter-dose intervals ('%s')" -msgstr "“%s”只能与正数的给药间隔(“%s”)一起使用" +#: rxData.cpp:2991 +#, fuzzy +msgid "rxode2 only supports 500 factors" +msgstr "Rxode2 500 " -#: et.cpp:2949 -#, c-format -msgid "'%s' does not make sense with multiple dosing times" -msgstr "'%s' 在多次给药时没有意义" +#: rxData.cpp:3039 +msgid "error calculating 'chol(thetaMat)'" +msgstr "" -#: et.cpp:2978 -msgid "dosing windows can only have 1-2 items in them" -msgstr "给药时间窗只能有1-2个项" +#: rxData.cpp:3042 +#, fuzzy +msgid "" +"error trying to correct 'thetaMat' to be a symmetric, positive definite " +"matrix" +msgstr "thetaMat" -#: et.cpp:2987 -#, c-format -msgid "'%s' requires non zero additional doses ('%s') or steady state dosing ('%s': %f, '%s': %d; '%s': %d), reset '%s' to zero." -msgstr "“%s”需要非零额外附加给药(“%s”)或稳态给药(“%s”:%f,“%s”:%d;“%s”: %d),将“%s”重置为零。" +#: rxData.cpp:3045 +#, fuzzy +msgid "corrected 'thetaMat' to be a symmetric, positive definite matrix" +msgstr "thetaMat" -#: et.cpp:2993 -#, c-format -msgid "'%s' must be 1 when specifying a steady-state constant infusion" -msgstr "当描述为稳态恒速输注时,'%s' 必须为 1" +#: rxData.cpp:3181 +#, fuzzy +msgid "" +"when specifying 'thetaMat' the parameters cannot be a 'data.frame'/'matrix'." +msgstr "thetaMatomegasigmadata.frame/matrix" -#: et.cpp:2996 +#: rxData.cpp:3227 #, c-format -msgid "'%s' must be 0, 1 or 2" -msgstr "'%s' 必须为 0、1 或 2" +msgid "" +"provided multi-subject data (n=%d) trying to simulate a different number of " +"subjects (n=%d)" +msgstr "n=%d n=%d" -#: et.cpp:2999 -#, c-format -msgid "'%s' required with '%s'" -msgstr "“%s”和“%s”是必需的" +#: rxData.cpp:3314 rxData.cpp:3332 rxData.cpp:3341 +msgid "" +"if parameters are not named, they must match the order and size of the " +"parameters in the model" +msgstr "" -#: et.cpp:3003 -#, c-format -msgid "'%s' cannot be used with steady state constant infusion" -msgstr "'%s' 不能与稳态恒速输注一起使用" +#: rxData.cpp:3420 +msgid "can not allocate enough memory to load 'evid'" +msgstr "evid" -#: et.cpp:3006 -#, c-format -msgid "steady state ('%s') is not supported with dosing windows" -msgstr "给药时间窗不支持稳定状态('%s')" +#: rxData.cpp:3463 +msgid "nothing to solve" +msgstr "" -#: et.cpp:3009 -#, c-format -msgid "additional doses must be positive ('%s'=%d)" -msgstr "额外的附加给药必须为正数('%s'=%d)" +#: rxData.cpp:3516 +msgid "can not allocate memory for the covariates" +msgstr "" -#: et.cpp:3012 -#, c-format -msgid "additional doses require an inter-dose interval ('%s')" -msgstr "额外的附加给药需要给药间隔(“%s”)" +#: rxData.cpp:3604 +msgid "data must be ordered by 'ID' and 'TIME' variables" +msgstr "IDTIME" -#: et.cpp:3017 -#, c-format -msgid "for steady state infusions, you need %s=0, %s>0, %s=1, %s=0" -msgstr "对于稳态输注,您需要 %s=0、%s>0、%s=1、%s=0" +#: rxData.cpp:3674 +msgid "cannot allocate enough memory to sort input parameters" +msgstr "" -#: et.cpp:3030 -msgid "dosing time window lists can have 1-2 numeric entries in them" -msgstr "给药时间窗列表中可以包含1-2个数字项" +#: rxData.cpp:3804 +msgid "'resample' must be NULL or a character vector" +msgstr "resample() NULL " -#: et.cpp:3035 -msgid "dosing window list needs to be numeric values only" -msgstr "给药时间窗列表只需要是数值的值" +#: rxData.cpp:3913 +msgid "nPopPar != 1 but parameters are specified as a NumericVector" +msgstr "nPopPar != 1" + +#: rxData.cpp:3957 rxData.cpp:4924 rxData.cpp:4933 rxData.cpp:4941 +#: rxData.cpp:4949 rxData.cpp:4957 rxData.cpp:4966 rxData.cpp:4974 +#: rxData.cpp:4981 rxData.cpp:4988 rxData.cpp:4995 rxData.cpp:5002 +#: rxData.cpp:5009 rxData.cpp:5018 rxData.cpp:5028 rxData.cpp:5037 +#: rxData.cpp:5043 rxData.cpp:5050 rxData.cpp:5057 +msgid "ran out of memory" +msgstr "" -#: et.cpp:3088 -msgid "cannot figure out what type of 'EventTable' you are trying to create" -msgstr "无法弄清楚您尝试创建的“事件表”类型" +#: rxData.cpp:4027 +msgid "Something is wrong" +msgstr "" -#: et.cpp:3173 et.cpp:3176 -msgid "cannot have event tables with integer and character 'cmt'" -msgstr "事件表中整数和字符“cmt”不能混合使用" +#: rxData.cpp:4045 +msgid "aborted solve" +msgstr "" -#: et.cpp:3261 +#: rxData.cpp:4069 #, c-format -msgid "assumed a dose interval of %.1f between event tables; use 'ii' to adjust" -msgstr "假设事件表之间的给药间隔为%.1f;使用“ii”进行调整" +msgid "" +"exited from at least one while after %d iterations, (increase with " +"`rxSolve(..., maxwhile=#)`)" +msgstr "%d(' rxSolve(,maxwhile = #))" -#: et.cpp:3347 -msgid "no events table found for 'seq'/'rep'/'rbind'/'c'" -msgstr "未找到用于“seq”/“rep”/“rbind”/“c”的事件表" +#: rxData.cpp:4411 +msgid "zero 'thetaMat' specified, no uncertainty in fixed effects" +msgstr "thetaMat" -#: et.cpp:3468 -msgid "'wait' cannot be a vector" -msgstr "“wait”不能是向量" +#: rxData.cpp:4414 +msgid "zero 'omega', no variability from random-effects" +msgstr "omega" -#: etTran.cpp:141 -#, c-format -msgid "negative compartments on non-ode 'cmt' (%s) does not make sense (id: %s, row: %d)" -msgstr "non-ode 'cmt'(%s)上的负数房室没有意义(ID: %s, 行: %d)" +#: rxData.cpp:4417 +msgid "zero 'sigma', no unexplained variability" +msgstr "sigma" -#: etTran.cpp:276 etTran.cpp:286 -#, c-format -msgid "negative compartments on non-ode 'cmt' (%s) does not make sense (id: %s row: %d)" -msgstr "non-ode 'cmt'(%s)上的负数房室没有意义(ID: %s, 行: %d)" +#: rxData.cpp:4435 +msgid "" +"dropped key column, returning data.frame instead of special solved data.frame" +msgstr "data.framedata.frame" + +#: rxData.cpp:4629 +msgid "control list not setup correctly" +msgstr "" -#: etTran.cpp:307 -msgid "should not reach here" -msgstr "不应该到达这里" +#: rxData.cpp:4691 +msgid "" +"cannot solve without event information\n" +"this can occur when the data frame you are providing does not have the " +"column 'time'" +msgstr "" + +#: rxData.cpp:4701 +msgid "cannot update this object" +msgstr "" + +#: rxData.cpp:4759 +#, fuzzy +msgid "cannot load rxode2 dlls for this model" +msgstr " Rxode2 dll" + +#: rxData.cpp:4828 rxData.cpp:4847 +msgid "not thread safe method, using 1 core" +msgstr " 1 " -#: etTran.cpp:471 -msgid "cannot keep 'evid'; try 'addDosing'" -msgstr "不能保持“evid”;尝试“adDosing”" +#: rxData.cpp:4856 +msgid "since throwing warning with NA time, change to single threaded" +msgstr "" -#: etTran.cpp:616 -msgid "'time' is required in dataset" -msgstr "数据集中需要“time”" +#: rxData.cpp:5123 +msgid "'infSSstep' needs to be positive" +msgstr "infSSstep" -#: etTran.cpp:708 -msgid "steady state column ('ss') needs to be an integer" -msgstr "稳态列 ('ss') 需要是一个整数" +#: rxData.cpp:5194 +msgid "unknown covariate interpolation specified" +msgstr "" -#: etTran.cpp:719 -msgid "event id ('evid') needs to be an integer" -msgstr "事件id列('evid') 需要为整数" +#: rxData.cpp:5292 +#, fuzzy, c-format +msgid "" +"number of parameters (%d) solved by rxode2 for multi-subject data needs to " +"be a multiple of the number of subjects (%d)" +msgstr "Rxode2%d" -#: etTran.cpp:728 -msgid "missing DV ('mdv') needs to be an integer" -msgstr "视为因变量缺失列('mdv') 需要是一个整数" +#: rxData.cpp:5415 +msgid "could not allocate enough memory for solving" +msgstr "" -#: etTran.cpp:742 -msgid "missing dependent variable ('mdv') needs to be an integer" -msgstr "视为因变量缺失列('MDV') 需要是一个整数" +#: rxData.cpp:5740 +#, c-format +msgid "partial match of '%s' to '%s'" +msgstr "%s%s" -#: etTran.cpp:750 -msgid "'rate' needs to be a number" -msgstr "“rate(速率)”列需要是一个数字" +#: rxData.cpp:5813 +msgid "cannot update nonexistent parameters" +msgstr "" -#: etTran.cpp:759 -msgid "'dur' needs to be a number" -msgstr "“dur(持续时长)”列需要是一个数字" +#: rxData.cpp:6068 +#, fuzzy +msgid "Can not figure out the rxode2 object" +msgstr " Rxode2 " -#: etTran.cpp:774 -msgid "amount ('amt') needs to be a number" -msgstr "药量(“amt”)列需要是一个数字" +#: rxData.cpp:6182 rxData.cpp:6225 +msgid "can not figure out the DLL for this object" +msgstr " DLL" -#: etTran.cpp:782 -msgid "inter-dose interval ('ii') needs to be a number" -msgstr "给药间隔列('ii') 需要是一个数字" +#: rxData.cpp:6426 +msgid "package-based models cannot be unloaded" +msgstr "\"(unloaded)\"" -#: etTran.cpp:790 -msgid "number of additional doses ('addl') needs to be an integer" -msgstr "额外的附件给药次数列('addl') 需要是一个整数" +#: rxData.cpp:6473 +msgid "package-based models cannot be deleted" +msgstr "" -#: etTran.cpp:798 -msgid "dependent variable ('dv') needs to be a number" -msgstr "因变量列('dv') 需要是一个数字" +#: rxInv.cpp:36 +msgid "matrix seems singular; Using pseudo-inverse\n" +msgstr ";\n" -#: etTran.cpp:806 -msgid "censoring variable ('cens') needs to be a number" -msgstr "删失变量列(“cens”)需要是一个数字" +#: rxInv.cpp:57 rxInv.cpp:61 +msgid "can not invert in 'rxToCholOmega'" +msgstr "rxToCholOmega" -#: etTran.cpp:814 -msgid "limit variable ('limit') needs to be a number" -msgstr "定量限变量列(“limit”)需要是一个数字" +#: rxInv.cpp:128 +msgid "theta number must be positive for 'd(omegaInv)'" +msgstr "theta'd(omegaInv)'" -#: etTran.cpp:863 -#, c-format -msgid "censoring column can only be -1, 0 or 1 (id: %s, row: %d)" -msgstr "删失列只能为 -1、0 或 1(id: %s,row: %d)" +#: rxInv.cpp:132 +msgid "theta number must be positive for 'd(D)'" +msgstr "theta''d(D)'" -#: etTran.cpp:888 -#, c-format -msgid "infinite times are not allowed (id: %s, row: %d)" -msgstr "不允许无穷大的时间(id: %s,row: %d)" +#: rxInv.cpp:165 +msgid "error in 'rxSymInvCholEnvCalculate' environment" +msgstr "rxSymInvCholEnvCalculate" -#: etTran.cpp:946 -#, c-format -msgid "steady state records cannot be on negative compartments (id: %s, row: %d)" -msgstr "达到稳态的记录不能位负数的房室上(id: %s,row: %d)" +#: rxInv.cpp:178 +msgid "theta for omega calculations not setup yet" +msgstr "omegatheta" -#: etTran.cpp:976 +#: rxInv.cpp:276 #, c-format -msgid "when using steady state constant infusion modeling duration does not make sense (id: %s, row: %d)" -msgstr "使用稳态恒速输注建模时,输注持续时间没有意义(id: %s,row: %d)" +msgid "theta has to have %d elements" +msgstr "theta %d " -#: etTran.cpp:995 -#, c-format -msgid "specifying duration with a steady state constant infusion makes no sense (id: %s row: %d)" -msgstr "使用稳态恒速输注时,指定输注持续时长没有意义(id: %s,row: %d)" +#: rxInv.cpp:279 +msgid "Can only assign 'theta' in this environment" +msgstr "theta" -#: etTran.cpp:1001 etTran.cpp:1007 +#: rxode2_df.cpp:143 #, c-format -msgid "specifying duration with a steady state constant infusion makes no sense (id: %d row: %d)" -msgstr "使用稳态恒速输注时,指定输注持续时长没有意义(id: %d, row: %d)" +msgid "" +"The simulated residual errors do not match the model specification (%d=%d)" +msgstr "" -#: etTran.cpp:1018 -#, c-format -msgid "'rate' and/or 'dur' are not specified correctly (id: %d row: %d)" -msgstr "未正确指定“rate”和/或“dur”(id: %s,row: %d)" +#: rxode2_df.cpp:217 +msgid "'alag(.)'/'rate(.)'/'dur(.)' cannot depend on the state values" +msgstr "'alag.'/'rate.'/'dur.' " -#: etTran.cpp:1036 -#, c-format -msgid "'amt' or 'dur'/'rate' are non-zero therefore MDV cannot = 0 (id: %s row: %d)" -msgstr "“amt”或“dur”/“rate”不为零,因此MDV不能= 0(id: %s, row: %d)" +#: rxode2_df.cpp:227 +msgid "could not solve the system" +msgstr "" -#: etTran.cpp:1074 -msgid "'addl' is ignored with observations" -msgstr "“addl”被观测忽略" +#: rxode2_df.cpp:229 +msgid "" +"some ID(s) could not solve the ODEs correctly; These values are replaced " +"with 'NA'" +msgstr " ID ;NA" -#: etTran.cpp:1096 etTran.cpp:1180 +#: rxode2_df.cpp:782 #, c-format -msgid "'limit' (%f) cannot equal 'dv' (%f) id: %s row: %d" -msgstr "“limit”(%f)不能等于“dv”(%f) id: %s, row: %d" +msgid "dose to compartment %d ignored (not in system; 'id=%d')" +msgstr " %d ;'id=%d'" -#: etTran.cpp:1129 +#: sbuf.c:182 #, c-format -msgid "'cmt' and 'dvid' specify different compartments (id: %s row: %d)" -msgstr "“cmt”和“dvid”指了不同的房室(id: %s, row: %d)" +msgid "encoding error in 'addLine' format: '%s' n: %d; errno: %d" +msgstr "addLine%sn%d;errno %d" -#: etTran.cpp:1150 -msgid "'DVID'/'CMT' translation:\n" -msgstr "“DVID”/“CMT”转换:\n" +#: utilc.c:70 utilc.c:125 utilc.c:180 utilc.c:235 utilc.c:292 utilc.c:348 +#: utilc.c:404 utilc.c:462 utilc.c:524 +msgid "'a' needs to be a number" +msgstr "a" -#: etTran.cpp:1156 -#, c-format -msgid "'dvid'->'cmt' or 'cmt' on observation record on a undefined compartment (use 'cmt()' 'dvid()') id: %s row: %d" -msgstr "'dvid'->'cmt' 或 'cmt' 在未定义的房室上的观测记录上(使用 'cmt()' 'dvid()') id: %s row: %d" +#: utilc.c:78 utilc.c:133 utilc.c:188 utilc.c:243 utilc.c:300 utilc.c:356 +#: utilc.c:412 utilc.c:470 utilc.c:532 +msgid "'z' needs to be a number" +msgstr "z" -#: etTran.cpp:1195 -#, c-format -msgid "'mdv' cannot be 0 when 'evid'=1 id: %s row: %d" -msgstr "当“evid”=1时,“mdv” 不能为 0,id: %s, row: %d" +#: utilc.c:102 utilc.c:157 utilc.c:212 utilc.c:268 utilc.c:325 utilc.c:381 +#: utilc.c:437 utilc.c:498 utilc.c:560 +msgid "inconsistent sizes" +msgstr "" -#: etTran.cpp:1212 -msgid "'addl' is ignored with 'EVID=2'" -msgstr "“EVID=2”,“addl”被忽略" +#: utilc.c:588 utilc.c:598 utilc.c:641 utilc.c:651 utilc.c:694 utilc.c:704 +#: utilc.c:748 utilc.c:758 +msgid "'low' must be a numeric of length 1" +msgstr "low 1 " -#: etTran.cpp:1215 -msgid "'ss' is ignored with 'EVID=2'" -msgstr "“EVID=2”,“ss”被忽略" +#: utilc.c:591 utilc.c:605 utilc.c:644 utilc.c:658 utilc.c:697 utilc.c:711 +#: utilc.c:751 utilc.c:765 +msgid "'high' must be a numeric of length 1" +msgstr "high 1 " -#: etTran.cpp:1257 -msgid "'addl' is ignored with 'EVID=3'" -msgstr "“EVID=2”,“addl”被忽略" +#: utilc.c:608 utilc.c:661 utilc.c:714 utilc.c:768 +msgid "'high' must be greater than 'low'" +msgstr "highlow" -#: etTran.cpp:1260 -msgid "'ss' is ignored with 'EVID=3'" -msgstr "“EVID=2”,“ss”被忽略" +#~ msgid "'shape' must be non-negative" +#~ msgstr "shape()" -#: etTran.cpp:1284 -#, c-format -msgid "'mdv' cannot be 0 when 'evid'=4 id: %s row: %d" -msgstr "当“evid”=4时,“mdv” 不能为 0, id: %s, row: %d" +#~ msgid "dimension, 'd' of correlation matrix must be > 1" +#~ msgstr "d> 1" -#: etTran.cpp:1310 -#, c-format -msgid "cannot have an infusion event with a replacement event (id: %s row: %d)" -msgstr "\"替换(replacement)\"事件不能具有输注事件(id: %s, row: %d)" +#~ msgid "'eta' must be >= 1" +#~ msgstr "eta>= 1" -#: etTran.cpp:1317 -#, c-format -msgid "cannot have an infusion event with a multiplication event (id: %s row: %d)" -msgstr "\"倍数(multiplication)\"事件不能具有输注事件(id: %s, row: %d)" +#~ msgid "" +#~ "log standard deviation size needs to be the same size as the log standard " +#~ "error of the estimate" +#~ msgstr "" -#: etTran.cpp:1328 -msgid "'rate' or 'dur' is ignored with classic Rxode2 'EVID's" -msgstr "“rate”或“dur”在经典Rxode2 'EVID'中被忽略" +#~ msgid "'nu' must be greater than 'd'-1" +#~ msgstr "Wishartnud()-1" -#: etTran.cpp:1332 -msgid "'ss' is ignored with classic Rxode2 'EVID's" -msgstr "“ss”在经典Rxode2 'EVID'中被忽略" +#~ msgid "unknown 'diagXformType' transformation" +#~ msgstr "diagXformType(X)" -#: etTran.cpp:1353 #, c-format -msgid "'ss' with 'addl' not supported (id: %s row: %d)" -msgstr "不支持带有“addl”的“ss”(id: %s, row: %d)" +#~ msgid "variable 'type': Unrecognized cvPost type='%s'" +#~ msgstr " 'type' cvPost='%s'" -#: etTran.cpp:1364 -#, c-format -msgid "'amt' value NA or 0 for dose event (id: %s row: %d)" -msgstr "给药事件的“amt”值为NA或为0(id: %s, row: %d)" +#~ msgid "variable 'type': Can only use type string or integer[1,3]" +#~ msgstr " 'type'[13]" -#: etTran.cpp:1402 #, c-format -msgid "'amt' value NA for dose event; (id: %s, amt: %f, evid: %d Rxode2 evid: %d, row: %d)" -msgstr "给药事件的“amt”值为NA;(id: %s, amt: %f, evid: %d Rxode2 evid: %d, row: %d)" +#~ msgid "variable 'diagXformType': Unrecognized transformation '%s'" +#~ msgstr " 'diagXformType(X)' '%s'" -#: etTran.cpp:1480 -msgid "there are evid=3/4 records in an incorrectly sorted dataset, system is reset, but time is not reset" -msgstr "数据集中存在错误排序的evid=3或4记录,系统已重置,但时间未重置" +#~ msgid "" +#~ "variable 'diagXformType': Can only use transformation string or " +#~ "integer[1,6]" +#~ msgstr " 'diagXformType(X)'[16]" -#: etTran.cpp:1537 -msgid "censoring missing 'DV' values do not make sense" -msgstr "删失缺失的“DV”值没有意义" +#~ msgid "" +#~ "'n' is determined by the 'omega' argument which contains the simulated " +#~ "standard deviations" +#~ msgstr "nomega" -#: etTran.cpp:1590 -msgid "no rows in event table or input data" -msgstr "事件表或输入数据中没有数据行" +#~ msgid "" +#~ "when sampling from correlation priors to create covariance matrices, the " +#~ "input must be a matrix of standard deviations" +#~ msgstr "" -#: etTran.cpp:1612 -msgid "empty data" -msgstr "空数据" +#~ msgid "" +#~ "'omega' needs to be a matrix or a numeric vector that can be converted to " +#~ "a matrix" +#~ msgstr "nomega" -#: etTran.cpp:1628 -msgid "while censoring is included in dataset, no observations are censored" -msgstr "虽然数据集中包含删失,但不会对任何观测值进行删失" +#~ msgid "'thetaMat' needs 'params' to be non-NULL" +#~ msgstr "thetaMat\"(non-NULL)\"" -#: etTran.cpp:1632 -msgid "'dv' and 'limit' swapped since 'limit' > 'dv'" -msgstr "“dv”和“limit”交换,因为“limit”>“dv”" +#~ msgid "" +#~ "when specifying 'thetaMat', 'omega', or 'sigma' the parameters cannot be " +#~ "a 'data.frame'/'matrix'" +#~ msgstr "thetaMatomegasigmadata.frame/matrix" -#: etTran.cpp:1753 -msgid "number of individuals not calculated correctly" -msgstr "个体数量没有被计算正确" +#~ msgid "'theta' must be the same size as 'thetaMat'" +#~ msgstr "thetathetaMat" -#: etTran.cpp:1908 -msgid "corrupted event table" -msgstr "事件表已损坏" +#~ msgid "'omega' must be symmetric, positive definite" +#~ msgstr "omega" -#: etTran.cpp:2022 -msgid "\n" -"with negative times, compartments initialize at first negative observed time\n" -"with positive times, compartments initialize at time zero\n" -"use 'rxSetIni0(FALSE)' to initialize at first observed time\n" -"this warning is displayed once per session" -msgstr "\n" -"当时间为负数时,房室在第一次负数的观察时间初始化\n" -"当时间为正数时,房室在时间0初始化\n" -"使用'rxSetIni0(FALSE)',在第一次观测的时间初始化\n" -"此警告在每个会话中显示一次" +#~ msgid "'omega' needs to be a matrix or lotri matrix" +#~ msgstr "omega\"(matrix)\"\"lotri matrix\"" -#: expandGrid.cpp:73 -msgid "unanticipated input for rxExpandGrid_" -msgstr "意料之外的rxExpandGrid_输入" +#~ msgid "'sigma' must be symmetric, positive definite" +#~ msgstr "sigma" -#: expm.cpp:211 -msgid "requested tolerance is too high" -msgstr "请求的公差(tolerance)太高" +#~ msgid "'sigma' needs to be a matrix or lotri matrix" +#~ msgstr "sigma\"(matrix)\"\"lotri matrix\"" -#: expm.cpp:410 -#, c-format -msgid "unsupported indLin code: %d" -msgstr "不支持的indLin代码: %d" +#~ msgid "un-handled nesting information" +#~ msgstr "" -#: forder.cpp:62 -#, c-format -msgid "ignoring invalid %s==\"%s\"\n" -" not an integer >= 1\n" -"remove any characters that are not a digit [0-9]\n" -" See ?Rxode2::setDTthreads" -msgstr "忽略无效的 %s==“%s”\n" -"不是一个整数 >= 1\n" -"删除任何不是数字[0-9]的字符\n" -"请参阅?Rxode2::setDTthreads" +#~ msgid "cannot find 'id' column in dataset" +#~ msgstr "id" -#: forder.cpp:88 -#, c-format -msgid "ignoring invalid RXODE2_NUM_PROCS_PERCENT==%d.\n" -"If used it must be an integer between 2 and 100. Default is 50. See ?rxSetThreads" -msgstr "忽略无效的RXODE2_NUM_PROCS_PERCENT==%d。\n" -"如果使用,它必须是介于 2 和 100 之间的整数。默认值为 50。请参阅?rxSetThreads" +#~ msgid "'omega' must be a list/lotri/matrix" +#~ msgstr "omega\"(list)\"/lotri/\"(matrix)\"" -#: forder.cpp:124 -msgid "'verbose' must be TRUE or FALSE" -msgstr "“verbose”必须为逻辑值真(TRUE)或假(FALSE)" +#~ msgid "event table was not updated (no dose/sampling windows)" +#~ msgstr "/" -#: forder.cpp:127 -msgid "This installation of data.table has not been compiled with OpenMP support.\n" -msgstr "此data.table安装没有在OpenMP支持下编译。\n" +#~ msgid "" +#~ "windows need to be a list of observation windows, each of 2 elements e.g. " +#~ "list(c(0,2), c(2,7))" +#~ msgstr "\"(list)\"C02C27" -#: forder.cpp:132 -#, c-format -msgid " omp_get_num_procs() %d\n" -msgstr " omp_get_num_procs() %d\n" +#~ msgid "windows need to be ordered list(c(2,0)) is invalid" +#~ msgstr "Windowslist(c(2,0))" -#: forder.cpp:133 #, c-format -msgid " RXODE2_NUM_PROCS_PERCENT %s\n" -msgstr " RXODE2_NUM_PROCS_PERCENT %s\n" +#~ msgid "unknown method: '%s'" +#~ msgstr "%s" -#: forder.cpp:134 -#, c-format -msgid " RXODE2_NUM_THREADS %s\n" -msgstr " RXODE2_NUM_THREADS %s\n" +#~ msgid "can only specify either 'amt' or 'value'" +#~ msgstr "amtvalue" -#: forder.cpp:135 -#, c-format -msgid " RXODE2_THROTTLE %s\n" -msgstr " RXODE2_THROTTLE %s\n" +#~ msgid "can only specify either 'cmt', 'ytype', 'state' or 'var'" +#~ msgstr "cmtytypestatevar" -#: forder.cpp:136 -#, c-format -msgid " omp_get_thread_limit() %d\n" -msgstr " omp_get_thread_limit() %d\n" +#~ msgid "can only specify either 'duration' or 'dur'" +#~ msgstr "durationdur" -#: forder.cpp:137 -#, c-format -msgid " omp_get_max_threads() %d\n" -msgstr " omp_get_max_threads() %d\n" +#~ msgid "need a 'time' column" +#~ msgstr "time()" -#: forder.cpp:138 -#, c-format -msgid " OMP_THREAD_LIMIT %s\n" -msgstr " OMP_THREAD_LIMIT %s\n" +#~ msgid "using 'mdv' instead of 'method'" +#~ msgstr "mdvmethod" -#: forder.cpp:139 -#, c-format -msgid " OMP_NUM_THREADS %s\n" -msgstr " OMP_NUM_THREADS %s\n" +#~ msgid "using 'evid' instead of 'mdv'" +#~ msgstr "evidmdv" -#: forder.cpp:141 -#, c-format -msgid " Rxode2 is using %d threads with throttle==%d. See ?setRxthreads.\n" -msgstr " Rxode2 正在使用%d个线程和throttle==%d。请参阅?setRxthreads。\n" +#~ msgid "'ID' type is unknown" +#~ msgstr "ID" -#: forder.cpp:149 -msgid "'throttle' must be a single number, non-NA, and >=1" -msgstr "“throttle”必须是单个数字,非NA且 >=1" +#~ msgid "can not figure out how to import the compartment variable" +#~ msgstr "\"compartment()\"" -#: forder.cpp:163 -msgid "threads= must be either NULL or a single number >= 0 See ?setRxthreads" -msgstr "threads=必须是NULL或单个>=0的数字。请参阅?setRxthreads" +#~ msgid "replacement/multiplication events cannot be combined with infusions" +#~ msgstr "\"(replacement)\"/\"(multiplication)\"" -#: forder.cpp:167 -msgid "internal error: percent= must be TRUE or FALSE at C level" -msgstr "内部错误:percent(百分比)= 在C级别必须为TRUE或FALSE" +#~ msgid "old Rxode2 'evid' values are not supported with string compartments" +#~ msgstr " Rxode2evid" -#: forder.cpp:170 -#, c-format -msgid "internal error: threads==%d should be between 2 and 100 (percent=TRUE at C level)" -msgstr "内部错误:threads==%d 应介于 2 和 100 之间(C 级别的percent(百分比)=TRUE)" +#~ msgid "" +#~ "'amt'/'time' needs units to convert the rate to the right units to import " +#~ "the data" +#~ msgstr "amt/time" -#: intdy.c:50 -#, c-format -msgid "[intdy] k = %d illegal\n" -msgstr "[intdy] k = %d 非法\n" +#~ msgid "'do.sampling' is not supported with dose windows" +#~ msgstr "\"do.sampling\"" -#: intdy.c:55 -#, c-format -msgid "intdy -- t = %g illegal. t not in interval tcur - _rxC(hu) to tcur\n" -msgstr "intdy -- t = %g 非法。t没有在tcur - _rxC(hu)到tcur的间隔中\n" +#~ msgid "" +#~ "dosing window you need to specify window in order, e.g. " +#~ "'et(time=list(c(0,2)),amt=3)'" +#~ msgstr "'et(time=list(c(0,2)),amt=3)'" -#: lincmt.c:39 lincmt.c:46 -msgid "could not find a start to the infusion" -msgstr "找不到输注的开始" +#~ msgid "dosing time or time windows must only be 1-2 elements" +#~ msgstr "1~2" -#: lincmt.c:51 lincmt.c:58 -msgid "could not find an end to the infusion" -msgstr "找不到输注的终止" +#~ msgid "cannot mix named compartments and integer compartments" +#~ msgstr "" -#: lincmt.c:200 -msgid "solve data is not loaded" -msgstr "求解数据未加载" +#~ msgid "cannot add more 'ID's to this event table" +#~ msgstr "ID" -#: lincmt.c:1879 -msgid "not an integer/real" -msgstr "不是整数/实数" +#~ msgid "can only have one of the following: 'amt', 'dose'" +#~ msgstr "amtdose" -#: lincmt.c:1897 lincmt.c:2007 lincmt.c:2179 -msgid "The dimensions of the parameters must match" -msgstr "参数的维数必须匹配" +#~ msgid "" +#~ "can only have one of the following: 'ii', 'dosing.interval', " +#~ "'dosingInterval' or 'dosing_interval'" +#~ msgstr "iidosing.intervaldosingIntervadosing_interval" -#: lincmt.c:2394 -msgid "'ncmt' needs to be 1-3" -msgstr "“ncmt”需要为 1~3" +#~ msgid "" +#~ "can only have one of the following: 'cmt', 'dosing.to', 'dose.to', 'state'" +#~ msgstr "cmtdosing.todose.tostate" -#: lincmt.c:2397 -msgid "'inp' needs to be list/data frame" -msgstr "“inp”需要是\"列表(list)\"/\"数据框(data frame)\"类型" +#~ msgid "" +#~ "can only have one of the following: 'amount.units', 'amt.units', 'dose." +#~ "units'" +#~ msgstr "'amount.units'amt.unitsdose.units" -#: lincmtB.cpp:181 -#, c-format -msgid "invalid trans (2 cmt trans %d)\n" -msgstr "无效的\"trans(参数化方式)\"(2 cmt trans %d)\n" +#~ msgid "" +#~ "can only have one of the following: 'time.units', 'timeUnits', " +#~ "'time_units'" +#~ msgstr "time.unitstimeUnitstime_units" -#: lsoda.c:221 -#, c-format -msgid "[lsoda] illegal itask = %d\n" -msgstr "[lsoda]非法itask = %d\n" +#~ msgid "can only have one of the following: 'add.sampling', 'do.sampling'" +#~ msgstr "add.samplingdo.sampling" -#: lsoda.c:226 -#, c-format -msgid "[lsoda] ixpr = %d is illegal\n" -msgstr "[lsoda] ixpr = %d是非法的\n" +#~ msgid "can only have one of the following: 'time', 'start.time', 'from'" +#~ msgstr "timestart.timefrom" -#: lsoda.c:230 -msgid "[lsoda] mxstep < 0\n" -msgstr "[lsoda]mxstep< 0\n" +#~ msgid "can only have one of the following: 'nbrDoses', 'nbr.doses'" +#~ msgstr "nbrDosesnbr.doses" -#: lsoda.c:235 -msgid "[lsoda] mxhnil < 0\n" -msgstr "[lsoda] mxhnil < 0\n" +#~ msgid "can only have one of the following: 'dur', 'duration'" +#~ msgstr "durduration" -#: lsoda.c:240 #, c-format -msgid "[lsoda] mxordn = %d is less than 0\n" -msgstr "[lsoda] mxordn = %d小于0\n" +#~ msgid "unused argument '%s'" +#~ msgstr " '%s'" + +#~ msgid "" +#~ "multiple event tables supplied, not sure what to do; try 'c', 'rbind', " +#~ "'seq' or 'rep'" +#~ msgstr ";crbindseqrep" -#: lsoda.c:246 #, c-format -msgid "[lsoda] mxords = %d is less than 0\n" -msgstr "[lsoda] mxords = %d小于0\n" +#~ msgid "'%s' cannot be a vector" +#~ msgstr "'%s' " -#: lsoda.c:253 -msgid "[lsoda] hmax < 0.\n" -msgstr "[lsoda] hmax < 0.\n" +#~ msgid "nothing done" +#~ msgstr "" -#: lsoda.c:260 -msgid "[lsoda] hmin < 0.\n" -msgstr "[lsoda] hmin < 0.\n" +#, c-format +#~ msgid "cannot mix named and integer compartments in '%s'" +#~ msgstr " '%s' " -#: lsoda.c:490 #, c-format -msgid "unhandled error message: %s\n" -msgstr "未处理的错误消息: %s\n" +#~ msgid "'%s' compartment cannot be a vector" +#~ msgstr "%s" -#: lsoda.c:768 #, c-format -msgid "lsoda -- warning..internal t = %g and _rxC(h) = %g are\n" -msgstr "lsoda -- 警告..内部 t = %g 和 _rxC(h) = %g 是\n" +#~ msgid "'%s' cannot be zero" +#~ msgstr "'%s' " -#: lsoda.c:769 -msgid " such that in the machine, t + _rxC(h) = t on the next step\n" -msgstr " 这样在机器中,下一步的t _rxC(h) = t\n" +#, c-format +#~ msgid "'%s' cannot be an vector" +#~ msgstr "'%s' " -#: lsoda.c:770 -msgid " solver will continue anyway.\n" -msgstr " 无论如何,求解器将继续。\n" +#, c-format +#~ msgid "'%s' must be an integer or a character" +#~ msgstr "'%s' \"(integer)\"\"(character)\"" -#: lsoda.c:772 #, c-format -msgid "lsoda -- above warning has been issued %d times,\n" -msgstr "lsoda -- 以上警告已发出 %d 次,\n" +#~ msgid "turning off compartments can only be done when '%s'=2" +#~ msgstr " '%s' = 2 " -#: lsoda.c:773 -msgid " it will not be issued again for this problem\n" -msgstr " 不会因此问题再次发出\n" +#, c-format +#~ msgid "zero '%s' cannot be used with '%s'" +#~ msgstr "%s%s" -#: lsoda.c:805 -msgid "[lsoda] a switch to the stiff method has occurred " -msgstr "[LSODA] 已切换到刚性方法 " +#, c-format +#~ msgid "'%s' requires an '%s'" +#~ msgstr "%s%s" -#: lsoda.c:807 -msgid "[lsoda] a switch to the nonstiff method has occurred" -msgstr "[LSODA] 已切换到非刚性方法" +#, c-format +#~ msgid "'%s' is ignored when '%s'=2 or '%s'=3" +#~ msgstr "%s=2 %s=3 %s" -#: lsoda.c:808 #, c-format -msgid "at t = %g, tentative step size _rxC(h) = %g, step _rxC(nst) = %d\n" -msgstr "在 t = %g 时,暂定步长 _rxC(h) = %g,步长 _rxC(nst) = %d\n" +#~ msgid "'%s' needs a '%s'" +#~ msgstr "%s%s" -#: par_solve.cpp:2729 -msgid "'alag(.)'/'rate(.)'/'dur(.)' cannot depend on the state values" -msgstr "'alag(.)'/'rate(.)'/'dur(.)' 不能依赖于状态值" +#, c-format +#~ msgid "can not specify '%s' and '%s' for a dose, please pick one" +#~ msgstr "%s%s" -#: par_solve.cpp:2733 -msgid "could not solve the system" -msgstr "无法求解系统" +#~ msgid "'ii' needs a 'dose'/'amt'" +#~ msgstr "ii()dose()/amt()" -#: par_solve.cpp:2735 -msgid "some ID(s) could not solve the ODEs correctly; These values are replaced with 'NA'" -msgstr "某些 ID 无法正确求解常微分方程;这些值将替换为“NA”" +#~ msgid "dosing interval of zero makes no sense with multiple dose events" +#~ msgstr "" -#: par_solve.cpp:2807 #, c-format -msgid "one or more covariates were all 'NA' for subject 'id=%d'" -msgstr "一个或多个协变量都是“NA”,受试者“id=%d”" +#~ msgid "non-zero '%s' needs a '%s'" +#~ msgstr "'%s' '%s'" -#: par_solve.cpp:3230 #, c-format -msgid "dose to compartment %d ignored (not in system; 'id=%d')" -msgstr "忽略房室 %d 的给药(不在系统中;'id=%d')" +#~ msgid "can only specify '%s' or '%s', not both" +#~ msgstr "%s%s" -#: parseLinCmt.c:39 -msgid " with first order absorption\n" -msgstr " 具有一阶速率吸收\n" - -#: prja.c:42 -msgid "[prja] _rxC(miter) != 2\n" -msgstr "[prja] _rxC(miter) != 2\n" +#, c-format +#~ msgid "'%s' can only have one item" +#~ msgstr "'%s' " -#: rxData.cpp:296 -msgid "column(s) in 'drop' were not in solved data" -msgstr "“drop(丢弃)”中的列不在已求解的数据中" +#, c-format +#~ msgid "'%s' must be logical" +#~ msgstr "'%s' " -#: rxData.cpp:444 #, c-format -msgid "refusing to simulate %d items" -msgstr "拒绝模拟 %d 项" +#~ msgid "cannot specify '%s' and '%s' for a dose, please pick one" +#~ msgstr "%s%s" -#: rxData.cpp:451 -msgid "matrix must be a square matrix" -msgstr "矩阵必须是方阵" +#~ msgid "-1 and -2 rates do not make sense with units" +#~ msgstr "-1 -2 (rate)" -#: rxData.cpp:459 -msgid "matrix must have named dimensions (try 'lotri')" -msgstr "矩阵必须具有命名的维度(尝试“lotri”)" +#, c-format +#~ msgid "'%s' is cannot be converted and added to this table" +#~ msgstr "%s" -#: rxData.cpp:491 -msgid "lower bounds needs to be a named vector, a single value or exactly the same size" -msgstr "下限需要是命名向量、单个值或完全相同的大小" +#, c-format +#~ msgid "" +#~ "steady state constant infusion dosing records must have '%s=-1' or " +#~ "positive rate" +#~ msgstr "%s=-1(rate)" -#: rxData.cpp:511 -msgid "upper bounds needs to be a named vector, a single value or exactly the same size" -msgstr "上限必须是命名向量、单个值或完全相同的大小" +#, c-format +#~ msgid "'%s' cannot be converted and added to this table" +#~ msgstr "%s" -#: rxData.cpp:527 -msgid "t distribution not yet supported" -msgstr "尚不支持t分布" +#, c-format +#~ msgid "number of doses must be at least one ('%s': %d)" +#~ msgstr "%s %d" -#: rxData.cpp:807 -msgid "cannot figure out the model variables" -msgstr "无法计算出模型变量" +#, c-format +#~ msgid "'%s' can only be used with positive inter-dose intervals ('%s')" +#~ msgstr "%s%s" -#: rxData.cpp:837 rxData.cpp:855 -msgid "class:\t" -msgstr "class:\t" +#, c-format +#~ msgid "'%s' does not make sense with multiple dosing times" +#~ msgstr "'%s' " -#: rxData.cpp:843 rxData.cpp:861 -msgid "need an Rxode2-type object to extract model variables" -msgstr "需要一个 Rxode2 类型的对象来提取模型变量" +#~ msgid "dosing windows can only have 1-2 items in them" +#~ msgstr "1-2" -#: rxData.cpp:851 -msgid "a NULL object does not have any Rxode2 model variables" -msgstr "一个NULL对象没有任何 Rxode2 模型变量" +#, c-format +#~ msgid "" +#~ "'%s' requires non zero additional doses ('%s') or steady state dosing " +#~ "('%s': %f, '%s': %d; '%s': %d), reset '%s' to zero." +#~ msgstr "%s%s%s%f%s%d;%s %d%s" -#: rxData.cpp:896 -msgid "can only lookup one state at a time" -msgstr "一次只能查找一个状态" +#, c-format +#~ msgid "'%s' must be 1 when specifying a steady-state constant infusion" +#~ msgstr "'%s' 1" -#: rxData.cpp:899 -msgid "only one state variable should be input" -msgstr "只应输入一个状态变量" +#, c-format +#~ msgid "'%s' must be 0, 1 or 2" +#~ msgstr "'%s' 01 2" -#: rxData.cpp:909 #, c-format -msgid "cannot locate compartment \"%s\"" -msgstr "找不到区间“%s”" +#~ msgid "'%s' required with '%s'" +#~ msgstr "%s%s" -#: rxData.cpp:1148 -msgid "only one estimate per named list item; use 'list(x=1)' instead of 'list(x=1:2)'" -msgstr "每个命名\"list(列表)\"项只有一个估计值;使用“'list(x=1)”而不是“'list(x=1:2)”" +#, c-format +#~ msgid "'%s' cannot be used with steady state constant infusion" +#~ msgstr "'%s' " -#: rxData.cpp:1155 -msgid "incompatible initial estimate" -msgstr "不能共存的初始估计" +#, c-format +#~ msgid "steady state ('%s') is not supported with dosing windows" +#~ msgstr "'%s'" -#: rxData.cpp:1210 #, c-format -msgid "trying to scale the same compartment by 'scale=c(%s=%f,...)' and 'S%d=%f' choose one" -msgstr "尝试\"缩放(scale)\"相同房室通过“scale=c(%s=%f,...)”和“S%d=%f”选择一个" +#~ msgid "additional doses must be positive ('%s'=%d)" +#~ msgstr "'%s'=%d" -#: rxData.cpp:1221 #, c-format -msgid "trying to scale the same compartment by 'scale=c(%s=%f,...)' and 's%d=%f' choose one" -msgstr "尝试\"缩放(scale)\"相同房室通过“scale=c(%s=%f,...)”和“s%d=%f”选择一个" +#~ msgid "additional doses require an inter-dose interval ('%s')" +#~ msgstr "%s" -#: rxData.cpp:1245 -msgid "scaled a compartment that is not defined by the Rxode2 model" -msgstr "\"缩放(scale)\"了未由 Rxode2 模型定义的房室" +#, c-format +#~ msgid "for steady state infusions, you need %s=0, %s>0, %s=1, %s=0" +#~ msgstr " %s=0%s>0%s=1%s=0" -#: rxData.cpp:1374 -msgid "could not allocate memory for solving parameters" -msgstr "无法为求解参数分配内存" +#~ msgid "dosing time window lists can have 1-2 numeric entries in them" +#~ msgstr "1-2" -#: rxData.cpp:1418 -msgid "memory for residual errors could not be allocated" -msgstr "无为法残差分配内存" +#~ msgid "dosing window list needs to be numeric values only" +#~ msgstr "" -#: rxData.cpp:1425 -msgid "cannot allocate memory to simulate the residuals" -msgstr "无法分配内存用于模拟残差" +#~ msgid "cannot figure out what type of 'EventTable' you are trying to create" +#~ msgstr "" -#: rxData.cpp:1484 -msgid "'thetaMat' must be a named matrix" -msgstr "“thetaMat”必须是已命名的矩阵" +#~ msgid "cannot have event tables with integer and character 'cmt'" +#~ msgstr "cmt" -#: rxData.cpp:1492 rxData.cpp:2868 -msgid "'thetaMat' must be symmetric" -msgstr "“thetaMat”必须是对称的" +#, c-format +#~ msgid "" +#~ "assumed a dose interval of %.1f between event tables; use 'ii' to adjust" +#~ msgstr "%.1f;ii" -#: rxData.cpp:1513 -msgid "'thetaMat' is ignored since nStud <= 1" -msgstr "'thetaMat' 被忽略,因为 nStud <= 1" +#~ msgid "no events table found for 'seq'/'rep'/'rbind'/'c'" +#~ msgstr "seq/rep/rbind/c" -#: rxData.cpp:1553 -#, c-format -msgid "parameter '%s' was not simulated in 'thetaMat'" -msgstr "参数 '%s' 未在 'thetaMat' 中模拟" +#~ msgid "'wait' cannot be a vector" +#~ msgstr "wait" -#: rxData.cpp:1562 #, c-format -msgid "'%s' must be a named matrix" -msgstr "'%s' 必须是已命名的矩阵" +#~ msgid "" +#~ "negative compartments on non-ode 'cmt' (%s) does not make sense (id: %s, " +#~ "row: %d)" +#~ msgstr "non-ode 'cmt'%sID %s %d" -#: rxData.cpp:1572 #, c-format -msgid "'%s' must be symmetric" -msgstr "'%s' 必须是对称的" +#~ msgid "" +#~ "negative compartments on non-ode 'cmt' (%s) does not make sense (id: %s " +#~ "row: %d)" +#~ msgstr "non-ode 'cmt'%sID %s %d" -#: rxData.cpp:1692 -msgid "requires 'params'" -msgstr "需要“params(参数)”" +#~ msgid "should not reach here" +#~ msgstr "" -#: rxData.cpp:1697 -msgid "'params' must be a named vector" -msgstr "“params(参数)”必须是一个已命名的向量" +#~ msgid "cannot keep 'evid'; try 'addDosing'" +#~ msgstr "evid;adDosing" -#: rxData.cpp:1718 -msgid "multi-subject simulation without without 'omega'" -msgstr "多个体模拟时缺少'omega'" +#~ msgid "'time' is required in dataset" +#~ msgstr "time" -#: rxData.cpp:2069 -msgid "ran out of memory during 'updateSolveEnvPost'" -msgstr "在“updateSolveEnvPost”期间内存不足" +#~ msgid "steady state column ('ss') needs to be an integer" +#~ msgstr " 'ss' " -#: rxData.cpp:2399 -msgid "No additional parameters were specified, returning original object" -msgstr "未指定其他参数,返回原始对象" +#~ msgid "event id ('evid') needs to be an integer" +#~ msgstr "id'evid' " -#: rxData.cpp:2478 -msgid "can not update object" -msgstr "无法更新对象" +#~ msgid "missing DV ('mdv') needs to be an integer" +#~ msgstr "'mdv' " -#: rxData.cpp:2525 -msgid "'from' must be of length 1" -msgstr "“from”的长度必须为 1" +#~ msgid "missing dependent variable ('mdv') needs to be an integer" +#~ msgstr "'MDV' " -#: rxData.cpp:2533 -msgid "'to' must be of length 1" -msgstr "“to”的长度必须为 1" +#~ msgid "'rate' needs to be a number" +#~ msgstr "rate()" -#: rxData.cpp:2543 -msgid "'by' must be of length 1" -msgstr "“by”的长度必须为 1" +#~ msgid "'dur' needs to be a number" +#~ msgstr "dur()" -#: rxData.cpp:2551 -msgid "'length.out' must be of length 1" -msgstr "“length.out”的长度必须为 1" +#~ msgid "amount ('amt') needs to be a number" +#~ msgstr "amt" -#: rxData.cpp:2557 -msgid "cannot use both 'by' and 'length.out' for Rxode2 simulations" -msgstr "不能同时使用“by”和“length.out”进行Rxode2模拟" +#~ msgid "inter-dose interval ('ii') needs to be a number" +#~ msgstr "'ii' " -#: rxData.cpp:2654 -msgid "Rxode2 only supports 500 factors" -msgstr "Rxode2 仅支持 500 个因子" +#~ msgid "number of additional doses ('addl') needs to be an integer" +#~ msgstr "'addl' " -#: rxData.cpp:2797 -msgid "when specifying 'thetaMat', 'omega', or 'sigma' the parameters cannot be a 'data.frame'/'matrix'." -msgstr "当指定“thetaMat”、“omega”或“sigma”时,参数不能是“data.frame”/“matrix”。" +#~ msgid "dependent variable ('dv') needs to be a number" +#~ msgstr "'dv' " -#: rxData.cpp:2920 rxData.cpp:2943 rxData.cpp:2952 -msgid "if parameters are not named, they must match the order and size of the parameters in the model" -msgstr "如果未命名参数,则它们必须与模型中参数的顺序和大小匹配" +#~ msgid "censoring variable ('cens') needs to be a number" +#~ msgstr "cens" -#: rxData.cpp:3030 -msgid "can not allocate enough memory to load 'evid'" -msgstr "无法分配足够的内存来加载“evid”" +#~ msgid "limit variable ('limit') needs to be a number" +#~ msgstr "limit" -#: rxData.cpp:3074 -msgid "nothing to solve" -msgstr "没有什么可求解的" +#, c-format +#~ msgid "censoring column can only be -1, 0 or 1 (id: %s, row: %d)" +#~ msgstr " -10 1id %srow %d" -#: rxData.cpp:3128 -msgid "can not allocate memory for the covariates" -msgstr "无法为协变量分配内存" +#, c-format +#~ msgid "infinite times are not allowed (id: %s, row: %d)" +#~ msgstr "id %srow %d" -#: rxData.cpp:3215 -msgid "data must be ordered by 'ID' and 'TIME' variables" -msgstr "数据必须按“ID”和“TIME”变量排序" +#, c-format +#~ msgid "" +#~ "steady state records cannot be on negative compartments (id: %s, row: %d)" +#~ msgstr "id %srow %d" -#: rxData.cpp:3285 -msgid "cannot allocate enough memory to sort input parameters" -msgstr "无法分配足够的内存来对输入参数进行排序" +#, c-format +#~ msgid "" +#~ "when using steady state constant infusion modeling duration does not make " +#~ "sense (id: %s, row: %d)" +#~ msgstr "id %srow %d" -#: rxData.cpp:3416 -msgid "'resample' must be NULL or a character vector" -msgstr "“resample”(重采样)必须为 NULL 或字符向量" +#, c-format +#~ msgid "" +#~ "specifying duration with a steady state constant infusion makes no sense " +#~ "(id: %s row: %d)" +#~ msgstr "id %srow %d" -#: rxData.cpp:3525 -msgid "nPopPar != 1 but parameters are specified as a NumericVector" -msgstr "nPopPar != 1,但参数被指定为数字向量" +#, c-format +#~ msgid "" +#~ "specifying duration with a steady state constant infusion makes no sense " +#~ "(id: %d row: %d)" +#~ msgstr "id %d, row %d" -#: rxData.cpp:3636 -msgid "Something is wrong" -msgstr "有点不对劲" +#, c-format +#~ msgid "'rate' and/or 'dur' are not specified correctly (id: %d row: %d)" +#~ msgstr "rate/durid %srow %d" -#: rxData.cpp:3699 -msgid "aborted solve" -msgstr "中止求解" +#, c-format +#~ msgid "" +#~ "'amt' or 'dur'/'rate' are non-zero therefore MDV cannot = 0 (id: %s row: " +#~ "%d)" +#~ msgstr "amtdur/rateMDV= 0id %s, row %d" + +#~ msgid "'addl' is ignored with observations" +#~ msgstr "addl" -#: rxData.cpp:3723 #, c-format -msgid "exited from at least one while after %d iterations, (increase with `rxSolve(..., maxwhile=#)`)" -msgstr "在%d次迭代后至少一段时间退出,(增加' rxSolve(…,maxwhile = #)”)" +#~ msgid "'limit' (%f) cannot equal 'dv' (%f) id: %s row: %d" +#~ msgstr "limit%fdv%f id %s, row %d" -#: rxData.cpp:4066 -msgid "zero 'thetaMat' specified, no uncertainty in fixed effects" -msgstr "“thetaMat”指定为零,固定效应没有不确定性" +#, c-format +#~ msgid "'cmt' and 'dvid' specify different compartments (id: %s row: %d)" +#~ msgstr "cmtdvidid %s, row %d" -#: rxData.cpp:4069 -msgid "zero 'omega', no variability from random-effects" -msgstr "“omega”指定为零,没有来自于随即效应的变异" +#~ msgid "'DVID'/'CMT' translation:\n" +#~ msgstr "DVID/CMT:\n" -#: rxData.cpp:4072 -msgid "zero 'sigma', no unexplained variability" -msgstr "“sigma”指定为零,没有不确定性" +#, c-format +#~ msgid "" +#~ "'dvid'->'cmt' or 'cmt' on observation record on a undefined compartment " +#~ "(use 'cmt()' 'dvid()') id: %s row: %d" +#~ msgstr "'dvid'->'cmt' 'cmt' 'cmt()' 'dvid()' id %s row %d" -#: rxData.cpp:4090 -msgid "dropped key column, returning data.frame instead of special solved data.frame" -msgstr "丢弃的键列,返回data.frame而不是特殊已求解的data.frame" +#, c-format +#~ msgid "'mdv' cannot be 0 when 'evid'=1 id: %s row: %d" +#~ msgstr "evid=1,mdv 0id %s, row %d" -#: rxData.cpp:4285 -msgid "control list not setup correctly" -msgstr "控制列表设置不正确" +#~ msgid "'addl' is ignored with 'EVID=2'" +#~ msgstr "EVID=2addl" -#: rxData.cpp:4348 -msgid "cannot solve without event information" -msgstr "没有事件信息无法求解" +#~ msgid "'ss' is ignored with 'EVID=2'" +#~ msgstr "EVID=2ss" -#: rxData.cpp:4358 -msgid "cannot update this object" -msgstr "无法更新此对象" +#~ msgid "'addl' is ignored with 'EVID=3'" +#~ msgstr "EVID=2addl" -#: rxData.cpp:4414 -msgid "cannot load Rxode2 dlls for this model" -msgstr "无法加载此模型的 Rxode2 dll" +#~ msgid "'ss' is ignored with 'EVID=3'" +#~ msgstr "EVID=2ss" -#: rxData.cpp:4467 -msgid "thread safe method, but results may depend on system/load, using 1 core (can change with `cores=`)" -msgstr "线程安全方法,但结果可能取决于系统/负载,使用 1 个内核(可以使用“cores=”修改)" +#, c-format +#~ msgid "'mdv' cannot be 0 when 'evid'=4 id: %s row: %d" +#~ msgstr "evid=4mdv 0, id %s, row %d" -#: rxData.cpp:4478 rxData.cpp:4495 -msgid "not thread safe method, using 1 core" -msgstr "非线程安全方法,使用 1 个内核" +#, c-format +#~ msgid "" +#~ "cannot have an infusion event with a replacement event (id: %s row: %d)" +#~ msgstr "\"(replacement)\"id %s, row %d" -#: rxData.cpp:4487 -msgid "thread safe method, but results may depend on system/load" -msgstr "线程安全方法,但结果可能取决于系统/负载" +#, c-format +#~ msgid "" +#~ "cannot have an infusion event with a multiplication event (id: %s row: %d)" +#~ msgstr "\"(multiplication)\"id %s, row %d" -#: rxData.cpp:4551 -msgid "'infSSstep' needs to be positive" -msgstr "“infSSstep”需要是正数" +#~ msgid "'rate' or 'dur' is ignored with classic Rxode2 'EVID's" +#~ msgstr "ratedurRxode2 'EVID'" -#: rxData.cpp:4599 -msgid "assumed transit compartment model since 'podo' is in the model" -msgstr "假设是转移室模型,因为“podo”在模型中" +#~ msgid "'ss' is ignored with classic Rxode2 'EVID's" +#~ msgstr "ssRxode2 'EVID'" -#: rxData.cpp:4635 -msgid "unknown covariate interpolation specified" -msgstr "未知的协变量插值指定" +#, c-format +#~ msgid "'ss' with 'addl' not supported (id: %s row: %d)" +#~ msgstr "addlssid %s, row %d" -#: rxData.cpp:4726 #, c-format -msgid "number of parameters (%d) solved by Rxode2 for multi-subject data needs to be a multiple of the number of subjects (%d)" -msgstr "用于多个体数据通过Rxode2已求解的参数数量(%d),应是多个体量的倍数" +#~ msgid "'amt' value NA or 0 for dose event (id: %s row: %d)" +#~ msgstr "amtNA0id %s, row %d" -#: rxData.cpp:4844 -msgid "could not allocate enough memory for solving" -msgstr "无法分配足够的内存用于求解" +#, c-format +#~ msgid "" +#~ "'amt' value NA for dose event; (id: %s, amt: %f, evid: %d Rxode2 evid: " +#~ "%d, row: %d)" +#~ msgstr "amtNA;(id: %s, amt: %f, evid: %d Rxode2 evid: %d, row: %d)" -#: rxData.cpp:5237 -msgid "cannot update nonexistent parameters" -msgstr "无法更新不存在的参数" +#~ msgid "" +#~ "there are evid=3/4 records in an incorrectly sorted dataset, system is " +#~ "reset, but time is not reset" +#~ msgstr "evid=34" -#: rxData.cpp:5492 -msgid "Can not figure out the Rxode2 object" -msgstr "无法找出 Rxode2 对象" +#~ msgid "censoring missing 'DV' values do not make sense" +#~ msgstr "DV" -#: rxData.cpp:5597 rxData.cpp:5640 -msgid "can not figure out the DLL for this object" -msgstr "无法找出此对象的 DLL" +#~ msgid "no rows in event table or input data" +#~ msgstr "" -#: rxData.cpp:5828 -msgid "package-based models cannot be unloaded" -msgstr "无法\"卸载(unloaded)\"基于包的模型" +#~ msgid "empty data" +#~ msgstr "" -#: rxData.cpp:5875 -msgid "package-based models cannot be deleted" -msgstr "无法删除基于包的模型" +#~ msgid "while censoring is included in dataset, no observations are censored" +#~ msgstr "" -#: rxInv.cpp:34 -msgid "matrix seems singular; Using pseudo-inverse\n" -msgstr "矩阵似乎是单数;使用伪逆矩阵\n" +#~ msgid "'dv' and 'limit' swapped since 'limit' > 'dv'" +#~ msgstr "dvlimitlimit>dv" -#: rxInv.cpp:55 rxInv.cpp:59 -msgid "can not invert in 'rxToCholOmega'" -msgstr "不能在“rxToCholOmega”中反转" +#~ msgid "number of individuals not calculated correctly" +#~ msgstr "" -#: rxInv.cpp:126 -msgid "theta number must be positive for 'd(omegaInv)'" -msgstr "theta数量必须为'd(omegaInv)'的正数" +#~ msgid "corrupted event table" +#~ msgstr "" -#: rxInv.cpp:130 -msgid "theta number must be positive for 'd(D)'" -msgstr "theta数量必须为''d(D)'的正数" +#~ msgid "" +#~ "\n" +#~ "with negative times, compartments initialize at first negative observed " +#~ "time\n" +#~ "with positive times, compartments initialize at time zero\n" +#~ "use 'rxSetIni0(FALSE)' to initialize at first observed time\n" +#~ "this warning is displayed once per session" +#~ msgstr "" +#~ "\n" +#~ "\n" +#~ "0\n" +#~ "'rxSetIni0(FALSE)'\n" +#~ "" -#: rxInv.cpp:163 -msgid "error in 'rxSymInvCholEnvCalculate' environment" -msgstr "“rxSymInvCholEnvCalculate”环境中的报错" +#~ msgid "not an integer/real" +#~ msgstr "/" -#: rxInv.cpp:176 -msgid "theta for omega calculations not setup yet" -msgstr "用于omega计算的theta尚未设置" +#~ msgid "The dimensions of the parameters must match" +#~ msgstr "" -#: rxInv.cpp:274 -#, c-format -msgid "theta has to have %d elements" -msgstr "theta必须有 %d 个元素" +#~ msgid "'ncmt' needs to be 1-3" +#~ msgstr "ncmt 1~3" -#: rxInv.cpp:277 -msgid "Can only assign 'theta' in this environment" -msgstr "只能在此环境中分配“theta”" +#~ msgid "'inp' needs to be list/data frame" +#~ msgstr "inp\"(list)\"/\"(data frame)\"" -#: sbuf.c:165 #, c-format -msgid "encoding error in 'addLine' format: '%s' n: %d; errno: %d" -msgstr "“addLine”格式的编码错误:“%s”n:%d;errno: %d" +#~ msgid "invalid trans (2 cmt trans %d)\n" +#~ msgstr "\"trans()\"2 cmt trans %d\n" + +#, c-format +#~ msgid "one or more covariates were all 'NA' for subject 'id=%d'" +#~ msgstr "NAid=%d" + +#~ msgid " with first order absorption\n" +#~ msgstr " \n" -#: threefry.cpp:46 threefry.cpp:118 threefry.cpp:701 -msgid "n should be a positive integer" -msgstr "n 应为正整数" +#~ msgid "cannot figure out the model variables" +#~ msgstr "" -#: threefry.cpp:47 threefry.cpp:119 threefry.cpp:626 threefry.cpp:702 -msgid "'ncores' has to be greater than one" -msgstr "“ncores”必须大于 1" +#~ msgid "class:\t" +#~ msgstr "class:\t" + +#~ msgid "need an Rxode2-type object to extract model variables" +#~ msgstr " Rxode2 " -#: threefry.cpp:480 #, c-format -msgid "dimension wrong in 'gradpsi' (d=%d)" -msgstr "“gradpsi”(d=%d)中的维度数错误" +#~ msgid "'%s' must be symmetric" +#~ msgstr "'%s' " -#: threefry.cpp:582 -msgid "covariance matrix is ill-conditioned and method failed (truncated mvn)" -msgstr "协方差矩阵\"病态(ill-conditioned)\"且方法失败(截断多元正太分布)" +#~ msgid "requires 'params'" +#~ msgstr "params()" -#: threefry.cpp:628 -msgid "'lower' and 'upper' must have the same number of elements." -msgstr "“下”和“上”必须具有相同数量的元素。" +#~ msgid "cannot solve without event information" +#~ msgstr "" -#: threefry.cpp:629 -msgid "'sigma' must be a square matrix with the same dimension as 'upper' and 'lower'" -msgstr "“sigma”必须是与“上”和“下”维度相同的方阵" +#~ msgid "" +#~ "thread safe method, but results may depend on system/load, using 1 core " +#~ "(can change with `cores=`)" +#~ msgstr "/ 1 cores=" -#: threefry.cpp:631 -msgid "'lower' is bigger than 'upper' for at least one item" -msgstr "至少一项的“较低”大于“较高”" +#~ msgid "thread safe method, but results may depend on system/load" +#~ msgstr "/" -#: threefry.cpp:641 -msgid "truncated multivariate normal may fail as covariance matrix is singular" -msgstr "截断的多元正态可能会失败,因为协方差矩阵是奇异的" +#~ msgid "assumed transit compartment model since 'podo' is in the model" +#~ msgstr "podo" -#: threefry.cpp:678 -msgid "acceptance probability smaller than 0.001" -msgstr "接受概率小于 0.001" +#~ msgid "n should be a positive integer" +#~ msgstr "n " -#: threefry.cpp:681 -msgid "could not sample from truncated normal" -msgstr "无法从截断正态采样" +#~ msgid "'ncores' has to be greater than one" +#~ msgstr "ncores 1" -#: threefry.cpp:683 #, c-format -msgid "sample of size %d which is smaller than requested 'n' returned" -msgstr "返回的样本量 %d 小于请求的“n”" +#~ msgid "dimension wrong in 'gradpsi' (d=%d)" +#~ msgstr "gradpsid=%d" -#: threefry.cpp:1447 -msgid "when 'sigma' is a list, it has to have at least 1 element" -msgstr "当“sigma”是一个列表时,它必须至少有 1 个元素" +#~ msgid "" +#~ "covariance matrix is ill-conditioned and method failed (truncated mvn)" +#~ msgstr "\"(ill-conditioned)\"" -#: threefry.cpp:1450 -msgid "'sigma' must be a list of square symmetric matrices" -msgstr "“sigma”必须是包含有对称方阵的\"列表(list)\"" +#~ msgid "'lower' and 'upper' must have the same number of elements." +#~ msgstr "" -#: threefry.cpp:1461 -#, c-format -msgid "'sigma' list element %d does not match dimension of first matrix" -msgstr "“sigma”列表元素 %d 与第一个矩阵的维度数不匹配" +#~ msgid "" +#~ "'sigma' must be a square matrix with the same dimension as 'upper' and " +#~ "'lower'" +#~ msgstr "sigma" -#: threefry.cpp:1499 -msgid "'mu' length must match 'sigma' dimensions" -msgstr "“mu”长度必须与“sigma”维度数匹配" +#~ msgid "'lower' is bigger than 'upper' for at least one item" +#~ msgstr "" -#: threefry.cpp:1649 -msgid "'prob' function should return a vector the same length as the input" -msgstr "“prob”函数应返回与输入长度相同的向量" +#~ msgid "" +#~ "truncated multivariate normal may fail as covariance matrix is singular" +#~ msgstr "" -#: utilc.c:60 utilc.c:88 -msgid "'n' must be greater than 0" -msgstr "“n”必须大于 0" +#~ msgid "acceptance probability smaller than 0.001" +#~ msgstr " 0.001" -#: utilc.c:178 -msgid "'phi' requires numeric values" -msgstr "“phi”需要是数值" +#~ msgid "could not sample from truncated normal" +#~ msgstr "" -#: utilc.c:201 utilc.c:256 utilc.c:311 utilc.c:366 utilc.c:423 utilc.c:479 -#: utilc.c:535 utilc.c:593 utilc.c:655 -msgid "'a' needs to be a number" -msgstr "“a”需要是一个数字" +#, c-format +#~ msgid "sample of size %d which is smaller than requested 'n' returned" +#~ msgstr " %d n" -#: utilc.c:209 utilc.c:264 utilc.c:319 utilc.c:374 utilc.c:431 utilc.c:487 -#: utilc.c:543 utilc.c:601 utilc.c:663 -msgid "'z' needs to be a number" -msgstr "“z”需要是一个数字" +#~ msgid "when 'sigma' is a list, it has to have at least 1 element" +#~ msgstr "sigma 1 " -#: utilc.c:233 utilc.c:288 utilc.c:343 utilc.c:399 utilc.c:456 utilc.c:512 -#: utilc.c:568 utilc.c:629 utilc.c:691 -msgid "inconsistent sizes" -msgstr "不一致的大小" +#~ msgid "'sigma' must be a list of square symmetric matrices" +#~ msgstr "sigma\"(list)\"" -#: utilc.c:719 utilc.c:729 utilc.c:772 utilc.c:782 utilc.c:825 utilc.c:835 -#: utilc.c:879 utilc.c:889 -msgid "'low' must be a numeric of length 1" -msgstr "“low”必须是长度为 1 的数字" +#, c-format +#~ msgid "'sigma' list element %d does not match dimension of first matrix" +#~ msgstr "sigma %d " -#: utilc.c:722 utilc.c:736 utilc.c:775 utilc.c:789 utilc.c:828 utilc.c:842 -#: utilc.c:882 utilc.c:896 -msgid "'high' must be a numeric of length 1" -msgstr "“high”必须是长度为 1 的数字" +#~ msgid "'mu' length must match 'sigma' dimensions" +#~ msgstr "musigma" -#: utilc.c:739 utilc.c:792 utilc.c:845 utilc.c:899 -msgid "'high' must be greater than 'low'" -msgstr "“high”必须大于“low”" +#~ msgid "'prob' function should return a vector the same length as the input" +#~ msgstr "prob" + +#~ msgid "'n' must be greater than 0" +#~ msgstr "n 0" +#~ msgid "'phi' requires numeric values" +#~ msgstr "phi" diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index 00a4ac6d5..796b4ba1d 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -67,7 +67,7 @@ RcppExport SEXP _rxode2_rxExpandGrid_(SEXP c1SEXP, SEXP c2SEXP, SEXP typeSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -102,7 +102,7 @@ RcppExport SEXP _rxode2_rxExpandSens_(SEXP stateSEXP, SEXP calcSensSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -138,28 +138,29 @@ RcppExport SEXP _rxode2_rxExpandSens2_(SEXP stateSEXP, SEXP s1SEXP, SEXP s2SEXP) if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; } // rxExpandFEta_ -List rxExpandFEta_(CharacterVector state, int neta, int pred); -static SEXP _rxode2_rxExpandFEta__try(SEXP stateSEXP, SEXP netaSEXP, SEXP predSEXP) { +List rxExpandFEta_(CharacterVector state, int neta, int pred, bool isTheta); +static SEXP _rxode2_rxExpandFEta__try(SEXP stateSEXP, SEXP netaSEXP, SEXP predSEXP, SEXP isThetaSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::traits::input_parameter< CharacterVector >::type state(stateSEXP); Rcpp::traits::input_parameter< int >::type neta(netaSEXP); Rcpp::traits::input_parameter< int >::type pred(predSEXP); - rcpp_result_gen = Rcpp::wrap(rxExpandFEta_(state, neta, pred)); + Rcpp::traits::input_parameter< bool >::type isTheta(isThetaSEXP); + rcpp_result_gen = Rcpp::wrap(rxExpandFEta_(state, neta, pred, isTheta)); return rcpp_result_gen; END_RCPP_RETURN_ERROR } -RcppExport SEXP _rxode2_rxExpandFEta_(SEXP stateSEXP, SEXP netaSEXP, SEXP predSEXP) { +RcppExport SEXP _rxode2_rxExpandFEta_(SEXP stateSEXP, SEXP netaSEXP, SEXP predSEXP, SEXP isThetaSEXP) { SEXP rcpp_result_gen; { Rcpp::RNGScope rcpp_rngScope_gen; - rcpp_result_gen = PROTECT(_rxode2_rxExpandFEta__try(stateSEXP, netaSEXP, predSEXP)); + rcpp_result_gen = PROTECT(_rxode2_rxExpandFEta__try(stateSEXP, netaSEXP, predSEXP, isThetaSEXP)); } Rboolean rcpp_isInterrupt_gen = Rf_inherits(rcpp_result_gen, "interrupted-error"); if (rcpp_isInterrupt_gen) { @@ -174,7 +175,7 @@ RcppExport SEXP _rxode2_rxExpandFEta_(SEXP stateSEXP, SEXP netaSEXP, SEXP predSE if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -208,7 +209,7 @@ RcppExport SEXP _rxode2_rxRepR0_(SEXP netaSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -244,7 +245,7 @@ RcppExport SEXP _rxode2_rxExpandNesting(SEXP objSEXP, SEXP nestingInfoSEXP, SEXP if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -290,7 +291,7 @@ RcppExport SEXP _rxode2_rxIs(SEXP objSEXP, SEXP clsSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -324,7 +325,7 @@ RcppExport SEXP _rxode2_getRxFn(SEXP nameSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -358,7 +359,7 @@ RcppExport SEXP _rxode2_dynLoad(SEXP dllSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -392,7 +393,7 @@ RcppExport SEXP _rxode2_rxModelVars_(SEXP objSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -427,7 +428,7 @@ RcppExport SEXP _rxode2_rxState(SEXP objSEXP, SEXP stateSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -461,7 +462,7 @@ RcppExport SEXP _rxode2_rxParams_(SEXP objSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -495,7 +496,7 @@ RcppExport SEXP _rxode2_rxDfdy(SEXP objSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -529,7 +530,7 @@ RcppExport SEXP _rxode2_rxLhs(SEXP objSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -569,7 +570,7 @@ RcppExport SEXP _rxode2_rxInits(SEXP objSEXP, SEXP vecSEXP, SEXP reqSEXP, SEXP d if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -604,7 +605,7 @@ RcppExport SEXP _rxode2_rxSetupIni(SEXP objSEXP, SEXP initsSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -640,7 +641,7 @@ RcppExport SEXP _rxode2_rxSetupScale(SEXP objSEXP, SEXP scaleSEXP, SEXP extraArg if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -673,7 +674,7 @@ RcppExport SEXP _rxode2_atolRtolFactor_(SEXP factorSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -734,7 +735,7 @@ RcppExport SEXP _rxode2_rxSimThetaOmega(SEXP paramsSEXP, SEXP omegaSEXP, SEXP om if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -767,7 +768,7 @@ RcppExport SEXP _rxode2_rxSolveFree() { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -808,7 +809,7 @@ RcppExport SEXP _rxode2_rxSolve_(SEXP objSEXP, SEXP rxControlSEXP, SEXP specPara if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -842,7 +843,7 @@ RcppExport SEXP _rxode2_rxSolveDollarNames(SEXP objSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -878,7 +879,7 @@ RcppExport SEXP _rxode2_rxSolveGet(SEXP objSEXP, SEXP argSEXP, SEXP exactSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -914,7 +915,7 @@ RcppExport SEXP _rxode2_rxSolveUpdate(SEXP objSEXP, SEXP argSEXP, SEXP valueSEXP if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -955,7 +956,7 @@ RcppExport SEXP _rxode2_rxSolveSEXP(SEXP objSSEXP, SEXP rxControlSSEXP, SEXP spe if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -988,7 +989,7 @@ RcppExport SEXP _rxode2_rxRmModelLib_(SEXP strSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1022,7 +1023,7 @@ RcppExport SEXP _rxode2_rxGetrxode2(SEXP objSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1056,7 +1057,7 @@ RcppExport SEXP _rxode2_rxIsCurrent(SEXP objSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1089,7 +1090,7 @@ RcppExport SEXP _rxode2_rxAssignPtr(SEXP objectSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1123,7 +1124,7 @@ RcppExport SEXP _rxode2_rxDll(SEXP objSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1157,7 +1158,7 @@ RcppExport SEXP _rxode2_rxC(SEXP objSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1191,7 +1192,7 @@ RcppExport SEXP _rxode2_rxIsLoaded(SEXP objSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1225,7 +1226,7 @@ RcppExport SEXP _rxode2_rxDynLoad(SEXP objSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1259,7 +1260,7 @@ RcppExport SEXP _rxode2_rxLock(SEXP objSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1293,7 +1294,7 @@ RcppExport SEXP _rxode2_rxUnlock(SEXP objSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1327,7 +1328,7 @@ RcppExport SEXP _rxode2_rxAllowUnload(SEXP allowSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1360,7 +1361,7 @@ RcppExport SEXP _rxode2_rxUnloadAll_() { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1394,7 +1395,7 @@ RcppExport SEXP _rxode2_rxDynUnload(SEXP objSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1428,7 +1429,7 @@ RcppExport SEXP _rxode2_rxDelete(SEXP objSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1462,7 +1463,7 @@ RcppExport SEXP _rxode2_setRstudio(SEXP isRstudioSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1496,7 +1497,7 @@ RcppExport SEXP _rxode2_setProgSupported(SEXP isSupportedSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1529,7 +1530,7 @@ RcppExport SEXP _rxode2_getProgSupported() { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1565,7 +1566,7 @@ RcppExport SEXP _rxode2_rxUpdateTrans_(SEXP retSEXP, SEXP prefixSEXP, SEXP libNa if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1599,7 +1600,7 @@ RcppExport SEXP _rxode2_dropUnitsRxSolve(SEXP xSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1633,7 +1634,7 @@ RcppExport SEXP _rxode2_rxSetSilentErr(SEXP silentSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1667,7 +1668,7 @@ RcppExport SEXP _rxode2_rxInv(SEXP matrixSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1704,7 +1705,7 @@ RcppExport SEXP _rxode2_rxSymInvChol(SEXP invObjOrMatrixSEXP, SEXP thetaSEXP, SE if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1740,7 +1741,7 @@ RcppExport SEXP _rxode2_rxSymInvCholEnvCalculate(SEXP objSEXP, SEXP whatSEXP, SE if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1785,7 +1786,7 @@ RcppExport SEXP _rxode2_isNullZero(SEXP objSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1819,29 +1820,108 @@ RcppExport SEXP _rxode2_rxErf(SEXP vSEXP) { if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); + } + UNPROTECT(1); + return rcpp_result_gen; +} +// binomProbsPredVec_ +NumericVector binomProbsPredVec_(int n, int m, int Y, int M, bool doP, double tol); +static SEXP _rxode2_binomProbsPredVec__try(SEXP nSEXP, SEXP mSEXP, SEXP YSEXP, SEXP MSEXP, SEXP doPSEXP, SEXP tolSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::traits::input_parameter< int >::type n(nSEXP); + Rcpp::traits::input_parameter< int >::type m(mSEXP); + Rcpp::traits::input_parameter< int >::type Y(YSEXP); + Rcpp::traits::input_parameter< int >::type M(MSEXP); + Rcpp::traits::input_parameter< bool >::type doP(doPSEXP); + Rcpp::traits::input_parameter< double >::type tol(tolSEXP); + rcpp_result_gen = Rcpp::wrap(binomProbsPredVec_(n, m, Y, M, doP, tol)); + return rcpp_result_gen; +END_RCPP_RETURN_ERROR +} +RcppExport SEXP _rxode2_binomProbsPredVec_(SEXP nSEXP, SEXP mSEXP, SEXP YSEXP, SEXP MSEXP, SEXP doPSEXP, SEXP tolSEXP) { + SEXP rcpp_result_gen; + { + Rcpp::RNGScope rcpp_rngScope_gen; + rcpp_result_gen = PROTECT(_rxode2_binomProbsPredVec__try(nSEXP, mSEXP, YSEXP, MSEXP, doPSEXP, tolSEXP)); + } + Rboolean rcpp_isInterrupt_gen = Rf_inherits(rcpp_result_gen, "interrupted-error"); + if (rcpp_isInterrupt_gen) { + UNPROTECT(1); + Rf_onintr(); + } + bool rcpp_isLongjump_gen = Rcpp::internal::isLongjumpSentinel(rcpp_result_gen); + if (rcpp_isLongjump_gen) { + Rcpp::internal::resumeJump(rcpp_result_gen); + } + Rboolean rcpp_isError_gen = Rf_inherits(rcpp_result_gen, "try-error"); + if (rcpp_isError_gen) { + SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); + UNPROTECT(1); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); + } + UNPROTECT(1); + return rcpp_result_gen; +} +// binomProbs_ +NumericVector binomProbs_(NumericVector x, NumericVector probs, bool naRm, int nIn, int cont); +static SEXP _rxode2_binomProbs__try(SEXP xSEXP, SEXP probsSEXP, SEXP naRmSEXP, SEXP nInSEXP, SEXP contSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::traits::input_parameter< NumericVector >::type x(xSEXP); + Rcpp::traits::input_parameter< NumericVector >::type probs(probsSEXP); + Rcpp::traits::input_parameter< bool >::type naRm(naRmSEXP); + Rcpp::traits::input_parameter< int >::type nIn(nInSEXP); + Rcpp::traits::input_parameter< int >::type cont(contSEXP); + rcpp_result_gen = Rcpp::wrap(binomProbs_(x, probs, naRm, nIn, cont)); + return rcpp_result_gen; +END_RCPP_RETURN_ERROR +} +RcppExport SEXP _rxode2_binomProbs_(SEXP xSEXP, SEXP probsSEXP, SEXP naRmSEXP, SEXP nInSEXP, SEXP contSEXP) { + SEXP rcpp_result_gen; + { + Rcpp::RNGScope rcpp_rngScope_gen; + rcpp_result_gen = PROTECT(_rxode2_binomProbs__try(xSEXP, probsSEXP, naRmSEXP, nInSEXP, contSEXP)); + } + Rboolean rcpp_isInterrupt_gen = Rf_inherits(rcpp_result_gen, "interrupted-error"); + if (rcpp_isInterrupt_gen) { + UNPROTECT(1); + Rf_onintr(); + } + bool rcpp_isLongjump_gen = Rcpp::internal::isLongjumpSentinel(rcpp_result_gen); + if (rcpp_isLongjump_gen) { + Rcpp::internal::resumeJump(rcpp_result_gen); + } + Rboolean rcpp_isError_gen = Rf_inherits(rcpp_result_gen, "try-error"); + if (rcpp_isError_gen) { + SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); + UNPROTECT(1); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; } // meanProbs_ -NumericVector meanProbs_(NumericVector x, NumericVector probs, bool naRm, bool useT); -static SEXP _rxode2_meanProbs__try(SEXP xSEXP, SEXP probsSEXP, SEXP naRmSEXP, SEXP useTSEXP) { +NumericVector meanProbs_(NumericVector x, NumericVector probs, bool naRm, bool useT, bool pred, int nIn); +static SEXP _rxode2_meanProbs__try(SEXP xSEXP, SEXP probsSEXP, SEXP naRmSEXP, SEXP useTSEXP, SEXP predSEXP, SEXP nInSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::traits::input_parameter< NumericVector >::type x(xSEXP); Rcpp::traits::input_parameter< NumericVector >::type probs(probsSEXP); Rcpp::traits::input_parameter< bool >::type naRm(naRmSEXP); Rcpp::traits::input_parameter< bool >::type useT(useTSEXP); - rcpp_result_gen = Rcpp::wrap(meanProbs_(x, probs, naRm, useT)); + Rcpp::traits::input_parameter< bool >::type pred(predSEXP); + Rcpp::traits::input_parameter< int >::type nIn(nInSEXP); + rcpp_result_gen = Rcpp::wrap(meanProbs_(x, probs, naRm, useT, pred, nIn)); return rcpp_result_gen; END_RCPP_RETURN_ERROR } -RcppExport SEXP _rxode2_meanProbs_(SEXP xSEXP, SEXP probsSEXP, SEXP naRmSEXP, SEXP useTSEXP) { +RcppExport SEXP _rxode2_meanProbs_(SEXP xSEXP, SEXP probsSEXP, SEXP naRmSEXP, SEXP useTSEXP, SEXP predSEXP, SEXP nInSEXP) { SEXP rcpp_result_gen; { Rcpp::RNGScope rcpp_rngScope_gen; - rcpp_result_gen = PROTECT(_rxode2_meanProbs__try(xSEXP, probsSEXP, naRmSEXP, useTSEXP)); + rcpp_result_gen = PROTECT(_rxode2_meanProbs__try(xSEXP, probsSEXP, naRmSEXP, useTSEXP, predSEXP, nInSEXP)); } Rboolean rcpp_isInterrupt_gen = Rf_inherits(rcpp_result_gen, "interrupted-error"); if (rcpp_isInterrupt_gen) { @@ -1856,7 +1936,7 @@ RcppExport SEXP _rxode2_meanProbs_(SEXP xSEXP, SEXP probsSEXP, SEXP naRmSEXP, SE if (rcpp_isError_gen) { SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen); UNPROTECT(1); - Rf_error(CHAR(rcpp_msgSEXP_gen)); + Rf_error("%s", CHAR(rcpp_msgSEXP_gen)); } UNPROTECT(1); return rcpp_result_gen; @@ -1869,7 +1949,7 @@ static int _rxode2_RcppExport_validate(const char* sig) { signatures.insert("List(*rxExpandGrid_)(RObject&,RObject&,RObject&)"); signatures.insert("List(*rxExpandSens_)(CharacterVector,CharacterVector)"); signatures.insert("List(*rxExpandSens2_)(CharacterVector,CharacterVector,CharacterVector)"); - signatures.insert("List(*rxExpandFEta_)(CharacterVector,int,int)"); + signatures.insert("List(*rxExpandFEta_)(CharacterVector,int,int,bool)"); signatures.insert("std::string(*rxRepR0_)(int)"); signatures.insert("List(*rxExpandNesting)(const RObject&,List&,bool)"); signatures.insert("bool(*rxIs)(const RObject&,std::string)"); @@ -1916,7 +1996,9 @@ static int _rxode2_RcppExport_validate(const char* sig) { signatures.insert("RObject(*rxSymInvCholEnvCalculate)(List,std::string,Nullable)"); signatures.insert("LogicalVector(*isNullZero)(RObject)"); signatures.insert("NumericVector(*rxErf)(NumericVector)"); - signatures.insert("NumericVector(*meanProbs_)(NumericVector,NumericVector,bool,bool)"); + signatures.insert("NumericVector(*binomProbsPredVec_)(int,int,int,int,bool,double)"); + signatures.insert("NumericVector(*binomProbs_)(NumericVector,NumericVector,bool,int,int)"); + signatures.insert("NumericVector(*meanProbs_)(NumericVector,NumericVector,bool,bool,bool,int)"); } return signatures.find(sig) != signatures.end(); } @@ -1973,6 +2055,8 @@ RcppExport SEXP _rxode2_RcppExport_registerCCallable() { R_RegisterCCallable("rxode2", "_rxode2_rxSymInvCholEnvCalculate", (DL_FUNC)_rxode2_rxSymInvCholEnvCalculate_try); R_RegisterCCallable("rxode2", "_rxode2_isNullZero", (DL_FUNC)_rxode2_isNullZero_try); R_RegisterCCallable("rxode2", "_rxode2_rxErf", (DL_FUNC)_rxode2_rxErf_try); + R_RegisterCCallable("rxode2", "_rxode2_binomProbsPredVec_", (DL_FUNC)_rxode2_binomProbsPredVec__try); + R_RegisterCCallable("rxode2", "_rxode2_binomProbs_", (DL_FUNC)_rxode2_binomProbs__try); R_RegisterCCallable("rxode2", "_rxode2_meanProbs_", (DL_FUNC)_rxode2_meanProbs__try); R_RegisterCCallable("rxode2", "_rxode2_RcppExport_validate", (DL_FUNC)_rxode2_RcppExport_validate); return R_NilValue; diff --git a/src/approx.c b/src/approx.c index 0d9c3c993..1e8b33ced 100644 --- a/src/approx.c +++ b/src/approx.c @@ -81,7 +81,7 @@ static inline double getValue(int idx, double *y, rx_solving_options_ind *ind, r if (op->f2 == 1.0 && op->f1 == 0.0) { // use nocb // Go forward - while (ISNA(ret) && i != ind->n_all_times){ + while (ISNA(ret) && i != ind->n_all_times-1){ i++; ret = y[ind->ix[i]]; } if (ISNA(ret)){ @@ -309,4 +309,3 @@ void _update_par_ptr(double t, unsigned int id, rx_solve *rx, int idxIn) { /* void doSort(rx_solving_options_ind *ind); */ void sortInd(rx_solving_options_ind *ind); - diff --git a/src/expandGrid.cpp b/src/expandGrid.cpp index aa6fa8b88..addbfe5a4 100644 --- a/src/expandGrid.cpp +++ b/src/expandGrid.cpp @@ -22,7 +22,7 @@ std::string symengineRes(std::string val); //' @param c1 character vector of items to be expanded //' @param c2 second character vector of items to be expanded //' @param type 0 for a typical data frame, 1 for symengine sensitivity expansion -//' @return data frame (when type = 0) or symengine string (when type=1) +//' @return data frame (when type = 0) or symengine string (when type=1) //' @export //' @keywords internal //[[Rcpp::export]] @@ -39,10 +39,10 @@ List rxExpandGrid_(RObject &c1, RObject &c2, RObject &type){ int iType = as(type); if (iType == 0){ for (int i = lenF; i--;){ - i1 = i % len1; - i2 = std::floor(i / len1); - out1[i] = in1[i1]; - out2[i] = in2[i2]; + i1 = i % len1; + i2 = std::floor(i / len1); + out1[i] = in1[i1]; + out2[i] = in2[i2]; } List out(2); out[0] = out1; @@ -56,17 +56,17 @@ List rxExpandGrid_(RObject &c1, RObject &c2, RObject &type){ CharacterVector out4(lenF); CharacterVector out5(lenF); for (int i = lenF; i--;){ - i1 = i % len1; - i2 = std::floor(i / len1); - std::string s1 = as(in1[i1]); - std::string s2 = as(in2[i2]); - out1[i] = s1; - out2[i] = s2; - out3[i] = "df(" + s1 + ")/dy(" + s2 + ")"; - std::string sDf = "rx__df_" + s1 + "_dy_" + s2 + "__"; - out4[i] = sDf; - out5[i] = "assign(\"" + sDf + "\",with(model,D(rx__d_dt_" + - s1 + "__, \"" + symengineRes(s2) + "\")), envir=model)"; + i1 = i % len1; + i2 = std::floor(i / len1); + std::string s1 = as(in1[i1]); + std::string s2 = as(in2[i2]); + out1[i] = s1; + out2[i] = s2; + out3[i] = "df(" + s1 + ")/dy(" + s2 + ")"; + std::string sDf = "rx__df_" + s1 + "_dy_" + s2 + "__"; + out4[i] = sDf; + out5[i] = "assign(\"" + sDf + "\",with(model,D(rx__d_dt_" + + s1 + "__, \"" + symengineRes(s2) + "\")), envir=model)"; } List out(5); out[0] = out1; @@ -131,7 +131,7 @@ List rxExpandSens_(CharacterVector state, CharacterVector calcSens){ std::string curState2=as(state[j]); // sprintf("df(%s)/dy(%s)*rx__sens_%s_BY_%s__", s1, rxToSymPy(s2), s2, rxToSymPy(sns)) curLine += "rx__df_"+curState+"_dy_"+curState2+ - "__*rx__sens_"+curState2+"_BY_"+curSens+"__+"; + "__*rx__sens_"+curState2+"_BY_"+curSens+"__+"; } curLine += "rx__df_"+curState+ "_dy_"+curSens+"__),envir=model)"; line[i] = curLine; @@ -166,8 +166,8 @@ List rxExpandSens_(CharacterVector state, CharacterVector calcSens){ out[13] = FS; out[14] = FR; out.attr("names") = CharacterVector::create("ddt","ddtS","line","s0", "s0D","s0r", "ddS2", - "rateS","rateR", "durS","durR","lagS", "lagR", - "fS","fR"); + "rateS","rateR", "durS","durR","lagS", "lagR", + "fS","fR"); out.attr("class") = "data.frame"; out.attr("row.names") = IntegerVector::create(NA_INTEGER, -lenF); return out; @@ -217,9 +217,9 @@ List rxExpandSens2_(CharacterVector state, CharacterVector s1, CharacterVector s for (int j = len1; j--;){ std::string s2 = as(state[j]); curLine += "+D("+v1+",\""+symengineRes(s2)+"\")*rx__sens_"+s2+"_BY_"+cS1+ - "__+rx__sens_"+s2+"_BY_"+cS1+"_BY_"+cS2+ - "__*rx__df_"+ - cS + "_dy_"+s2+"__"; + "__+rx__sens_"+s2+"_BY_"+cS1+"_BY_"+cS2+ + "__*rx__df_"+ + cS + "_dy_"+s2+"__"; } curLine += "),envir=model)"; line[i] = curLine; @@ -240,22 +240,25 @@ List rxExpandSens2_(CharacterVector state, CharacterVector s1, CharacterVector s out.attr("names") = CharacterVector::create("ddt","ddtS","ddS2","line","s0r","s0D","s0"); out.attr("class") = "data.frame"; out.attr("row.names") = IntegerVector::create(NA_INTEGER, -lenF); - return out; + return out; } //' Expand d(f)/d(eta) //' //' @param state is the state to expand //' @param neta is the number of etas -//' @param pred type of prediction +//' @param pred type of prediction +//' @param isTheta logical, is the expansion actually for thetas instead of etas //' @keywords internal //' @return String of symengine expressions to evaluate to calculate df/deta //' @export //[[Rcpp::export]] -List rxExpandFEta_(CharacterVector state, int neta, int pred){ +List rxExpandFEta_(CharacterVector state, int neta, int pred, bool isTheta=false){ CharacterVector fe(neta); CharacterVector calcS(neta); int nstate = state.size(); + std::string th = ""; + if (isTheta) th = "TH"; for (int i = 0; i < neta; i++){ std::string etaN = std::to_string(i+1); std::string feta; @@ -263,35 +266,35 @@ List rxExpandFEta_(CharacterVector state, int neta, int pred){ switch(pred){ case 2: - feta = "rx__sens_rx_pred__BY_ETA_" + - etaN + "___"; - calc = "assign(\"" + feta + "\",with(.s,-D(rx_pred_, ETA_" + - etaN + "_)"; + feta = "rx__sens_rx_pred__BY_" + th + "ETA_" + + etaN + "___"; + calc = "assign(\"" + feta + "\",with(.s,-D(rx_pred_, " + th + "ETA_" + + etaN + "_)"; for (int j = nstate; j--;){ - calc += "-rx__sens_" + as(state[j]) + "_BY_ETA_" + etaN + - "___*D(rx_pred_,\""+ symengineRes(as(state[j])) + "\")"; + calc += "-rx__sens_" + as(state[j]) + "_BY_" + th + "ETA_" + etaN + + "___*D(rx_pred_,\""+ symengineRes(as(state[j])) + "\")"; } calc += "), envir=.s)"; break; case 1: - feta = "rx__sens_rx_pred__BY_ETA_" + - etaN + "___"; - calc = "assign(\"" + feta + "\",with(.s,D(rx_pred_, ETA_" + - etaN + "_)"; + feta = "rx__sens_rx_pred__BY_" + th + "ETA_" + + etaN + "___"; + calc = "assign(\"" + feta + "\",with(.s,D(rx_pred_, " + th + "ETA_" + + etaN + "_)"; for (int j = nstate; j--;){ - calc += "+rx__sens_" + as(state[j]) + "_BY_ETA_" + etaN + - "___*D(rx_pred_,"+ symengineRes(as(state[j])) + ")"; + calc += "+rx__sens_" + as(state[j]) + "_BY_" + th + "ETA_" + etaN + + "___*D(rx_pred_,"+ symengineRes(as(state[j])) + ")"; } calc += "), envir=.s)"; break; case 0: - feta = "rx__sens_rx_r__BY_ETA_" + - etaN + "___"; - calc = "assign(\"" + feta + "\",with(.s,D(rx_r_,ETA_" + - etaN + "_)"; + feta = "rx__sens_rx_r__BY_" + th + "ETA_" + + etaN + "___"; + calc = "assign(\"" + feta + "\",with(.s,D(rx_r_," + th +"ETA_" + + etaN + "_)"; for (int j = nstate; j--;){ - calc += "+rx__sens_" + as(state[j]) + "_BY_ETA_" + etaN + - "___*D(rx_r_,"+ symengineRes(as(state[j])) + ")"; + calc += "+rx__sens_" + as(state[j]) + "_BY_" + th + "ETA_" + etaN + + "___*D(rx_r_,"+ symengineRes(as(state[j])) + ")"; } calc += "), envir=.s)"; break; @@ -310,7 +313,7 @@ List rxExpandFEta_(CharacterVector state, int neta, int pred){ //' Rep R0 for foce //' -//' @param number ETA to substitute +//' @param neta ETA to substitute //' //' @return Returns a string of R code to substitute the rx_r expression in the symengine environment .s //' @@ -332,15 +335,15 @@ List rxModelVars_(const RObject &obj); // Expands nesting for theta/eta; // // @param thetaNest -// +// // @noRd void rxExpandNestingRep(CharacterVector &thetaNest, - CharacterVector &thetaNestTran, - CharacterVector &thetaNestFull, - int &thCnt, int &curtheta, - List &aboveVars, NumericVector& above, - std::string &retS, - List &data, std::string thetaVar = "THETA[") { + CharacterVector &thetaNestTran, + CharacterVector &thetaNestFull, + int &thCnt, int &curtheta, + List &aboveVars, NumericVector& above, + std::string &retS, + List &data, std::string thetaVar = "THETA[") { std::string theta; int lastTheta; int firstTheta = curtheta; @@ -356,14 +359,14 @@ void rxExpandNestingRep(CharacterVector &thetaNest, std::string curPar = as(nestVars[i]); retS += curPar + "="; for (int k = 0; k < nnest; ++k) { - theta = thetaVar + std::to_string(lastTheta+i+k*nnest+firstTheta) + "]"; - retS += "(" + curNest + "==" + std::to_string(k+1)+")*" + theta; - thetaNestTran[thCnt] = curPar + "(" + curNest + "==" + - as(curNestLvl[k])+")"; - thetaNestFull[thCnt] = theta; - curtheta++; thCnt++; - if (k != nnest-1) retS += "+"; - else retS += ";\n"; + theta = thetaVar + std::to_string(lastTheta+i+k*nnest+firstTheta) + "]"; + retS += "(" + curNest + "==" + std::to_string(k+1)+")*" + theta; + thetaNestTran[thCnt] = curPar + "(" + curNest + "==" + + as(curNestLvl[k])+")"; + thetaNestFull[thCnt] = theta; + curtheta++; thCnt++; + if (k != nnest-1) retS += "+"; + else retS += ";\n"; } } } @@ -373,7 +376,7 @@ void rxExpandNestingRep(CharacterVector &thetaNest, //[[Rcpp::export]] List rxExpandNesting(const RObject& obj, List& nestingInfo, - bool compile=false){ + bool compile=false){ std::string retS=""; List mv = rxModelVars_(obj); IntegerVector flags = as(mv["flags"]); @@ -414,23 +417,23 @@ List rxExpandNesting(const RObject& obj, List& nestingInfo, if (thetaNest.size() > 0) { rxExpandNestingRep(thetaNest, thetaNestTran, thetaNestFull, - thCnt, curtheta, aboveVars, above, retS, data, - "THETA["); + thCnt, curtheta, aboveVars, above, retS, data, + "THETA["); } else if (etaNest.size() == 0) { // const RObject& obj, List& nestingInfo, - // bool compile=false + // bool compile=false CharacterVector blank; blank.attr("names") = CharacterVector::create(); return List::create(_["mod"] = obj, - _["theta"] = blank, - _["eta"] = blank); + _["theta"] = blank, + _["eta"] = blank); } - + int etCnt = 0; rxExpandNestingRep(etaNest, etaNestTran, etaNestFull, - etCnt, cureta, - belowVars, below, retS, data, - "ETA["); + etCnt, cureta, + belowVars, below, retS, data, + "ETA["); CharacterVector mod = mv["model"]; List ret(3); retS += as(mod[0]); diff --git a/src/init.c b/src/init.c index 5ecee8f32..b76245d75 100644 --- a/src/init.c +++ b/src/init.c @@ -168,7 +168,7 @@ SEXP _rxode2_rxAllowUnload(SEXP); SEXP _rxode2_rxExpandGrid_(SEXP, SEXP, SEXP); SEXP _rxode2_rxExpandSens_(SEXP, SEXP); SEXP _rxode2_rxExpandSens2_(SEXP, SEXP, SEXP); -SEXP _rxode2_rxExpandFEta_(SEXP, SEXP, SEXP); +SEXP _rxode2_rxExpandFEta_(SEXP, SEXP, SEXP, SEXP); SEXP _rxode2_rxRepR0_(SEXP); SEXP _rxode2_rLKJ1(SEXP, SEXP, SEXP); SEXP _rxode2_rLKJcv1(SEXP, SEXP); @@ -224,7 +224,7 @@ void _update_par_ptr(double t, unsigned int id, rx_solve *rx, int idx); double _getParCov(unsigned int id, rx_solve *rx, int parNo, int idx); int par_progress(int c, int n, int d, int cores, clock_t t0, int stop); -void ind_solve(rx_solve *rx, unsigned int cid, t_dydt_liblsoda dydt_lls, +void ind_solve(rx_solve *rx, unsigned int cid, t_dydt_liblsoda dydt_lls, t_dydt_lsoda_dum dydt_lsoda, t_jdum_lsoda jdum, t_dydt c_dydt, t_update_inis u_inis, int jt); void par_solve(rx_solve *rx); @@ -282,7 +282,9 @@ SEXP _rxode2_trans(SEXP parse_file, SEXP prefix, SEXP model_md5, SEXP parseStr, SEXP isEscIn, SEXP inME, SEXP goodFuns, SEXP fullPrintIn); SEXP _rxode2_assignSeedInfo(void); SEXP _rxSetSeed(SEXP); -SEXP _rxode2_meanProbs_(SEXP x, SEXP probs, SEXP naRm, SEXP useT); +SEXP _rxode2_meanProbs_(SEXP x, SEXP probs, SEXP naRm, SEXP useT, SEXP pred, SEXP inN); +SEXP _rxode2_binomProbs_(SEXP x, SEXP probs, SEXP naRm, SEXP inN, SEXP cont); +SEXP _rxode2_binomProbsPredVec_(SEXP n, SEXP m, SEXP Y, SEXP M, SEXP doP, SEXP tol); typedef SEXP (*lotriMat_type) (SEXP, SEXP, SEXP); typedef SEXP (*asLotriMat_type) (SEXP, SEXP, SEXP); @@ -360,7 +362,9 @@ extern SEXP chin(SEXP x, SEXP table); SEXP _rxode2_RcppExport_registerCCallable(void); void R_init_rxode2(DllInfo *info){ R_CallMethodDef callMethods[] = { - {"_rxode2_meanProbs_", (DL_FUNC) &_rxode2_meanProbs_, 4}, + {"_rxode2_binomProbsPredVec_", (DL_FUNC) &_rxode2_binomProbsPredVec_, 6}, + {"_rxode2_binomProbs_", (DL_FUNC) &_rxode2_binomProbs_, 5}, + {"_rxode2_meanProbs_", (DL_FUNC) &_rxode2_meanProbs_, 6}, {"_rxode2_getEtRxsolve", (DL_FUNC) &_rxode2_getEtRxsolve, 1}, {"_rxode2_assignSeedInfo", (DL_FUNC) &_rxode2_assignSeedInfo, 0}, {"_rxProgress", (DL_FUNC) &_rxProgress, 2}, @@ -420,7 +424,7 @@ void R_init_rxode2(DllInfo *info){ {"_rxode2_rxExpandGrid_", (DL_FUNC) &_rxode2_rxExpandGrid_, 3}, {"_rxode2_rxExpandSens_", (DL_FUNC) &_rxode2_rxExpandSens_, 2}, {"_rxode2_rxExpandSens2_",(DL_FUNC) &_rxode2_rxExpandSens2_, 3}, - {"_rxode2_rxExpandFEta_", (DL_FUNC) &_rxode2_rxExpandFEta_, 3}, + {"_rxode2_rxExpandFEta_", (DL_FUNC) &_rxode2_rxExpandFEta_, 4}, {"_rxode2_rxRepR0_", (DL_FUNC) &_rxode2_rxRepR0_, 1}, {"_rxode2_rxOptRep_", (DL_FUNC) &_rxode2_rxOptRep_, 1}, {"_rxode2_rxSetSilentErr", (DL_FUNC) &_rxode2_rxSetSilentErr, 1}, @@ -494,14 +498,14 @@ void R_init_rxode2(DllInfo *info){ {"_rxSetSeed", (DL_FUNC) _rxSetSeed, 1}, {"_rxode2_rxordSelect", (DL_FUNC) _rxode2_rxordSelect, 2}, {"_rxode2_rxErf", (DL_FUNC) &_rxode2_rxErf, 1}, - {NULL, NULL, 0} + {NULL, NULL, 0} }; // C callable to assign environments. R_RegisterCCallable("rxode2", "_rxode2_rxModelVars_", (DL_FUNC) &_rxode2_rxModelVars_); R_RegisterCCallable("rxode2", "getSilentErr", (DL_FUNC) &getSilentErr); R_RegisterCCallable("rxode2", "logit", (DL_FUNC) &logit); R_RegisterCCallable("rxode2", "expit", (DL_FUNC) &expit); - + R_RegisterCCallable("rxode2", "powerDi", (DL_FUNC) &powerDi); R_RegisterCCallable("rxode2", "powerD", (DL_FUNC) &powerD); R_RegisterCCallable("rxode2", "powerDD", (DL_FUNC) &powerDD); @@ -516,10 +520,10 @@ void R_init_rxode2(DllInfo *info){ R_RegisterCCallable("rxode2", "_getParCov", (DL_FUNC) &_getParCov); R_RegisterCCallable("rxode2","rxRmModelLib", (DL_FUNC) &rxRmModelLib); R_RegisterCCallable("rxode2","rxGetModelLib", (DL_FUNC) &rxGetModelLib); - + R_RegisterCCallable("rxode2","rxode2_ode_free", (DL_FUNC) &rxode2_ode_free); - - //Functions + + //Functions R_RegisterCCallable("rxode2","rxode2_sum", (DL_FUNC) &rxode2_sum); R_RegisterCCallable("rxode2","rxode2_prod", (DL_FUNC) &rxode2_prod); diff --git a/src/matexp.f b/src/matexp.f index 00a94eaa4..c1a0eab28 100644 --- a/src/matexp.f +++ b/src/matexp.f @@ -21,7 +21,6 @@ SUBROUTINE DGEXX ( TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, * Error: Variable 'ldb' cannot appear in the expression at (1) * DOUBLE PRECISION A( LDA, * ), B( LDB, * ), C( LDC, * ) -* complex(kind=8) A( LDA, * ), B( LDB, * ), C( LDC, * ) * * .. diff --git a/src/par_solve.cpp b/src/par_solve.cpp index ad2a10fb0..31a828423 100644 --- a/src/par_solve.cpp +++ b/src/par_solve.cpp @@ -368,7 +368,7 @@ extern "C" SEXP _rxProgressAbort(SEXP str){ par_progress_0=0; if (rxt.d != rxt.n || rxt.cur != rxt.n){ rxSolveFreeC(); - Rf_errorcall(R_NilValue, CHAR(STRING_ELT(str,0))); + Rf_errorcall(R_NilValue, "%s", CHAR(STRING_ELT(str,0))); } return R_NilValue; } diff --git a/src/rxData.cpp b/src/rxData.cpp index 2f82efec4..265dca3d7 100644 --- a/src/rxData.cpp +++ b/src/rxData.cpp @@ -42,7 +42,7 @@ void resetSolveLinB(); using namespace Rcpp; using namespace arma; -typedef void (*seedEng_t)(uint32_t ncores); +typedef void (*seedEng_t)(int ncores); extern seedEng_t seedEng; #include "cbindThetaOmega.h" @@ -50,8 +50,6 @@ extern seedEng_t seedEng; #include "rxThreadData.h" //#include "seed.h" -extern "C" uint64_t dtwiddle(const void *p, int i); -extern "C" void calcNradix(int *nbyte, int *nradix, int *spare, uint64_t *maxD, uint64_t *minD); extern "C" void RSprintf(const char *format, ...); extern "C" int getRxThreads(const int64_t n, const bool throttle); extern "C" double *global_InfusionRate(unsigned int mx); @@ -65,6 +63,10 @@ extern "C" int getThrottle(); extern "C" int getRxThreads(const int64_t n, const bool throttle); extern "C" void rxode2_assign_fn_pointers_(const char *mv); extern "C" void setSilentErr(int silent); +extern "C" SEXP _rxode2parse_assignUdf(SEXP in); +extern "C" SEXP _rxode2parse_udfEnvSet(SEXP udf); +extern "C" SEXP _rxode2parse_udfReset(); +extern "C" SEXP _rxode2parse_rxC(SEXP in); extern "C" { typedef SEXP (*_rxode2parse_getForder_type)(void); @@ -731,7 +733,7 @@ List rxModelVars_character(const RObject &obj){ if (sobj == ""){ // Blank rxode2 model return rxModelVars_blank(); - } else if (fileExists(sobj)){ + } else if (fileExists(sobj)) { // From file Function f = getRxFn(".rxModelVarsCharacter"); return f(obj); @@ -1206,7 +1208,7 @@ NumericVector rxSetupIni(const RObject &obj, //' //' @param obj rxode2 object //' -//' @param inits A numeric vector of initial conditions. +//' @param scale A numeric vector scales //' //' @param extraArgs A list of extra args to parse for initial conditions. //' @@ -1776,12 +1778,12 @@ void rxSimOmega(bool &simOmega, defaultType = 3; } RObject ol = _rxode2_cvPost_(as(NumericVector::create(dfSub)), - as(omegaMC), - as(IntegerVector::create(1)), - as(LogicalVector::create(false)), - as(LogicalVector::create(false)), - as(IntegerVector::create(defaultType)), - as(IntegerVector::create(omegaXform))); + as(omegaMC), + as(IntegerVector::create(1)), + as(LogicalVector::create(false)), + as(LogicalVector::create(false)), + as(IntegerVector::create(defaultType)), + as(IntegerVector::create(omegaXform))); if (TYPEOF(ol) == VECSXP) { omegaList = ol; } else { @@ -1789,12 +1791,12 @@ void rxSimOmega(bool &simOmega, } } else { RObject ol = _rxode2_cvPost_(as(NumericVector::create(dfSub)), - as(omegaMC), - as(IntegerVector::create(nStud)), - as(LogicalVector::create(true)), - as(LogicalVector::create(false)), - as(IntegerVector::create(1)), - as(IntegerVector::create(1))); + as(omegaMC), + as(IntegerVector::create(nStud)), + as(LogicalVector::create(true)), + as(LogicalVector::create(false)), + as(IntegerVector::create(1)), + as(IntegerVector::create(1))); if (TYPEOF(ol) == VECSXP) { omegaList = ol; } else { @@ -2142,15 +2144,22 @@ List rxSimThetaOmega(const Nullable ¶ms = R_NilValue, } if (_globals.gsigma != NULL) free(_globals.gsigma); rx->neps = sigma0.n_rows; - _globals.gsigma = (double*)malloc((rx->neps * rx->neps + 2 * rx->neps)* sizeof(double)); - std::copy(&sigma0[0], &sigma0[0] + rx->neps * rx->neps, _globals.gsigma + 2 * rx->neps); + if (rx->neps > 0) { + _globals.gsigma = (double*)malloc((rx->neps * rx->neps + 2 * rx->neps)* sizeof(double)); + std::copy(&sigma0[0], &sigma0[0] + rx->neps * rx->neps, + _globals.gsigma + 2 * rx->neps); + } else { + _globals.gsigma = NULL; + } _globals.nSigma = 0; } arma::vec in = as(sigmaLower); arma::vec lowerSigmaV = fillVec(in, sigma0.n_rows); arma::vec upperSigmaV = fillVec(in, sigma0.n_rows); - std::copy(&lowerSigmaV[0], &lowerSigmaV[0] + rx->neps, _globals.gsigma); - std::copy(&upperSigmaV[0], &upperSigmaV[0] + rx->neps, _globals.gsigma + rx->neps); + if (rx->neps > 0) { + std::copy(&lowerSigmaV[0], &lowerSigmaV[0] + rx->neps, _globals.gsigma); + std::copy(&upperSigmaV[0], &upperSigmaV[0] + rx->neps, _globals.gsigma + rx->neps); + } // structure of _globals.gsigma is // lower // upper @@ -2474,6 +2483,7 @@ void resetFkeep(); //' @export // [[Rcpp::export]] LogicalVector rxSolveFree(){ + _rxode2parse_udfReset(); resetFkeep(); rx_solve* rx = getRxSolve_(); // Free the solve id order @@ -2486,7 +2496,7 @@ LogicalVector rxSolveFree(){ _globals.gomega = NULL; if (_globals.gsigma != NULL) free(_globals.gsigma); _globals.gsigma = NULL; - + _globals.zeroTheta = false; _globals.zeroOmega = false; _globals.zeroSigma = false; @@ -2624,6 +2634,19 @@ extern "C" SEXP get_fkeepLevels(int col) { return wrap(cur[1]); } +extern "C" SEXP assign_fkeepAttr(int col, SEXP in) { + List cur = keepFcovType[col]; + List attr = cur[2]; + RObject curRO = as(in); + CharacterVector attrN = attr.names(); + for (unsigned int i = 0; i < attr.size(); i++) { + std::string curAttr = as(attrN[i]); + curRO.attr(curAttr) = attr[i]; + } + return wrap(curRO); +} + + extern "C" SEXP get_fkeepChar(int col, double val) { List cur = keepFcovType[col]; StringVector levels = cur[1]; @@ -2705,6 +2728,7 @@ struct rxSolve_t { bool convertInt = false; bool throttle = false; int maxItemsPerId = 0; + bool hasICov = false; }; SEXP rxSolve_(const RObject &obj, const List &rxControl, const Nullable &specParams, @@ -2832,6 +2856,9 @@ static inline void rxSolve_ev1Update(const RObject &obj, int nobs = asInt(etE["nobs"], "nobs"); if (nobs == 0){ // KEEP/DROP? + if (rxSolveDat->hasICov) { + Rf_warningcall(R_NilValue, "'iCov' ignored when there are no samples/observations in the input dataset"); + } List ev1a = etTrans(as(ev1), obj, rxSolveDat->hasCmt, false, false, true, R_NilValue, rxControl[Rxc_keepF], @@ -4403,7 +4430,6 @@ static inline SEXP rxSolve_finalize(const RObject &obj, #ifdef rxSolveT clock_t _lastT0 = clock(); #endif - rxSolveSaveRxSolve(rxSolveDat); rx_solve* rx = getRxSolve_(); // if (rxSolveDat->throttle){ @@ -4673,6 +4699,7 @@ SEXP rxSolve_(const RObject &obj, const List &rxControl, rxSolve_t rxSolveDat0; rxSolve_t* rxSolveDat = &rxSolveDat0; RObject object; + rxSolveDat->hasICov = !Rf_isNull(rxControl[Rxc_iCov]); rxSolveDat->updateObject = asBool(rxControl[Rxc_updateObject], "updateObject"); rxSolveDat->isRxSolve = rxIs(obj, "rxSolve"); rxSolveDat->isEnvironment = rxIs(obj, "environment"); @@ -4694,7 +4721,7 @@ SEXP rxSolve_(const RObject &obj, const List &rxControl, } getRxModels(); bool didNesting=false; - if (rxSolveDat->updateObject && !rxSolveDat->isRxSolve && !rxSolveDat->isEnvironment){ + if (rxSolveDat->updateObject && !rxSolveDat->isRxSolve && !rxSolveDat->isEnvironment) { if (rxIs(rxCurObj, "rxSolve")){ object = rxCurObj; rxSolveDat->isRxSolve = true; @@ -4737,6 +4764,16 @@ SEXP rxSolve_(const RObject &obj, const List &rxControl, rxSolveFreeObj = object; } } + + _rxode2parse_udfEnvSet(rxSolveDat->mv[RxMv_udf]); + LogicalVector recompileUdf = _rxode2parse_assignUdf(rxSolveDat->mv[RxMv_udf]); + + if (recompileUdf[0]) { + Function rxode2 = getRxFn("rxode2"); + object = rxode2(object); + rxSolveDat->mv = rxModelVars(object); + rxSolveFreeObj = object; + } if (rxSolveDat->isRxSolve || rxSolveDat->isEnvironment){ rx_solve* rx = getRxSolve_(); iniRx(rx); @@ -4856,7 +4893,7 @@ SEXP rxSolve_(const RObject &obj, const List &rxControl, warning(_("since throwing warning with NA time, change to single threaded")); op->cores=1; } - seedEng(op->cores); + seedEng((int)(op->cores)); if (_globals.pendingDoses != NULL) { int i=0; while (_globals.pendingDoses[i] != NULL){ @@ -6213,7 +6250,11 @@ CharacterVector rxC(RObject obj){ rets = as(e["c"]); } else if (rxIs(obj, "rxDll")){ rets = as(as(obj)["c"]); - } else if (rxIs(obj, "character")){ + } else if (rxIs(obj, "character")) { + Nullable rxCp = _rxode2parse_rxC(obj); + if (!rxCp.isNull()) { + return as(rxCp); + } Function f = getRxFn("rxCompile.character"); RObject newO = f(as(obj)); rets = rxDll(newO); diff --git a/src/rxData.h b/src/rxData.h index d0717ce3f..8ae91a094 100644 --- a/src/rxData.h +++ b/src/rxData.h @@ -7,6 +7,7 @@ extern "C" { double get_fkeep(int col, int id, rx_solving_options_ind *ind); int get_fkeepType(int col); SEXP get_fkeepLevels(int col); + SEXP assign_fkeepAttr(int col, SEXP in); SEXP get_fkeepChar(int col, double val); double *getLlikSave(void); SEXP get_fkeepn(void); @@ -34,7 +35,7 @@ extern "C" { int isProgSupported(void); void updateExtraDoseGlobals(rx_solving_options_ind* ind); - + #if defined(__cplusplus) } #endif diff --git a/src/rxode2_df.cpp b/src/rxode2_df.cpp index bf61bc0a2..4a1754c0a 100644 --- a/src/rxode2_df.cpp +++ b/src/rxode2_df.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include "checkmate.h" #include // for uint64_t rather than unsigned long long #include "../inst/include/rxode2.h" @@ -293,16 +294,18 @@ extern "C" SEXP rxode2_df(int doDose0, int doTBS) { i++) { int curType = get_fkeepType(j); if (curType == 4) { - df[i] = NumericVector(rx->nr); + df[i] = assign_fkeepAttr(j, NumericVector(rx->nr)); } else if (curType == 1) { + df[i] = assign_fkeepAttr(j, StringVector(rx->nr)); df[i] = StringVector(rx->nr); + } else if (curType == 5) { + df[i] = assign_fkeepAttr(j, LogicalVector(rx->nr)); } else { IntegerVector cur(rx->nr); if (curType == 2) { cur.attr("levels") = get_fkeepLevels(j); - cur.attr("class") = "factor"; } - df[i] = cur; + df[i] = assign_fkeepAttr(j,cur); } j++; } @@ -746,11 +749,25 @@ extern "C" SEXP rxode2_df(int doDose0, int doTBS) { dfp[ii] = get_fkeep(j, curi + ind->ix[i], ind); } else if (TYPEOF(tmp) == STRSXP){ SET_STRING_ELT(tmp, ii, get_fkeepChar(j, get_fkeep(j, curi + ind->ix[i], ind))); + } else if (TYPEOF(tmp) == LGLSXP) { + // Everything here is double + dfi = LOGICAL(tmp); + double curD = get_fkeep(j, curi + ind->ix[i], ind); + if (ISNA(curD) || std::isnan(curD)) { + dfi[ii] = NA_LOGICAL; + } else { + dfi[ii] = (int) (curD); + } } else { dfi = INTEGER(tmp); /* if (j == 0) RSprintf("j: %d, %d; %f\n", j, i, get_fkeep(j, curi + i)); */ // is this ntimes = nAllTimes or nObs time for this subject...? - dfi[ii] = (int) (get_fkeep(j, curi + ind->ix[i], ind)); + double curD = get_fkeep(j, curi + ind->ix[i], ind); + if (ISNA(curD) || std::isnan(curD)) { + dfi[ii] = NA_INTEGER; + } else { + dfi[ii] = (int) (curD); + } } jj++; } @@ -951,7 +968,7 @@ extern "C" SEXP rxode2_df(int doDose0, int doTBS) { jj++;kk++; } // Put in state names - CharacterVector stateNames2 = rxStateNames(op->modNamePtr); + CharacterVector stateNames2 = rxStateNames(op->modNamePtr); if (nPrnState){ for (j = 0; j < neq[0]; j++){ if (!rmState[j]){ diff --git a/src/rxode2parse.cpp b/src/rxode2parse.cpp index 2f9f23949..6e6c06ac3 100644 --- a/src/rxode2parse.cpp +++ b/src/rxode2parse.cpp @@ -76,6 +76,63 @@ extern "C" SEXP _rxode2_codeLoaded(void) { END_RCPP } +extern "C" SEXP _rxode2parse_rxC(SEXP in) { +BEGIN_RCPP + if (TYPEOF(in) != STRSXP) return R_NilValue; + assignRxode2ParsePtrs(); + Function fun = as(rxode2parse[".rxC"]); + return wrap(fun(in)); +END_RCPP +} + +extern "C" SEXP _rxode2parse_assignUdf(SEXP in) { +BEGIN_RCPP + if (Rf_length(in) == 0 || Rf_length(in) == 1) { + return wrap(LogicalVector::create(false)); + } + if (TYPEOF(in) != INTSXP) { + return wrap(LogicalVector::create(false)); + } + if (Rf_isNull(Rf_getAttrib(in, R_NamesSymbol))) { + return wrap(LogicalVector::create(false)); + } + assignRxode2ParsePtrs(); + Function fun = as(rxode2parse[".setupUdf"]); + LogicalVector needRecompile = fun(in); + return wrap(needRecompile); +END_RCPP +} + +extern "C" SEXP _rxode2parse_udfEnvSet(SEXP udf) { +BEGIN_RCPP + if (Rf_isNull(udf)) { + return R_NilValue; + } + if (Rf_length(udf) == 0 || Rf_length(udf) == 1) { + return R_NilValue; + } + if (TYPEOF(udf) != INTSXP) { + return R_NilValue; + } + if (Rf_isNull(Rf_getAttrib(udf, R_NamesSymbol))) { + return R_NilValue; + } + assignRxode2ParsePtrs(); + Function fun = as(rxode2parse[".udfEnvSetUdf"]); + fun(udf); + return R_NilValue; + END_RCPP +} + +extern "C" SEXP _rxode2parse_udfReset() { + BEGIN_RCPP + assignRxode2ParsePtrs(); + Function fun2 = as(rxode2parse[".udfEnvReset"]); + fun2(); + return R_NilValue; + END_RCPP +} + extern "C" SEXP _rxode2_codegen(SEXP c_file, SEXP prefix, SEXP libname, SEXP pMd5, SEXP timeId, SEXP lastMv, SEXP goodFuns) { BEGIN_RCPP assignRxode2ParsePtrs(); diff --git a/src/utilcpp.cpp b/src/utilcpp.cpp index af77f7f9c..534368369 100644 --- a/src/utilcpp.cpp +++ b/src/utilcpp.cpp @@ -15,7 +15,7 @@ using namespace Rcpp; using namespace arma; -extern "C" SEXP _rxode2_isNullZero(SEXP); +extern "C" SEXP _rxode2_isNullZero(SEXP); //[[Rcpp::export]] LogicalVector isNullZero(RObject obj) { @@ -131,8 +131,182 @@ NumericVector rxErf(NumericVector v) { #define min2( a , b ) ( (a) < (b) ? (a) : (b) ) #define max2( a , b ) ( (a) > (b) ? (a) : (b) ) +double binomProbsLimF(double theta, double w, int n, int Y, double U) { + return w*Rf_pbeta(1-theta, n-Y+1, Y, 1, 0) + (1-w)*Rf_pbeta(1-theta, n-Y, Y+1, 1, 0) - U; +} + +//[[Rcpp::export]] +NumericVector binomProbsPredVec_(int n, int m, int Y, int M, bool doP=true, double tol=1e-7) { + NumericVector ret(M); + for (int i = 0; i < M; i++) { + double w = unif_rand(); + double U = unif_rand(); + double V = unif_rand(); + // root finding using bisection + double x0 = 0.0, x1 = 1.0; + double root = -1.0; + double f0 = binomProbsLimF(x0, w, n, Y, U); + if (f0 == 0) root = x0; + double f1 = binomProbsLimF(x1, w, n, Y, U); + if (f1 == 0) root = x1; + if (root == -1.0) { + double xc, fc; + for (;;) { + xc = 0.5*(x0+x1); + if(fabs(x0-x1) < tol) { + root = xc; + break; + } + fc = binomProbsLimF(xc, w, n, Y, U); + if(fabs(fc) < tol) { + root = xc; + break; + } + if(f0*fc > 0.0) { + x0 = xc; f0 = fc; + } else { + x1 = xc; f1 = fc; + } + } + } + if (doP) { + ret[i] = Rf_qbinom(V, m, root, 1, 0)/m; + } else { + ret[i] = Rf_qbinom(V, m, root, 1, 0); + } + } + return ret; +} + //[[Rcpp::export]] -NumericVector meanProbs_(NumericVector x, NumericVector probs, bool naRm, bool useT) { +NumericVector binomProbs_(NumericVector x, NumericVector probs, bool naRm, int nIn, + int cont) { + double oldM = 0.0, newM = 0.0; + int n = 0; + for (int i = 0; i < x.size(); ++i) { + double cur = x[i]; + if (ISNA(cur)) { + if (naRm) { + continue; + } else { + NumericVector ret(4+probs.size()); + for (int j = 0; j < ret.size(); ++j) { + ret[j] = NA_REAL; + } + return ret; + } + } + n++; + if (n == 1) { + oldM = newM = cur; + } else { + newM = oldM + (cur - oldM)/n; + oldM = newM; + } + } + int nC; + if (nIn == 0) { + nC = n; + } else { + nC = nIn; + } + double var=0; + double sd=0; + if (n > 1) { + var = oldM*(1.0-oldM); + sd = sqrt(var); + } else { + var = 0.0; + sd = 0.0; + } + // mean, var, sd + NumericVector ret(4+probs.size()); + ret[0] = oldM; + ret[1] = var; + ret[2] = sd; + ret[3] = (double)n; + + for (int i = 0; i < probs.size(); ++i) { + double p = probs[i]; + std::string str = std::to_string(p*100) + "%"; + if (p == 0) { + ret[i+4] = 0; + } else if (p == 1) { + ret[i+4] = 1; + } else if (p == 0.5) { + ret[i+4] = oldM; + } else { + double z; + if (p > 0.5) { + z = Rf_qnorm5(p, 0.0, 1.0, 1, 0); + } else { + z = Rf_qnorm5(1.0-p, 0.0, 1.0, 1, 0); + } + double z2 = z*z; + double c1, c2, c3, ns, nh, ph; +#define contWilsonContinuityCorrection 0 +#define contWilson 1 +#define contWald 2 +#define contAgrestiCoull 3 + switch (cont) { + case contWilsonContinuityCorrection: + c1 = 2*nC*oldM + z2; + c2 = z*sqrt(z2 - 1.0/nC + 4*nC*var + (4*oldM-2))+1.0; + c3 = 2*(nC+z2); + if (p < 0.5) { + if (p == 0.0) { + ret[i+4] = 0.0; + } else { + ret[i+4] = max2(0, (c1-c2)/c3); + } + } else { + if (p == 1.0) { + ret[i+4] = 1.0; + } else { + ret[i+4] = min2(1, (c1+c2)/c3); + } + } + break; + case contWilson: + c1 = 1.0/(1.0+z2/nC)*(oldM+z2/(2.0*nC)); + c2 = z/(1.0+z2/nC)*sqrt(oldM*(1.0-oldM)/nC + z2/(4.0*nC*nC)); + if (p < 0.5) { + ret[i+4] = c1-c2; + } else { + ret[i+4] = c1+c2; + } + break; + case contWald: + c1 = oldM; + c2 = z*sqrt(oldM*(1-oldM)/nC); + if (p < 0.5) { + ret[i+4] = c1-c2; + } else { + ret[i+4] = c1+c2; + } + break; + case contAgrestiCoull: + // p = ns/n; p*n = ns + ns = oldM*nC; + nh = nC+z2; + ph = 1/nh*(ns+z2/2.0); + c1 = ph; // ns + c2 = z*sqrt(ph/nh*(1-ph)); + if (p < 0.5) { + ret[i+4] = c1-c2; + } else { + ret[i+4] = c1+c2; + } + break; + } + } + } + return ret; +} + +//[[Rcpp::export]] +NumericVector meanProbs_(NumericVector x, NumericVector probs, bool naRm, bool useT, + bool pred, int nIn) { double oldM = 0.0, newM = 0.0, oldS = 0.0, newS = 0.0, mx=R_NegInf, mn=R_PosInf; int n = 0; @@ -177,7 +351,18 @@ NumericVector meanProbs_(NumericVector x, NumericVector probs, bool naRm, bool u ret[3] = mn; ret[4] = mx; ret[5] = (double)n; - double c = sd/sqrt((double)(n)); + double c; + int nC; + if (nIn == 0) { + nC = n; + } else { + nC = nIn; + } + if (pred) { + c = sd*sqrt(1.0+(1.0/nC)); + } else { + c = sd/sqrt((double)(nC)); + } for (int i = 0; i < probs.size(); ++i) { double p = probs[i]; std::string str = std::to_string(p*100) + "%"; @@ -188,7 +373,7 @@ NumericVector meanProbs_(NumericVector x, NumericVector probs, bool naRm, bool u } else if (p == 0.5) { ret[i+6] = oldM; } else if (useT) { - ret[i+6] = oldM + c * Rf_qt(p, (double)(n-1), 1, 0); + ret[i+6] = oldM + c * Rf_qt(p, (double)(nC-1), 1, 0); } else { ret[i+6] = oldM + c * Rf_qnorm5(p, 0.0, 1.0, 1, 0); } diff --git a/tests/testthat/test-backward.R b/tests/testthat/test-backward.R index b1e175ff5..0b1a0b774 100644 --- a/tests/testthat/test-backward.R +++ b/tests/testthat/test-backward.R @@ -1,4 +1,5 @@ rxTest({ + ## Dynmodel routines ode <- " dose=200; @@ -169,7 +170,6 @@ rxTest({ x$add.sampling(0.5) expect_equal(as.numeric(x$time[2]), 0.5) }) - x <- solve(mod1, theta, ev, inits) test_that("Add dosing makes sense", { diff --git a/tests/testthat/test-binomProb.R b/tests/testthat/test-binomProb.R new file mode 100644 index 000000000..d6a604d6a --- /dev/null +++ b/tests/testthat/test-binomProb.R @@ -0,0 +1,154 @@ +test_that("test binomProb()", { + + x <- rbinom(1001, 1, prob = 0.05) + m <- mean(x) + v <- m * (1 - m) + s <- sqrt(v) + + n <- 1001 + z <- qnorm(1 - 0.025) + z2 <- z * z + c1 <- 2*n*m + z2 + c2 <- z*sqrt(z2 - 1.0/n + 4*n*v + (4.0*m-2.0))+1.0 + c3 <- 2*(n+z2) + z2.5 <- (c1 + c(-1, 1) * c2) / c3 + + n <- 1001 + z <- qnorm(1 - 0.05) + z2 <- z * z + c1 <- 2*n*m + z2 + c2 <- z*sqrt(z2 - 1.0/n + 4*n*v + (4.0*m-2.0))+1.0 + c3 <- 2*(n+z2) + z5 <- (c1 + c(-1, 1) * c2) / c3 + + + t1 <- c("2.5%"=z2.5[1], + "5%"=z5[1], + "50%"=m, + "95%"=z5[2], + "97.5%"=z2.5[2]) + expect_equal(binomProbs(x, ciMethod="wilsonCorrect"), t1) + expect_equal(binomProbs(x, ciMethod="wc"), t1) + + t2 <- c(c("mean"=m, "var"=v, "sd"=s, "n"=n), t1) + expect_equal(binomProbs(x, onlyProbs=FALSE, ciMethod="wilsonCorrect"), t2) + + x2 <- c(x, NA_real_) + setNames(rep(NA_real_, length(t1)),names(t1)) + expect_equal(binomProbs(x2, ciMethod="wilsonCorrect"), + setNames(rep(NA_real_, length(t1)),names(t1))) + + expect_equal(binomProbs(x2, onlyProbs=FALSE, ciMethod="wilsonCorrect"), + setNames(rep(NA_real_, length(t2)),names(t2))) + expect_equal(binomProbs(x2,na.rm=TRUE, ciMethod="wilsonCorrect"), t1) + expect_equal(binomProbs(x2, onlyProbs=FALSE, na.rm=TRUE, ciMethod="wilsonCorrect"), t2) + + + n <- 50 + z <- qnorm(1 - 0.025) + z2 <- z * z + c1 <- 2*n*m + z2 + c2 <- z*sqrt(z2 - 1.0/n + 4*n*v + (4.0*m-2.0))+1.0 + c3 <- 2*(n+z2) + z2.5 <- (c1 + c(-1, 1) * c2) / c3 + + n <- 50 + z <- qnorm(1 - 0.05) + z2 <- z * z + c1 <- 2*n*m + z2 + c2 <- z*sqrt(z2 - 1.0/n + 4*n*v + (4.0*m-2.0))+1.0 + c3 <- 2*(n+z2) + z5 <- (c1 + c(-1, 1) * c2) / c3 + + + t1 <- c("2.5%"=z2.5[1], + "5%"=z5[1], + "50%"=m, + "95%"=z5[2], + "97.5%"=z2.5[2]) + + expect_equal(binomProbs(x, n=50, ciMethod="wilsonCorrect"), t1) + + # now wilson + x <- rbinom(1001, 1, prob = 0.05) + + getVals <- function(x, a=0.025) { + p <- mean(x) + n <- length(x) + z <- qnorm(1 - a) + z2 <- z ^ 2 + c0 <- 1.0 / (1.0 + z2 / n) + c1 <- c0 * (p + z2 / (2 * n)) + c2 <- z * c0 * sqrt(p * (1 - p) / n + z2 / (4 * n * n)) + (c1 + c(-1, 1) * c2) + } + + m <- mean(x) + z2.5 <- getVals(x, 0.025) + z5 <- getVals(x, 0.05) + + t1 <- c("2.5%"=z2.5[1], + "5%"=z5[1], + "50%"=m, + "95%"=z5[2], + "97.5%"=z2.5[2]) + + expect_equal(binomProbs(x, ciMethod="wilson"), t1) + + # wald + x <- rbinom(1001, 1, prob = 0.05) + + getVals <- function(x, a=0.025) { + p <- mean(x) + n <- length(x) + z <- qnorm(1 - a) + c1 <- p + c2 <- z * sqrt(p * (1 - p) / n) + (c1 + c(-1, 1) * c2) + } + + m <- mean(x) + z2.5 <- getVals(x, 0.025) + z5 <- getVals(x, 0.05) + + t1 <- c("2.5%"=z2.5[1], + "5%"=z5[1], + "50%"=m, + "95%"=z5[2], + "97.5%"=z2.5[2]) + + expect_equal(binomProbs(x, ciMethod="wald"), t1) + + # Agresti-Coull + x <- rbinom(1001, 1, prob = 0.05) + + getVals <- function(x, a=0.025) { + p <- mean(x) + n <- length(x) + z <- qnorm(1 - a) + z2 <- z ^ 2 + nh <- n + z2 + ns <- p * n + ph <- 1 / nh * (ns + z2 / 2) + c1 <- ph + c2 <- z * sqrt(ph * (1 - ph) / nh) + (c1 + c(-1, 1) * c2) + } + + m <- mean(x) + z2.5 <- getVals(x, 0.025) + z5 <- getVals(x, 0.05) + + t1 <- c("2.5%"=z2.5[1], + "5%"=z5[1], + "50%"=m, + "95%"=z5[2], + "97.5%"=z2.5[2]) + + expect_equal(binomProbs(x, ciMethod="agrestiCoull"), t1) + expect_equal(binomProbs(x, ciMethod="ac"), t1) + + + expect_equal(names(binomProbs(x, pred=TRUE)), names(binomProbs(x))) + +}) diff --git a/tests/testthat/test-convertId.R b/tests/testthat/test-convertId.R new file mode 100644 index 000000000..bd1e07c7e --- /dev/null +++ b/tests/testthat/test-convertId.R @@ -0,0 +1,37 @@ +rxTest({ + test_that("in certain solves, the convertId_ did not always work, test here", { + + f <- function() { + description <- "One compartment PK model with linear clearance" + ini({ + lcl <- 1 + label("Clearance (CL)") + lvc <- 3.45 + label("Central volume of distribution (V)") + propSd <- c(0, 0.5) + label("Proportional residual error (fraction)") + }) + model({ + cl <- exp(lcl) + vc <- exp(lvc) + cp <- linCmt() + cp ~ prop(propSd) + }) + } + + dMod <- + data.frame( + Dose = c(5, 5, 5, 5, 5, 5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 5, 5, 5, 5, 5, 5), + ID = c("001-0001", "001-0002", "001-0003", "001-0004", "001-0005", "001-0006", "001-0007", "001-0008", "001-0009", "001-0010", "001-0011", "001-0012", "001-0013", "001-0014", "001-0015", "001-0016", "001-0017", "001-0018"), + TIME = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + EVID = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + CMT = c("central", "central", "central", "central", "central", "central", "central", "central", "central", "central", "central", "central", "central", "central", "central", "central", "central", "central"), + AMT = c(5, 5, 5, 5, 5, 5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 5, 5, 5, 5, 5, 5), + WT = c(70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70) + ) + + f <- rxSolve(f, dMod) + expect_error(print(f), NA) + + }) +}) diff --git a/tests/testthat/test-dsl.R b/tests/testthat/test-dsl.R index 8e29a14cd..3edce09ba 100644 --- a/tests/testthat/test-dsl.R +++ b/tests/testthat/test-dsl.R @@ -553,4 +553,12 @@ rxTest({ expect_equal(rxToSE("tad"), "(t-tlast())") expect_equal(rxFromSE("tlast(NaN)"), "tlast()") }) + + test_that("parsing errors", { + + test <- "E0=THETA[1];\nEm=0.5;\nE50=THETA[2];\ng=2;\nv=E0+Em*t^g/(E50^g+t^g);\nrx_yj_~152;\nrx_lambda_~1;\nrx_low_~0;\nrx_hi_~1;\nrx_r_~0;\nrx_pred_~DV*v-log(1+exp(v));\n" + + expect_error(rxS(test), NA) + + }) }) diff --git a/tests/testthat/test-keep.R b/tests/testthat/test-keep.R index 5948e5975..f6d0bc15c 100644 --- a/tests/testthat/test-keep.R +++ b/tests/testthat/test-keep.R @@ -27,29 +27,29 @@ test_that("Make sure the keep gives the right values", { V2 <- exp(ThetaV2) Q <- exp(ThetaQ) V3 <- exp(ThetaV3) - + K20 <- CL / V2 K23 <- Q / V2 K32 <- Q / V3 - + CP <- A2 / V2 - + ## d / dt(A1) <- -KA * A1 d / dt(A2) <- KA * transit3 - K23 * A2 + K32 * A3 - K20 * A2 d / dt(A3) <- K23 * A2 - K32 * A3 - + d / dt(transit1) <- KA * A1 - KA * transit1 d / dt(transit2) <- KA * transit1 - KA * transit2 d / dt(transit3) <- KA * transit2 - KA * transit3 - + f(A1) <- 1 - + d / dt(AUC) <- CP A1(0) <- 0 A2(0) <- 0 A3(0) <- 0 - + AGE2 <- AGE }) @@ -84,8 +84,8 @@ test_that("Make sure the keep gives the right values", { expect_equal(PK.ev_ref2$AGE, PK.ev_ref2$AGE2) }) -test_that("rxSolve 'keep' maintains character output (#190)", { - +test_that("rxSolve 'keep' maintains character output (#190/#622)", { + one.cmt <- function() { ini({ tka <- 0.45 @@ -107,20 +107,49 @@ test_that("rxSolve 'keep' maintains character output (#190)", { d <- nlmixr2data::theo_sd d$SEX <- ifelse(d$ID < 7, "M", "F") d$fSEX <- factor(d$SEX) + d$oSEX <- d$fSEX + class(d$oSEX) <- c("ordered", "factor") d$iSEX <- as.integer(d$fSEX) + d$lSEX <- as.logical(d$iSEX == 1) d$dSEX <- d$iSEX + 0.5 + library(units) + d$uSEX <- set_units(d$dSEX, kg) d$eSEX <- lapply(d$SEX, function(e) { - str2lang(e) + str2lang(e) }) - sim <- rxSolve(one.cmt, events = d, keep = c("SEX", "fSEX", "iSEX", "dSEX")) - + sim <- rxSolve(one.cmt, events = d, keep = c("SEX", "fSEX", "iSEX", "dSEX", "oSEX", "uSEX", "lSEX")) + expect_type(sim$SEX, "character") expect_s3_class(sim$fSEX, "factor") expect_equal(levels(sim$fSEX), c("F", "M")) expect_type(sim$iSEX, "integer") expect_type(sim$dSEX, "double") + expect_true(inherits(sim$oSEX, "ordered")) + expect_true(inherits(sim$uSEX, "units")) + expect_true(is.logical(sim$lSEX)) + + d <- nlmixr2data::theo_sd + d$SEX <- ifelse(d$ID < 7, "M", "F") + d$SEX[4] <- NA_character_ + d$fSEX <- factor(d$SEX) + d$fSEX[4] <- NA_integer_ + d$iSEX <- as.integer(d$fSEX) + d$iSEX[4] <- NA_integer_ + d$lSEX <- as.logical(d$iSEX == 1) + d$lSEX[4] <- NA + d$dSEX <- d$iSEX + 0.5 + d$eSEX <- lapply(d$SEX, function(e) { + str2lang(e) + }) + + sim <- rxSolve(one.cmt, events = d, keep = c("SEX", "fSEX", "iSEX", "dSEX", "lSEX")) + + expect_true(is.na(d$SEX[4])) + expect_true(is.na(d$fSEX[4])) + expect_true(is.na(d$iSEX[4])) + expect_true(is.na(d$lSEX[4])) expect_error(rxSolve(one.cmt, events = d, keep = c("eSEX"))) - + }) diff --git a/tests/testthat/test-lag.R b/tests/testthat/test-lag.R index 687903aa6..5251ac9bf 100644 --- a/tests/testthat/test-lag.R +++ b/tests/testthat/test-lag.R @@ -1,8 +1,10 @@ rxTest({ + et <- et(1:10) et$b <- 1:10 test_that("lag()", { + suppressMessages(expect_error(rxode2({ a <- lag() }))) diff --git a/tests/testthat/test-meanProb.R b/tests/testthat/test-meanProb.R index 322c539a3..aa1ffc95a 100644 --- a/tests/testthat/test-meanProb.R +++ b/tests/testthat/test-meanProb.R @@ -1,4 +1,5 @@ test_that("test meanProb()", { + x <- rnorm(10) m <- mean(x) s <- sd(x) @@ -7,19 +8,109 @@ test_that("test meanProb()", { mx <- max(x) t1 <- c("0%"=mn, "25%"=m+(s/sqrt(10))*qt(0.25, 9), "50%"=m, "75%"=m+(s/sqrt(10))*qt(0.75, 9), "100%"=mx) expect_equal(meanProbs(x), t1) + + t1.100 <- c("0%"=mn, "25%"=m+(s/sqrt(100))*qt(0.25, 99), "50%"=m, "75%"=m+(s/sqrt(100))*qt(0.75, 99), "100%"=mx) + expect_equal(meanProbs(x, n=100), t1.100) + + t1.p100 <- c("0%"=mn, "25%"=m+s*sqrt(1.0+(1.0/100))*qt(0.25, 99), "50%"=m, "75%"=m+s*sqrt(1.0+(1.0/100))*qt(0.75, 99), "100%"=mx) + expect_equal(meanProbs(x, n=100, pred=TRUE), t1.p100) + t2 <- c(c("mean"=m, "var"=v, "sd"=s, "min"=mn, "max"=mx, "n"=10), t1) expect_equal(meanProbs(x, onlyProbs=FALSE), t2) x2 <- c(x, NA_real_) setNames(rep(NA_real_, length(t1)),names(t1)) - + expect_equal(meanProbs(x2), setNames(rep(NA_real_, length(t1)),names(t1))) expect_equal(meanProbs(x2, onlyProbs=FALSE), setNames(rep(NA_real_, length(t2)),names(t2))) - expect_equal(meanProbs(x2,na.rm=TRUE), t1) + expect_equal(meanProbs(x2, na.rm=TRUE), t1) expect_equal(meanProbs(x2, onlyProbs=FALSE, na.rm=TRUE), t2) - + mod <- rxode2({ + d/dt(intestine) <- -a * intestine + d/dt(blood) <- a * intestine - b * blood + }) + + et <- eventTable() + et$add.sampling(seq(0, 10, length.out = 50)) + et$add.dosing( + dose = 2/24, rate = 2, strt.time = 0, + nbr.doses = 10, dosing.interval = 1 + ) + + p <- data.frame(a = 6, b = seq(0.4, 0.9, length.out = 4)) + + pk1 <- suppressWarnings(rxSolve(mod, p, et, cores = 1)) + + ci1 <- confint(pk1, "blood", mean=TRUE) + + # use dplyr + ci2 <- pk1 |> + dplyr::group_by(time) |> + dplyr::reframe(eff=meanProbs(blood, c(0.025, 0.5, 0.975), na.rm=TRUE, names=FALSE), + p1=c(0.025, 0.5, 0.975), Percentile=c("2.5%", "50%", "97.5%")) |> + dplyr::arrange(time, p1) + + expect_equal(ci1$eff, ci2$eff) + + ci1 <- confint(pk1, "blood", mean=TRUE, pred=TRUE) + + ci2 <- pk1 |> + dplyr::group_by(time) |> + dplyr::reframe(eff=meanProbs(blood, c(0.025, 0.5, 0.975), na.rm=TRUE, names=FALSE, pred=TRUE), + p1=c(0.025, 0.5, 0.975), Percentile=c("2.5%", "50%", "97.5%")) |> + dplyr::arrange(time, p1) + + expect_equal(ci1$eff, ci2$eff) + + ci1 <- confint(pk1, "blood", mean=TRUE, n=100) + + ci2 <- pk1 |> + dplyr::group_by(time) |> + dplyr::reframe(eff=meanProbs(blood, c(0.025, 0.5, 0.975), na.rm=TRUE, names=FALSE, + n=100), + p1=c(0.025, 0.5, 0.975), Percentile=c("2.5%", "50%", "97.5%")) |> + dplyr::arrange(time, p1) + + expect_equal(ci1$eff, ci2$eff) + + + ci1 <- confint(pk1, "blood", mean=TRUE, pred=TRUE, n=100) + + ci2 <- pk1 |> + dplyr::group_by(time) |> + dplyr::reframe(eff=meanProbs(blood, c(0.025, 0.5, 0.975), na.rm=TRUE, names=FALSE, + pred=TRUE, n=100), + p1=c(0.025, 0.5, 0.975), Percentile=c("2.5%", "50%", "97.5%")) |> + dplyr::arrange(time, p1) + + expect_equal(ci1$eff, ci2$eff) + + + ci1 <- confint(pk1, "blood", mean=TRUE, useT=FALSE) + + # use dplyr + ci2 <- pk1 |> + dplyr::group_by(time) |> + dplyr::reframe(eff=meanProbs(blood, c(0.025, 0.5, 0.975), na.rm=TRUE, names=FALSE, useT=FALSE), + p1=c(0.025, 0.5, 0.975), Percentile=c("2.5%", "50%", "97.5%")) |> + dplyr::arrange(time, p1) + + expect_equal(ci1$eff, ci2$eff) + + ci1 <- confint(pk1, "blood", mean=TRUE, useT=FALSE, pred=TRUE) + + # use dplyr + ci2 <- pk1 |> + dplyr::group_by(time) |> + dplyr::reframe(eff=meanProbs(blood, c(0.025, 0.5, 0.975), na.rm=TRUE, names=FALSE, useT=FALSE, + pred=TRUE), + p1=c(0.025, 0.5, 0.975), Percentile=c("2.5%", "50%", "97.5%")) |> + dplyr::arrange(time, p1) + + expect_equal(ci1$eff, ci2$eff) + }) diff --git a/tests/testthat/test-piping-ini.R b/tests/testthat/test-piping-ini.R index 4003a90d3..e504a239e 100644 --- a/tests/testthat/test-piping-ini.R +++ b/tests/testthat/test-piping-ini.R @@ -1,3 +1,59 @@ +test_that("back transformation piping", { + + mod1 <- function() { + ini({ + # central + KA <- 2.94E-01 + backTransform("exp") + CL <- 1.86E+01 + V2 <- 4.02E+01 + # peripheral + Q <- 1.05E+01 + V3 <- 2.97E+02 + # effects + Kin <- 1 + Kout <- 1 + EC50 <- 200 + }) + model({ + C2 <- centr/V2 + C3 <- peri/V3 + d/dt(depot) <- -KA*depot + d/dt(centr) <- KA*depot - CL*C2 - Q*C2 + Q*C3 + d/dt(peri) <- Q*C2 - Q*C3 + eff(0) <- 1 + d/dt(eff) <- Kin - Kout*(1-C2/(EC50+C2))*eff + }) + } + + ui <- rxode(mod1) + + expect_equal(ui$iniDf$backTransform[ui$iniDf$name == "KA"], "exp") + + p1 <- ui %>% + ini( + KA <- backTransform("log") + ) + + expect_equal(p1$iniDf$backTransform[ui$iniDf$name == "KA"], "log") + + p2 <-ui %>% + ini( + KA <- backTransform(log) + ) + + expect_equal(p2$iniDf$backTransform[ui$iniDf$name == "KA"], "log") + + p3 <- ui |> + ini(KA <- backTransform(NULL)) + + expect_equal(p3$iniDf$backTransform[ui$iniDf$name == "KA"], NA_character_) + + expect_error(ui |> + ini(KA <- backTransform(matt)), "matt") + +}) + test_that("piping with ini can update labels (rxode2/issues#351)", { mod <- function() { ini({ @@ -16,6 +72,25 @@ test_that("piping with ini can update labels (rxode2/issues#351)", { expect_equal(newLabelUi$iniDf$label[newLabelUi$iniDf$name == "a"], "bar") }) +test_that("piping with ini can remove labels (#627)", { + + mod <- function() { + ini({ + a <- 1 + label("foo") + addSd <- 2 + }) + model({ + b <- a + b ~ add(addSd) + }) + } + ui <- rxode2(mod) + expect_equal(ui$iniDf$label[ui$iniDf$name == "a"], "foo") + newLabelUi <- ini(ui, a = label(NULL)) + expect_equal(newLabelUi$iniDf$label[ui$iniDf$name == "a"], NA_character_) +}) + test_that("piping with ini gives an error pointing the user to use label for character rhs (rxode2/issues#351)", { mod <- function() { ini({ @@ -145,6 +220,7 @@ test_that(".iniSimplifyAssignArrow", { }) test_that("piping with ini can update reorder parameters (rxode2/issues#352)", { + mod <- function() { ini({ a <- 1 @@ -157,7 +233,9 @@ test_that("piping with ini can update reorder parameters (rxode2/issues#352)", { b ~ add(addSd) }) } + ui <- rxode2(mod) + # No modification expect_equal(ui$iniDf$name, c("a", "b", "c", "addSd")) # b to the top by number @@ -170,6 +248,9 @@ test_that("piping with ini can update reorder parameters (rxode2/issues#352)", { expect_equal(suppressMessages(ini(ui, b <- 1, append = TRUE))$iniDf$name, c("a", "c", "addSd", "b")) # b to the bottom by name expect_equal(suppressMessages(ini(ui, b <- 1, append = "addSd"))$iniDf$name, c("a", "c", "addSd", "b")) + + expect_equal(suppressMessages(ini(ui, b <- 1, append = addSd))$iniDf$name, c("a", "c", "addSd", "b")) + # b after c expect_equal(suppressMessages(ini(ui, b <- 1, append = "c"))$iniDf$name, c("a", "c", "b", "addSd")) # a and b after c; counter-intuitive: the order of a and b are reversed @@ -180,11 +261,16 @@ test_that("piping with ini can update reorder parameters (rxode2/issues#352)", { regexp = "parameter 'b' set to be moved after itself, no change in order made" ) + expect_error( + ini(ui, b <- 1, append = d/dt(fun)), + "append") + # Invalid parameter is correctly caught expect_error( ini(ui, b <- 1, append = "foo"), "append" ) + }) test_that(".iniAddCovarianceBetweenTwoEtaValues", { @@ -275,9 +361,10 @@ test_that(".iniHandleAppend", { b ~ add(addSd) }) } + expect_error( ini(mod, a <- 1, append=factor("A")), - regexp = "'append' must be NULL, logical, numeric, or character" + regexp = "'append' must be NULL, logical, numeric, or character/expression of variable in model" ) expect_error( ini(mod, q <- 1, append=0), @@ -569,3 +656,171 @@ test_that("append allows promoting from covariate (#472)", { ) expect_equal(newmod$iniDf$name, c("lka", "ka_dose", "lcl", "lvc", "propSd")) }) + +test_that("change ini type with ~", { + + mod <- function() { + ini({ + lka <- 0.45 + lcl <- 1 + lvc <- 3.45 + propSd <- 0.5 + }) + model({ + ka <- exp(lka) + cl <- exp(lcl) + vc <- exp(lvc) + kel <- cl / vc + d/dt(depot) <- -ka*depot + d/dt(central) <- ka*depot-kel*central + cp <- central / vc + cp ~ prop(propSd) + }) + } + + mod1 <- mod |> ini( ~ lka) + expect_equal(mod1$omega, lotri(lka ~ 0.45)) + + mod2 <- mod1 |> ini( ~ lka) + expect_equal(mod2$omega, NULL) + + expect_error(mod1 |> ini( ~ propSd)) + + expect_error(mod1 |> ini( ~ matt)) + + ## all etas + + mod <- function() { + ini({ + lka ~ 0.45 + lcl ~ 1 + lvc ~ 3.45 + }) + model({ + ka <- exp(lka) + cl <- exp(lcl) + vc <- exp(lvc) + kel <- cl / vc + d/dt(depot) <- -ka*depot + d/dt(central) <- ka*depot-kel*central + cp <- central / vc + }) + } + + mod2 <- mod |> ini( ~ lka) + + expect_equal(mod2$omega, lotri(lcl ~ 1, lvc ~ 3.45)) + + # remove correlated eta + + mod <- function() { + ini({ + lka + lcl + lvc ~ + c(0.45, + 0.01, 1, + 0.01, -0.01, 3.45) + }) + model({ + ka <- exp(lka) + cl <- exp(lcl) + vc <- exp(lvc) + kel <- cl / vc + d/dt(depot) <- -ka*depot + d/dt(central) <- ka*depot-kel*central + cp <- central / vc + }) + } + + mod2 <- mod |> ini( ~ lka) + + expect_equal(mod2$omega, lotri(lcl + lvc ~ c(1, + -0.01, 3.45))) + + + # negative and zero + + mod <- function() { + ini({ + lka <- 0.45 + lcl <- -1 + lvc <- 0 + }) + model({ + ka <- exp(lka) + cl <- exp(lcl) + vc <- exp(lvc) + kel <- cl / vc + d/dt(depot) <- -ka*depot + d/dt(central) <- ka*depot-kel*central + cp <- central / vc + }) + } + + mod2 <- mod |> ini( ~ lcl) + + expect_equal(mod2$omega, lotri(lcl ~ 1)) + + mod2 <- mod |> ini( ~ lvc) + + expect_equal(mod2$omega, lotri(lvc ~ 1)) + + mod3 <- mod2 |> ini( ~ lvc) + + expect_equal(mod3$omega, NULL) + + mod4 <- mod3 |> ini( ~ lvc) + + expect_equal(mod4$omega, lotri(lvc ~ 1)) + +}) + + + +test_that("change ini variable to covariate with -", { + + mod <- function() { + ini({ + lka + lcl + lvc ~ + c(0.45, + 0.01, 1, + 0.01, -0.01, 3.45) + }) + model({ + ka <- exp(lka) + cl <- exp(lcl) + vc <- exp(lvc) + kel <- cl / vc + d/dt(depot) <- -ka*depot + d/dt(central) <- ka*depot-kel*central + cp <- central / vc + }) + } + + mod2 <- mod |> ini(-lka) + + expect_equal(mod2$allCovs, "lka") + expect_equal(mod2$omega, lotri(lcl + lvc ~ c(1, -0.01, 3.45))) + + mod <- function() { + ini({ + lka ~ 0.45 + lcl ~ 1 + lvc ~ 3.45 + }) + model({ + ka <- exp(lka) + cl <- exp(lcl) + vc <- exp(lvc) + kel <- cl / vc + d/dt(depot) <- -ka*depot + d/dt(central) <- ka*depot-kel*central + cp <- central / vc + }) + } + + mod2 <- mod |> ini(-lka) + + expect_equal(mod2$allCovs, "lka") + + +}) diff --git a/tests/testthat/test-plot.R b/tests/testthat/test-plot.R index c716381b1..e13c15aa9 100644 --- a/tests/testthat/test-plot.R +++ b/tests/testthat/test-plot.R @@ -1,5 +1,5 @@ rxTest({ - + expect_plotlog <- function(o, timex, logx, logy, dat) { # Checking for the correct type for logx and logy is nontrivial, so j expect_named(o, c("timex", "logx", "logy", "dat")) @@ -77,7 +77,7 @@ rxTest({ test_that("plot() with invalid component throws an error", { skip_on_os("mac") - + pheno2 <- function() { ini({ tcl <- log(0.008) @@ -104,5 +104,5 @@ rxTest({ expect_warning(plot(sim, sim, "foo")) expect_error(plot(sim), NA) }) - + }) diff --git a/tests/testthat/test-rxui-ctl.R b/tests/testthat/test-rxui-ctl.R new file mode 100644 index 000000000..619bb2078 --- /dev/null +++ b/tests/testthat/test-rxui-ctl.R @@ -0,0 +1,48 @@ +rxTest({ + test_that("get information from rxUi", { + + ## Test mixed solved and ODEs + mod2 <- function() { + sigma <- lotri({ + err1 ~ 0.05 + err2 ~ 0.05 + }) + ini({ + KA = 2.94E-01 + TCL = 1.86E+01 + V2 = 4.02E+01 + Q = 1.05E+01 + V3 = 2.97E+02 + Kin = 1 + Kout = 1 + EC50 = 200 + eta.Cl ~ 0.2 + }) + model({ + ## the order of variables do not matter, the type of compartmental + ## model is determined by the parameters specified. + CL <- TCL * exp(eta.Cl) + C2 <- linCmt(KA, CL, V2, Q, V3) + eff(0) <- 1 ## This specifies that the effect compartment starts at 1. + d/dt(eff) <- Kin - Kout * (1 - C2 / (EC50 + C2)) * eff + ## + resp <- eff + err1 + pk <- C2 * exp(err2) + }) + } + + f <- mod2() + + ev <- eventTable() %>% + add.dosing(dose = 10000, nbr.doses = 10, dosing.interval = 12, dosing.to = 2) %>% + add.dosing(dose = 20000, nbr.doses = 5, start.time = 120, dosing.interval = 24, dosing.to = 2) %>% + add.sampling(0:240) + + ev <- ev %>% et(0.5, evid = 2) + + pk4 <- rxSolve(f, events=ev, nSub=4, cores = 1, addDosing = TRUE) + expect_true(inherits(pk4, "rxSolve")) + + }) + +}) diff --git a/tests/testthat/test-udf.R b/tests/testthat/test-udf.R new file mode 100644 index 000000000..dd533b9d2 --- /dev/null +++ b/tests/testthat/test-udf.R @@ -0,0 +1,333 @@ +rxTest({ + + e <- et(1:10) |> as.data.frame() + + e$x <- 1:10 + e$y <- 21:30 + + + gg <- function(x, y) { + x + y + } + + f <- rxode2({ + z = gg(x, y) + }) + + + test_that("udf1 works well", { + expect_warning(rxSolve(f, e)) + + d <- suppressWarnings(rxSolve(f, e)) + + expect_true(all(d$z == d$x + d$y)) + }) + + + # now modify gg + gg <- function(x, y, z) { + x + y + z + } + + test_that("udf with 3 arguments works", { + expect_error(rxSolve(f, e)) + }) + + # now modify gg back to 2 arguments + gg <- function(x, y) { + x * y + } + + test_that("when changing gg the results will be different", { + # different solve results but still runs + + d <- suppressWarnings(rxSolve(f, e)) + + expect_true(all(d$z == d$x * d$y)) + + }) + + rm(gg) + + test_that("Without a udf, the solve errors", { + expect_error(rxSolve(f, e)) + }) + + + gg <- function(x, ...) { + x + } + + test_that("cannot solve with udf functions that have ...", { + expect_error(rxSolve(f, e)) + }) + + gg <- function(x, y) { + stop("running me") + } + + test_that("functions that error will error the solve",{ + expect_error(rxSolve(f, e)) + }) + + gg <- function(x, y) { + "running " + } + + + test_that("runs with improper output will error", { + expect_error(rxSolve(f, e)) + }) + + gg <- function(x, y) { + "3" + } + + test_that("error for invalid input", { + expect_error(rxSolve(f, e)) + }) + + gg <- function(x, y) { + 3L + } + + test_that("test symengine functions work with udf funs", { + + expect_equal(rxToSE("gg(x,y)"), "gg(x, y)") + + expect_error(rxToSE("gg()"), "user function") + + expect_error(rxFromSE("Derivative(gg(a,b),a)"), NA) + + expect_error(rxFromSE("Derivative(gg(a),a)")) + + expect_error(rxFromSE("Derivative(gg(),a)")) + }) + + gg <- function(x, ...) { + x + } + + test_that("test that functions with ... will error symengine translation", { + expect_error(rxToSE("gg(x,y)")) + + expect_error(rxFromSE("Derivative(gg(a,b),a)")) + }) + + ## manual functions in C vs R functions + + gg <- function(x, y) { + x + y + } + + test_that("R vs C functions", { + d <- suppressWarnings(rxSolve(f, e)) + expect_true(all(d$z == d$x + d$y)) + }) + + # now add a C function with different values + rxFun("gg", c("x", "y"), + "double gg(double x, double y) { return x*y;}") + + + test_that("C functions rule", { + + + d <- suppressWarnings(rxSolve(f, e)) + + expect_true(all(d$z == d$x * d$y)) + + }) + + rxRmFun("gg") + + test_that("c conversion", { + + udf <- function(x, y) { + a <- x + y + b <- a ^ 2 + a + b + } + + expect_true(grepl("R_pow_di[(]", rxFun2c(udf)[[1]]$cCode)) + + udf <- function(x, y) { + a <- x + y + b <- a ^ x + a + b + } + + expect_true(grepl("R_pow[(]", rxFun2c(udf)[[1]]$cCode)) + + udf <- function(x, y) { + a <- x + y + b <- cos(a) + x + a + b + } + + expect_true(grepl("cos[(]", rxFun2c(udf)[[1]]$cCode)) + + udf <- function(x, y) { + if (a < b) { + return(b ^ 2) + } + a + b + } + + expect_true(grepl("if [(]", rxFun2c(udf)[[1]]$cCode)) + + + udf <- function(x, y) { + a <- x + b <- x ^ 2 + a + if (a < b) { + return(b ^ 2) + } else { + a + b + } + } + + expect_true(grepl("else [{]", rxFun2c(udf)[[1]]$cCode)) + + udf <- function(x, y) { + a <- x + b <- x ^ 2 + a + if (a < b) { + return(b ^ 2) + } else if (a > b + 3) { + return(a + b) + } + a ^ 2 + b ^ 2 + } + + expect_true(grepl("else if [(]", rxFun2c(udf)[[1]]$cCode)) + + udf <- function(x, y) { + a <- x + b <- x ^ 2 + a + if (a < b) { + return(b ^ 2) + } else if (a > b + 3) { + b <- 3 + if (a > 2) { + a <- 2 + } + return(a + b) + } + a ^ 2 + b ^ 2 + } + + expect_true(grepl("else if [(]", rxFun2c(udf)[[1]]$cCode)) + + udf <- function(x, y) { + a <- x + y + x <- a ^ 2 + x + } + + expect_error(rxFun2c(udf)[[1]]$cCode) + + + udf <- function(x, y) { + a <- x + b <- x ^ 2 + a + if (a < b) { + b ^ 2 + } else { + a + b + } + } + + rxFun(udf) + rxRmFun("udf") + + }) + + test_that("udf with model functions", { + + gg <- function(x, y) { + x/y + } + + # Step 1 - Create a model specification + f <- function() { + ini({ + KA <- .291 + CL <- 18.6 + V2 <- 40.2 + Q <- 10.5 + V3 <- 297.0 + Kin <- 1.0 + Kout <- 1.0 + EC50 <- 200.0 + }) + model({ + # A 4-compartment model, 3 PK and a PD (effect) compartment + # (notice state variable names 'depot', 'centr', 'peri', 'eff') + C2 <- gg(centr, V2) + C3 <- peri/V3 + d/dt(depot) <- -KA*depot + d/dt(centr) <- KA*depot - CL*C2 - Q*C2 + Q*C3 + d/dt(peri) <- Q*C2 - Q*C3 + d/dt(eff) <- Kin - Kout*(1-C2/(EC50+C2))*eff + eff(0) <- 1 + }) + } + + u <- f() + + # this pre-compiles and displays the simulation model + u$simulationModel + + # Step 2 - Create the model input as an EventTable, + # including dosing and observation (sampling) events + + # QD (once daily) dosing for 5 days. + + qd <- eventTable(amount.units = "ug", time.units = "hours") + qd$add.dosing(dose = 10000, nbr.doses = 5, dosing.interval = 24) + + # Sample the system hourly during the first day, every 8 hours + # then after + + qd$add.sampling(0:24) + qd$add.sampling(seq(from = 24 + 8, to = 5 * 24, by = 8)) + + # Step 3 - set starting parameter estimates and initial + # values of the state + + # Step 4 - Fit the model to the data + expect_error(suppressWarnings(solve(u, qd)), NA) + + u1 <- u$simulationModel + + expect_error(suppressWarnings(solve(u1, qd)), NA) + + u2 <- u$simulationIniModel + expect_error(suppressWarnings(solve(u2, qd)), NA) + + expect_error(suppressWarnings(rxSolve(f, qd)), NA) + }) + + test_that("symengine load", { + + mod <- "tke=THETA[1];\nprop.sd=THETA[2];\neta.ke=ETA[1];\nke=gg(tke,exp(eta.ke));\nipre=gg(10,exp(-ke*t));\nlipre=log(ipre);\nrx_yj_~2;\nrx_lambda_~1;\nrx_low_~0;\nrx_hi_~1;\nrx_pred_f_~ipre;\nrx_pred_~rx_pred_f_;\nrx_r_~(rx_pred_f_*prop.sd)^2;\n" + + gg <- function(x, y) { + x * y + } + + expect_error(rxS(mod, TRUE, TRUE), NA) + + rxFun(gg) + + rm(gg) + + expect_error(rxS(mod, TRUE, TRUE), NA) + + rxRmFun("gg") + + + }) + +}) diff --git a/tests/testthat/test-ui-assign-model-parts.R b/tests/testthat/test-ui-assign-model-parts.R index 893118824..c90ee6dcb 100644 --- a/tests/testthat/test-ui-assign-model-parts.R +++ b/tests/testthat/test-ui-assign-model-parts.R @@ -94,6 +94,12 @@ test_that("rxode2<- and other rxUi methods", { expect_equal(body(uiOne$fun), body(rxode2(one.compartment)$fun)) expect_equal(body(uiTwo$fun), body(rxode2(two.compartment)$fun)) + uiOne <- rxode2(one.compartment) + uiOne$model <- model(one.compartment2) + expect_equal(model(uiOne), model(one.compartment2)) + expect_equal(ini(uiOne), ini(one.compartment)) + + uiOne <- rxode2(one.compartment) model(uiOne) <- model(one.compartment2) @@ -143,7 +149,7 @@ test_that("rxode2<- and other rxUi methods", { })) ini(uiOne) <- iniNew - + expect_equal(ini(uiOne), iniNew) expect_equal(uiOne$matt, "f") expect_equal(uiOne$f, "matt") @@ -208,7 +214,7 @@ test_that("rxode2<- and other rxUi methods", { expect_equal(uiOne$matt, "f") expect_equal(uiOne$f, "matt") expect_true(inherits(uiOne, "uiOne")) - + uiTwo <- uiOne %>% model(ka <- tka * exp(eta.ka)) @@ -223,7 +229,7 @@ test_that("rxode2<- and other rxUi methods", { expect_equal(uiTwo$matt, "f") expect_equal(uiTwo$f, "matt") expect_true(inherits(uiTwo, "uiOne")) - + # rename something in the ini block is also an insignificant change uiTwo <- uiOne %>% @@ -257,10 +263,45 @@ test_that("ini(model) <- NULL drops", { }) } - uiOne <- one.compartment() ini(uiOne) <- NULL expect_length(uiOne$iniDf$ntheta, 0L) expect_equal(as.ini(NULL), quote(ini({}))) #nolint + + # try with $ini assignment + uiOne <- one.compartment() + uiOne$ini <- NULL + expect_length(uiOne$iniDf$ntheta, 0L) + expect_equal(as.ini(NULL), quote(ini({}))) #nolint }) +test_that("assign model changes meta information", { + + one.compartment <- function() { + ini({ + tka <- log(1.57) + tcl <- log(2.72) + tv <- log(31.5) + eta.ka ~ 0.6 + eta.cl ~ 0.3 + eta.v ~ 0.1 + }) + model({ + ka <- exp(tka + eta.ka) + cl <- exp(tcl + eta.cl) + v <- exp(tv + eta.v) + d/dt(depot) = -ka * depot + d/dt(center) = ka * depot - cl / v * center + cp = center / v + }) + } + + uiOne <- one.compartment() + + uiOne$matt <- "matt" + + expect_equal(uiOne$meta$matt, "matt") + + expect_equal(uiOne$matt, "matt") + +}) diff --git a/tests/testthat/test-ui-mod-functions.R b/tests/testthat/test-ui-mod-functions.R index a9e450cba..d879a6f0e 100644 --- a/tests/testthat/test-ui-mod-functions.R +++ b/tests/testthat/test-ui-mod-functions.R @@ -1,5 +1,118 @@ rxTest({ + + test_that("binding together two models without inis", { + + ocmt <- function() { + model({ + ka <- tka + cl <- tcl + v <- tv + d/dt(depot) = -ka * depot + d/dt(center) = ka * depot - cl / v * center + cp = center / v + }) + } + + idr <- function() { + model({ + kin <- exp(tkin) + kout <- exp(tkout) + ic50 <- exp(tic50) + d/dt(eff) <- kin - kout*(1-ceff^gamma/(ic50^gamma+ceff^gamma)) + }) + } + + m1 <- rxAppendModel(ocmt %>% model(ceff=cp,append=TRUE), idr) + + expect_output( + expect_error(print(m1), NA), + "Normalized Syntax" + ) + + expect_equal(m1$theta, setNames(numeric(0), character(0))) + + }) + + test_that("binding together with first model missing an ini", { + + ocmt <- function() { + model({ + ka <- tka + cl <- tcl + v <- tv + d/dt(depot) = -ka * depot + d/dt(center) = ka * depot - cl / v * center + cp = center / v + }) + } + + idr <- function() { + ini({ + tkin <- log(1) + tkout <- log(1) + tic50 <- log(10) + gamma <- fix(1) + idr.sd <- 1 + }) + model({ + kin <- exp(tkin) + kout <- exp(tkout) + ic50 <- exp(tic50) + d/dt(eff) <- kin - kout*(1-ceff^gamma/(ic50^gamma+ceff^gamma)) + eff ~ add(idr.sd) + }) + } + + m1 <- rxAppendModel(ocmt %>% model(ceff=cp,append=TRUE), idr) + + expect_output( + expect_error(print(m1), NA), + "Normalized Syntax" + ) + expect_true("idr.sd" %in% m1$iniDf$name) + + }) + test_that("binding together second model missing ini", { + + ocmt <- function() { + ini({ + tka <- exp(0.45) + tcl <- exp(1) + tv <- exp(3.45) + add.sd <- 0.7 + }) + model({ + ka <- tka + cl <- tcl + v <- tv + d/dt(depot) = -ka * depot + d/dt(center) = ka * depot - cl / v * center + cp = center / v + cp ~ add(add.sd) + }) + } + + idr <- function() { + model({ + kin <- exp(tkin) + kout <- exp(tkout) + ic50 <- exp(tic50) + d/dt(eff) <- kin - kout*(1-ceff^gamma/(ic50^gamma+ceff^gamma)) + }) + } + + m1 <- rxAppendModel(ocmt %>% model(ceff=cp,append=TRUE), idr) + + expect_output( + expect_error(print(m1), NA), + "Normalized Syntax" + ) + expect_true("tv" %in% m1$iniDf$name) + + }) + test_that("binding together", { + ocmt <- function() { ini({ tka <- exp(0.45) @@ -112,4 +225,645 @@ rxTest({ expect_false(any(addModelLine$iniDf$name == "eff2")) expect_false(any(addModelLine$iniDf$name == "matt")) }) + + test_that("bind together functions where population parameters overlap", { + + ocmt <- function() { + ini({ + tka <- exp(0.45) + tcl <- exp(1) + tv <- exp(3.45) + add.sd <- 0.7 + }) + model({ + ka <- tka + cl <- tcl + v <- tv + d/dt(depot) = -ka * depot + d/dt(center) = ka * depot - cl / v * center + cp = center / v + cp ~ add(add.sd) + }) + } + + idr <- function() { + ini({ + tkin <- log(1) + tkout <- log(1) + tic50 <- log(10) + gamma <- fix(1) + idr.sd <- 1 + tv <- 3 + }) + model({ + kin <- exp(tkin) + kout <- exp(tkout) + ic50 <- exp(tic50) + v <- exp(tv) + d/dt(eff) <- kin - kout*(1-ceff^gamma/(ic50^gamma+ceff^gamma) * v) + eff ~ add(idr.sd) + }) + } + + m1 <- rxAppendModel(ocmt %>% model(ceff=cp,append=TRUE), idr) + + expect_equal(m1$theta, + c(tka = 1.56831218549017, tcl = 2.71828182845905, tv = 31.5003923087479, add.sd = 0.7, tkin = 0, tkout = 0, tic50 = 2.30258509299405, gamma = 1, idr.sd = 1)) + + }) + + + test_that("bind together functions where population parameters where all parameters overlap", { + + ocmt <- function() { + ini({ + tv <- exp(3.45) + }) + model({ + ka <- tka + cl <- tcl + v <- tv + d/dt(depot) = -ka * depot + d/dt(center) = ka * depot - cl / v * center + cp = center / v + }) + } + + idr <- function() { + ini({ + tv <- 3 + }) + model({ + kin <- exp(tkin) + kout <- exp(tkout) + ic50 <- exp(tic50) + v <- exp(tv) + d/dt(eff) <- kin - kout*(1-ceff^gamma/(ic50^gamma+ceff^gamma) * v) + }) + } + + m1 <- rxAppendModel(ocmt %>% model(ceff=cp,append=TRUE), idr) + + expect_equal(m1$theta, + c(tv = 31.5003923087479)) + + }) + + test_that("etas in first model but not in second", { + + ocmt <- function() { + ini({ + tka <- 0.45 + tcl <- 1 + tv <- 3.45 + eta.ka ~ 0.1 + eta.cl ~ 0.1 + eta.v ~ 0.1 + add.sd <- 0.7 + }) + model({ + ka <- exp(tka + eta.ka) + cl <- exp(tcl + eta.cl) + v <- exp(tv + eta.v) + d/dt(depot) = -ka * depot + d/dt(center) = ka * depot - cl / v * center + cp = center / v + cp ~ add(add.sd) + }) + } + + idr <- function() { + ini({ + tkin <- log(1) + tkout <- log(1) + tic50 <- log(10) + gamma <- fix(1) + idr.sd <- 1 + }) + model({ + kin <- exp(tkin) + kout <- exp(tkout) + ic50 <- exp(tic50) + d/dt(eff) <- kin - kout*(1-ceff^gamma/(ic50^gamma+ceff^gamma)) + eff ~ add(idr.sd) + }) + } + + m1 <- rxAppendModel(ocmt %>% model(ceff=cp,append=TRUE), idr) + + expect_equal(m1$omega, + lotri({ + eta.ka ~ 0.1 + eta.cl ~ 0.1 + eta.v ~ 0.1 + })) + + expect_equal(m1$theta, + c(tka = 0.45, tcl = 1, tv = 3.45, add.sd = 0.7, tkin = 0, tkout = 0, tic50 = 2.30258509299405, gamma = 1, idr.sd = 1)) + + }) + + test_that("etas in second model but not first", { + + ocmt <- function() { + ini({ + tka <- exp(0.45) + tcl <- exp(1) + tv <- exp(3.45) + add.sd <- 0.7 + }) + model({ + ka <- tka + cl <- tcl + v <- tv + d/dt(depot) = -ka * depot + d/dt(center) = ka * depot - cl / v * center + cp = center / v + cp ~ add(add.sd) + }) + } + + idr <- function() { + ini({ + tkin <- log(1) + tkout <- log(1) + tic50 <- log(10) + gamma <- fix(1) + idr.sd <- 1 + eta.kin ~ 0.1 + eta.kout ~ 0.1 + eta.ic50 ~ 0.1 + }) + model({ + kin <- exp(tkin + eta.kin) + kout <- exp(tkout + eta.kout) + ic50 <- exp(tic50 + eta.ic50) + d/dt(eff) <- kin - kout*(1-ceff^gamma/(ic50^gamma+ceff^gamma)) + eff ~ add(idr.sd) + }) + } + + m1 <- rxAppendModel(ocmt %>% model(ceff=cp,append=TRUE), idr) + + expect_equal(m1$omega, + lotri({ + eta.kin ~ 0.1 + eta.kout ~ 0.1 + eta.ic50 ~ 0.1 + })) + + expect_equal(m1$theta, + c(tka = 1.56831218549017, tcl = 2.71828182845905, tv = 31.5003923087479, add.sd = 0.7, tkin = 0, tkout = 0, tic50 = 2.30258509299405, gamma = 1, idr.sd = 1)) + + }) + + test_that("bind together 2 models with etas", { + + ocmt <- function() { + ini({ + tka <- 0.45 + tcl <- 1 + tv <- 3.45 + eta.ka ~ 0.1 + eta.cl ~ 0.1 + eta.v ~ 0.1 + add.sd <- 0.7 + }) + model({ + ka <- exp(tka + eta.ka) + cl <- exp(tcl + eta.cl) + v <- exp(tv + eta.v) + d/dt(depot) = -ka * depot + d/dt(center) = ka * depot - cl / v * center + cp = center / v + cp ~ add(add.sd) + }) + } + + idr <- function() { + ini({ + tkin <- log(1) + tkout <- log(1) + tic50 <- log(10) + gamma <- fix(1) + idr.sd <- 1 + eta.kin ~ 0.1 + eta.kout ~ 0.1 + eta.ic50 ~ 0.1 + }) + model({ + kin <- exp(tkin + eta.kin) + kout <- exp(tkout + eta.kout) + ic50 <- exp(tic50 + eta.ic50) + d/dt(eff) <- kin - kout*(1-ceff^gamma/(ic50^gamma+ceff^gamma)) + eff ~ add(idr.sd) + }) + } + + m1 <- rxAppendModel(ocmt %>% model(ceff=cp,append=TRUE), idr) + + expect_equal(m1$omega, + lotri({ + eta.ka ~ 0.1 + eta.cl ~ 0.1 + eta.v ~ 0.1 + eta.kin ~ 0.1 + eta.kout ~ 0.1 + eta.ic50 ~ 0.1 + })) + + expect_equal(m1$theta, + c(tka = 0.45, tcl = 1, tv = 3.45, add.sd = 0.7, tkin = 0, tkout = 0, tic50 = 2.30258509299405, gamma = 1, idr.sd = 1)) + + + }) + + test_that("bind together 2 models with etas with overlapping etas", { + + ocmt <- function() { + ini({ + tka <- 0.45 + tcl <- 1 + tv <- 3.45 + eta.ka ~ 0.1 + eta.cl ~ 0.1 + eta.v ~ 0.1 + add.sd <- 0.7 + }) + model({ + ka <- exp(tka + eta.ka) + cl <- exp(tcl + eta.cl) + v <- exp(tv + eta.v) + d/dt(depot) = -ka * depot + d/dt(center) = ka * depot - cl / v * center + cp = center / v + cp ~ add(add.sd) + }) + } + + idr <- function() { + ini({ + tkin <- log(1) + tkout <- log(1) + tic50 <- log(10) + gamma <- fix(1) + idr.sd <- 1 + eta.kin ~ 0.1 + eta.kout ~ 0.1 + eta.ic50 ~ 0.1 + eta.v ~ 1 + }) + model({ + kin <- exp(tkin + eta.kin) + kout <- exp(tkout + eta.kout) + ic50 <- exp(tic50 + eta.ic50) + d/dt(eff) <- kin - kout*(1-ceff^gamma/(ic50^gamma+ceff^gamma) + eta.v) + eff ~ add(idr.sd) + }) + } + + m1 <- rxAppendModel(ocmt %>% model(ceff=cp,append=TRUE), idr) + + expect_equal(m1$omega, + lotri({ + eta.ka ~ 0.1 + eta.cl ~ 0.1 + eta.v ~ 0.1 + eta.kin ~ 0.1 + eta.kout ~ 0.1 + eta.ic50 ~ 0.1 + })) + + expect_equal(m1$theta, + c(tka = 0.45, tcl = 1, tv = 3.45, add.sd = 0.7, tkin = 0, tkout = 0, tic50 = 2.30258509299405, gamma = 1, idr.sd = 1)) + + }) + + test_that("bind together 2 models with etas with overlapping etas w/cov in 1", { + + ocmt <- function() { + ini({ + tka <- 0.45 + tcl <- 1 + tv <- 3.45 + eta.ka + eta.cl ~ c(0.1, + 0.001, 0.1) + eta.v ~ 0.1 + add.sd <- 0.7 + }) + model({ + ka <- exp(tka + eta.ka) + cl <- exp(tcl + eta.cl) + v <- exp(tv + eta.v) + d/dt(depot) = -ka * depot + d/dt(center) = ka * depot - cl / v * center + cp = center / v + cp ~ add(add.sd) + }) + } + + idr <- function() { + ini({ + tkin <- log(1) + tkout <- log(1) + tic50 <- log(10) + gamma <- fix(1) + idr.sd <- 1 + eta.kin ~ 0.1 + eta.kout ~ 0.1 + eta.ic50 ~ 0.1 + eta.v ~ 1 + }) + model({ + kin <- exp(tkin + eta.kin) + kout <- exp(tkout + eta.kout) + ic50 <- exp(tic50 + eta.ic50) + d/dt(eff) <- kin - kout*(1-ceff^gamma/(ic50^gamma+ceff^gamma) + eta.v) + eff ~ add(idr.sd) + }) + } + + m1 <- rxAppendModel(ocmt %>% model(ceff=cp,append=TRUE), idr) + + expect_equal(m1$omega, + lotri({ + eta.ka + eta.cl ~ c(0.1, 0.001, 0.1) + eta.v ~ 0.1 + eta.kin ~ 0.1 + eta.kout ~ 0.1 + eta.ic50 ~ 0.1 + })) + + expect_equal(m1$theta, + c(tka = 0.45, tcl = 1, tv = 3.45, add.sd = 0.7, tkin = 0, tkout = 0, tic50 = 2.30258509299405, gamma = 1, idr.sd = 1)) + + }) + + + test_that("bind together 2 models with etas with overlapping etas w/cov in 2", { + + ocmt <- function() { + ini({ + tka <- 0.45 + tcl <- 1 + tv <- 3.45 + eta.ka ~ 0.1 + eta.cl ~ 0.1 + eta.v ~ 0.1 + add.sd <- 0.7 + }) + model({ + ka <- exp(tka + eta.ka) + cl <- exp(tcl + eta.cl) + v <- exp(tv + eta.v) + d/dt(depot) = -ka * depot + d/dt(center) = ka * depot - cl / v * center + cp = center / v + cp ~ add(add.sd) + }) + } + + idr <- function() { + ini({ + tkin <- log(1) + tkout <- log(1) + tic50 <- log(10) + gamma <- fix(1) + idr.sd <- 1 + eta.kin + eta.kout~ c(0.1, + 0.01, 0.1) + eta.ic50 ~ 0.1 + eta.v ~ 1 + }) + model({ + kin <- exp(tkin + eta.kin) + kout <- exp(tkout + eta.kout) + ic50 <- exp(tic50 + eta.ic50) + d/dt(eff) <- kin - kout*(1-ceff^gamma/(ic50^gamma+ceff^gamma) + eta.v) + eff ~ add(idr.sd) + }) + } + + m1 <- rxAppendModel(ocmt %>% model(ceff=cp,append=TRUE), idr) + + expect_equal(m1$omega, + lotri({ + eta.ka ~ 0.1 + eta.cl ~ 0.1 + eta.v ~ 0.1 + eta.kin + eta.kout ~ c(0.1, 0.01, 0.1) + eta.ic50 ~ 0.1 + })) + + expect_equal(m1$theta, + c(tka = 0.45, tcl = 1, tv = 3.45, add.sd = 0.7, tkin = 0, tkout = 0, tic50 = 2.30258509299405, gamma = 1, idr.sd = 1)) + + }) + + test_that("bind together 2 models with etas with overlapping etas w/cov in 1", { + + ocmt <- function() { + ini({ + tka <- 0.45 + tcl <- 1 + tv <- 3.45 + eta.ka ~ 0.1 + eta.v + eta.cl~ c(0.1, + 0.01, 0.1) + add.sd <- 0.7 + }) + model({ + ka <- exp(tka + eta.ka) + cl <- exp(tcl + eta.cl) + v <- exp(tv + eta.v) + d/dt(depot) = -ka * depot + d/dt(center) = ka * depot - cl / v * center + cp = center / v + cp ~ add(add.sd) + }) + } + + idr <- function() { + ini({ + tkin <- log(1) + tkout <- log(1) + tic50 <- log(10) + gamma <- fix(1) + idr.sd <- 1 + eta.kin ~ 0.1 + eta.kout ~ 0.1 + eta.ic50 ~ 0.1 + eta.v ~ 1 + }) + model({ + kin <- exp(tkin + eta.kin) + kout <- exp(tkout + eta.kout) + ic50 <- exp(tic50 + eta.ic50) + d/dt(eff) <- kin - kout*(1-ceff^gamma/(ic50^gamma+ceff^gamma) + eta.v) + eff ~ add(idr.sd) + }) + } + + expect_error(rxAppendModel(ocmt %>% model(ceff=cp,append=TRUE), idr)) + }) + + test_that("bind together 2 models with etas with overlapping etas w/cov in 2", { + + ocmt <- function() { + ini({ + tka <- 0.45 + tcl <- 1 + tv <- 3.45 + eta.ka ~ 0.1 + eta.v ~ 0.1 + eta.cl ~ 0.1 + add.sd <- 0.7 + }) + model({ + ka <- exp(tka + eta.ka) + cl <- exp(tcl + eta.cl) + v <- exp(tv + eta.v) + d/dt(depot) = -ka * depot + d/dt(center) = ka * depot - cl / v * center + cp = center / v + cp ~ add(add.sd) + }) + } + + idr <- function() { + ini({ + tkin <- log(1) + tkout <- log(1) + tic50 <- log(10) + gamma <- fix(1) + idr.sd <- 1 + eta.kin ~ 0.1 + eta.kout ~ 0.1 + eta.ic50 + eta.v ~ c(0.1, + 0.001, 1) + }) + model({ + kin <- exp(tkin + eta.kin) + kout <- exp(tkout + eta.kout) + ic50 <- exp(tic50 + eta.ic50) + d/dt(eff) <- kin - kout*(1-ceff^gamma/(ic50^gamma+ceff^gamma) + eta.v) + eff ~ add(idr.sd) + }) + } + + expect_error(rxAppendModel(ocmt %>% model(ceff=cp,append=TRUE), idr)) + + }) + + test_that("combine models without anything in common", { + + ocmt <- function() { + ini({ + tka <- exp(0.45) + tcl <- exp(1) + tv <- exp(3.45) + add.sd <- 0.7 + }) + model({ + ka <- tka + cl <- tcl + v <- tv + d/dt(depot) = -ka * depot + d/dt(center) = ka * depot - cl / v * center + cp = center / v + cp ~ add(add.sd) + }) + } + + idr <- function() { + ini({ + tkin <- log(1) + tkout <- log(1) + tic50 <- log(10) + gamma <- fix(1) + idr.sd <- 1 + }) + model({ + kin <- exp(tkin) + kout <- exp(tkout) + ic50 <- exp(tic50) + d/dt(eff) <- kin - kout*(1-ceff^gamma/(ic50^gamma+ceff^gamma)) + eff ~ add(idr.sd) + }) + } + + m1 <- rxAppendModel(ocmt, idr, common=FALSE) + + expect_true("idr.sd" %in% m1$iniDf$name) + expect_true("tv" %in% m1$iniDf$name) + + }) + + test_that("combine 3 models", { + + ocmt <- function() { + ini({ + tka <- exp(0.45) + tcl <- exp(1) + tv <- exp(3.45) + add.sd <- 0.7 + }) + model({ + ka <- tka + cl <- tcl + v <- tv + d/dt(depot) = -ka * depot + d/dt(center) = ka * depot - cl / v * center + cp = center / v + cp ~ add(add.sd) + }) + } + + d1 <- ocmt |> rxRename(tkaD1=tka, + tclD1=tcl, + tvD1=tv, + add.sd.d1=add.sd, + kaD1=ka, + clD1=cl, + vD1=v, + depotD1=depot, + centerD1=center, + cpD1=cp) + + d2 <- ocmt |> rxRename(tkad2=tka, + tcld2=tcl, + tvd2=tv, + add.sd.d2=add.sd, + kad2=ka, + cld2=cl, + vd2=v, + depotd2=depot, + centerd2=center, + cpd2=cp) + + idr <- function() { + ini({ + tkin <- log(1) + tkout <- log(1) + tic50 <- log(10) + gamma <- fix(1) + idr.sd <- 1 + }) + model({ + kin <- exp(tkin) + kout <- exp(tkout) + ic50 <- exp(tic50) + d/dt(eff) <- kin - kout*(1-ceff^gamma/(ic50^gamma+ceff^gamma)) + eff ~ add(idr.sd) + }) + } + + idr <- idr |> model(ceff=cpD1 + cpd2, append=NA) + + full <- rxAppendModel(d1, d2, idr, common=FALSE) + + expect_equal(full$theta, + c(tkaD1 = 1.56831218549017, tclD1 = 2.71828182845905, tvD1 = 31.5003923087479, add.sd.d1 = 0.7, tkad2 = 1.56831218549017, tcld2 = 2.71828182845905, tvd2 = 31.5003923087479, add.sd.d2 = 0.7, tkin = 0, tkout = 0, tic50 = 2.30258509299405, gamma = 1, idr.sd = 1)) + + }) }) diff --git a/tests/testthat/test-ui-piping.R b/tests/testthat/test-ui-piping.R index b8c4c5547..2107aa0f1 100644 --- a/tests/testthat/test-ui-piping.R +++ b/tests/testthat/test-ui-piping.R @@ -13,6 +13,19 @@ rxTest({ expect_equal(testPipeQuote(tmp), list(quote(d/dt(depot)))) + + t <- c("-d/dt(peripheral1)", "-d/dt(peripheral2)") + expect_equal(testPipeQuote(t), + list(quote(-d/dt(peripheral1)), + quote(-d/dt(peripheral2)))) + + t <- c(a="x", b="y") + + expect_equal(testPipeQuote(t), + list(quote(a <- x), quote(b <- y))) + + + tmp <- list(tmp="d/dt(depot)") expect_equal(testPipeQuote(tmp$tmp), @@ -24,6 +37,73 @@ rxTest({ list(quote(d/dt(depot)))) }) + test_that("equivalent drop statements", { + + expect_equal(.changeDropNullLine(quote(a <- NULL)), + quote(-a)) + expect_equal(.changeDropNullLine(quote(a ~ NULL)), + quote(-a)) + expect_equal(.changeDropNullLine(str2lang("a = NULL")), + quote(-a)) + + expect_equal(.changeDropNullLine(quote(d/dt(a) <- NULL)), + quote(-d/dt(a))) + expect_equal(.changeDropNullLine(quote(d/dt(a) ~ NULL)), + quote(-d/dt(a))) + expect_equal(.changeDropNullLine(str2lang("d/dt(a) = NULL")), + quote(-d/dt(a))) + + expect_equal(.changeDropNullLine(quote(lag(a) <- NULL)), + quote(-lag(a))) + expect_equal(.changeDropNullLine(quote(lag(a) ~ NULL)), + quote(-lag(a))) + expect_equal(.changeDropNullLine(str2lang("lag(a) = NULL")), + quote(-lag(a))) + + expect_equal(.changeDropNullLine(quote(alag(a) <- NULL)), + quote(-alag(a))) + expect_equal(.changeDropNullLine(quote(alag(a) ~ NULL)), + quote(-alag(a))) + expect_equal(.changeDropNullLine(str2lang("alag(a) = NULL")), + quote(-alag(a))) + + expect_equal(.changeDropNullLine(quote(F(a) <- NULL)), + quote(-F(a))) + expect_equal(.changeDropNullLine(quote(F(a) ~ NULL)), + quote(-F(a))) + expect_equal(.changeDropNullLine(str2lang("F(a) = NULL")), + quote(-F(a))) + + expect_equal(.changeDropNullLine(quote(f(a) <- NULL)), + quote(-f(a))) + expect_equal(.changeDropNullLine(quote(f(a) ~ NULL)), + quote(-f(a))) + expect_equal(.changeDropNullLine(str2lang("f(a) = NULL")), + quote(-f(a))) + + expect_equal(.changeDropNullLine(quote(rate(a) <- NULL)), + quote(-rate(a))) + expect_equal(.changeDropNullLine(quote(rate(a) ~ NULL)), + quote(-rate(a))) + expect_equal(.changeDropNullLine(str2lang("rate(a) = NULL")), + quote(-rate(a))) + + expect_equal(.changeDropNullLine(quote(dur(a) <- NULL)), + quote(-dur(a))) + expect_equal(.changeDropNullLine(quote(dur(a) ~ NULL)), + quote(-dur(a))) + expect_equal(.changeDropNullLine(str2lang("dur(a) = NULL")), + quote(-dur(a))) + + expect_equal(.changeDropNullLine(quote(a(0) <- NULL)), + quote(-a(0))) + expect_equal(.changeDropNullLine(quote(a(0) ~ NULL)), + quote(-a(0))) + expect_equal(.changeDropNullLine(str2lang("a(0) = NULL")), + quote(-a(0))) + + }) + test_that("test fix/unfix for eta", { expect_equal(testPipeQuote(a~fix), list(quote(a<-fix))) @@ -749,7 +829,6 @@ rxTest({ expect_error(f %>% ini(tka=c(0, 0.5, 1, 4)), "tka") - expect_error(f %>% ini(tka=NULL), "tka") expect_error(f %>% ini(tka=c(3,2,1)), "tka") suppressMessages( @@ -828,7 +907,6 @@ rxTest({ expect_error(f %>% ini(tka=c(0, 0.5, 1, 4)), "tka") - expect_error(f %>% ini(tka=NULL), "tka") expect_error(f %>% ini(tka=c(3,2,1)), "tka") suppressMessages( @@ -899,7 +977,6 @@ rxTest({ expect_error(f %>% ini(tka=c(0, 0.5, 1, 4)), "tka") - expect_error(f %>% ini(tka=NULL), "tka") expect_error(f %>% ini(tka=c(3,2,1)), "tka") suppressMessages( @@ -1415,6 +1492,18 @@ rxTest({ expect_true("cp1" %in% f2$mv0$lhs) expect_equal(f2$lstExpr[[length(f2$lstExpr)]], quote(cp1 <- cp)) + f <- rxode2(ocmt) + f2 <- f %>% model(cp1 <- cp, append=Inf) + + expect_true("cp1" %in% f2$mv0$lhs) + expect_equal(f2$lstExpr[[length(f2$lstExpr)]], quote(cp1 <- cp)) + + f <- rxode2(ocmt) + f2 <- f %>% model(cp1 <- cp, append=100) + + expect_true("cp1" %in% f2$mv0$lhs) + expect_equal(f2$lstExpr[[length(f2$lstExpr)]], quote(cp1 <- cp)) + f2 <- f %>% model(f2 <- 3 * 2, append=NA) expect_true("f2" %in% f2$mv0$lhs) expect_equal(f2$lstExpr[[1]], quote(f2 <- 3 * 2)) @@ -1921,12 +2010,12 @@ test_that("piping with append=lhs", { test_that("test ui appending of derived variables like `sim` can work", { - + one.compartment <- function() { ini({ tka <- 0.45 - tcl <- 1 - tv <- 3.45 + tcl <- 1 + tv <- 3.45 eta.ka ~ 0.6 eta.cl ~ 0.3 eta.v ~ 0.1 @@ -1946,5 +2035,182 @@ test_that("test ui appending of derived variables like `sim` can work", { f <- rxode2(one.compartment) expect_error(model(f$simulationModel, sim2=sim+1, append=sim), NA) - + +}) + + +test_that("off-diagonal piping issue #518", { + + mod <- function() { + ini({ + a <- 1 + b <- 2 + etaa + etab ~ c(3, 0.1, 4) + c <- 5 + etac ~ 6 + d <- 7 + f <- 9 + etad + etaf ~ c(8, 0.2, 10) + }) + model({ + g <- (a + etaa)/(b + etab) + h <- (c + etac) + i <- (d + etad) + j <- f + etaf + }) + } + + modNew <- + ini( + rxode2(mod), + etab + etac + etad ~ + c(7, + 0.2, 8, + 0.3, 0.4, 9), + etaa ~ 0 + ) + + expect_error(modNew$omega, NA) + +}) + +test_that("piping append", { + + mod <- function() { + ini({ + tka <- 0.45 + label("Ka") + tcl <- 1 + label("Cl") + tv <- 3.45 + label("V") + add.sd <- c(0, 0.7) + eta.cl ~ 0.3 + eta.v ~ 0.1 + }) + model({ + ka <- exp(tka) + cl <- exp(tcl + eta.cl) + v <- exp(tv + eta.v) + d/dt(depot) = -ka * depot + d/dt(center) = ka * depot - cl/v * center + cp = center/v + cp ~ add(add.sd) + }) + } + + t <- c("-cp","-d/dt(depot)") + expect_error(mod |> model(t), NA) + + t <- c("cp <- NULL","d/dt(depot) = NULL") + expect_error(mod |> model(t), NA) + + t <- c("cp <- NULL","d/dt(depot) ~ NULL") + expect_error(mod |> model(t), NA) + + mod5 <- mod |> + model({ + PD <- 1-emax*cp/(ec50+cp) + ## + effect(0) <- e0 + kin <- e0*kout + d/dt(effect) <- kin*PD -kout*effect + }, append=d/dt(center)) + + expect_equal(mod5$theta, c(tka = 0.45, tcl = 1, tv = 3.45, add.sd = 0.7)) + + mod5 <- mod |> + model({ + PD <- 1-emax*cp/(ec50+cp) + ## + effect(0) <- e0 + kin <- e0*kout + d/dt(effect) <- kin*PD -kout*effect + }, append="d/dt(center)") + + expect_equal(mod5$theta, c(tka = 0.45, tcl = 1, tv = 3.45, add.sd = 0.7)) + + mod6 <- mod5 |> + model({ + emax <- exp(temax) + e0 <- exp(te0 + eta.e0) + ec50 <- exp(tec50) + kin <- exp(tkin) + kout <- exp(tkout) + }, append=NA) + + expect_equal(mod6$theta, + c(tka = 0.45, tcl = 1, tv = 3.45, add.sd = 0.7, temax = 1, te0 = 1, tec50 = 1, tkin = 1, tkout = 1)) + + expect_equal( + mod6$omega, + lotri({ + eta.cl ~ 0.3 + eta.v ~ 0.1 + eta.e0 ~ 1 + })) + + mod6 <- mod5 |> + model({ + emax <- exp(temax) + e0 <- exp(te0 + eta.e0) + ec50 <- exp(tec50) + kin <- exp(tkin) + kout <- exp(tkout) + }, append=FALSE) + + expect_equal( + mod6$omega, + lotri({ + eta.cl ~ 0.3 + eta.v ~ 0.1 + eta.e0 ~ 1 + })) + + expect_equal(mod6$theta, + c(tka = 0.45, tcl = 1, tv = 3.45, add.sd = 0.7, temax = 1, te0 = 1, tec50 = 1, tkin = 1, tkout = 1)) + + mod6 <- mod5 |> + model({ + emax <- exp(temax) + e0 <- exp(te0 + eta.e0) + ec50 <- exp(tec50) + kin <- exp(tkin) + kout <- exp(tkout) + }, append=0) + + expect_equal( + mod6$omega, + lotri({ + eta.cl ~ 0.3 + eta.v ~ 0.1 + eta.e0 ~ 1 + })) + + expect_equal(mod6$theta, + c(tka = 0.45, tcl = 1, tv = 3.45, add.sd = 0.7, temax = 1, te0 = 1, tec50 = 1, tkin = 1, tkout = 1)) + + # make sure auto model piping turns off + + withr::with_options(list(rxode2.autoVarPiping=FALSE), + mod7 <- mod5 |> + model({ + emax <- exp(temax) + e0 <- exp(te0 + eta.e0) + ec50 <- exp(tec50) + kin <- exp(tkin) + kout <- exp(tkout) + }, append=NA)) + + expect_equal(mod7$theta, + c(tka = 0.45, tcl = 1, tv = 3.45, add.sd = 0.7)) + + expect_equal( + mod7$omega, + lotri({ + eta.cl ~ 0.3 + eta.v ~ 0.1 + })) + + }) diff --git a/tests/testthat/test-ui-rename.R b/tests/testthat/test-ui-rename.R index 8f27e6040..d405f161a 100644 --- a/tests/testthat/test-ui-rename.R +++ b/tests/testthat/test-ui-rename.R @@ -1,5 +1,6 @@ rxTest({ test_that("rename for ui makes sense", { + ocmt <- function() { ini({ tka <- exp(0.45) @@ -147,8 +148,113 @@ rxTest({ expect_equal(tmp$lstExpr[[6]], quote(rate(dcmt) <- 1)) expect_equal(tmp$lstExpr[[7]], quote(dur(dcmt) <- 1)) expect_equal(tmp$lstExpr[[8]], quote(alag(dcmt) <- 1)) - - }) + + test_that("rename with sigma and thetaMat", { + + f <- function() { + description <- "BOLUS_2CPT_CLV1QV2 SINGLE DOSE FOCEI (120 Ind/2280 Obs) runODE032" + dfObs <- 2280 + dfSub <- 120 + sigma <- lotri({ + eps1 ~ 1 + }) + thetaMat <- lotri({ + theta1 + theta2 + theta3 + theta4 + RSV + eps1 + eta1 + + omega.2.1 + eta2 + omega.3.1 + omega.3.2 + eta3 + + omega.4.1 + omega.4.2 + omega.4.3 + eta4 ~ + c(0.000887681, + -0.00010551, 0.000871409, 0.000184416, -0.000106195, + 0.00299336, -0.000120234, -5.06663e-05, 0.000165252, + 0.00121347, 5.2783e-08, -1.56562e-05, 5.99331e-06, + -2.53991e-05, 9.94218e-06, 0, 0, 0, 0, 0, 0, -4.71273e-05, + 4.69667e-05, -3.64271e-05, 2.54796e-05, -8.16885e-06, + 0, 0.000169296, 0, 0, 0, 0, 0, 0, 0, 0, -7.37156e-05, + 2.56634e-05, -8.08349e-05, 1.37e-05, -4.36564e-06, + 0, 8.75181e-06, 0, 0.00015125, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6.63383e-05, + -8.19002e-05, 0.000548985, 0.000168356, 1.59122e-06, + 0, 3.48714e-05, 0, 4.31593e-07, 0, 0, 0.000959029, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -9.49661e-06, 0.000110108, + -0.000306537, -9.12897e-05, 3.1877e-06, 0, 1.36628e-05, + 0, -1.95096e-05, 0, 0, -0.00012977, 0, 0, 0, 0.00051019) + }) + ini({ + theta1 <- 1.37034036528946 + label("log Cl") + theta2 <- 4.19814911033061 + label("log Vc") + theta3 <- 1.38003493562413 + label("log Q") + theta4 <- 3.87657341967489 + label("log Vp") + RSV <- c(0, 0.196446108190896, 1) + label("RSV") + eta1 ~ 0.101251418415006 + eta2 ~ 0.0993872449483344 + eta3 ~ 0.101302674763154 + eta4 ~ 0.0730497519364148 + }) + model({ + cmt(CENTRAL) + cmt(PERI) + cl <- exp(theta1 + eta1) + v <- exp(theta2 + eta2) + q <- exp(theta3 + eta3) + v2 <- exp(theta4 + eta4) + v1 <- v + scale1 <- v + k21 <- q/v2 + k12 <- q/v + d/dt(CENTRAL) <- k21 * PERI - k12 * CENTRAL - cl * CENTRAL/v1 + d/dt(PERI) <- -k21 * PERI + k12 * CENTRAL + f <- CENTRAL/scale1 + ipred <- f + rescv <- RSV + w <- ipred * rescv + ires <- DV - ipred + iwres <- ires/w + y <- ipred + w * eps1 + }) + } + + f <- f() + + f2 <- rxRename(f, eta.cl=eta1, eta.v=eta2, eta.q=eta3, eta.v2=eta4, eps=eps1) + + expect_equal(sort(intersect(dimnames(f2$omega)[[1]], + c("eta.cl", "eta.v", "eta.q", "eta.v2"))), + c("eta.cl", "eta.q", "eta.v", "eta.v2")) + + expect_equal(sort(intersect(dimnames(f2$thetaMat)[[1]], + c("eta.cl", "eta.v", "eta.q", "eta.v2", "eps"))), + c("eps", "eta.cl", "eta.q", "eta.v", "eta.v2")) + + expect_equal(dimnames(f2$sigma)[[1]], "eps") + + f <- rxUiDecompress(f) + f$sigma <- f$meta$sigma + f$thetaMat <- f$meta$thetaMat + rm("sigma", envir=f$meta) + rm("thetaMat", envir=f$meta) + f <- rxUiCompress(f) + + f3 <- rxRename(f, eta.cl=eta1, eta.v=eta2, eta.q=eta3, eta.v2=eta4, eps=eps1) + + expect_equal(sort(intersect(dimnames(f3$omega)[[1]], + c("eta.cl", "eta.v", "eta.q", "eta.v2"))), + c("eta.cl", "eta.q", "eta.v", "eta.v2")) + + expect_equal(sort(intersect(dimnames(f3$thetaMat)[[1]], + c("eta.cl", "eta.v", "eta.q", "eta.v2", "eps"))), + c("eps", "eta.cl", "eta.q", "eta.v", "eta.v2")) + + expect_equal(dimnames(f3$sigma)[[1]], "eps") + + }) + + }) diff --git a/tests/testthat/test-ui.R b/tests/testthat/test-ui.R index d1de7e556..6ad66edd7 100644 --- a/tests/testthat/test-ui.R +++ b/tests/testthat/test-ui.R @@ -20,6 +20,7 @@ rxTest({ suppressMessages( expect_equal(.rxReplaceCommentWithLabel(cmt), eq) ) + # Leave comment labels in here as they are required for equality testing below one.cmt <- function() { ini({ @@ -89,6 +90,7 @@ rxTest({ }) test_that("meta information parsing", { + one.cmt <- function() { meta1 <- "meta" ini({ diff --git a/vignettes/articles/Integrating-User-Defined-Functions-into-rxode2.Rmd b/vignettes/articles/Integrating-User-Defined-Functions-into-rxode2.Rmd new file mode 100644 index 000000000..548878da8 --- /dev/null +++ b/vignettes/articles/Integrating-User-Defined-Functions-into-rxode2.Rmd @@ -0,0 +1,205 @@ +--- +title: "Integrating User Defined Functions into rxode2" +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +## User Defined Functions + +```{r setup} +library(rxode2) +``` + +When defining models you may have wished to write a small R function +or make a function integrate into `rxode2` somehow. This article +discusses 2 ways to do this: + +- A R-based user function which can be loaded as a simple function + or in certain circumstances translated to C to run more + efficiently + +- A C function that you define and integrate into code + +## R based user functions + +A R-based user function is the most convenient to include in the ODE, +but is slower than what you could have done if it was written in `C` , +`C++` or some other compiled language. This was requested [in +github](https://github.com/nlmixrdevelopment/RxODE/issues/162#issue-568886732) +with an appropriate example; However, I will use a very simple example +here to simply illustrate the concepts. + +```{r fExample} + +newAbs <- function(x) { + if (x < 0) { + -x + } else { + x + } +} + +f <- rxode2({ + a <- newAbs(time) +}) + +e <- et(-10, 10, length.out=40) +``` + +Now that the ODE has been compiled the R functions will be called +while solving the ODE. Since this is calling R, this forces the +parallization to be turned off since R is single-threaded. It also +takes more time to solve since it is shuttling back and forth between +R and C. Lets see how this very simple function performs: + +```{r benmchmark1} +mb1 <- microbenchmark::microbenchmark(withoutC=suppressWarnings(rxSolve(f,e))) + +library(ggplot2) +autoplot(mb1) + rxTheme() +``` + +Not terribly bad, even though it is shuffling between R and C. + +You can make it a better by converting the functions to C: + +```{r convertC} +# Create C functions automatically with `rxFun()` +rxFun(newAbs) +# Recompile to use the C functions +# Note it would recompile anyway if you didn't do this step, +# it just makes sure that it doesn't recompile every step in +# the benchmark +f <- rxode2({ + a <- newAbs(time) +}) + +mb2 <- microbenchmark::microbenchmark(withC=rxSolve(f,e, cores=1)) + +mb <- rbind(mb1, mb2) +autoplot(mb) + rxTheme() + xgxr::xgx_scale_y_log10() +print(mb) +``` + +The C version is almost twice as fast as the R version. You may have +noticed the conversion also created C versions of the first +derivative. This is done automatically and gives not just C versions +of function, but C versions of the derivatives and registers them with +`rxode2`. This allows the C versions to work with not only `rxode2` +but `nlmixr2` models. + +This function was setup in advance to allow this type of +conversion. In general the derivatives will be calculated if there is +not a `return()` statement in the user defined function. This means +simply let R return the last value instead of explictly calling out +the `return()`. Many people prefer this method of coding. + +Even if there is a `return` function, the function could be converted +to `C`. In the github issue, they used a function that would not +convert the derivatives: + +```{r fConvNoDer} +# Light +f_R <- function(actRad, k_0, a_k) { + photfac <- a_k * actRad + k_0 + if (photfac > 1) { + photfac = 1 + } + return(photfac) +} + +rxFun(f_R) +``` + +While this is still helpful because some functions have early returns, +the `nlmixr2` models requiring derivatives would be calculated be +non-optimized finite differences when this occurs. While this gets +into the internals of `rxode2` and `nlmixr2` you can see this more +easily when calculating the derivatives: + +```{r derExample} +rxFromSE("Derivative(f_R(actRad, k_0, a_k),k_0)") +``` + +Whereas the originally defined function `newAbs()` would use the new +derivatives calculated as well: + +```{r derFromC} +rxFromSE("Derivative(newAbs(x),x)") +``` + +In some circumstances, the conversion to C is not possible, though you +can still use the R function. + +There are some requirements for R functions to be integrated into the +rxode2 system: + +- The function must have a set number of arguments, variable + arguments like `f(…)` are currently not allowed. + +- The function is given each argument as a single number, and the + function should return a single number + +If these requirements are met you can use the R function in +rxode2. Additional requirements for conversion to C include: + +- Any functions that you use within the R function must be + understood and available to `rxode2`. + + - Practically speaking if you have `fun2()` which refers to + `fun1()`, `fun1()` must be changed to C code and available to + `rxode2` before changing the function `fun2()` to C. + +- The functions can include `if`/`else` assignments or simple return + statements (either by returning a value or having that value on a + line by itself). Special R control structures and functions (like + `for` and `lapply`) cannot be present. + +- The function cannot refer to any package functions + +- As mentioned, if the `return()` statement is present, the + derivative C functions and `rxode2`'s derivative table is not + updated. + +## C based functions + +You can add your own C functions directly into rxode2 as well using +`rxFun()`: + +```{r rxFun} +fun <- " + double fun(double a, double b, double c) { + return a*a+b*a+c; + } +" ## C-code for function + +rxFun("fun", c("a", "b", "c"), fun) +``` + +If you wanted you could also use C functions or expressions for the derivatives by using the `rxD()` function: + +```{r rxD} +rxD("fun", list( + function(a, b, c) { # derivative of arg1: a + paste0("2*", a, "+", b) + }, + function(a, b, c) { # derivative of arg2: b + return(a) + }, + function(a, b, c) { # derivative of arg3: c + return("0.0") + } +)) +``` + +Removing the function with `rxRmFun()` will also remove the derivative +table: + +```{r rxDrm} +rxRmFun("fun") +``` diff --git a/vignettes/articles/Modifying-Models.Rmd b/vignettes/articles/Modifying-Models.Rmd new file mode 100644 index 000000000..ff8fd7f00 --- /dev/null +++ b/vignettes/articles/Modifying-Models.Rmd @@ -0,0 +1,851 @@ +--- +title: "Modifying Models" +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +```{r setup} +library(rxode2) +``` + +There are two fundamental operations that you may wish to do in +`rxode2`/`nlmixr2`. First you might want to modify your model (ie add +covariate effects, add between subject variability, etc). The second +thing you may wish to do is change initial estimates, change the +boundaries of the problem, fix/unfix the initial estimates, etc. + +## Modifying model + +There are a few tasks you might want to do with the overall model: + +- Change a line in the model + +- Add a line to the model + +- Rename parameters in the model + +- Combine different models + +- Create functions to add certain model features to the model + +We will go over the model piping and other functions that you can use +to modify models and even add your own functions that modify models. + +We will not cover any of the model modification functions in `nlmixr2lib` + +### Modifying a model line + +In my opinion, modifying lines in a model is likely the most common +task in modifying a model. We may wish to modify the model to have a +between subject variability or add a covariate effects. + +To begin of course you need a base model to modify. Let's start with a +very simple PK example, using the single-dose theophylline dataset +generously provided by Dr. Robert A. Upton of the University of +California, San Francisco: + +```{r iniModel} +one.compartment <- function() { + ini({ + tka <- 0.45; label("Ka") + tcl <- 1; label("Cl") + tv <- 3.45; label("V") + eta.ka ~ 0.6 + eta.cl ~ 0.3 + eta.v ~ 0.1 + add.sd <- 0.7 + }) + model({ + ka <- exp(tka + eta.ka) + cl <- exp(tcl + eta.cl) + v <- exp(tv + eta.v) + d/dt(depot) = -ka * depot + d/dt(center) = ka * depot - cl / v * center + cp = center / v + cp ~ add(add.sd) + }) +} +``` + +If we believed we did not have enough absorption to support between +subject variability you can change the line to drop the between +subject by modifying a single line. To do this simply type the line +you want in the model piping expression: + +```{r removeEta} +mod <- one.compartment |> + model(ka <- exp(tka)) + +print(mod) +``` + +As expected, the line is modified. Also you can notice that the +initial estimate for the between subject variability is dropped since +it is no longer part of the model. + +If for some reason you wanted to add it back to the model you can +modify the model and add it back: + +```{r addEta} +mod2 <- mod |> + model(ka <- tka * exp(eta.ka)) + +print(mod2) +``` + +In this modification, the `eta.ka` is automatically assumed to be a +between subject variability parameter. Also since `eta.ka` is not +mu-referenced `rxode2` points this out. + +The automatic detection of `eta.ka` is because the name follows a +convention. Parameters starting or ending with the following names are +assumed to be between subject variability parameters: + +- eta (from NONMEM convention) +- ppv (per patient variability) +- psv (per subject variability) +- iiv (inter-individual variability) +- bsv (between subject variability) +- bpv (between patient variability) + +If this is not functioning correctly you can change it to a covariate +which you can add a type of initial estimate to later: + +```{r addCov} +mod2 <- mod |> + model(ka <- tka * exp(eta.ka) + WT * covWt, cov="eta.ka") + +print(mod2) +``` + +As seen above, the `eta.ka` in the above model is assumed to be a +data-input parameter or covariate instead of an estimated parameter. + +You can also note that `WT` is automatically recognized as a covariate +and `covWt` is automatically recognized as a covariate parameter. + +In general covariates and typical/population parameters are +automatically converted to estimated parameters based on the parameter +name starting with (or ending with): + +- tv (for typical value) +- t (also for typical value) +- pop (for population parameter) +- err (for error parameter) +- eff (for effect parameter) +- cov (for covariate parameters) + +This has a few notable exceptions for parameters like (`wt`, `sex` and +`crcl`) which are assumed to be covariates. + +If you don't want any automatic variable conversion, you can also use +`auto=FALSE`: + +```{r addWithoutAuto} +mod3 <- mod |> + model(ka <- tka * exp(eta.ka) + WT * covWt, auto=FALSE) + +print(mod3) +``` + +In this case all additional parameters (`eta.ka`, `WT`, and `covWt`) +are assumed to be parameters in the dataset. + +### Note on automatic detection of variables + +The automatic detection of variables is convenient for many models but +may not suit your style; If you do not like it you can always change +it by using `options()`: + +```{r option1} +options(rxode2.autoVarPiping=FALSE) +``` + +With this option disabled, all variables will be assumed to be +covariates and you will have to promote them to population parameters +with the `ini` block + +In the last example with this option enabled none of the variables +starting with `t` will be added to the model + +```{r option1ignore} +mod7 <- mod3 |> + model({ + emax <- exp(temax) + e0 <- exp(te0 + eta.e0) + ec50 <- exp(tec50) + kin <- exp(tkin) + kout <- exp(tkout) + }, append=FALSE) + +print(mod7) +``` + +Of course you could use it and then turn it back on: + +```{r option1resume} +options(rxode2.autoVarPiping=TRUE) +mod8 <- mod |> + model({ + emax <- exp(temax) + e0 <- exp(te0 + eta.e0) + ec50 <- exp(tec50) + kin <- exp(tkin) + kout <- exp(tkout) + }, append=FALSE) + +print(mod8) +``` + +Or you can use the +`withr::with_options(list(rxode2.autoVarPiping=FALSE), ...)` to turn +the option on temporarily. + +If you don't like the defaults for changing variables you could change +them as well with `rxSetPipingAuto()` + +For example if you only wanted variables starting or ending with `te` +you can change this with: + +```{r autoVarsChange} +rxSetPipingAuto(thetamodelVars = rex::rex("te")) + +mod9 <- mod |> + model({ + emax <- exp(temax) + e0 <- exp(te0 + eta.e0) + ec50 <- exp(tec50) + kin <- exp(tkin) + kout <- exp(tkout) + }, append=FALSE) + +print(mod9) +``` + +And as requested only the population parameters starting with `te` are +added to the `ini` block. + +If you want to reset the defaults you simply call `rxSetPipingAuto()` +without any arguments: + +```{r autoVarsReset} +rxSetPipingAuto() +mod10 <- mod |> + model({ + emax <- exp(temax) + e0 <- exp(te0 + eta.e0) + ec50 <- exp(tec50) + kin <- exp(tkin) + kout <- exp(tkout) + }, append=FALSE) +``` + +### Adding model lines + +There are three ways to insert lines in a `rxode2`/`nlmixr2` +model. You can add lines to the end of the model, after an expression +or to the beginning of the model all controlled by the `append` +option. + +Let's assume that there are two different assays that were run with +the same compound and you have noticed that they both have different +variability. + +You can modify the model above by adding some lines to the end of the +model by using `append=TRUE`: + +```{r appendLines} +mod4 <- mod |> + model({ + cp2 <- cp + cp2 ~ lnorm(lnorm.sd) + }, append=TRUE) + +print(mod4) +``` + +Perhaps instead you may want to add an indirect response model in +addition to the concentrations, you can choose where to add this: with +`append=lhsVar` where `lhsVar` is the left handed variable above where +you want to insert the new lines: + +```{r insertLines} +mod5 <- mod |> + model({ + PD <- 1-emax*cp/(ec50+cp) + ## + effect(0) <- e0 + kin <- e0*kout + d/dt(effect) <- kin*PD -kout*effect + }, append=d/dt(center)) +``` + +The last type of insertion you may wish to do is to add lines to the +beginning of the model by using `append=FALSE`: + +```{r prependLines} +mod6 <- mod5 |> + model({ + emax <- exp(temax) + e0 <- exp(te0 + eta.e0) + ec50 <- exp(tec50) + kin <- exp(tkin) + kout <- exp(tkout) + }, append=FALSE) + +print(mod6) +``` + +### Remove lines in the model + +The lines in a model can be removed in one of 2 ways either use +`-param` or `param <- NULL` in model piping: + +```{r} +mod7 <- mod6 |> + model(-emax) + +print(mod7) + +# Equivalently + +mod8 <- mod6 |> + model(emax <- NULL) + +print(mod8) +``` + + +### Rename parameters in a model + +You may want to rename parameters in a model, which is easy to do with +`rxRename()`. When `dplyr` is loaded you can even replace it with +`rename()`. The semantics are similar between the two functions, that +is you assigning `newVar=oldVar`. For example: + +```{r rename1} +mod11 <- mod10 |> + rxRename(drug1kout=kout, tv.drug1kout=tkout) + +print(mod11) +``` + +You can see every instance of the variable is named in the model is +renamed inside the `model` and `ini` block. + +For completeness you can see this with the `dplyr` verb (since it is a +S3 method): + +```{r rename2} +library(dplyr) +mod12 <- mod10 |> + rename(drug1kout=kout, tv.drug1kout=tkout) + +print(mod12) +``` + +### Combine different models + +You can also combine different models with `rxAppendModel()`. In +general they need variables in common to combine. This is because you +generally want the models to link between each other. In the below +example a pk and pd model this is done by renaming `cp` in the first +model to `ceff` in the second model: + +```{r append1} +ocmt <- function() { + ini({ + tka <- exp(0.45) # Ka + tcl <- exp(1) # Cl + tv <- exp(3.45); # log V + ## the label("Label name") works with all models + add.sd <- 0.7 + }) + model({ + ka <- tka + cl <- tcl + v <- tv + d/dt(depot) <- -ka * depot + d/dt(center) <- ka * depot - cl / v * center + cp <- center / v + cp ~ add(add.sd) + }) +} + +idr <- function() { + ini({ + tkin <- log(1) + tkout <- log(1) + tic50 <- log(10) + gamma <- fix(1) + idr.sd <- 1 + }) + model({ + kin <- exp(tkin) + kout <- exp(tkout) + ic50 <- exp(tic50) + d/dt(eff) <- kin - kout*(1-ceff^gamma/(ic50^gamma+ceff^gamma)) + eff ~ add(idr.sd) + }) +} + +rxAppendModel(ocmt %>% rxRename(ceff=cp), idr) +``` + +You will get an error if you try to combine models without variables +in common: + +```{r append2} +try(rxAppendModel(ocmt, idr)) +``` + +If you want to combine the models without respecting the having the +variables in common, you can use `common=FALSE`: + +```{r append3} +mod2 <- rxAppendModel(ocmt, idr, common=FALSE) |> + model(ceff=cp, append=ic50) # here we add the translation after the + # ic50 line to make it reasonable + +print(mod2) +``` + +### Creating more complex model modification functions + +These are pretty flexible, but you may want to do even more, so there +are some helper functions to help you create functions to do more. We +will discuss how to extract the model from the function and how to +update it. + +Lets start with a model: + +```{r modelExtractFn} +f <- function() { + ini({ + tka <- 0.45 + tcl <- 1 + tv <- 3.45 + eta.ka ~ 0.6 + eta.v ~ 0.1 + }) + model({ + ka <- exp(tka + eta.ka) + cl <- exp(tcl) + v <- exp(tv + eta.v) + d/dt(depot) <- -ka * depot + d/dt(center) <- ka * depot - cl/v * center + cp <- center/v + }) +} +``` + +Lets assume for a moment you want to remove an eta to `cl`. First you probably want to get all the model lines. You can do that with `modelExtract()`: + +```{r modelExtract} +totLines <- modelExtract(f, endpoint=NA) # endpoints should be included + +print(totLines) +``` + +Now you want to only worry about the `cl` line, you can subset here: + +```{r modelExtract2} +clLine <- modelExtract(f, cl, lines=TRUE) +line <- attr(clLine, "lines") +``` + +Now I wish to change the line to "cl \<- exp(tcl+eta.cl)" + +```{r modelExtract3} +totLines[line] <- "cl <- exp(tcl+eta.cl)" + +# For now lets remove the entire `ini` block (so you don't have to +# worry about syncing parameters). + +# + +ini(f) <- NULL + +model(f) <- totLines + +print(f) +``` + +Note that these functions do not modify the `ini({})` block. You may +have to modify the ini block first to make it a valid +`rxode2`/`nlmixr2` model. + +In this particular case, using model piping would be easier, but it +simply demonstrates two different way to extract model information and +a way to add information to the final model. + +These methods can be tricky because when using them you have to have +model that is parsed correctly. This means you have to make sure the +parameters and endpoints follow the correct rules + +## Modifying initial estimates + +The common items you want to do with initial estimates are: + +- Fix/Unfix a parameter + +- Change the initial condition values and bounds + +- Change the initial condition type + +- Change labels and transformations + +- Reorder parameters + +You may wish to create your own functions; we will discuss this too. + + +### Fixing or unfixing a parameter + +You can fix model estimates in two ways. The first is to fix the value +to whatever is in the model function, this is done by piping the model +parameter name (like `tka`) and setting it equal to `fix` (`%>% +ini(tka=fix)`). Below is a full example: + +```{r fixEstimate} +f <- function() { + ini({ + tka <- 0.45 + tcl <- 1 + tv <- 3.45 + add.sd <- c(0, 0.7) + eta.ka ~ 0.6 + eta.v ~ 0.1 + }) + model({ + ka <- exp(tka + eta.ka) + cl <- exp(tcl) + v <- exp(tv + eta.v) + d/dt(depot) <- -ka * depot + d/dt(center) <- ka * depot - cl/v * center + cp <- center/v + cp ~ add(add.sd) + }) +} + +f2 <- f |> + ini(tka=fix) + +print(f2) +``` + +You can also fix the parameter to a different value if you wish; This +is very similar you can specify the value to fix inside of a `fix` +pseudo-function as follows: `%>% ini(tka=fix(0.1))`. A fully worked +example is below: + +```{r fixEstimate2} +f <- function() { + ini({ + tka <- 0.45 + tcl <- 1 + tv <- 3.45 + add.sd <- c(0, 0.7) + eta.ka ~ 0.6 + eta.v ~ 0.1 + }) + model({ + ka <- exp(tka + eta.ka) + cl <- exp(tcl) + v <- exp(tv + eta.v) + d/dt(depot) <- -ka * depot + d/dt(center) <- ka * depot - cl/v * center + cp <- center/v + cp ~ add(add.sd) + }) +} + +f2 <- f |> + ini(tka=fix(0.1)) + +print(f2) +``` + +### Unfixing parameters + +You an unfix parameters very similarly to fixing. Instead of using the +`fix` keyword, you use the `unfix` keyword. So to unfix a parameter +(keeping its value) you would pipe the model using (`|> +ini(tka=unfix)`). Starting with the fixed model above a fully worked +example is: + +```{r unfix0} +print(f2) + +f3 <- f2 |> ini(tka=unfix) + +print(f3) +``` + +You can also unfix and change the initial estimate with +`ini(parameter=unfix(newEst))`: + +```{r unfix1} +print(f2) + +f3 <- f2 |> + ini(tka=unfix(10)) + +print(f3) +``` + + +### Changing the parameter values and possibly bounds + +#### Multiple parameter assignment + +You can also assign multiple parameters by providing them: + +- As a vector/list + +- As multiple lines in a piped `ini()` block + +- Using a covariance matrix + +In the case of a vector you can specify them and then pipe the model. + +For example: + +```{r pipeModel1} +ini1 <- c(tka=0.1, tcl=1, tv=3) + +f4 <- f |> ini(ini1) + +print(f4) + +# or equivalently + +ini1 <- list(tka=0.1, tcl=1, tv=3) + +f4a <- f |> ini(ini1) + +print(f4) +``` + +This can also be added with multiple lines or commas separating estimates: + +```{r pipeIni2} +# commas separating values: +f4 <- f |> ini(tka=0.1, tcl=1, tv=3) +print(f4) + +# multiple lines in {} +f4 <- f |> + ini({ + tka <- 0.2 + tcl <- 2 + tv <- 6 + }) + +print(f4) +``` + +You could also use a matrix to specify the covariance: + +```{r iniCov} +ome <- lotri(eta.ka + eta.v ~ c(0.6, + 0.01, 10.1)) + +f4 <- f |> ini(ome) + +print(f4) + +# or equavialtly use the lotri-type syntax for the omega: + +f4 <- f |> ini(eta.ka + eta.v ~ c(0.6, + 0.01, 0.2)) +print(f4) +``` + +#### Single parameter assignment + +The simplest way to change the initial parameter estimates is to +simply use `ini(parameter=newValue)`. You can also use `<-` or `~` to +change the value: + +A fully worked example showing all three types of initial value +modification is: + +```{r iniAssign1} +f3 <- f |> + ini(tka <- 0.1) + +f4 <- f |> + ini(tka=0.1) + +f5 <- f |> + ini(tka ~ 0.1) + +print(f5) +``` + +You can change the bounds like you do in the model specification by +using a numeric vector of `c(low, estimate)` or `c(low, estimate, +hi)`. Here is a worked example: + +```{r iniAssign2} +f3 <- f |> + ini(tka <- c(0, 0.1, 0.2)) + +print(f3) + + +f3 <- f |> + ini(tka <- c(0, 0.1)) + +print(f3) +``` + +Note by changing the parameters to their default values they might not +show up in the parameter printout: + +```{r iniAssign3} +f3 <- f |> + ini(tka <- c(0, 0.1, 0.2)) + +print(f3) + +# Now reassign +f4 <- f3 |> + ini(tka <- c(-Inf, 0.1, Inf)) + +print(f4) +``` + +#### Changing parameter types + +You can change the parameter type by two operators either by using +`-par` to convert the parameter to a covariate or `~par` to toggle +between population and individual parameters. + +Here is an example that does all 3: + +```{r parType} +# Switch population parameter to between subject variability parameter: +f4 <- f |> + ini( ~ tcl) + +print(f4) + +# Switch back to population parameter +f5 <- f4 |> + ini( ~ tcl) + +print(f5) + +# Change the variable to a covariate parameter (ie it doesn't have an +# initial estimate so remove it with the `-` operator): + +f6 <- f4 |> + ini(-tcl) + +print(f6) + +# You can change the covariate or remove the parameter estimate by +# `tcl <- NULL`: + +f6 <- f4 |> + ini(tcl <- NULL) + +print(f6) + +# to add it back as a between subject variability or population +# parameter you can pipe it as follows: + +f7 <- f6 |> + ini(tcl=4) + +print(f7) + + +f8 <- f6 |> + ini(tcl ~ 0.1) + +print(f8) +``` + +#### Changing parameter labels + +If you want to change/add a parameter label you assign the parameter +to `label("label to add")`. For example: + +```{r label0} +f4 <- f |> + ini(tka=label("Typical Ka (1/hr)")) + +print(f4) +``` + +You can also change the order while performing operations: + +```{r label1} +f5 <- f |> + ini(tka=label("Typical Ka (1/hr)"), append=tcl) + +print(f5) +``` + +If you want to remove the labels you can remove them with +`ini(par=label(NULL))`; For example: + +```{r label2} +f6 <- f |> + ini(tka=label(NULL)) + +print(f6) +``` + +#### Changing parameter transformations + +Back-transformations over-ride the back transformations in `nlmixr2` +models. They are very similar to the modification of the labels. + +Here you use `|> ini(tka=backTransform(exp))` to add an exponential +back-transformation for data: + +```{r parTrans0} +f7 <- f |> + ini(tka=backTransform(exp)) + +print(f7) +``` + +If you wish to remove them you can also do that with `|> +ini(tka=backTransform(NULL))`: + +```{r parTrans1} +f8 <- f |> + ini(tka=backTransform(NULL)) + +print(f8) +``` + +### More granular access of initial conditions + +Just like with `model()` you can modify the underlying data frame that +represents the `ini()` block. In this case I will simply change the +initial estimate of the first parameter (`tka`): + +```{r getIni} +f <- rxode2(f) + +ini <- f$iniDf + +print(ini) + +ini$est[1] <- 7 + +ini(f) <- ini + +print(f) +```