21  NCA Parameter Dependencies

21.1 Overview

PKNCA resolves parameter dependencies automatically. When you request aucinf.obs, PKNCA internally ensures lambda.z is computed first because aucinf.obs depends on it. This graph makes those dependencies explicit.

21.2 How dependencies are defined

Every NCA parameter is registered via add.interval.col() with a depends vector listing the parameters that must be computed before it. The full registry is accessible via get.interval.cols().

21.3 Interactive dependency graph

# Get all registered interval columns (parameters)
cols <- get.interval.cols()

# Build edge list from the 'depends' field
edges <- lapply(names(cols), function(param) {
  deps <- cols[[param]]$depends
  if (length(deps) == 0) return(NULL)
  data.frame(from = deps, to = param, stringsAsFactors = FALSE)
}) |>
  bind_rows()

# All unique nodes
all_nodes <- unique(c(edges$from, edges$to, names(cols)))

# Assign category for colouring
categorise <- function(name) {
  case_when(
    grepl("^auc",       name) ~ "AUC",
    grepl("^lambda|half\\.life|r\\.squared", name) ~ "Half-life / λz",
    grepl("^cl\\.|^vz\\.|^vss", name) ~ "CL / Volume",
    grepl("^mrt",       name) ~ "MRT",
    grepl("^c(max|min|0|last|first)|^t(max|min|last|first|lag)|clast", name) ~ "Cmax / Tmax",
    grepl("^f$|bioavail|^ae|^fe|^clr|^vd",  name) ~ "Bioavailability / Renal",
    grepl("^tss",       name) ~ "Steady-state",
    TRUE ~ "Other"
  )
}

category_colours <- c(
  "AUC"                    = "#4e79a7",
  "Half-life / λz"         = "#f28e2b",
  "CL / Volume"            = "#e15759",
  "MRT"                    = "#76b7b2",
  "Cmax / Tmax"            = "#59a14f",
  "Bioavailability / Renal"= "#edc948",
  "Steady-state"           = "#b07aa1",
  "Other"                  = "#aaaaaa"
)

nodes <- data.frame(
  id    = all_nodes,
  label = all_nodes,
  group = categorise(all_nodes),
  stringsAsFactors = FALSE
) |>
  mutate(color = category_colours[group])

visNetwork(nodes, edges,
           width = "100%", height = "700px",
           main = "PKNCA NCA Parameter Dependencies") |>
  visNodes(shape = "dot", size = 14,
           font = list(size = 12),
           borderWidth = 2) |>
  visEdges(arrows = "to",
           color  = list(color = "#aaaaaa", highlight = "#333333"),
           smooth = list(type = "cubicBezier")) |>
  visOptions(
    highlightNearest = list(enabled = TRUE, degree = 2, hover = TRUE),
    nodesIdSelection = list(enabled = TRUE, main = "Select parameter")
  ) |>
  visLegend(useGroups = TRUE, position = "right") |>
  visPhysics(stabilization = list(iterations = 200)) |>
  visLayout(randomSeed = 42)

How to use this graph:

  • Click a parameter node to highlight its immediate dependencies and dependents
  • The “Select parameter” dropdown jumps to a specific node
  • Drag nodes to rearrange; scroll to zoom
  • Colours indicate parameter family (see legend)

21.4 Dependency table

For a text-based reference:

dep_table <- lapply(names(cols), function(param) {
  data.frame(
    parameter = param,
    depends_on = if (length(cols[[param]]$depends) == 0) "(none)"
                 else paste(cols[[param]]$depends, collapse = ", "),
    stringsAsFactors = FALSE
  )
}) |>
  bind_rows() |>
  arrange(parameter)

