forked from DARTH-git/darthpack
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Shiny_framework.R
497 lines (428 loc) · 22.6 KB
/
Shiny_framework.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
################################################################################
# This script calibrates the Sick-Sicker state-transition model (STM) to #
# epidemiological targets using a Bayesian approach with the Incremental #
# Mixture Importance Samping (IMIS) algorithm #
# #
# Depends on: #
# 00_general_functions.R #
# Authors: #
# - Fernando Alarid-Escudero, PhD, <fernando.alarid@cide.edu> #
# - Eline Krijkamp, MS #
# - Petros Pechlivanoglou, PhD #
# - Hawre Jalal, MD, PhD #
# - Eva A. Enns, PhD #
################################################################################
# The structure of this code is according to the DARTH framework #
# https://github.com/DARTH-git/Decision-Modeling-Framework #
################################################################################
library(shiny)
setwd(dirname(rstudioapi::getActiveDocumentContext()$path)) # set the working directory
devtools::load_all(".")
###Function
ui <- fluidPage(
# App title ----
titlePanel("Sick-Sicker Markov Model"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(width=5,
tabsetPanel(id = "input",type="tabs",
tabPanel("Component selection",
# Input: which components should run? ----
checkboxInput("calib", " Model Calibration ", FALSE),
checkboxInput("valid", " Model Validation ", FALSE),
checkboxInput("deter", "Deterministic Sensitivity Analysis", FALSE),
checkboxInput("psa", "Probabilistic Sensitivity Analysis", FALSE),
checkboxInput("voi", "Value of Information Analysis", FALSE)
),
tabPanel("Model Structure",
# Input: Age ----
sliderInput(inputId = "age",
label = "Cohort Age",value=c(25,100),
min = 0, max = 100, step = 1),
# Input: Discount Rate ----
numericInput(inputId = "Dis",
label = "Discount Rate",
value = 0.03,
min=0,
step=0.0001)
),
tabPanel("Probabilities",
# Input: Probabilities----
numericInput(inputId = "p_HS1",
label = "Probability of Transition Healthy to Sick",
value = 0.15,
min=0,max=1),
numericInput(inputId = "p_S1H",
label = "Probability of Transition Sick to Healthy",
value = 0.5,
min=0,max=1),
numericInput(inputId = "p_S1S2",
label = "Probability of Transition Sick to Sicker",
value = 0.105,
min=0,max=1),
# Input: Rate Ratio ----
numericInput(inputId = "hr_S1",
label = "Hazard Ratio of Sick to Dead compared to Healthy",
value = 3,
min=0),
numericInput(inputId = "hr_S2",
label = "Hazard Ratio of Sicker to Dead compared to Healthy",
value = 10,
min=0)
),
tabPanel("Utilities", # Input: Utilities ----
numericInput(inputId = "u_H",
label = "Utility when Healthy",
value = 1,
max=1,
min=0),
numericInput(inputId = "u_S1",
label = "Utility when Sick",
value = 0.75,
max=1,
min=0),
numericInput(inputId = "u_S2",
label = "Utility when Sicker",
value = 0.5,
max=1,
min=0),
numericInput(inputId = "u_Trt",
label = "Utility of Sick Patients when on Treatment",
value = 0.95,
max=1,
min=0),
numericInput(inputId = "u_D",
label = "Utility when Dead",
value = 0,
max=1,
min=0)
),
tabPanel("Costs", # Input: Costs ----
numericInput(inputId = "c_H",
label = "Cost when Healthy",
value = 2000,
min=0),
numericInput(inputId = "c_S1",
label = "Cost when Sick",
value = 4000,
min=0),
numericInput(inputId = "c_S2",
label = "Cost when Sicker",
value = 15000,
min=0),
numericInput(inputId = "c_Trt",
label = "Cost when on Treatment",
value = 12000,
min=0),
numericInput(inputId = "c_D",
label = "Cost when Dead",
value = 0,
min=0)
)
),
actionButton("button", "Run")
),
# Main panel for displaying outputs ----
mainPanel(width=7,
p("Evalulating the Cost-Effectiveness of a Treatment to Improve Quality of Life for Sick Patients using a Sick-Sicker Model"),
p("**Refresh App after changing input parameters or the type of sensitivity analysis"),
tabsetPanel(id = "output", type="tabs",
tabPanel("Decision Model",
#Output: Matplot ----
imageOutput("modeldiagram"),
htmlOutput("diagramtext"),
imageOutput("traceplot"),
htmlOutput("traceplottext")
)
)
)
)
)
server <- function(input, output) {
# Histogram of the Old Faithful Geyser Data ----
# with requested number of bins
# This expression that generates a histogram is wrapped in a call
# to renderPlot to indicate that:
#
# 1. It is "reactive" and therefore should be automatically
# re-executed when inputs (input$bins) change
# 2. Its output type is a plot
observeEvent(input$psa,{
if(input$psa == TRUE) {
insertTab(inputId = "input",
tabPanel("Probabilistic analysis"
),
target = "Costs",
position = c("after")
)
}else{
removeTab(inputId = "input",target = "Probabilistic analysis")
}
})
observeEvent(input$button, {
withProgress(message = 'Performing Health Economic Analysis', value = 0, {
input.file <- paste(getwd(),"/data-raw/01_basecase_params.csv", sep="")
calib.file <- paste(getwd(),"/data-raw/01_init_params.csv", sep="")
#print(input.file)
input.arrange<-c(input$c_H,
input$c_S1,
input$c_S2,
input$c_D,
input$c_Trt,
input$u_H,
input$u_S1,
input$u_S2,
input$u_D,
input$u_Trt,
input$p_HS1,
input$p_S1H,
input$p_S1S2,
input$hr_S1,
input$hr_S2,
as.numeric(input$age)[1],
as.numeric(input$age)[2]-as.numeric(input$age)[1],
input$Dis,
input$Dis)
names(input.arrange)<-c("c_H",
"c_S1",
"c_S2",
"c_D",
"c_Trt",
"u_H",
"u_S1",
"u_S2",
"u_D",
"u_Trt",
"p_HS1",
"p_S1H",
"p_S1S2",
"hr_S1",
"hr_S2",
"n_age_init",
"n_t",
"d_c",
"d_e")
input.mat<-as.matrix(input.arrange)
calib.mat<-t(input.mat)
#input.list <- shiny::reactiveValuesToList(input)
#input.mat <- rbind(unlist(input.list))
#calib.mat <- rbind(unlist(input.list))
write.csv(input.mat, input.file, row.names = F)
write.csv(calib.mat, calib.file, row.names = F)
#### 00 Install and load packages ####
#source("R/app0_packages-setup.R", echo = TRUE)
#### 02 Load simulation model and test it ####
source("analysis/02_decision_model.R", echo = TRUE)
#### 03 Calibrate simulation model ####
if(input$calib == TRUE){
source("analysis/03_calibration.R", echo = TRUE)
insertTab(inputId = "output",
tabPanel("Model Calibration",
#Output: Matplot ----
tableOutput("calibsummary"),
htmlOutput("calibsumtext"),
imageOutput("jointposterior"),
htmlOutput("calibjointtext"),
imageOutput("jointmarginal"),
htmlOutput("calibmargtext")
), target = "Decision Model",
position = c("after")
)
}
#### 05c Conduct value of information analysis ####
if(input$voi == TRUE) {
source("analysis/05c_value_of_information.R", echo = TRUE)
insertTab(inputId = "output",
tabPanel("Value of Information Analysis",
#Output: Matplot ----
imageOutput("evpi"),
htmlOutput("evpitext")
), target = "Decision Model",
position = c("after")
)
}
#### 04 Validate simulation model ####
if(input$valid == TRUE) {
source("analysis/04_validation.R", echo = TRUE)
insertTab(inputId = "output",
tabPanel("Model Validation",
#Output: Matplot ----
imageOutput("validsicker"),
htmlOutput("validsickertext"),
imageOutput("validsurv"),
htmlOutput("validsurvtext"),
imageOutput("validprev"),
htmlOutput("validprevtext")
), target = "Decision Model",
position = c("after")
)
}
#### 05a Conduct probabilistic analysis ####
if(input$psa == TRUE) {
source("analysis/05a_probabilistic_analysis.R", echo = TRUE)
insertTab(inputId = "output",
tabPanel("Probabilistic Sensitivity Analysis",
#Output: Matplot ----
tableOutput("psaresults"),
htmlOutput("cearesultstext"),
imageOutput("scatter"),
htmlOutput("psascattertext"),
imageOutput("ceaf"),
htmlOutput("psaceaftext"),
imageOutput("elc"),
htmlOutput("psaelctext")
), target = "Decision Model",
position = c("after")
)
}
#### 05b Conduct deterministic analysis ####
if(input$deter == TRUE) {
source("analysis/05b_deterministic_analysis.R", echo = TRUE)
insertTab(inputId = "output",
tabPanel("Deterministic Sensitivity Analysis",
#Output: Matplot ----
tableOutput("cearesults"),
htmlOutput("cearesultstext"),
imageOutput("cefrontier"),
htmlOutput("frontiertext"),
imageOutput("owsa"),
htmlOutput("owsatext"),
imageOutput("owsa_optimal"),
htmlOutput("owsaoptext"),
imageOutput("owsa_tornado"),
htmlOutput("owsatortext"),
imageOutput("twsa"),
htmlOutput("twsatext")
), target = "Decision Model",
position = c("after")
)
}
})
output$cearesults <- renderTable({
read.csv("./tables/05b_deterministic_cea_results.csv")
},digits=2)
output$psaresults <- renderTable({
read.csv("./tables/05a_probabilistic_cea_results.csv")
},digits=2)
output$calibsummary <- renderTable({
read.csv("./tables/03_summary_posterior.csv")
},digits=2)
output$modeldiagram <-renderImage({
filename = normalizePath(file.path('./figs/02_model_diagram.png'))
list(src=filename, width = 400, height = 400)
},
deleteFile = FALSE)
output$traceplot <-renderImage({
filename = normalizePath(file.path('./figs/02_trace_plot.png'))
list(src=filename,
width = 400, height = 400
)},
deleteFile = FALSE)
output$jointposterior<-renderImage({
filename = normalizePath(file.path('./figs/03_posterior_distribution_joint.png'))
list(src=filename,
width = 400, height = 400
)},
deleteFile = FALSE)
output$jointmarginal<-renderImage({
filename = normalizePath(file.path('./figs/03_posterior_distribution_marginal.png'))
list(src=filename,
width = 400, height = 400
)},
deleteFile = FALSE)
output$validprev<-renderImage({
filename = normalizePath(file.path('./figs/04_posterior_vs_targets_prevalence.png'))
list(src=filename,
width = 400, height = 400
)},
deleteFile = FALSE)
output$validsurv<-renderImage({
filename = normalizePath(file.path('./figs/04_posterior_vs_targets_survival.png'))
list(src=filename,
width = 400, height = 400
)},
deleteFile = FALSE)
output$validsicker<-renderImage({
filename = normalizePath(file.path('./figs/04_posterior_vs_targets_proportion_sicker.png'))
list(src=filename,
width = 400, height = 400
)},
deleteFile = FALSE)
output$cefrontier<-renderImage({
filename = normalizePath(file.path('./figs/05b_cea_frontier.png'))
list(src=filename,
width = 400, height = 400
)},
deleteFile = FALSE)
output$owsa<-renderImage({
filename = normalizePath(file.path('./figs/05b_owsa_nmb.png'))
list(src=filename,
width = 400, height = 400
)},
deleteFile = FALSE)
output$owsa_optimal<-renderImage({
filename = normalizePath(file.path('./figs/05b_optimal_owsa_nmb.png'))
list(src=filename,
width = 400, height = 400
)},
deleteFile = FALSE)
output$owsa_tornado<-renderImage({
filename = normalizePath(file.path('./figs/05b_tornado_Treatment_nmb.png'))
list(src=filename,
width = 400, height = 400
)},
deleteFile = FALSE)
output$twsa<-renderImage({
filename = normalizePath(file.path('./figs/05b_twsa_uS1_uTrt_nmb.png'))
list(src=filename,
width = 400, height = 400
)},
deleteFile = FALSE)
output$scatter<-renderImage({
filename = normalizePath(file.path('./figs/05a_cea_plane_scatter.png'))
list(src=filename,
width = 400, height = 400
)},
deleteFile = FALSE)
output$ceaf<-renderImage({
filename = normalizePath(file.path('./figs/05a_ceac_ceaf.png'))
list(src=filename,
width = 400, height = 400
)},
deleteFile = FALSE)
output$elc<-renderImage({
filename = normalizePath(file.path('./figs/05a_elc.png'))
list(src=filename,
width = 400, height = 400
)},
deleteFile = FALSE)
output$evpi<-renderImage({
filename = normalizePath(file.path('./figs/05c_evpi.png'))
list(src=filename,
width = 400, height = 400
)},
deleteFile = FALSE)
output$evpitext <- renderUI({ HTML("Expected value of perfect information.")})
output$diagramtext <- renderUI({ HTML("State-transition diagram of the Sick-Sicker model. Healthy individuals can get Sick, die or stay healthy. Sick individuals can recover, transitioning back to healthy, can die, or stay sick. Once individuals are Sicker, they stay Sicker until they die.")})
output$traceplottext <- renderUI({ HTML("Cohort trace of the Sick-Sicker cohort model.")})
output$calibsumtext <- renderUI({ HTML("Summary statistics of the posterior distribution.")})
output$calibjointtext <- renderUI({ HTML("Joint posterior distribution.")})
output$calibmargtext <- renderUI({ HTML("Pairwise posterior distribution of calibrated parameters.")})
output$validsurvtext <- renderUI({ HTML("Survival data: Model-predicted outputs vs targets.")})
output$validprevtext <- renderUI({ HTML("Prevalence data of sick individuals: Model-predicted output vs targets.")})
output$validsickertext <- renderUI({ HTML("Proportion who are Sicker, among all those afflicted (Sick + Sicker): Model-predicted output.")})
output$psascattertext <- renderUI({ HTML("The cost-effectiveness plane graph showing the results of the probabilistic sensitivity analysis for
the Sick-Sicker case-study.")})
output$psaceaftext <- renderUI({ HTML("Cost-effectiveness acceptability curves (CEACs) and frontier (CEAF).")})
output$psaelctext <- renderUI({ HTML("Expected Loss Curves.")})
output$owsatext <- renderUI({ HTML("One-way sensitivity analysis results. ")})
output$owsaoptext <- renderUI({ HTML("One-way sensitivity analysis - optimal strategy. ")})
output$owsatortext <- renderUI({ HTML("Tornado plot. ")})
output$twsatext <- renderUI({ HTML("Two-way sensitivity analysis results. ")})
output$frontiertext <- renderUI({ HTML("Plot of the cost-effectiveness frontier. ")})
output$cearesultstext <- renderUI({ HTML("CEA results. ")})
})
}
#tags$div(img(src = "www/images/image.png"))
shinyApp(ui = ui, server = server)