Hospital Capacity Planning Using Discrete Event Simulation: Numerical Methods

knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "%>"
)

Introduction

Packages

install.packages("devtools")
devtools::install_github("r-lib/devtools")
url <- "http://owos.gm.fh-koeln.de:8055/bartz/spot.git"
devtools::install_git(url = url)
url <- "http://owos.gm.fh-koeln.de:8055/bartz/babsim.hospital"
devtools::install_git(url = url, subdir = "babsim.hospital")
rm(list = ls())
suppressPackageStartupMessages({
library("SPOT")
library("babsim.hospital")
library("simmer")
library("simmer.plot")
library("plotly")
})
packageVersion("SPOT")

Motivation

Data used by babsim.hospital

Data Sources

Simulation Data: UK Data

library(readxl)
X20201111UKdata <- read_excel("../../inst/extdata/CovidDataGroup1.xlsx")
ukdataRawFull1 <- X20201111UKdata
str(ukdataRawFull1)

Consider Second Wave

ukdataRaw <- ukdataRawFull1[as.Date(ukdataRawFull1$Date) > "2020-09-01",]
str(ukdataRaw)
simData <- data.frame(Day = as.Date(ukdataRaw$Date),
                      Infected = ukdataRaw$NewCases)
plot(simData$Infected ~ simData$Day, type="b")

Field Data (Real ICU Beds)

Preprocessing TL ICU Data

Day <- as.Date(ukdataRaw$Date)
bed <- ukdataRaw$TotalCOVID19Inpatient - ukdataRaw$COVID19NonInvasiveCPAP - ukdataRaw$COVID19VentilatedICU
intensiveBed <-  ukdataRaw$COVID19NonInvasiveCPAP
intensiveBedVentilation <- ukdataRaw$COVID19VentilatedICU
fieldData <- data.frame(Day = Day,
                        bed = bed,
                        intensiveBed = intensiveBed,
                        intensiveBedVentilation = intensiveBedVentilation)
str(fieldData)
max(fieldData$intensiveBed)

Performing Simulations

seed = 123
simrepeats = 2
parallel = FALSE
percCores = 0.8
resourceNames =  c("bed", "intensiveBed", "intensiveBedVentilation")
resourceEval = c("bed", "intensiveBed", "intensiveBedVentilation")
FieldStartDate = as.Date(min(fieldData$Day))
rownames(fieldData) <- NULL
icu = FALSE
icuWeights = c(1,2,10)
SimStartDate = FieldStartDate
data <- list(simData = simData,
 fieldData = fieldData)
visualizeUK <- function(data,
                        region = 05315){
  dataCov <- data$fieldData
  par(mfrow=c(3,1))
  plot(dataCov$Day, dataCov$bed, type = "b", xlab = "Day", 
       ylab="Patients", 
       main = paste0("bed: non ICU patients in hospital")
  )
  dataCov$weekly <- slide_dbl(dataCov$bed, ~mean(.x), .before = (7 -1))
  lines(dataCov$Day, dataCov$weekly, col = "red")
  ##
  plot(dataCov$Day, dataCov$intensiveBed, type = "b", xlab = "Tag", 
       ylab="Patients", 
       main = paste0("intensiveBed: ICU bed without ventilation")
  )
  dataCov$weekly <- slide_dbl(dataCov$intensiveBed, ~mean(.x), .before = (7 -1))
  lines(dataCov$Day, dataCov$weekly, col = "red")
  ##
  plot(dataCov$Day, dataCov$intensiveBedVentilation, type = "b", xlab = "Tag", 
       ylab="Patients", 
       main = paste0("intensiveBedVentilation: ICU bed with ventilation")
  )
  dataCov$weekly <- slide_dbl(dataCov$intensiveBedVentilation, ~mean(.x), .before = (7 -1))
  lines(dataCov$Day, dataCov$weekly, col = "red")
}
visualizeUK(data=data)
UKdata <- data
### usethis::use_data(UKdata, overwrite = TRUE)
conf <- babsimToolsConf()
conf$ResourceEval <- conf$ResourceNames
conf <- getConfFromData(conf = conf,
                        simData = data$simData,
                        fieldData = data$fieldData)
  conf$parallel = parallel
  conf$simRepeats = simrepeats
  conf$ICU = FALSE
  conf$ResourceNames = resourceNames
  conf$ResourceEval = resourceEval
  conf$percCores = percCores
  conf$logLevel = 0
  conf$w2 = icuWeights
  set.seed(conf$seed)

Simulation Model Parameters

