tests/testthat/test-monolix-read.R

.nlmixr <- .nlmixr2 <- function(...) suppressWarnings(suppressMessages(nlmixr2::nlmixr(...)))

pk.turnover.emax3 <- function() {
  ini({
    tktr <- log(1)
    tka <- log(1)
    tcl <- log(0.1)
    tv <- log(10)
    ##
    eta.ktr ~ 1
    eta.ka ~ 1
    eta.cl ~ 2
    eta.v ~ 1
    prop.err <- 0.1
    pkadd.err <- 0.1
    ##
    temax <- logit(0.8)
    tec50 <- log(0.5)
    tkout <- log(0.05)
    te0 <- log(100)
    ##
    eta.emax ~ .5
    eta.ec50  ~ .5
    eta.kout ~ .5
    eta.e0 ~ .5
    ##
    pdadd.err <- 10
  })
  model({
    ktr <- exp(tktr + eta.ktr)
    ka <- exp(tka + eta.ka)
    cl <- exp(tcl + eta.cl)
    v <- exp(tv + eta.v)
    emax = expit(temax+eta.emax)
    ec50 =  exp(tec50 + eta.ec50)
    kout = exp(tkout + eta.kout)
    e0 = exp(te0 + eta.e0)
    ##
    DCP = center/v
    PD=1-emax*DCP/(ec50+DCP)
    ##
    effect(0) = e0
    kin = e0*kout
    ##
    d/dt(depot) = -ktr * depot
    d/dt(gut) =  ktr * depot -ka * gut
    d/dt(center) =  ka * gut - cl / v * center
    d/dt(effect) = kin*PD -kout*effect
    ##
    cp = center / v
    cp ~ prop(prop.err) + add(pkadd.err)
    effect ~ add(pdadd.err) | pca
  })
}

test_that("test monolix reading for 2019, 2020, and 2021", {
  
  if (file.exists(test_path("pk.turnover.emax3-2019.zip"))) {
    .path <- normalizePath(test_path("pk.turnover.emax3-2019.zip"))
    withr::with_tempdir({
      unzip(.path)
      f <- .nlmixr(pk.turnover.emax3, nlmixr2data::warfarin, "monolix",
                           control=monolixControl(modelName="pk.turnover.emax3"))
      expect_true(inherits(f, "nlmixr2FitData"))
    })
  }

  if (file.exists("pk.turnover.emax3-2020.zip")) {
    .path <- normalizePath(test_path("pk.turnover.emax3-2020.zip"))
    withr::with_tempdir({
      unzip(.path)
      f <- .nlmixr(pk.turnover.emax3, nlmixr2data::warfarin, "monolix",
                           control=monolixControl(modelName="pk.turnover.emax3"))
      expect_true(inherits(f, "nlmixr2FitData"))
    })
  }

  if (file.exists("pk.turnover.emax3-2021.zip")) {
    .path <- normalizePath(test_path("pk.turnover.emax3-2021.zip"))
    withr::with_tempdir({
      unzip(.path)
      f <- .nlmixr(pk.turnover.emax3, nlmixr2data::warfarin, "monolix",
                           control=monolixControl(modelName="pk.turnover.emax3"))
      expect_true(inherits(f, "nlmixr2FitData"))
    })
  }
  
})


