# Number of parameters registered by default
length(get.interval.cols())[1] 203
add.interval.col()
formalsmap argumentEvery NCA parameter that PKNCA can compute is registered in an internal registry via add.interval.col(). When you request auclast = TRUE in an interval, PKNCA looks up the registered function for auclast and calls it with the right arguments.
You can extend the registry with your own parameters — new functions that compute anything derivable from concentrations, times, doses, or other already-computed parameters. See also the package vignette Writing PKNCA Parameter Functions.
add.interval.col()add.interval.col(
name = "my.param", # column name used in intervals data frame
FUN = "pk.calc.my.param", # character string: function name
values = c(FALSE, TRUE), # allowed values in intervals (FALSE = skip, TRUE = compute)
unit_type = "time", # units category (see below)
pretty_name = "My parameter", # human-readable label
desc = "What it does", # one-line description
depends = NULL, # other parameters that must be computed first
sparse = FALSE, # TRUE if this is a sparse-PK parameter
formalsmap = list(), # list(<your function arg> = "<PKNCA data name>")
datatype = "interval", # "interval" (default), "individual", or "population"
# (only "interval" is currently supported; the others error)
pptestcd_cdisc = "MYPARAM", # CDISC PPTESTCD code for the parameter (≥ 0.12.2)
pptest_cdisc = "My Parameter" # CDISC PPTEST label for the parameter (≥ 0.12.2)
)Key rule: FUN must be a character string (the function name), not a function object.
unit_type values"unitless", "fraction", "%", "count", "time", "inverse_time", "amount", "amount_dose", "amount_time", "conc", "conc_dosenorm", "dose", "volume", "auc", "aumc", "auc_dosenorm", "aumc_dosenorm", "clearance", "renal_clearance", "renal_clearance_dosenorm"
formalsmap argumentEach formalsmap entry has the form <your function's argument> = "<PKNCA data name>" — the names of the list must be your function’s formal arguments, and the values are the PKNCA data or parameter names that supply them. For example, PKNCA registers mrt.obs with formalsmap = list(auc = "aucinf.obs", aumc = "aumcinf.obs"): the computed aucinf.obs value is passed to the function’s auc argument.
Standard PKNCA data names available as formalsmap values:
| PKNCA name | What it provides |
|---|---|
conc |
Concentration vector for the current interval |
time |
Time vector for the current interval |
dose |
Total dose in the current interval |
start |
Interval start time |
end |
Interval end time |
half.life |
Computed half-life (if in depends) |
auclast |
Computed AUClast (if in depends) |
cmax |
Computed Cmax (if in depends) |
| (any parameter name) | Any other registered parameter in depends |
If your function argument names exactly match PKNCA’s standard names, formalsmap can be omitted or left empty.
A parameter that divides two already-computed parameters. Use depends to declare what must be computed first (shown here without formalsmap because the function’s argument names match the parameter names).
# Exposure ratio: AUClast / Cmax (units: time, since AUC/conc = time × conc/conc = time)
pk.calc.exposure.ratio <- function(auclast, cmax) {
auclast / cmax
}
add.interval.col(
name = "exposure.ratio",
FUN = "pk.calc.exposure.ratio",
values = c(FALSE, TRUE),
unit_type = "time",
pretty_name = "Exposure ratio (AUClast / Cmax)",
desc = "AUClast divided by Cmax",
depends = c("auclast", "cmax")
)o_nca_er <- pk.nca(PKNCAdata(o_conc, o_dose, intervals = data.frame(
start = 0, end = Inf,
auclast = TRUE,
cmax = TRUE,
exposure.ratio = TRUE
)))
as.data.frame(o_nca_er) |>
filter(PPTESTCD %in% c("auclast", "cmax", "exposure.ratio")) |>
select(subject, PPTESTCD, PPORRES) |>
tidyr::pivot_wider(names_from = PPTESTCD, values_from = PPORRES) |>
mutate(check = auclast / cmax) |>
arrange(subject)# A tibble: 12 × 5
subject auclast cmax exposure.ratio check
<ord> <dbl> <dbl> <dbl> <dbl>
1 6 71.7 6.44 11.1 11.1
2 7 88.0 7.09 12.4 12.4
3 8 86.8 7.56 11.5 11.5
4 11 77.9 8 9.74 9.74
5 3 95.9 8.2 11.7 11.7
6 2 88.7 8.33 10.7 10.7
7 4 103. 8.6 11.9 11.9
8 9 83.9 9.03 9.30 9.30
9 12 115. 9.75 11.8 11.8
10 10 136. 10.2 13.3 13.3
11 1 147. 10.5 14.0 14.0
12 5 118. 11.4 10.4 10.4
A parameter that accesses conc and time directly. PKNCA passes the raw vectors from the concentration data. No depends needed. The identity formalsmap below is shown for explicitness — because the argument names match PKNCA’s standard names, it could equally be omitted.
# Concentration at exactly 2 hours (interpolated)
pk.calc.c_at_2h <- function(conc, time) {
interp.extrap.conc(conc = conc, time = time, time.out = 2)
}
add.interval.col(
name = "c.2h",
FUN = "pk.calc.c_at_2h",
values = c(FALSE, TRUE),
unit_type = "conc",
pretty_name = "Concentration at 2 h",
desc = "Interpolated concentration at t = 2 h",
depends = NULL,
formalsmap = list(conc = "conc", time = "time")
)# A tibble: 12 × 2
subject PPORRES
<ord> <dbl>
1 6 6.32
2 7 6.55
3 8 7.56
4 11 6.80
5 3 7.81
6 2 8.25
7 4 8.41
8 9 6.35
9 12 9.72
10 10 7.76
11 1 9.68
12 5 9.37
When computing several related quantities (e.g. early AUC, late AUC, and their ratio), register each as its own function. The late-AUC and fraction functions read the already-computed auclast dependency.
pk.calc.auc.early <- function(conc, time) {
t_idx <- time <= 4
if (sum(t_idx) < 2) return(NA_real_)
pk.calc.auc.last(conc[t_idx], time[t_idx])
}
pk.calc.auc.late <- function(conc, time, auclast) {
t_idx <- time <= 4
if (sum(t_idx) < 2) return(NA_real_)
auclast - pk.calc.auc.last(conc[t_idx], time[t_idx])
}
pk.calc.auc.early.frac <- function(conc, time, auclast) {
t_idx <- time <= 4
if (sum(t_idx) < 2) return(NA_real_)
pk.calc.auc.last(conc[t_idx], time[t_idx]) / auclast
}
add.interval.col(
name = "auc.early",
FUN = "pk.calc.auc.early",
values = c(FALSE, TRUE),
unit_type = "auc",
pretty_name = "AUC to last sample <= 4h",
desc = "AUC to the last sample at or before 4 h",
depends = NULL,
formalsmap = list(conc = "conc", time = "time")
)
add.interval.col(
name = "auc.late",
FUN = "pk.calc.auc.late",
values = c(FALSE, TRUE),
unit_type = "auc",
pretty_name = "AUC 4h to last",
desc = "AUC from 4 h to last sample",
depends = "auclast",
formalsmap = list(conc = "conc", time = "time", auclast = "auclast")
)
add.interval.col(
name = "auc.early.fraction",
FUN = "pk.calc.auc.early.frac",
values = c(FALSE, TRUE),
unit_type = "fraction",
pretty_name = "Early AUC fraction",
desc = "Fraction of AUClast occurring in first 4 h",
depends = "auclast",
formalsmap = list(conc = "conc", time = "time", auclast = "auclast")
)Note: One function can populate several output parameters at once by returning a one-row data frame whose column names are registered parameter names —
pk.nca()saves every column of the returned data frame. This is exactly howpk.calc.half.life()populateshalf.life,lambda.z,r.squared, and the other half-life diagnostics. Each output still needs its ownadd.interval.col()registration: register the function on the primary parameter, and register the other columns withFUN = NAplus adependson the primary (formalsmapmay not be given whenFUN = NA). The one-function-per-parameter pattern shown above is the simpler option when each output is cheap to compute.
o_nca_split <- pk.nca(PKNCAdata(o_conc, o_dose, intervals = data.frame(
start = 0, end = Inf,
auclast = TRUE,
auc.early = TRUE,
auc.late = TRUE,
auc.early.fraction = TRUE
)))
as.data.frame(o_nca_split) |>
filter(PPTESTCD %in% c("auclast", "auc.early", "auc.late", "auc.early.fraction")) |>
select(subject, PPTESTCD, PPORRES) |>
tidyr::pivot_wider(names_from = PPTESTCD, values_from = PPORRES) |>
arrange(subject)# A tibble: 12 × 5
subject auclast auc.early auc.late auc.early.fraction
<ord> <dbl> <dbl> <dbl> <dbl>
1 6 71.7 18.3 53.4 0.255
2 7 88.0 18.2 69.7 0.207
3 8 86.8 22.0 64.8 0.253
4 11 77.9 23.4 54.5 0.301
5 3 95.9 25.9 70.0 0.270
6 2 88.7 24.9 63.8 0.281
7 4 103. 24.1 78.5 0.235
8 9 83.9 22.8 61.2 0.271
9 12 115. 27.3 87.9 0.237
10 10 136. 24.5 111. 0.181
11 1 147. 32.1 115. 0.218
12 5 118. 29.1 89.0 0.247
The same split can be computed by one multi-output function returning a one-row data frame:
pk.calc.auc.split <- function(conc, time, auclast) {
t_idx <- time <= 4
early <- if (sum(t_idx) < 2) NA_real_ else pk.calc.auc.last(conc[t_idx], time[t_idx])
data.frame(auc.early.df = early, auc.late.df = auclast - early)
}
add.interval.col(
name = "auc.early.df",
FUN = "pk.calc.auc.split", # computes BOTH auc.early.df and auc.late.df
values = c(FALSE, TRUE),
unit_type = "auc",
pretty_name = "AUC 0-4h (multi-output)",
desc = "AUC from 0 to 4 h, from a multi-output function",
depends = "auclast",
formalsmap = list(conc = "conc", time = "time", auclast = "auclast")
)
add.interval.col(
name = "auc.late.df",
FUN = NA, # populated by pk.calc.auc.split via auc.early.df
values = c(FALSE, TRUE),
unit_type = "auc",
pretty_name = "AUC 4h to last (multi-output)",
desc = "AUC from 4 h to last sample, from a multi-output function",
depends = "auc.early.df"
)
o_nca_multi <- pk.nca(PKNCAdata(o_conc, o_dose, intervals = data.frame(
start = 0, end = Inf,
auclast = TRUE, auc.early.df = TRUE, auc.late.df = TRUE
)))
as.data.frame(o_nca_multi) |>
filter(PPTESTCD %in% c("auclast", "auc.early.df", "auc.late.df")) |>
select(subject, PPTESTCD, PPORRES) |>
tidyr::pivot_wider(names_from = PPTESTCD, values_from = PPORRES) |>
arrange(subject)# A tibble: 12 × 4
subject auclast auc.early.df auc.late.df
<ord> <dbl> <dbl> <dbl>
1 6 71.7 18.3 53.4
2 7 88.0 18.2 69.7
3 8 86.8 22.0 64.8
4 11 77.9 23.4 54.5
5 3 95.9 25.9 70.0
6 2 88.7 24.9 63.8
7 4 103. 24.1 78.5
8 9 83.9 22.8 61.2
9 12 115. 27.3 87.9
10 10 136. 24.5 111.
11 1 147. 32.1 115.
12 5 118. 29.1 89.0
exposure.ratio registered: TRUE
c.2h registered: TRUE
List of 11
$ FUN : chr "pk.calc.exposure.ratio"
$ values : logi [1:2] FALSE TRUE
$ unit_type : chr "time"
$ pretty_name : chr "Exposure ratio (AUClast / Cmax)"
$ desc : chr "AUClast divided by Cmax"
$ sparse : logi FALSE
$ formalsmap : list()
$ depends : chr [1:2] "auclast" "cmax"
$ datatype : chr "interval"
$ pptestcd_cdisc: chr "exposure.ratio"
$ pptest_cdisc : chr "AUClast divided by Cmax"
After registering the parameter, set a custom summary rule with PKNCA.set.summary():
start end N auclast cmax exposure.ratio
0 Inf 12 98.7 [22.5] 8.65 [17.0] 11.4 [12.0]
Caption: auclast, cmax: geometric mean and geometric coefficient of variation; exposure.ratio: geometric mean [CV%]; N: number of subjects
The vignette’s summary section covers the same registration.
add.interval.col() persist for the life of your R session. Re-run registration code in each session (e.g. in your analysis script or package).FUN must be a character string. Passing a function object causes an error.depends controls evaluation order. List all parameters your function reads. PKNCA resolves the dependency graph and ensures they are computed before your function is called.pk.nca() runs. Define them in the global environment or in a package loaded before calling pk.nca().pkgdown reference: PKNCAconc() · PKNCAdose() · PKNCAdata() · pk.nca() · add.interval.col() · get.interval.cols() · interp.extrap.conc() · pk.calc.auc.last() · PKNCA.set.summary() · geomean() · geocv()
---
title: "Writing Custom Parameter Functions"
---
```{r setup, include=FALSE}
library(PKNCA)
library(dplyr)
conflicted::conflicts_prefer(dplyr::filter, dplyr::select, .quiet = TRUE)
# Shared dataset
d_conc <- as.data.frame(Theoph) |> rename(time = Time, subject = Subject)
d_dose <- Theoph |> as.data.frame() |>
group_by(Subject) |>
summarise(dose = Dose[1] * Wt[1], .groups = "drop") |>
rename(subject = Subject) |>
mutate(time = 0)
o_conc <- PKNCAconc(d_conc, conc ~ time | subject)
o_dose <- PKNCAdose(d_dose, dose ~ time | subject, route = "extravascular")
```
## The parameter registry
Every NCA parameter that PKNCA can compute is **registered** in an internal registry via `add.interval.col()`. When you request `auclast = TRUE` in an interval, PKNCA looks up the registered function for `auclast` and calls it with the right arguments.
You can extend the registry with your own parameters — new functions that compute anything derivable from concentrations, times, doses, or other already-computed parameters. See also the package vignette [Writing PKNCA Parameter Functions](https://humanpred.github.io/pknca/articles/v80-writing-parameter-functions.html).
```{r}
# Number of parameters registered by default
length(get.interval.cols())
```
---
## Anatomy of `add.interval.col()`
```r
add.interval.col(
name = "my.param", # column name used in intervals data frame
FUN = "pk.calc.my.param", # character string: function name
values = c(FALSE, TRUE), # allowed values in intervals (FALSE = skip, TRUE = compute)
unit_type = "time", # units category (see below)
pretty_name = "My parameter", # human-readable label
desc = "What it does", # one-line description
depends = NULL, # other parameters that must be computed first
sparse = FALSE, # TRUE if this is a sparse-PK parameter
formalsmap = list(), # list(<your function arg> = "<PKNCA data name>")
datatype = "interval", # "interval" (default), "individual", or "population"
# (only "interval" is currently supported; the others error)
pptestcd_cdisc = "MYPARAM", # CDISC PPTESTCD code for the parameter (≥ 0.12.2)
pptest_cdisc = "My Parameter" # CDISC PPTEST label for the parameter (≥ 0.12.2)
)
```
**Key rule:** `FUN` must be a **character string** (the function name), not a function object.
### Available `unit_type` values
`"unitless"`, `"fraction"`, `"%"`, `"count"`, `"time"`, `"inverse_time"`, `"amount"`, `"amount_dose"`, `"amount_time"`, `"conc"`, `"conc_dosenorm"`, `"dose"`, `"volume"`, `"auc"`, `"aumc"`, `"auc_dosenorm"`, `"aumc_dosenorm"`, `"clearance"`, `"renal_clearance"`, `"renal_clearance_dosenorm"`
---
## The `formalsmap` argument
Each `formalsmap` entry has the form `<your function's argument> = "<PKNCA data name>"` — the **names** of the list must be your function's formal arguments, and the **values** are the PKNCA data or parameter names that supply them. For example, PKNCA registers `mrt.obs` with `formalsmap = list(auc = "aucinf.obs", aumc = "aumcinf.obs")`: the computed `aucinf.obs` value is passed to the function's `auc` argument.
Standard PKNCA data names available as `formalsmap` values:
| PKNCA name | What it provides |
|---|---|
| `conc` | Concentration vector for the current interval |
| `time` | Time vector for the current interval |
| `dose` | Total dose in the current interval |
| `start` | Interval start time |
| `end` | Interval end time |
| `half.life` | Computed half-life (if in `depends`) |
| `auclast` | Computed AUClast (if in `depends`) |
| `cmax` | Computed Cmax (if in `depends`) |
| *(any parameter name)* | Any other registered parameter in `depends` |
If your function argument names **exactly match** PKNCA's standard names, `formalsmap` can be omitted or left empty.
---
## Example 1: derived from other parameters
A parameter that divides two already-computed parameters. Use `depends` to declare what must be computed first (shown here without `formalsmap` because the function's argument names match the parameter names).
```{r}
# Exposure ratio: AUClast / Cmax (units: time, since AUC/conc = time × conc/conc = time)
pk.calc.exposure.ratio <- function(auclast, cmax) {
auclast / cmax
}
add.interval.col(
name = "exposure.ratio",
FUN = "pk.calc.exposure.ratio",
values = c(FALSE, TRUE),
unit_type = "time",
pretty_name = "Exposure ratio (AUClast / Cmax)",
desc = "AUClast divided by Cmax",
depends = c("auclast", "cmax")
)
```
```{r}
o_nca_er <- pk.nca(PKNCAdata(o_conc, o_dose, intervals = data.frame(
start = 0, end = Inf,
auclast = TRUE,
cmax = TRUE,
exposure.ratio = TRUE
)))
as.data.frame(o_nca_er) |>
filter(PPTESTCD %in% c("auclast", "cmax", "exposure.ratio")) |>
select(subject, PPTESTCD, PPORRES) |>
tidyr::pivot_wider(names_from = PPTESTCD, values_from = PPORRES) |>
mutate(check = auclast / cmax) |>
arrange(subject)
```
---
## Example 2: computed from raw concentration-time data
A parameter that accesses `conc` and `time` directly. PKNCA passes the raw vectors from the concentration data. No `depends` needed. The identity `formalsmap` below is shown for explicitness — because the argument names match PKNCA's standard names, it could equally be omitted.
```{r}
# Concentration at exactly 2 hours (interpolated)
pk.calc.c_at_2h <- function(conc, time) {
interp.extrap.conc(conc = conc, time = time, time.out = 2)
}
add.interval.col(
name = "c.2h",
FUN = "pk.calc.c_at_2h",
values = c(FALSE, TRUE),
unit_type = "conc",
pretty_name = "Concentration at 2 h",
desc = "Interpolated concentration at t = 2 h",
depends = NULL,
formalsmap = list(conc = "conc", time = "time")
)
```
```{r}
o_nca_c2 <- pk.nca(PKNCAdata(o_conc, o_dose, intervals = data.frame(
start = 0, end = Inf, c.2h = TRUE
)))
as.data.frame(o_nca_c2) |>
filter(PPTESTCD == "c.2h") |>
select(subject, PPORRES) |>
arrange(subject)
```
---
## Example 3: multiple related parameters sharing a dependency
When computing several related quantities (e.g. early AUC, late AUC, and their ratio), register each as its own function. The late-AUC and fraction functions read the already-computed `auclast` dependency.
```{r}
pk.calc.auc.early <- function(conc, time) {
t_idx <- time <= 4
if (sum(t_idx) < 2) return(NA_real_)
pk.calc.auc.last(conc[t_idx], time[t_idx])
}
pk.calc.auc.late <- function(conc, time, auclast) {
t_idx <- time <= 4
if (sum(t_idx) < 2) return(NA_real_)
auclast - pk.calc.auc.last(conc[t_idx], time[t_idx])
}
pk.calc.auc.early.frac <- function(conc, time, auclast) {
t_idx <- time <= 4
if (sum(t_idx) < 2) return(NA_real_)
pk.calc.auc.last(conc[t_idx], time[t_idx]) / auclast
}
add.interval.col(
name = "auc.early",
FUN = "pk.calc.auc.early",
values = c(FALSE, TRUE),
unit_type = "auc",
pretty_name = "AUC to last sample <= 4h",
desc = "AUC to the last sample at or before 4 h",
depends = NULL,
formalsmap = list(conc = "conc", time = "time")
)
add.interval.col(
name = "auc.late",
FUN = "pk.calc.auc.late",
values = c(FALSE, TRUE),
unit_type = "auc",
pretty_name = "AUC 4h to last",
desc = "AUC from 4 h to last sample",
depends = "auclast",
formalsmap = list(conc = "conc", time = "time", auclast = "auclast")
)
add.interval.col(
name = "auc.early.fraction",
FUN = "pk.calc.auc.early.frac",
values = c(FALSE, TRUE),
unit_type = "fraction",
pretty_name = "Early AUC fraction",
desc = "Fraction of AUClast occurring in first 4 h",
depends = "auclast",
formalsmap = list(conc = "conc", time = "time", auclast = "auclast")
)
```
> **Note:** One function *can* populate several output parameters at once by returning a **one-row data frame** whose column names are registered parameter names — `pk.nca()` saves every column of the returned data frame. This is exactly how `pk.calc.half.life()` populates `half.life`, `lambda.z`, `r.squared`, and the other half-life diagnostics. Each output still needs its own `add.interval.col()` registration: register the function on the primary parameter, and register the other columns with `FUN = NA` plus a `depends` on the primary (`formalsmap` may not be given when `FUN = NA`). The one-function-per-parameter pattern shown above is the simpler option when each output is cheap to compute.
```{r}
o_nca_split <- pk.nca(PKNCAdata(o_conc, o_dose, intervals = data.frame(
start = 0, end = Inf,
auclast = TRUE,
auc.early = TRUE,
auc.late = TRUE,
auc.early.fraction = TRUE
)))
as.data.frame(o_nca_split) |>
filter(PPTESTCD %in% c("auclast", "auc.early", "auc.late", "auc.early.fraction")) |>
select(subject, PPTESTCD, PPORRES) |>
tidyr::pivot_wider(names_from = PPTESTCD, values_from = PPORRES) |>
arrange(subject)
```
The same split can be computed by **one** multi-output function returning a one-row data frame:
```{r}
pk.calc.auc.split <- function(conc, time, auclast) {
t_idx <- time <= 4
early <- if (sum(t_idx) < 2) NA_real_ else pk.calc.auc.last(conc[t_idx], time[t_idx])
data.frame(auc.early.df = early, auc.late.df = auclast - early)
}
add.interval.col(
name = "auc.early.df",
FUN = "pk.calc.auc.split", # computes BOTH auc.early.df and auc.late.df
values = c(FALSE, TRUE),
unit_type = "auc",
pretty_name = "AUC 0-4h (multi-output)",
desc = "AUC from 0 to 4 h, from a multi-output function",
depends = "auclast",
formalsmap = list(conc = "conc", time = "time", auclast = "auclast")
)
add.interval.col(
name = "auc.late.df",
FUN = NA, # populated by pk.calc.auc.split via auc.early.df
values = c(FALSE, TRUE),
unit_type = "auc",
pretty_name = "AUC 4h to last (multi-output)",
desc = "AUC from 4 h to last sample, from a multi-output function",
depends = "auc.early.df"
)
o_nca_multi <- pk.nca(PKNCAdata(o_conc, o_dose, intervals = data.frame(
start = 0, end = Inf,
auclast = TRUE, auc.early.df = TRUE, auc.late.df = TRUE
)))
as.data.frame(o_nca_multi) |>
filter(PPTESTCD %in% c("auclast", "auc.early.df", "auc.late.df")) |>
select(subject, PPTESTCD, PPORRES) |>
tidyr::pivot_wider(names_from = PPTESTCD, values_from = PPORRES) |>
arrange(subject)
```
---
## Inspecting registered parameters
```{r}
# Confirm your parameter is registered
cols <- get.interval.cols()
cat("exposure.ratio registered:", "exposure.ratio" %in% names(cols), "\n")
cat("c.2h registered: ", "c.2h" %in% names(cols), "\n")
```
```{r}
# Inspect registration details
str(cols[["exposure.ratio"]])
```
---
## Custom summary statistics for your parameter
After registering the parameter, set a custom summary rule with `PKNCA.set.summary()`:
```{r}
PKNCA.set.summary(
"exposure.ratio",
description = "geometric mean [CV%]",
point = PKNCA::geomean,
spread = PKNCA::geocv
)
summary(pk.nca(PKNCAdata(o_conc, o_dose, intervals = data.frame(
start = 0, end = Inf,
auclast = TRUE, cmax = TRUE, exposure.ratio = TRUE
))))
```
The vignette's [summary section](https://humanpred.github.io/pknca/articles/v80-writing-parameter-functions.html#tell-pknca-how-to-summarize-the-parameter) covers the same registration.
---
## Important notes
- **Registration is session-scoped.** Custom parameters registered with `add.interval.col()` persist for the life of your R session. Re-run registration code in each session (e.g. in your analysis script or package).
- **`FUN` must be a character string.** Passing a function object causes an error.
- **`depends` controls evaluation order.** List all parameters your function reads. PKNCA resolves the dependency graph and ensures they are computed before your function is called.
- **Functions must be in scope** when `pk.nca()` runs. Define them in the global environment or in a package loaded before calling `pk.nca()`.
---
::: {.callout-note icon=false appearance="minimal"}
**pkgdown reference:** [PKNCAconc()](https://humanpred.github.io/pknca/reference/PKNCAconc.html) · [PKNCAdose()](https://humanpred.github.io/pknca/reference/PKNCAdose.html) · [PKNCAdata()](https://humanpred.github.io/pknca/reference/PKNCAdata.html) · [pk.nca()](https://humanpred.github.io/pknca/reference/pk.nca.html) · [add.interval.col()](https://humanpred.github.io/pknca/reference/add.interval.col.html) · [get.interval.cols()](https://humanpred.github.io/pknca/reference/get.interval.cols.html) · [interp.extrap.conc()](https://humanpred.github.io/pknca/reference/interp.extrap.conc.html) · [pk.calc.auc.last()](https://humanpred.github.io/pknca/reference/pk.calc.auxc.html) · [PKNCA.set.summary()](https://humanpred.github.io/pknca/reference/PKNCA.set.summary.html) · [geomean()](https://humanpred.github.io/pknca/reference/geomean.html) · [geocv()](https://humanpred.github.io/pknca/reference/geomean.html)
:::