para <- babsimHospitalPara()
str(para)

Run simulation

arrivalTimes <- data.frame(time = getArrivalTimes(data$simData$Infected))
envs <- babsimHospital(arrivalTimes = arrivalTimes,
                         conf = conf,
                         para = para)

Visualize Output

Simmer Plots

resources <- get_mon_resources(envs)
resources$capacity <- resources$capacity/1e5
plot(resources, metric = "usage", c("bed", "intensiveBed", "intensiveBedVentilation"), items = "server",steps= TRUE)
plot(resources, metric = "usage", "bed", items = "server", steps = TRUE)
  1. The following command generates a plot of icu beds without ventilation:
plot(resources, metric = "usage", "intensiveBed", items = "server", steps = TRUE)
  1. The following command generates a plot of icu beds with ventilation:
plot(resources, metric = "usage", "intensiveBedVentilation", items = "server", steps = TRUE)

Evaluate Simulation Results

fieldEvents <- getRealBeds(data = data$fieldData,
                        resource = conf$ResourceNames)
res <- getDailyMaxResults(envs = envs,  fieldEvents = fieldEvents, conf=conf)
resDefault <- getError(res, conf=conf)

The error is r resDefault.

p <- plotDailyMaxResults(res, showBeds = TRUE)
plot(p)
ggplotly(p) 

Optimization

para <- babsimHospitalPara()
print(para)
conf$simulationDates$StartDate
conf$simulationDates$EndDate
conf$fieldDates$StartDate
conf$fieldDates$EndDate

Run 01 with adapted probabilities:

# modified 17.2.2021: factorUK added
# modified 22.2.2021: factorIcuUK added
library("babsim.hospital")
library("SPOT")
library("simmer")
studyDate <- as.Date( min(conf$simulationDates$EndDate, conf$fieldDates$EndDate ))
resUK <- runoptUK(
  expName = paste0("UK-", format(Sys.time(), "%Y-%b.%d-%H.%M-V"), utils::packageVersion("babsim.hospital")),
  simData = data$simData,
  fieldData = data$fieldData,
  TrainSimStartDate = studyDate - 10*7, # "2020-09-02",
  TrainFieldStartDate = studyDate - 8*7, # "2020-09-15",
  TestSimStartDate = studyDate - 6*7 , #"2020-09-30",
  TestFieldStartDate = studyDate - 4*7, #"2020-10-23",
  Overlap = 0,
  seed = 101170,
  repeats = 2, 
  funEvals = 50,
  size = 30,
  simrepeats = 2,
  parallel = TRUE,
  percCores = 0.9,
  icu = FALSE,
  icuWeights = c(1,2,10),
  verbosity = 0,
  resourceNames =  c("bed", "intensiveBed", "intensiveBedVentilation"),
  resourceEval = c("bed", "intensiveBed", "intensiveBedVentilation"),
  factorUK = 0.1,
  factorIcuUK = 1.0
)
ukpara01 <- resUK[[1]]
usethis::use_data(ukpara01, overwrite = TRUE)

Run 02 with adapted probabilities and durations:

# modified 17.2.2021: factorUK added
# modified 22.2.2021: factorIcuUK added
library("babsim.hospital")
library("SPOT")
library("simmer")
studyDate <- as.Date( min(conf$simulationDates$EndDate, conf$fieldDates$EndDate ))
resUK <- runoptUK(
  expName = paste0("UK-", format(Sys.time(), "%Y-%b.%d-%H.%M-V"), utils::packageVersion("babsim.hospital")),
  simData = data$simData,
  fieldData = data$fieldData,
  TrainSimStartDate = studyDate - 10*7, # "2020-09-02",
  TrainFieldStartDate = studyDate - 8*7, # "2020-09-15",
  TestSimStartDate = studyDate - 6*7 , #"2020-09-30",
  TestFieldStartDate = studyDate - 4*7, #"2020-10-23",
  Overlap = 0,
  seed = 101170,
  repeats = 2, 
  funEvals = 50,
  size = 30,
  simrepeats = 2,
  parallel = TRUE,
  percCores = 0.9,
  icu = FALSE,
  icuWeights = c(1,2,10),
  verbosity = 0,
  resourceNames =  c("bed", "intensiveBed", "intensiveBedVentilation"),
  resourceEval = c("bed", "intensiveBed", "intensiveBedVentilation"),
  factorUK = 0.1,
  factorIcuUK = 2
)
ukpara02 <- resUK[[1]]
usethis::use_data(ukpara02, overwrite = TRUE)