test_that("test more nlmixr2/monolix features", {

  pk.turnover.emax4 <- function() {
    ini({
      tktr <- log(1)
      tka <- log(1)
      tcl <- log(0.1)
      tv <- log(10)
      ##
      eta.ktr ~ 1
      eta.ka ~ 1
      eta.cl ~ 2
      eta.v ~ 1
      prop.err <- 0.1
      pkadd.err <- 0.1
      ##
      temax <- logit(0.8)
      tec50 <- log(0.5)
      tkout <- log(0.05)
      te0 <- log(100)
      ##
      eta.emax + eta.ec50 ~ c(.5,
                              0.05, .5)
      eta.kout ~ .5
      eta.e0 ~ .5
      ##
      pdadd.err <- 10
    })
    model({
      ktr <- exp(tktr + eta.ktr)
      ka <- exp(tka + eta.ka)
      cl <- exp(tcl + eta.cl)
      v <- exp(tv + eta.v)
      emax = expit(temax+eta.emax)
      ec50 =  exp(tec50 + eta.ec50)
      kout = exp(tkout + eta.kout)
      e0 = exp(te0 + eta.e0)
      ##
      DCP = center/v
      PD=1-emax*DCP/(ec50+DCP)
      ##
      effect(0) = e0
      kin = e0*kout
      ##
      d/dt(depot) = -ktr * depot
      d/dt(gut) =  ktr * depot -ka * gut
      d/dt(center) =  ka * gut - cl / v * center
      d/dt(effect) = kin*PD -kout*effect
      ##
      cp = center / v
      cp ~ prop(prop.err) + add(pkadd.err)
      effect ~ add(pdadd.err) | pca
    })
  }


  skip_if_not(file.exists(test_path("pk.turnover.emax4-2021.zip")))
  .path <- normalizePath(test_path("pk.turnover.emax4-2021.zip"))
  withr::with_tempdir({
    unzip(.path)
    f <- .nlmixr(pk.turnover.emax4, nlmixr2data::warfarin, "monolix",
                         control=monolixControl(modelName="pk.turnover.emax4"))
    expect_true(inherits(f, "nlmixr2FitData"))
  })
  
})

test_that("test Monolix pheno", {

  pheno <- function() {
    ini({
      tcl <- log(0.008) # typical value of clearance
      tv <-  log(0.6)   # typical value of volume
      ## var(eta.cl)
      eta.cl + eta.v ~ c(1,
                         0.01, 1) ## cov(eta.cl, eta.v), var(eta.v)
      # interindividual variability on clearance and volume
      add.err <- 0.1    # residual variability
    })
    model({
      cl <- exp(tcl + eta.cl) # individual value of clearance
      v <- exp(tv + eta.v)    # individual value of volume
      ke <- cl / v            # elimination rate constant
      d/dt(A1) = - ke * A1    # model differential equation
      cp = A1 / v             # concentration in plasma
      cp ~ add(add.err)       # define error model
    })
  }

  skip_if_not(file.exists(test_path("pheno-2021.zip")))
  .path <- normalizePath(test_path("pheno-2021.zip"))
  withr::with_tempdir({
    unzip(.path)
    f <- .nlmixr(pheno, nlmixr2data::pheno_sd, "monolix",
                         control=monolixControl(modelName="pheno"))
    expect_true(inherits(f, "nlmixr2FitData"))
  })
  
})

