Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial implementation #151

Merged
merged 5 commits into from
Jun 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# nonmem2rx (development version)

* Added support for `ADVAN5` and `ADVAN7` models

* Add parsing of accept/ignore characters for example `IGNORE=(C='C')`
(See Issue #140)

Expand Down
48 changes: 48 additions & 0 deletions R/advan5.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#' Handle the Ks for advan5/7 ode processing
#' @param k This is the detected K parameter
#' @return nothing called for side effects
#' @noRd
#' @author Matthew L. Fidler
.advan5handleK <- function(k) {
if (!(.nonmem2rx$advan %in% c(5L, 7L))) return(NULL)
if (k %in% .nonmem2rx$advan5k) return(NULL)
.reg1 <- "^[Kk]([1-9])[Tt]?([0-9])$"
.reg2 <- "^[Kk]([1-9][0-9]*)[Tt]([0-9]+)$"
if (grepl(.reg1, k)) {
.n1 <- as.numeric(gsub(.reg1, "\\1", k))
.n2 <- as.numeric(gsub(.reg1, "\\2", k))
} else if (grepl(.reg2, k)) {
.n1 <- as.numeric(gsub(.reg2, "\\1", k))
.n2 <- as.numeric(gsub(.reg2, "\\2", k))
} else {
return(NULL)
}
.newMax <- max(.n1, .n2, .nonmem2rx$advan5max)
if (.newMax > .nonmem2rx$advan5max) {
.nonmem2rx$advan5 <- c(.nonmem2rx$advan5, rep("", .newMax - .nonmem2rx$advan5max))
.nonmem2rx$advan5max <- .newMax
}
.nonmem2rx$advan5[.n1] <- paste0(.nonmem2rx$advan5[.n1], "-", k, "*rxddta", .n1)
.pushObservedDadt(.n1)
.setMaxA(.n1)
if (.n2 != 0) {
.nonmem2rx$advan5[.n2] <- paste0(.nonmem2rx$advan5[.n2], "+", k, "*rxddta", .n1)
.pushObservedDadt(.n2)
.setMaxA(.n2)
}
.nonmem2rx$advan5k <- c(.nonmem2rx$advan5k, k)
NULL
}
#' Get the advan5 odes
#'
#' @return advan5 odes if defined
#' @author Matthew L. Fidler
#' @noRd
.advan5odes <- function() {
if (!(.nonmem2rx$advan %in% c(5L, 7L))) return("")
.w <- which(.nonmem2rx$advan5 == "")
.ret <- paste0("d/dt(rxddta", seq_along(.nonmem2rx$advan5), ") <- ",
gsub("^[+]", "", .nonmem2rx$advan5))
if (length(.w) > 0) .ret <- .ret[-.w]
paste0("\n",paste(.ret, collapse="\n"))
}
5 changes: 4 additions & 1 deletion R/nonmem2rx.R
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@
.nonmem2rx$needExtCalc <- TRUE
.nonmem2rx$mixp <- integer(0)
.nonmem2rx$nspop <- 0L
.nonmem2rx$advan5 <- NULL
.nonmem2rx$advan5max <- 0L
.nonmem2rx$advan5k <- NULL
}
#' Add theta name to .nonmem2rx info
#'
Expand Down Expand Up @@ -725,7 +728,7 @@ nonmem2rx <- function(file, inputData=NULL, nonmemOutputDir=NULL,
"d/dt(depot)=0\nd/dt(central)=0\n"),
ifelse(.nonmem2rx$needExit, "ierprdu <- -1\n", ""),
paste(.nonmem2rx$model, collapse="\n"),

