24  Utility Functions

24.1 Overview

PKNCA exports several lower-level utility functions useful for data preparation, interval validation, and direct computation outside the full PKNCAdata → pk.nca() pipeline.


24.2 BLQ concentration handling: clean.conc.blq()

Applies the BLQ-handling rule to a concentration vector before calculation. The full analysis pipeline applies this automatically, but clean.conc.blq() is useful for pre-processing or testing your own rule.

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
# Replace BLQ with half the LLOQ (= 0.05 here)
clean.conc.blq(conc, time, conc.blq = 0.05)
  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

24.3 NA concentration handling: clean.conc.na()

Removes or replaces NA concentrations. Internally called before AUC computation.

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")
  conc time
1  0.5    0
3  0.3    2
4  0.1    3
# Replace NAs with 0
clean.conc.na(conc_na, time_na, conc.na = 0)
  conc time
1  0.5    0
2  0.0    1
3  0.3    2
4  0.1    3
5  0.0    4

24.4 Concentration interpolation / extrapolation: interp.extrap.conc()

Interpolates or extrapolates a concentration at a target time given a known concentration-time profile. The aucint.* parameters use it internally when an interval boundary falls between two observed timepoints and no dosing data are given; with dosing data they use the dose-aware interp.extrap.conc.dose() instead.

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)
[1] 3.535534
# Extrapolate beyond the last sample (t = 12):
# estimate lambda.z first, then pass it to interp.extrap.conc()
hl_ex <- pk.calc.half.life(conc = conc_ex, time = time_ex)
hl_ex$lambda.z
[1] 0.2626444
interp.extrap.conc(conc = conc_ex, time = time_ex, time.out = 12,
                   lambda.z = hl_ex$lambda.z)
[1] 0.3497357

The method (linear vs log-linear) follows the auc.method setting. Extrapolation beyond Tlast requires supplying lambda.z (the terminal slope) — the function never estimates λz itself, and without lambda.z the result is NA. The example above estimates it with pk.calc.half.life(), covered next. For interpolation around dose events, see the Dose-Aware Interpolation chapter and the vignette Methods for Dose-Aware Interpolation and Extrapolation.


24.5 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.

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")]
  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.


24.6 Direct AUC computation: pk.calc.auc.all()

Computes AUC directly on a concentration-time vector with the chosen integration method. It returns the AUC with a "method" attribute (≥ 0.13.0) naming that method — the text that pk.nca() moves into the PPANMETH column of its results.

pk.calc.auc.all(
  conc   = subj1$conc,
  time   = subj1$Time,
  method = "lin up/log down"
)
[1] 147.2347
attr(,"method")
[1] "AUC: lin up/log down"

The attribute carries through arithmetic, so wrap the result in as.numeric() before comparing it to a bare number (for example with identical() or testthat::expect_equal()):

as.numeric(pk.calc.auc.all(conc = subj1$conc, time = subj1$Time,
                           method = "lin up/log down"))
[1] 147.2347

Other direct AUC functions:

Function AUC type
pk.calc.auc.last() AUC to last measurable concentration
pk.calc.auc.all() AUC to the last observation including post-Tlast BLQ values (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 the AUC parameters in the registry; the interval forms (pk.calc.aucint() and relatives) are described in the AUC chapter. Integration methods are compared in AUC integration methods.


24.7 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).

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? (drop the start/end bounds columns first)
param_cols <- setdiff(names(expanded), c("start", "end"))
param_cols[sapply(expanded[1, param_cols], isTRUE)]
[1] "auclast" "cmax"   
# Invalid specification — missing start column — raises an error;
# the handler returns the error message
tryCatch(
  check.interval.specification(data.frame(end = Inf, auclast = TRUE)),
  error = function(e) conditionMessage(e)
)
[1] "Column(s) 'start' missing from interval specification"

This is useful for debugging custom interval definitions before running the full analysis.


24.8 Listing all available parameters

cols <- get.interval.cols()
cat("Total registered parameters:", length(cols), "\n")
Total registered parameters: 237 
# Show first few with their dependency lists
lapply(head(cols, 5), function(x) x$depends)
$start
NULL

$end
NULL

$auclast
NULL

$auclast_se
[1] "auclast"

$auclast_df
[1] "auclast"
# All dose-normalized parameters
dn_params <- names(cols)[endsWith(names(cols), ".dn")]
cat("Dose-normalized parameters:\n")
Dose-normalized parameters:
cat(paste(" -", dn_params), sep = "\n")
 - 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

24.9 Modifying PKNCAdose after creation: setRoute() and setDuration()

