conc <- c(0.5, 0.3, 0, 0.1, 0, 0.0, 0.02)
time <- c(0, 1, 2, 3, 4, 5, 6 )
# Drop BLQ (0) values
clean.conc.blq(conc, time, conc.blq = "drop") conc time
1 0.50 0
2 0.30 1
4 0.10 3
7 0.02 6
clean.conc.blq()clean.conc.na()interp.extrap.conc()pk.calc.half.life()pk.calc.auc.all()check.interval.specification()setRoute() and setDuration()get.parameter.deps()PKNCA.options()PKNCA.choose.option()PKNCA exports several lower-level utility functions useful for data preparation, interval validation, and direct computation outside the full PKNCAdata → pk.nca() pipeline.
clean.conc.blq()Applies the BLQ-handling rule to a concentration vector before fitting. The full analysis pipeline applies this automatically, but clean.conc.blq() is useful for pre-processing or testing your own rule.
conc time
1 0.50 0
2 0.30 1
4 0.10 3
7 0.02 6
conc time
1 0.50 0
2 0.30 1
3 0.05 2
4 0.10 3
5 0.05 4
6 0.05 5
7 0.02 6
The conc.blq argument accepts: - "drop" — remove BLQ rows - "keep" — keep BLQ rows as-is - A number — substitute BLQ values with that number
clean.conc.na()Removes or replaces NA concentrations. Internally called before AUC computation.
conc time
1 0.5 0
3 0.3 2
4 0.1 3
conc time
1 0.5 0
2 0.0 1
3 0.3 2
4 0.1 3
5 0.0 4
interp.extrap.conc()Interpolates or extrapolates a concentration at a target time given a known concentration-time profile. Used internally when an interval boundary falls between two observed timepoints.
[1] 3.535534
[1] NA
The method (linear vs log-linear) follows the auc.method setting. Extrapolation uses the terminal log-linear slope (requires at least 3 points for λz estimation).
pk.calc.half.life()Runs the full curve-stripping algorithm on raw concentration-time data and returns the selected half-life, λz, and associated diagnostics. Useful for batch processing outside the standard pipeline.
half.life lambda.z r.squared lambda.z.n.points lambda.z.time.first span.ratio
1 14.30438 0.048457 0.9999997 3 9.05 1.071001
This is the same function called internally by pk.nca() when half.life = TRUE.
pk.calc.auc.all()Computes AUC (trapezoid rule) directly on a concentration-time vector. Returns the scalar AUC value.
Other direct AUC functions:
| Function | AUC type |
|---|---|
pk.calc.auc.last() |
AUC to last measurable concentration |
pk.calc.auc.all() |
AUC to last, treating BLQ as 0 |
pk.calc.auc.inf.obs() |
AUC extrapolated to ∞ (observed Clast) |
pk.calc.auc.inf.pred() |
AUC extrapolated to ∞ (predicted Clast) |
These are the building blocks behind every AUC parameter in the registry.
check.interval.specification()Validates an intervals data frame before passing it to PKNCAdata(). Returns the data frame with all parameter columns filled in (missing columns defaulted to FALSE).
[1] "end" "auclast" "cmax"
Error: Column(s) 'start' missing from interval specification
This is useful for debugging custom interval definitions before running the full analysis.
Total registered parameters: 203
$start
NULL
$end
NULL
$auclast
NULL
$aucall
NULL
$aumclast
NULL
Dose-normalized parameters:
- auclast.dn
- aucall.dn
- aucinf.obs.dn
- aucinf.pred.dn
- aumclast.dn
- aumcall.dn
- aumcinf.obs.dn
- aumcinf.pred.dn
- cmax.dn
- cmin.dn
- clast.obs.dn
- clast.pred.dn
- cav.dn
- ctrough.dn
- clr.last.dn
- clr.obs.dn
- clr.pred.dn
setRoute() and setDuration()After creating a PKNCAdose object, you can change the route or infusion duration without rebuilding from scratch.
Found column named route, using it for the attribute of the same name.
Found column named duration, using it for the attribute of the same name.
route duration
1 intravascular 0.5
This is useful when you want to test how route assumption changes affect MRT or Vss calculations without rebuilding the full PKNCAdata object.
get.parameter.deps()Returns the upstream parameters that a given parameter depends on. Useful when debugging why a parameter is NA (a dependency may have failed).
[1] "adj_tobit_residual" "adj.r.squared" "aucinf.obs"
[4] "aucinf.obs.dn" "aucinf.pred" "aucinf.pred.dn"
[7] "aucint.inf.obs" "aucint.inf.obs.dose" "aucint.inf.pred"
[10] "aucint.inf.pred.dose" "aucivinf.obs" "aucivinf.pred"
[13] "aucivpbextinf.obs" "aucivpbextinf.pred" "aucpext.obs"
[16] "aucpext.pred" "aumcinf.obs" "aumcinf.obs.dn"
[19] "aumcinf.pred" "aumcinf.pred.dn" "aumcint.inf.obs"
[22] "aumcint.inf.obs.dose" "aumcint.inf.pred" "aumcint.inf.pred.dose"
[25] "aumcivinf.obs" "aumcivinf.pred" "cav.int.inf.obs"
[28] "cav.int.inf.pred" "cl.int.inf.obs" "cl.int.inf.pred"
[31] "cl.iv.obs" "cl.iv.pred" "cl.obs"
[34] "cl.pred" "clast.pred" "clast.pred.dn"
[37] "half.life" "kel.int.inf.obs" "kel.int.inf.pred"
[40] "kel.iv.obs" "kel.iv.pred" "kel.obs"
[43] "kel.pred" "lambda.z" "lambda.z.corrxy"
[46] "lambda.z.n.points" "lambda.z.n.points_blq" "lambda.z.time.first"
[49] "lambda.z.time.last" "mrt.int.inf.obs" "mrt.int.inf.pred"
[52] "mrt.iv.obs" "mrt.iv.pred" "mrt.md.obs"
[55] "mrt.md.pred" "mrt.obs" "mrt.pred"
[58] "r.squared" "span.ratio" "thalf.eff.iv.obs"
[61] "thalf.eff.iv.pred" "thalf.eff.obs" "thalf.eff.pred"
[64] "tobit_residual" "vss.int.inf.obs" "vss.int.inf.pred"
[67] "vss.iv.obs" "vss.iv.pred" "vss.md.obs"
[70] "vss.md.pred" "vss.obs" "vss.pred"
[73] "vz.all" "vz.int.all" "vz.int.inf.obs"
[76] "vz.int.inf.pred" "vz.int.last" "vz.iv.all"
[79] "vz.iv.last" "vz.iv.obs" "vz.iv.pred"
[82] "vz.ivint.all" "vz.ivint.last" "vz.last"
[85] "vz.obs" "vz.pred"
PKNCA.options()PKNCA.options() with no arguments returns the full named list of current settings:
$adj.r.squared.factor
[1] 1e-04
$max.missing
[1] 0.5
$auc.method
[1] "lin up/log down"
$conc.na
[1] "drop"
$conc.blq
$conc.blq$first
[1] "keep"
$conc.blq$middle
[1] "drop"
$conc.blq$last
[1] "keep"
$debug
NULL
$first.tmax
[1] TRUE
$first.tmin
[1] TRUE
$allow.tmax.in.half.life
[1] FALSE
$keep_interval_cols
NULL
$min.hl.points
[1] 3
$min.span.ratio
[1] 2
$max.aucinf.pext
[1] 20
$min.hl.r.squared
[1] 0.9
$progress
[1] TRUE
$tau.choices
[1] NA
$single.dose.aucs
start end auclast aucall aumclast aumcall aucint.last aucint.last.dose
1 0 24 TRUE FALSE FALSE FALSE FALSE FALSE
2 0 Inf FALSE FALSE FALSE FALSE FALSE FALSE
aucint.all aucint.all.dose aumcint.last aumcint.last.dose aumcint.all
1 FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE
aumcint.all.dose c0 cmax cmin tmax tmin tlast tfirst clast.obs cl.last
1 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
cl.all cl.int.all cl.int.last f mrt.last mrt.all mrt.int.all mrt.int.last
1 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
mrt.iv.last vss.last vss.iv.last vss.all vss.int.all vss.int.last cav
1 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
cav.int.last cav.int.all ctrough cstart ptr tlag deg.fluc swing ceoi
1 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
aucabove.predose.all aucabove.trough.all count_conc count_conc_measured
1 FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE
totdose volpk ae clr.last clr.obs clr.pred fe ertlst ermax ertmax
1 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
sparse_auclast sparse_auc_se sparse_auc_df sparse_aumclast sparse_aumc_se
1 FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE
sparse_aumc_df time_above aucivlast aucivall aucivint.last aucivint.all
1 FALSE FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE FALSE
aucivpbextlast aucivpbextall aucivpbextint.last aucivpbextint.all aumcivlast
1 FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE
aumcivall aumcivint.last aumcivint.all half.life r.squared adj.r.squared
1 FALSE FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE TRUE FALSE FALSE
lambda.z.corrxy lambda.z lambda.z.time.first lambda.z.time.last
1 FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE
lambda.z.n.points clast.pred span.ratio tobit_residual adj_tobit_residual
1 FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE
lambda.z.n.points_blq thalf.eff.last thalf.eff.iv.last kel.last kel.iv.last
1 FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE
kel.all kel.int.all kel.int.last cl.iv.all cl.iv.last cl.ivint.all
1 FALSE FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE FALSE
cl.ivint.last cl.sparse.last mrt.sparse.last mrt.iv.all mrt.ivint.all
1 FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE
mrt.ivint.last vz.all vz.int.all vz.int.last vz.iv.all vz.iv.last
1 FALSE FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE FALSE
vz.ivint.all vz.ivint.last vz.last vss.iv.all vss.ivint.all vss.ivint.last
1 FALSE FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE FALSE
vss.sparse.last aucinf.obs aucinf.pred aumcinf.obs aumcinf.pred
1 FALSE FALSE FALSE FALSE FALSE
2 FALSE TRUE FALSE FALSE FALSE
aucint.inf.obs aucint.inf.obs.dose aucint.inf.pred aucint.inf.pred.dose
1 FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE
aumcint.inf.obs aumcint.inf.obs.dose aumcint.inf.pred aumcint.inf.pred.dose
1 FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE
aucivinf.obs aucivinf.pred aucivpbextinf.obs aucivpbextinf.pred aumcivinf.obs
1 FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE
aumcivinf.pred aucpext.obs aucpext.pred kel.iv.all kel.ivint.all
1 FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE
kel.ivint.last kel.sparse.last cl.obs cl.pred cl.int.inf.obs cl.int.inf.pred
1 FALSE FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE FALSE
cl.iv.obs cl.iv.pred mrt.obs mrt.pred mrt.int.inf.obs mrt.int.inf.pred
1 FALSE FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE FALSE
mrt.iv.obs mrt.iv.pred mrt.md.obs mrt.md.pred vz.obs vz.pred vz.int.inf.obs
1 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
vz.int.inf.pred vz.iv.obs vz.iv.pred vz.sparse.last vss.obs vss.pred
1 FALSE FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE FALSE
vss.iv.obs vss.iv.pred vss.md.obs vss.md.pred vss.int.inf.obs
1 FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE
vss.int.inf.pred cav.int.inf.obs cav.int.inf.pred thalf.eff.obs
1 FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE
thalf.eff.pred thalf.eff.iv.obs thalf.eff.iv.pred kel.obs kel.pred kel.iv.obs
1 FALSE FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE FALSE
kel.iv.pred kel.int.inf.obs kel.int.inf.pred auclast.dn aucall.dn
1 FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE
aucinf.obs.dn aucinf.pred.dn aumclast.dn aumcall.dn aumcinf.obs.dn
1 FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE
aumcinf.pred.dn cmax.dn cmin.dn clast.obs.dn clast.pred.dn cav.dn ctrough.dn
1 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
clr.last.dn clr.obs.dn clr.pred.dn
1 FALSE FALSE FALSE
2 FALSE FALSE FALSE
$allow_partial_missing_units
[1] FALSE
$hl_method
[1] "log-linear"
$tobit_n_points_penalty
[1] 0
$tobit_optim_control
list()
Note:
PKNCA.options.describe()is exported but non-functional in PKNCA 0.12.1 (raises an error). UsePKNCA.options()to inspect current settings, and see the Workflow Overview page for the full option reference table.
PKNCA.choose.option()Selects a value from either the local options list passed to PKNCAdata() or the global PKNCA.options() defaults. Useful when writing custom parameter functions that need to respect session-level settings.
[1] 3
[1] 5
---
title: "Utility Functions"
---
```{r setup, include=FALSE}
library(PKNCA)
library(dplyr)
library(ggplot2)
conflicted::conflicts_prefer(dplyr::filter, dplyr::select, .quiet = TRUE)
```
## Overview
PKNCA exports several lower-level utility functions useful for data preparation, interval validation, and direct computation outside the full `PKNCAdata` → `pk.nca()` pipeline.
---
## BLQ concentration handling: `clean.conc.blq()`
Applies the BLQ-handling rule to a concentration vector **before** fitting. The full analysis pipeline applies this automatically, but `clean.conc.blq()` is useful for pre-processing or testing your own rule.
```{r}
conc <- c(0.5, 0.3, 0, 0.1, 0, 0.0, 0.02)
time <- c(0, 1, 2, 3, 4, 5, 6 )
# Drop BLQ (0) values
clean.conc.blq(conc, time, conc.blq = "drop")
```
```{r}
# Replace BLQ with half the LLOQ (= 0.05 here)
clean.conc.blq(conc, time, conc.blq = 0.05)
```
The `conc.blq` argument accepts:
- `"drop"` — remove BLQ rows
- `"keep"` — keep BLQ rows as-is
- A number — substitute BLQ values with that number
---
## NA concentration handling: `clean.conc.na()`
Removes or replaces NA concentrations. Internally called before AUC computation.
```{r}
conc_na <- c(0.5, NA, 0.3, 0.1, NA)
time_na <- c(0, 1, 2, 3, 4)
# Default: drop NAs
clean.conc.na(conc_na, time_na, conc.na = "drop")
```
```{r}
# Replace NAs with 0
clean.conc.na(conc_na, time_na, conc.na = 0)
```
---
## Concentration interpolation / extrapolation: `interp.extrap.conc()`
Interpolates or extrapolates a concentration at a target time given a known concentration-time profile. Used internally when an interval boundary falls between two observed timepoints.
```{r}
conc_ex <- c(10, 8, 5, 2.5, 1)
time_ex <- c(0, 1, 2, 4, 8)
# Interpolate at t = 3 (between t=2 and t=4)
interp.extrap.conc(conc = conc_ex, time = time_ex, time.out = 3)
```
```{r}
# Extrapolate beyond the last sample (t = 12)
interp.extrap.conc(conc = conc_ex, time = time_ex, time.out = 12)
```
The method (linear vs log-linear) follows the `auc.method` setting. Extrapolation uses the terminal log-linear slope (requires at least 3 points for λz estimation).
---
## Direct half-life computation: `pk.calc.half.life()`
Runs the full curve-stripping algorithm on raw concentration-time data and returns the selected half-life, λz, and associated diagnostics. Useful for batch processing outside the standard pipeline.
```{r}
subj1 <- as.data.frame(Theoph) |> filter(Subject == "1")
hl_result <- pk.calc.half.life(
conc = subj1$conc,
time = subj1$Time,
options = PKNCA.options()
)
hl_result[c("half.life", "lambda.z", "r.squared", "lambda.z.n.points",
"lambda.z.time.first", "span.ratio")]
```
This is the same function called internally by `pk.nca()` when `half.life = TRUE`.
---
## Direct AUC computation: `pk.calc.auc.all()`
Computes AUC (trapezoid rule) directly on a concentration-time vector. Returns the scalar AUC value.
```{r}
pk.calc.auc.all(
conc = subj1$conc,
time = subj1$Time,
method = "lin up/log down"
)
```
Other direct AUC functions:
| Function | AUC type |
|---|---|
| `pk.calc.auc.last()` | AUC to last measurable concentration |
| `pk.calc.auc.all()` | AUC to last, treating BLQ as 0 |
| `pk.calc.auc.inf.obs()` | AUC extrapolated to ∞ (observed Clast) |
| `pk.calc.auc.inf.pred()` | AUC extrapolated to ∞ (predicted Clast) |
These are the building blocks behind every AUC parameter in the registry.
---
## Validating interval specifications: `check.interval.specification()`
Validates an intervals data frame before passing it to `PKNCAdata()`. Returns the data frame with all parameter columns filled in (missing columns defaulted to `FALSE`).
```{r}
my_intervals <- data.frame(
start = 0,
end = Inf,
auclast = TRUE,
cmax = TRUE
)
# Returns the full expanded interval spec
expanded <- check.interval.specification(my_intervals)
# Which parameters are requested?
names(expanded)[as.logical(expanded[1, ])]
```
```{r}
# Invalid specification — missing start column — raises an error
tryCatch(
check.interval.specification(data.frame(end = Inf, auclast = TRUE)),
error = function(e) cat("Error:", conditionMessage(e), "\n")
)
```
This is useful for debugging custom interval definitions before running the full analysis.
---
## Listing all available parameters
```{r}
cols <- get.interval.cols()
cat("Total registered parameters:", length(cols), "\n")
# Show first few with their dependency lists
lapply(head(cols, 5), function(x) x$depends)
```
```{r}
# All dose-normalized parameters
dn_params <- names(cols)[endsWith(names(cols), ".dn")]
cat("Dose-normalized parameters:\n")
cat(paste(" -", dn_params), sep = "\n")
```
---
## Modifying PKNCAdose after creation: `setRoute()` and `setDuration()`
After creating a `PKNCAdose` object, you can change the route or infusion duration without rebuilding from scratch.
```{r}
d_dose_u <- data.frame(subject = "1", dose = 100, time = 0)
o_dose_u <- PKNCAdose(d_dose_u, dose ~ time | subject, route = "extravascular")
# Change to intravascular
o_dose_iv <- setRoute(o_dose_u, route = "intravascular")
# Add infusion duration (0.5 h = 30 min)
o_dose_inf <- setDuration(o_dose_iv, duration = 0.5)
# Verify
o_dose_inf$data[c("route", "duration")]
```
This is useful when you want to test how route assumption changes affect MRT or Vss calculations without rebuilding the full `PKNCAdata` object.
---
## Getting parameter dependencies: `get.parameter.deps()`
Returns the upstream parameters that a given parameter depends on. Useful when debugging why a parameter is `NA` (a dependency may have failed).
```{r}
get.parameter.deps("vss.obs")
```
```{r}
get.parameter.deps("half.life")
```
---
## Listing all current option values: `PKNCA.options()`
`PKNCA.options()` with no arguments returns the full named list of current settings:
```{r}
PKNCA.options()
```
> **Note:** `PKNCA.options.describe()` is exported but non-functional in PKNCA 0.12.1 (raises an error). Use `PKNCA.options()` to inspect current settings, and see the [Workflow Overview](workflow.qmd) page for the full option reference table.
---
## Choosing an option value: `PKNCA.choose.option()`
Selects a value from either the local `options` list passed to `PKNCAdata()` or the global `PKNCA.options()` defaults. Useful when writing custom parameter functions that need to respect session-level settings.
```{r}
# With no local override, returns the global default
PKNCA.choose.option("min.hl.points", options = list())
```
```{r}
# With a local override, the local value wins
PKNCA.choose.option("min.hl.points", options = list(min.hl.points = 5))
```
---
::: {.callout-note icon=false appearance="minimal"}
**pkgdown reference:** [clean.conc.blq()](https://humanpred.github.io/pknca/reference/clean.conc.blq.html) · [clean.conc.na()](https://humanpred.github.io/pknca/reference/clean.conc.na.html) · [interp.extrap.conc()](https://humanpred.github.io/pknca/reference/interp.extrap.conc.html) · [pk.calc.half.life()](https://humanpred.github.io/pknca/reference/pk.calc.half.life.html) · [check.interval.specification()](https://humanpred.github.io/pknca/reference/check.interval.specification.html) · [get.interval.cols()](https://humanpred.github.io/pknca/reference/get.interval.cols.html) · [setRoute()](https://humanpred.github.io/pknca/reference/setRoute.html) · [setDuration()](https://humanpred.github.io/pknca/reference/setDuration.html) · [get.parameter.deps()](https://humanpred.github.io/pknca/reference/get.parameter.deps.html) · [PKNCA.options()](https://humanpred.github.io/pknca/reference/PKNCA.options.html) · [PKNCA.choose.option()](https://humanpred.github.io/pknca/reference/PKNCA.choose.option.html)
:::