test_that("pbpk mavoglurant", {

  pbpk <- function(){
    ini({
      ##theta=exp(c(1.1, .3, 2, 7.6, .003, .3))
      lKbBR = 1.1
      lKbMU = 0.3
      lKbAD = 2

      lCLint = 7.6
      lKbBO = 0.03
      lKbRB = 0.3
      eta.LClint ~ 4
      lnorm.sd <- 1
    })
    model({
      KbBR = exp(lKbBR)
      KbMU = exp(lKbMU)
      KbAD = exp(lKbAD)
      CLint= exp(lCLint + eta.LClint)
      KbBO = exp(lKbBO)
      KbRB = exp(lKbRB)

      ## Regional blood flows
      CO  = (187.00*WT^0.81)*60/1000;         # Cardiac output (L/h) from White et al (1968)
      QHT = 4.0 *CO/100;
      QBR = 12.0*CO/100;
      QMU = 17.0*CO/100;
      QAD = 5.0 *CO/100;
      QSK = 5.0 *CO/100;
      QSP = 3.0 *CO/100;
      QPA = 1.0 *CO/100;
      QLI = 25.5*CO/100;
      QST = 1.0 *CO/100;
      QGU = 14.0*CO/100;
      QHA = QLI - (QSP + QPA + QST + QGU); # Hepatic artery blood flow
      QBO = 5.0 *CO/100;
      QKI = 19.0*CO/100;
      QRB = CO - (QHT + QBR + QMU + QAD + QSK + QLI + QBO + QKI);
      QLU = QHT + QBR + QMU + QAD + QSK + QLI + QBO + QKI + QRB;

      ## Organs' volumes = organs' weights / organs' density
      VLU = (0.76 *WT/100)/1.051;
      VHT = (0.47 *WT/100)/1.030;
      VBR = (2.00 *WT/100)/1.036;
      VMU = (40.00*WT/100)/1.041;
      VAD = (21.42*WT/100)/0.916;
      VSK = (3.71 *WT/100)/1.116;
      VSP = (0.26 *WT/100)/1.054;
      VPA = (0.14 *WT/100)/1.045;
      VLI = (2.57 *WT/100)/1.040;
      VST = (0.21 *WT/100)/1.050;
      VGU = (1.44 *WT/100)/1.043;
      VBO = (14.29*WT/100)/1.990;
      VKI = (0.44 *WT/100)/1.050;
      VAB = (2.81 *WT/100)/1.040;
      VVB = (5.62 *WT/100)/1.040;
      VRB = (3.86 *WT/100)/1.040;

      ## Fixed parameters
      BP = 0.61;      # Blood:plasma partition coefficient
      fup = 0.028;    # Fraction unbound in plasma
      fub = fup/BP;   # Fraction unbound in blood

      KbLU = exp(0.8334);
      KbHT = exp(1.1205);
      KbSK = exp(-.5238);
      KbSP = exp(0.3224);
      KbPA = exp(0.3224);
      KbLI = exp(1.7604);
      KbST = exp(0.3224);
      KbGU = exp(1.2026);
      KbKI = exp(1.3171);


      ##-----------------------------------------
      S15 = VVB*BP/1000;
      C15 = Venous_Blood/S15

      ##-----------------------------------------
      d/dt(Lungs) = QLU*(Venous_Blood/VVB - Lungs/KbLU/VLU);
      d/dt(Heart) = QHT*(Arterial_Blood/VAB - Heart/KbHT/VHT);
      d/dt(Brain) = QBR*(Arterial_Blood/VAB - Brain/KbBR/VBR);
      d/dt(Muscles) = QMU*(Arterial_Blood/VAB - Muscles/KbMU/VMU);
      d/dt(Adipose) = QAD*(Arterial_Blood/VAB - Adipose/KbAD/VAD);
      d/dt(Skin) = QSK*(Arterial_Blood/VAB - Skin/KbSK/VSK);
      d/dt(Spleen) = QSP*(Arterial_Blood/VAB - Spleen/KbSP/VSP);
      d/dt(Pancreas) = QPA*(Arterial_Blood/VAB - Pancreas/KbPA/VPA);
      d/dt(Liver) = QHA*Arterial_Blood/VAB + QSP*Spleen/KbSP/VSP + QPA*Pancreas/KbPA/VPA + QST*Stomach/KbST/VST + QGU*Gut/KbGU/VGU - CLint*fub*Liver/KbLI/VLI - QLI*Liver/KbLI/VLI;
      d/dt(Stomach) = QST*(Arterial_Blood/VAB - Stomach/KbST/VST);
      d/dt(Gut) = QGU*(Arterial_Blood/VAB - Gut/KbGU/VGU);
      d/dt(Bones) = QBO*(Arterial_Blood/VAB - Bones/KbBO/VBO);
      d/dt(Kidneys) = QKI*(Arterial_Blood/VAB - Kidneys/KbKI/VKI);
      d/dt(Arterial_Blood) = QLU*(Lungs/KbLU/VLU - Arterial_Blood/VAB);
      d/dt(Venous_Blood) = QHT*Heart/KbHT/VHT + QBR*Brain/KbBR/VBR + QMU*Muscles/KbMU/VMU + QAD*Adipose/KbAD/VAD + QSK*Skin/KbSK/VSK + QLI*Liver/KbLI/VLI + QBO*Bones/KbBO/VBO + QKI*Kidneys/KbKI/VKI + QRB*Rest_of_Body/KbRB/VRB - QLU*Venous_Blood/VVB;
      d/dt(Rest_of_Body) = QRB*(Arterial_Blood/VAB - Rest_of_Body/KbRB/VRB);

      C15 ~ lnorm(lnorm.sd)
    })
  }

  expect_error(bblDatToMonolix(pbpk, nlmixr2data::mavoglurant), NA)

  skip_if_not(file.exists(test_path("pbpk-2021.zip")))
  .path <- normalizePath(test_path("pbpk-2021.zip"))
  withr::with_tempdir({
    unzip(.path)
    f <- .nlmixr(pbpk, nlmixr2data::mavoglurant, "monolix",
                         control=monolixControl(modelName="pbpk"))
    expect_true(inherits(f, "nlmixr2FitData"))
  })
  
})

