using Pumas
using PumasUtilities
using Random
using CairoMakie
using AlgebraOfGraphics
using DataFramesMeta
using CSV
PK38 - Invitro/Invivo extrapolation II
1 Learning Outcome
In this tutorial, we will develop a model to analyze data based on the metabolic rate of a compound using differential equations instead of transforming data into rate versus concentration plot.
2 Background
Before constructing a model, it is important to establish the process the model will follow and a scenario for the simulation.
Below is the scenario for this tutorial:
- Structural Model - Two Enzyme Model
- Route of administration - in vitro experiment
- Dosage regimen - 50, 30, 10, 3, 1 μmol
This diagram describes how such an administered dose will be handled, which facilitates building the model.
3 Libraries
Call the required libraries to get started.
4 Model
This is a model that depicts the drug passing through two cytochrome P450 isoenzymes (assuming 100% hepatic elimination). Due to this physiologic process, nonlinear elimination for the compound will be applied.
The volume of the incubation medium is set to 1 mL.
= @model begin
pk_38 @metadata begin
= "Invitro/Invivo Extrapolation Model"
desc = u"minute"
timeu end
@param begin
"""
Maximum Metabolic Capacity of System 1 (nmol/min)
"""
∈ RealDomain(lower = 0)
tvvmax1 """
Michelis Menten Constant of System 1 (μmol/L)
"""
∈ RealDomain(lower = 0)
tvkm1 """
Maximum Metabolic Capacity of System 2 (nmol/min)
"""
∈ RealDomain(lower = 0)
tvvmax2 """
Michelis Menten Constant of System 2 (μmol/L)
"""
∈ RealDomain(lower = 0)
tvkm2 ∈ PDiagDomain(4)
Ω """
Additive RUV
"""
∈ RealDomain(lower = 0)
σ_add end
@random begin
~ MvNormal(Ω)
η end
@pre begin
= tvvmax1 * exp(η[1])
Vmax1 = tvkm1 * exp(η[2])
Km1 = tvvmax2 * exp(η[3])
Vmax2 = tvkm2 * exp(η[4])
Km2 = 1
Vmedium end
@vars begin
:= ((Vmax1 * Central / (Km1 + Central)) + (Vmax2 * Central / (Km2 + Central)))
VMKM end
@dynamics begin
' = -VMKM / Vmedium
Centralend
@derived begin
= @. Central / Vmedium
cp """
Observed Concentration (μmol/L)
"""
~ @. Normal(cp, σ_add)
dv end
end
PumasModel
Parameters: tvvmax1, tvkm1, tvvmax2, tvkm2, Ω, σ_add
Random effects: η
Covariates:
Dynamical system variables: Central
Dynamical system type: Nonlinear ODE
Derived: cp, dv
Observed: cp, dv
5 Parameters
Parameters provided for simulation are as below.
Vmax1
- Maximum Metabolic Capacity of System 1 (nmol/min)Km1
- Michelis Menten Constant of System 1 (μmol/l)Vmax2
- Maximum Metabolic Capacity of System 2 (nmol/min)Km2
- Michelis Menten Constant of System 2 (μmol/l)
These are the initial estimates we will be using in this model exercise. Note that tv
represents the typical value for parameters.
= (;
param = 0.960225,
tvvmax1 = 0.0896,
tvkm1 = 1.01877,
tvvmax2 = 8.67998,
tvkm2 = Diagonal([0.01, 0.01, 0.01, 0.01]),
Ω = 0.02,
σ_add )
6 Dosage Regimen
To start the evaluation process, the dosing regimen specified in the background section must be developed first prior to running a simulation.
The dosage regimen is specified as:
Each group is given a different concentration of 50, 30, 10,3 & 5 μmol/L.
This is how to establish one of the dosing regimens:
= DosageRegimen(50; time = 0, cmt = 1) 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 | 1 | 50.0 | 1 | 0.0 | 0 | 0.0 | 0.0 | 0 | NullRoute |
This is how to create the single subject undergoing one of the dosing regimen above.
= Subject(;
sub1 = "50 μmol/L",
id = ev1,
events = [
time 0.1,
0.5,
1,
1.5,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
23,
27,
28,
29,
30,
31,
], )
Subject
ID: 50 μmol/L
Events: 1
The same previous two steps are repeated for each dosing group below.
= DosageRegimen(30; 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 | 30.0 | 1 | 0.0 | 0 | 0.0 | 0.0 | 0 | NullRoute |
= Subject(;
sub2 = "30 μmol/L",
id = ev2,
events = [
time 0.1,
0.5,
1,
1.5,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
], )
Subject
ID: 30 μmol/L
Events: 1
= DosageRegimen(10; time = 0, cmt = 1) ev3
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(;
sub3 = "10 μmol/L",
id = ev3,
events = [0.1, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 7, 8],
time )
Subject
ID: 10 μmol/L
Events: 1
= DosageRegimen(3; time = 0, cmt = 1) ev4
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 μmol/L", events = ev4, time = [0.1, 0.5, 1, 1.5, 2, 3]) sub4
Subject
ID: 3 μmol/L
Events: 1
= DosageRegimen(5; time = 0, cmt = 1) ev5
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 | 5.0 | 1 | 0.0 | 0 | 0.0 | 0.0 | 0 | NullRoute |
= Subject(; id = "5 μmol/L", events = ev5, time = [0.1, 0.5, 1, 1.5]) sub5
Subject
ID: 5 μmol/L
Events: 1
A population is created for each subject with a different dosing regimen.
= [sub1, sub2, sub3, sub4, sub5] pop5_sub
Population
Subjects: 5
Observations:
7 Simulation
We will simulate the concentration for the pre-specified time point for each group.
Random.seed!()
The Random.seed!
function is included here for purposes of reproducibility of the simulation in this tutorial. Specification of a seed value would not be required in a Pumas workflow that is estimating model parameters.
Random.seed!(123)
= simobs(pk_38, pop5_sub, param) sim_pop5_sub
Simulated population (Vector{<:Subject})
Simulated subjects: 5
Simulated variables: cp, dv
This line demonstrates how to see the simulation results in a DataFrame
and will be important for the following visualization step.
= DataFrame(sim_pop5_sub)
df38 first(df38, 3)
Row | id | time | cp | dv | evid | amt | cmt | rate | duration | ss | ii | route | η_1 | η_2 | η_3 | η_4 | Central | Vmax1 | Km1 | Vmax2 | Km2 | Vmedium |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
String? | Float64 | Float64? | Float64? | Int64? | Float64? | Symbol? | Float64? | Float64? | Int8? | Float64? | NCA.Route? | Float64? | Float64? | Float64? | Float64? | Float64? | Float64? | Float64? | Float64? | Float64? | Int64? | |
1 | 50 μmol/L | 0.0 | missing | missing | 1 | 50.0 | Central | 0.0 | 0.0 | 0 | 0.0 | NullRoute | -0.145024 | 0.200914 | -0.134699 | -0.0280485 | missing | 0.830596 | 0.109538 | 0.890383 | 8.4399 | 1 |
2 | 50 μmol/L | 0.1 | 49.841 | 49.7956 | 0 | missing | missing | missing | missing | missing | missing | missing | -0.145024 | 0.200914 | -0.134699 | -0.0280485 | 49.841 | 0.830596 | 0.109538 | 0.890383 | 8.4399 | 1 |
3 | 50 μmol/L | 0.5 | 49.2052 | 49.2059 | 0 | missing | missing | missing | missing | missing | missing | missing | -0.145024 | 0.200914 | -0.134699 | -0.0280485 | 49.2052 | 0.830596 | 0.109538 | 0.890383 | 8.4399 | 1 |
8 Visualization
This step wrangles the data to create the plot. This step may look different from other plots in other tutorials, but really is two steps from the same process merged into one step.
With dropmissing()
, we are eliminating any missing values (in this case, this will be missing values in :cp
, plasma concentration). Next is the setup for the AlgebraOfGraphics
plot creation with the common structure denoted below:
= sorter("3 μmol/L", "5 μmol/L", "10 μmol/L", "30 μmol/L", "50 μmol/L")
dose_sorter @chain df38 begin
dropmissing(:cp)
data(_) *
mapping(
:time => "Time (min)",
:cp => "Concentration (μmol/L)",
= :id => dose_sorter => "Dose",
color *
) visual(ScatterLines, linewidth = 4, markersize = 12)
draw(;
= (; fontsize = 22),
figure = (;
axis = 0:5:35,
xticks = Makie.pseudolog10,
yscale = i -> (@. string(round(i; digits = 1))),
ytickformat
),
)end
9 Population Simulation
This block updates the parameters of the model to increase intersubject variability in parameters and defines timepoints for prediction of concentrations. The results are written to a CSV file.
= (
par = 0.960225,
tvvmax1 = 0.0896,
tvkm1 = 1.01877,
tvvmax2 = 8.67998,
tvkm2 = Diagonal([0.012, 0.021, 0.018, 0.032]),
Ω = 0.04,
σ_add
)
= DosageRegimen(50; time = 0, cmt = 1)
ev1 = map(
pop1 -> Subject(
i = i,
id = ev1,
events = (Group = "1",),
covariates = [
time 0.1,
0.5,
1,
1.5,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
23,
27,
28,
29,
30,
31,
],
),1:6,
)= DosageRegimen(30; time = 0, cmt = 1)
ev2 = map(
pop2 -> Subject(
i = i,
id = ev2,
events = (Group = "2",),
covariates = [
time 0.1,
0.5,
1,
1.5,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
],
),7:12,
)= DosageRegimen(10; time = 0, cmt = 1)
ev3 = map(
pop3 -> Subject(
i = i,
id = ev3,
events = (Group = "3",),
covariates = [0.1, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 7, 8],
time
),13:18,
)= DosageRegimen(3; time = 0, cmt = 1)
ev4 = map(
pop4 -> Subject(
i = i,
id = ev4,
events = (Group = "4",),
covariates = [0.1, 0.5, 1, 1.5, 2, 3],
time
),19:24,
)= DosageRegimen(1; time = 0, cmt = 1)
ev5 = map(
pop5 -> Subject(
i = i,
id = ev5,
events = (Group = "5",),
covariates = [0.1, 0.5, 1, 1.5],
time
),25:30,
)
These are the overall results:
= [pop1; pop2; pop3; pop4; pop5]
pop
Random.seed!(1234)
= simobs(pk_38, pop, par)
sim_pop
= DataFrame(sim_pop)
df_sim
#CSV.write("pk_38.csv", df_sim)
With the CSV.write
function, you can input the name of the dataframe (df_sim
) and the file name of your choice (pk_38.csv
) to save the file to your local directory or repository.
10 Conclusion
Constructing a model based on the metabolic rate of a compound involves:
- understanding the process of how the drug is passed through the system,
- translating processes into differential equations using Pumas, and
- simulating the model in a single patient for evaluation.