using PumasUtilities
using Random
using Pumas
using CairoMakie
using AlgebraOfGraphics
using CSV
using DataFramesMeta
using Dates
PK10 - Simultaneous fitting of IV/PO data
1 Background
- Structural model - Two compartment linear elimination with first order absorption
- Route of administration - IV bolus and oral given on separate occasions
- Dosage regimens - 100 mg IV Bolus and 500 mg Oral
- Subject - 1
2 Learning Outcome
This exercise demonstrates simultaneous fitting of IV/PO data and will help you understand the disposition of drugs following IV and oral administration (with and without lag time).
3 Objectives
To build a two-compartment model, simulate the model for a single subject given IV bolus and oral dose on separate occasions and subsequently perform simulation for a population.
4 Libraries
Load the necessary libraries.
5 Model definition
Note the expression of the model parameters with helpful comments. The model is expressed with differential equations. Residual variability is a proportional error model.
In this two compartment model, we administer doses to the Depot and Central compartments.
= @model begin
pk_10 @metadata begin
= "Two Compartment Model"
desc = u"minute"
timeu end
@param begin
"""
Volume of Central Compartment (L)
"""
∈ RealDomain(lower = 0)
tvvc """
Volume of Peripheral Compartment (L)
"""
∈ RealDomain(lower = 0)
tvvp """
InterCompartmental Clearance (L/min)
"""
∈ RealDomain(lower = 0)
tvq """
Clearance (L/min)
"""
∈ RealDomain(lower = 0)
tvcl """
Absorption Rate Constant (min⁻¹)
"""
∈ RealDomain(lower = 0)
tvka """
Fraction of drug absorbed
"""
∈ RealDomain(lower = 0)
tvfa """
Lagtime (min)
"""
∈ RealDomain(lower = 0)
tvlag ∈ PDiagDomain(7)
Ω """
Proportional RUV
"""
∈ RealDomain(lower = 0)
σ²_prop end
@random begin
~ MvNormal(Ω)
η end
@pre begin
= tvvc * exp(η[1])
Vc = tvvp * exp(η[2])
Vp = tvq * exp(η[3])
Q = tvcl * exp(η[4])
CL = tvka * exp(η[5])
Ka end
@dosecontrol begin
= (Depot = tvfa * exp(η[6]),)
bioav = (Depot = tvlag * exp(η[7]),)
lags end
@dynamics Depots1Central1Periph1
@derived begin
= @. Central / Vc
cp """
Observed Concentration (mg/L)
"""
~ @. Normal(cp, sqrt(cp^2 * σ²_prop))
dv end
end
PumasModel
Parameters: tvvc, tvvp, tvq, tvcl, tvka, tvfa, tvlag, Ω, σ²_prop
Random effects: η
Covariates:
Dynamical system variables: Depot, Central, Peripheral
Dynamical system type: Closed form
Derived: cp, dv
Observed: cp, dv
6 Initial Estimates of Model Parameters
The model parameters for simulation are the following. Note that tv
represents the typical value for parameters.
Vc
- Volume of Central Compartment (L)Vp
- Volume of Peripheral Compartment (L)Q
- InterCompartmental clearance (L/min)Cl
- Clearance from Central InterCompartmental (L/min)Ka
- Absorption rate constant (min⁻¹)Fa
- Fraction of drug absorbedlags
- Lagtime (min)Ω
- Between Subject Variabilityσ
- Residual error
6.1 IV / PO - without lagtime
A vector of model parameter values is defined.
= (
param1 = 59.9348,
tvvc = 60.5898,
tvvp = 1.55421,
tvq = 0.967573,
tvcl = 0.0471557,
tvka = 0.318748,
tvfa = 14.8187,
tvlag = Diagonal([0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01]),
Ω = 0.01,
σ²_prop )
6.2 IV / PO - with lagtime
= (param1..., tvlag = 14.8187) param2
7 Dosage Regimen and Subjects
Dosage Regimen - single subject receiving 100 mg Intravenous bolus dose and 500 mg oral dose on different occasions.
7.1 IV
= DosageRegimen(100, time = 0, cmt = 2) ev1
Row | time | cmt | amt | evid | ii | addl | rate | duration | ss | route |
---|---|---|---|---|---|---|---|---|---|---|
Float64 | Int64 | Float64 | Int8 | Float64 | Int64 | Float64 | Float64 | Int8 | NCA.Route | |
1 | 0.0 | 2 | 100.0 | 1 | 0.0 | 0 | 0.0 | 0.0 | 0 | NullRoute |
= Subject(id = "ID:1 IV", events = ev1, observations = (cp = nothing,)) sub1_iv
Subject
ID: ID:1 IV
Events: 1
Observations: cp: (n=0)
7.2 PO
= DosageRegimen(500, time = 0, cmt = 1) ev2
Row | time | cmt | amt | evid | ii | addl | rate | duration | ss | route |
---|---|---|---|---|---|---|---|---|---|---|
Float64 | Int64 | Float64 | Int8 | Float64 | Int64 | Float64 | Float64 | Int8 | NCA.Route | |
1 | 0.0 | 1 | 500.0 | 1 | 0.0 | 0 | 0.0 | 0.0 | 0 | NullRoute |
= ["ID:1 PO No Lag", "ID:1 PO With Lag"]
ids
= map(
pop_po -> Subject(id = ids[i], events = ev2, observations = (cp = nothing,)),
i 1:length(ids),
)
Population
Subjects: 2
Observations: cp
8 Single-Subject Simulation
8.1 IV
Simulate plasma concentration with specific observation times after IV bolus.
Initialize the random number generator with a seed for reproducibility of the simulation.
Random.seed!(123)
Define the timepoints at which concentration values will be simulated.
= simobs(pk_10, sub1_iv, param1, obstimes = 0.1:0.1:400) sim_iv_sub1
SimulatedObservations
Simulated variables: cp, dv
Time: 0.1:0.1:400.0
8.2 PO
Simulate plasma concentration with specific observation times after PO (with and without lag time)
= map(zip(pop_po, [param1, param2])) do (subj, p)
sim_po_sub1 return simobs(pk_10, subj, p, obstimes = 0.1:0.1:400)
end
Simulated population (Vector{<:Subject})
Simulated subjects: 2
Simulated variables: cp, dv
9 Visualize Results
= [sim_iv_sub1, sim_po_sub1...]
all_sims @chain DataFrame(all_sims) begin
dropmissing(:cp)
data(_) *
mapping(:time => "Time (minutes)", :cp => "Concentration (mg/L)"; color = :id => "") *
visual(Lines; linewidth = 4)
draw(;
= (; xticks = 0:50:400),
axis = (; fontsize = 22),
figure = (; position = :bottom),
legend
)end
10 Perform a Population Simulation
We perform a population simulation with 50 participants.
This code demonstrates how to write the simulated concentrations to a comma separated file (.csv).
= (
par = 59.9348,
tvvc = 60.5898,
tvvp = 1.55421,
tvq = 0.967573,
tvcl = 0.0471557,
tvka = 0.318748,
tvfa = 14.8187,
tvlag = Diagonal([0.04, 0.09, 0.0252, 0.0125, 0.06, 0.0225, 0.0158]),
Ω = 0.0168738,
σ²_prop
)
= DosageRegimen(100, time = 0, cmt = 2)
ev1 = map(i -> Subject(id = i, events = ev1), 1:50)
pop_iv
Random.seed!(1234)
= simobs(pk_10, pop_iv, par, obstimes = 0:1:400)
pop_sim_iv = DataFrame(pop_sim_iv)
df_pop_iv :route] .= "IV"
df_pop_iv[!,
= DosageRegimen(500, time = 0, cmt = 1)
ev2 = map(i -> Subject(id = i, events = ev2), 1:50)
pop_oral
Random.seed!(1234)
= simobs(pk_10, pop_oral, par, obstimes = 0:1:400)
pop_sim_oral = DataFrame(pop_sim_oral)
df_pop_oral :route] .= "ORAL"
df_pop_oral[!,
= vcat(df_pop_iv, df_pop_oral)
pkdata_10_sim #CSV.write("pk_10_sim.csv", pkdata_10_sim)
11 Conclusion
This tutorial showed simultaneous fitting of IV/Oral data to understand the disposition of drugs.