diff --git a/DESCRIPTION b/DESCRIPTION index fdf770e8..ecdaa04f 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -52,7 +52,17 @@ Suggests: rmarkdown, scales, testthat, - truncnorm + truncnorm, + shiny, + DT, + bookdown, + diagram, + heemod, + shinycssloaders, + shinydashboard, + shinyjs, + survminer, + R6 VignetteBuilder: knitr Roxygen: list(markdown = TRUE) RoxygenNote: 7.1.2 diff --git a/R/shinyIndivCtstm.R b/R/shinyIndivCtstm.R new file mode 100644 index 00000000..daa0134e --- /dev/null +++ b/R/shinyIndivCtstm.R @@ -0,0 +1,44 @@ + +#' @title Launch an example shiny application using hesim +#' +#' @description +#' An example of how hesim can be used in a shiny application. +#' +#' @export +#' +#' @examples +#' if (interactive()) { +#' +#' shinyIndivCtstm() +#' +#' } +shinyIndivCtstm <- function() { + if (!requireNamespace(package = "shiny")) + message("Package 'shiny' is required to run this function") + if (!requireNamespace(package = "shinydashboard")) + message("Package 'shinydashboard' is required to run this function") + if (!requireNamespace(package = "shinycssloaders")) + message("Package 'shinycssloaders' is required to run this function") + if (!requireNamespace(package = "shinyjs")) + message("Package 'shinyjs' is required to run this function") + if (!requireNamespace(package = "magrittr")) + message("Package 'magrittr' is required to run this function") + if (!requireNamespace(package = "heemod")) + message("Package 'heemod' is required to run this function") + if (!requireNamespace(package = "survminer")) + message("Package 'survminer' is required to run this function") + if (!requireNamespace(package = "DT")) + message("Package 'DT' is required to run this function") + if (!requireNamespace(package = "diagram")) + message("Package 'diagram' is required to run this function") + if (!requireNamespace(package = "rmarkdown")) + message("Package 'rmarkdown' is required to run this function") + if (!requireNamespace(package = "bookdown")) + message("Package 'bookdown' is required to run this function") + if (!requireNamespace(package = "knitr")) + message("Package 'knitr' is required to run this function") + if (!requireNamespace(package = "kableExtra")) + message("Package 'kableExtra' is required to run this function") + + shiny::shinyAppDir(system.file("examples/IndivCtstm app", package = "hesim", mustWork = TRUE)) +} diff --git a/inst/examples/IndivCtstm_app/app.R b/inst/examples/IndivCtstm_app/app.R new file mode 100644 index 00000000..e32fca07 --- /dev/null +++ b/inst/examples/IndivCtstm_app/app.R @@ -0,0 +1,18 @@ +#The app.R script is where the app can be called from +# It can also be called from hesim::shinyIndivCtstm() +# See https://shiny.rstudio.com/gallery/ for examples of shiny app layouts and functionalties + +library("shiny") +library("hesim") +options(encoding = "UTF-8") + +# Setwd --------------- +# setwd if running script from this file. Set wd() as the hesim project location +# setwd() + +App_location <- "./inst/examples/IndivCtstm_app/" + +runApp(appDir = file.path(getwd(),App_location), # This looks for the ui.R, server.R and www folder within the wd. Do not rename these. + launch.browser = TRUE, # This line will open the application in the user's default browser + quiet = FALSE, + display.mode = "normal") diff --git a/inst/examples/IndivCtstm_app/html-report.Rmd b/inst/examples/IndivCtstm_app/html-report.Rmd new file mode 100644 index 00000000..d449c533 --- /dev/null +++ b/inst/examples/IndivCtstm_app/html-report.Rmd @@ -0,0 +1,150 @@ +--- +title: "hesim html example report" +author: "Example using IndivCtstm" +date: "`r format(Sys.time(), '%d %B, %Y')`" +output: + bookdown::html_document2: + number_sections: no + fig_caption: yes + toc: true + toc_depth: 2 +fontsize: 11pt +sansfont: Calibri Light +# fontfamily: newcent +# spacing: double +endnote: no +always_allow_html: true +params: + Stateprobs: "params$Stateprobs" + Summarisedf: "params$Summarisedf" + labs_indiv: "params$labs_indiv" +--- + +```{r setup, echo=FALSE} +knitr::opts_chunk$set( + cache = FALSE, + message = FALSE, + warning = FALSE, + fig.height = (12 / 2.5), + fig.width = (18 / 2.5), + dpi = 350 +) +``` + +
+ +# Introduction + +Producing automated reports for modelers and users is possible using R Markdown. This enables you to focus the writing of technical reports on the story surrounding the results and ensures that the outputs match the model. R Markdown has several features that make it ideal for this purpose: + +1. Links directly to the code within the text and outputs +2. Allows passing of information from an R Shiny app to the markdown document script for rendering an up-to-date report +3. Reasonably flexible with respect to formatting, including tables, figures, Microsoft Word templates and so on +4. Easy to use and to understand the script documents +5. Allows presentation of the code used to generate a rendered output for simple and effective QC, communication and general transparency + +The majority of any R Markdown document will be raw text, though the front matter may be the most important part of the document. The document will be generated that includes both content as well as the output of any embedded R code chunks within the document. There are a lot of cheat sheets and reference guides for Markdown and bookdown (e.g. [Yihui Xie](https://bookdown.org/yihui/rmarkdown-cookbook/), [Adam Prichard](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet)) + +The purpose of this report is to demonstrate the use of R Markdown through outputting the results of the `hesim` example model. + +# Results + +The results of the `hesim` example are passed to R Markdown via the `rmarkdown::render()` function. Within this function, `envir` is used to import the current user environment with loaded libraries. For instance, `ggplot2` was loaded in the main R script, so importing the script environment into R Markdown means it does not need to be loaded again here. This means that the data and values that were created in the R script are also loaded in. `params` can also be specified, which lists the data to be used in the report; this is particularly important if `rmarkdown::render()` is being called from a `shiny` application, as it may be that the outputs are dynamically generated. In this example, the state probability data frame, the summary data frame with the discounted outcomes, and the state and strategy labels were passed to R Markdown via the code below. The differences in how the information is passed from within the R script and from within the `shiny` application are shown. + +In the code below, the `input` refers to the .Rmd file (this file), which lays out the R Markdown document. The output The `output_format` is the selected format of the document, in this case `"html_document"` is used to create a html output (see [other options](https://rmarkdown.rstudio.com/lesson-9.html)). `output_file` refers to the name of the output to be created, which needs to be consistent with the output format. + +***Gathering results from R script:*** +```markdown + +Note: This code chunk uses markdown instead of r. markdown shows the script without running it, whereas r runs the script. Both markdown and r code chunks look the same when rendered into the document + + Export_params <- list( + # Main results + Stateprobs = ictstm$stateprobs_, + Summarisedf = ce_sim_ictstm, + labs_indiv = labs_indiv + ) + + # html document + rmarkdown::render( + input = "./hesim report.Rmd", + output_format = 'bookdown::html_document2', + output_file = "hesim-html-report.html", + params = Export_params, + envir = environment() + ) + +``` + +***Gathering results from R shiny app:*** +```markdown + + output$Create_htmlreport <- downloadHandler( + filename = "hesim-html-report.html", + content = function(file) { + + ce_sim_ictstm <- ictstm()$summarize() + + Export_params <- list( + # Main results + Stateprobs = ictstm()$stateprobs_, + Summarisedf = ce_sim_ictstm, + labs_indiv = labs_indiv + ) + + # html document + rmarkdown::render( + input = "./hesim report.Rmd", + output_format = 'bookdown::html_document2', + output_file = file, + params = Export_params, + envir = environment() + ) + } + ) + +``` + +The two subsections below (as denoted by the `##` in the .Rmd script) below show how inputs from the main model can be used within the document + +## State transition probabilities + +The code below is an r chunk, which means that is it run as the R Markdown document renders. It will therefore return the outputs of the code. `print(params$Stateprobs)` is called below, which prints the value of `params$Stateprobs`. If `echo = TRUE` is specified at the top of the chunk, then the code is also printed into the document. + +```{r FigStateTransitionTable, echo = TRUE} +print(params$Stateprobs) + +``` + +
+Figures can be printed into the document within the r chunks in exactly the same way as they are called in the main R script. + +```{r FigStateTransitionPlot, echo = TRUE, fig.cap="State transition probabilities over time"} +autoplot(params$Stateprobs, labels = params$labs_indiv, + ci = FALSE) + theme_bw() + ggplot2::theme(legend.position = "bottom") + +``` + + +## Cost and survival summary + +Tables can also be displayed in R Markdown documents in a similar way to figures. The `kableExtra` package can be used with `knitr` to format tables in the desired way. + +Note that the `echo = FALSE` parameter can be added to code chunks to prevent printing of the R code that generated the output. + +```{r TableSummary, echo = FALSE} +Tableout <- summary(params$Summarisedf, labels = params$labs_indiv) %>% format() +kbl(Tableout, booktabs = T, position = "h", align = "c", centering = T, caption = "Summary of total costs and QALYs") %>% + kable_styling(latex_options = "hold_position") + +``` + +# Discussion +The purpose of R Markdown is to make reporting from R automated and accessible for modelers and intended audience. However, it is always important to leave room for thoughtful interpretation and messaging. It is recommended that you note throughout your document where further results interpretation is needed upon document finalization. Useful formatting tips include: + +- Single asterisks italicize text *like this*. +- Double asterisks embolden text **like this**. +- Use text colour to mark sections + +To assist with discussions and interpretations, the values that have been calculated or used in the R chunks can be directly imported into the text, for example, the top row of Table 1 shows that is the `r colnames(Tableout)[3]` regimen `r Tableout[1,2]` outcome value is `r Tableout[1,3]`. + diff --git a/inst/examples/IndivCtstm_app/html-report.html b/inst/examples/IndivCtstm_app/html-report.html new file mode 100644 index 00000000..4da818e0 --- /dev/null +++ b/inst/examples/IndivCtstm_app/html-report.html @@ -0,0 +1,911 @@ + + + + + + + + + + + + + + +hesim html example report + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ +
+ +


