using Random
using Pumas
using PumasUtilities
using AlgebraOfGraphics
using CairoMakie
using CSV
using DataFramesMeta
using Dates
PK26 - Target mediated drug disposition
1 Background
- Structural model - Two compartment model with parallel linear and non-linear elimination
- Route of administration - IV bolus (Single dose)
- Dosage Regimen - 0.1 mg/kg, 0.3 mg/kg, 1 mg/kg, 3 mg/kg, and 10 mg/kg
- Number of Subjects - 5
2 Learning Outcomes
To understand the antibody kinetics with linear and nonlinear elimination after an IV bolus dose in man.
3 Objectives
- To build a two compartment model with parallel linear and non-linear elimination to understand the antibody kinetics.
- To simulate 5 subjects after a single dose IV bolus administration
4 Libraries
Call the necessary libraries to get started.
5 Model
A two compartment model with parallel linear and non-linear elimination
= @model begin
pk_26 @metadata begin
= "Parallel Linear and Non-linear Elimination Model"
desc = u"hr"
timeu end
@param begin
"""
Maximum rate of Metabolism(mg/hr/kg)
"""
∈ RealDomain(lower = 0)
tvvmax """
Michaelis constant (mg/L/kg)
"""
∈ RealDomain(lower = 0)
tvkm """
Volume of Peripheral Compartment(L/kg)
"""
∈ RealDomain(lower = 0)
tvvp """
Volume of Central Compartment(L/kg)
"""
∈ RealDomain(lower = 0)
tvvc """
Inter-compartmental Clearance(L/hr/kg)
"""
∈ RealDomain(lower = 0)
tvq """
Linear Clearance(L/hr/kg)
"""
∈ RealDomain(lower = 0)
tvcll ∈ PDiagDomain(6)
Ω """
Proportional RUV
"""
∈ RealDomain(lower = 0)
σ²_prop end
@random begin
~ MvNormal(Ω)
η end
@pre begin
= tvvmax * exp(η[1])
Vmax = tvkm * exp(η[2])
Km = tvvp * exp(η[3])
Vp = tvvc * exp(η[4])
Vc = tvq * exp(η[5])
Q = tvcll * exp(η[6]) # Linear clearance
CLl # CLmm = Vmax/(Km+C) Non-linear clearance
end
@dynamics begin
' =
Central-(Vmax / (Km + (Central / Vc))) * (Central / Vc) - CLl * (Central / Vc) -
/ Vc) * Central + (Q / Vp) * Peripheral
(Q ' = (Q / Vc) * Central - (Q / Vp) * Peripheral
Peripheralend
@derived begin
= @. Central / Vc
cp """
Observed Concentration (mg/L)
"""
~ @. Normal(cp, sqrt(cp^2 * σ²_prop))
dv end
end
PumasModel
Parameters: tvvmax, tvkm, tvvp, tvvc, tvq, tvcll, Ω, σ²_prop
Random effects: η
Covariates:
Dynamical system variables: Central, Peripheral
Dynamical system type: Nonlinear ODE
Derived: cp, dv
Observed: cp, dv
6 Parameters
The parameters are as given below. Note that tv
represents the typical value for parameters.
Vmax
- Maximum rate of metabolism (mg/hr/kg)Km
- Michaelis constant (mg/L/kg)Vp
- Volume of Peripheral Compartment (L/kg)Vc
- Volume of Central Compartment (L/kg)Q
- Inter-compartmental Clearance (L/hr/kg)CLl
- Linear Clearance (L/hr/kg)Ω
- Between Subject Variabilityσ²_prop
- Residual error
= (
param = 0.0338,
tvvmax = 0.0760,
tvkm = 0.0293,
tvvp = 0.0729,
tvvc = 0.0070,
tvq = 0.0069,
tvcll = Diagonal([0.04, 0.04, 0.04, 0.04, 0.04, 0.04]),
Ω = 0.04,
σ²_prop )
7 Dosage Regimen
5 subjects received an IV bolus dose of 0.1, 0.3, 1, 3 and 10 mg/kg respectively at time=0
= DosageRegimen(0.1, time = 0) DR1
1×10 DataFrame
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 | 0.1 | 1 | 0.0 | 0 | 0.0 | 0.0 | 0 | NullRoute |
= Subject(id = "0.1 mg/kg", events = DR1, time = 0.1:0.01:1.5) s1
Subject
ID: 0.1 mg/kg
Events: 1
= DosageRegimen(0.3, time = 0) DR2
1×10 DataFrame
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 | 0.3 | 1 | 0.0 | 0 | 0.0 | 0.0 | 0 | NullRoute |
= Subject(id = "0.3 mg/kg", events = DR2, time = 0.1:0.01:7) s2
Subject
ID: 0.3 mg/kg
Events: 1
= DosageRegimen(1, time = 0) DR3
1×10 DataFrame
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 | 1.0 | 1 | 0.0 | 0 | 0.0 | 0.0 | 0 | NullRoute |
= Subject(id = "1 mg/kg", events = DR3, time = 0.1:0.1:21) s3
Subject
ID: 1 mg/kg
Events: 1
= DosageRegimen(3, time = 0) DR4
1×10 DataFrame
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 | 3.0 | 1 | 0.0 | 0 | 0.0 | 0.0 | 0 | NullRoute |
= Subject(id = "3 mg/kg", events = DR4, time = 0.1:0.1:30) s4
Subject
ID: 3 mg/kg
Events: 1
= DosageRegimen(10, time = 0) DR5
1×10 DataFrame
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 | 10.0 | 1 | 0.0 | 0 | 0.0 | 0.0 | 0 | NullRoute |
= Subject(id = "10 mg/kg", events = DR5, time = 0.1:0.1:43) s5
Subject
ID: 10 mg/kg
Events: 1
= [s1, s2, s3, s4, s5] pop
Population
Subjects: 5
Observations:
A more succinct way of generating the pop
above across the 5 subjects is given below
= [0.1, 0.3, 1, 3, 10]
doses = [0.1:0.01:1.5, 0.1:0.01:7, 0.1:0.1:21, 0.1:0.1:30, 0.1:0.1:43]
samp_times = map(zip(doses, samp_times)) do (d, times)
pop Subject(id = string(d, " mg/kg"), events = DosageRegimen(d, time = 0), time = times)
end
Population
Subjects: 5
Observations:
8 Simulation
To simulate plasma concentration data for 5 subjects with specific obstimes
.
Random.seed!(123)
The random effects are zero’ed out since we are simulating means
= zero_randeffs(pk_26, pop, param) zfx
5-element Vector{@NamedTuple{η::Vector{Float64}}}:
(η = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],)
(η = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],)
(η = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],)
(η = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],)
(η = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],)
= simobs(pk_26, pop, param, zfx) sim
Simulated population (Vector{<:Subject})
Simulated subjects: 5
Simulated variables: cp, dv
9 Visualization
@chain DataFrame(sim) begin
dropmissing(:cp)
data(_) *
mapping(
:time => "Time (days)",
:cp => "PK26 Concentrations (mg/L)",
= :id => nonnumeric => "Doses",
color *
) visual(Lines, linewidth = 4)
draw(;
= (
axis = log10,
yscale = map(i -> 10.0^i, -2:2),
yticks = i -> (@. string(round(i; digits = 1))),
ytickformat = 0:10:40,
xticks
),= (;
figure = 22,
fontsize = (;
legend = 6,
linewidth = :bottom,
position = true,
tellwidth = true,
tellheight = Auto(),
width
),
),
)end
10 Population simulation
= (
par = 0.0338,
tvvmax = 0.0760,
tvkm = 0.0293,
tvvp = 0.0729,
tvvc = 0.0070,
tvq = 0.0069,
tvcll = Diagonal([0.04, 0.03, 0.03, 0.02, 0.04, 0.04]),
Ω = 0.04,
σ²_prop
)
= DosageRegimen(0.1, time = 0)
DR1 = DosageRegimen(0.3, time = 0)
DR2 = DosageRegimen(1, time = 0)
DR3 = DosageRegimen(3, time = 0)
DR4 = DosageRegimen(10, time = 0)
DR5
= map(i -> Subject(id = i, events = DR1), 1:45)
pop1 = map(i -> Subject(id = i, events = DR2), 46:90)
pop2 = map(i -> Subject(id = i, events = DR3), 91:135)
pop3 = map(i -> Subject(id = i, events = DR4), 136:180)
pop4 = map(i -> Subject(id = i, events = DR5), 181:225)
pop5
= vcat(pop1, pop2, pop3, pop4, pop5)
pop
Random.seed!(314)
= simobs(pk_26, pop1, par, obstimes = [0.07, 0.15, 0.33, 0.43, 0.96, 1.2])
sim_pop1 = simobs(
sim_pop2
pk_26,
pop2,
par,= [0.23, 0.33, 0.51, 1.18, 1.75, 2.2, 3.06, 3.5, 4, 4.5, 5, 5.5, 6.89],
obstimes
)= simobs(
sim_pop3
pk_26,
pop3,
par,= [0.2, 0.4, 1.2, 3.2, 4.5, 6, 7.1, 9, 10, 11, 12, 13, 14.3, 21],
obstimes
)= simobs(
sim_pop4
pk_26,
pop4,
par,= [
obstimes 0.4,
0.5,
0.6,
1.1,
3.2,
5,
7.1,
9,
10,
12,
14.2,
15,
16,
17,
19,
20.9,
22,
24,
25,
26,
27,
27.5,
28.1,
],
)= simobs(
sim_pop5
pk_26,
pop5,
par,= [
obstimes 0.2,
0.5,
1.2,
2,
3.2,
5,
7.1,
9,
12,
14.1,
16,
18,
20,
21.1,
22,
24,
25,
26.5,
28.1,
30,
32,
34,
36,
38,
40,
42.1,
],
)
= vcat(sim_pop1, sim_pop2, sim_pop3, sim_pop4, sim_pop5)
populationsimulation sim_plot(populationsimulation)
= DataFrame(populationsimulation)
df_pop #CSV.write("pk_26.csv", df_pop)