Skip to content
This repository has been archived by the owner on Jul 17, 2024. It is now read-only.

Commit

Permalink
Merge branch 'main' into 68-use-new-steady-state-for-lincmt
Browse files Browse the repository at this point in the history
  • Loading branch information
mattfidler committed Jan 14, 2024
2 parents a95097a + 2963b78 commit 5bc4230
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 35 deletions.
6 changes: 3 additions & 3 deletions CRAN-SUBMISSION
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Version: 2.0.13
Date: 2022-11-10 14:23:39 UTC
SHA: edb38d156f0c2a631d4bde9283133ac9e2d4d936
Version: 2.0.17
Date: 2023-12-09 14:16:33 UTC
SHA: 322bf8f43bd079b336d33cd4e3af1f7a6a91648c
3 changes: 1 addition & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: rxode2parse
Title: Parsing and Code Generation Functions for 'rxode2'
Version: 2.0.16.9000
Version: 2.0.17.9000
Authors@R: c(
person("Matthew L.", "Fidler", , "matthew.fidler@gmail.com", role = c("aut", "cre"),
comment = c(ORCID = "0000-0001-8538-6691")),
Expand Down Expand Up @@ -57,4 +57,3 @@ Language: en-US
NeedsCompilation: yes
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.2.3
VignetteBuilder: knitr
14 changes: 11 additions & 3 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
# rxode2parse (development version)

# rxode2parse 2.0.17

* Added ability to query R user functions in a rxode2 model (will
force single threaded solve)

* Moved core `rxFunParse` and `rxRmFunParse` here so that C and R user
function clashes can be handled

* Model variables now tracks which compartments have a lag-time defined
* Model variables now tracks which compartments have a lag-time
defined

* For compartment with steady state doses (NONMEM equivalent SS=1,
SS=2), an additional tracking time-point is added at to track the
time when the lagged dose is given. As an upshot, the lagged dose
will start at the steady state concentration shifted by + ii - lag
in `rxode2`
in `rxode2` (currently for ode systems only)

* This release calculates non bio-availability adjusted duration for
all rates instead of trying to figure the rate duration during
Expand All @@ -25,7 +28,12 @@
* Steady state bolus doses with `addl` are treated as non steady state
events (like what is observed in `NONMEM`)

* Timsort was upgraded; drop radix support in rxode2 struct
* Timsort was upgraded; drop radix support in rxode2 structure

* `etTrans` now supports keeping logical vectors (with the appropriate
version of `rxode2`).

* Security fixes were applied as requested by CRAN

# rxode2parse 2.0.16

Expand Down
8 changes: 4 additions & 4 deletions cran-comments.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Cran comments

- Explicitly use data.table in the R code (already used in C/C++)
- This fixes the note that we are not using data.table in our package (though we were)


- Fixes the issues requested flagged by CRAN
- Also changes solving structure; The reverse dependencies
rxode2random rxode2et and rxode2 need updates after this
- Once updated the rxode2 reverse dependencies all successfully check
2 changes: 1 addition & 1 deletion inst/include/rxode2_model_shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#define _safe_log(a) (&_solveData->safeZero ? (((a) <= 0) ? log(DBL_EPSILON) : log(a)) : log(a))
#define safe_zero(a) (&_solveData->safeZero ? ((a) == 0 ? DBL_EPSILON : ((double)(a))) : ((double)(a)))
#define _as_zero(a) (&_solveData->safeZero && fabs((double)(a)) < sqrt(DBL_EPSILON) ? 0.0 : ((double)(a)))
#define _as_dbleps(a) (&_solveData->safeZero && fabs(a) < sqrt(DBL_EPSILON) ? (((double)(a)) < 0 ? -sqrt(DBL_EPSILON) : sqrt(DBL_EPSILON)) : ((double)(a)))
#define _as_dbleps(a) (&_solveData->safeZero && fabs((double)a) < sqrt(DBL_EPSILON) ? (((double)(a)) < 0 ? -sqrt(DBL_EPSILON) : sqrt(DBL_EPSILON)) : ((double)(a)))
#define _as_dbleps2(a) (&_solveData->safeZero && fabs((double)(a)) < sqrt(DBL_EPSILON) ? sqrt(DBL_EPSILON) : ((double)(a)))
#define factorial(a) exp(lgamma1p(a))
#define sign_exp(sgn, x)(((sgn) > 0.0) ? exp(x) : (((sgn) < 0.0) ? -exp(x) : 0.0))
Expand Down
2 changes: 1 addition & 1 deletion src/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ void codegen(char *model, int show_ode, const char *prefix, const char *libname,
// Hence CMT = 4 could translate in data to 44 with sensi=10
// Then cmt=44 translates back to cmt-10 or 4.
// This makes the sensitivity equations insensitive to CMT changes that occur in FOCEi
sAppend(&sbOut,"#define _CMT ((abs(CMT)<=%d) ? CMT : ((CMT<0) ? CMT+%d: CMT-%d))\n",
sAppend(&sbOut,"#define _CMT ((fabs(CMT)<=%d) ? CMT : ((CMT<0) ? CMT+%d: CMT-%d))\n",
baseSize, tb.sensi, tb.sensi);
} else {
sAppendN(&sbOut,"#define _CMT CMT\n", 17);
Expand Down
77 changes: 58 additions & 19 deletions src/etTran.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,10 +317,10 @@ IntegerVector toCmt(RObject inCmt, CharacterVector& state, const bool isDvid,
warn = warn + std::to_string(warnDvid[i]) + ", ";
}
warn = warn + std::to_string(warnDvid[warnDvid.size()-1]);
Rf_warningcall(R_NilValue, warn.c_str());
Rf_warningcall(R_NilValue, "%s", warn.c_str());
}
if (warnConvertDvid.size() > 0){
Rf_warningcall(R_NilValue, warnC.c_str());
Rf_warningcall(R_NilValue, "%s", warnC.c_str());
}
return out;
} else {
Expand Down Expand Up @@ -455,6 +455,33 @@ bool rxode2parseIsIntegerish(SEXP in) {
return as<bool>(isIntegerish(in));
}

RObject etTranGetAttrKeep(SEXP in) {
RObject cur = as<RObject>(in);
std::vector<std::string> attr = cur.attributeNames();
if (cur.hasAttribute("levels")) {
List ret(attr.size()-1);
CharacterVector retN(attr.size()-1);
unsigned int j = 0;
for (unsigned int i = 0; i < attr.size(); ++i) {
if (attr[i] != "levels") {
retN[j] = attr[i];
ret[j] = cur.attr(attr[i]);
j++;
}
}
ret.attr("names") = retN;
return as<RObject>(ret);
}
List ret(attr.size());
CharacterVector retN(attr.size());
for (unsigned int i = 0; i < attr.size(); ++i) {
retN[i] = attr[i];
ret[i] = cur.attr(attr[i]);
}
ret.attr("names") = retN;
return as<RObject>(ret);
}

//' Event translation for rxode2
//'
//' @param inData Data frame to translate
Expand Down Expand Up @@ -651,7 +678,7 @@ List etTransParse(List inData, List mv, bool addCmt=false,
wKeep += " " + as<std::string>(keep[j]);
}
}
Rf_warningcall(R_NilValue, wKeep.c_str());
Rf_warningcall(R_NilValue, "%s", wKeep.c_str());
}
List covUnits(covCol.size());
CharacterVector covUnitsN(covCol.size());
Expand Down Expand Up @@ -1249,7 +1276,7 @@ List etTransParse(List inData, List mv, bool addCmt=false,
obsId.push_back(cid);
}
if (caddl > 0){
Rf_warningcall(R_NilValue, _("'addl' is ignored with observations"));
Rf_warningcall(R_NilValue, "%s", _("'addl' is ignored with observations"));
}
if (flg != 1){
flg=1;
Expand Down Expand Up @@ -1370,10 +1397,10 @@ List etTransParse(List inData, List mv, bool addCmt=false,
if (rateI == 0) allInf=false;
else allBolus=false;
if (caddl > 0){
Rf_warningcall(R_NilValue, _("'addl' is ignored with 'EVID=2'"));
Rf_warningcall(R_NilValue, "%s", _("'addl' is ignored with 'EVID=2'"));
}
if (flg != 1){
Rf_warningcall(R_NilValue, _("'ss' is ignored with 'EVID=2'"));
Rf_warningcall(R_NilValue, "%s", _("'ss' is ignored with 'EVID=2'"));
}
id.push_back(cid);
evid.push_back(2);
Expand Down Expand Up @@ -1415,10 +1442,10 @@ List etTransParse(List inData, List mv, bool addCmt=false,
case 3:
cevid = 3;
if (caddl > 0){
Rf_warningcall(R_NilValue, _("'addl' is ignored with 'EVID=3'"));
Rf_warningcall(R_NilValue, "%s", _("'addl' is ignored with 'EVID=3'"));
}
if (flg != 1){
Rf_warningcall(R_NilValue, _("'ss' is ignored with 'EVID=3'"));
Rf_warningcall(R_NilValue, "%s", _("'ss' is ignored with 'EVID=3'"));
}
id.push_back(cid);
evid.push_back(3);
Expand Down Expand Up @@ -1496,11 +1523,11 @@ List etTransParse(List inData, List mv, bool addCmt=false,
continue;
}
if (rateI != 0 && hasEvid){
Rf_warningcall(R_NilValue, _("'rate' or 'dur' is ignored with classic rxode2 'EVID's"));
Rf_warningcall(R_NilValue, "%s", _("'rate' or 'dur' is ignored with classic rxode2 'EVID's"));
rateI = 0;
}
if (flg!=1 && hasEvid){ // ss=1 is the same as ss=0 for NONMEM
Rf_warningcall(R_NilValue, _("'ss' is ignored with classic rxode2 'EVID's"));
Rf_warningcall(R_NilValue, "%s", _("'ss' is ignored with classic rxode2 'EVID's"));
flg=1;
}
}
Expand Down Expand Up @@ -1861,7 +1888,7 @@ List etTransParse(List inData, List mv, bool addCmt=false,
doseId.push_back(allId[j]);
}
}
Rf_warningcall(R_NilValue, idWarn.c_str());
Rf_warningcall(R_NilValue, "%s", idWarn.c_str());
redoId=true;
}
}
Expand Down Expand Up @@ -1899,10 +1926,10 @@ List etTransParse(List inData, List mv, bool addCmt=false,
}
}
}
if (!_ini0) Rf_warningcall(R_NilValue, idWarn.c_str());
if (!_ini0) Rf_warningcall(R_NilValue, "%s", idWarn.c_str());
}
if (warnCensNA) Rf_warningcall(R_NilValue, _("censoring missing 'DV' values do not make sense"));
if (warnNaTime) Rf_warningcall(R_NilValue, _("missing 'TIME' values do not make sense (ignored)"));
if (warnCensNA) Rf_warningcall(R_NilValue, "%s", _("censoring missing 'DV' values do not make sense"));
if (warnNaTime) Rf_warningcall(R_NilValue, "%s", _("missing 'TIME' values do not make sense (ignored)"));
#ifdef rxSolveT
REprintf(" Time7: %f\n", ((double)(clock() - _lastT0))/CLOCKS_PER_SEC);
_lastT0 = clock();
Expand Down Expand Up @@ -1994,11 +2021,11 @@ List etTransParse(List inData, List mv, bool addCmt=false,
int censAdd = 0;
if (censCol != -1) censAdd=1;
if (censAdd && censNone) {
Rf_warningcall(R_NilValue, _("while censoring is included in dataset, no observations are censored"));
Rf_warningcall(R_NilValue, "%s", _("while censoring is included in dataset, no observations are censored"));
censAdd=0;
}
if (swapDvLimit){
Rf_warningcall(R_NilValue, _("'dv' and 'limit' swapped since 'limit' > 'dv'"));
Rf_warningcall(R_NilValue, "%s", _("'dv' and 'limit' swapped since 'limit' > 'dv'"));
}
int limitAdd = 0;
if (limitCol != -1) limitAdd=1;
Expand Down Expand Up @@ -2104,36 +2131,48 @@ List etTransParse(List inData, List mv, bool addCmt=false,
for (j = 0; j < (int)(keepCol.size()); j++){
SEXP cur = inData[keepCol[j]];
RObject calc;
List curType(2);
List curType(3);
if (TYPEOF(cur) == STRSXP){
calc = convertId_(cur);
curType[0] = IntegerVector::create(1);
curType[1] = calc.attr("levels");
curType[2] = etTranGetAttrKeep(cur);
calc.attr("levels") = R_NilValue;
calc.attr("class") = R_NilValue;
inDataFK[j] = as<NumericVector>(calc);
inDataFKL[j] = curType;
} else if (TYPEOF(cur) == INTSXP){
calc = cur;
if (calc.hasAttribute("levels")) {
// need to check type
calc = clone(cur); // make sure they don't affect changes
curType[0] = IntegerVector::create(2);
curType[1] = calc.attr("levels");
curType[2] = etTranGetAttrKeep(cur);
calc.attr("levels") = R_NilValue;
calc.attr("class") = R_NilValue;
inDataFK[j] = as<NumericVector>(calc);
} else {
curType[0] = IntegerVector::create(3);
curType[1] = R_NilValue;
curType[2] = etTranGetAttrKeep(cur);
inDataFK[j] = as<NumericVector>(calc);
}
inDataFKL[j] = curType;
} else if (TYPEOF(cur) == REALSXP) {
curType[0] = IntegerVector::create(4);
curType[1] = R_NilValue;
curType[2] = etTranGetAttrKeep(cur);
inDataFK[j] = cur;
inDataFKL[j] = curType;
} else if (TYPEOF(cur) == LGLSXP) {
curType[0] = IntegerVector::create(5);
curType[1] = R_NilValue;
curType[2] = etTranGetAttrKeep(cur);
inDataFK[j] = as<NumericVector>(cur);
inDataFKL[j] = curType;
} else {
stop("the columns that are kept must be either a string, a factor, an integer number, or a real number");
stop(_("the columns that are kept must be either an underlying logical, string, factor, integer number, or real number"));
}
}
int maxItemsPerId = 0;
Expand Down Expand Up @@ -2450,7 +2489,7 @@ List etTransParse(List inData, List mv, bool addCmt=false,
Rf_setAttrib(lstF, R_RowNamesSymbol, IntegerVector::create(NA_INTEGER,-idxOutput.size()+rmAmt));
if (doWarnNeg){
if (!warnedNeg){
Rf_warningcall(R_NilValue, _("\nwith negative times, compartments initialize at first negative observed time\nwith positive times, compartments initialize at time zero\nuse 'rxSetIni0(FALSE)' to initialize at first observed time\nthis warning is displayed once per session"));
Rf_warningcall(R_NilValue, "%s", _("\nwith negative times, compartments initialize at first negative observed time\nwith positive times, compartments initialize at time zero\nuse 'rxSetIni0(FALSE)' to initialize at first observed time\nthis warning is displayed once per session"));
warnedNeg=true;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/tran.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ char *f1LinCmtLine = NULL;
char *rate1LinCmtLine = NULL;
char *dur1LinCmtLine = NULL;

SEXP _rxode2parse_resetUdf();
SEXP _rxode2parse_resetUdf(void);

void reset(void) {
// Reset sb/sbt string buffers
Expand Down
2 changes: 1 addition & 1 deletion src/tran.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ static inline int allSpaces(char *v2) {

void parseFree(int last);

#define err_trans(chr) Rf_errorcall(R_NilValue, _(chr));
#define err_trans(chr) Rf_errorcall(R_NilValue, "%s", _(chr));

void _rxode2parse_unprotect(void);

Expand Down

0 comments on commit 5bc4230

Please sign in to comment.