Tumor growth inhibition model

Prediction intervals










[LONGITUDINAL]	
input={K, KDE, KPQ, KQPP, LAMBDAP, GAMMA, DELTAQP}

PK:
depot(target=C)

EQUATION:
PT_0=5
Q_0 = 40
PSTAR = PT+Q+QP
ddt_C = -KDE*C
ddt_PT = LAMBDAP*PT*(1-PSTAR/K) + KQPP*QP - KPQ*PT - GAMMA*KDE*PT*C
ddt_Q = KPQ*PT - GAMMA*KDE*Q*C
ddt_QP = GAMMA*KDE*Q*C - KQPP*QP - DELTAQP*QP

;----------------------------------------------------
[INDIVIDUAL]
input={K_pop,omega_K,KDE_pop,omega_KDE,KPQ_pop,omega_KPQ,KQPP_pop,omega_KQPP,
       LAMBDAP_pop,omega_LAMBDAP,GAMMA_pop,omega_GAMMA,DELTAQP_pop,omega_DELTAQP}

DEFINITION:
K     = {distribution=lognormal, prediction=K_pop,     sd=omega_K}
KDE     = {distribution=lognormal, prediction=KDE_pop,     sd=omega_KDE}
KPQ     = {distribution=lognormal, prediction=KPQ_pop,     sd=omega_KPQ}
KQPP     = {distribution=lognormal, prediction=KQPP_pop,     sd=omega_KQPP}
LAMBDAP = {distribution=lognormal, prediction=LAMBDAP_pop, sd=omega_LAMBDAP}
GAMMA  = {distribution=lognormal, prediction=GAMMA_pop,  sd=omega_GAMMA}
DELTAQP  = {distribution=lognormal, prediction=DELTAQP_pop,  sd=omega_DELTAQP}
#-------------------------------------------------------------------------
#  This application is governed by the CeCILL-B license. 
#  You can  use, modify and/ or redistribute this code under the terms
#  of the CeCILL license:  http://www.cecill.info/index.en.html
#
#  Marc Lavielle, Inria Saclay
#  April 29th, 2015
#-------------------------------------------------------------------------