.advan5odes(),
"\n})",
"}")
.fun <- eval(parse(text=.txt))
Expand Down
8 changes: 4 additions & 4 deletions R/sub.R
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ nonmem2rxRec.sub <- function(x) {
for (.cur in .x) {
.Call(`_nonmem2rx_trans_sub`, .cur)
}
if (.nonmem2rx$advan %in% c(5L, 7L)) {
stop("General Linear model translation not supported (ADVAN5 or ADVAN7)",
call.=FALSE)
}
## if (.nonmem2rx$advan %in% c(5L, 7L)) {
## stop("General Linear model translation not supported (ADVAN5 or ADVAN7)",
## call.=FALSE)
## }
if (.nonmem2rx$advan %in% c(9L, 15L)) {
stop("Differential Algebra Equations are not supported in translation (ADVAN9 or ADVAN15)",
call.=FALSE)
Expand Down
2 changes: 2 additions & 0 deletions src/abbrev.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ SEXP nonmem2rxAddLhsVar(const char* v);
SEXP nonmem2rxGetExtendedVar(const char *v);
SEXP nonmem2rxMixP(int p);
SEXP nonmem2rxNspop(int nspop);
SEXP nonmem2rxAdvan5handleK(const char* v);

int maxA = 0,
definingScale = 0;
Expand Down Expand Up @@ -309,6 +310,7 @@ int abbrev_identifier_or_constant(char *name, int i, D_ParseNode *pn) {
sAppendN(&curLine, "nmipredsim", 10);
return 1;
}
if (v[0] == 'K') nonmem2rxAdvan5handleK(v);
// use only upper case in output since NONMEM is case insensitive and rxode2 is sensitive.
if (extendedCtrlInt && strstr(curLine.s, "<-") != NULL) {
char *v2 = (char*) rc_dup_str(CHAR(STRING_ELT(nonmem2rxGetExtendedVar(v), 0)),0);
Expand Down
8 changes: 8 additions & 0 deletions src/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,3 +536,11 @@ extern "C" SEXP nonmem2rxNspop(int nspop) {
END_RCPP
}


extern "C" SEXP nonmem2rxAdvan5handleK(const char* v) {
BEGIN_RCPP
Environment nonmem2rxNs = loadNamespace("nonmem2rx");
Function advan5handleK(".advan5handleK", nonmem2rxNs);
return advan5handleK(v);
END_RCPP
}
99 changes: 99 additions & 0 deletions tests/testthat/test-advan5.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
test_that("test advan5/advan7 translations", {

.a <- function(k, clear=FALSE) {
if (clear) .clearNonmem2rx()
.nonmem2rx$advan <- 5L
.advan5handleK(k)
list(advan5=.nonmem2rx$advan5,
advan5k=.nonmem2rx$advan5k,
advan5max=.nonmem2rx$advan5max)
}


expect_equal(.a("k15", clear=TRUE),
list(advan5 = c("-k15*rxddta1", "", "", "", "+k15*rxddta1"), advan5k = "k15", advan5max = 5))

expect_equal(.a("k56"),
list(advan5 = c("-k15*rxddta1", "", "", "",
"+k15*rxddta1-k56*rxddta5",
"+k56*rxddta5"),
advan5k = c("k15", "k56"), advan5max = 6))

expect_equal(.a("K67"),
list(advan5 = c("-k15*rxddta1", "", "", "",
"+k15*rxddta1-k56*rxddta5",
"+k56*rxddta5-K67*rxddta6",
"+K67*rxddta6"),
advan5k = c("k15", "k56", "K67"),
advan5max = 7))

expect_equal(.a("K74"),
list(advan5 = c("-k15*rxddta1", "", "",
"+K74*rxddta7", "+k15*rxddta1-k56*rxddta5",
"+k56*rxddta5-K67*rxddta6",
"+K67*rxddta6-K74*rxddta7"),
advan5k = c("k15", "k56", "K67", "K74"),
advan5max = 7))

expect_equal(.a("K42"),
list(advan5 = c("-k15*rxddta1", "+K42*rxddta4", "",
"+K74*rxddta7-K42*rxddta4", "+k15*rxddta1-k56*rxddta5",
"+k56*rxddta5-K67*rxddta6", "+K67*rxddta6-K74*rxddta7"),
advan5k = c("k15", "k56", "K67", "K74", "K42"),
advan5max = 7))

expect_equal(.a("K42"),
list(advan5 = c("-k15*rxddta1", "+K42*rxddta4", "",
"+K74*rxddta7-K42*rxddta4", "+k15*rxddta1-k56*rxddta5",
"+k56*rxddta5-K67*rxddta6", "+K67*rxddta6-K74*rxddta7"),
advan5k = c("k15", "k56", "K67", "K74", "K42"),
advan5max = 7))

expect_equal(.a("K40"),
list(advan5 = c("-k15*rxddta1", "+K42*rxddta4", "",
"+K74*rxddta7-K42*rxddta4-K40*rxddta4",
"+k15*rxddta1-k56*rxddta5", "+k56*rxddta5-K67*rxddta6",
"+K67*rxddta6-K74*rxddta7"),
advan5k = c("k15", "k56", "K67", "K74", "K42", "K40"), advan5max =7))

expect_equal(.a("K24"),
list(advan5 = c("-k15*rxddta1", "+K42*rxddta4-K24*rxddta2", "",
"+K74*rxddta7-K42*rxddta4-K40*rxddta4+K24*rxddta2",
"+k15*rxddta1-k56*rxddta5", "+k56*rxddta5-K67*rxddta6",
"+K67*rxddta6-K74*rxddta7"),
advan5k = c("k15", "k56", "K67", "K74", "K42", "K40", "K24"), advan5max = 7))

expect_equal(.a("K24"),
list(advan5 = c("-k15*rxddta1", "+K42*rxddta4-K24*rxddta2", "",
"+K74*rxddta7-K42*rxddta4-K40*rxddta4+K24*rxddta2",
"+k15*rxddta1-k56*rxddta5", "+k56*rxddta5-K67*rxddta6",
"+K67*rxddta6-K74*rxddta7"),
advan5k = c("k15", "k56", "K67", "K74", "K42", "K40", "K24"), advan5max = 7))

expect_equal(.a("K23"),
list(advan5 =
c("-k15*rxddta1",
"+K42*rxddta4-K24*rxddta2-K23*rxddta2",
"+K23*rxddta2", "+K74*rxddta7-K42*rxddta4-K40*rxddta4+K24*rxddta2",
"+k15*rxddta1-k56*rxddta5", "+k56*rxddta5-K67*rxddta6",
"+K67*rxddta6-K74*rxddta7"),
advan5k = c("k15", "k56", "K67", "K74", "K42", "K40", "K24", "K23"), advan5max = 7))

expect_equal(.a("K32"),
list(advan5 = c("-k15*rxddta1", "+K42*rxddta4-K24*rxddta2-K23*rxddta2+K32*rxddta3",
"+K23*rxddta2-K32*rxddta3", "+K74*rxddta7-K42*rxddta4-K40*rxddta4+K24*rxddta2",
"+k15*rxddta1-k56*rxddta5", "+k56*rxddta5-K67*rxddta6", "+K67*rxddta6-K74*rxddta7"),
advan5k = c("k15", "k56", "K67", "K74", "K42", "K40", "K24", "K23", "K32"), advan5max = 7))

expect_equal(.a("K10T0"),
list(advan5 = c("-k15*rxddta1", "+K42*rxddta4-K24*rxddta2-K23*rxddta2+K32*rxddta3",
"+K23*rxddta2-K32*rxddta3", "+K74*rxddta7-K42*rxddta4-K40*rxddta4+K24*rxddta2",
"+k15*rxddta1-k56*rxddta5", "+k56*rxddta5-K67*rxddta6", "+K67*rxddta6-K74*rxddta7",
"", "", "-K10T0*rxddta10"),
advan5k = c("k15", "k56", "K67", "K74", "K42", "K40", "K24", "K23", "K32", "K10T0"),
advan5max = 10))

expect_equal(.advan5odes(),
"\nd/dt(rxddta1) <- -k15*rxddta1\nd/dt(rxddta2) <- K42*rxddta4-K24*rxddta2-K23*rxddta2+K32*rxddta3\nd/dt(rxddta3) <- K23*rxddta2-K32*rxddta3\nd/dt(rxddta4) <- K74*rxddta7-K42*rxddta4-K40*rxddta4+K24*rxddta2\nd/dt(rxddta5) <- k15*rxddta1-k56*rxddta5\nd/dt(rxddta6) <- k56*rxddta5-K67*rxddta6\nd/dt(rxddta7) <- K67*rxddta6-K74*rxddta7\nd/dt(rxddta10) <- -K10T0*rxddta10")

})
6 changes: 3 additions & 3 deletions tests/testthat/test-psn.R
Original file line number Diff line number Diff line change
Expand Up @@ -194,14 +194,14 @@ if (identical(Sys.getenv("NOT_CRAN"), "true")) {
"PsN/test_files/postfrem/frem_covstep_removed/final_models/model_4.lst",
"PsN/test_files/run45.lst",
"PsN/test_files/output/onePROB/oneEST/noSIM/warfarin_ddmore.lst",
"PsN/test_files/output/special_mod/rounding_errors.lst")
"PsN/test_files/output/special_mod/rounding_errors.lst",
"PsN/test_files/output/special_mod/two_digit_cov_index.lst",
"PsN/test_files/output/nm6/nm61_1.lst")

.fileError <- c("PsN/test_files/output/special_mod/missingmodel.lst",
"PsN/test_files/output/special_mod/empty.lst",
"PsN/test_files/output/special_mod/empty_lines.lst",
#bad advan
"PsN/test_files/output/special_mod/two_digit_cov_index.lst",
"PsN/test_files/output/nm6/nm61_1.lst",
# bad lincmt
"PsN/test_files/output/special_mod/objv_infinity.lst",
"PsN/test_files/output/special_mod/interrupted_at_eigen.lst",
Expand Down
1 change: 0 additions & 1 deletion tests/testthat/test-sub.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ test_that("test sub", {
.s("ADVAN=ADVAN2 TRANS=TRANS2", c(advan=2L, trans=2L, abbrevLin=2L))
expect_error(.s("ADVAN1 TRANS3"), "ADVAN1 does not support TRANS3")
expect_error(.s("ADVAN20"), "Unsupported ADVAN20")
expect_error(.s("ADVAN7"), "General Linear model translation not supported")
expect_error(.s("ADVAN9"), "Differential Algebra Equations")
expect_error(.s("ADVAN15"), "Differential Algebra Equations")

Expand Down