After creating a PKNCAdose object, you can change the route or infusion duration without rebuilding from scratch.

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")
Found column named route, using it for the attribute of the same name.
# Add infusion duration (0.5 h = 30 min)
o_dose_inf <- setDuration(o_dose_iv, duration = 0.5)
Found column named duration, using it for the attribute of the same name.
# Verify
o_dose_inf$data[c("route", "duration")]
          route duration
1 intravascular      0.5

This is useful when you want to test how route assumption changes affect MRT or Vss calculations without re-specifying the PKNCAdose object from scratch.


24.10 Getting parameter dependents: get.parameter.deps()

By default, returns the downstream parameters that depend on a given parameter — the results that would be affected if it fails or is excluded.

get.parameter.deps("half.life")
  [1] "adj_tobit_residual"    "adj.r.squared"         "aucinf.obs"           
  [4] "aucinf.obs_df"         "aucinf.obs_se"         "aucinf.obs.dn"        
  [7] "aucinf.pred"           "aucinf.pred.dn"        "aucint.inf.obs"       
 [10] "aucint.inf.pred"       "aucivall_df"           "aucivall_se"          
 [13] "aucivinf.obs"          "aucivinf.obs_df"       "aucivinf.obs_se"      
 [16] "aucivinf.pred"         "aucivlast_df"          "aucivlast_se"         
 [19] "aucivpbextinf.obs"     "aucivpbextinf.pred"    "aucpext.obs"          
 [22] "aucpext.pred"          "aumcinf.obs"           "aumcinf.obs_df"       
 [25] "aumcinf.obs_se"        "aumcinf.obs.dn"        "aumcinf.pred"         
 [28] "aumcinf.pred.dn"       "aumcint.inf.obs"       "aumcint.inf.pred"     
 [31] "aumcivall_df"          "aumcivall_se"          "aumcivinf.obs"        
 [34] "aumcivinf.obs_df"      "aumcivinf.obs_se"      "aumcivinf.pred"       
 [37] "aumcivlast_df"         "aumcivlast_se"         "cav.int.inf.obs"      
 [40] "cav.int.inf.pred"      "cl.int.inf.obs"        "cl.int.inf.pred"      
 [43] "cl.iv.obs"             "cl.iv.pred"            "cl.obs"               
 [46] "cl.pred"               "clast.pred"            "clast.pred.dn"        
 [49] "f.int.obs"             "f.int.pred"            "f.obs"                
 [52] "f.pred"                "half.life"             "kel.int.inf.obs"      
 [55] "kel.int.inf.pred"      "kel.iv.obs"            "kel.iv.pred"          
 [58] "kel.obs"               "kel.pred"              "lambda.z"             
 [61] "lambda.z.corrxy"       "lambda.z.n.points"     "lambda.z.n.points_blq"
 [64] "lambda.z.time.first"   "lambda.z.time.last"    "mrt.int.inf.obs"      
 [67] "mrt.int.inf.pred"      "mrt.iv.obs"            "mrt.iv.pred"          
 [70] "mrt.ivmd.obs"          "mrt.ivmd.pred"         "mrt.md.obs"           
 [73] "mrt.md.pred"           "mrt.obs"               "mrt.pred"             
 [76] "r.squared"             "ratio.aucinf.obs"      "ratio.aucinf.pred"    
 [79] "span.ratio"            "thalf.eff.iv.obs"      "thalf.eff.iv.pred"    
 [82] "thalf.eff.obs"         "thalf.eff.pred"        "tobit_residual"       
 [85] "vss.int.inf.obs"       "vss.int.inf.pred"      "vss.iv.obs"           
 [88] "vss.iv.pred"           "vss.ivmd.obs"          "vss.ivmd.pred"        
 [91] "vss.md.obs"            "vss.md.pred"           "vss.obs"              
 [94] "vss.pred"              "vz.all"                "vz.int.all"           
 [97] "vz.int.inf.obs"        "vz.int.inf.pred"       "vz.int.last"          
[100] "vz.iv.all"             "vz.iv.last"            "vz.iv.obs"            
[103] "vz.iv.pred"            "vz.ivint.all"          "vz.ivint.last"        
[106] "vz.last"               "vz.obs"                "vz.pred"              

For the opposite direction, recursive = TRUE (≥ 0.13.0) returns what a parameter is calculated from, following each dependency back to the raw inputs (such as conc, time, and dose) and the arguments of the calculation functions along the way, including the options they read:

