The tci
package provides closed-form solutions for 1-, 2-, 3-, and 3-compartment with effect-site PK models based on solutions described and code provided in Abuhelwa, Foster, and Upton (2015). It does not, however, include an ordinary differential equation (ODE) solver as many other R packages do, including mrgsolve, PKPDsim, and RxODE. tci
package functions can nonetheless be applied to models from these packages through the creation of user-defined PK functions.
User-defined PK functions should be created to return concentrations at a vector of time points under a continuous infusion and should be assigned S3 class “pkmod.” To illustrate, we create an example two-compartment model based on ODEs is illustrated using the mrgsolve
R package(Baron 2020). Using mrgsolve
syntax, a model can be specified as a character string and compiled using the mcode
function.
library(tci)
library(mrgsolve)
#>
#> Attaching package: 'mrgsolve'
#> The following object is masked from 'package:stats':
#>
#> filter
# define two-compartment model based on ODEs
<- '
code $PARAM CL=10, V=10, Q = 10, V2=10
$CMT A1 A2
$ODE
dxdt_A1 = -(CL/V)*A1 - (Q/V)*A1 + (Q/V2)*A2;
dxdt_A2 = -(Q/V2)*A2 + (Q/V)*A1;
'
<- mcode("example", code)
mod2cpt #> Building example ...
#> done.
Initial parameter values are required by mrgsolve
but can be updated as needed using the mrgsolve::update
function. We now need to write a wrapper that takes as arguments a time at which to evaluate the PK model (tm
), an infusion rate (kR
), PK model parameters (pars
), initial concentrations (init
), and an infusion starting time (inittm
). The starting time is used by functions in tci
that iteratively calculate concentrations from a series of infusions. The function should return a matrix with concentrations for each compartment in the rows and evaluation times as columns.
# wrapper function to evaluate pk2 in format used by tci
<- function(tm, kR, pars,
pkmod2cpt_ode pkm = pk2,
init = c(0,0),
inittm = 0){
# begin times at 0 and end at last time evaluated
<- tm - inittm
tm <- max(tm)
end_inf
# name parameter/initial concentrations
names(pars) <- toupper(names(pars))
names(init) <- c("A1","A2")
# pass parameters as list
<- sapply(pars, as.list)
pars <- unlist(pars[c("V","V2")])
vols
# update parameters and initial values (as amounts)
<- update(mod2cpt, param = pars, init = init*vols)
mod2cpt
# dosing regimen - mrgsolve function in terms of amount infused
<- ev(amt = kR*end_inf, time = 0, tinf = end_inf)
event
# simulate responses (skip tm=0 unless specified)
<- mrgsim_q(x = mod2cpt, # pk model
dat data = event, # dosing event
stime = tm) # evaluation times
# skip tm=0 unless specified in tm
<- dat@data[-1,]
dat
# return concentrations with compartments in rows and times in columns
<- t(dat[,c("A1","A2")]) / vols
cons
rownames(cons) <- colnames(cons) <- NULL
return(cons)
}class(pkmod2cpt_ode) <- "pkmod"
For use with the tci
package, the user-defined PK function should have class “pkmod.” We can now assign parameter values and predict from this model as we would any other.
# create dose
<- create_intvl(
dose as.matrix(cbind(time = c(0.5,4,4.5,10),
infrt = c(100,0,100,0)))
)
# model parameters
<- c(CL = 15, V = 10, Q = 10, V2 = 20)
pars_2cpt
# predict concentrations
predict_pkmod(pkmod2cpt_ode,
pars = pars_2cpt,
inf = dose,
tms = c(1,2,3))
#> time c1 c2
#> [1,] 1 1.0084483 0.6881986
#> [2,] 2 0.3252449 0.6216142
#> [3,] 3 0.2181003 0.4785318
# plot concentrations
plot(pkmod2cpt_ode,
pars = pars_2cpt,
inf = dose,
title = "Concentrations for a user-defined 2-compartment model")
We can also apply TCI algorithms to calculate infusion schedules required to reach designated targets with the user-defined model.
# target concentration = 1 for times 0 - 5
# target concentration = 2 for times 5 - 10
<- c(0,5,10)
tci_times <- c(1,2,2)
tci_targets
# plasma-targeting
<- tci(Ct = tci_targets,
inf_3cpt_plasma tms = tci_times,
pkmod = pkmod2cpt_ode,
pars = pars_2cpt,
tci_alg = "plasma")
# print infusion schedule
head(inf_3cpt_plasma)
#> infrt begin end dtm Ct c1_start c2_start c1_end
#> [1,] 73.20009 0.0000000 0.1666667 0.1666667 1 0 0.00000000 1
#> [2,] 24.15371 0.1666667 0.3333333 0.1666667 1 1 0.04324996 1
#> [3,] 23.42262 0.3333333 0.5000000 0.1666667 1 1 0.11966300 1
#> [4,] 22.74993 0.5000000 0.6666667 0.1666667 1 1 0.18997314 1
#> [5,] 22.13097 0.6666667 0.8333333 0.1666667 1 1 0.25466780 1
#> [6,] 21.56144 0.8333333 1.0000000 0.1666667 1 1 0.31419547 1
#> c2_end
#> [1,] 0.04324996
#> [2,] 0.11966300
#> [3,] 0.18997314
#> [4,] 0.25466780
#> [5,] 0.31419547
#> [6,] 0.36896883
# plot infusion schedule
plot(inf_3cpt_plasma)