From a1b933e912d1803af74707b8ed3ac97a219b0a4c Mon Sep 17 00:00:00 2001 From: Bill Denney Date: Thu, 20 Aug 2026 13:07:10 -0400 Subject: [PATCH] docs: correct registry description strings to match the implementation Fixes #582. Replaces #590, which predates the 40-character desc limit and whose replacement strings run 63-243 characters. adj.r.squared.factor described itself as a factor multiplied by the number of data points and added to the adjusted r^2. The code instead accepts every regression whose adjusted r^2 is within adj.r.squared.factor of the best and picks the one using the most points. This string is built by paste() for PKNCA.options() and is not subject to the desc length limit. span.ratio described itself as the half-life divided by the calculation duration, the inverse of what half.life.R computes: ret$span.ratio <- (max(data$time) - min(data$time))/ret$half.life The roxygen for pk.calc.half.life() already described it the correct way, so the registry string also contradicted the manual page. The eight dose-aware aucint*/aumcint* parameters ending in .dose described themselves as AUCdn/AUMCdn. In this package `dn` means dose normalized (auclast.dn, aucinf.obs.dn), while these parameters use dose-aware interpolation -- as their own pretty_name has always said. All replacements are within the 40-character limit. The aucint.inf/aumcint.inf copy-paste that #590 also fixed is already correct on main; the new tests pin it so it stays that way. Tests enumerate the parameter sets rather than listing cases, so a newly added interval parameter is covered automatically. Co-Authored-By: Claude Opus 5 --- NEWS.md | 10 ++++++++++ R/PKNCA.options.R | 9 ++++++--- R/aucint.R | 16 ++++++++-------- R/half.life.R | 2 +- tests/testthat/test-PKNCA.options.R | 6 ++++++ tests/testthat/test-aucint.R | 23 +++++++++++++++++++++++ tests/testthat/test-half.life.R | 5 +++++ 7 files changed, 59 insertions(+), 12 deletions(-) diff --git a/NEWS.md b/NEWS.md index 73dc6064..1c8348f5 100644 --- a/NEWS.md +++ b/NEWS.md @@ -6,6 +6,16 @@ the dosing including dose amount and route. # Development version +* Corrected registry description strings that did not match the + implementation (#582). `adj.r.squared.factor` is described as selecting + the regression with the most points among those within the tolerance of + the best adjusted r^2, rather than as a factor added per data point. + `span.ratio` is described as the lambda z time span divided by the + half-life; the previous text stated the inverse. The eight dose-aware + `aucint*`/`aumcint*` parameters ending in `.dose` no longer describe + themselves as `AUCdn`/`AUMCdn`, which is this package's abbreviation for + dose normalization (`auclast.dn` and similar). + * Bug fix: `pk.calc.sparse_auc()` and `pk.calc.sparse_aumc()` now use their `options` argument when integrating the mean concentration-time profile, so per-run options (e.g. `PKNCAdata(options = list(conc.blq = "keep"))`) affect diff --git a/R/PKNCA.options.R b/R/PKNCA.options.R index edd6a012..3fcbf020 100644 --- a/R/PKNCA.options.R +++ b/R/PKNCA.options.R @@ -4,9 +4,12 @@ adj.r.squared.factor=function(x, default=FALSE, description=FALSE) { if (description) return(paste( - "The adjusted r^2 for the calculation of lambda.z has this factor", - "times the number of data points added to it. It allows for more", - "data points to be preferred in the calculation of half-life.")) + "During the calculation of lambda.z, all candidate regressions", + "with an adjusted r^2 within adj.r.squared.factor of the best", + "adjusted r^2 are considered acceptable, and the acceptable", + "regression using the most data points is selected. It allows", + "for more data points to be preferred in the calculation of", + "half-life.")) if (default) return(0.0001) checkmate::assert_number(x, .var.name = "adj.r.squared.factor") diff --git a/R/aucint.R b/R/aucint.R index 62164141..0b74a277 100644 --- a/R/aucint.R +++ b/R/aucint.R @@ -262,7 +262,7 @@ add.interval.col("aucint.last.dose", values=c(FALSE, TRUE), unit_type="auc", pretty_name="AUCint (based on AUClast extrapolation, dose-aware)", - desc="AUCdn T1 to T2 (zero extrap)", + desc="AUC T1 to T2, dose-aware (zero extrap)", formalsmap=list(conc="conc.group", time="time.group", time.dose="time.dose.group"), pptestcd_cdisc="AUCINTD", pptest_cdisc="AUC from T1 to T2 Normalized by Dose") @@ -282,7 +282,7 @@ add.interval.col("aucint.all.dose", values=c(FALSE, TRUE), unit_type="auc", pretty_name="AUCint (based on AUCall extrapolation, dose-aware)", - desc="AUCdn T1 to T2 (AUCall extrap)", + desc="AUC T1 to T2, dose-aware (AUCall)", formalsmap=list(conc="conc.group", time="time.group", time.dose="time.dose.group"), pptestcd_cdisc="AUCINTAD", pptest_cdisc="AUCint (based on AUCall extrapolation, dose-aware)") @@ -303,7 +303,7 @@ add.interval.col("aucint.inf.obs.dose", values=c(FALSE, TRUE), unit_type="auc", pretty_name="AUCint (based on AUCinf,obs extrapolation, dose-aware)", - desc="AUCdn T1 to T2 (AUCinf,obs extrap)", + desc="AUC T1 to T2, dose-aware (AUCinf,obs)", formalsmap=list(conc="conc.group", time="time.group", time.dose="time.dose.group"), depends=c("lambda.z", "clast.obs"), pptestcd_cdisc="AUCINTID", @@ -325,7 +325,7 @@ add.interval.col("aucint.inf.pred.dose", values=c(FALSE, TRUE), unit_type="auc", pretty_name="AUCint (based on AUCinf,pred extrapolation, dose-aware)", - desc="AUCdn T1 to T2 (AUCinf,pred extrap)", + desc="AUC T1 to T2, dose-aware (AUCinf,pred)", formalsmap=list(conc="conc.group", time="time.group", time.dose="time.dose.group"), depends=c("lambda.z", "clast.pred"), pptestcd_cdisc="AUCINTPD", @@ -416,7 +416,7 @@ add.interval.col("aumcint.last.dose", values=c(FALSE, TRUE), unit_type="aumc", pretty_name="AUMCint (based on AUMClast extrapolation, dose-aware)", - desc="AUMCdn T1 to T2 (zero extrap)", + desc="AUMC T1 to T2, dose-aware (zero extrap)", formalsmap=list(conc="conc.group", time="time.group", time.dose="time.dose.group")) # aumcint.all (without dose awareness) @@ -434,7 +434,7 @@ add.interval.col("aumcint.all.dose", values=c(FALSE, TRUE), unit_type="aumc", pretty_name="AUMCint (based on AUMCall extrapolation, dose-aware)", - desc="AUMCdn T1 to T2 (AUMCall extrap)", + desc="AUMC T1 to T2, dose-aware (AUMCall)", formalsmap=list(conc="conc.group", time="time.group", time.dose="time.dose.group")) # aumcint.inf.obs (without dose awareness) @@ -453,7 +453,7 @@ add.interval.col("aumcint.inf.obs.dose", values=c(FALSE, TRUE), unit_type="aumc", pretty_name="AUMCint (based on AUMCinf,obs extrapolation, dose-aware)", - desc="AUMCdn T1 to T2 (AUMCinf,obs extrap)", + desc="AUMC T1 to T2, dose-aware (AUMCinf,obs)", formalsmap=list(conc="conc.group", time="time.group", time.dose="time.dose.group"), depends=c("lambda.z", "clast.obs")) @@ -473,7 +473,7 @@ add.interval.col("aumcint.inf.pred.dose", values=c(FALSE, TRUE), unit_type="aumc", pretty_name="AUMCint (based on AUMCinf,pred extrapolation, dose-aware)", - desc="AUMCdn T1 to T2 (AUMCinf,pred extrap)", + desc="AUMC T1 to T2, dose-aware (AUMCinf,pred)", formalsmap=list(conc="conc.group", time="time.group", time.dose="time.dose.group"), depends=c("lambda.z", "clast.pred")) diff --git a/R/half.life.R b/R/half.life.R index bae93bf8..33e270fb 100644 --- a/R/half.life.R +++ b/R/half.life.R @@ -757,7 +757,7 @@ add.interval.col("span.ratio", values=c(FALSE, TRUE), unit_type="fraction", pretty_name="Span ratio", - desc="Half-life to calculation duration ratio", + desc="Lambda z time span to half-life ratio", depends="half.life", pptestcd_cdisc="LAMZSPN", pptest_cdisc="Lambda z Span") diff --git a/tests/testthat/test-PKNCA.options.R b/tests/testthat/test-PKNCA.options.R index 483d859c..665f62e2 100644 --- a/tests/testthat/test-PKNCA.options.R +++ b/tests/testthat/test-PKNCA.options.R @@ -481,3 +481,9 @@ test_that("PKNCA.options fails when setting defaults and another option simultan ) }) + +test_that("adj.r.squared.factor description matches the selection rule in the code (#582)", { + desc <- PKNCA.options.describe("adj.r.squared.factor") + expect_match(desc, "within adj.r.squared.factor of the best", fixed = TRUE) + expect_match(desc, "regression using the most data points is selected", fixed = TRUE) +}) diff --git a/tests/testthat/test-aucint.R b/tests/testthat/test-aucint.R index ed4d36b3..447e6e29 100644 --- a/tests/testthat/test-aucint.R +++ b/tests/testthat/test-aucint.R @@ -738,3 +738,26 @@ test_that("Integration functions are passed correctly through wrapper", { expect_true(is.numeric(auc_result) && auc_result > 0) expect_true(is.numeric(aumc_result) && aumc_result > 0) }) + +test_that("the *int.inf.* descriptions name the AUCinf extrapolation they use (#582)", { + cols <- get.interval.cols() + auc_inf <- grep("^aucint[.]inf[.]", names(cols), value = TRUE) + aumc_inf <- grep("^aumcint[.]inf[.]", names(cols), value = TRUE) + expect_equal(length(auc_inf), 4) + expect_equal(length(aumc_inf), 4) + auc_desc <- vapply(cols[auc_inf], FUN = function(x) x$desc, FUN.VALUE = character(1)) + aumc_desc <- vapply(cols[aumc_inf], FUN = function(x) x$desc, FUN.VALUE = character(1)) + expect_true(all(grepl("AUCinf,", auc_desc, fixed = TRUE))) + expect_true(all(grepl("AUMCinf,", aumc_desc, fixed = TRUE))) +}) + +test_that("dose-aware interval parameters are not described as dose-normalized (#582)", { + cols <- get.interval.cols() + dose_aware <- grep("int[.].*[.]dose$", names(cols), value = TRUE) + expect_equal(length(dose_aware), 8) + descs <- vapply(cols[dose_aware], FUN = function(x) x$desc, FUN.VALUE = character(1)) + # "dn" is the abbreviation for dose normalization (auclast.dn and friends); + # these parameters use dose-aware interpolation instead. + expect_equal(unname(descs[grepl("dn", descs, fixed = TRUE)]), character(0)) + expect_true(all(grepl("dose-aware", descs, fixed = TRUE))) +}) diff --git a/tests/testthat/test-half.life.R b/tests/testthat/test-half.life.R index afdb8874..10ad005d 100644 --- a/tests/testthat/test-half.life.R +++ b/tests/testthat/test-half.life.R @@ -996,3 +996,8 @@ test_that("pk.calc.half.life tobit manually.selected.points sets exclude for neg "Negative half-life estimated with manually-selected points" ) }) + +test_that("span.ratio is described as span over half-life, not the inverse (#582)", { + # ret$span.ratio <- (max(data$time) - min(data$time))/ret$half.life + expect_equal(get.interval.cols()[["span.ratio"]]$desc, "Lambda z time span to half-life ratio") +})