Additional PML examples

This section provides example modeling code for the following cases.

Multinomial (ordered categorical)

Time to event model (exponential)

Time to event model (Weibull)

Emax (Hill) model with exponent

One-compartment IV bolus population PK

One-compartment IV bolus, two parallel models with common fixed effects

One-compartment model with sequence

One-compartment model with sleep statement

One-compartment first-order absorption model, compartment initialized with sequence

One-compartment first-order absorption, closed-form

One-compartment first-order absorption with lag time, closed-form

One-compartment IV bolus with time-to-event outcome and PK observations

Multinomial (ordered categorical)

  category3(){
#observed values are one of three categories 0, 1, or 2
#probability of observing a higher category number increases
#with covariate x
covariate(x)
fixef(
x1=c(0, 1.5,)
x12=c(0, 1,)
)
ranef(nx1=0.25)
stparm(xx1=x1+nx1, xx2=xx1+x12)
#xx2 > xx1 since x12 > 0
y1=x-xx1
y2=x-xx2
#xx2 > xx1, so y1 > y2
#ilogit(y)=exp(y)/(1+exp(y)), built in function
p01=ilogit(y1)
p12=ilogit(y2)
#by construction, y2<y1, so 0<p12<p01<1
#p12=prob(category2)
#p01=prob(category 2)+prob(category 1)
#1-p01=prob(category 0)
LL(y, log(y == 0 ? 1-p01:y == 1 ? p01-p12:p12-0))
}

Time to event model (exponential)

Hazard model data for subject 1. Events occurred at time=1.72 and 2.43, then from 2.43 to 4.00 no event occurred (right censored). The first record with an empty observation establishes the time of the start of the first period.

  ## id  time  dose occur
1 0 10 .
1 1.72 10 1
1 2.43 10 1
1 4.00 10 0
#The above data says the event occurred at times 1.72 and
#2.43, then between times 2.43 and 4.00 it did not occur,
#so it is right-censored.

Model file:

  hazard(){
covariate(dose)
fixef(
tvlHaz=c(, -2,)
dlHazdDose=c(-0.8, 1.2, 1.2)
)
stparm(haz=exp((tvlHaz+nlHaz)+dlHazdDose*dose))
ranef(nlHaz=0.01)
#The hazard function haz (which here is a constant) is
#integrated over the current period by a hidden differential
#equation dcumhazard/dt=haz, which yields a survival
#probability of S=exp(-cumhazard). That integral is reset
#to zero after every observation.
#
#The likelihood (if the event occurred) is S*haz and S (if
#an event did not occur). This likelihood computation and
#the differential equation computation are automatically
#invoked by event(occur,haz).
event(occur, haz)
}

Interval censoring capabilities of the event statement are signified by observed values.

2: Indicates the end of an interval in which the event occurred one or more times but at unknown times. In this case P = 1 – S.

–1, –2, –…: Indicates the end of an interval in which the event occurred exactly n=1, or 2, or … times, where the time is unknown. In this case:

    Phoenix_UserDocs_PML_image1611

(a Poisson distribution).

Note: this is equivalent to a simple Poisson count model.

–999999: Indicates the end of an interval in which the event occurred an unknown number of times, i.e., the subject was simply out of contact with no information, so P = 1.

Time to event model (Weibull)

To model Weibull-distributed events, whether censored or not, if there is more than one event per subject, a decision must be made as to what time value to use for each observation. There are usually two possibilities:

Delta-time since prior observation (or start of subject)

Delta-time since start of subject

This section shows how to do both possibilities.

First, Weibull has two structural parameters, which will be called lambda and k in this example. lambda is the scale parameter. The larger the lambda, the larger the expected time to observation. k is the shape parameter. The larger the k, the more sigmoidal the survival function. The hazard rate is a function of these two parameters:

   hazard=k/lambda*(T/lambda)^(k-1)

where T is one of the two Delta-time values mentioned above.

To follow option 1, one could say:

   hazard=k/lambda*(T/lambda)^(k-1)
deriv(T=1) #take explicit control of time
deriv(cumhaz=hazard)
LL(flag, log(flag?hazard*exp(-cumhaz):
exp(-cumhaz)), doafter={cumhaz=0; T=0;})

or use the built-in event statement:

   hazard=k/lambda*(T/lambda)^(k-1)
deriv(T=1)
event(occur, hazard, doafter={T=0;})

To follow option 2, one could say:

   hazard=k/lambda*(T/lambda)^(k-1)
deriv(T=1)
deriv(cumhaz=hazard)
LL(occur, log(occur?hazard*exp(-cumhaz):
exp(-cumhaz)))
# Notice that t could be used in place of T, and
# deriv(T=1) could be removed.

Notice that the event statement can only be used in option 1 because it automatically resets the accumulated hazard, where in option 2, that is not desired.

Emax (Hill) model with exponent

  emaxhill(){
e=e0+(emax-e0)*c^Power/(c^Power+ec50^Power)
fixef(
tvE0=c(0, 2,)
tvEMax=c(0, 5,)
tvlEC50=c(0, 1.1,)
tvPower=c(0, 1,)
)
covariate(c)
stparm(
e0=tvE0+nE0
emax=tvEMax+nEMax
ec50=exp(tvlEC50+nlEC50)
Power=tvPower #no random effect
)
ranef(nE0=1, nEMax=2, nlEC50=1)
error(eps1=2)
observe(eObs=e+eps1)
}