+
+

Introduction

+

Producing automated reports for modelers and users is possible using R Markdown. This enables you to focus the writing of technical reports on the story surrounding the results and ensures that the outputs match the model. R Markdown has several features that make it ideal for this purpose:

+
    +
  1. Links directly to the code within the text and outputs
  2. +
  3. Allows passing of information from an R Shiny app to the markdown document script for rendering an up-to-date report
  4. +
  5. Reasonably flexible with respect to formatting, including tables, figures, Microsoft Word templates and so on
  6. +
  7. Easy to use and to understand the script documents
  8. +
  9. Allows presentation of the code used to generate a rendered output for simple and effective QC, communication and general transparency
  10. +
+

The majority of any R Markdown document will be raw text, though the front matter may be the most important part of the document. The document will be generated that includes both content as well as the output of any embedded R code chunks within the document. There are a lot of cheat sheets and reference guides for Markdown and bookdown (e.g. Yihui Xie, Adam Prichard)

+

The purpose of this report is to demonstrate the use of R Markdown through outputting the results of the hesim example model.

+
+
+

Results

+

The results of the hesim example are passed to R Markdown via the rmarkdown::render() function. Within this function, envir is used to import the current user environment with loaded libraries. For instance, ggplot2 was loaded in the main R script, so importing the script environment into R Markdown means it does not need to be loaded again here. This means that the data and values that were created in the R script are also loaded in. params can also be specified, which lists the data to be used in the report; this is particularly important if rmarkdown::render() is being called from a shiny application, as it may be that the outputs are dynamically generated. In this example, the state probability data frame, the summary data frame with the discounted outcomes, and the state and strategy labels were passed to R Markdown via the code below. The differences in how the information is passed from within the R script and from within the shiny application are shown.

+

In the code below, the input refers to the .Rmd file (this file), which lays out the R Markdown document. The output The output_format is the selected format of the document, in this case "html_document" is used to create a html output (see other options). output_file refers to the name of the output to be created, which needs to be consistent with the output format.

+

Gathering results from R script:

+

+Note: This code chunk uses markdown instead of r. markdown shows the script without running it, whereas r runs the script. Both markdown and r code chunks look the same when rendered into the document
+
+ Export_params <- list(
+   # Main results
+   Stateprobs            = ictstm$stateprobs_,
+   Summarisedf           = ce_sim_ictstm,
+   labs_indiv            = labs_indiv
+ )
+
+ # html document
+ rmarkdown::render(
+   input = "./hesim report.Rmd",
+   output_format = 'bookdown::html_document2',
+   output_file = "hesim-html-report.html",
+   params = Export_params,
+   envir = environment()
+ )
+ 
+

Gathering results from R shiny app:

+

+  output$Create_htmlreport <- downloadHandler(
+      filename = "hesim-html-report.html",
+      content = function(file) {
+        
+        ce_sim_ictstm <- ictstm()$summarize()
+
+        Export_params <- list(
+          # Main results
+          Stateprobs            = ictstm()$stateprobs_,
+          Summarisedf           = ce_sim_ictstm,
+          labs_indiv            = labs_indiv
+        )
+
+        # html document
+        rmarkdown::render(
+          input = "./hesim report.Rmd",
+          output_format = 'bookdown::html_document2',
+          output_file = file,
+          params = Export_params,
+          envir = environment()
+        )
+      }
+    )
+ 
+