get.parameter.deps("vss.obs", recursive = TRUE)
 [1] "adj.r.squared.factor"     "allow.tmax.in.half.life" 
 [3] "check"                    "conc"                    
 [5] "conc.blq"                 "conc.na"                 
 [7] "dose"                     "duration.dose"           
 [9] "first.tmax"               "hl_method"               
[11] "lloq"                     "manually.selected.points"
[13] "max.hl.points"            "min.hl.points"           
[15] "min.hl.start.time"        "options"                 
[17] "r.squared.factor"         "time"                    
[19] "time.dose"                "tobit_n_points_penalty"  
[21] "tobit_optim_control"     

The registry entry lists only the direct dependencies:

get.interval.cols()[["vss.obs"]]$depends
[1] "cl.obs"  "mrt.obs"

24.11 Listing all current option values: PKNCA.options()

PKNCA.options() with no arguments returns the full named list of current settings:

PKNCA.options()
$adj.r.squared.factor
[1] 1e-04

$r.squared.factor
[1] NA

$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

$max.hl.points
[1] Inf

$min.hl.start.time
[1] 0

$min.span.ratio
[1] 2

$max.aucinf.pext
[1] 20

$min.hl.r.squared
[1] 0.9

$progress
[1] TRUE

$tau.choices
[1] NA

$auto.interval.method
[1] "builder"

$auto.interval.tolerance
[1] 0.05

$single.dose.aucs
  start end auclast auclast_se auclast_df aucall aucall_se aucall_df aumclast
1     0  24    TRUE      FALSE      FALSE  FALSE     FALSE     FALSE    FALSE
2     0 Inf   FALSE      FALSE      FALSE  FALSE     FALSE     FALSE    FALSE
  aumclast_se aumclast_df aumcall aumcall_se aumcall_df aucint.last aucint.all
1       FALSE       FALSE   FALSE      FALSE      FALSE       FALSE      FALSE
2       FALSE       FALSE   FALSE      FALSE      FALSE       FALSE      FALSE
  aumcint.last aumcint.all    c0  cmax  cmin  tmax  tmin tlast tfirst clast.obs
1        FALSE       FALSE FALSE FALSE FALSE FALSE FALSE FALSE  FALSE     FALSE
2        FALSE       FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE  FALSE     FALSE
  cl.last cl.all cl.int.all cl.int.last mrt.last mrt.all mrt.int.all
1   FALSE  FALSE      FALSE       FALSE    FALSE   FALSE       FALSE
2   FALSE  FALSE      FALSE       FALSE    FALSE   FALSE       FALSE
  mrt.int.last mrt.iv.last vss.last vss.iv.last vss.all vss.int.all
1        FALSE       FALSE    FALSE       FALSE   FALSE       FALSE
2        FALSE       FALSE    FALSE       FALSE   FALSE       FALSE
  vss.int.last   cav cav.int.last cav.int.all ctrough cstart   ptr  tlag
1        FALSE FALSE        FALSE       FALSE   FALSE  FALSE FALSE FALSE
2        FALSE FALSE        FALSE       FALSE   FALSE  FALSE FALSE FALSE
  deg.fluc swing  ceoi aucabove.predose.all aucabove.trough.all count_conc
1    FALSE FALSE FALSE                FALSE               FALSE      FALSE
2    FALSE FALSE FALSE                FALSE               FALSE      FALSE
  count_conc_measured totdose volpk    ae clr.last clr.obs clr.pred    fe
1               FALSE   FALSE FALSE FALSE    FALSE   FALSE    FALSE FALSE
2               FALSE   FALSE FALSE FALSE    FALSE   FALSE    FALSE FALSE
  ertlst ermax ertmax erint erlst ratio.cmax ratio.auclast ratio.aucint.last
1  FALSE FALSE  FALSE FALSE FALSE      FALSE         FALSE             FALSE
2  FALSE FALSE  FALSE FALSE FALSE      FALSE         FALSE             FALSE
  ratio.aucint.all sparse_auclast sparse_auc_se sparse_auc_df sparse_aumclast
1            FALSE          FALSE         FALSE         FALSE           FALSE
2            FALSE          FALSE         FALSE         FALSE           FALSE
  sparse_aumc_se sparse_aumc_df time_above aucivlast aucivlast_se aucivlast_df
1          FALSE          FALSE      FALSE     FALSE        FALSE        FALSE
2          FALSE          FALSE      FALSE     FALSE        FALSE        FALSE
  aucivall aucivall_se aucivall_df aucivint.last aucivint.all aucivpbextlast