test_that("nimo test", {
  
  nimo <- function() {
    ini({
      ## Note that the UI can take expressions
      ## Also note that these initial estimates should be provided on the log-scale
      tcl <- log(0.001)
      tv1 <- log(1.45)
      tQ <- log(0.004)
      tv2 <- log(44)
      tkss <- log(12)
      tkint <- log(0.3)
      tksyn <- log(1)
      tkdeg <- log(7)
      ## Initial estimates should be high for SAEM ETAs
      eta.cl  ~ 2
      eta.v1  ~ 2
      eta.kss ~ 2
      ##  Also true for additive error (also ignored in SAEM)
      lnorm.sd <- 10
    })
    model({
      cl <- exp(tcl + eta.cl)
      v1 <- exp(tv1 + eta.v1)
      Q  <- exp(tQ)
      v2 <- exp(tv2)
      kss <- exp(tkss + eta.kss)
      kint <- exp(tkint)
      ksyn <- exp(tksyn)
      kdeg <- exp(tkdeg)

      k <- cl/v1
      k12 <- Q/v1
      k21 <- Q/v2

      eff(0) <- ksyn/kdeg ##initializing compartment

      ## Concentration is calculated
      conc = 0.5*(central/v1-eff-kss)+0.5*sqrt((central/v1-eff-kss)**2+4*kss*central/v1)

      d/dt(central)  = -(k+k12)*conc*v1+k21*peripheral-kint*eff*conc*v1/(kss+conc)
      d/dt(peripheral) = k12*conc*v1-k21*peripheral  ##Free Drug second compartment amount
      d/dt(eff) = ksyn - kdeg*eff - (kint-kdeg)*conc*eff/(kss+conc)

      conc ~ lnorm(lnorm.sd)

    })
  }

  tmp <- nlmixr2data::nimoData

  tmp$DV <-exp(tmp$DV)

  skip_if_not(file.exists(test_path("nimo-2021.zip")))
  .path <- normalizePath(test_path("nimo-2021.zip"))
  withr::with_tempdir({
    unzip(.path)
    f <- suppressWarnings(.nlmixr2(nimo, tmp, "monolix",
                                           control=monolixControl(modelName="nimo")))
    expect_true(inherits(f, "nlmixr2FitData"))
  })
  
})

# WBC Model tests ####

