---
title: "AUC integration methods"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{AUC integration methods}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r knitr-setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  warning = FALSE,
  comment = "#>"
)
```

```{r setup, include = FALSE}
library(PKNCA)
library(ggplot2)
auc_methods <- c("lin up/log down", "linear", "lin-log")
auc_types <- c("AUCinf", "AUClast", "AUCall")

comma_and <- function(x) {
  paste(
    paste(x[-length(x)], collapse = ", "),
    ngettext(length(x) - 1, ", and", "and"),
    x[length(x)]
  )
}
```

# Integration methods for Area Under the Concentration-Time curve (AUC)

There are `r length(auc_methods)` methods for choosing how to integrate the AUC
between two concentration measurements in `PKNCA`.  They are
`r comma_and(auc_methods)`.  Additionally, there are `r length(auc_types)`
methods for extrapolating after the last concentration above the limit of
quantification.  They are `r comma_and(auc_types)`.  Other methods of
calculating AUC (such as AUC~tau~ and AUC~int~) are made with variants of these.

# Definitions and abbreviations

* AUC: Area under the concentration-time curve
* BLQ: Below the lower limit of quantification
* LLOQ: lower limit of quantification
* NCA: Noncompartmental analysis
* Profile: A set of concentration-time points for calculation
* T~last~: The last concentration above the limit of quantification within a profile
* T~max~: The time of the maximum concentration

# Description of methods of integrating between two concentrations before T~last~

Note that other NCA tools may not describe interpolation as zero.  The
zero-interpolation rules are used by PKNCA to assist with other methods used
across the suite of tools for interpolation and data cleaning within PKNCA.  The
zero-interpolation rules could be swapped for linear trapezoidal rules with the
same effects here.

## Linear up/logarithmic down (`"lin up/log down"`) interpolation

Linear up/logarithmic down interpolation is the most commonly used method for
PK, and it is the default for `PKNCA`.

Linear up/logarithmic down interpolation is often used when an exogenous
substance is dosed and measured, and when the elimination likely occurs by
first-order elimination from the body.

Linear up/logarithmic down interpolation uses the following rules in order for
each pair of concentrations through T~last~:

1. If concentrations are both zero, interpolate as zero;
2. If concentrations are decreasing and the second concentration is not zero,
   use logarithmic interpolation; and
3. If concentrations are decreasing before T~last~ or increasing ever, use
   linear interpolation.

## Linear trapezoidal (`"linear"`) interpolation

Linear trapezoidal interpolation is often used when an endogenous substance is
measured (and possibly dosed), and when the elimination may not occur by
first-order elimination processes.

Linear trapezoidal interpolation uses the following rules in order for each pair
of concentrations through T~last~:

1. If concentrations are both zero, interpolate as zero; and
2. Use linear interpolation for all other times (this could be the only rule).

## Linear to T~max~/logarithmic after T~max~ (`"lin-log"`) interpolation

Linear to T~max~/logarithmic after T~max~ interpolation is infrequently used.
It uses the following rules in order for each pair of concentrations through
T~last~:

1. If concentrations are both zero, interpolate as zero;
2. If concentrations are before T~max~, use linear interpolation;
3. If concentrations are after T~max~ (and before T~last~) and either concentration is zero, use linear interpolation; and
4. If concentrations are after T~max~ and neither is zero, use logarithmic interpolation.

# Description of methods of integrating between two concentrations after T~last~

## `"AUClast"` extrapolation

AUClast extrapolation after T~last~ is the simplest.  It is no extrapolation;
the extrapolated AUC integral is zero.

## `"AUCall"` extrapolation

AUCall extrapolation after T~last~ has two rules:

1. If the last concentration measured is above the limit of quantification (in
   other words, the last time is T~last~), then no extrapolation is done; otherwise
2. Integrate linearly the triangle between T~last~ and the time of zero
   concentration after T~last~.

## `"AUCinf"` extrapolation

AUCinf extrapolation requires estimation of a half-life.  It extrapolates using the equation

$Extrap = \frac{C_{last}}{\lambda_z}$

# Examples

```{r setup-example, include=FALSE}
examples <-
  list(
    "Clast is above the LLOQ" =
      data.frame(
        conc = c(0, 1.8, 3, 2, 1, 0.5, 0.25),
        time = 0:6
      ),
    "Clast is below the LLOQ" =
      data.frame(
        conc = c(0, 1.8, 3, 2, 1, 0.5, 0),
        time = 0:6
      ),
    "Concentrations increase and decrease after T~max~ with zeros in the middle" =
      data.frame(
        conc = c(0, 1.8, 0, 0, 3, 2, 2.5, 0, 0, 2.5, 1, 0.5, 0),
        time = 0:12
      )
  )
