nlmixrdevelopment / nlmixr

nlmixr: an R package for population PKPD modeling
https://nlmixrdevelopment.github.io/nlmixr/
GNU General Public License v2.0
114 stars 45 forks source link

Tumour growth model: SAEM requires all ETAS to be mu-referenced #600

Closed andreasmeid closed 1 year ago

andreasmeid commented 2 years ago

Hi,

I just tried to reproduce a ddmore-NONMEM analysis with nlmixr (data and NONMEM code are available from http://repository.ddmore.eu/model/DDMODEL00000217). However, I receive the error message "SAEM requires all ETAS to be mu-referenced" which I do not understand (as all etas appear to be defined correctly). Can you figure our what is wrong (with the model formula or data specification)?

Many thanks and best wishes Andreas

library(tidyverse) TS <- read.table("Simulated SLD.csv", header=T, sep=",") %>% select(-CCOM)

TS2 <- TS %>% group_by(ID) %>% mutate(BQL_IND = case_when(any(BQL == 1) ~ 1, all(BQL != 1) ~ 0)) %>% filter(BQL_IND != 1) %>% select(ID, TIME, DV, AUC0, AUC1, EVID, FLAG, CMT, ECOG) %>% mutate(dvid = case_when(EVID == 0 ~ "cp", EVID != 0 ~ "other")) %>% rename(cmt=CMT, dv=DV, id=ID) %>% mutate(dv=as.numeric(dv), cmt=as.numeric(cmt)) %>% filter(dvid=="cp") # simplifications for first run (e.g., remove subjects with values below LLOQ)

library(nlmixr)

myModel <- function() { # Claret-like model for describing CTS. ini({ tKG <- log(0.3) tKD0 <- log(0.03) tKD1 <- log(0.01) tIBASE <- log(0.01) eta.KG <- 0.08 eta.KD <- 0.1 eta.IBASE <- 0.1 add.err <- 20 # SD of additive unexpained variability, SD of additive error (mm) }) model({ KG = exp(tKG + eta.KG) # tumour growth rate constant (1/day) KD0 = exp(tKD0 + eta.KD) # carboplatin related death rate constant (1/day/AUC0) KD1 = exp(tKD1 + eta.KD) # gemcitabine related death rate constant (1/day/AUC1) IBASE = exp(tIBASE + eta.IBASE) # baseline SLD (m) E0 = AUC0 E1 = AUC1 A(0) = IBASE1000 # SLD baseline d/dt(A) = KG/1000 A - (KD0/1000 E0 + KD1/100 E1) * A # Model for dSLD(t) cp = A cp ~ add(add.err) }) }

fit.myModel <- nlmixr(myModel,TS2,est="saem",control=saemControl(n.burn=50,n.em=100,print=50));

mattfidler commented 2 years ago

Hi @andreasmeid

I am unclear what is wrong here. Could you provide some sample dataset so I can try to reproduce what you are experiencing?

In the new nlmixr2 mu referencing is no longer needed, so this may not be taken care of on this repository.

andreasmeid commented 2 years ago

To be honest, I only saw it now, the random effects were assigned with the wrong symbol ("<-" instead of "~"). With the correct notation the model runs. Maybe it could be pointed out more explicitly, obviously I didn't recognize it in the tutorials.

The data is available for download as csv-file on the ddmore repository (see link above). There are also the original NONMEM files. In the NONMEM code there is, among other things, also the NONMEM-specific assignment IF(NEWIND.NE.2) OCB=CB. This I have now picked up in advance in the R data management, hopefully correct. If something like this doesn't exist yet, could some kind of dictionary between NONMEM code and nlmixr code be thought of for the future?

But for now the issue seems to be solved, thanks a lot

mattfidler commented 2 years ago

In theory the newind flag exists

mattfidler commented 2 years ago

The meaning may be slightly different. Details about functions and variables like newind are here:

https://nlmixrdevelopment.github.io/RxODE/articles/RxODE-syntax.html

andreasmeid commented 2 years ago

Thank you very much for the link to the ODE syntx. This was indeed very helpful. When I tackle the second part of the tumor growth model (http://repository.ddmore.foundation/model/DDMODEL00000218#Files), I get an error message that is hard to interpret: "Error in RxODE::rxState(rxode) : Evaluation error: syntax errors (see above)." I have no idea which syntax error might be meant here.

OS <- read.table(here("data/Simulated_OS.csv"), header=T, sep=",")

OS2 <- OS %>% group_by(ID) %>% mutate(group_IND = case_when(any(AUC1 > 0) ~ "CB + G",    # and group
                                                           all(AUC1 == 0) ~ "CB")) %>%
  rename(NWLS=NWLSCOV) %>% select(-CCOM) %>%
  mutate(dvid = case_when(EVID == 0 ~ "Y",                                              # indicator for dependent var (dv)
                          EVID != 0 ~ "other")) %>% rename(dv=DV, id=ID) %>% 
  mutate(dvid=as.factor(dvid)) %>%               # adjust variable types
  mutate(AUC0 = case_when(TIME == 0 ~ lead(AUC0),                                        # assign first value to baseline
                          TIME != 0 ~ AUC0),                                             
         AUC1 = case_when(TIME == 0 ~ lead(AUC1),                                        
                          TIME != 0 ~ AUC1),
         NWLS = case_when(TIME == 0 ~ lead(NWLS),                                        
                          TIME != 0 ~ NWLS)) 

myModel_OS <- function(){           # TTE model for OS. Weibull baseline hazard. 
  ini({

    tLAM <- log(0.001)               # scale parameter
    tSHP <- log(2)                   # shape parameter
    tBSLD0 <- log(0.1)               # parameter for SLD (sum of longest diameter) at enrolment
    tBTSR <- log(0.1)                # parameter for TSR(t) (tumour size ratio)
    tBNWLS <- log(0.1)               # parameter for NewLesion(t)
    tBECOG <- log(0.1)               # parameter for ECOG at enrolment
    eta.LAM ~ 0.01                   # inter-individual variability in scale parameter
    add.err <- 0

  })
  model({

    LAM = exp(tLAM + eta.LAM)           
    SHP = exp(tSHP)
    BSLD0 = exp(tBSLD0)
    BTSR = exp(tBTSR)
    BNWLS = exp(tBNWLS)
    BECOG = exp(tBECOG)

    #Time constant covariates
      TVSLD0 = 70                      # average SLD at enrolment
      NSLD0 = SLD0/TVSLD0              # normalised SLD at enrolment
      IECOG=ECOG                       # ECOG at enrolment

    # Model for dSLD(t)
      A(0) = IBASE*1000                # SLD baseline 
      MMBAS = IBASE*1000               # Parameter of the SLD(t) model were estimated previously (IPP approach)
      d/dt(A) = KG/1000 * A - (KD0/1000 * AUC0 + + KD1/100 * AUC1) * A
      TUM = A
      TSR = (TUM-MMBAS)/MMBAS

      if(time==0){                     #TSR(t) for t<= week 12 and TSR(week12) for t> week 12
        WTS = 0
        TM12 = 0
      } 
      if(time<=84){   
        WTS = TSR
        TM12 = WTS     
      } 
      else {
        WTS = WTS
      }

    # survival model
      DEL = 1E-6
      d/dt(A2) = LAM*SHP*(LAM*(T+DEL))**(SHP-1) *EXP(BSLD0*NSLD0+BTSR*WTS+BNWLS*NWLS+BECOG*IECOG)

    # Death hazard 
      CHZ = A2
      SUR=EXP(-CHZ)
      DELX = 1E-6
      xTUM = A
      xTSR = (xTUM-MMBAS)/MMBAS
      if(time==0){   
            XWTS=0
            XTM12=0
      } 

      if(time<=84){   
          XWTS = XTSR
          XTM12 = XWTS     
      } 
      else {
          XWTS=XWTS
      }

      HAZN = LAM*SHP*(LAM*(TIME+DELx))**(SHP-1)*EXP(BSLD0*NSLD0+BTSR*XWTS+BNWLS*NWLS+BECOG*IECOG)
    # prediction
      if(FLAG == 9 & EVID == 0 & OSCENS == 1){
        IPRED=SUR                      # probability of survival (censored event)
        Y = IPRED                      # Y is probability for TTE data
        Y ~ add(add.err)  
      }
      if(FLAG == 9 & EVID == 0 & OSCENS == 0){
        IPRED=SUR*HAZN                # probability of event (death) at time=TIME
        Y = IPRED                     # Y is probability for TTE data
        Y ~ add(add.err)
      }

  })

}

fit.OSModel <- nlmixr(myModel_OS,OS2,est="saem",control=saemControl(n.burn=50,n.em=100,print=50),
                      RxODE.syntax.assign.state = TRUE);

What could be the reason for this or where could one specifically look in the code?

mattfidler commented 2 years ago

The current version of nlmixr stores the errors, but not the messages; put a rxClean() at the beginning should see the errors:

myModel_OS <- function(){           # TTE model for OS. Weibull baseline hazard. 
  ini({

    tLAM <- log(0.001)               # scale parameter
    tSHP <- log(2)                   # shape parameter
    tBSLD0 <- log(0.1)               # parameter for SLD (sum of longest diameter) at enrolment
    tBTSR <- log(0.1)                # parameter for TSR(t) (tumour size ratio)
    tBNWLS <- log(0.1)               # parameter for NewLesion(t)
    tBECOG <- log(0.1)               # parameter for ECOG at enrolment
    eta.LAM ~ 0.01                   # inter-individual variability in scale parameter
    add.err <- 0

  })
  model({

    LAM = exp(tLAM + eta.LAM)           
    SHP = exp(tSHP)
    BSLD0 = exp(tBSLD0)
    BTSR = exp(tBTSR)
    BNWLS = exp(tBNWLS)
    BECOG = exp(tBECOG)

    #Time constant covariates
    TVSLD0 = 70                      # average SLD at enrolment
    NSLD0 = SLD0/TVSLD0              # normalised SLD at enrolment
    IECOG=ECOG                       # ECOG at enrolment

    # Model for dSLD(t)
    A(0) = IBASE*1000                # SLD baseline 
    MMBAS = IBASE*1000               # Parameter of the SLD(t) model were estimated previously (IPP approach)
    d/dt(A) = KG/1000 * A - (KD0/1000 * AUC0 + + KD1/100 * AUC1) * A
    TUM = A
    TSR = (TUM-MMBAS)/MMBAS

    if(time==0){                     #TSR(t) for t<= week 12 and TSR(week12) for t> week 12
      WTS = 0
      TM12 = 0
    } 
    if(time<=84){   
      WTS = TSR
      TM12 = WTS     
    } 
    else {
      WTS = WTS
    }

    # survival model
    DEL = 1E-6
    d/dt(A2) = LAM*SHP*(LAM*(T+DEL))**(SHP-1) *EXP(BSLD0*NSLD0+BTSR*WTS+BNWLS*NWLS+BECOG*IECOG)

    # Death hazard 
    CHZ = A2
    SUR=EXP(-CHZ)
    DELX = 1E-6
    xTUM = A
    xTSR = (xTUM-MMBAS)/MMBAS
    if(time==0){   
      XWTS=0
      XTM12=0
    } 

    if(time<=84){   
      XWTS = XTSR
      XTM12 = XWTS     
    } 
    else {
      XWTS=XWTS
    }

    HAZN = LAM*SHP*(LAM*(TIME+DELx))**(SHP-1)*EXP(BSLD0*NSLD0+BTSR*XWTS+BNWLS*NWLS+BECOG*IECOG)
    # prediction
    if(FLAG == 9 & EVID == 0 & OSCENS == 1){
      IPRED=SUR                      # probability of survival (censored event)
      Y = IPRED                      # Y is probability for TTE data
      Y ~ add(add.err)  
    }
    if(FLAG == 9 & EVID == 0 & OSCENS == 0){
      IPRED=SUR*HAZN                # probability of event (death) at time=TIME
      Y = IPRED                     # Y is probability for TTE data
      Y ~ add(add.err)
    }

  })

}

library(nlmixr)
rxClean()

nlmixr(myModel_OS)
#> i parameter labels from comments will be replaced by 'label()'
#> RxODE model syntax error:
#> ================================================================================
#> :001:     TVSLD0 = 70
#> :002:     NSLD0 = SLD0/TVSLD0
#> :003:     IECOG = ECOG
#> :004:     A(0) = IBASE * 1000
#> :005:     MMBAS = IBASE * 1000
#> :006:     d/dt(A) = KG/1000 * A - (KD0/1000 * AUC0 + +KD1/100 * AUC1) * A
#> :007:     TUM = A
#> :008:     TSR = (TUM - MMBAS)/MMBAS
#> :009:     if (time == 0) {
#> :010:         WTS = 0
#> :011:         TM12 = 0
#> :012:     }
#> :013:     if (time <= 84) {
#> :014:         WTS = TSR
#> :015:         TM12 = WTS
#> :016:     }
#> :017:     else {
#> :018:         WTS = WTS
#> :019:     }
#> :020:     DEL = 1e-06
#> :021: function 'EXP' is not supported in RxODE:
#>           d/dt(A2) = LAM * SHP * (LAM * (T + DEL))^(SHP - 1) * EXP(BSLD0 * NSLD0 + BTSR * WTS + BNWLS * NWLS + BECOG * IECOG)
#>                                                                ^~~
#> :021:     d/dt(A2) = LAM * SHP * (LAM * (T + DEL))^(SHP - 1) * EXP(BSLD0 * NSLD0 + BTSR * WTS + BNWLS * NWLS + BECOG * IECOG)
#> :022:     CHZ = A2
#> :023: function 'EXP' is not supported in RxODE:
#>           SUR = EXP(-CHZ)
#>                 ^~~
#> :023:     SUR = EXP(-CHZ)
#> :024:     DELX = 1e-06
#> :025:     xTUM = A
#> :026:     xTSR = (xTUM - MMBAS)/MMBAS
#> :027:     if (time == 0) {
#> :028:         XWTS = 0
#> :029:         XTM12 = 0
#> :030:     }
#> :031:     if (time <= 84) {
#> :032:         XWTS = XTSR
#> :033:         XTM12 = XWTS
#> :034:     }
#> :035:     else {
#> :036:         XWTS = XWTS
#> :037:     }
#> :038: function 'EXP' is not supported in RxODE:
#>           HAZN = LAM * SHP * (LAM * (TIME + DELx))^(SHP - 1) * EXP(BSLD0 * NSLD0 + BTSR * XWTS + BNWLS * NWLS + BECOG * IECOG)
#>                                                                ^~~
#> :038:     if (FLAG == 9 & EVID == 0 & OSCENS == 1) {
#> :039:         IPRED = SUR
#> :040:         Y = IPRED
#> :041:     }
#> :042:     if (FLAG == 9 & EVID == 0 & OSCENS == 0) {
#> :043:         IPRED = SUR * HAZN
#> :044:         Y = IPRED
#> :045:     }
#> ================================================================================
#> RxODE model syntax error:
#> ================================================================================
#> :001:     TVSLD0 = 70
#> :002:     NSLD0 = SLD0/TVSLD0
#> :003:     IECOG = ECOG
#> :004:     A(0) = IBASE * 1000
#> :005:     MMBAS = IBASE * 1000
#> :006:     d/dt(A) = KG/1000 * A - (KD0/1000 * AUC0 + +KD1/100 * AUC1) * A
#> :007:     TUM = A
#> :008:     TSR = (TUM - MMBAS)/MMBAS
#> :009:     if (time == 0) {
#> :010:         WTS = 0
#> :011:         TM12 = 0
#> :012:     }
#> :013:     if (time <= 84) {
#> :014:         WTS = TSR
#> :015:         TM12 = WTS
#> :016:     }
#> :017:     else {
#> :018:         WTS = WTS
#> :019:     }
#> :020:     DEL = 1e-06
#> :021: function 'EXP' is not supported in RxODE:
#>           d/dt(A2) = LAM * SHP * (LAM * (T + DEL))^(SHP - 1) * EXP(BSLD0 * NSLD0 + BTSR * WTS + BNWLS * NWLS + BECOG * IECOG)
#>                                                                ^~~
#> :021:     d/dt(A2) = LAM * SHP * (LAM * (T + DEL))^(SHP - 1) * EXP(BSLD0 * NSLD0 + BTSR * WTS + BNWLS * NWLS + BECOG * IECOG)
#> :022:     CHZ = A2
#> :023: function 'EXP' is not supported in RxODE:
#>           SUR = EXP(-CHZ)
#>                 ^~~
#> :023:     SUR = EXP(-CHZ)
#> :024:     DELX = 1e-06
#> :025:     xTUM = A
#> :026:     xTSR = (xTUM - MMBAS)/MMBAS
#> :027:     if (time == 0) {
#> :028:         XWTS = 0
#> :029:         XTM12 = 0
#> :030:     }
#> :031:     if (time <= 84) {
#> :032:         XWTS = XTSR
#> :033:         XTM12 = XWTS
#> :034:     }
#> :035:     else {
#> :036:         XWTS = XWTS
#> :037:     }
#> :038: function 'EXP' is not supported in RxODE:
#>           HAZN = LAM * SHP * (LAM * (TIME + DELx))^(SHP - 1) * EXP(BSLD0 * NSLD0 + BTSR * XWTS + BNWLS * NWLS + BECOG * IECOG)
#>                                                                ^~~
#> :038:     if (FLAG == 9 & EVID == 0 & OSCENS == 1) {
#> :039:         IPRED = SUR
#> :040:         Y = IPRED
#> :041:     }
#> :042:     if (FLAG == 9 & EVID == 0 & OSCENS == 0) {
#> :043:         IPRED = SUR * HAZN
#> :044:         Y = IPRED
#> :045:     }
#> ================================================================================
#> Error in RxODE::rxState(rxode): Evaluation error: syntax errors (see above).

Created on 2022-03-30 by the reprex package (v2.0.1)

Session info ``` r sessioninfo::session_info() #> - Session info --------------------------------------------------------------- #> setting value #> version R version 4.1.3 (2022-03-10) #> os Windows 10 x64 (build 19042) #> system x86_64, mingw32 #> ui RTerm #> language (EN) #> collate English_United States.1252 #> ctype English_United States.1252 #> tz America/Chicago #> date 2022-03-30 #> pandoc 2.17.1.1 @ C:/R/Rstudio/bin/quarto/bin/ (via rmarkdown) #> #> - Packages ------------------------------------------------------------------- #> ! package * version date (UTC) lib source #> backports 1.4.1 2021-12-13 [1] CRAN (R 4.1.2) #> brew 1.0-7 2022-02-04 [1] CRAN (R 4.1.3) #> cachem 1.0.6 2021-08-19 [1] CRAN (R 4.1.3) #> checkmate 2.0.0 2020-02-06 [1] CRAN (R 4.1.3) #> cli 3.2.0 2022-02-14 [1] CRAN (R 4.1.3) #> colorspace 2.0-3 2022-02-21 [1] CRAN (R 4.1.3) #> crayon 1.5.0 2022-02-14 [1] CRAN (R 4.1.3) #> data.table 1.14.2 2021-09-27 [1] CRAN (R 4.1.3) #> digest 0.6.29 2021-12-01 [1] CRAN (R 4.1.3) #> dparser 1.3.1-5 2022-03-21 [1] CRAN (R 4.1.3) #> dplyr 1.0.8 2022-02-08 [1] CRAN (R 4.1.3) #> ellipsis 0.3.2 2021-04-29 [1] CRAN (R 4.1.3) #> evaluate 0.15 2022-02-18 [1] CRAN (R 4.1.3) #> fansi 1.0.2 2022-01-14 [1] CRAN (R 4.1.3) #> fastmap 1.1.0 2021-01-25 [1] CRAN (R 4.1.3) #> fs 1.5.2 2021-12-08 [1] CRAN (R 4.1.3) #> generics 0.1.2 2022-01-31 [1] CRAN (R 4.1.3) #> ggplot2 3.3.5 2021-06-25 [1] CRAN (R 4.1.3) #> glue 1.6.2 2022-02-24 [1] CRAN (R 4.1.3) #> gtable 0.3.0 2019-03-25 [1] CRAN (R 4.1.3) #> highr 0.9 2021-04-16 [1] CRAN (R 4.1.3) #> htmltools 0.5.2 2021-08-25 [1] CRAN (R 4.1.3) #> knitr 1.37 2021-12-16 [1] CRAN (R 4.1.3) #> lattice 0.20-45 2021-09-22 [1] CRAN (R 4.1.3) #> lazyeval 0.2.2 2019-03-15 [1] CRAN (R 4.1.3) #> lbfgsb3c 2020-3.2 2020-03-03 [1] CRAN (R 4.1.3) #> lifecycle 1.0.1 2021-09-24 [1] CRAN (R 4.1.3) #> lotri 0.3.1 2021-01-05 [1] CRAN (R 4.1.3) #> magrittr 2.0.2 2022-01-26 [1] CRAN (R 4.1.3) #> memoise 2.0.1 2021-11-26 [1] CRAN (R 4.1.3) #> munsell 0.5.0 2018-06-12 [1] CRAN (R 4.1.3) #> n1qn1 6.0.1-10 2020-11-17 [1] CRAN (R 4.1.3) #> nlme 3.1-155 2022-01-16 [1] CRAN (R 4.1.3) #> nlmixr * 2.0.6 2021-11-02 [1] CRAN (R 4.1.3) #> pillar 1.7.0 2022-02-01 [1] CRAN (R 4.1.3) #> pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 4.1.3) #> PreciseSums 0.4 2020-07-10 [1] CRAN (R 4.1.3) #> purrr 0.3.4 2020-04-17 [1] CRAN (R 4.1.3) #> qs 0.25.3 2022-02-22 [1] CRAN (R 4.1.3) #> R6 2.5.1 2021-08-19 [1] CRAN (R 4.1.3) #> RApiSerialize 0.1.0 2014-04-19 [1] CRAN (R 4.1.1) #> Rcpp 1.0.8.3 2022-03-17 [1] CRAN (R 4.1.3) #> D RcppParallel 5.1.5 2022-01-05 [1] CRAN (R 4.1.3) #> reprex 2.0.1 2021-08-05 [1] CRAN (R 4.1.3) #> rex 1.2.1 2021-11-26 [1] CRAN (R 4.1.3) #> rlang 1.0.2 2022-03-04 [1] CRAN (R 4.1.3) #> rmarkdown 2.13 2022-03-10 [1] CRAN (R 4.1.3) #> rstudioapi 0.13 2020-11-12 [1] CRAN (R 4.1.3) #> RxODE 1.1.5 2022-03-23 [1] CRAN (R 4.1.3) #> scales 1.1.1 2020-05-11 [1] CRAN (R 4.1.3) #> sessioninfo 1.2.2 2021-12-06 [1] CRAN (R 4.1.3) #> stringfish 0.15.5 2021-12-01 [1] CRAN (R 4.1.3) #> stringi 1.7.6 2021-11-29 [1] CRAN (R 4.1.2) #> stringr 1.4.0 2019-02-10 [1] CRAN (R 4.1.3) #> sys 3.4 2020-07-23 [1] CRAN (R 4.1.3) #> tibble 3.1.6 2021-11-07 [1] CRAN (R 4.1.3) #> tidyselect 1.1.2 2022-02-21 [1] CRAN (R 4.1.3) #> units 0.8-0 2022-02-05 [1] CRAN (R 4.1.3) #> utf8 1.2.2 2021-07-24 [1] CRAN (R 4.1.3) #> vctrs 0.3.8 2021-04-29 [1] CRAN (R 4.1.3) #> withr 2.5.0 2022-03-03 [1] CRAN (R 4.1.3) #> xfun 0.30 2022-03-02 [1] CRAN (R 4.1.3) #> yaml 2.3.5 2022-02-21 [1] CRAN (R 4.1.2) #> #> [1] C:/R/R-4.1.3/library #> #> D -- DLL MD5 mismatch, broken installation. #> #> ------------------------------------------------------------------------------ ```
mattfidler commented 2 years ago

This parses correctly:

myModel_OS <- function(){           # TTE model for OS. Weibull baseline hazard. 
  ini({

    tLAM <- log(0.001)               # scale parameter
    tSHP <- log(2)                   # shape parameter
    tBSLD0 <- log(0.1)               # parameter for SLD (sum of longest diameter) at enrolment
    tBTSR <- log(0.1)                # parameter for TSR(t) (tumour size ratio)
    tBNWLS <- log(0.1)               # parameter for NewLesion(t)
    tBECOG <- log(0.1)               # parameter for ECOG at enrolment
    eta.LAM ~ 0.01                   # inter-individual variability in scale parameter
    add.err <- 0

  })
  model({

    LAM = exp(tLAM + eta.LAM)           
    SHP = exp(tSHP)
    BSLD0 = exp(tBSLD0)
    BTSR = exp(tBTSR)
    BNWLS = exp(tBNWLS)
    BECOG = exp(tBECOG)

    #Time constant covariates
    TVSLD0 = 70                      # average SLD at enrolment
    NSLD0 = SLD0/TVSLD0              # normalised SLD at enrolment
    IECOG=ECOG                       # ECOG at enrolment

    # Model for dSLD(t)
    A(0) = IBASE*1000                # SLD baseline 
    MMBAS = IBASE*1000               # Parameter of the SLD(t) model were estimated previously (IPP approach)
    d/dt(A) = KG/1000 * A - (KD0/1000 * AUC0 + + KD1/100 * AUC1) * A
    TUM = A
    TSR = (TUM-MMBAS)/MMBAS

    if(time==0){                     #TSR(t) for t<= week 12 and TSR(week12) for t> week 12
      WTS = 0
      TM12 = 0
    } 
    if(time<=84){   
      WTS = TSR
      TM12 = WTS     
    } 
    else {
      WTS = WTS
    }

    # survival model
    DEL = 1E-6
    d/dt(A2) = LAM*SHP*(LAM*(T+DEL))**(SHP-1) *exp(BSLD0*NSLD0+BTSR*WTS+BNWLS*NWLS+BECOG*IECOG)

    # Death hazard 
    CHZ = A2
    SUR=exp(-CHZ)
    DELX = 1E-6
    xTUM = A
    xTSR = (xTUM-MMBAS)/MMBAS
    if(time==0){   
      XWTS=0
      XTM12=0
    } 

    if(time<=84){   
      XWTS = XTSR
      XTM12 = XWTS     
    } 
    else {
      XWTS=XWTS
    }

    HAZN = LAM*SHP*(LAM*(TIME+DELx))**(SHP-1)*exp(BSLD0*NSLD0+BTSR*XWTS+BNWLS*NWLS+BECOG*IECOG)
    # prediction
    if(FLAG == 9 & EVID == 0 & OSCENS == 1){
      IPRED=SUR                      # probability of survival (censored event)
      Y = IPRED                      # Y is probability for TTE data
    }
    if(FLAG == 9 & EVID == 0 & OSCENS == 0){
      IPRED=SUR*HAZN                # probability of event (death) at time=TIME
      Y = IPRED                     # Y is probability for TTE data
    }
    Y ~ add(add.err)

  })

}

library(nlmixr)
rxClean()

nlmixr(myModel_OS)
#> i parameter labels from comments will be replaced by 'label()'
#> __ RxODE-based ODE model _______________________________________________________ 
#> -- Initialization: ------------------------------------------------------------- 
#> Fixed Effects ($theta): 
#>       tLAM       tSHP     tBSLD0      tBTSR     tBNWLS     tBECOG 
#> -6.9077553  0.6931472 -2.3025851 -2.3025851 -2.3025851 -2.3025851 
#> 
#> Omega ($omega): 
#>         eta.LAM
#> eta.LAM    0.01
#> 
#>  Covariates or Uninitialized Parameters ($all.covs)
#>  [1] "SLD0"   "ECOG"   "IBASE"  "KG"     "KD0"    "AUC0"   "KD1"    "AUC1"  
#>  [9] "T"      "NWLS"   "XTSR"   "TIME"   "DELx"   "FLAG"   "EVID"   "OSCENS"
#> -- mu-referencing ($muRefTable): ----------------------------------------------- 
#>                              +-------------------+
#>                              ¦ theta   ¦ eta     ¦
#>                              +---------+---------¦
#>                              ¦ tLAM    ¦ eta.LAM ¦
#>                              +-------------------+
#> 
#> -- Model: ---------------------------------------------------------------------- 
#>     
#>     LAM = exp(tLAM + eta.LAM)           
#>     SHP = exp(tSHP)
#>     BSLD0 = exp(tBSLD0)
#>     BTSR = exp(tBTSR)
#>     BNWLS = exp(tBNWLS)
#>     BECOG = exp(tBECOG)
#>     
#>     #Time constant covariates
#>     TVSLD0 = 70                      # average SLD at enrolment
#>     NSLD0 = SLD0/TVSLD0              # normalised SLD at enrolment
#>     IECOG=ECOG                       # ECOG at enrolment
#>     
#>     # Model for dSLD(t)
#>     A(0) = IBASE*1000                # SLD baseline 
#>     MMBAS = IBASE*1000               # Parameter of the SLD(t) model were estimated previously (IPP approach)
#>     d/dt(A) = KG/1000 * A - (KD0/1000 * AUC0 + + KD1/100 * AUC1) * A
#>     TUM = A
#>     TSR = (TUM-MMBAS)/MMBAS
#>     
#>     if(time==0){                     #TSR(t) for t<= week 12 and TSR(week12) for t> week 12
#>       WTS = 0
#>       TM12 = 0
#>     } 
#>     if(time<=84){   
#>       WTS = TSR
#>       TM12 = WTS     
#>     } 
#>     else {
#>       WTS = WTS
#>     }
#>     
#>     # survival model
#>     DEL = 1E-6
#>     d/dt(A2) = LAM*SHP*(LAM*(T+DEL))**(SHP-1) *exp(BSLD0*NSLD0+BTSR*WTS+BNWLS*NWLS+BECOG*IECOG)
#>     
#>     # Death hazard 
#>     CHZ = A2
#>     SUR=exp(-CHZ)
#>     DELX = 1E-6
#>     xTUM = A
#>     xTSR = (xTUM-MMBAS)/MMBAS
#>     if(time==0){   
#>       XWTS=0
#>       XTM12=0
#>     } 
#>     
#>     if(time<=84){   
#>       XWTS = XTSR
#>       XTM12 = XWTS     
#>     } 
#>     else {
#>       XWTS=XWTS
#>     }
#>     
#>     HAZN = LAM*SHP*(LAM*(TIME+DELx))**(SHP-1)*exp(BSLD0*NSLD0+BTSR*XWTS+BNWLS*NWLS+BECOG*IECOG)
#>     # prediction
#>     if(FLAG == 9 & EVID == 0 & OSCENS == 1){
#>       IPRED=SUR                      # probability of survival (censored event)
#>       Y = IPRED                      # Y is probability for TTE data
#>     }
#>     if(FLAG == 9 & EVID == 0 & OSCENS == 0){
#>       IPRED=SUR*HAZN                # probability of event (death) at time=TIME
#>       Y = IPRED                     # Y is probability for TTE data
#>     }
#>     Y ~ add(add.err)
#>      
#> ________________________________________________________________________________

Created on 2022-03-30 by the reprex package (v2.0.1)

Session info ``` r sessioninfo::session_info() #> - Session info --------------------------------------------------------------- #> setting value #> version R version 4.1.3 (2022-03-10) #> os Windows 10 x64 (build 19042) #> system x86_64, mingw32 #> ui RTerm #> language (EN) #> collate English_United States.1252 #> ctype English_United States.1252 #> tz America/Chicago #> date 2022-03-30 #> pandoc 2.17.1.1 @ C:/R/Rstudio/bin/quarto/bin/ (via rmarkdown) #> #> - Packages ------------------------------------------------------------------- #> ! package * version date (UTC) lib source #> assertthat 0.2.1 2019-03-21 [1] CRAN (R 4.1.3) #> backports 1.4.1 2021-12-13 [1] CRAN (R 4.1.2) #> brew 1.0-7 2022-02-04 [1] CRAN (R 4.1.3) #> cachem 1.0.6 2021-08-19 [1] CRAN (R 4.1.3) #> checkmate 2.0.0 2020-02-06 [1] CRAN (R 4.1.3) #> cli 3.2.0 2022-02-14 [1] CRAN (R 4.1.3) #> colorspace 2.0-3 2022-02-21 [1] CRAN (R 4.1.3) #> crayon 1.5.0 2022-02-14 [1] CRAN (R 4.1.3) #> data.table 1.14.2 2021-09-27 [1] CRAN (R 4.1.3) #> digest 0.6.29 2021-12-01 [1] CRAN (R 4.1.3) #> dparser 1.3.1-5 2022-03-21 [1] CRAN (R 4.1.3) #> dplyr 1.0.8 2022-02-08 [1] CRAN (R 4.1.3) #> ellipsis 0.3.2 2021-04-29 [1] CRAN (R 4.1.3) #> evaluate 0.15 2022-02-18 [1] CRAN (R 4.1.3) #> fansi 1.0.2 2022-01-14 [1] CRAN (R 4.1.3) #> fastmap 1.1.0 2021-01-25 [1] CRAN (R 4.1.3) #> fs 1.5.2 2021-12-08 [1] CRAN (R 4.1.3) #> generics 0.1.2 2022-01-31 [1] CRAN (R 4.1.3) #> ggplot2 3.3.5 2021-06-25 [1] CRAN (R 4.1.3) #> glue 1.6.2 2022-02-24 [1] CRAN (R 4.1.3) #> gtable 0.3.0 2019-03-25 [1] CRAN (R 4.1.3) #> highr 0.9 2021-04-16 [1] CRAN (R 4.1.3) #> htmltools 0.5.2 2021-08-25 [1] CRAN (R 4.1.3) #> huxtable 5.4.0 2021-05-14 [1] CRAN (R 4.1.3) #> knitr 1.37 2021-12-16 [1] CRAN (R 4.1.3) #> lattice 0.20-45 2021-09-22 [1] CRAN (R 4.1.3) #> lazyeval 0.2.2 2019-03-15 [1] CRAN (R 4.1.3) #> lbfgsb3c 2020-3.2 2020-03-03 [1] CRAN (R 4.1.3) #> lifecycle 1.0.1 2021-09-24 [1] CRAN (R 4.1.3) #> lotri 0.3.1 2021-01-05 [1] CRAN (R 4.1.3) #> magrittr 2.0.2 2022-01-26 [1] CRAN (R 4.1.3) #> memoise 2.0.1 2021-11-26 [1] CRAN (R 4.1.3) #> munsell 0.5.0 2018-06-12 [1] CRAN (R 4.1.3) #> n1qn1 6.0.1-10 2020-11-17 [1] CRAN (R 4.1.3) #> nlme 3.1-155 2022-01-16 [1] CRAN (R 4.1.3) #> nlmixr * 2.0.6 2021-11-02 [1] CRAN (R 4.1.3) #> pillar 1.7.0 2022-02-01 [1] CRAN (R 4.1.3) #> pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 4.1.3) #> PreciseSums 0.4 2020-07-10 [1] CRAN (R 4.1.3) #> purrr 0.3.4 2020-04-17 [1] CRAN (R 4.1.3) #> qs 0.25.3 2022-02-22 [1] CRAN (R 4.1.3) #> R6 2.5.1 2021-08-19 [1] CRAN (R 4.1.3) #> RApiSerialize 0.1.0 2014-04-19 [1] CRAN (R 4.1.1) #> Rcpp 1.0.8.3 2022-03-17 [1] CRAN (R 4.1.3) #> D RcppParallel 5.1.5 2022-01-05 [1] CRAN (R 4.1.3) #> reprex 2.0.1 2021-08-05 [1] CRAN (R 4.1.3) #> rex 1.2.1 2021-11-26 [1] CRAN (R 4.1.3) #> rlang 1.0.2 2022-03-04 [1] CRAN (R 4.1.3) #> rmarkdown 2.13 2022-03-10 [1] CRAN (R 4.1.3) #> rstudioapi 0.13 2020-11-12 [1] CRAN (R 4.1.3) #> RxODE 1.1.5 2022-03-23 [1] CRAN (R 4.1.3) #> scales 1.1.1 2020-05-11 [1] CRAN (R 4.1.3) #> sessioninfo 1.2.2 2021-12-06 [1] CRAN (R 4.1.3) #> stringfish 0.15.5 2021-12-01 [1] CRAN (R 4.1.3) #> stringi 1.7.6 2021-11-29 [1] CRAN (R 4.1.2) #> stringr 1.4.0 2019-02-10 [1] CRAN (R 4.1.3) #> sys 3.4 2020-07-23 [1] CRAN (R 4.1.3) #> tibble 3.1.6 2021-11-07 [1] CRAN (R 4.1.3) #> tidyselect 1.1.2 2022-02-21 [1] CRAN (R 4.1.3) #> units 0.8-0 2022-02-05 [1] CRAN (R 4.1.3) #> utf8 1.2.2 2021-07-24 [1] CRAN (R 4.1.3) #> vctrs 0.3.8 2021-04-29 [1] CRAN (R 4.1.3) #> withr 2.5.0 2022-03-03 [1] CRAN (R 4.1.3) #> xfun 0.30 2022-03-02 [1] CRAN (R 4.1.3) #> yaml 2.3.5 2022-02-21 [1] CRAN (R 4.1.2) #> #> [1] C:/R/R-4.1.3/library #> #> D -- DLL MD5 mismatch, broken installation. #> #> ------------------------------------------------------------------------------ ```
mattfidler commented 2 years ago

Also additive error initial estimate should not start at 0...

mattfidler commented 2 years ago

I looked through the ddmore files and they use phi(dum) and no error; This means they are specifying the likelihood. Unfortunately this isn't supported yet in nlmixr model functions

andreasmeid commented 2 years ago

Many thanks for these very helpful notes. Is there a way to fit the parametric survival model with another R package, for example? I could calculate the tumour size (ODE for A in the code above) with RxODE, for example. The subsequent weibull survival model can be seen separate and thus could be fit in a different step, I guess.