/
v23-auc-integration-methods.Rmd
230 lines (194 loc) · 8.41 KB
/
v23-auc-integration-methods.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
---
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)
)
}
}
}
```