NONMEM 语法对照#
本节中提供了一些在 NONMEM 中常用的模型与 Maspectra 的对照:
我们将通过三种建模方式,对同一个模型 (血管外给药一室模型, Extravascular One Compartment Model with Linear Elimination) 进行模型拟合。
基础自定义模型#
根据模型中央室的浓度 (Concentration) 公式
\[\begin{split}
C_{central}(t) = \begin{cases}
0 & \text{if } t \leq T_{alag} \\
\frac{Dose}{V} \cdot \frac{K_a}{K_a - K} \cdot \left( e^{-K \cdot (t - T_{alag})} - e^{-K_a \cdot (t - T_{alag})} \right) & \text{if } t > T_{alag}
\end{cases}
\end{split}\]
可定义含吸收延迟的模型为:
from mas.model import *
class Warfarin(Module):
def __init__(self) -> None:
super().__init__()
# 定义 theta 参数及初值
self.pop_v = theta(7.81, bounds=(0, None))
self.pop_cl = theta(0.134, bounds=(0, None))
self.pop_ka = theta(0.571, bounds=(0, None))
self.pop_alag = theta(0.823, bounds=(0, None))
# 定义 eta/omega 参数及 omega 的方差初值
self.eta_v = omega(0.049)
self.eta_cl = omega(0.0802)
self.eta_ka = omega(0.47)
self.eta_alag = omega(0.156)
# 定义 epsilon/sigma 参数及 sigma 的方差初值
self.eps_prop = sigma(0.0104)
self.eps_add = sigma(0.554)
# 设置模型中需要的数据列 (结构模型所需变量、协变量)
self.dose = column("DOSE")
self.time = column("TIME")
self.wt = column("WT) # 体重协变量
def pred(self):
v = self.pop_v * exp(self.eta_v)
cl = self.pop_cl * exp(self.eta_cl)
ka = self.pop_ka * exp(self.eta_ka)
alag = self.pop_alag * exp(self.eta_alag)
k = cl / v
ipred = 0
if self.time > alag:
ipred = self.dose / v * ka / (ka - k) * (exp(-k * (self.time - alag)) - exp(-ka * (self.time - alag)))
y = ipred * (1 + self.eps_prop) + self.eps_add
return y
model = PopModel(mod=Warfarin, data=warfarin)
fit_res = model.fit(FOCEi(maxiter=9999, print=10), cov=True)
fit_res.summary()
$PROBLEM Warfarin PK Model
$DATA warfarin.csv IGNORE=#
$INPUT ID TIME AMT DV DVID MDV DOSE WT AGE SEX
$PRED
V = THETA(1) * EXP(ETA(1))
CL = THETA(2) * EXP(ETA(2))
KA = THETA(3) * EXP(ETA(3))
ALAG = THETA(4) * EXP(ETA(4))
K = CL / V
IPRED = 0
IF (TIME>ALAG) THEN
IPRED = DOSE / V * KA / (KA - K) * (EXP(-K * (TIME - ALAG)) - EXP(-KA * (TIME - ALAG)))
ENDIF
Y = IPRED * (1 + EPS(1)) + EPS(2)
$THETA
(0.0, 7.81, 1000000.0) ; pop_v
(0.0, 0.134, 1000000.0) ; pop_cl
(0.0, 0.571, 1000000.0) ; pop_ka
(0.0, 0.823, 1000000.0) ; pop_alag
$OMEGA 0.049
$OMEGA 0.0802
$OMEGA 0.47
$OMEGA 0.156
$SIGMA 0.0104
$SIGMA 0.554
$ESTIMATION METHOD=COND INTER MAXEVAL=9999 PRINT=10
$COVARIANCE
内置药动学房室模型#
因为该模型较常用,在 Maspectra 和 NONMEM 软件中均以内置模型库形式支持,以简化建模、提升拟合速度。
from mas.model import *
class Warfarin(EvOneCmtLinear):
# EvOneCmtLinear 代表血管外给药一室模型 (Extravascular One Compartment Model with Linear Elimination)
# 对应 NONMEM 的 ADVAN2
def __init__(self) -> None:
super().__init__()
# 定义 theta 参数及初值
self.pop_cl = theta(0.134, bounds=(0, None))
self.pop_v = theta(7.81, bounds=(0, None))
self.pop_ka = theta(0.571, bounds=(0, None))
self.pop_alag = theta(0.823, bounds=(0, None))
# 定义 eta/omega 参数及 omega 的方差初值
self.eta_cl = omega(0.049)
self.eta_v = omega(0.0802)
self.eta_ka = omega(0.047)
self.eta_alag = omega(0.156)
# 定义 epsilon/sigma 参数及 sigma 的方差初值
self.eps_prop = sigma(0.0104)
self.eps_add = sigma(0.554)
def pred(self) -> Expression:
cl = self.pop_cl * exp(self.eta_cl)
v = self.pop_v * exp(self.eta_v)
ka = self.pop_ka * exp(self.eta_ka)
alag = self.pop_alag * exp(self.eta_alag)
# 使用生理意义参数形式 (Physiological, 即使用 CL/Q 等参数)
# 对应 NONMEM 中 TRANS2
pred_res = self.pred_physio(cl=cl, v=v, ka=ka, alag1=alag, s2=v)
ipred = pred_res.F
y = ipred * (1 + self.eps_prop) + self.eps_add
return y
model = PopModel(mod=Warfarin, data=warfarin)
fit_res = model.fit(FOCEi(maxiter=9999, print=10), cov=True)
fit_res.summary()
$PROBLEM Warfarin PK Model
$DATA warfarin.csv IGNORE=#
$INPUT ID TIME AMT DV DVID MDV WT AGE SEX
$SUBROUTINES ADVAN2 TRANS2
$PK
CL = THETA(1) * EXP(ETA(1))
V = THETA(2) * EXP(ETA(2))
KA = THETA(3) * EXP(ETA(3))
ALAG1 = THETA(4) * EXP(ETA(4))
S2 = V
$ERROR
IPRED = F
T = IPRED * (1 + EPS(1)) + EPS(2)
$THETA
(0.0, 7.81, 1000000.0) ; pop_v
(0.0, 0.134, 1000000.0) ; pop_cl
(0.0, 0.571, 1000000.0) ; pop_ka
(0.0, 0.823, 1000000.0) ; pop_alag
$OMEGA 0.049
$OMEGA 0.0802
$OMEGA 0.47
$OMEGA 0.156
$SIGMA 0.0104
$SIGMA 0.554
$ESTIMATION METHOD=COND INTER MAXEVAL=9999 PRINT=10
$COVARIANCE
ADVAN/TRANS 与 Maspectra 的对照表为:
ADVAN 与 TRANS 编号 |
Maspectra 模型类名与方法 |
---|---|
ADVAN1 TRANS1 |
|
ADVAN1 TRANS2 |
|
ADVAN2 TRANS1 |
|
ADVAN2 TRANS2 |
|
ADVAN3 TRANS1 |
|
ADVAN3 TRANS3 |
|
ADVAN3 TRANS4 |
|
ADVAN3 TRANS5 |
|
ADVAN3 TRANS6 |
|
ADVAN4 TRANS1 |
|
ADVAN4 TRANS3 |
|
ADVAN4 TRANS4 |
|
ADVAN4 TRANS5 |
|
ADVAN4 TRANS6 |
微分方程模型#
我们也可以基于该模型各房室药量 (Amount) 的微分方程
\[\begin{split}
\begin{align*}
\frac{dA_{depot}}{dt} &= -k_a \cdot A_{depot} \\
\frac{dA_{central}}{dt} &= k_a \cdot A_{depot} - k \cdot A_{central}
\end{align*}
\end{split}\]
定义相同的模型:
from mas.model import *
class Warfarin(OdeModule):
def __init__(self) -> None:
# 设置 ODE 算法
# DVERK 算法对应 ADVAN6, LSODA 算法对应 ADVAN13 ,
super().__init__(solver=odeint.DVERK(tol=1e-3))
# 定义模型房室
self.depot_cmt = compartment(default_dose=True)
self.central_cmt = compartment(default_obs=True)
# 定义 theta 参数及初值
self.pop_v = theta(7.81, bounds=(0, None))
self.pop_cl = theta(0.134, bounds=(0, None))
self.pop_ka = theta(0.571, bounds=(0, None))
self.pop_alag = theta(0.823, bounds=(0, None))
# 定义 eta/omega 参数及 omega 的方差初值
self.eta_v = omega(0.049)
self.eta_cl = omega(0.0802)
self.eta_ka = omega(0.47)
self.eta_alag = omega(0.156)
# 定义 epsilon/sigma 参数及 sigma 的方差初值
self.eps_prop = sigma(0.0104)
self.eps_add = sigma(0.554)
def pred(self) -> Expression:
cl = self.pop_cl * exp(self.eta_cl)
v = self.pop_v * exp(self.eta_v)
ka = self.pop_ka * exp(self.eta_ka)
k = cl / v
# 设置 depot 房室的吸收延迟参数
alag1 = self.pop_alag * exp(self.eta_alag)
self.depot_cmt.alag = alag1
# 定义微分方差
self.depot_cmt.dAdt = -ka * self.depot_cmt.A
self.central_cmt.dAdt = ka * self.depot_cmt.A - k * self.central_cmt.A
ipred = self.central_cmt.A / v
y = ipred * (1 + self.eps_prop) + self.eps_add
return y
model = PopModel(mod=Warfarin, data=warfarin)
fit_res = model.fit(FOCEi(maxiter=9999, print=10), cov=True)
fit_res.summary()
$PROBLEM Warfarin PK Model
$DATA warfarin.csv IGNORE=#
$INPUT ID TIME AMT DV DVID MDV WT AGE SEX
$SUBROUTINES ADVAN6 TRANS1 TOL=3
$MODEL COMP(dose_cmt, DEFDOSE) COMP(central_cmt, DEFOBS)
$PK
V = THETA(1) * EXP(ETA(1))
CL = THETA(2) * EXP(ETA(2))
KA = THETA(3) * EXP(ETA(3))
ALAG1 = THETA(4) * EXP(ETA(4))
K = CL / V
$DES
DADT(1) = -KA * A(1)
DADT(2) = KA * A(1) - K * A(2)
$ERROR
IPRED = A(2) / V
Y = IPRED * (1 + EPS(1)) + EPS(2)
$THETA
(0.0, 7.81, 1000000.0) ; pop_v
(0.0, 0.134, 1000000.0) ; pop_cl
(0.0, 0.571, 1000000.0) ; pop_ka
(0.0, 0.823, 1000000.0) ; pop_alag
$OMEGA 0.049
$OMEGA 0.0802
$OMEGA 0.47
$OMEGA 0.156
$SIGMA 0.0104
$SIGMA 0.554
$ESTIMATION METHOD=COND INTER MAXEVAL=9999 PRINT=10
$COVARIANCE