R/app.R

Defines functions runApp generate_ui server

####################

server <- function(input, output, session) {

    params = yaml.load_file( system.file("content/parameter_values.yaml", package='covid19icu') )
   
    
    observe({
        updateSliderInput(session, "floorcapramp", max=input$time)
        updateSliderInput(session, "icucapramp", max=input$time)

        # check if numeric inputs are NA
        if(is.na(input$floorcap)) { 
          updateNumericInput(session, "floorcap", value=params$L)
         } 
        if(is.na(input$icucap)) { 
          updateNumericInput(session, "icucap", value=params$M)
        }




        if(is.na(input$floorcaptarget)) { 
          updateNumericInput(session, "floorcaptarget", value=params$L)
         } 

        if(!is.na(input$floorcaptarget) && !is.na(input$floorcap) && input$floorcaptarget<input$floorcap) {
          updateNumericInput(session, "floorcaptarget", value=input$floorcap)
        }


        if(is.na(input$icucaptarget)) { 
          updateNumericInput(session, "icucaptarget", value=params$M)
        } 

       if(!is.na(input$icucaptarget) && !is.na(input$icucap) && input$icucaptarget<input$icucap) { 
          updateNumericInput(session, "icucaptarget", value=input$icucap)
       }

      })
    #####################################################################################################
    
    
    output$hospitalPlot <- renderPlot({
    # put slider control values here as arguments
    plots<-plot_hospital(params=update_inputs(t=input$time,
                                              young= input$ages[1],
                                              medium =input$ages[2]-input$ages[1],
                                              #######################
                                              I_init= input$initrep,
                                              I_final=input$finalrep,
                                              distribution =input$distrib,
                                              doublingtime=input$doubling_time,
                                              rampslope=input$rampslope,
                                              #######################
                                              M=ifelse(is.na(input$icucap),params$M,input$icucap),
                                              L=ifelse(is.na(input$floorcap),params$L,input$floorcap),
                                              L_occupied=input$L_occupied,
                                              M_occupied=input$M_occupied,
                                              Lramp=input$floorcapramp,
                                              Mramp=input$icucapramp,
                                              ######################
                                              avg_LOS_ICU=input$avgicudischargetime,
                                              avg_LOS_Floor=input$avgfloordischargetime,
                                              #####################
                                              p_death_ICU2= input$ICUdeath_medium,
                                              p_death_ICU3= input$ICUdeath_old,
                                              p_death_floor2=input$floordeath_medium,
                                              p_death_floor3=input$floordeath_old,
                                              #####################
                                              ed_visits_timeseries= as.numeric(strsplit(input$ed_visits_timeseries, split = ",")[[1]]),
                                              #####################
                                               L_final=input$floorcaptarget,
                                               M_final=input$icucaptarget),
                                              #####################
                                            dynamicModel=input$dynamicModel,
                                            doprotocols=input$doprotocols)

    
    plot_grid(plots[[1]], plots[[2]],plots[[3]],plots[[4]], nrow=2, ncol=2, labels=c('A', 'B', 'C', 'D'), align="hv")

  })
  
  output$hospitalTable <- renderTable({
    
     text = text_hospital(params=update_inputs(t=input$time,
                                               young= input$ages[1],
                                               medium =input$ages[2]-input$ages[1],
                                               #######################
                                               I_init= input$initrep,
                                               I_final=input$finalrep,
                                               distribution =input$distrib,
                                               doublingtime=input$doubling_time,
                                               rampslope=input$rampslope,
                                               #######################
                                               M=ifelse(is.na(input$icucap),params$M,input$icucap),
                                               L=ifelse(is.na(input$floorcap),params$L,input$floorcap),
                                               L_occupied=input$L_occupied,
                                               M_occupied=input$M_occupied,
                                               Lramp=input$floorcapramp,
                                               Mramp=input$icucapramp,
                                               ######################
                                               avg_LOS_ICU=input$avgicudischargetime,
                                               avg_LOS_Floor=input$avgfloordischargetime,
                                               #####################
                                               p_death_ICU2= input$ICUdeath_medium,
                                               p_death_ICU3= input$ICUdeath_old,
                                               p_death_floor2=input$floordeath_medium,
                                               p_death_floor3=input$floordeath_old,
                                               #####################
                                               ed_visits_timeseries= as.numeric(strsplit(input$ed_visits_timeseries, split = ",")[[1]]),
                          #####################
                          L_final=input$floorcaptarget,
                          M_final=input$icucaptarget),
                          #####################
                          dynamicModel=input$dynamicModel,
                          doprotocols=input$doprotocols)
  })

  output$keypoints <- renderText({
     dat = text_hospital(doprotocols=input$doprotocols,
                         params=update_inputs(t=input$time,
                                              young= input$ages[1],
                                              medium =input$ages[2]-input$ages[1],
                                              #######################
                                              I_init= input$initrep,
                                              I_final=input$finalrep,
                                              distribution =input$distrib,
                                              doublingtime=input$doubling_time,
                                              rampslope=input$rampslope,
                                              #######################
                                              M=ifelse(is.na(input$icucap),params$M,input$icucap),
                                              L=ifelse(is.na(input$floorcap),params$L,input$floorcap),
                                              L_occupied=input$L_occupied,
                                              M_occupied=input$M_occupied,
                                              Lramp=input$floorcapramp,
                                              Mramp=input$icucapramp,
                                              ######################
                                              avg_LOS_ICU=input$avgicudischargetime,
                                              avg_LOS_Floor=input$avgfloordischargetime,
                                              #####################
                                              p_death_ICU2= input$ICUdeath_medium,
                                              p_death_ICU3= input$ICUdeath_old,
                                              p_death_floor2=input$floordeath_medium,
                                              p_death_floor3=input$floordeath_old,
                                              #####################
                                              ed_visits_timeseries=  as.numeric(strsplit(input$ed_visits_timeseries, split = ",")[[1]]),
                         #####################
                         L_final=input$floorcaptarget,
                         M_final=input$icucaptarget),
                         #####################
                                       dynamicModel=input$dynamicModel)
    
    rownames(dat) = dat$Variable
     
    dat$Value = as.character(dat$Value)
    
    if (dat["Days to floor overflow","Value"] == "No shortage"){
      dat["Days to floor overflow","Value"] = "a time beyond the simulation"
    } else {dat["Days to floor overflow","Value"] = paste(dat["Days to floor overflow","Value"], " days")}
    
    if (dat["Days to ICU overflow","Value"] == "No shortage"){
      dat["Days to ICU overflow","Value"] = "a time beyond the simulation"
    } else {dat["Days to ICU overflow","Value"] = paste(dat["Days to ICU overflow","Value"], " days")}

    paste("<h4> </br> <b> Key points: </b> Under the specified capacities and expansion strategy, 
          the model predicts that <b> ICU beds will reach capacity at ", 
          dat["Days to ICU overflow","Value"], 
          "</b>, and <b> floor beds at ",
          dat["Days to floor overflow","Value"], 
          "</b>. The model predicts <b>", 
          dat["Total deaths","Value"], 
          " deaths </b> and a hospital <b> case-fatality rate of ",
          dat["Case fatality ratio","Value"], 
          " </b>. ", "An additional <b>",
          dat["Extra floor beds needed for COVID19+ patients", "Value"],
          " floor beds </b> and <b>",
          dat["Extra ICU beds needed for COVID19+ patients", "Value"],
          " ICU beds </b> would be needed to accommodate all COVID19+ patients who present to the health system. </h4>", sep="")

  })
  
  output$agebands <- renderText({
   agebands <- c(input$ages) 
   paste("<p> <b>0-18 years:</b> ", 
         agebands[1]*100, 
         "% <b>- 18-65 years:</b>  ",
         (agebands[2]-agebands[1])*100, 
         "% <b>- 65+ years:</b> ", 
         (1-agebands[2])*100, 
         " %</p>", sep="")  
  })

  output$report <- downloadHandler(
      # For PDF output, change this to "report.pdf"
      filename = "ScenarioReport.pdf",
      content = function(file) {
        # Copy the report file to a temporary directory before processing it, in
        # case we don't have write permissions to the current working dir (which
        # can happen when deployed).
        tempReport <- file.path(tempdir(), "ScenarioReport.Rmd")
        file.copy("ScenarioReport.Rmd", tempReport, overwrite = TRUE)

        # Set up parameters to pass to Rmd document
        params_rmd <- list(t=input$time,
                         young=input$ages[1],
                         medium=input$ages[2]-input$ages[1],
                         I_init=input$initrep,
                         I_final=input$finalrep,
                         distribution=input$distrib,
                         doublingtime=input$doubling_time,
                         rampslope=input$rampslope,
                         M=ifelse(is.na(input$icucap),params$M,input$icucap),
                         L=ifelse(is.na(input$floorcap),params$L,input$floorcap),
                         L_occupied=input$L_occupied,
                         M_occupied=input$M_occupied,
                         #L_final=ifelse(is.na(input$floorcaptarget),params$L,input$floorcaptarget),
                         Lramp=input$floorcapramp,
                         #M_final=ifelse(is.na(input$icucaptarget),params$M,input$icucaptarget),
                         Mramp=input$icucapramp,
                         avg_LOS_ICU=input$avgicudischargetime,
                         avg_LOS_Floor=input$avgfloordischargetime,
                         p_death_ICU2 = input$ICUdeath_medium,
                         p_death_ICU3= input$ICUdeath_old,
                         p_death_floor2=input$floordeath_medium,
                         p_death_floor3= input$floordeath_old,
                       ed_visits_timeseries= as.numeric(strsplit(input$ed_visits_timeseries, split = ",")[[1]]),
                       #####################
                       L_final=input$floorcaptarget,
                       M_final=input$icucaptarget,
                        #####################
                        dynamicModel=input$dynamicModels,
                       doprotocols=input$doprotocols)


        # Knit the document, passing in the `params` list, and eval it in a
        # child of the global environment (this isolates the code in the document
        # from the code in this app).
        rmarkdown::render(tempReport, output_file = file,
          params = params_rmd,
          envir = new.env(parent = globalenv())
        )
      }
    )



}

