Model integrated NCA
In addition to running NCA independently on a dataset, NCA parameters can be computed from the output of a simulation of a Pumas model.
NCA used to be computed inside the model, by annotating the observed variables of interest with @nca in the @observed block. That macro has been removed, together with the conversion of a Subject to an NCASubject. Computing the NCA parameters from the simulation output instead, as shown below, keeps the model itself free of the analysis and gives access to the full set of NCA options.
NCA needs a route of administration, since the parameters that depend on the dose are undefined without it. The route is not part of the dose records, so it is carried as a covariate of the subject, holding one of the strings NCA accepts: "ivbolus", "ivinfusion" or "ev". A covariate named route is picked up by the reader automatically.
parmet = @model begin
@param begin
θ ∈ VectorDomain(5)
Ω ∈ PDiagDomain(4)
σ_prop ∈ RealDomain(; lower = 0)
end
@random begin
η ~ MvNormal(Ω)
end
@pre begin
CL = θ[1] * exp(η[1])
Vc = θ[2] * exp(η[2])
CLM = θ[3] * exp(η[3])
VM = θ[4] * exp(η[4])
fm = θ[5]
K = (fm * (CL / Vc))
KPM = ((1 - fm) * (CL / Vc))
KM = (CLM / VM)
end
@dynamics begin
Central' = -K * Central - KPM * Central
Metabolite' = KPM * Central - KM * Metabolite
end
@derived begin
cp := @. Central / Vc
cm := @. Metabolite / VM
dv_cp ~ @. ProportionalNormal(cp, σ_prop)
dv_cm ~ @. ProportionalNormal(cm, σ_prop)
end
end
ev = DosageRegimen(2000; ii = 24, addl = 3)
population =
map(i -> Subject(; id = i, events = ev, covariates = (; route = "ivbolus")), 1:4)
parms = (;
θ = [
11.5, # CL
50.0, # V
10.0, # CLM
8.0, # VM
0.7, # fm
],
Ω = diagm(0 => [0.04, 0.04, 0.04, 0.04]),
σ_prop = 0.01,
)The model is simulated as usual:
sims = simobs(parmet, population, parms; obstimes = 0:1:108)The simulation is then written to a table and read_nca_pumas reads that table into NCA profiles. concentration names the column to analyse — here the simulated observation dv_cp, but any concentration column of the table can be used — and grouping by dosenum, the dose counter of the table, starts a new profile at every dose:
df = DataFrame(sims)
nca_dv_cp =
read_nca_pumas(df; concentration = :dv_cp, dose = :amt, tau = :ii, group = [:dosenum])The NCA parameters are computed from the profiles with run_nca:
run_nca(nca_dv_cp, [:auc, :cmax, :half_life])| Row | dosenum | id | profile | dose | route | duration | tau | assumed_tau | auc | cmax | half_life |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Int64 | String | Int64 | Float64 | String | Missing | Missing | Missing | Float64 | Float64 | Float64 | |
| 1 | 1 | 1 | 1 | 2000.0 | ivbolus | missing | missing | missing | 191.585 | 41.0313 | 3.27353 |
| 2 | 2 | 1 | 2 | 2000.0 | ivbolus | missing | missing | missing | 192.258 | 40.7598 | 3.27928 |
| 3 | 3 | 1 | 3 | 2000.0 | ivbolus | missing | missing | missing | 191.822 | 39.8767 | 3.27462 |
| 4 | 4 | 1 | 4 | 2000.0 | ivbolus | missing | missing | missing | 192.766 | 41.431 | 3.27702 |
| 5 | 1 | 2 | 5 | 2000.0 | ivbolus | missing | missing | missing | 204.388 | 36.4351 | 3.85226 |
| 6 | 2 | 2 | 6 | 2000.0 | ivbolus | missing | missing | missing | 208.028 | 37.2094 | 3.8424 |
| 7 | 3 | 2 | 7 | 2000.0 | ivbolus | missing | missing | missing | 208.386 | 36.9923 | 3.85134 |
| 8 | 4 | 2 | 8 | 2000.0 | ivbolus | missing | missing | missing | 207.412 | 36.6388 | 3.84605 |
| 9 | 1 | 3 | 9 | 2000.0 | ivbolus | missing | missing | missing | 168.391 | 38.2607 | 3.01891 |
| 10 | 2 | 3 | 10 | 2000.0 | ivbolus | missing | missing | missing | 169.796 | 39.2944 | 3.01361 |
| 11 | 3 | 3 | 11 | 2000.0 | ivbolus | missing | missing | missing | 169.029 | 38.139 | 3.02529 |
| 12 | 4 | 3 | 12 | 2000.0 | ivbolus | missing | missing | missing | 168.924 | 38.4243 | 3.02407 |
| 13 | 1 | 4 | 13 | 2000.0 | ivbolus | missing | missing | missing | 202.056 | 39.5039 | 3.5447 |
| 14 | 2 | 4 | 14 | 2000.0 | ivbolus | missing | missing | missing | 203.57 | 39.4734 | 3.54055 |
| 15 | 3 | 4 | 15 | 2000.0 | ivbolus | missing | missing | missing | 204.148 | 40.2535 | 3.54513 |
| 16 | 4 | 4 | 16 | 2000.0 | ivbolus | missing | missing | missing | 203.149 | 39.376 | 3.5479 |
The dosage regimen used here administers four doses, so there are four profiles and hence four rows per subject, identified by dosenum together with id. Observations taken before the first dose carry dosenum = 0 and have to be dropped before reading, since a profile needs exactly one dose record.
The endpoints to compute are given as the second argument, and they can be renamed and given their own keyword arguments there; see run_nca and the Endpoint Reference for the full set. Omitting the argument computes every endpoint applicable to the data.