knitr::kable(dep_table, col.names = c("Parameter", "Depends on"))
Parameter Depends on
adj.r.squared half.life
adj_tobit_residual half.life
ae (none)
aucabove.predose.all cstart
aucabove.trough.all ctrough
aucall (none)
aucall.dn aucall
aucinf.obs lambda.z, clast.obs
aucinf.obs.dn aucinf.obs
aucinf.pred lambda.z, clast.pred
aucinf.pred.dn aucinf.pred
aucint.all (none)
aucint.all.dose (none)
aucint.inf.obs lambda.z, clast.obs
aucint.inf.obs.dose lambda.z, clast.obs
aucint.inf.pred lambda.z, clast.pred
aucint.inf.pred.dose lambda.z, clast.pred
aucint.last (none)
aucint.last.dose (none)
aucivall aucall, c0
aucivinf.obs aucinf.obs, c0
aucivinf.pred aucinf.pred, c0
aucivint.all aucint.all, c0
aucivint.last aucint.last, c0
aucivlast auclast, c0
aucivpbextall aucall, aucivall
aucivpbextinf.obs aucinf.obs, aucivinf.obs
aucivpbextinf.pred aucinf.pred, aucivinf.pred
aucivpbextint.all aucint.all, aucivint.all
aucivpbextint.last aucint.last, aucivint.last
aucivpbextlast auclast, aucivlast
auclast (none)
auclast.dn auclast
aucpext.obs auclast, aucinf.obs
aucpext.pred auclast, aucinf.pred
aumcall (none)
aumcall.dn aumcall
aumcinf.obs lambda.z, clast.obs
aumcinf.obs.dn aumcinf.obs
aumcinf.pred lambda.z, clast.pred
aumcinf.pred.dn aumcinf.pred
aumcint.all (none)
aumcint.all.dose (none)
aumcint.inf.obs lambda.z, clast.obs
aumcint.inf.obs.dose lambda.z, clast.obs
aumcint.inf.pred lambda.z, clast.pred
aumcint.inf.pred.dose lambda.z, clast.pred
aumcint.last (none)
aumcint.last.dose (none)
aumcivall aumcall, c0
aumcivinf.obs aumcinf.obs, c0
aumcivinf.pred aumcinf.pred, c0
aumcivint.all aumcint.all, c0
aumcivint.last aumcint.last, c0
aumcivlast aumclast, c0
aumclast (none)
aumclast.dn aumclast
c0 (none)
cav auclast
cav.dn cav
cav.int.all aucint.all
cav.int.inf.obs aucint.inf.obs
cav.int.inf.pred aucint.inf.pred
cav.int.last aucint.last
ceoi (none)
cl.all aucall
cl.int.all aucint.all
cl.int.inf.obs aucint.inf.obs
cl.int.inf.pred aucint.inf.pred
cl.int.last aucint.last
cl.iv.all aucivall
cl.iv.last aucivlast
cl.iv.obs aucivinf.obs
cl.iv.pred aucivinf.pred
cl.ivint.all aucivint.all
cl.ivint.last aucivint.last
cl.last auclast
cl.obs aucinf.obs
cl.pred aucinf.pred
cl.sparse.last sparse_auclast
clast.obs (none)
clast.obs.dn clast.obs
clast.pred half.life
clast.pred.dn clast.pred
clr.last ae
clr.last.dn clr.last
clr.obs ae
clr.obs.dn clr.obs
clr.pred ae
clr.pred.dn clr.pred
cmax (none)
cmax.dn cmax
cmin (none)
cmin.dn cmin
count_conc (none)
count_conc_measured (none)
cstart (none)
ctrough (none)
ctrough.dn ctrough
deg.fluc cmax, cmin, cav
end (none)
ermax (none)
ertlst (none)
ertmax (none)
f (none)
fe ae
half.life tmax, tlast
kel.all mrt.all
kel.int.all mrt.int.all
kel.int.inf.obs mrt.int.inf.obs
kel.int.inf.pred mrt.int.inf.pred
kel.int.last mrt.int.last
kel.iv.all mrt.iv.all
kel.iv.last mrt.iv.last
kel.iv.obs mrt.iv.obs
kel.iv.pred mrt.iv.pred
kel.ivint.all mrt.ivint.all
kel.ivint.last mrt.ivint.last
kel.last mrt.last
kel.obs mrt.obs
kel.pred mrt.pred
kel.sparse.last mrt.sparse.last
lambda.z half.life
lambda.z.corrxy half.life
lambda.z.n.points half.life
lambda.z.n.points_blq half.life
lambda.z.time.first half.life
lambda.z.time.last half.life
mrt.all aucall, aumcall
mrt.int.all aucint.all, aumcint.all
mrt.int.inf.obs aucint.inf.obs, aumcint.inf.obs
mrt.int.inf.pred aucint.inf.pred, aumcint.inf.pred
mrt.int.last aucint.last, aumcint.last
mrt.iv.all aucivall, aumcivall
mrt.iv.last auclast, aumclast
mrt.iv.obs aucinf.obs, aumcinf.obs
mrt.iv.pred aucinf.pred, aumcinf.pred
mrt.ivint.all aucivint.all, aumcivint.all
mrt.ivint.last aucivint.last, aumcivint.last
mrt.last auclast, aumclast
mrt.md.obs auclast, aumclast, aucinf.obs
mrt.md.pred auclast, aumclast, aucinf.pred
mrt.obs aucinf.obs, aumcinf.obs
mrt.pred aucinf.pred, aumcinf.pred
mrt.sparse.last sparse_auclast, sparse_aumclast
ptr cmax, ctrough
r.squared half.life
span.ratio half.life
sparse_auc_df sparse_auclast
sparse_auc_se sparse_auclast
sparse_auclast (none)
sparse_aumc_df sparse_aumclast
sparse_aumc_se sparse_aumclast
sparse_aumclast sparse_auclast
start (none)
swing cmax, cmin
tfirst (none)
thalf.eff.iv.last mrt.iv.last
thalf.eff.iv.obs mrt.iv.obs
thalf.eff.iv.pred mrt.iv.pred
thalf.eff.last mrt.last
thalf.eff.obs mrt.obs
thalf.eff.pred mrt.pred
time_above (none)
tlag (none)
tlast (none)
tmax (none)
tmin (none)
tobit_residual half.life
totdose (none)
volpk (none)
vss.all cl.all, mrt.all
vss.int.all cl.int.all, mrt.int.all
vss.int.inf.obs cl.int.inf.obs, mrt.int.inf.obs
vss.int.inf.pred cl.int.inf.pred, mrt.int.inf.pred
vss.int.last cl.int.last, mrt.int.last
vss.iv.all cl.iv.all, mrt.iv.all
vss.iv.last cl.last, mrt.iv.last
vss.iv.obs cl.obs, mrt.iv.obs
vss.iv.pred cl.pred, mrt.iv.pred
vss.ivint.all cl.ivint.all, mrt.ivint.all
vss.ivint.last cl.ivint.last, mrt.ivint.last
vss.last cl.last, mrt.last
vss.md.obs cl.last, mrt.md.obs
vss.md.pred cl.last, mrt.md.pred
vss.obs cl.obs, mrt.obs
vss.pred cl.pred, mrt.pred
vss.sparse.last cl.sparse.last, mrt.sparse.last
vz.all cl.all, lambda.z
vz.int.all cl.int.all, lambda.z
vz.int.inf.obs cl.int.inf.obs, lambda.z
vz.int.inf.pred cl.int.inf.pred, lambda.z
vz.int.last cl.int.last, lambda.z
vz.iv.all cl.iv.all, lambda.z
vz.iv.last cl.iv.last, lambda.z
vz.iv.obs cl.iv.obs, lambda.z
vz.iv.pred cl.iv.pred, lambda.z
vz.ivint.all cl.ivint.all, lambda.z
vz.ivint.last cl.ivint.last, lambda.z
vz.last cl.last, lambda.z
vz.obs cl.obs, lambda.z
vz.pred cl.pred, lambda.z
vz.sparse.last cl.sparse.last, kel.sparse.last