####################


generate_ui <- function(params) {

fluidPage(theme=shinytheme("simplex"),
 titlePanel("COVID-19 Hospital Capacity Model"),
  sidebarLayout(
    sidebarPanel(
      tabsetPanel(
        tabPanel("Scenario", fluid=TRUE,
          includeMarkdown(system.file("content/instructions.md", package='covid19icu')),
          h3("Scenario:"),
          sliderInput("time", "Time Horizon (days)",     min=2, max=params$t_Max, step=1, value=params$t),



          #radioButtons("scenarioSelect", h4("Scenario selection"), c("Static"="static", "Dynamic model-based"="dynamic"), inline=TRUE,selected="static"),
          #conditionalPanel(condition="input.scenarioSelect == 'static'",


            # Keep this static functionality
            radioButtons("distrib", "Change in number of COVID19+ presentations to the health system per day",
                       c("Exponential"="exponential",
                         "Linear"="ramp",
                         "Saturated"="logistic",
                         "Flat"="uniform"),
                       inline=TRUE,
                       selected="exponential"),
            sliderInput("initrep", "Initial COVID19+ presentations to the health system per day", min=1, max=params$I_initmax, value=params$I_init),
            conditionalPanel(
              condition = "input.distrib=='logistic'",
              sliderInput("finalrep", "Peak number of COVID19+ presentations to the health system per day", min=1, max=params$I_finalmax, value=params$I_final)
              ),
	         conditionalPanel(
              condition = "input.distrib=='ramp'",
              sliderInput("rampslope", "Rate of increase in number of COVID19+ presentations to the health system per day", min=params$rampslope_min, 
                          max=params$rampslope_max, value=params$rampslope, step = params$rampslope_step)
              ),
            conditionalPanel(
              condition = "input.distrib == 'exponential'",
              sliderInput("doubling_time", "Doubling time for COVID19+ presentations to the health system per day (days)", min=params$doublingtime_min, max=params$doublingtime_max, value=params$doublingtime, step=0.1)
            )
          # end static functionality


          # development version only 
          # set condition to "0==0" to show scenario type selection
          ,
          conditionalPanel(condition="0==1",
          conditionalPanel(condition="input.scenarioSelect == 'dynamic'", 
            radioButtons("dynamicModel", "Dynamic model projection",
                         c("Scenario Generation"=0,
                           "Input ED visits"=1,
                           "Input Infection incidence"=2),
                         inline=TRUE,
                         selected=0)
          ),
          conditionalPanel( condition= "input.dynamicModel==1",
             textInput("ed_visits_timeseries", label = h6("ED visit time-series"), value = "0,0,0,0,0,0,0,0")
          ),
          conditionalPanel(condition= "input.dynamicModel==2",
                textInput("infecton_timeseries", label = h6("Infection incidence time-series"), value = "0,0,0,0,0,0,0,0"),
                sliderInput("reporting_delay", "Time from infection incidence to presenting to ED",     min=1, max=20, step=1, value=10),
                sliderInput("reporting_percentage", "Percentage of infectives presenting to ED",     min=1, max=100, step=1, value=20),
          ) 
          ) 
          , 
          hr(),
        downloadButton("report", "Download scenario report")
        ),
        tabPanel("Capacity", fluid=TRUE,
		      includeMarkdown(system.file("content/capacity.md", package='covid19icu')),

          	

		numericInput("icucap", "Initial ICU capacity for COVID19+ patients (number of beds) ",  min=0, max=params$M_Max, step=1, value=params$M),
		numericInput("floorcap", "Initial floor capacity for COVID19+ patients (number of beds)", min=0, max=params$L_Max, step=1, value=params$L),

		sliderInput("M_occupied", "% of initial ICU capacity for COVID19+ patients occupied at time 0",     min=0, max=100, value=params$M_occupied),
		sliderInput("L_occupied", "% of initial floor capacity for COVID19+ patients occupied at time 0",     min=0, max=100, value=params$L_occupied)),

        tabPanel("Strategy", fluid=TRUE,
          includeMarkdown(system.file("content/protocols.md", package='covid19icu')),
          radioButtons("doprotocols", "Capacity expansion strategy",
                       c("Off"=0, "On"=1),
                       inline=TRUE,
                       selected=0),
          conditionalPanel(
            condition = "input.doprotocols==1",
            numericInput("icucaptarget",  "Target ICU capacity for COVID19+ patients (number of beds)", min=0, max=params$M_Max, step=1, value=params$M),

            sliderInput("icucapramp",  "ICU capacity scale-up (days)", min=0, max=30, value=c(params$icucapramp1,params$icucapramp2)),
            numericInput("floorcaptarget",  "Target floor capacity for COVID19+ patients (number of beds)", min=0, max=params$L_Max, step=1, value=params$L),

            sliderInput("floorcapramp",  "Floor capacity scale-up (days)", min=0, max=30, value=c(params$floorcapramp1,params$floorcapramp2))
          )),
          
        tabPanel("Parameters", fluid=TRUE,
          includeMarkdown(system.file("content/parameters.md", package='covid19icu')),
          sliderInput("ages",  "Age breakdown of COVID+ admissions (0-18), (18-65), (65+) ", min=0, max=1, value=c(params$young,params$medium+params$young)),
          tableOutput("agebands"),
          sliderInput("avgfloordischargetime", "Average time on floor for COVID19+ patients", min= params$minfloordischargetime, max=params$maxfloordischargetime, value=params$avgfloordischargetime),
          sliderInput("avgicudischargetime", "Average time in ICU for COVID19+ patients",     min=params$minicudischargetime, max=params$maxicudischargetime, value=params$avgicudischargetime),
		#sliderInput("ICUdeath_young", "Probability of death in ICU (<18 years)",     min=0, max=1, value=params$p_death_ICU1),
		sliderInput("floordeath_medium", "Probability of death for COVID19+ patients on the floor given time on floor (18-64 years)",     min=0, max=params$max_p_death_Floor2, value=params$p_death_Floor2),
		sliderInput("floordeath_old", "Probability of death for COVID19+ patients on the floor given time on floor (65+ years)",     min=0, max=params$max_p_death_Floor3, value=params$p_death_Floor3),
		sliderInput("ICUdeath_medium", "Probability of death for COVID19+ patients in ICU given time in ICU (18-64 years)",     min=0, max=1, value=params$p_death_ICU2),
		sliderInput("ICUdeath_old", "Probability of death for COVID19+ patients in ICU given time in ICU (65+ years)",     min=0, max=1, value=params$p_death_ICU3),
        )),width=4),
    mainPanel(
    tabsetPanel(
       tabPanel("Plots", fluid=TRUE,
         plotOutput("hospitalPlot",height="700px")
       ),
       tabPanel("Summary", fluid=TRUE,
			includeMarkdown(system.file("content/summary.md", package='covid19icu')),
                tableOutput("hospitalTable")
                ),
    tabPanel("Inputs", fluid=TRUE,
             includeMarkdown(system.file("content/inputs.md", package='covid19icu'))
    ),
    tabPanel("Outputs", fluid=TRUE,
             includeMarkdown(system.file("content/outputs.md", package='covid19icu'))
    ),
	    tabPanel("About", fluid=TRUE,
       includeMarkdown(system.file("content/queue_graphic.md", package='covid19icu'))
       )
    )
  )),
  htmlOutput("keypoints"),

  hr(),
  includeMarkdown(system.file("content/footer.md", package='covid19icu'))
)
}

#' @export
runApp <- function() { 
  params = yaml.load_file( system.file("content/parameter_values.yaml", package='covid19icu') )
  
  shinyApp(ui = generate_ui(params), server = server)
}
fcrawford/covid19_icu documentation built on Nov. 21, 2020, 12:14 p.m.