diff --git a/R/auc_integrate.R b/R/auc_integrate.R index 336db5ec..15b4a979 100644 --- a/R/auc_integrate.R +++ b/R/auc_integrate.R @@ -183,3 +183,48 @@ auc_integrate <- function(conc, time, clast, tlast, lambda.z, interval_method, f ret <- sum(ret) ret } + +#' Support function for AUMC integration (reuses the same interval_method logic as AUC) +#' +#' @inheritParams auc_integrate +#' @param fun_linear Linear trapezoidal rule for t×conc (AUMC) +#' @param fun_log Log trapezoidal rule for t×conc (AUMC) +#' @param fun_inf Analytical extrapolation to infinity for AUMC +#' +#' @details +#' This function works identically to `auc_integrate()`, but integrates +#' the first moment curve (t × conc) instead of conc. +#' The `interval_method` vector from `choose_interval_method()` is reused directly. +#' +#' @returns The numeric value of the AUMC +#' @keywords internal +aumc_integrate <- function(conc, time, clast, tlast, lambda.z, interval_method, + fun_linear, fun_log, fun_inf) { + assert_lambdaz(lambda.z = lambda.z) + + interval_method_within <- interval_method[-length(interval_method)] + interval_method_extrap <- interval_method[length(interval_method)] + + idx_1 <- seq_len(length(conc) - 1) + idx_1_linear <- idx_1[interval_method_within == "linear"] + idx_1_log <- idx_1[interval_method_within == "log"] + + ret <- + c( + fun_linear(conc[idx_1_linear], conc[idx_1_linear + 1], + time[idx_1_linear], time[idx_1_linear + 1]), + fun_log(conc[idx_1_log], conc[idx_1_log + 1], + time[idx_1_log], time[idx_1_log + 1]) + ) + + if (interval_method_extrap %in% "extrap_log") { + # Whether AUMCinf,obs or AUMCinf,pred is calculated depends on if clast,obs + # or clast,pred is passed in. + ret[length(ret)+1] <- fun_inf(clast, tlast, lambda.z) + } else if (interval_method_extrap != "zero") { + stop("Invalid interval_method_extrap in aumc_integrate, please report a bug: ", interval_method_extrap) # nocov + } + + ret <- sum(ret) + ret +} diff --git a/R/aucint.R b/R/aucint.R index b8aebf86..d739a05b 100644 --- a/R/aucint.R +++ b/R/aucint.R @@ -356,3 +356,323 @@ PKNCA.set.summary( point=business.geomean, spread=business.geocv ) + + +#' Calculate the AUMC over an interval with interpolation and/or +#' extrapolation of concentrations for the beginning and end of the +#' interval. +#' +#' @details +#' When `pk.calc.aumcint()` needs to extrapolate using `lambda.z` (in other +#' words, using the half-life), it will always extrapolate using the logarithmic +#' trapezoidal rule to align with using a half-life calculation for the +#' extrapolation. +#' +#' @inheritParams pk.calc.aucint +#' @family AUMC calculations +#' @returns The AUMC for an interval of time as a number +#' @export +pk.calc.aumcint <- function(conc, time, + interval=NULL, start=NULL, end=NULL, + clast=pk.calc.clast.obs(conc, time), + lambda.z=NA, + time.dose=NULL, + route="extravascular", + duration.dose=0, + method=NULL, + auc.type="AUClast", + conc.blq=NULL, + conc.na=NULL, + check=TRUE, + ..., + options=list()) { + # Check inputs + method <- PKNCA.choose.option(name="auc.method", value=method, options=options) + if (check) { + assert_conc_time(conc, time) + data <- + clean.conc.blq( + conc = conc, time = time, + conc.blq = conc.blq, conc.na = conc.na, options = options, + check = FALSE + ) + } else { + data <- data.frame(conc, time) + } + if (all(data$conc %in% 0)) { + return(structure(0, exclude = "DO NOT EXCLUDE")) + } + interval <- assert_intervaltime_single(interval = interval, start = start, end = end) + missing_times <- + if (is.infinite(interval[2])) { + setdiff(c(interval[1], time.dose), data$time) + } else { + setdiff(c(interval, time.dose), data$time) + } + # Handle the potential double-calculation (before/after tlast) with AUMCinf + conc_clast <- NULL + time_clast <- NULL + if (auc.type %in% "AUCinf") { + tlast <- pk.calc.tlast(conc=data$conc, time=data$time) + clast_obs <- pk.calc.clast.obs(conc=data$conc, time=data$time) + if (is.na(clast) && is.na(lambda.z)) { + # clast.pred is NA likely because the half-life was not calculable + return(structure(NA_real_, exclude = "clast.pred is NA because the half-life is NA")) + } else if (is.na(clast)) { + stop("Please report a bug. clast is NA and the half-life is not NA") # nocov + } else if (clast != clast_obs & interval[2] > tlast) { + # If using clast.pred, we need to doubly calculate at tlast. + conc_clast <- clast + time_clast <- tlast + } + } + extrap_times <- numeric() + if (length(missing_times) > 0) { + if (is.null(time.dose)) { + missing_conc <- + interp.extrap.conc( + conc = data$conc, time = data$time, + time.out = missing_times, + method = method, + auc.type = auc.type, + clast = clast, + lambda.z = lambda.z, + options = options, + ... + ) + } else { + missing_conc <- + interp.extrap.conc.dose( + conc = data$conc, time = data$time, + time.out = missing_times, + method = method, + auc.type = auc.type, + clast = clast, lambda.z = lambda.z, + options = options, + # arguments specific to interp.extrap.conc.dose + time.dose = time.dose, + route.dose = route, + duration.dose = duration.dose, + out.after = FALSE, + ... + ) + } + new_data <- data.frame(conc=c(data$conc, conc_clast, missing_conc), + time=c(data$time, time_clast, missing_times)) + tlast <- pk.calc.tlast(conc = data$conc, time = data$time, check = FALSE) + extrap_times <- missing_times[missing_times > tlast] + new_data <- new_data[new_data$time >= interval[1] & + new_data$time <= interval[2],] + new_data <- new_data[order(new_data$time),] + conc_interp <- new_data$conc + time_interp <- new_data$time + if (any(mask_na_conc <- is.na(conc_interp))) { + missing_times <- time_interp[mask_na_conc] + warning_message <- + if (any(is.na(lambda.z))) { + paste("Some interpolated/extrapolated concentration values are missing", + "(may be due to interpolating or extrapolating over a dose with lambda.z=NA).", + "Time points with missing data are: ", + paste(missing_times, collapse=", ")) + } else { + paste("Some interpolated/extrapolated concentration values are missing", + "Time points with missing data are: ", + paste(missing_times, collapse=", ")) + } + warning(warning_message) + return(NA_real_) + } + } else { + mask_time <- data$time >= interval[1] & data$time <= interval[2] + conc_interp <- data$conc[mask_time] + time_interp <- data$time[mask_time] + } + # AUMCinf traces an AUMClast curve if the interval is finite (because + # the interval doesn't go to infinity) while AUMCall and AUMClast trace + # their own curves. Or, they all trace their own curves. + auc.type_map <- + if (is.infinite(interval[2])) { + list( + AUClast="AUClast", + AUCall="AUCall", + AUCinf="AUCinf" + )[[auc.type]] + } else { + list( + AUClast="AUClast", + AUCall="AUCall", + AUCinf="AUClast" + )[[auc.type]] + } + + interval_method <- + choose_interval_method( + conc = conc_interp, + time = time_interp, + tlast = max(time_interp), + method = method, + auc.type = auc.type, + options = options + ) + if (is.finite(interval[2])) { + interval_method[length(interval_method)] <- "zero" + } + if (length(extrap_times) > 0) { + interval_method[which(time_interp == extrap_times) - 1] <- "log" + } + ret <- + aumc_integrate( + conc = conc_interp, time = time_interp, + clast = clast, tlast = tlast, lambda.z = lambda.z, + interval_method = interval_method, + fun_linear = aumcintegrate_linear, + fun_log = aumcintegrate_log, + fun_inf = aumcintegrate_inf + ) + ret +} + +#' @describeIn pk.calc.aumcint Interpolate or extrapolate concentrations for +#' AUMClast +#' @export +pk.calc.aumcint.last <- function(conc, time, start=NULL, end=NULL, time.dose, ..., options=list()) { + if (missing(time.dose)) + time.dose <- NULL + pk.calc.aumcint(conc=conc, time=time, + start=start, end=end, + options=options, + time.dose=time.dose, + ..., + auc.type="AUClast") +} + +#' @describeIn pk.calc.aumcint Interpolate or extrapolate concentrations for +#' AUMCall +#' @export +pk.calc.aumcint.all <- function(conc, time, start=NULL, end=NULL, time.dose, ..., options=list()) { + if (missing(time.dose)) + time.dose <- NULL + pk.calc.aumcint(conc=conc, time=time, + start=start, end=end, + options=options, + time.dose=time.dose, + ..., + auc.type="AUCall") +} + +#' @describeIn pk.calc.aumcint Interpolate or extrapolate concentrations for +#' AUMCinf.obs +#' @export +pk.calc.aumcint.inf.obs <- function(conc, time, start=NULL, end=NULL, time.dose, lambda.z, clast.obs, ..., options=list()) { + if (missing(time.dose)) + time.dose <- NULL + pk.calc.aumcint(conc=conc, time=time, + start=start, end=end, + time.dose=time.dose, + lambda.z=lambda.z, clast=clast.obs, + options=options, ..., + auc.type="AUCinf") +} + +#' @describeIn pk.calc.aumcint Interpolate or extrapolate concentrations for +#' AUMCinf.pred +#' @export +pk.calc.aumcint.inf.pred <- function(conc, time, start=NULL, end=NULL, time.dose, lambda.z, clast.pred, ..., options=list()) { + if (missing(time.dose)) + time.dose <- NULL + pk.calc.aumcint(conc=conc, time=time, + start=start, end=end, + time.dose=time.dose, + lambda.z=lambda.z, clast=clast.pred, + options=options, ..., + auc.type="AUCinf") +} + + +# aumcint.last (without dose awareness) +add.interval.col("aumcint.last", + FUN="pk.calc.aumcint.last", + values=c(FALSE, TRUE), + unit_type="aumc", + pretty_name="AUMCint (based on AUMClast extrapolation)", + desc="The area under the moment curve in the interval extrapolating from Tlast to infinity with zeros (matching AUMClast)", + formalsmap=list(conc="conc.group", time="time.group", time.dose=NULL)) + +# aumcint.last.dose (WITH dose awareness) +add.interval.col("aumcint.last.dose", + FUN="pk.calc.aumcint.last", + values=c(FALSE, TRUE), + unit_type="aumc", + pretty_name="AUMCint (based on AUMClast extrapolation, dose-aware)", + desc="The area under the moment curve in the interval extrapolating from Tlast to infinity with zeros (matching AUMClast) with dose-aware interpolation/extrapolation of concentrations", + formalsmap=list(conc="conc.group", time="time.group", time.dose="time.dose.group")) + +# aumcint.all (without dose awareness) +add.interval.col("aumcint.all", + FUN="pk.calc.aumcint.all", + values=c(FALSE, TRUE), + unit_type="aumc", + pretty_name="AUMCint (based on AUMCall extrapolation)", + desc="The area under the moment curve in the interval extrapolating from Tlast to infinity with the triangle from Tlast to the next point and zero thereafter (matching AUMCall)", + formalsmap=list(conc="conc.group", time="time.group", time.dose=NULL)) + +# aumcint.all.dose (WITH dose awareness) +add.interval.col("aumcint.all.dose", + FUN="pk.calc.aumcint.all", + values=c(FALSE, TRUE), + unit_type="aumc", + pretty_name="AUMCint (based on AUMCall extrapolation, dose-aware)", + desc="The area under the moment curve in the interval extrapolating from Tlast to infinity with the triangle from Tlast to the next point and zero thereafter (matching AUMCall) with dose-aware interpolation/extrapolation of concentrations", + formalsmap=list(conc="conc.group", time="time.group", time.dose="time.dose.group")) + +# aumcint.inf.obs (without dose awareness) +add.interval.col("aumcint.inf.obs", + FUN="pk.calc.aumcint.inf.obs", + values=c(FALSE, TRUE), + unit_type="aumc", + pretty_name="AUMCint (based on AUMCinf,obs extrapolation)", + desc="The area under the moment curve in the interval extrapolating from Tlast to infinity with zeros (matching AUMClast)", + formalsmap=list(conc="conc.group", time="time.group", time.dose=NULL), + depends=c("lambda.z", "clast.obs")) + +# aumcint.inf.obs.dose (WITH dose awareness) +add.interval.col("aumcint.inf.obs.dose", + FUN="pk.calc.aumcint.inf.obs", + values=c(FALSE, TRUE), + unit_type="aumc", + pretty_name="AUMCint (based on AUMCinf,obs extrapolation, dose-aware)", + desc="The area under the moment curve in the interval extrapolating from Tlast to infinity with zeros (matching AUMClast) with dose-aware interpolation/extrapolation of concentrations", + formalsmap=list(conc="conc.group", time="time.group", time.dose="time.dose.group"), + depends=c("lambda.z", "clast.obs")) + +# aumcint.inf.pred (without dose awareness) +add.interval.col("aumcint.inf.pred", + FUN="pk.calc.aumcint.inf.pred", + values=c(FALSE, TRUE), + unit_type="aumc", + pretty_name="AUMCint (based on AUMCinf,pred extrapolation)", + desc="The area under the moment curve in the interval extrapolating from Tlast to infinity with the triangle from Tlast to the next point and zero thereafter (matching AUMCall)", + formalsmap=list(conc="conc.group", time="time.group", time.dose=NULL), + depends=c("lambda.z", "clast.pred")) + +# aumcint.inf.pred.dose (WITH dose awareness) +add.interval.col("aumcint.inf.pred.dose", + FUN="pk.calc.aumcint.inf.pred", + values=c(FALSE, TRUE), + unit_type="aumc", + pretty_name="AUMCint (based on AUMCinf,pred extrapolation, dose-aware)", + desc="The area under the moment curve in the interval extrapolating from Tlast to infinity with the triangle from Tlast to the next point and zero thereafter (matching AUMCall) with dose-aware interpolation/extrapolation of concentrations", + formalsmap=list(conc="conc.group", time="time.group", time.dose="time.dose.group"), + depends=c("lambda.z", "clast.pred")) + +PKNCA.set.summary( + name = c( + "aumcint.last", "aumcint.last.dose", + "aumcint.all", "aumcint.all.dose", + "aumcint.inf.obs", "aumcint.inf.obs.dose", + "aumcint.inf.pred", "aumcint.inf.pred.dose" + ), + description = "geometric mean and geometric coefficient of variation", + point = business.geomean, + spread = business.geocv +) \ No newline at end of file diff --git a/R/auciv.R b/R/auciv.R index a99c1a52..fb870b1d 100644 --- a/R/auciv.R +++ b/R/auciv.R @@ -198,3 +198,124 @@ PKNCA.set.summary( point=business.mean, spread=business.sd ) + + +#' Calculate AUMC for intravenous dosing with C0 back-extrapolation +#' +#' @details Analogous to pk.calc.auciv but for AUMC. +#' Replaces the first AUMC interval (from measured C0) with one using extrapolated c0. +#' +#' @inheritParams pk.calc.auxc +#' @param c0 The concentration at time 0 (extrapolated) +#' @param aumc The AUMC calculated without c0 adjustment (e.g., aumcall, aumclast) +#' @return The AUMC with IV back-extrapolation applied +#' @export +pk.calc.aumciv <- function(conc, time, c0, aumc, ..., options = list(), check = TRUE) { + if (check) { + assert_conc_time(conc = conc, time = time) + data <- clean.conc.blq(conc, time, options = options, check = FALSE) + } else { + data <- data.frame(conc = conc, time = time) + } + + if (!(0 %in% time)) { + return(structure(NA_real_, exclude = "No time 0 in data")) + } else if (is.na(c0)) { + return(structure(NA_real_, exclude = "c0 is not calculated")) + } + + # AUMC for first interval using measured concentrations + aumc_first <- pk.calc.aumc.last( + conc = data$conc[1:2], + time = data$time[1:2], + ..., + check = FALSE + ) + + # AUMC for first interval using extrapolated c0 + aumc_second <- pk.calc.aumc.last( + conc = c(c0, data$conc[2]), + time = data$time[1:2], + ..., + check = FALSE + ) + + aumc_final <- aumc + aumc_second - aumc_first + aumc_final +} + +# Register all standard AUMC IV versions +add.interval.col( + name = "aumcivlast", + FUN = "pk.calc.aumciv", + unit_type = "aumc", + pretty_name = "AUMClast (IV dosing)", + depends = c("aumclast", "c0"), + desc = "AUMClast with back-extrapolation using extrapolated C0 for IV dosing", + sparse = FALSE, + formalsmap = list(aumc = "aumclast") +) + +add.interval.col( + name = "aumcivall", + FUN = "pk.calc.aumciv", + unit_type = "aumc", + pretty_name = "AUMCall (IV dosing)", + depends = c("aumcall", "c0"), + desc = "AUMCall with back-extrapolation using extrapolated C0 for IV dosing", + sparse = FALSE, + formalsmap = list(aumc = "aumcall") +) + +add.interval.col( + name = "aumcivint.last", + FUN = "pk.calc.aumciv", + unit_type = "aumc", + pretty_name = "AUMCint,last (IV dosing)", + depends = c("aumcint.last", "c0"), + desc = "The AUMCint,last calculated with back-extrapolation for intravenous dosing using extrapolated C0", + sparse = FALSE, + formalsmap = list(aumc = "aumcint.last") +) + +add.interval.col( + name = "aumcivint.all", + FUN = "pk.calc.aumciv", + unit_type = "aumc", + pretty_name = "AUMCint,all (IV dosing)", + depends = c("aumcint.all", "c0"), + desc = "The AUMCint,all calculated with back-extrapolation for intravenous dosing using extrapolated C0", + sparse = FALSE, + formalsmap = list(aumc = "aumcint.all") +) + +add.interval.col( + name = "aumcivinf.obs", + FUN = "pk.calc.aumciv", + unit_type = "aumc", + pretty_name = "AUMCinf,obs (IV dosing)", + depends = c("aumcinf.obs", "c0"), + desc = "AUMCinf,obs with back-extrapolation using extrapolated C0", + sparse = FALSE, + formalsmap = list(aumc = "aumcinf.obs") +) + +add.interval.col( + name = "aumcivinf.pred", + FUN = "pk.calc.aumciv", + unit_type = "aumc", + pretty_name = "AUMCinf,pred (IV dosing)", + depends = c("aumcinf.pred", "c0"), + desc = "AUMCinf,pred with back-extrapolation using extrapolated C0", + sparse = FALSE, + formalsmap = list(aumc = "aumcinf.pred") +) + + +PKNCA.set.summary( + name = c("aumcivlast", "aumcivall", "aumcivinf.obs", "aumcivinf.pred", + "aumcivint.last", "aumcivint.all"), + description = "geometric mean and geometric coefficient of variation", + point = business.geomean, + spread = business.geocv +) \ No newline at end of file diff --git a/R/pk.calc.simple.R b/R/pk.calc.simple.R index c1770600..03d10d5d 100644 --- a/R/pk.calc.simple.R +++ b/R/pk.calc.simple.R @@ -440,12 +440,7 @@ add.interval.col("kel.obs", desc="Elimination rate (as calculated from the MRT with observed Clast)", formalsmap=list(mrt="mrt.obs"), depends="mrt.obs") -PKNCA.set.summary( - name="kel.obs", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("kel.pred", FUN="pk.calc.kel", values=c(FALSE, TRUE), @@ -454,12 +449,7 @@ add.interval.col("kel.pred", desc="Elimination rate (as calculated from the MRT with predicted Clast)", formalsmap=list(mrt="mrt.pred"), depends="mrt.pred") -PKNCA.set.summary( - name="kel.pred", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("kel.last", FUN="pk.calc.kel", values=c(FALSE, TRUE), @@ -468,12 +458,7 @@ add.interval.col("kel.last", desc="Elimination rate (as calculated from the MRT using AUClast)", formalsmap=list(mrt="mrt.last"), depends="mrt.last") -PKNCA.set.summary( - name="kel.last", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("kel.iv.obs", FUN="pk.calc.kel", values=c(FALSE, TRUE), @@ -482,12 +467,7 @@ add.interval.col("kel.iv.obs", desc="Elimination rate (as calculated from the intravenous MRTobs)", formalsmap=list(mrt="mrt.iv.obs"), depends="mrt.iv.obs") -PKNCA.set.summary( - name="kel.iv.obs", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("kel.iv.pred", FUN="pk.calc.kel", values=c(FALSE, TRUE), @@ -496,12 +476,7 @@ add.interval.col("kel.iv.pred", desc="Elimination rate (as calculated from the intravenous MRTpred)", formalsmap=list(mrt="mrt.iv.pred"), depends="mrt.iv.pred") -PKNCA.set.summary( - name="kel.iv.pred", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("kel.iv.last", FUN="pk.calc.kel", values=c(FALSE, TRUE), @@ -510,11 +485,100 @@ add.interval.col("kel.iv.last", desc="Elimination rate (as calculated from the intravenous MRTlast)", formalsmap=list(mrt="mrt.iv.last"), depends="mrt.iv.last") +add.interval.col("kel.all", + FUN = "pk.calc.kel", + values = c(FALSE, TRUE), + unit_type = "inverse_time", + pretty_name = "Kel (based on AUCall)", + desc = "Elimination rate (as calculated from the MRTall)", + formalsmap = list(mrt = "mrt.all"), + depends = "mrt.all") + +add.interval.col("kel.int.all", + FUN = "pk.calc.kel", + values = c(FALSE, TRUE), + unit_type = "inverse_time", + pretty_name = "Kel (based on AUCint.all)", + desc = "Elimination rate (as calculated from the MRTint.all)", + formalsmap = list(mrt = "mrt.int.all"), + depends = "mrt.int.all") + +add.interval.col("kel.int.inf.obs", + FUN = "pk.calc.kel", + values = c(FALSE, TRUE), + unit_type = "inverse_time", + pretty_name = "Kel (based on AUCint.inf.obs)", + desc = "Elimination rate (as calculated from the MRTint.inf.obs)", + formalsmap = list(mrt = "mrt.int.inf.obs"), + depends = "mrt.int.inf.obs") + +add.interval.col("kel.int.inf.pred", + FUN = "pk.calc.kel", + values = c(FALSE, TRUE), + unit_type = "inverse_time", + pretty_name = "Kel (based on AUCint.inf.pred)", + desc = "Elimination rate (as calculated from the MRTint.inf.pred)", + formalsmap = list(mrt = "mrt.int.inf.pred"), + depends = "mrt.int.inf.pred") + +add.interval.col("kel.int.last", + FUN = "pk.calc.kel", + values = c(FALSE, TRUE), + unit_type = "inverse_time", + pretty_name = "Kel (based on AUCint.last)", + desc = "Elimination rate (as calculated from the MRTint.last)", + formalsmap = list(mrt = "mrt.int.last"), + depends = "mrt.int.last") + +add.interval.col("kel.iv.all", + FUN = "pk.calc.kel", + values = c(FALSE, TRUE), + unit_type = "inverse_time", + pretty_name = "Kel (for IV dosing, based on AUCall)", + desc = "Elimination rate (as calculated from the MRTiv.all))", + formalsmap = list(mrt = "mrt.iv.all"), + depends = "mrt.iv.all") + +add.interval.col("kel.ivint.all", + FUN = "pk.calc.kel", + values = c(FALSE, TRUE), + unit_type = "inverse_time", + pretty_name = "Kel (IV dose interval, based on AUCint.all)", + desc = "Elimination rate (as calculated from the MRTivint.all)", + formalsmap = list(mrt = "mrt.ivint.all"), + depends = "mrt.ivint.all") + + +add.interval.col("kel.ivint.last", + FUN = "pk.calc.kel", + values = c(FALSE, TRUE), + unit_type = "inverse_time", + pretty_name = "Kel (IV dose interval, based on AUCint.last)", + desc = "Elimination rate (as calculated from the MRTivint.last)", + formalsmap = list(mrt = "mrt.ivint.last"), + depends = "mrt.ivint.last") + +add.interval.col("kel.sparse.last", + FUN = "pk.calc.kel", + values = c(FALSE, TRUE), + unit_type = "inverse_time", + pretty_name = "Kel (for sparse data, based on AUClast)", + desc = "Elimination rate (as calculated from the MRTsparse.last)", + sparse = TRUE, + formalsmap = list(mrt = "mrt.sparse.last"), + depends = "mrt.sparse.last") + PKNCA.set.summary( - name="kel.iv.last", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv + name = c( + # Elimination rate constant (kel) + "kel.obs", "kel.pred", "kel.last", "kel.iv.obs", "kel.iv.pred", "kel.iv.last", + "kel.all", "kel.int.all", "kel.int.inf.obs", "kel.int.inf.pred", "kel.int.last", + "kel.iv.all", "kel.ivint.all", "kel.ivint.last", + "kel.sparse.last" + ), + description = "geometric mean and geometric coefficient of variation", + point = business.geomean, + spread = business.geocv ) #' Calculate the (observed oral) clearance @@ -556,12 +620,7 @@ add.interval.col("cl.last", desc="Clearance or observed oral clearance calculated to Clast", formalsmap=list(auc="auclast"), depends="auclast") -PKNCA.set.summary( - name="cl.last", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("cl.all", FUN="pk.calc.cl", values=c(FALSE, TRUE), @@ -570,12 +629,7 @@ add.interval.col("cl.all", desc="Clearance or observed oral clearance calculated with AUCall", formalsmap=list(auc="aucall"), depends="aucall") -PKNCA.set.summary( - name="cl.all", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("cl.obs", FUN="pk.calc.cl", values=c(FALSE, TRUE), @@ -584,12 +638,7 @@ add.interval.col("cl.obs", desc="Clearance or observed oral clearance calculated with observed Clast", formalsmap=list(auc="aucinf.obs"), depends="aucinf.obs") -PKNCA.set.summary( - name="cl.obs", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("cl.pred", FUN="pk.calc.cl", values=c(FALSE, TRUE), @@ -598,11 +647,119 @@ add.interval.col("cl.pred", desc="Clearance or observed oral clearance calculated with predicted Clast", formalsmap=list(auc="aucinf.pred"), depends="aucinf.pred") + +add.interval.col("cl.int.all", + FUN = "pk.calc.cl", + values = c(FALSE, TRUE), + unit_type = "clearance", + pretty_name = "CL (based on AUCint.all)", + desc = "Clearance or observed oral clearance calculated with AUCint.all", + formalsmap = list(auc = "aucint.all"), + depends = "aucint.all") + +add.interval.col("cl.int.inf.obs", + FUN = "pk.calc.cl", + values = c(FALSE, TRUE), + unit_type = "clearance", + pretty_name = "CL (based on AUCint.inf.obs)", + desc = "Clearance or observed oral clearance calculated with AUCint.inf.obs", + formalsmap = list(auc = "aucint.inf.obs"), + depends = "aucint.inf.obs") + +add.interval.col("cl.int.inf.pred", + FUN = "pk.calc.cl", + values = c(FALSE, TRUE), + unit_type = "clearance", + pretty_name = "CL (based on AUCint.inf.pred)", + desc = "Clearance or observed oral clearance calculated with AUCint.inf.pred", + formalsmap = list(auc = "aucint.inf.pred"), + depends = "aucint.inf.pred") + +add.interval.col("cl.int.last", + FUN = "pk.calc.cl", + values = c(FALSE, TRUE), + unit_type = "clearance", + pretty_name = "CL (based on AUCint.last)", + desc = "Clearance or observed oral clearance calculated with AUCint.last", + formalsmap = list(auc = "aucint.last"), + depends = "aucint.last") + +add.interval.col("cl.iv.all", + FUN = "pk.calc.cl", + values = c(FALSE, TRUE), + unit_type = "clearance", + pretty_name = "CL (for IV dosing, based on AUCall)", + desc = "Clearance for intravenous dosing calculated with AUCall", + formalsmap = list(auc = "aucivall"), + depends = "aucivall") + +add.interval.col("cl.iv.last", + FUN = "pk.calc.cl", + values = c(FALSE, TRUE), + unit_type = "clearance", + pretty_name = "CL (for IV dosing, based on AUClast)", + desc = "Clearance for intravenous dosing calculated with AUClast", + formalsmap = list(auc = "aucivlast"), + depends = "aucivlast") + +add.interval.col("cl.iv.obs", + FUN = "pk.calc.cl", + values = c(FALSE, TRUE), + unit_type = "clearance", + pretty_name = "CL (for IV dosing, based on AUCinf,obs)", + desc = "Clearance for intravenous dosing calculated with AUCinf,obs", + formalsmap = list(auc = "aucivinf.obs"), + depends = "aucivinf.obs") + +add.interval.col("cl.iv.pred", + FUN = "pk.calc.cl", + values = c(FALSE, TRUE), + unit_type = "clearance", + pretty_name = "CL (for IV dosing, based on AUCinf,pred)", + desc = "Clearance for intravenous dosing calculated with AUCinf,pred", + formalsmap = list(auc = "aucivinf.pred"), + depends = "aucivinf.pred") + +add.interval.col("cl.ivint.all", + FUN = "pk.calc.cl", + values = c(FALSE, TRUE), + unit_type = "clearance", + pretty_name = "CL (IV dose interval, based on AUCint.all)", + desc = "Clearance for intravenous dosing calculated with interval AUCint.all", + formalsmap = list(auc = "aucivint.all"), + depends = "aucivint.all") + +add.interval.col("cl.ivint.last", + FUN = "pk.calc.cl", + values = c(FALSE, TRUE), + unit_type = "clearance", + pretty_name = "CL (IV dose interval, based on AUCint.last)", + desc = "Clearance for intravenous dosing calculated with interval AUCint.last", + formalsmap = list(auc = "aucivint.last"), + depends = "aucivint.last") + +add.interval.col("cl.sparse.last", + FUN = "pk.calc.cl", + values = c(FALSE, TRUE), + unit_type = "clearance", + pretty_name = "CL (for sparse data, based on AUClast)", + desc = "Clearance from sparse sampling calculated with population AUClast", + sparse = TRUE, + formalsmap = list(auc = "sparse_auclast"), + depends = "sparse_auclast") + PKNCA.set.summary( - name="cl.pred", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv + name = c( + # Clearance (observed, predicted, last, all, interpolated, IV, etc.) + "cl.last","cl.all", "cl.obs", "cl.pred", + "cl.int.all", "cl.int.inf.obs", "cl.int.inf.pred", "cl.int.last", + "cl.iv.all", "cl.iv.last", "cl.iv.obs", "cl.iv.pred", + "cl.ivint.all", "cl.ivint.last", + "cl.sparse.last" + ), + description = "geometric mean and geometric coefficient of variation", + point = business.geomean, + spread = business.geocv ) #' Calculate the absolute (or relative) bioavailability @@ -666,12 +823,7 @@ add.interval.col("mrt.obs", desc="The mean residence time to infinity using observed Clast", formalsmap=list(auc="aucinf.obs", aumc="aumcinf.obs"), depends=c("aucinf.obs", "aumcinf.obs")) -PKNCA.set.summary( - name="mrt.obs", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("mrt.pred", FUN="pk.calc.mrt", values=c(FALSE, TRUE), @@ -680,12 +832,7 @@ add.interval.col("mrt.pred", desc="The mean residence time to infinity using predicted Clast", formalsmap=list(auc="aucinf.pred", aumc="aumcinf.pred"), depends=c("aucinf.pred", "aumcinf.pred")) -PKNCA.set.summary( - name="mrt.pred", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("mrt.last", FUN="pk.calc.mrt", values=c(FALSE, TRUE), @@ -694,11 +841,72 @@ add.interval.col("mrt.last", desc="The mean residence time to the last observed concentration above the LOQ", formalsmap=list(auc="auclast", aumc="aumclast"), depends=c("auclast", "aumclast")) + +add.interval.col("mrt.all", + FUN = "pk.calc.mrt", + values = c(FALSE, TRUE), + unit_type = "time", + pretty_name = "MRT (based on AUCall)", + desc = "Mean residence time calculated with AUCall/AUMCall", + formalsmap = list(auc = "aucall", aumc = "aumcall"), + depends = c("aucall", "aumcall")) + +add.interval.col("mrt.int.all", + FUN = "pk.calc.mrt", + values = c(FALSE, TRUE), + unit_type = "time", + pretty_name = "MRT (based on AUCint.all)", + desc = "Mean residence time over interval calculated with AUCint.all/AUMCint.all", + formalsmap = list(auc = "aucint.all", aumc = "aumcint.all"), + depends = c("aucint.all", "aumcint.all")) + +add.interval.col("mrt.int.inf.obs", + FUN = "pk.calc.mrt", + values = c(FALSE, TRUE), + unit_type = "time", + pretty_name = "MRT (based on AUCint.inf.obs)", + desc = "Mean residence time over interval calculated with AUCint.inf.obs/AUMCint.inf.obs", + formalsmap = list(auc = "aucint.inf.obs", aumc = "aumcint.inf.obs"), + depends = c("aucint.inf.obs", "aumcint.inf.obs")) + +add.interval.col("mrt.int.inf.pred", + FUN = "pk.calc.mrt", + values = c(FALSE, TRUE), + unit_type = "time", + pretty_name = "MRT (based on AUCint.inf.pred)", + desc = "Mean residence time over interval calculated with AUCint.inf.pred/AUMCint.inf.pred", + formalsmap = list(auc = "aucint.inf.pred", aumc = "aumcint.inf.pred"), + depends = c("aucint.inf.pred", "aumcint.inf.pred")) + +add.interval.col("mrt.int.last", + FUN = "pk.calc.mrt", + values = c(FALSE, TRUE), + unit_type = "time", + pretty_name = "MRT (based on AUCint.last)", + desc = "Mean residence time over interval calculated with AUCint.last/AUMCint.last", + formalsmap = list(auc = "aucint.last", aumc = "aumcint.last"), + depends = c("aucint.last", "aumcint.last")) + +add.interval.col("mrt.sparse.last", + FUN = "pk.calc.mrt", + values = c(FALSE, TRUE), + unit_type = "time", + pretty_name = "MRT (for sparse data, based on AUClast)", + desc = "Mean residence time from sparse sampling", + sparse = TRUE, + formalsmap = list(auc = "sparse_auclast", aumc = "sparse_aumclast"), + depends = c("sparse_auclast", "sparse_aumclast")) + PKNCA.set.summary( - name="mrt.last", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv + name = c( + # Mean residence time (MRT) + "mrt.obs", "mrt.pred", "mrt.last", "mrt.last", "mrt.all", + "mrt.int.all", "mrt.int.inf.obs", "mrt.int.inf.pred", "mrt.int.last", + "mrt.sparse.last" + ), + description = "geometric mean and geometric coefficient of variation", + point = business.geomean, + spread = business.geocv ) #' @describeIn pk.calc.mrt MRT for an IV infusion @@ -720,12 +928,7 @@ add.interval.col("mrt.iv.obs", desc="The mean residence time to infinity using observed Clast correcting for dosing duration", formalsmap=list(auc="aucinf.obs", aumc="aumcinf.obs"), depends=c("aucinf.obs", "aumcinf.obs")) -PKNCA.set.summary( - name="mrt.iv.obs", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("mrt.iv.pred", FUN="pk.calc.mrt.iv", values=c(FALSE, TRUE), @@ -734,12 +937,7 @@ add.interval.col("mrt.iv.pred", desc="The mean residence time to infinity using predicted Clast correcting for dosing duration", formalsmap=list(auc="aucinf.pred", aumc="aumcinf.pred"), depends=c("aucinf.pred", "aumcinf.pred")) -PKNCA.set.summary( - name="mrt.iv.pred", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("mrt.iv.last", FUN="pk.calc.mrt.iv", values=c(FALSE, TRUE), @@ -748,11 +946,43 @@ add.interval.col("mrt.iv.last", desc="The mean residence time to the last observed concentration above the LOQ correcting for dosing duration", formalsmap=list(auc="auclast", aumc="aumclast"), depends=c("auclast", "aumclast")) + +add.interval.col("mrt.iv.all", + FUN = "pk.calc.mrt.iv", + values = c(FALSE, TRUE), + unit_type = "time", + pretty_name = "MRT (for IV dosing, based on AUCall)", + desc = "Mean residence time for IV dosing calculated with AUCall/AUMCall", + formalsmap = list(auc = "aucivall", aumc = "aumcivall"), + depends = c("aucivall", "aumcivall")) + +add.interval.col("mrt.ivint.all", + FUN = "pk.calc.mrt.iv", + values = c(FALSE, TRUE), + unit_type = "time", + pretty_name = "MRT (IV dose interval, based on AUCint.all)", + desc = "Mean residence time for IV interval calculated with AUCint.all/AUMCint.all", + formalsmap = list(auc = "aucivint.all", aumc = "aumcivint.all"), + depends = c("aucivint.all", "aumcivint.all")) + +add.interval.col("mrt.ivint.last", + FUN = "pk.calc.mrt.iv", + values = c(FALSE, TRUE), + unit_type = "time", + pretty_name = "MRT (IV dose interval, based on AUCint.last)", + desc = "Mean residence time for IV interval calculated with AUCint.last/AUMCint.last", + formalsmap = list(auc = "aucivint.last", aumc = "aumcivint.last"), + depends = c("aucivint.last", "aumcivint.last")) + PKNCA.set.summary( - name="mrt.iv.last", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv + name = c( + # Mean residence time (MRT) + "mrt.iv.obs", "mrt.iv.pred", "mrt.iv.last", + "mrt.iv.all", "mrt.ivint.all", "mrt.ivint.last" + ), + description = "geometric mean and geometric coefficient of variation", + point = business.geomean, + spread = business.geocv ) #' Calculate the mean residence time (MRT) for multiple-dose data with nonlinear @@ -833,12 +1063,7 @@ add.interval.col("vz.obs", desc="The terminal volume of distribution using observed Clast", formalsmap=list(cl="cl.obs"), depends=c("cl.obs", "lambda.z")) -PKNCA.set.summary( - name="vz.obs", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("vz.pred", FUN="pk.calc.vz", values=c(FALSE, TRUE), @@ -847,11 +1072,136 @@ add.interval.col("vz.pred", desc="The terminal volume of distribution using predicted Clast", formalsmap=list(cl="cl.pred"), depends=c("cl.pred", "lambda.z")) + +add.interval.col("vz.all", + FUN = "pk.calc.vz", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vz (based on AUCall)", + desc = "Terminal volume of distribution calculated with AUCall-based CL", + formalsmap = list(cl = "cl.all"), + depends = c("cl.all", "lambda.z")) + +add.interval.col("vz.int.all", + FUN = "pk.calc.vz", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vz (based on AUCint.all)", + desc = "Terminal volume of distribution using interval AUCint.all", + formalsmap = list(cl = "cl.int.all"), + depends = c("cl.int.all", "lambda.z")) + +add.interval.col("vz.int.inf.obs", + FUN = "pk.calc.vz", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vz (based on AUCint.inf.obs)", + desc = "Terminal volume of distribution using interval AUCint.inf.obs", + formalsmap = list(cl = "cl.int.inf.obs"), + depends = c("cl.int.inf.obs", "lambda.z")) + +add.interval.col("vz.int.inf.pred", + FUN = "pk.calc.vz", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vz (based on AUCint.inf.pred)", + desc = "Terminal volume of distribution using interval AUCint.inf.pred", + formalsmap = list(cl = "cl.int.inf.pred"), + depends = c("cl.int.inf.pred", "lambda.z")) + +add.interval.col("vz.int.last", + FUN = "pk.calc.vz", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vz (based on AUCint.last)", + desc = "Terminal volume of distribution using interval AUCint.last", + formalsmap = list(cl = "cl.int.last"), + depends = c("cl.int.last", "lambda.z")) + +add.interval.col("vz.iv.all", + FUN = "pk.calc.vz", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vz (for IV dosing, based on AUCall)", + desc = "Terminal volume of distribution for IV dosing using AUCall", + formalsmap = list(cl = "cl.iv.all"), + depends = c("cl.iv.all", "lambda.z")) + +add.interval.col("vz.iv.last", + FUN = "pk.calc.vz", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vz (for IV dosing, based on AUClast)", + desc = "Terminal volume of distribution for IV dosing using AUClast", + formalsmap = list(cl = "cl.iv.last"), + depends = c("cl.iv.last", "lambda.z")) + +add.interval.col("vz.iv.obs", + FUN = "pk.calc.vz", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vz (for IV dosing, based on AUCinf,obs)", + desc = "Terminal volume of distribution for IV dosing using observed AUCinf", + formalsmap = list(cl = "cl.iv.obs"), + depends = c("cl.iv.obs", "lambda.z")) + +add.interval.col("vz.iv.pred", + FUN = "pk.calc.vz", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vz (for IV dosing, based on AUCinf,pred)", + desc = "Terminal volume of distribution for IV dosing using predicted AUCinf", + formalsmap = list(cl = "cl.iv.pred"), + depends = c("cl.iv.pred", "lambda.z")) + +add.interval.col("vz.ivint.all", + FUN = "pk.calc.vz", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vz (IV dose interval, based on AUCint.all)", + desc = "Terminal volume of distribution for IV interval using AUCint.all", + formalsmap = list(cl = "cl.ivint.all"), + depends = c("cl.ivint.all", "lambda.z")) + +add.interval.col("vz.ivint.last", + FUN = "pk.calc.vz", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vz (IV dose interval, based on AUCint.last)", + desc = "Terminal volume of distribution for IV interval using AUCint.last", + formalsmap = list(cl = "cl.ivint.last"), + depends = c("cl.ivint.last", "lambda.z")) + +add.interval.col("vz.last", + FUN = "pk.calc.vz", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vz (based on AUClast)", + desc = "Terminal volume of distribution calculated with AUClast-based CL", + formalsmap = list(cl = "cl.last"), + depends = c("cl.last", "lambda.z")) + +add.interval.col("vz.sparse.last", + FUN = "pk.calc.vz", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vz (for sparse data, based on AUClast)", + desc = "Terminal volume of distribution from sparse sampling", + sparse = TRUE, + formalsmap = list(cl = "cl.sparse.last"), + depends = c("cl.sparse.last", "lambda.z")) + PKNCA.set.summary( - name="vz.pred", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv + name = c( + # Volume of distribution (Vz) + "vz.obs", "vz.pred", + "vz.all", "vz.int.all", "vz.int.inf.obs", "vz.int.inf.pred", + "vz.int.last", "vz.iv.all", "vz.iv.last", "vz.iv.obs", "vz.iv.pred", + "vz.ivint.all", "vz.ivint.last", "vz.last", "vz.sparse.last" + ), + description = "geometric mean and geometric coefficient of variation", + point = business.geomean, + spread = business.geocv ) #' Calculate the steady-state volume of distribution (Vss) @@ -873,12 +1223,7 @@ add.interval.col("vss.obs", desc="The steady-state volume of distribution using observed Clast", formalsmap=list(cl="cl.obs", mrt="mrt.obs"), depends=c("cl.obs", "mrt.obs")) -PKNCA.set.summary( - name="vss.obs", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("vss.pred", FUN="pk.calc.vss", values=c(FALSE, TRUE), @@ -887,12 +1232,7 @@ add.interval.col("vss.pred", desc="The steady-state volume of distribution using predicted Clast", formalsmap=list(cl="cl.pred", mrt="mrt.pred"), depends=c("cl.pred", "mrt.pred")) -PKNCA.set.summary( - name="vss.pred", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("vss.last", FUN="pk.calc.vss", values=c(FALSE, TRUE), @@ -901,12 +1241,7 @@ add.interval.col("vss.last", desc="The steady-state volume of distribution calculating through Tlast", formalsmap=list(cl="cl.last", mrt="mrt.last"), depends=c("cl.last", "mrt.last")) -PKNCA.set.summary( - name="vss.last", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("vss.iv.obs", FUN="pk.calc.vss", values=c(FALSE, TRUE), @@ -915,12 +1250,7 @@ add.interval.col("vss.iv.obs", desc="The steady-state volume of distribution with intravenous infusion using observed Clast", formalsmap=list(cl="cl.obs", mrt="mrt.iv.obs"), depends=c("cl.obs", "mrt.iv.obs")) -PKNCA.set.summary( - name="vss.iv.obs", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("vss.iv.pred", FUN="pk.calc.vss", values=c(FALSE, TRUE), @@ -929,12 +1259,7 @@ add.interval.col("vss.iv.pred", desc="The steady-state volume of distribution with intravenous infusion using predicted Clast", formalsmap=list(cl="cl.pred", mrt="mrt.iv.pred"), depends=c("cl.pred", "mrt.iv.pred")) -PKNCA.set.summary( - name="vss.iv.pred", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("vss.iv.last", FUN="pk.calc.vss", values=c(FALSE, TRUE), @@ -943,12 +1268,6 @@ add.interval.col("vss.iv.last", desc="The steady-state volume of distribution with intravenous infusion calculating through Tlast", formalsmap=list(cl="cl.last", mrt="mrt.iv.last"), depends=c("cl.last", "mrt.iv.last")) -PKNCA.set.summary( - name="vss.iv.last", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) add.interval.col("vss.md.obs", FUN="pk.calc.vss", @@ -958,12 +1277,7 @@ add.interval.col("vss.md.obs", desc="The steady-state volume of distribution for nonlinear multiple-dose data using observed Clast", formalsmap=list(cl="cl.last", mrt="mrt.md.obs"), depends=c("cl.last", "mrt.md.obs")) -PKNCA.set.summary( - name="vss.md.obs", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv -) + add.interval.col("vss.md.pred", FUN="pk.calc.vss", values=c(FALSE, TRUE), @@ -972,11 +1286,100 @@ add.interval.col("vss.md.pred", desc="The steady-state volume of distribution for nonlinear multiple-dose data using predicted Clast", formalsmap=list(cl="cl.last", mrt="mrt.md.pred"), depends=c("cl.last", "mrt.md.pred")) + +add.interval.col("vss.all", + FUN = "pk.calc.vss", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vss (based on AUCall)", + desc = "Steady-state volume of distribution calculated with AUCall-based CL and MRT", + formalsmap = list(cl = "cl.all", mrt = "mrt.all"), + depends = c("cl.all", "mrt.all")) + +add.interval.col("vss.int.all", + FUN = "pk.calc.vss", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vss (based on AUCint.all)", + desc = "Steady-state volume of distribution using interval AUCint.all", + formalsmap = list(cl = "cl.int.all", mrt = "mrt.int.all"), + depends = c("cl.int.all", "mrt.int.all")) + +add.interval.col("vss.int.inf.obs", + FUN = "pk.calc.vss", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vss (based on AUCint.inf.obs)", + desc = "Steady-state volume of distribution using interval AUCint.inf.obs", + formalsmap = list(cl = "cl.int.inf.obs", mrt = "mrt.int.inf.obs"), + depends = c("cl.int.inf.obs", "mrt.int.inf.obs")) + +add.interval.col("vss.int.inf.pred", + FUN = "pk.calc.vss", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vss (based on AUCint.inf.pred)", + desc = "Steady-state volume of distribution using interval AUCint.inf.pred", + formalsmap = list(cl = "cl.int.inf.pred", mrt = "mrt.int.inf.pred"), + depends = c("cl.int.inf.pred", "mrt.int.inf.pred")) + +add.interval.col("vss.int.last", + FUN = "pk.calc.vss", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vss (based on AUCint.last)", + desc = "Steady-state volume of distribution using interval AUCint.last", + formalsmap = list(cl = "cl.int.last", mrt = "mrt.int.last"), + depends = c("cl.int.last", "mrt.int.last")) + +add.interval.col("vss.iv.all", + FUN = "pk.calc.vss", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vss (for IV dosing, based on AUCall)", + desc = "Steady-state volume of distribution for IV dosing using AUCall", + formalsmap = list(cl = "cl.iv.all", mrt = "mrt.iv.all"), + depends = c("cl.iv.all", "mrt.iv.all")) + +add.interval.col("vss.ivint.all", + FUN = "pk.calc.vss", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vss (IV dose interval, based on AUCint.all)", + desc = "Steady-state volume of distribution for IV interval using AUCint.all", + formalsmap = list(cl = "cl.ivint.all", mrt = "mrt.ivint.all"), + depends = c("cl.ivint.all", "mrt.ivint.all")) + +add.interval.col("vss.ivint.last", + FUN = "pk.calc.vss", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vss (IV dose interval, based on AUCint.last)", + desc = "Steady-state volume of distribution for IV interval using AUCint.last", + formalsmap = list(cl = "cl.ivint.last", mrt = "mrt.ivint.last"), + depends = c("cl.ivint.last", "mrt.ivint.last")) + +add.interval.col("vss.sparse.last", + FUN = "pk.calc.vss", + values = c(FALSE, TRUE), + unit_type = "volume", + pretty_name = "Vss (for sparse data, based on AUClast)", + desc = "Steady-state volume of distribution from sparse sampling", + sparse = TRUE, + formalsmap = list(cl = "cl.sparse.last", mrt = "mrt.sparse.last"), + depends = c("cl.sparse.last", "mrt.sparse.last")) + PKNCA.set.summary( - name="vss.md.pred", - description="geometric mean and geometric coefficient of variation", - point=business.geomean, - spread=business.geocv + name = c( + # Volume of distribution at steady state (Vss) + "vss.obs", "vss.pred", "vss.last", "vss.iv.obs", "vss.iv.pred", "vss.iv.last", + "vss.md.obs", "vss.md.pred", "vss.all", + "vss.int.all", "vss.int.inf.obs", "vss.int.inf.pred", "vss.int.last", + "vss.iv.all", "vss.ivint.all", "vss.ivint.last", "vss.sparse.last" + ), + description = "geometric mean and geometric coefficient of variation", + point = business.geomean, + spread = business.geocv ) #' Calculate the average concentration during an interval. diff --git a/R/sparse.R b/R/sparse.R index 7a59f2cc..cff1710b 100644 --- a/R/sparse.R +++ b/R/sparse.R @@ -401,3 +401,184 @@ PKNCA.set.summary( is_sparse_pk <- function(object) { UseMethod("is_sparse_pk") } + + + +#' Calculate the variance for the AUMC of sparsely sampled PK +#' +#' This function calculates the variance of the area under the first moment +#' curve (AUMC) for sparse PK data. It follows the same methodology as +#' [var_sparse_auc()] but applies to the moment curve (time × concentration). +#' +#' Equation 7.vii in Nedelman and Jia, 1998 is adapted for AUMC: +#' +#' \deqn{var\left(\hat{AUMC}\right) = \sum\limits_{i=0}^m\left(\frac{w_i^2 s_i^2}{r_i}\right) + 2\sum\limits_{i 0) { + rlang::warn( + message = "Cannot yet calculate sparse degrees of freedom for multiple samples per subject", + class = "pknca_sparse_df_multi" + ) + df <- NA_real_ + } + + attr(var_aumc, "df") <- df + var_aumc +} + +#' Calculate AUMC and related parameters using sparse NCA methods +#' +#' This is the exact analog of [pk.calc.sparse_auc()] but for the first moment curve. +#' +#' @inheritParams pk.calc.sparse_auc +#' @returns A data.frame with columns: +#' \item{sparse_aumc}{The estimated AUMC} +#' \item{sparse_aumc_se}{Standard error of the AUMC estimate} +#' \item{sparse_aumc_df}{Degrees of freedom for the variance estimate} +#' @family Sparse Methods +#' @export +pk.calc.sparse_aumc <- function(conc, time, subject, + method = NULL, + auc.type = "AUClast", + ..., + options = list()) { + sparse_pk <- as_sparse_pk(conc = conc, time = time, subject = subject) + sparse_pk_wt <- sparse_auc_weight_linear(sparse_pk) + sparse_pk_mean <- sparse_mean(sparse_pk = sparse_pk_wt, + sparse_mean_method = "arithmetic mean, <=50% BLQ") + + aumc <- + pk.calc.aumc( + conc = sparse_pk_attribute(sparse_pk_mean, "mean"), + time = sparse_pk_attribute(sparse_pk_mean, "time"), + auc.type = auc.type, + method = "linear" + ) + + var_aumc <- var_sparse_aumc(sparse_pk_mean) + + data.frame( + sparse_aumc = aumc, + sparse_aumc_se = sqrt(as.numeric(var_aumc)), + sparse_aumc_df = attr(var_aumc, "df") + ) +} + +#' @describeIn pk.calc.sparse_aumc Compute the AUMClast for sparse PK +#' @export +pk.calc.sparse_aumclast <- function(conc, time, subject, ..., options = list()) { + if ("auc.type" %in% names(list(...))) { + rlang::abort( + message = "auc.type cannot be changed when calling pk.calc.sparse_aumclast, please use pk.calc.sparse_aumc", + class = "pknca_sparse_aumclast_change_auc_type" + ) + } + ret <- pk.calc.sparse_aumc( + conc = conc, time = time, subject = subject, + ..., options = options, + auc.type = "AUClast", + lambda.z = NA + ) + names(ret)[names(ret) == "sparse_aumc"] <- "sparse_aumclast" + ret +} + +# Column registrations +add.interval.col( + "sparse_aumclast", + sparse = TRUE, + FUN = "pk.calc.sparse_aumclast", + values = c(FALSE, TRUE), + unit_type = "aumc", + pretty_name = "Sparse AUMClast", + desc = "For sparse PK sampling, the area under the moment curve from the beginning of the interval to the last concentration above the limit of quantification" +) +PKNCA.set.summary( + name = "sparse_aumclast", + description = "geometric mean and geometric coefficient of variation", + point = business.geomean, + spread = business.geocv +) + +add.interval.col( + "sparse_aumc_se", + FUN = NA, + values = c(FALSE, TRUE), + unit_type = "aumc", + pretty_name = "Sparse AUMC standard error", + desc = "For sparse PK sampling, the standard error of the area under the moment curve", + depends = "sparse_aumclast" +) +PKNCA.set.summary( + name = "sparse_aumc_se", + description = "arithmetic mean and standard deviation", + point = business.mean, + spread = business.sd +) + +add.interval.col( + "sparse_aumc_df", + FUN = NA, + values = c(FALSE, TRUE), + unit_type = "count", + pretty_name = "Sparse AUMC degrees of freedom", + desc = "For sparse PK sampling, the degrees of freedom for the AUMC variance estimate", + depends = "sparse_aumclast" +) +PKNCA.set.summary( + name = "sparse_aumc_df", + description = "arithmetic mean and standard deviation", + point = business.mean, + spread = business.sd +)