```

```{r example-figures, fig.cap = caption, echo = FALSE}
caption <- character()
for (current_example_nm in names(examples)) {
  for (current_method in auc_methods) {
    for (current_type in auc_types) {
      caption <-
        c(
          caption,
          sprintf(
            "Example PK where %s; %s interpolation method; %s extrapolation method (AUC type); and keeping all BLQ values (not default BLQ handling)",
            current_example_nm, current_method, current_type
          )
        )
      current_example <- examples[[current_example_nm]]

      # Handle BLQ
      current_example_noblq <- clean.conc.blq(conc = current_example$conc, time = current_example$time)
      current_example_noblq$BLQ <- "Above LLOQ"
      current_example_points <-
        merge(current_example, current_example_noblq, all = TRUE)
      current_example_points$BLQ[is.na(current_example_points$BLQ)] <- "Below LLOQ"
      
      # Calculate some NCA parameters required for interpolation and extrapolation
      tlast <- pk.calc.tlast(conc = current_example$conc, time = current_example$time)
      half_life <- pk.calc.half.life(conc = current_example$conc, time = current_example$time)
      
      # Define the methods used for interpolation and extrapolation
      current_example$method <-
        factor(
          PKNCA:::choose_interval_method(
            conc = current_example$conc,
            time = current_example$time,
            tlast = tlast,
            method = current_method,
            auc.type = current_type,
            options = list()
          ),
          levels = c("zero", "linear", "log", "extrap_log")
        )
      stopifnot(!any(is.na(current_example$method)))
      current_example_interpolate <-
        data.frame(
          time =
            sort(c(
              # make lines almost directly down at the transition after Tlast to
              # zero, where applicable
              current_example$time + sqrt(.Machine$double.eps),
              seq(min(current_example$time), max(current_example$time) + diff(current_example$time)[1], length.out = 200)
            ))
        )
      current_example_interpolate$conc <-
        interp.extrap.conc(
          conc = current_example$conc,
          time = current_example$time,
          time.out = current_example_interpolate$time,
          lambda.z = half_life$lambda.z,
          method = current_method,
          auc.type = current_type,
          conc.blq = "keep"
        )
      current_example$time_after <- c(current_example$time[-1], Inf)
      if (current_example$method[nrow(current_example)] == "zero") {
        current_example_plot <- current_example
      } else {
        current_example_before_tlast <- current_example[current_example$time < tlast, ]
        current_example_after_tlast <- current_example[current_example$time >= tlast, ][1, ]
        current_example_after_tlast$method <- current_example$method[nrow(current_example)]
        current_example_after_tlast$time_after <- Inf
        current_example_plot <-
          dplyr::bind_rows(
            current_example_before_tlast,
            current_example_after_tlast
          )
      }
      print(
        ggplot(current_example_points, aes(x = time, y = conc)) +
          geom_rect(data = current_example_plot, aes(xmin = time, xmax = time_after, ymin = -Inf, ymax = Inf, fill = method), alpha = 0.2) +
          geom_point(aes(shape = BLQ)) +
          geom_line(data = current_example_interpolate) +
          scale_colour_hue(drop = FALSE)
      )
    }
  }
}
```