Use Optimized Parameters from Run 01

ukpara <- ukpara01
print(ukpara)
para <- getBestParameter(resUK[[1]])
para01 <- getBestParameter(ukpara01)
str(para01)
conf$simRepeats = 10
res01 <- modelResultHospital(para=para01, 
                           conf=conf,
                           data = data)
resOpt01 <- getError(res01, conf=conf)
p01 <- plotDailyMaxResults(res01, showBeds = TRUE)
print(p01)
ggplotly(p01)

Use Optimized Parameters from Run 02

ukpara <- ukpara02
print(ukpara)
para <- getBestParameter(resUK[[1]])
para02 <- getBestParameter(ukpara02)
str(para02)
conf$simRepeats = 100
res02 <- modelResultHospital(para=para02, 
                           conf=conf,
                           data = data)
resOpt02 <- getError(res02, conf=conf)
p02 <- plotDailyMaxResults(res02, showBeds = TRUE)
print(p02)
ggplotly(p02)

Visualize and Analyse Parameter Settings

visualizeGraph(para=para, option = "P")
getMatrixP(para = para )
visualizeGraph(para = para, option = "D")
getMatrixD(para = para)

Project Work

Part I (26.1.2021)

Part II (2.2.2021)

Specific Questions for Each Group

Organisation

Group 1. Group Problem Understanding, Data Understanding

Group 2. Data Preparation (Extract, transfer load)

Group 3. Theoretical Modeling

Group 4. Performing Simulations

Group 5. Optimization, Evaluation, Visualization

Code for Part II (Simulation and Optimization of babsimhospital)

## install.packages("devtools")
## devtools::install_github("r-lib/devtools")

## url <- "http://owos.gm.fh-koeln.de:8055/bartz/spot.git"
## devtools::install_git(url = url)

## url <- "http://owos.gm.fh-koeln.de:8055/bartz/babsim.hospital"
## devtools::install_git(url = url, subdir = "babsim.hospital")

rm(list = ls())
suppressPackageStartupMessages({
library("SPOT")
library("babsim.hospital")
library("simmer")
library("simmer.plot")
library("readxl")
  })

packageVersion("SPOT")
### X20201111UKdata <- read_excel("/Users/bartz/workspace/Lehre.d/IDEA-Master-AIT-WS2020-2021/Numerical-Methods/Datasets/CovidDataGroup1.xlsx")
X20201111UKdata <- read_excel("~bartz/workspace/Lehre.d/IDEA-Master-AIT-WS2020-2021/Numerical-Methods/Datasets/CovidDataGroup1.xlsx")
ukdataRaw <- X20201111UKdata[as.Date(X20201111UKdata$Date) > "2020-09-01",]
simData <- data.frame(Day = as.Date(ukdataRaw$Date),
                      Infected = ukdataRaw$NewCases)
Day <- as.Date(ukdataRaw$Date)
bed <- ukdataRaw$TotalCOVID19Inpatient - ukdataRaw$COVID19NonInvasiveCPAP - ukdataRaw$COVID19VentilatedICU
intensiveBed <-  ukdataRaw$COVID19NonInvasiveCPAP
intensiveBedVentilation <- ukdataRaw$COVID19VentilatedICU
fieldData <- data.frame(Day = Day,
                        bed = bed,
                        intensiveBed = intensiveBed,
                        intensiveBedVentilation = intensiveBedVentilation)
rownames(fieldData) <- NULL
data <- list(simData = simData,
 fieldData = fieldData)
conf <- babsimToolsConf()
conf$ResourceEval <- conf$ResourceNames
conf <- getConfFromData(conf = conf,
                        simData = data$simData,
                        fieldData = data$fieldData)
conf$parallel = TRUE
conf$simRepeats = 2
conf$ICU = FALSE
conf$ResourceNames =  c("bed", "intensiveBed", "intensiveBedVentilation")
conf$ResourceEval =  c("bed", "intensiveBed", "intensiveBedVentilation")
conf$percCores = 0.8
conf$logLevel = 0
conf$w2 = c(1,2,10)
conf$seed = 123
set.seed(conf$seed)
para <- babsimHospitalPara()
arrivalTimes <- data.frame(time = getArrivalTimes(data$simData$Infected))
envs <- babsimHospital(arrivalTimes = arrivalTimes,
                         conf = conf,
                         para = para)