1    FALSE       FALSE       FALSE         FALSE        FALSE          FALSE
2    FALSE       FALSE       FALSE         FALSE        FALSE          FALSE
  aucivpbextall aucivpbextint.last aucivpbextint.all aumcivlast aumcivlast_se
1         FALSE              FALSE             FALSE      FALSE         FALSE
2         FALSE              FALSE             FALSE      FALSE         FALSE
  aumcivlast_df aumcivall aumcivall_se aumcivall_df aumcivint.last
1         FALSE     FALSE        FALSE        FALSE          FALSE
2         FALSE     FALSE        FALSE        FALSE          FALSE
  aumcivint.all half.life r.squared adj.r.squared lambda.z.corrxy lambda.z
1         FALSE     FALSE     FALSE         FALSE           FALSE    FALSE
2         FALSE      TRUE     FALSE         FALSE           FALSE    FALSE
  lambda.z.time.first lambda.z.time.last lambda.z.n.points clast.pred
1               FALSE              FALSE             FALSE      FALSE
2               FALSE              FALSE             FALSE      FALSE
  span.ratio tobit_residual adj_tobit_residual lambda.z.n.points_blq
1      FALSE          FALSE              FALSE                 FALSE
2      FALSE          FALSE              FALSE                 FALSE
  thalf.eff.last thalf.eff.iv.last kel.last kel.iv.last kel.all kel.int.all
1          FALSE             FALSE    FALSE       FALSE   FALSE       FALSE
2          FALSE             FALSE    FALSE       FALSE   FALSE       FALSE
  kel.int.last cl.iv.all cl.iv.last cl.ivint.all cl.ivint.last cl.sparse.last
1        FALSE     FALSE      FALSE        FALSE         FALSE          FALSE
2        FALSE     FALSE      FALSE        FALSE         FALSE          FALSE
  f.last f.int.last f.int.all mrt.sparse.last mrt.iv.all mrt.ivint.all
1  FALSE      FALSE     FALSE           FALSE      FALSE         FALSE
2  FALSE      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.obs_se aucinf.obs_df aucinf.pred
1           FALSE      FALSE         FALSE         FALSE       FALSE
2           FALSE       TRUE         FALSE         FALSE       FALSE
  aumcinf.obs aumcinf.obs_se aumcinf.obs_df aumcinf.pred aucint.inf.obs
1       FALSE          FALSE          FALSE        FALSE          FALSE
2       FALSE          FALSE          FALSE        FALSE          FALSE
  aucint.inf.pred aumcint.inf.obs aumcint.inf.pred aucivinf.obs aucivinf.obs_se
1           FALSE           FALSE            FALSE        FALSE           FALSE
2           FALSE           FALSE            FALSE        FALSE           FALSE
  aucivinf.obs_df aucivinf.pred aucivpbextinf.obs aucivpbextinf.pred
1           FALSE         FALSE             FALSE              FALSE
2           FALSE         FALSE             FALSE              FALSE
  aumcivinf.obs aumcivinf.obs_se aumcivinf.obs_df aumcivinf.pred aucpext.obs
1         FALSE            FALSE            FALSE          FALSE       FALSE
2         FALSE            FALSE            FALSE          FALSE       FALSE
  aucpext.pred kel.iv.all kel.ivint.all kel.ivint.last kel.sparse.last cl.obs
1        FALSE      FALSE         FALSE          FALSE           FALSE  FALSE
2        FALSE      FALSE         FALSE          FALSE           FALSE  FALSE
  cl.pred cl.int.inf.obs cl.int.inf.pred cl.iv.obs cl.iv.pred f.obs f.pred
1   FALSE          FALSE           FALSE     FALSE      FALSE FALSE  FALSE
2   FALSE          FALSE           FALSE     FALSE      FALSE FALSE  FALSE
  f.int.obs f.int.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 mrt.ivmd.obs mrt.ivmd.pred
1      FALSE       FALSE      FALSE       FALSE        FALSE         FALSE
2      FALSE       FALSE      FALSE       FALSE        FALSE         FALSE
  vz.obs vz.pred vz.int.inf.obs vz.int.inf.pred vz.iv.obs vz.iv.pred
1  FALSE   FALSE          FALSE           FALSE     FALSE      FALSE
2  FALSE   FALSE          FALSE           FALSE     FALSE      FALSE
  vz.sparse.last vss.obs vss.pred vss.iv.obs vss.iv.pred vss.md.obs vss.md.pred
1          FALSE   FALSE    FALSE      FALSE       FALSE      FALSE       FALSE
2          FALSE   FALSE    FALSE      FALSE       FALSE      FALSE       FALSE
  vss.ivmd.obs vss.ivmd.pred vss.int.inf.obs vss.int.inf.pred cav.int.inf.obs