shinyUI(fluidPage(
  titlePanel(
    list(HTML('<p style="color:#4C0B5F; font-size:24px">Tumor growth inhibition model</p>
              <p style="color:#4C0B5F; font-size:18px">Prediction intervals</p>' )),
    windowTitle="tumor growth III"),
  navbarPage("", selected="Plot", id="nav", inverse="FALSE", 
             title="",
             tabPanel("Plot",
                      tabsetPanel( id="tabs", type="pills",
                                   tabPanel("dosage"),
                                   tabPanel("population parameters"),
                                   tabPanel("iiv"),
                                   tabPanel("output"),
                                   tabPanel("settings")
                      ),
                      fluidRow(
                        column(3,
                               br(), br(),
                               conditionalPanel(condition="input.tabs=='dosage'",
                                                sliderInput("tfd", "time of first dose:", value=0, min=-50, max = 50, step=5),
                                                sliderInput("nd", "number of doses:", value=6, min=0, max = 20, step=1),
                                                sliderInput("ii", "interdose interval:", value = 15, min = 1, max = 20, step=1),
                                                sliderInput("amt", "amount:", value = 1, min = 0, max = 5, step=0.2),
                                                br()
                               ),
                               
                               conditionalPanel(condition="input.tabs=='population parameters'",
                                                sliderInput("GAMMA", "GAMMA_pop:", value = 1, min = 0, max = 4, step=0.1), 
                                                sliderInput("K", "K_pop:", value = 100, min = 0, max = 200, step=5),
                                                sliderInput("KDE", "KDE_pop:", value = 0.3, min = 0, max = 1, step=0.05),
                                                sliderInput("LAMBDAP", "LAMBDAP_pop:", value = 0.12, min = 0, max = 0.5, step=0.025) ,
                                                sliderInput("DELTAQP", "DELTAQP_pop:", value = 0.01, min = 0, max = 0.05, step=0.0025),
                                                sliderInput("KPQ", "KPQ_pop:", value = 0.025, min = 0, max = 0.1, step=0.005),
                                                sliderInput("KQPP", "KQPP_pop:", value = 0.004, min = 0, max = 0.01, step=0.0005),
                                                br()
                               ),
                               
                               conditionalPanel(condition="input.tabs=='iiv'",
                                                sliderInput("oGAMMA", "omega_GAMMA:", value = 0.2, min = 0, max = 1, step=0.05), 
                                                sliderInput("oK", "omega_K:", value = 0.2, min = 0, max = 1, step=0.05), 
                                                sliderInput("oKDE", "omega_KDE:", value = 0.2, min = 0, max = 1, step=0.05), 
                                                sliderInput("oLAMBDAP", "omega_LAMBDAP:", value = 0.2, min = 0, max = 1, step=0.05), 
                                                sliderInput("oDELTAQP", "omega_DELTAQP:", value = 0.2, min = 0, max = 1, step=0.05), 
                                                sliderInput("oKPQ", "omega_KPQ:", value = 0.2, min = 0, max = 1, step=0.05), 
                                                sliderInput("oKQPP", "omega_KQPP:", value = 0.2, min = 0, max = 1, step=0.05),
                                                br()
                               ),
                               
                               conditionalPanel(condition="input.tabs=='output'",
                                                radioButtons("output","",c("PSTAR" = "PSTAR","PT" = "PT","Q" = "Q","QP" = "QP")),
                                                br(),
                                                sliderInput("range", "time range", min = -100, max = 500, value = c(-50,200), step=10),
                                                br(),
                                                sliderInput("ngp", "grid size", min = 101, max = 1001, value = 201, step=50),
                                                br()
                               ),
                               
                               conditionalPanel(condition="input.tabs=='settings'",
                                                sliderInput("level", "level (%)", min = 5, max = 95, value = 80, step=5),
                                                sliderInput("nband", "number of bands", min = 1, max = 20, value = 8, step=1),
                                                sliderInput("nbsim", "number of simulations", min = 200, max = 2000, value = 600, step=200),
                                                br()
                               )
                        ),
                        column(9,
                               plotOutput("plot1",  height="500px"))
                      )),
             tabPanel("Table", tableOutput("table")),
             navbarMenu("Codes",
                        tabPanel("Mlxtran", pre(includeText("tgi3_model.txt"))),
                        tabPanel("ui.R", pre(includeText("ui.R"))),
                        tabPanel("server.R", pre(includeText("server.R"))
                        )
             ),
             tabPanel("ReadMe", withMathJax(), includeMarkdown("readMe.Rmd")),
             tabPanel("About", includeMarkdown("../../about/about.Rmd"))
  )
))

#-------------------------------------------------------------------------
#  This application is governed by the CeCILL-B license. 
#  You can  use, modify and/ or redistribute this code under the terms
#  of the CeCILL license:  http://www.cecill.info/index.en.html
#
#  Marc Lavielle, Inria Saclay
#  April 30th, 2015
#-------------------------------------------------------------------------

library(mlxR)

shinyServer(function(input, output) {
  
  r <- reactive({  
    param.value=c(input$K,input$KDE,input$KPQ,input$KQPP,input$LAMBDAP,input$GAMMA,input$DELTAQP,
                  input$oK,input$oKDE,input$oKPQ,input$oKQPP,input$oLAMBDAP,input$oGAMMA,input$oDELTAQP)
    t.value=seq(input$range[1],input$range[2],length.out=input$ngp)
    t1=0
    t2=input$ii*(input$nd-1)+t1
    if (t2>=t1){
      t.dose=seq(t1,t2,by=input$ii)
      adm <- list(time=t.dose, amount=input$amt)
    }else{
      adm <- list(time=t1, amount=0)
    }
    
    f  <- list(name=c('PSTAR','PT','Q','QP'),time=t.value)
    p   <- list(name=c('K_pop','KDE_pop','KPQ_pop','KQPP_pop','LAMBDAP_pop','GAMMA_pop','DELTAQP_pop',
                       'omega_K','omega_KDE','omega_KPQ','omega_KQPP','omega_LAMBDAP','omega_GAMMA','omega_DELTAQP'), 
                value=param.value)
  g <- list(size=input$nbsim,level='individual')
  
    res <- simulx( model     = 'tgi3_model.txt',
                   treatment = adm, 
                   parameter = p,
                   group = g,
                   output    = f)
  ro <- res[[input$output]]
  })
  
  
  output$plot1 <- renderPlot({
    withProgress(message = 'Creating plot', detail='Wait...', value = 0.1, expr={
      r=r()
    qr <- prctilemlx(r,band=list(level=input$level,number=input$nband))
print(qr)
    })
  })
    
  output$table <- renderTable({ 
    r=r()
    rq <- prctilemlx(r,list(level=input$level,number=input$nband),plot=FALSE)
    y=rq$y
  })
})

Objective

Visualize the prediction distribution of the tumor size defined by the Tumor Growth Inhibition (TGI) model proposed by Ribba et al., when the individual parameters of the model are log-normally distributed.

\[ \newcommand{\deriv}[1]{\dot{#1}(t)} \def\iid{\mathop{\sim}_{\rm i.i.d.}} \]


Mathematical model

ODEs:

\[ \begin{aligned} \deriv{C} &= - k_{de} C(t) \\ \deriv{P_T} &= \lambda P_T(t)(1- P^{\star}(t)/K) + k_{QPP}Q_P(t) -k_{PQ} P_T(t) -\gamma \, k_{de} P_T(t)C(t) \\ \deriv{Q} &= k_{PK} P_T(t) -\gamma \, k_{de} Q(t)C(t) \\ \deriv{Q_P} &= \gamma \, k_{de} Q(t)C(t) - k_{QPP} Q_P(t) -\delta_{QP} Q_P(t) \end{aligned} \]

  • \(C\): concentration of the compartment that receives the doses.
  • \(P_T\): proliferative cells
  • \(Q\): quescient cells
  • \(Q_P\): damaged quescient cells
  • \(P^{\star} = P_T(t) + Q(t) + Q_P(t)\): observed tumor size

Initial conditions:

\[ \begin{aligned} C(0) &= Q_P(0) = 0 \\ P_T(0) &= p_{T0} \\ Q(0) &= q_0 \end{aligned} \]

Population distribution:

The parameters of the model \(\gamma\), \(k_{PK}\), \(k_{de}\), \(\lambda\), \(\delta_{QP}\), \(k_{PQ}\), \(k_{QPP}\) are log-normally distributed


Playing with the shiny app

1. Define the dosage regimen in the tab input:

  • time of first dose,
  • number of doses,
  • interdose interval,
  • amount per dose.


2. select the population parameters (i.e. the reference values of the parameters) in the tab population parameters:


3. select the standard deviations of the (transformed) individual parameters, i.e. the standard deviations of the random effects, in the tab iiv. In this example, all the individual parameters are log-normally distributed.


4. define the outputs in the tab outputs :

  • select the output to display,

  • select the time range where the prediction is computed,

  • select the number of time points of the grid where the prediction is computed.


5. define the prediction distribution to display in the tab settings:

  • select the level of the prediction interval (between 5% and 95%),

  • select the number of bands which form this prediction interval

  • the number of simulations used for estimating this prediction distribution.

By default a 80% prediction interval decomposed in 8 bands is used. Then, the 10th, 20th, 30th, …, 70th and 90th percentiles are displayed.


This application is governed by the CeCILL-B license.
You can use, modify and/or redistribute these codes under the terms of the CeCILL license.


This Shiny application requires the mlxR package.


Marc Lavielle
Inria Saclay, Popix team
April 29th, 2015