One-compartment IV bolus population PK

  ivbolus(){
dosepoint(a)
deriv(a=-a*ke)
#replace above line with “cfMicro(a, ke)” for closed form
#formulation
c=a/v
fixef(
tvlKe=c(, -4.6,)
tvlV=c(, 2.3,)
)
stparm(ke=exp(tvlKe+nlKe), v=exp(tvlV+nlV))
ranef(nlKe=0.25, nlV=0.25)
error(eps1=0.5) #initial estimate res err cv=50%
observe(cObs=c*(1+eps1)) #proportional residual error
}

One-compartment IV bolus, two parallel models with common fixed effects

  ivboluspar(){
dosepoint(a1)
deriv(a1=-a1*ke1)
c1=a1/v1
dosepoint(a2)
deriv(a2=-a2*ke2)
c2=a2/v2
fixef(
tvlKe=c(, -4.6,)
tvlV=c(, 2.3,)
)
ranef(block(nlKe1, nlV1)=c(0.25, 0.01, 0.25)
same(nlKe2,nlV2))
stparm(ke1=exp(tvlKe+nlKe1), v1=exp(tvlV+nlV1))
stparm(ke2=exp(tvlKe+nlKe2), v2=exp(tvlV+nlV2))
error(eps1=1)
observe(cObs1=c1+eps1)
observe(cObs2=c2+eps1)
}

One-compartment model with sequence

  onecompfoseq(){
deriv(a=-a*ke)
c=a/v
fixef(
tvlKe=c(, -4.6,)
tvlV=c(, 2.3,)
)
stparm(ke=exp(tvlKe+nlKe), v=exp(tvlV+nlV))
ranef(nlKe=0.5, nlV=0.5)
error(eps1=1)
observe(cObs=c+c*eps1) #proportional residual error
sequence{
a=10 #sets initial value of compartment a to 10
#useful if all subjects have a single bolus dose of 10 at
#time=0
}
}

One-compartment model with sleep statement

  testmodel(){
deriv(a=-a*ke)
c=a/v
fixef(
tvlKe=c(, -4.6,)
tvlV=c(, 2.3,)
)
stparm(ke=exp(tvlKe+nlKe), v=exp(tvlV+nlV))
ranef(nlKe=0.5, nlV=0.5)
error(eps1=1)
observe(cObs=c+c*eps1)
sequence {
sleep(1) #sleep for time duration=1
a=10 #set compartment a to 10 after sleep i.e., at time=1
}
}

One-compartment first-order absorption model, compartment initialized with sequence

  onecmtfo(){
deriv(aa=-aa*ka)
deriv(a1=aa*ka-a1*ke)
#replace above two lines with "cfMicro(aa, ke, first=
#(depot=ka))" to obtain faster closed form version
dosepoint(aa)
sequence {a1=4.8} #initializes compartment a1 to 4.8
c=a1/v
stparm(
ka=exp(tvlKa+nlKa)
ke=exp(tvlKe+nlKe)
v=exp(tvlV+nlV)
)
ranef(nlKa=0.25, nlKe=0.25, nlV=0.25)
fixef(
tvlKa=c(, -0.7,)
tvlKe=c(, -3,)
tvlV=c(, 2.3,)
)
error(eps1=1)
observe(cObs=c+eps1)
}

One-compartment first-order absorption, closed-form

  onecmptfocf(){
cfMicro(a1, ke, first=(aa=ka))
#aa is an arbitrary name of the depot (dosing) compartment -
#not used elsewhere in the model.
dosepoint(aa)
c=a1/v
stparm(
ka=exp(tvlKa+nlKa)
ke=exp(tvlKe+nlKe)
v=exp(tvlV+nlV)
)
ranef(nlKa=0.25, nlKe=0.25, nlV=0.25)
fixef(
tvlKa=c(, -0.7,)
tvlKe=c(, -3,)
tvlV=c(, 2.3,)
)
error(eps1=1)
observe(cObs=c+c*eps1)
}

One-compartment first-order absorption with lag time, closed-form

  onecmptfolag(){
dosepoint(aa, tlag=tlag)
cfMicro(aa,ke,first=(depot=ka))
#faster evaluation than equivalent ODE system
#deriv(aa=-aa*ka)
#deriv(a1=aa*ka-a1*ke)
c=a1/v
stparm(
ka=exp(tvlKa+nlKa)
tlag=exp(tvlTLag+nlTLag)
ke=exp(tvlKe+nlKe)
v=exp(tvlV+nlV)
)
ranef(nlKa=0.25, nlTLag=0.25, nlKe=0.25, nlV=0.25)
fixef(
tvlKa=c(, 1,)
tvlTLag=c(, 0.1,)
tvlKe=c(, -3,)
tvlV=c(, 2.3,)
)
error(eps1=1)
observe(cObs=c+c*eps1)
}

One-compartment IV bolus with time-to-event outcome and PK observations

  timetoeventconc(){
dosepoint(a)
deriv(a=-a*ke)
c=a/v
fixef(
tvlKe=c(, -4.6,)
tvlV=c(, 2.3,)
dHdC=c(0, 0.01,)
)
stparm(ke=exp(tvlKe+nlKe), v=exp(tvlV+nlV))
ranef(nlKe=0.5, nlV=0.5)   
error(eps1=1)
observe(cObs=c+c*eps1)
#instantaneous hazard rate is assumed proportional to
#concentration c
#proportionality constant dHdC is a fixed effect to be
#estimated
event(occur, c*dHdC)
}



Legal Notice | Contact Certara
© Certara USA, Inc. All rights reserved.