1        FALSE         FALSE           FALSE            FALSE           FALSE
2        FALSE         FALSE           FALSE            FALSE           FALSE
  cav.int.inf.pred ratio.aucinf.obs ratio.aucinf.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"

$sparse_lambda_z_se
[1] "delta"

$tobit_n_points_penalty
[1] 0

$tobit_optim_control
list()

PKNCA_options_defaults() (≥ 0.13.0) returns the default value of one or more options (or all of them, with no argument) without changing the current settings — unlike PKNCA.options(default = TRUE), which resets them:

PKNCA_options_defaults(c("auc.method", "min.hl.points", "max.hl.points"))
$auc.method
[1] "lin up/log down"

$min.hl.points
[1] 3

$max.hl.points
[1] Inf

PKNCA.options.describe() returns the description of a single option; see the Workflow Overview page for the full option reference table, and the vignette Options for Controlling PKNCA.

PKNCA.options.describe("auc.method")
[1] "The method used to calculate the AUC and related statistics. Options are: \"lin up/log down\", \"linear\", \"lin-log\""

24.12 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.

# With no local override, returns the global default
PKNCA.choose.option("min.hl.points", options = list())
[1] 3
# With a local override, the local value wins
PKNCA.choose.option("min.hl.points", options = list(min.hl.points = 5))
[1] 5

24.13 Routes of administration: pknca_routes() and pknca_match_route() (≥ 0.13.0)

pknca_routes() lists the routes PKNCA distinguishes. With synonyms = TRUE it returns a table of the spellings data use for a route (“po”, “intravenous bolus”, CDISC ROUTE terms, …), the route PKNCA uses for each, and the PKNCAdose(route = ) value it implies; pknca_match_route() looks a character vector up in that table, giving NA for spellings it does not know. A spelling that does not say bolus or infusion maps to the generic "iv".

pknca_routes()
[1] "extravascular"          "iv_bolus"               "iv_infusion"           
[4] "iv_continuous_infusion"
head(pknca_routes(synonyms = TRUE))
        synonym         route    dose_route
1 extravascular extravascular extravascular
2          oral extravascular extravascular
3            po extravascular extravascular
4        per os extravascular extravascular
5      by mouth extravascular extravascular
6       peroral extravascular extravascular
pknca_match_route(c("PO", "INTRAVENOUS BOLUS", "iv", "nasal spray"))
          route    dose_route
1 extravascular extravascular
2      iv_bolus intravascular
3            iv intravascular
4          <NA>          <NA>

The dose_route column is ready to pass to the route argument of PKNCAdose().


24.14 Converting durations: pknca_difftime_to_unit() (≥ 0.13.0)

Converts a difftime (such as a collection duration computed as the difference of two date-times) into a number in an analysis time unit — the conversion pk.nca() applies to date-time data. A value that is not a difftime is an error.

pknca_difftime_to_unit(as.difftime(90, units = "mins"), "hr")
[1] 1.5

Date-time concentration and dose times are covered in the date-time chapter.


24.15 Checking inputs before building objects (≥ 0.13.0)

Applications that assemble PKNCA objects from user data can run the same checks PKNCA runs, before calling the constructors:

Function What it checks
assert_conc_time() Concentrations and times are valid numbers and the times are sorted
assert_impute_method() An imputation specification resolves to known methods, the way PKNCAdata() and pk.nca() resolve it
PKNCA_impute_fun_list() The imputation function names an imputation string resolves to
assert_PKNCAconc(), assert_PKNCAdose(), assert_PKNCAresults() The object has the expected class
# Unsorted times are an error
tryCatch(
  assert_conc_time(conc = c(1, 2, 3), time = c(0, 2, 1)),
  error = function(e) conditionMessage(e)
)
[1] "Assertion on 'time' failed: Must be sorted."
# An imputation chain resolves to one function name per method
PKNCA_impute_fun_list(c("start_conc0", "start_predose,start_conc0"))
[[1]]
[1] "PKNCA_impute_method_start_conc0"

[[2]]
[1] "PKNCA_impute_method_start_predose" "PKNCA_impute_method_start_conc0"  
# An unknown method is an error
tryCatch(
  assert_impute_method("start_bogus"),
  error = function(e) conditionMessage(e)
)
[1] "The following imputation functions were not found: PKNCA_impute_method_start_bogus.  The imputation setting must be an imputation method or a column of the intervals."

Imputation methods themselves are described in the imputation chapter.