diff --git a/NAMESPACE b/NAMESPACE index 1d625987..a54dc6cf 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -189,6 +189,12 @@ export(pk.calc.aumc.inf) export(pk.calc.aumc.inf.obs) export(pk.calc.aumc.inf.pred) export(pk.calc.aumc.last) +export(pk.calc.aumcint) +export(pk.calc.aumcint.all) +export(pk.calc.aumcint.inf.obs) +export(pk.calc.aumcint.inf.pred) +export(pk.calc.aumcint.last) +export(pk.calc.aumciv) export(pk.calc.auxc) export(pk.calc.c0) export(pk.calc.cav) @@ -204,6 +210,9 @@ export(pk.calc.cstart) export(pk.calc.ctrough) export(pk.calc.deg.fluc) export(pk.calc.dn) +export(pk.calc.ermax) +export(pk.calc.ertlst) +export(pk.calc.ertmax) export(pk.calc.f) export(pk.calc.fe) export(pk.calc.half.life) @@ -214,6 +223,8 @@ export(pk.calc.mrt.md) export(pk.calc.ptr) export(pk.calc.sparse_auc) export(pk.calc.sparse_auclast) +export(pk.calc.sparse_aumc) +export(pk.calc.sparse_aumclast) export(pk.calc.swing) export(pk.calc.tfirst) export(pk.calc.thalf.eff) @@ -244,6 +255,7 @@ export(superposition) export(time_calc) export(ungroup) export(var_sparse_auc) +export(var_sparse_aumc) importFrom(dplyr,"%>%") importFrom(dplyr,filter) importFrom(dplyr,full_join) diff --git a/R/PKNCA.options.R b/R/PKNCA.options.R index ee567009..d0d580de 100644 --- a/R/PKNCA.options.R +++ b/R/PKNCA.options.R @@ -142,6 +142,28 @@ } x }, + first.ertmax=function(x, default=FALSE, description=FALSE) { + if (description) + return(paste( + "If there is more than one concentration equal to maximum excretion rate, which time", + "should be selected for ertmax? If 'TRUE', the first will be selected.", + "If 'FALSE', the last will be selected.")) + if (default) + return(TRUE) + if (length(x) != 1) + stop("first.ertmax must be a scalar") + if (is.na(x)) + stop("first.ertmax may not be NA") + if (!is.logical(x)) { + x <- as.logical(x) + if (is.na(x)) { + stop("Could not convert first.ertmax to a logical value") + } else { + warning("Converting first.ertmax to a logical value: ", x) + } + } + x + }, first.tmax=function(x, default=FALSE, description=FALSE) { if (description) return(paste( @@ -579,4 +601,3 @@ PKNCA.set.summary <- function(name, description, point, spread, assign("summary", current, envir=.PKNCAEnv) invisible(current) } - diff --git a/R/pk.calc.urine.R b/R/pk.calc.urine.R index 3ac84472..3c4ef25e 100644 --- a/R/pk.calc.urine.R +++ b/R/pk.calc.urine.R @@ -240,11 +240,11 @@ PKNCA.set.summary( #' @param time The starting time of the collection interval #' @param duration.conc The duration of the collection interval #' @param check Should the concentration and time data be checked? -#' @param first.tmax If TRUE, return the first time of maximum excretion rate; otherwise, return the last +#' @param first.ertmax If TRUE, return the first time of maximum excretion rate; otherwise, return the last #' @return The midpoint collection time of the maximum excretion rate, or NA if not available #' @export -pk.calc.ertmax <- function(conc, volume, time, duration.conc, check = TRUE, first.tmax = NULL) { - +pk.calc.ertmax <- function(conc, volume, time, duration.conc, check = TRUE, first.ertmax = NULL) { + first.ertmax <- PKNCA.choose.option(name="first.ertmax", value=first.ertmax, options=options) # Generate messages about missing concentrations/volumes message_all <- generate_missing_messages(conc, volume, name_a = "concentrations", @@ -258,7 +258,7 @@ pk.calc.ertmax <- function(conc, volume, time, duration.conc, check = TRUE, firs midtime <- time + duration.conc / 2 ret <- midtime[er %in% ermax] - if (first.tmax) { + if (first.ertmax) { ret <- ret[1] } else { ret <- ret[length(ret)] @@ -299,32 +299,32 @@ generate_missing_messages <- function(a, b, mask_a <- is.na(a) mask_b <- is.na(b) - + mask_both <- mask_a & mask_b mask_a_only <- mask_a & !mask_both mask_b_only <- mask_b & !mask_both - + msg_both <- msg_a <- msg_b <- NA_character_ n <- length(mask_a) - + if (all(mask_both)) { msg_both <- sprintf("All %s and %s are missing", name_a, name_b) } else if (any(mask_both)) { msg_both <- sprintf("%g of %g %s and %s are missing", sum(mask_both), n, name_a, name_b) } - + if (all(mask_a_only)) { msg_a <- sprintf("All %s are missing", name_a) } else if (any(mask_a_only)) { msg_a <- sprintf("%g of %g %s are missing", sum(mask_a_only), n, name_a) } - + if (all(mask_b_only)) { msg_b <- sprintf("All %s are missing", name_b) } else if (any(mask_b_only)) { msg_b <- sprintf("%g of %g %s are missing", sum(mask_b_only), n, name_b) } - + # Return non-NA messages stats::na.omit(c(msg_both, msg_a, msg_b)) } diff --git a/man/as_sparse_pk.Rd b/man/as_sparse_pk.Rd index 4cf7fd98..2bf13b3d 100644 --- a/man/as_sparse_pk.Rd +++ b/man/as_sparse_pk.Rd @@ -25,6 +25,7 @@ Generate a sparse_pk object \seealso{ Other Sparse Methods: \code{\link{pk.calc.sparse_auc}()}, +\code{\link{pk.calc.sparse_aumc}()}, \code{\link{sparse_auc_weight_linear}()}, \code{\link{sparse_mean}()} } diff --git a/man/aumc_integrate.Rd b/man/aumc_integrate.Rd new file mode 100644 index 00000000..815390bf --- /dev/null +++ b/man/aumc_integrate.Rd @@ -0,0 +1,51 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auc_integrate.R +\name{aumc_integrate} +\alias{aumc_integrate} +\title{Support function for AUMC integration (reuses the same interval_method logic as AUC)} +\usage{ +aumc_integrate( + conc, + time, + clast, + tlast, + lambda.z, + interval_method, + fun_linear, + fun_log, + fun_inf +) +} +\arguments{ +\item{conc}{Measured concentrations} + +\item{time}{Time of the measurement of the concentrations} + +\item{clast}{The last concentration above the limit of quantification} + +\item{tlast}{Time of last concentration above the limit of quantification +(will be calculated, if not provided)} + +\item{lambda.z}{The elimination rate (in units of inverse time) for +extrapolation} + +\item{interval_method}{The method for integrating each interval of \code{conc}} + +\item{fun_linear}{Linear trapezoidal rule for t×conc (AUMC)} + +\item{fun_log}{Log trapezoidal rule for t×conc (AUMC)} + +\item{fun_inf}{Analytical extrapolation to infinity for AUMC} +} +\value{ +The numeric value of the AUMC +} +\description{ +Support function for AUMC integration (reuses the same interval_method logic as AUC) +} +\details{ +This function works identically to \code{auc_integrate()}, but integrates +the first moment curve (t × conc) instead of conc. +The \code{interval_method} vector from \code{choose_interval_method()} is reused directly. +} +\keyword{internal} diff --git a/man/pk.calc.aumcint.Rd b/man/pk.calc.aumcint.Rd new file mode 100644 index 00000000..019ae8b0 --- /dev/null +++ b/man/pk.calc.aumcint.Rd @@ -0,0 +1,153 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/aucint.R +\name{pk.calc.aumcint} +\alias{pk.calc.aumcint} +\alias{pk.calc.aumcint.last} +\alias{pk.calc.aumcint.all} +\alias{pk.calc.aumcint.inf.obs} +\alias{pk.calc.aumcint.inf.pred} +\title{Calculate the AUMC over an interval with interpolation and/or +extrapolation of concentrations for the beginning and end of the +interval.} +\usage{ +pk.calc.aumcint( + 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() +) + +pk.calc.aumcint.last( + conc, + time, + start = NULL, + end = NULL, + time.dose, + ..., + options = list() +) + +pk.calc.aumcint.all( + conc, + time, + start = NULL, + end = NULL, + time.dose, + ..., + options = list() +) + +pk.calc.aumcint.inf.obs( + conc, + time, + start = NULL, + end = NULL, + time.dose, + lambda.z, + clast.obs, + ..., + options = list() +) + +pk.calc.aumcint.inf.pred( + conc, + time, + start = NULL, + end = NULL, + time.dose, + lambda.z, + clast.pred, + ..., + options = list() +) +} +\arguments{ +\item{conc}{Measured concentrations} + +\item{time}{Time of the measurement of the concentrations} + +\item{interval}{Numeric vector of two numbers for the start and end time of +integration} + +\item{start}{The start time of the interval} + +\item{end}{The end time of the interval} + +\item{clast, clast.obs, clast.pred}{The last concentration above the limit of +quantification; this is used for AUCinf calculations. If provided as +clast.obs (observed clast value, default), AUCinf is AUCinf,obs. If +provided as clast.pred, AUCinf is AUCinf,pred.} + +\item{lambda.z}{The elimination rate (in units of inverse time) for +extrapolation} + +\item{time.dose, route, duration.dose}{The time of doses, route of +administration, and duration of dose used with interpolation and +extrapolation of concentration data (see \code{\link[=interp.extrap.conc.dose]{interp.extrap.conc.dose()}}). If +\code{NULL}, \code{\link[=interp.extrap.conc]{interp.extrap.conc()}} will be used instead (assuming that no doses +affecting concentrations are in the interval).} + +\item{method}{The method for integration (one of 'lin up/log down', +'lin-log', or 'linear')} + +\item{auc.type}{The type of AUC to compute. Choices are 'AUCinf', 'AUClast', +and 'AUCall'.} + +\item{conc.blq}{How to handle BLQ values in between the first and last above +LOQ concentrations. (See \code{\link[=clean.conc.blq]{clean.conc.blq()}} for usage instructions.)} + +\item{conc.na}{How to handle missing concentration values. (See +\code{\link[=clean.conc.na]{clean.conc.na()}} for usage instructions.)} + +\item{check}{Run \code{\link[=assert_conc_time]{assert_conc_time()}}, \code{\link[=clean.conc.blq]{clean.conc.blq()}}, and +\code{\link[=clean.conc.na]{clean.conc.na()}}?} + +\item{...}{Additional arguments passed to \code{pk.calc.auxc} and +\code{interp.extrap.conc}} + +\item{options}{List of changes to the default PKNCA options (see +\code{PKNCA.options()})} +} +\value{ +The AUMC for an interval of time as a number +} +\description{ +Calculate the AUMC over an interval with interpolation and/or +extrapolation of concentrations for the beginning and end of the +interval. +} +\details{ +When \code{pk.calc.aumcint()} needs to extrapolate using \code{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. +} +\section{Functions}{ +\itemize{ +\item \code{pk.calc.aumcint.last()}: Interpolate or extrapolate concentrations for +AUMClast + +\item \code{pk.calc.aumcint.all()}: Interpolate or extrapolate concentrations for +AUMCall + +\item \code{pk.calc.aumcint.inf.obs()}: Interpolate or extrapolate concentrations for +AUMCinf.obs + +\item \code{pk.calc.aumcint.inf.pred()}: Interpolate or extrapolate concentrations for +AUMCinf.pred + +}} +\concept{AUMC calculations} diff --git a/man/pk.calc.aumciv.Rd b/man/pk.calc.aumciv.Rd new file mode 100644 index 00000000..22b70ea6 --- /dev/null +++ b/man/pk.calc.aumciv.Rd @@ -0,0 +1,36 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auciv.R +\name{pk.calc.aumciv} +\alias{pk.calc.aumciv} +\title{Calculate AUMC for intravenous dosing with C0 back-extrapolation} +\usage{ +pk.calc.aumciv(conc, time, c0, aumc, ..., options = list(), check = TRUE) +} +\arguments{ +\item{conc}{Measured concentrations} + +\item{time}{Time of the measurement of the concentrations} + +\item{c0}{The concentration at time 0 (extrapolated)} + +\item{aumc}{The AUMC calculated without c0 adjustment (e.g., aumcall, aumclast)} + +\item{...}{For functions other than \code{pk.calc.auxc}, these values are passed +to \code{pk.calc.auxc}} + +\item{options}{List of changes to the default PKNCA options (see +\code{PKNCA.options()})} + +\item{check}{Run \code{\link[=assert_conc_time]{assert_conc_time()}}, \code{\link[=clean.conc.blq]{clean.conc.blq()}}, and +\code{\link[=clean.conc.na]{clean.conc.na()}}?} +} +\value{ +The AUMC with IV back-extrapolation applied +} +\description{ +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. +} diff --git a/man/pk.calc.ermax.Rd b/man/pk.calc.ermax.Rd new file mode 100644 index 00000000..41c00411 --- /dev/null +++ b/man/pk.calc.ermax.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/pk.calc.urine.R +\name{pk.calc.ermax} +\alias{pk.calc.ermax} +\title{Calculate the maximum excretion rate} +\usage{ +pk.calc.ermax(conc, volume, time, duration.conc, check = TRUE) +} +\arguments{ +\item{conc}{The concentration in the excreta (e.g., urine or feces)} + +\item{volume}{The volume (or mass) of the sample} + +\item{time}{The starting time of the collection interval} + +\item{duration.conc}{The duration of the collection interval} + +\item{check}{Should the concentration data be checked?} +} +\value{ +The maximum excretion rate, or NA if not available +} +\description{ +Calculate the maximum excretion rate +} diff --git a/man/pk.calc.ertlst.Rd b/man/pk.calc.ertlst.Rd new file mode 100644 index 00000000..83858b73 --- /dev/null +++ b/man/pk.calc.ertlst.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/pk.calc.urine.R +\name{pk.calc.ertlst} +\alias{pk.calc.ertlst} +\title{Calculate the midpoint collection time of the last measurable excretion rate} +\usage{ +pk.calc.ertlst(conc, volume, time, duration.conc, check = TRUE) +} +\arguments{ +\item{conc}{The concentration in the excreta (e.g., urine or feces)} + +\item{volume}{The volume (or mass) of the sample} + +\item{time}{The starting time of the collection interval} + +\item{duration.conc}{The duration of the collection interval} + +\item{check}{Should the concentration and time data be checked?} +} +\value{ +The midpoint collection time of the last measurable excretion rate, or NA/0 if not available +} +\description{ +Calculate the midpoint collection time of the last measurable excretion rate +} diff --git a/man/pk.calc.ertmax.Rd b/man/pk.calc.ertmax.Rd new file mode 100644 index 00000000..019f93f3 --- /dev/null +++ b/man/pk.calc.ertmax.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/pk.calc.urine.R +\name{pk.calc.ertmax} +\alias{pk.calc.ertmax} +\title{Calculate the midpoint collection time of the maximum excretion rate} +\usage{ +pk.calc.ertmax( + conc, + volume, + time, + duration.conc, + check = TRUE, + first.ertmax = NULL +) +} +\arguments{ +\item{conc}{The concentration in the excreta (e.g., urine or feces)} + +\item{volume}{The volume (or mass) of the sample} + +\item{time}{The starting time of the collection interval} + +\item{duration.conc}{The duration of the collection interval} + +\item{check}{Should the concentration and time data be checked?} + +\item{first.ertmax}{If TRUE, return the first time of maximum excretion rate; otherwise, return the last} +} +\value{ +The midpoint collection time of the maximum excretion rate, or NA if not available +} +\description{ +Calculate the midpoint collection time of the maximum excretion rate +} diff --git a/man/pk.calc.sparse_auc.Rd b/man/pk.calc.sparse_auc.Rd index ab8b711a..e2677cbb 100644 --- a/man/pk.calc.sparse_auc.Rd +++ b/man/pk.calc.sparse_auc.Rd @@ -58,6 +58,7 @@ Where: \seealso{ Other Sparse Methods: \code{\link{as_sparse_pk}()}, +\code{\link{pk.calc.sparse_aumc}()}, \code{\link{sparse_auc_weight_linear}()}, \code{\link{sparse_mean}()} } diff --git a/man/pk.calc.sparse_aumc.Rd b/man/pk.calc.sparse_aumc.Rd new file mode 100644 index 00000000..592da554 --- /dev/null +++ b/man/pk.calc.sparse_aumc.Rd @@ -0,0 +1,60 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/sparse.R +\name{pk.calc.sparse_aumc} +\alias{pk.calc.sparse_aumc} +\alias{pk.calc.sparse_aumclast} +\title{Calculate AUMC and related parameters using sparse NCA methods} +\usage{ +pk.calc.sparse_aumc( + conc, + time, + subject, + method = NULL, + auc.type = "AUClast", + ..., + options = list() +) + +pk.calc.sparse_aumclast(conc, time, subject, ..., options = list()) +} +\arguments{ +\item{conc}{Measured concentrations} + +\item{time}{Time of the measurement of the concentrations} + +\item{subject}{Subject identifiers (may be any class; may not be null)} + +\item{method}{The method for integration (one of 'lin up/log down', +'lin-log', or 'linear')} + +\item{auc.type}{The type of AUC to compute. Choices are 'AUCinf', 'AUClast', +and 'AUCall'.} + +\item{...}{For functions other than \code{pk.calc.auxc}, these values are passed +to \code{pk.calc.auxc}} + +\item{options}{List of changes to the default PKNCA options (see +\code{PKNCA.options()})} +} +\value{ +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} +} +\description{ +This is the exact analog of \code{\link[=pk.calc.sparse_auc]{pk.calc.sparse_auc()}} but for the first moment curve. +} +\section{Functions}{ +\itemize{ +\item \code{pk.calc.sparse_aumclast()}: Compute the AUMClast for sparse PK + +}} +\seealso{ +Other Sparse Methods: +\code{\link{as_sparse_pk}()}, +\code{\link{pk.calc.sparse_auc}()}, +\code{\link{sparse_auc_weight_linear}()}, +\code{\link{sparse_mean}()} +} +\concept{Sparse Methods} diff --git a/man/sparse_auc_weight_linear.Rd b/man/sparse_auc_weight_linear.Rd index 1373dae9..00fb4462 100644 --- a/man/sparse_auc_weight_linear.Rd +++ b/man/sparse_auc_weight_linear.Rd @@ -33,6 +33,7 @@ Where: Other Sparse Methods: \code{\link{as_sparse_pk}()}, \code{\link{pk.calc.sparse_auc}()}, +\code{\link{pk.calc.sparse_aumc}()}, \code{\link{sparse_mean}()} } \concept{Sparse Methods} diff --git a/man/sparse_mean.Rd b/man/sparse_mean.Rd index f59377f4..2e23ce9e 100644 --- a/man/sparse_mean.Rd +++ b/man/sparse_mean.Rd @@ -34,6 +34,7 @@ are: Other Sparse Methods: \code{\link{as_sparse_pk}()}, \code{\link{pk.calc.sparse_auc}()}, +\code{\link{pk.calc.sparse_aumc}()}, \code{\link{sparse_auc_weight_linear}()} } \concept{Sparse Methods} diff --git a/man/var_sparse_aumc.Rd b/man/var_sparse_aumc.Rd new file mode 100644 index 00000000..e2e56335 --- /dev/null +++ b/man/var_sparse_aumc.Rd @@ -0,0 +1,37 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/sparse.R +\name{var_sparse_aumc} +\alias{var_sparse_aumc} +\title{Calculate the variance for the AUMC of sparsely sampled PK} +\usage{ +var_sparse_aumc(sparse_pk) +} +\arguments{ +\item{sparse_pk}{A sparse_pk object from \code{\link[=as_sparse_pk]{as_sparse_pk()}}} +} +\value{ +The variance of the AUMC estimate with a "df" attribute containing +the degrees of freedom +} +\description{ +This function calculates the variance of the area under the first moment +curve (AUMC) for sparse PK data. It follows the same methodology as +\code{\link[=var_sparse_auc]{var_sparse_auc()}} but applies to the moment curve (time × concentration). +} +\details{ +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