resources <- get_mon_resources(envs)
resources$capacity <- resources$capacity /1e5
plot(resources, metric = "usage", c("bed", "intensiveBed", "intensiveBedVentilation"), items = "server",steps= TRUE)
# plot(resources, metric = "usage", "bed", items = "server", steps = TRUE)
# plot(resources, metric = "usage", "intensiveBed", items = "server", steps = TRUE)
# plot(resources, metric = "usage", "intensiveBedVentilation", items = "server", steps = TRUE)
fieldEvents <- getRealBeds(data = data$fieldData,
                        resource = conf$ResourceNames)
res <- getDailyMaxResults(envs = envs,  fieldEvents = fieldEvents, conf=conf)
errDefault <- getError(res, conf=conf)
print(errDefault)
p <- plotDailyMaxResults(res, showBeds = TRUE)
plot(p)
ggplotly(p)
library("babsim.hospital")
library("SPOT")
library("simmer")
studyDate <- as.Date( min(conf$simulationDates$EndDate, conf$fieldDates$EndDate ))
resUK <- runoptUK(
  expName = paste0("UK-", format(Sys.time(), "%Y-%b.%d-%H.%M-V"), utils::packageVersion("babsim.hospital")),
  simData = data$simData,
  fieldData = data$fieldData,
  TrainSimStartDate = studyDate - 10*7, # "2020-09-02",
  TrainFieldStartDate = studyDate - 8*7, # "2020-09-15",
  TestSimStartDate = studyDate - 6*7 , #"2020-09-30",
  TestFieldStartDate = studyDate - 4*7, #"2020-10-23",
  Overlap = 0,
  seed = 101170,
  repeats = 2,
  funEvals = 50,
  size = 35,
  simrepeats = 2,
  parallel = TRUE,
  percCores = 0.9,
  icu = FALSE,
  icuWeights = c(1,2,10),
  verbosity = 0,
  resourceNames =  c("bed", "intensiveBed", "intensiveBedVentilation"),
  resourceEval = c("bed", "intensiveBed", "intensiveBedVentilation")
)
ukpara <- resUK[[1]]
print(ukpara)
paraOpt <- getBestParameter(resUK[[1]])
str(paraOpt)
# Best para as provided by SPOT.
# Can be used if optimization is not possible:
# paraOpt <- getBestParameter(ukpara)
# print(paraOpt)
conf$simRepeats = 10
resOpt <- modelResultHospital(para=paraOpt, 
                            conf=conf,
                            data = data)
errOpt <- getError(resOpt, conf=conf)
print(errOpt)
p <- plotDailyMaxResults(resOpt, showBeds = TRUE)
print(p)
# ggplotly(p)
 getMatrixP(para = para )
visualizeGraph(para=paraOpt, option = "P")
getMatrixD(para = paraOpt)
visualizeGraph(para = paraOpt, option = "D")

Summary

Appendix

Modification of the Boundaries for UK ICUs

  bounds <- getBounds()
    a <- bounds$lower
    b <- bounds$upper
  length(a)
getParameterNameList(1:29)
getParameterDataFrame()
factorUK <- 0.1
 bounds <- getBounds()
    a <- bounds$lower
    b <- bounds$upper
    a[16] <- a[16] * factorUK
    a[18] <- a[18] * factorUK
    a[20] <- a[20] * factorUK 
    b[16] <- b[16] * factorUK
    b[18] <- b[18] * factorUK
    b[20] <- b[20] * factorUK

Second consideration

factorUK <- 0.1
factorIcuUK <- 2
   bounds <- getBounds()
    a <- bounds$lower
    b <- bounds$upper
      a[16] <- a[16] * factorUK
    a[18] <- a[18] * factorUK
    a[20] <- a[20] * factorUK 
    b[16] <- b[16] * factorUK
    b[18] <- b[18] * factorUK
    b[20] <- b[20] * factorUK
    a[6] <- a[6] * factorIcuUK
    a[7] <- a[7] * factorIcuUK
    a[8] <- a[8] * factorIcuUK 
    b[6] <- b[6] * factorIcuUK
    b[7] <- b[7] * factorIcuUK
    b[8] <- b[8] * factorIcuUK
a

Results

para.df <- getParameterDataFrame()
para.df[,]
para.table <- xtable::xtable(para.df)
para.df <- getParameterDataFrame()
para.df[,"obk"] <- a
para.df[,"koeln"] <- b 
colnames(para.df) <- c("default", "minUK", "maxUK", "minDE", "MaxDE")
para.table <- xtable::xtable(para.df)
para.table


Try the babsim.hospital package in your browser

Any scripts or data that you put into this service are public.

babsim.hospital documentation built on May 30, 2022, 9:05 a.m.