The two subsections below (as denoted by the ## in the .Rmd script) below show how inputs from the main model can be used within the document

+
+

State transition probabilities

+

The code below is an r chunk, which means that is it run as the R Markdown document renders. It will therefore return the outputs of the code. print(params$Stateprobs) is called below, which prints the value of params$Stateprobs. If echo = TRUE is specified at the top of the chunk, then the code is also printed into the document.

+
print(params$Stateprobs)
+
##          sample strategy_id grp_id state_id           t prob
+##       1:      1           1      1        1  0.00000000    1
+##       2:      1           1      1        1  0.08333333    1
+##       3:      1           1      1        1  0.16666667    1
+##       4:      1           1      1        1  0.25000000    1
+##       5:      1           1      1        1  0.33333333    1
+##      ---                                                    
+## 3248996:   1000           3      1        3 29.66666667    1
+## 3248997:   1000           3      1        3 29.75000000    1
+## 3248998:   1000           3      1        3 29.83333333    1
+## 3248999:   1000           3      1        3 29.91666667    1
+## 3249000:   1000           3      1        3 30.00000000    1
+


+Figures can be printed into the document within the r chunks in exactly the same way as they are called in the main R script.

+
autoplot(params$Stateprobs, labels = params$labs_indiv,
+            ci = FALSE) + theme_bw() + ggplot2::theme(legend.position = "bottom")
+
+State transition probabilities over time +

+Figure 1: State transition probabilities over time +

+
+
+
+

Cost and survival summary

+

Tables can also be displayed in R Markdown documents in a similar way to figures. The kableExtra package can be used with knitr to format tables in the desired way.

+

Note that the echo = FALSE parameter can be added to code chunks to prevent printing of the R code that generated the output.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Table 1: Summary of total costs and QALYs +
+Discount rate + +Outcome + +SOC + +New 1 + +New 2 +
+0.00 + +QALYs + +7.88 (7.08, 8.70) + +8.60 (7.80, 9.44) + +9.22 (8.38, 10.06) +
+0.00 + +Costs: Drug + +18,195 (16,960, 19,389) + +90,216 (84,148, 96,569) + +122,429 (114,276, 131,033) +
+0.00 + +Costs: Medical + +62,814 (6,148, 206,641) + +63,327 (6,897, 203,534) + +65,200 (7,253, 210,602) +
+0.00 + +Costs: total + +81,010 (24,722, 225,523) + +153,543 (96,251, 297,018) + +187,629 (129,105, 337,383) +
+0.01 + +Costs: Drug + +17,167 (16,053, 18,238) + +86,021 (80,504, 91,858) + +116,326 (108,924, 124,118) +
+0.01 + +Costs: Medical + +57,552 (5,751, 187,443) + +57,634 (6,397, 182,529) + +59,032 (6,737, 187,706) +
+0.01 + +Costs: total + +74,719 (23,312, 205,220) + +143,655 (91,915, 271,558) + +175,358 (122,787, 307,324) +
+0.03 + +QALYs + +6.59 (5.99, 7.19) + +7.11 (6.52, 7.72) + +7.53 (6.94, 8.12) +
+
+
+
+

Discussion

+

The purpose of R Markdown is to make reporting from R automated and accessible for modelers and intended audience. However, it is always important to leave room for thoughtful interpretation and messaging. It is recommended that you note throughout your document where further results interpretation is needed upon document finalization. Useful formatting tips include:

+ +

To assist with discussions and interpretations, the values that have been calculated or used in the R chunks can be directly imported into the text, for example, the top row of Table 1 shows that is the SOC regimen QALYs outcome value is 7.88 (7.08, 8.70).

+
+ + + + +
+ + + + + + + + + + + + + + + diff --git a/inst/examples/IndivCtstm_app/pdf-report.Rmd b/inst/examples/IndivCtstm_app/pdf-report.Rmd new file mode 100644 index 00000000..858167fe --- /dev/null +++ b/inst/examples/IndivCtstm_app/pdf-report.Rmd @@ -0,0 +1,163 @@ +--- +title: "hesim pdf report" +author: "Example using IndivCtstm" +date: "`r format(Sys.time(), '%d %B %Y')`" +output: + bookdown::pdf_document2: + number_sections: no + fig_caption: yes +header-includes: + - \usepackage{float} + - \usepackage{lscape} + - \newcommand{\blandscape}{\begin{landscape}} + - \newcommand{\elandscape}{\end{landscape}} +fontsize: 11pt +sansfont: Calibri Light +# fontfamily: newcent +# spacing: double +endnote: no +always_allow_html: true +params: + Stateprobs: "params$Stateprobs" + Summarisedf: "params$Summarisedf" + labs_indiv: "params$labs_indiv" +--- + +```{r setup, echo=FALSE} +knitr::opts_chunk$set( + cache = FALSE, + message = FALSE, + warning = FALSE, + fig.height = (12 / 2.5), + fig.width = (18 / 2.5), + dpi = 350, + pdf(encoding = "ISOLatin9.enc") +) +``` + +\newpage + +# Introduction + +Producing automated reports for modelers and users is possible using R Markdown. This enables you to focus the writing of technical reports on the story surrounding the results and ensures that the outputs match the model. R Markdown has several features that make it ideal for this purpose: + +1. Links directly to the code within the text and outputs +2. Allows passing of information from an R Shiny app to the markdown document script for rendering an up-to-date report +3. Reasonably flexible with respect to formatting, including tables, figures, Microsoft Word templates and so on +4. Easy to use and to understand the script documents +5. Allows presentation of the code used to generate a rendered output for simple and effective QC, communication and general transparency + +The majority of any R Markdown document will be raw text, though the front matter may be the most important part of the document. The document will be generated that includes both content as well as the output of any embedded R code chunks within the document. There are a lot of cheat sheets and reference guides for Markdown and bookdown (e.g. [Yihui Xie](https://bookdown.org/yihui/rmarkdown-cookbook/), [Adam Prichard](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet)) + +The purpose of this report is to demonstrate the use of R Markdown through outputting the results of the `hesim` example model. + +# Results + +The results of the `hesim` example are passed to R Markdown via the `rmarkdown::render()` function. Within this function, `envir` is used to import the current user environment with loaded libraries. For instance, `ggplot2` was loaded in the main R script, so importing the script environment into R Markdown means it does not need to be loaded again here. This means that the data and values that were created in the R script are also loaded in. `params` can also be specified, which lists the data to be used in the report; this is particularly important if `rmarkdown::render()` is being called from a `shiny` application, as it may be that the outputs are dynamically generated. In this example, the state probability data frame, the summary data frame with the discounted outcomes, and the state and strategy labels were passed to R Markdown via the code below. The differences in how the information is passed from within the R script and from within the `shiny` application are shown. + +In the code below, the `input` refers to the .Rmd file (this file), which lays out the R Markdown document. The output The `output_format` is the selected format of the document, in this case `"html_document"` is used to create a html output (see [other options](https://rmarkdown.rstudio.com/lesson-9.html)). `output_file` refers to the name of the output to be created, which needs to be consistent with the output format. + + + +***Gathering results from R script:*** +```markdown + +Note: This code chunk uses markdown instead of r. markdown shows the script +without running it, whereas r runs the script. Both markdown and r code chunks +look the same when rendered into the document + + Export_params <- list( + # Main results + Stateprobs = ictstm$stateprobs_, + Summarisedf = ce_sim_ictstm, + labs_indiv = labs_indiv + ) + + # pdf document + rmarkdown::render( + input = "./hesim pdf report.Rmd", + output_format = 'bookdown::pdf_document2', + output_file = "hesim-pdf-report.pdf", + params = Export_params, + envir = environment() + ) + +``` + +***Gathering results from R shiny app:*** +```markdown + + output$Create_pdfreport <- downloadHandler( + filename = "hesim-pdf-report.pdf", + content = function(file) { + + ce_sim_ictstm <- ictstm()$summarize() + + Export_params <- list( + # Main results + Stateprobs = ictstm()$stateprobs_, + Summarisedf = ce_sim_ictstm, + labs_indiv = labs_indiv + ) + + # html document + rmarkdown::render( + input = "./hesim pdf report.Rmd", + output_format = 'bookdown::pdf_document2', + output_file = file, + params = Export_params, + envir = environment() + ) + } + ) + +``` + +The two subsections below (as denoted by the `##` in the .Rmd script) below show how inputs from the main model can be used within the document + +## State transition probabilities + +The code below is an r chunk, which means that is it run as the R Markdown document renders. It will therefore return the outputs of the code. `print(params$Stateprobs)` is called below, which prints the value of `params$Stateprobs`. If `echo = TRUE` is specified at the top of the chunk, then the code is also printed into the document. + +```{r FigStateTransitionTable, echo = TRUE} +print(params$Stateprobs) + +``` + +\ + +Figures can be printed into the document within the r chunks in exactly the same way as they are called in the main R script. + +```{r FigStateTransitionPlot, echo = TRUE, fig.cap="State transition probabilities over time"} +autoplot(params$Stateprobs, labels = params$labs_indiv, + ci = FALSE) + theme_bw() + ggplot2::theme(legend.position = "bottom") + +``` + +## Cost and survival summary + +Tables can also be displayed in R Markdown documents in a similar way to figures. The `kableExtra` package can be used with `knitr` to format tables in the desired way. + +Note that the `echo = FALSE` parameter can be added to code chunks to prevent printing of the R code that generated the output. + +\newpage +\blandscape +```{r TableSummary, echo = FALSE} +Tableout <- summary(params$Summarisedf, labels = params$labs_indiv) %>% format() +kbl(Tableout, booktabs = T, position = "!ht", centering = T, caption = "Summary of total costs and QALYs") %>% + kable_styling(latex_options = "hold_position") + +``` +\elandscape + +\newpage +# Discussion +The purpose of R Markdown is to make reporting from R automated and accessible for modelers and intended audience. However, it is always important to leave room for thoughtful interpretation and messaging. It is recommended that you note throughout your document where further results interpretation is needed upon document finalization. Useful formatting tips include: + +\definecolor{colourred}{RGB}{255, 56, 56} +- Single asterisks italicize text *like this*. +- Double asterisks embolden text **like this**. +- Use \textcolor{colourred}{text colour} to mark sections + +To assist with discussions and interpretations, the values that have been calculated or used in the R chunks can be directly imported into the text, for example, the top row of Table 1 shows that is the `r colnames(Tableout)[3]` regimen `r Tableout[1,2]` outcome value is `r Tableout[1,3]`. + diff --git a/inst/examples/IndivCtstm_app/pdf-report.pdf b/inst/examples/IndivCtstm_app/pdf-report.pdf new file mode 100644 index 00000000..5d093927 Binary files /dev/null and b/inst/examples/IndivCtstm_app/pdf-report.pdf differ diff --git a/inst/examples/IndivCtstm_app/script.R b/inst/examples/IndivCtstm_app/script.R new file mode 100644 index 00000000..d8f9383e --- /dev/null +++ b/inst/examples/IndivCtstm_app/script.R @@ -0,0 +1,306 @@ +#Individual continuous time state transition model example +#Example based on 'hesim: Health Economic Simulation Modeling and Decision Analysis' by Davin Incerti and Jeroen Jansen +#https://www.researchgate.net/publication/349424271_hesim_Health_Economic_Simulation_Modeling_and_Decision_Analysis/link/605c068192851cd8ce65e830/download + +# Adapted by Rose Hart +#' The purpose of this script is to run all the functionality and design all of the graphs externally to the shiny app. +#' This makes the individual processes of the model easier to follow. The server.R script is then generated by wrapping +#' the functionality with shiny functions. Adaptations to the application can also be tested here before applying to the +#' main application + +# Load packages --------------- +# These will need installing if they have not been used before +# install.packages("hesim") +# install.packages("data.table") +# install.packages("flexsurv") +# install.packages("survminer") +# install.packages("heemod") +# install.packages("magrittr") +library(hesim) # Containing the mock trial data and the functions for model construction +library(data.table) # Used for organising the data in this example +library(flexsurv) # used for fitting parametric models to the trial data +library(survminer) # useful for easily presenting Kaplan–Meier plots. It also loads `ggplot2` as a dependent, which is a versatile package for producing + # almost any type of graph +library(heemod) # Can produce a really simple model diagram - also has other useful + # functions for partitioned survival modelling +library(diagram) # Assists with creating the diagram from heemod +library(magrittr) # Structuring data sequences with left -> right formatting instead of nested functions + + +# Setwd --------------- +# setwd for generating markdown reports +# setwd() + +# Informing inputs -------------- +# ~ States and transitions --------- +# ~~ Define matrix --------------- +tmat <- rbind( + c(NA, 1, 2), + c(NA, NA, 3), + c(NA, NA, NA) + ) +colnames(tmat) <- rownames(tmat) <- c("Stable", "Progression", "Death") +print(tmat) + +# ~~ Define transitions --------------- +transitions <- create_trans_dt(tmat)# +print(transitions) + +# This uses heemod functions to create a neat and simple model diagram for the app +Model_Diagram <- define_transition( #this function is part of the heemod package + state_names = c("Stable", "Progression", "Death"), + Stable,transition_id_1, transition_id_2, + ,Progressed, transition_id_3, + , , Death +) +plot(Model_Diagram) + +# ~~ Outline states and IDs in separate table for easy referencing -------------- +# Death is automatically added by get_labels() (below) in the code below in the default settings, +# but 'death_label = NULL' argument in get_labels() this will override this. Current setup is to maintain simplicity +states <- data.table( + state_id = 1:2, + state_name = c("Stable", "Progression") +) + + +# ~ Strategies ---------------------- +# ~~ Outline strategy and IDs ---------------- +strategies <- data.table( + strategy_id = 1:3, + strategy_name = c("SOC", "New 1", "New 2") + ) + +print(strategies) + +# ~ Patients ------------- +# ~~ Create patient sample to model ------------- +n_patients <- 1000 +patients <- data.table( + patient_id = 1:n_patients, + age = rnorm(n_patients, mean = 45, sd = 7), + female = rbinom(n_patients, size = 1, prob = .51) +) +# If groups are wanted, these can be defined in the 'grp_id' and 'grp_name' columns. Otherwise can be commented and left blank. +# patients[, grp_id := ifelse(female == 1, 1, 2)] +# patients[, grp_name := ifelse(female == 1, "Female", "Male")] + +#This is a plot to show the patient samples - it is an example of how ggplot can be used. +Patient_plot <- ggplot(patients, aes(x = age, fill = as.factor(female))) + + geom_histogram(binwidth = 1, colour = "#959595") + + theme_bw() + + scale_fill_manual("Gender:", values = c("#0D8E1E","#9552BB"), + labels = c("Male","Female")) + +Patient_plot + +# ~ Organising basic model settings ------------ +# ~~ Create hesim data object ----------- +hesim_dat <- hesim_data( + strategies = strategies, + patients = patients, + states = states, + transitions = transitions + ) + +print(hesim_dat) + +# ~~ Setting up labels for state and strategy IDs --------------- +labs_indiv <- get_labels(hesim_dat) +print(labs_indiv) + +# ~ 'Trial' data ---------- +# hesim package includes the 'onc3' data.table. This separates the three transitions by 'transition_id', where the IDs match the 'transitions' data +# These individual transitions can be filtered for and have parametric models fitted +# Data example showing patients 1 and 2: +onc3[patient_id %in% c(1, 2)] + +#view the data +transition_id_view <- 1 +TransitionData <- + survfit(as.formula(Surv(time, status) ~ strategy_name), data = onc3[which(transition_id == transition_id_view),]) + +trialdata_plot <- ggsurvplot( + fit = TransitionData, + data = onc3, + # break.y.by = 0.1, + # break.x.by = 0.5, + xlab = 'Time (Years)', + #xlim = c(0,5), + ylab = 'Survival', + #palette=c("red","blue","green"), + risk.table = TRUE, + #risk.table.y.text.col = TRUE, + #risk.table.height = 0.3, + #risk.table.title = 'Number at risk', + #conf.int = T, + #linetype = c(1,2), + legend = "top" +) +trialdata_plot + +# ~~ Fit the survival data ------------------ +n_trans <- max(tmat, na.rm = TRUE) +wei_fits <- vector(length = n_trans, mode = "list") +f <- as.formula(Surv(time, status) ~ factor(strategy_name) + female + age) + + +for (i in 1:length(wei_fits)){ + if (i == 3) {f <- update(f, .~.-factor(strategy_name))} + wei_fits[[i]] <- flexsurvreg(f, data = onc3, + subset = (transition_id == i), + dist = "weibull") +} + +wei_fits <- flexsurvreg_list(wei_fits) + +# ~ Costs --------------------- +# ~~ Create time-dependent drug costs per strategy -------------- +# The time units are in years. +drugcost_dt <- matrix(c( + 1, 1, 1, 0.00, 0.25, 2000, + 1, 1, 2, 0.25, Inf, 2000, + 1, 2, 1, 0.00, 0.25, 1500, + 1, 2, 2, 0.25, Inf , 1200, + 2, 1, 1, 0.00, 0.25, 12000, + 2, 1, 2, 0.25, Inf , 12000, + 2, 2, 1, 0.00, 0.25, 1500, + 2, 2, 2, 0.25, Inf , 1200, + 3, 1, 1, 0.00, 0.25, 15000, + 3, 1, 2, 0.25, Inf , 15000, + 3, 2, 1, 0.00, 0.25, 1500, + 3, 2, 2, 0.25, Inf , 1200 +),byrow = TRUE, ncol = 6, dimnames = list(NULL, c("strategy_id", "state_id", "time_id", "time_start", "time_stop","est"))) +drugcost_dt <- data.table(drugcost_dt) +print(drugcost_dt) + +drugcost_tbl <- stateval_tbl( + drugcost_dt, + dist = "fixed") +print(drugcost_tbl) + +# ~~ Medical costs --------------- +medcost_tbl <- stateval_tbl( + data.table(state_id = states$state_id, + mean = c(2000, 9500), + se = c(2000, 9500) + ), + dist = "gamma") +print(medcost_tbl) + +# ~ Utilities ---------------- +utility_tbl <- stateval_tbl( + data.table(state_id = states$state_id, + mean = c(.8, .6), + se = c(0.02, .05) + ), + dist = "beta") +print(utility_tbl) + + + +# Setting up the model -------------- +# ~ Number of parameter samples is needed to use for the PSA +n_samples <- 1000 + +# ~ Expanding the data input dataframe to set up for running all patients with all strategies +transmod_data <- expand(hesim_dat, + by = c("strategies", "patients")) +head(transmod_data) + +# ~ Wrapping inputs in hesim functions for use in model ------------- +# ~~ Efficacy ----------------- +transmod <- create_IndivCtstmTrans(object = wei_fits, + input_data = transmod_data, + trans_mat = tmat, n = n_samples, + uncertainty = "normal", + clock = "reset", + start_age = patients$age) + +# ~~ Utilities ----------------- +utilitymod <- create_StateVals(utility_tbl, n = n_samples, + hesim_data = hesim_dat) + +# ~~ Costs ------------------ +drugcostmod <- create_StateVals(drugcost_tbl, n = n_samples, + time_reset = TRUE, hesim_data = hesim_dat) +medcostmod <- create_StateVals(medcost_tbl, n = n_samples, + hesim_data = hesim_dat) +costmods <- list(Drug = drugcostmod, + Medical = medcostmod) + +# ~ Combining input into economic model ------------------- +ictstm <- IndivCtstm$new(trans_model = transmod, + utility_model = utilitymod, + cost_models = costmods) + + +# Run the disease simulation ---------------- +# ~ Run simulation ------------- +# This runs the disease simulation, and assumed that the max patient age is 100 (after which they automatically transfer to 'Death' state) +ictstm$sim_disease(max_age = 100, progress = TRUE) +# This is the event data simulated for each patient +head(ictstm$disprog_) + +# ~ Generate outcomes -------------- +# ~~ Survival -------------- +# Create survival curves with set time intervals +# Time is in years, so this will measure from 0 to 30 years, with 1/12 (1 month) intervals +ictstm$sim_stateprobs(t = seq(0, 30 , 1/12)) +head(ictstm$stateprobs_) + +Results_plot <- autoplot(ictstm$stateprobs_, labels = labs_indiv, + ci = FALSE) + theme_bw() + +Results_plot + +# ~~ QALYS ------------- +# QALYs and costs are simulated separately from the simulation of the disease +ictstm$sim_qalys(dr = c(0,.03)) +head(ictstm$qalys_) + +# ~~ Costs ------------ +ictstm$sim_costs(dr = c(0,.01)) +head(ictstm$costs_) + + +# ~ Summarize ---------------- +ce_sim_ictstm <- ictstm$summarize() + +summary(ce_sim_ictstm, labels = labs_indiv) %>% + format() + + +# REPORT ------------------------ +library(rmarkdown) # For creating markdown outputs (html and pdf) +library(bookdown) # For creating markdown outputs (html and pdf) +library(knitr) # For creating markdown outputs (html and pdf) +library(kableExtra) # For creating nice-looking tables in rmarkdown + +Export_params <- list( + # Main results + Stateprobs = ictstm$stateprobs_, + Summarisedf = ce_sim_ictstm, + labs_indiv = labs_indiv +) + +Markdown_location <- "./inst/examples/IndivCtstm_app" + +# html document +rmarkdown::render( + input = file.path(Markdown_location,"html-report.Rmd"), + output_format = 'bookdown::html_document2', + output_file = "./inst/examples/IndivCtstm_app/html-report.html", + params = Export_params, + envir = environment() +) + +# pdf document +rmarkdown::render( + input = file.path(Markdown_location,"pdf-report.Rmd"), + output_format = 'bookdown::pdf_document2', + output_file = "./inst/examples/IndivCtstm_app/pdf-report.pdf", + params = Export_params, + envir = environment() +) + diff --git a/inst/examples/IndivCtstm_app/server.R b/inst/examples/IndivCtstm_app/server.R new file mode 100644 index 00000000..62e8e917 --- /dev/null +++ b/inst/examples/IndivCtstm_app/server.R @@ -0,0 +1,496 @@ +#The server.R script is the model functionality. It is laid out in the same way as the 'hesim example model.R' script +# Unlike the 'hesim example model.R' script, the server takes in inputs from the 'inputs' defined in the ui.R, and used these +# in the calculations. It then produced the 'outputs' as defined in the ui.R, these are rendered here to appear in the +# shiny model graphical user interface + +library("shiny") +options(encoding = "UTF-8") + + +server <- function(input, output, session) { + # Informing inputs -------------- + # ~ states and transitions --------- + # ~~ Define matrix --------------- + tmat <- rbind( + c(NA, 1, 2), + c(NA, NA, 3), + c(NA, NA, NA) + ) + colnames(tmat) <- rownames(tmat) <- c("Stable", "Progression", "Death") + #print(tmat) + + # ~~ Define transitions --------------- + transitions <- create_trans_dt(tmat) + + # ~~ Outline states and IDs in separate table for easy referencing -------------- + # Death is automatically added by get_labels() (below) in the code below in the default settings, + # but 'death_label = NULL' argument in get_labels() this will override this. Current setup is to maintain simplicity + states <- data.table( + state_id = 1:2, + state_name = c("Stable", "Progression") + ) + + #I have added an extra table here to present in output$state_out. Remember, the front-end user cannot see the back-end + # comments, so as much information needs to be made available front end as possible + states_wDeath <- data.table( + state_id = 1:3, + state_name = c("Stable", "Progression", "Death") + ) + + # ~~ Output to shiny ----------- + output$state_out <- renderTable( + states_wDeath, + striped = TRUE, + digits = 0, + bordered = TRUE, + colnames = TRUE, + sanitize.text.function = function(x) x) + + output$tmat_out <- renderTable( + tmat, + striped = TRUE, + digits = 0, + bordered = TRUE, + colnames = TRUE, + rownames = TRUE, + sanitize.text.function = function(x) x) + + output$transitions_out <- renderTable( + transitions, + striped = TRUE, + digits = 0, + bordered = TRUE, + colnames = TRUE, + sanitize.text.function = function(x) x) + + Model_Diagram <- define_transition( #this function is part of the heemod package + state_names = c("Stable", "Progression", "Death"), + Stable,transition_id_1, transition_id_2, + ,Progressed, transition_id_3, + , , Death + ) + + output$diagram <- renderPlot({ + plot(Model_Diagram) + }) + + + # ~ Strategies ---------------------- + # ~~ Outline strategy and IDs ---------------- + strategies <- data.table( + strategy_id = 1:3, + strategy_name = c("SOC", "New 1", "New 2") + ) + + # ~~ Output to shiny ------------- + + output$strategies_out <- renderTable( + strategies, + striped = TRUE, + digits = 0, + bordered = TRUE, + colnames = TRUE, + sanitize.text.function = function(x) x) + + # ~ Patients ------------- + # ~~ Create patient sample to model ------------- + n_patients <- 1000 + patients <- data.table( + patient_id = 1:n_patients, + age = rnorm(n_patients, mean = 45, sd = 7), + female = rbinom(n_patients, size = 1, prob = .51) + ) + # If groups are wanted, these can be defined in the 'grp_id' and 'grp_name' columns. Otherwise can be commented and left blank. + # patients[, grp_id := ifelse(female == 1, 1, 2)] + # patients[, grp_name := ifelse(female == 1, "Female", "Male")] + + + # ~~ Output to shiny ------------- + + output$Patient_number <- renderText( + HTML("The number of patients simulated for this model is: ",n_patients,"") + ) + + output$Patient_hist <- renderPlot( + ggplot(patients, aes(x = age, fill = as.factor(female))) + + geom_histogram(binwidth = 1, colour = "#959595") + + theme_bw() + + scale_fill_manual("Gender:", values = c("#0D8E1E","#9552BB"), labels = c("Male","Female")) + ) + + # ~ Organising basic model settings ------------ + # ~~ Create hesim data object ----------- + hesim_dat <- hesim_data( + strategies = strategies, + patients = patients, + states = states, + transitions = transitions + ) + + #print(hesim_dat) + + # ~~ Setting up labels for state and strategy IDs --------------- + labs_indiv <- get_labels(hesim_dat) + #print(labs_indiv) + + # ~ 'Trial' data ---------- + # hesim package includes the 'onc3' data.table. This separates the three transitions by 'transition_id', where the IDs match the 'transitions' data + # These individual transitions can be filtered for and have parametric models fitted + # Data example showing patients 1 and 2: + # onc3[patient_id %in% c(1, 2)] + + # ~~ Fit the survival data ------------------ + n_trans <- max(tmat, na.rm = TRUE) + wei_fits <- vector(length = n_trans, mode = "list") + f <- as.formula(Surv(time, status) ~ factor(strategy_name) + female + age) + + for (i in 1:length(wei_fits)){ + if (i == 3) {f <- update(f, .~.-factor(strategy_name))} + wei_fits[[i]] <- flexsurvreg(f, data = onc3, + subset = (transition_id == i), + dist = "weibull") + } + + wei_fits <- flexsurvreg_list(wei_fits) + + # ~~ Output to shiny ------------- + output$Trial_data_plot <- renderPlot({ + req(input$trial_trans_input) + + transition_id_view <- input$trial_trans_input + TransitionData <- survfit(as.formula(Surv(time, status) ~ strategy_name), data = onc3[which(transition_id == transition_id_view), ]) + ggsurvplot( + fit = TransitionData, + data = onc3, + # break.y.by = 0.1, + # break.x.by = 0.5, + xlab = 'Time (Years)', + #xlim = c(0,5), + ylab = 'Survival', + #palette=c("red","blue","green"), + risk.table = TRUE, + #risk.table.y.text.col = TRUE, + #risk.table.height = 0.3, + #risk.table.title = 'Number at risk', + #conf.int = T, + #linetype = c(1,2), + legend = "top" + ) + }) + + # ~ Costs --------------------- + # ~~ Create time-dependent drug costs per strategy -------------- + # The time units are in years. + drugcost_dt <- matrix(c( + 1, 1, 1, 0.00, 0.25, 2000, + 1, 1, 2, 0.25, Inf, 2000, + 1, 2, 1, 0.00, 0.25, 1500, + 1, 2, 2, 0.25, Inf , 1200, + 2, 1, 1, 0.00, 0.25, 12000, + 2, 1, 2, 0.25, Inf , 12000, + 2, 2, 1, 0.00, 0.25, 1500, + 2, 2, 2, 0.25, Inf , 1200, + 3, 1, 1, 0.00, 0.25, 15000, + 3, 1, 2, 0.25, Inf , 15000, + 3, 2, 1, 0.00, 0.25, 1500, + 3, 2, 2, 0.25, Inf , 1200 + ),byrow = TRUE, ncol = 6, dimnames = list(NULL, c("strategy_id", "state_id", "time_id", "time_start", "time_stop","est"))) + drugcost_dt <- data.table(drugcost_dt) + #print(drugcost_dt) + + drugcost_tbl <- stateval_tbl( + drugcost_dt, + dist = "fixed") + #print(drugcost_tbl) + + # ~~ Medical costs --------------- + medcost_tbl <- stateval_tbl( + data.table(state_id = states$state_id, + mean = c(2000, 9500), + se = c(2000, 9500) + ), + dist = "gamma") + #print(medcost_tbl) + + # ~~ Output to shiny ------------- + + output$Drugcost_out <- renderTable( + drugcost_tbl, + striped = TRUE, + bordered = TRUE, + colnames = TRUE, + sanitize.text.function = function(x) x) + + output$Medcost_out <- renderTable( + medcost_tbl, + striped = TRUE, + bordered = TRUE, + colnames = TRUE, + sanitize.text.function = function(x) x) + + # ~ Utilities ---------------- + utility_tbl <- stateval_tbl( + data.table(state_id = states$state_id, + mean = c(.8, .6), + se = c(0.02, .05) + ), + dist = "beta") + + # ~~ Output to shiny ------------- + # ANSWER CODE CHANGES ARE HERE ---------------------------- + output$Utility_out <- renderTable( + utility_tbl, + striped = TRUE, + bordered = TRUE, + colnames = TRUE, + sanitize.text.function = function(x) x) + #print(utility_tbl) + + + # Setting up the model -------------- + # ~ Taking in inputs from shiny interface --------------------------- + # ~~ Number of parameter samples is needed to use for the PSA + + # All of these elements are reactive, so they change whenever they are interacted with. You can view the + # value changing and printing to the R console with an observe() (see below) + n_samples <- reactive({ + req(input$Input_nSamples) + input$Input_nSamples + }) + + # You can have an observe to print input$Input_nSamples to the console as feedback + #observe({print(paste0("The current number of samples is: ", input$Input_nSamples))}) + + # ~~ Years in time horizon + n_years <- reactive({ + req(input$Input_timehorizon) + input$Input_timehorizon + }) + + # ~~ Discount QALY + disc_QALY <- reactive({ + req(input$Input_discount_QALY) + input$Input_discount_QALY/100 + }) + + # ~~ Discount costs + disc_Cost <- reactive({ + req(input$Input_discount_Costs) + input$Input_discount_Costs/100 + }) + + + # ~ Expanding the data input dataframe to set up for running all patients with all strategies + transmod_data <- expand(hesim_dat, + by = c("strategies", "patients")) + head(transmod_data) + + # ~ Wrapping inputs in hesim functions for use in model ------------- + # ~~ Efficacy ----------------- + # these objects contain reactive data (e.g. n_samples()), so therefore need to be reactive themselves + transmod <- reactive(create_IndivCtstmTrans(wei_fits, transmod_data, + trans_mat = tmat, n = n_samples(), + uncertainty = "normal", + clock = "reset", + start_age = patients$age)) + + # ~~ Utilities ----------------- + utilitymod <- reactive(create_StateVals(utility_tbl, n = n_samples(), + hesim_data = hesim_dat)) + + # ~~ Costs ------------------ + drugcostmod <- reactive(create_StateVals(drugcost_tbl, n = n_samples(), + time_reset = TRUE, hesim_data = hesim_dat)) + medcostmod <- reactive(create_StateVals(medcost_tbl, n = n_samples(), + hesim_data = hesim_dat)) + costmods <- reactive(list(Drug = drugcostmod(), + Medical = medcostmod())) + + # Run the disease simulation ---------------- + + # ~ Combining input into economic model ------------------- + + # The above inputs are reactive() so they are updated any time the model inputs are changed. + # The script below runs only when the input$Run_model is clicked because it is eventReactive() + ictstm <- eventReactive(input$Run_model, { + + #Keeping all the hesim arguments bundled in a single expression means that the outputs will + # always be consistent and created at the same time + + #Each of the ictstm arguments in the original 'hesim example model.R' script are called here + # as ictstm_sub, then at the end, ictstm_sub is outputted and becomes the name of the eventReactive element + # which in this case is ictstm. + + ictstm_sub <- IndivCtstm$new(trans_model = transmod(), + utility_model = utilitymod(), + cost_models = costmods()) + + # Environment objects are not functions so do not require brackets () after them - if you are not including R6 class + #objects in your model then you will need to use brackets for all reactive data as it is now a reactive function + + # ~ Combining input into economic model ------------------- + + #This shows a notification to let the user know in the front-end that the model is running, as this can take a little while + showNotification( + paste("Running model, this will take a few moments..."), + id = "RunNotification", + duration = NULL, + type = "message" + ) + + # ~ Run simulation ------------- + # This runs the disease simulation, and assumed that the max patient age is 100 (after which they automatically transfer to 'Death' state) + + ictstm_sub$sim_disease(max_age = 100) + + # ~ Generate outcomes -------------- + # ~~ Survival -------------- + # Create survival curves with set time intervals + # Time is in years, so this will measure from 0 to 30 years, with 1/12 (1 month) intervals + ictstm_sub$sim_stateprobs(t = seq(0, n_years() , 1 / 12)) + + # ~~ QALYS ------------- + # QALYs and costs are simulated separately from the simulation of the disease + ictstm_sub$sim_qalys(dr = c(0,disc_QALY())) + + # ~~ Costs ------------ + ictstm_sub$sim_costs(dr = c(0,disc_Cost())) + + # The model calculations are now completed so the notification can be removed + removeNotification("RunNotification") + + # This outputs the ictstm_sub, this is like returning an object from a function. This eventReactive() + # element that this is wrapped in is called ictstm, so this is essentially saying ictstm <- ictstm_sub + return(ictstm_sub) + + }) + + + + # ~ Output to shiny --------------------------- + + # This will output the live ictstm() results (note the brackets are added to ictstm() because it is reactive) + # which will mean that it will update after every time the model is run. The render...() functions work like reactive() + # functions + output$Results_DT <- renderDataTable({ + req(input$Run_model >= 1) + req(!is.null(ictstm()$costs_)) + + ce_sim_ictstm <- ictstm()$summarize() + ce_sim_ictstm <- summary(ce_sim_ictstm, labels = labs_indiv) %>% + format() + + datatable( + data = ce_sim_ictstm, + rownames = FALSE, + # There are a lot of options available within datatable, such as search bars, ordering and paging options. + # Set these to TRUE to see what they do + options = list( + lengthChange = FALSE, + paging = FALSE, + searching = FALSE, + info = TRUE, + ordering = FALSE, + scrollX = FALSE, + autoWidth = TRUE + ) + ) + }) + + output$Results_graph <- renderPlot({ + req(input$Run_model >= 1) + + autoplot(isolate(ictstm()$stateprobs_), labels = labs_indiv, + ci = FALSE) + theme_bw() + }) + + output$Results_text <- renderText({ + req(input$Run_model >= 1) + HTML("The results displayed here are based on ",n_patients," sampled patients with",isolate(n_samples()),"probabilistic samples using the input data displayed." ) + }) + + # ~ Create report ------------------- + # This location is relative to the location of app.R + Markdown_location <- "./" + + # ANSWER CODE CHANGES HERE ----------------------------- + # Model_Diagram added to the Export_params for html and pdf document + + output$Create_htmlreport <- downloadHandler( + filename = "html-report_shiny.html", + content = function(file) { + + + # Create a notification in front-end to show this is happening + showNotification( + paste("Creating html report, this will take a few moments..."), + id = "HTMLNotification", + duration = NULL, + type = "message" + ) + # Make sure it closes when we exit this reactive, even if there's an error + on.exit(removeNotification("HTMLNotification")) + + ce_sim_ictstm <- ictstm()$summarize() + + Export_params <- list( + # Main results + Stateprobs = ictstm()$stateprobs_, + Summarisedf = ce_sim_ictstm, + labs_indiv = labs_indiv + ) + + # html document + rmarkdown::render( + input = file.path(Markdown_location,"html-report.Rmd"), + output_format = 'bookdown::html_document2', + output_file = file, + params = Export_params, + envir = environment() + ) + } + ) + + output$Create_pdfreport <- downloadHandler( + filename = "pdf-report_shiny.pdf", + content = function(file) { + + # Create a notification in front-end to show this is happening + showNotification( + paste("Creating pdf report, this will take a few moments..."), + id = "PDFNotification", + duration = NULL, + type = "message" + ) + # Make sure it closes when we exit this reactive, even if there's an error + on.exit(removeNotification("PDFNotification")) + + ce_sim_ictstm <- ictstm()$summarize() + + Export_params <- list( + # Main results + Stateprobs = ictstm()$stateprobs_, + Summarisedf = ce_sim_ictstm, + labs_indiv = labs_indiv + ) + + # pdf document + rmarkdown::render( + input = file.path(Markdown_location,"pdf-report.Rmd"), + output_format = 'bookdown::pdf_document2', + output_file = file, + params = Export_params, + envir = environment() + ) + } + ) + + + #Click the model on start-up + observe({ + if(input$Run_model == 0){ + click("Run_model") + } + }) + +} \ No newline at end of file diff --git a/inst/examples/IndivCtstm_app/ui.R b/inst/examples/IndivCtstm_app/ui.R new file mode 100644 index 00000000..f1ac9ba0 --- /dev/null +++ b/inst/examples/IndivCtstm_app/ui.R @@ -0,0 +1,176 @@ +# The UI.R script contains the ui, this is the layout of the graphical user interface (GUI) of your app +# This can be read linearly, going through content positioning tab by tab + +# Load packages --------------- +# Packages will need installing if they have not been installed before (use install.packages()) +# Packages can be defined in either the server.R or ui.R scripts, but ui.R is read first +library(shiny) # Shiny package to produce the app +library(shinydashboard) # Functions to give the app a tabbed layout +library(hesim) # Required for the model functionality (see the 'hesim example model.R script') +library(data.table) # Required for the model functionality (see the 'hesim example model.R script') +library(flexsurv) # Required for the model functionality (see the 'hesim example model.R script') +library(ggplot2) # Required for creating graphs +library(magrittr) # Required for the model functionality (see the 'hesim example model.R script') +library(shinyWidgets) # Used for creating lovely input options (in this case the % on the discount) + # see http://shinyapps.dreamrs.fr/shinyWidgets/ to see examples +library(rmarkdown) # For creating markdown outputs (html and pdf) +library(bookdown) # For creating markdown outputs (html and pdf) +library(knitr) # For creating markdown outputs (html and pdf) +library(kableExtra) # For creating nice-looking tables in rmarkdown +library(diagram) # Assists with creating the diagram from heemod +library(heemod) # Can produce a really simple model diagram - also has other useful functions for partitioned survival modelling +library(survminer) # useful for easily presenting Kaplan–Meier plots. +library(shinycssloaders) # Creates the loading animation +library(DT) # Creates datatables +library(shinyjs) # Adds functionality using a library of javascript functions. E.g. click() can be used to click + # buttons in the back end without user interaction. This is user in server.R to start the model calculations running + +options(encoding = "UTF-8") + +ui <- + #This app uses the shinydashboard package to create a layout - see https://rstudio.github.io/shinydashboard/ for details + dashboardPage( + # ~ Header ------------------- + dashboardHeader( + title = "", + titleWidth = 0 , + tags$li( + class = "dropdown", + style = " font-size: 16px; font-weight: bold;", + tags$a(("IndivCtstm demo shiny app")) + ) + ), + + # ~ Sidebar ------------------- + # This is not used in this model version, but can be added and laid out via the dashboardSidebar() function + dashboardSidebar(disable = TRUE), + + # ~ Body ------------------- + # Arranging the content and outputs within the headings and sub-headings + dashboardBody( + shinyjs::useShinyjs(), #this is needed to use the click() functions, and other functions used for enabling/disabling inputs + # ~~ Switches ------------------- + fluidRow( + box(width = 3, + title = "Switches", + status = "primary", + solidHeader = TRUE, + collapsible = TRUE, + sliderInput(inputId = "Input_nSamples", + label = "Number of probabilistic samples:", + min = 100, + max = 1000, + value = 100), + sliderInput(inputId = "Input_timehorizon", + label = "Enter time horizon (years):", + min = 10, + max = 30, + value = 30), + numericInputIcon( + inputId = "Input_discount_QALY", + label = "Discount for QALYs:", + min = 0, + max = 100, + value = 1, + icon = list(NULL, icon("percent")) + ), + numericInputIcon( + inputId = "Input_discount_Costs", + label = "Discount for Costs:", + min = 0, + max = 100, + value = 3.5, + icon = list(NULL, icon("percent")) + ), + column(12,hr()), + column(12, + actionButton("Run_model", + "Re-run the model", icon("sync"), + style = "color: #ffffff; background-color: #222D32; border-color: #1C75BB"), align = 'center'), + column(12,br()), + column(12, + downloadButton("Create_htmlreport", + "Create model html report", + style = "color: #ffffff; background-color: #222D32; border-color: #1C75BB"), align = 'center'), + column(12,br()), + column(12, + downloadButton("Create_pdfreport", + "Create model pdf report", + style = "color: #ffffff; background-color: #222D32; border-color: #1C75BB"), align = 'center') + ), + # ~~ Inputs ------------------- + tabBox( + title = "Inputs", + id = "Input_tabBox", + selected = "States and transitions", + width = 9,side = "right", + tabPanel(title = "Utilities", + # ANSWER CODE CHANGES ARE HERE ---------------------------- + fluidRow( + column(12,"Text can be written here to explain how the inputs are used if the coder chooses",br(),br()), + column(6, tags$u("Utility inputs"),br(),tableOutput("Utility_out")) + )), + tabPanel(title = "Costs", + fluidRow( + column(8, tags$u("Drug costs per strategy, state and time"),br(),tableOutput("Drugcost_out")), + column(4, tags$u("Medical costs per state"),br(),tableOutput("Medcost_out")) + )), + tabPanel(title = "Patients", + fluidRow( + column(12, + htmlOutput("Patient_number"), + plotOutput("Patient_hist")) + )), + tabPanel(title = "Trial data", + fluidRow( + column(12, + selectInput("trial_trans_input", + "Select transition to view data", + choices = c(1,2,3)), + withSpinner(# this is from the shinycssloaders package + plotOutput("Trial_data_plot", height = "500px"))) + )), + tabPanel(title = "Strategies", + fluidRow( + column(6, tags$u("Model strategies"),br(),tableOutput("strategies_out")) + )), + tabPanel(title = "Model diagram", + fluidRow( + align = "center", + plotOutput( + outputId = "diagram", + width = "620px", + height = "450px" + ) + )), + tabPanel(title = "States and transitions", + fluidRow( + column(6, tags$u("State names"),br(),tableOutput("state_out")), + column(6, tags$u("Transition matrix"),br(),tableOutput("tmat_out")), + column(6, tags$u("Transition IDs"),br(),tableOutput("transitions_out")) + )) + ), + # ~~ Results ------------------- + box( + title = "Results", + width = 12, + status = "primary", + solidHeader = TRUE, + collapsible = TRUE, + collapsed = FALSE, + fluidRow(column( + 12, + htmlOutput("Results_text"), br(),br(), + HTML("Survival outcomes "), + br(), + withSpinner(plotOutput("Results_graph")), + br(), + br(), + HTML("Summary table "), + br(), + withSpinner(dataTableOutput("Results_DT")) + )) + ) + ) + ) + ) \ No newline at end of file