21.5 Dependency resolution

When you call pk.nca(), PKNCA calls sort.interval.cols() internally to produce a topologically sorted execution order — parameters with no dependencies run first, then those that depend on already-computed values.

# Reconstruct execution order: parameters with no dependencies first,
# then those whose dependencies are already satisfied.
cols <- get.interval.cols()
dep_counts <- sapply(cols, function(x) length(x$depends))
all_deps <- data.frame(
  parameter  = names(dep_counts),
  n_depends  = unname(dep_counts)
) |>
  arrange(n_depends, parameter)

cat(sprintf("%d parameters have no dependencies (base parameters).\n", sum(all_deps$n_depends == 0)))
37 parameters have no dependencies (base parameters).
cat(sprintf("%d parameters have at least one dependency (derived parameters).\n\n", sum(all_deps$n_depends > 0)))
166 parameters have at least one dependency (derived parameters).
# Show only derived parameters — these illustrate the resolution order
all_deps |>
  filter(n_depends > 0) |>
  knitr::kable(
    col.names = c("Parameter", "N dependencies"),
    caption   = "Derived parameters ordered by number of dependencies (execution order)"
  )
Derived parameters ordered by number of dependencies (execution order)
Parameter N dependencies
adj.r.squared 1
adj_tobit_residual 1
aucabove.predose.all 1
aucabove.trough.all 1
aucall.dn 1
aucinf.obs.dn 1
aucinf.pred.dn 1
auclast.dn 1
aumcall.dn 1
aumcinf.obs.dn 1
aumcinf.pred.dn 1
aumclast.dn 1
cav 1
cav.dn 1
cav.int.all 1
cav.int.inf.obs 1
cav.int.inf.pred 1
cav.int.last 1
cl.all 1
cl.int.all 1
cl.int.inf.obs 1
cl.int.inf.pred 1
cl.int.last 1
cl.iv.all 1
cl.iv.last 1
cl.iv.obs 1
cl.iv.pred 1
cl.ivint.all 1
cl.ivint.last 1
cl.last 1
cl.obs 1
cl.pred 1
cl.sparse.last 1
clast.obs.dn 1
clast.pred 1
clast.pred.dn 1
clr.last 1
clr.last.dn 1
clr.obs 1
clr.obs.dn 1
clr.pred 1
clr.pred.dn 1
cmax.dn 1
cmin.dn 1
ctrough.dn 1
fe 1
kel.all 1
kel.int.all 1
kel.int.inf.obs 1
kel.int.inf.pred 1
kel.int.last 1
kel.iv.all 1
kel.iv.last 1
kel.iv.obs 1
kel.iv.pred 1
kel.ivint.all 1
kel.ivint.last 1
kel.last 1
kel.obs 1
kel.pred 1
kel.sparse.last 1
lambda.z 1
lambda.z.corrxy 1
lambda.z.n.points 1
lambda.z.n.points_blq 1
lambda.z.time.first 1
lambda.z.time.last 1
r.squared 1
span.ratio 1
sparse_auc_df 1
sparse_auc_se 1
sparse_aumc_df 1
sparse_aumc_se 1
sparse_aumclast 1
thalf.eff.iv.last 1
thalf.eff.iv.obs 1
thalf.eff.iv.pred 1
thalf.eff.last 1
thalf.eff.obs 1
thalf.eff.pred 1
tobit_residual 1
aucinf.obs 2
aucinf.pred 2
aucint.inf.obs 2
aucint.inf.obs.dose 2
aucint.inf.pred 2
aucint.inf.pred.dose 2
aucivall 2
aucivinf.obs 2
aucivinf.pred 2
aucivint.all 2
aucivint.last 2
aucivlast 2
aucivpbextall 2
aucivpbextinf.obs 2
aucivpbextinf.pred 2
aucivpbextint.all 2
aucivpbextint.last 2
aucivpbextlast 2
aucpext.obs 2
aucpext.pred 2
aumcinf.obs 2
aumcinf.pred 2
aumcint.inf.obs 2
aumcint.inf.obs.dose 2
aumcint.inf.pred 2
aumcint.inf.pred.dose 2
aumcivall 2
aumcivinf.obs 2
aumcivinf.pred 2
aumcivint.all 2
aumcivint.last 2
aumcivlast 2
half.life 2
mrt.all 2
mrt.int.all 2
mrt.int.inf.obs 2
mrt.int.inf.pred 2
mrt.int.last 2
mrt.iv.all 2
mrt.iv.last 2
mrt.iv.obs 2
mrt.iv.pred 2
mrt.ivint.all 2
mrt.ivint.last 2
mrt.last 2
mrt.obs 2
mrt.pred 2
mrt.sparse.last 2
ptr 2
swing 2
vss.all 2
vss.int.all 2
vss.int.inf.obs 2
vss.int.inf.pred 2
vss.int.last 2
vss.iv.all 2
vss.iv.last 2
vss.iv.obs 2
vss.iv.pred 2
vss.ivint.all 2
vss.ivint.last 2
vss.last 2
vss.md.obs 2
vss.md.pred 2
vss.obs 2
vss.pred 2
vss.sparse.last 2
vz.all 2
vz.int.all 2
vz.int.inf.obs 2
vz.int.inf.pred 2
vz.int.last 2
vz.iv.all 2
vz.iv.last 2
vz.iv.obs 2
vz.iv.pred 2
vz.ivint.all 2
vz.ivint.last 2
vz.last 2
vz.obs 2
vz.pred 2
vz.sparse.last 2
deg.fluc 3
mrt.md.obs 3
mrt.md.pred 3

pkgdown reference: get.interval.cols() · add.interval.col()