wbc <- function() {
  ini({
    ## Note that the UI can take expressions
    ## Also note that these initial estimates should be provided on the log-scale
    log_CIRC0 <- log(7.21)
    log_MTT <- log(124)
    log_SLOPU <- log(28.9)
    log_GAMMA <- log(0.239)
    ## Initial estimates should be high for SAEM ETAs
    eta.CIRC0  ~ .1
    eta.MTT  ~ .03
    eta.SLOPU ~ .2
    ##  Also true for additive error (also ignored in SAEM)
    prop.err <- 10
  })
  model({
    CIRC0 =  exp(log_CIRC0 + eta.CIRC0)
    MTT =  exp(log_MTT + eta.MTT)
    SLOPU =  exp(log_SLOPU + eta.SLOPU)
    GAMMA = exp(log_GAMMA)
    
    # PK parameters from input dataset
    CL = CLI;
    V1 = V1I;
    V2 = V2I;
    Q = 204;
    
    CONC = A_centr/V1;
    
    # PD parameters
    NN = 3;
    KTR = (NN + 1)/MTT;
    EDRUG = 1 - SLOPU * CONC;
    FDBK = (CIRC0 / A_circ)^GAMMA;
    
    CIRC = A_circ;
    
    A_prol(0) = CIRC0;
    A_tr1(0) = CIRC0;
    A_tr2(0) = CIRC0;
    A_tr3(0) = CIRC0;
    A_circ(0) = CIRC0;
    
    d/dt(A_centr) = A_periph * Q/V2 - A_centr * (CL/V1 + Q/V1);
    d/dt(A_periph) = A_centr * Q/V1 - A_periph * Q/V2;
    d/dt(A_prol) = KTR * A_prol * EDRUG * FDBK - KTR * A_prol;
    d/dt(A_tr1) = KTR * A_prol - KTR * A_tr1;
    d/dt(A_tr2) = KTR * A_tr1 - KTR * A_tr2;
    d/dt(A_tr3) = KTR * A_tr2 - KTR * A_tr3;
    d/dt(A_circ) = KTR * A_tr3 - KTR * A_circ;
    
    CIRC ~ prop(prop.err)
  })
}

test_that("Monolix wbc", {
  skip_if_not(file.exists(test_path("wbc-2021.zip")))
  skip_if_not(file.exists(test_path("wbc-charts-2021.zip")))
  .path <- normalizePath(test_path("wbc-2021.zip"))
  .pathCharts <- normalizePath(test_path("wbc-charts-2021.zip"))
  withr::with_tempdir({
    unzip(.path)
    
    f <- suppressWarnings(.nlmixr2(wbc, nlmixr2data::wbcSim, "monolix",
                                           control=monolixControl(modelName="wbc")))
    expect_true(inherits(f, "nlmixr2FitData"))
    expect_equal(f$env$parHistData, NULL)
    
    unzip(.pathCharts)
    
    f <- suppressWarnings(.nlmixr2(wbc, nlmixr2data::wbcSim, "monolix",
                                           control=monolixControl(modelName="wbc")))
    expect_true(inherits(f, "nlmixr2FitData"))
    expect_true(inherits(f$env$parHistData, "data.frame"))
    
    f <- suppressWarnings(.nlmixr2(wbc, nlmixr2data::wbcSim, "monolix", 
                                           control=monolixControl(modelName="wbc")))
    expect_true(inherits(f, "nlmixr2FitData"))
    expect_true(inherits(f$env$parHistData, "data.frame"))
    
  })
  
  withr::with_tempdir({
    unzip(.path)
    unzip(.pathCharts)
    f <- suppressWarnings(.nlmixr2(wbc, nlmixr2data::wbcSim, "monolix",
                                           control=monolixControl(modelName="wbc")))
    expect_true(inherits(f, "nlmixr2FitData"))
    expect_true(inherits(f$env$parHistData, "data.frame"))
  })
})

test_that("Monolix wbc test 2", {
  skip_if_not(file.exists(test_path("x-2021.zip")))
  .path <- normalizePath(test_path("x-2021.zip"))
  withr::with_tempdir({
    unzip(.path)
    # with piping, the original model name is scrubbed, and is changed to x
    p1 <- wbc %>%
      ini(prop.err=15) %>%
      .nlmixr2(., nlmixr2data::wbcSim, "monolix",
              control=monolixControl(modelName="x"))
    
    expect_true(inherits(p1, "nlmixr2FitData"))
    
    p2 <-wbc %>%
      ini(prop.err=7) %>%
      .nlmixr2(., nlmixr2data::wbcSim, "monolix",
              control=monolixControl(modelName="x"))
    
    expect_true(inherits(p2, "nlmixr2FitData"))

    expect_true(length(p2$parHistData[,1]) > 0)
  })
})
nlmixr2/babelmixr documentation built on Oct. 27, 2024, 4:24 a.m.