Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ vignettes/*.pdf
# R Environment Variables
.Renviron

# pkgdown site
docs/

# translation temp files
po/*~

Expand Down
2 changes: 1 addition & 1 deletion CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ abstract: >-
Reproducible analytical pipeline (RAP) for R discrete-event simulation (DES)
implementing the Stroke Capacity Planning Model from Monks et al. 2016.
version: 0.1.0
date-released: '2025-06-30'
date-released: '2025-07-11'
8 changes: 8 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,11 @@
# Stroke capacity planning model: R DES RAP 0.1.0

🌱 First release of the R stroke model.

## New features

* Implementation of the stroke model in R as a package (`R/`).
* Reproduction of paper results (`rmarkdown/analysis.Rmd`).
* Other RMarkdown files to generate results for tests, demonstrate logging, and how parameters can be loaded from a csv (`rmarkdown/`).
* Back, functional and unit tests (`tests/`).
* Other features include continuous integration (tests and linting), checklists, R environment, and other metadata.
2 changes: 1 addition & 1 deletion R/create_asu_trajectory.R
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ create_asu_trajectory <- function(env, patient_type, param) {
los_params <- switch(
dest,
esd = param[["asu_los_lnorm"]][["stroke_esd"]],
rehab = param[["asu_los_lnorm"]][["stroke_noesd"]],
rehab = param[["asu_los_lnorm"]][["stroke_no_esd"]],
other = param[["asu_los_lnorm"]][["stroke_mortality"]],
stop("Stroke post-asu destination '", dest, "' invalid",
call. = FALSE)
Expand Down
2 changes: 1 addition & 1 deletion R/create_rehab_trajectory.R
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ create_rehab_trajectory <- function(env, patient_type, param) {
los_params <- switch(
dest,
esd = param[["rehab_los_lnorm"]][["stroke_esd"]],
other = param[["rehab_los_lnorm"]][["stroke_noesd"]],
other = param[["rehab_los_lnorm"]][["stroke_no_esd"]],
stop("Stroke post-rehab destination '", dest, "' invalid",
call. = FALSE)
)
Expand Down
16 changes: 8 additions & 8 deletions R/parameters.R
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ create_rehab_arrivals <- function(
#'
#' Mean and standard deviation (SD) of LOS in days in the ASU.
#'
#' @param stroke_noesd_mean Numeric. Mean LOS for stroke patients without early
#' @param stroke_no_esd_mean Numeric. Mean LOS for stroke patients without early
#' supported discharged (ESD).
#' @param stroke_noesd_sd Numeric. SD LOS for stroke patients without ESD.
#' @param stroke_no_esd_sd Numeric. SD LOS for stroke patients without ESD.
#' @param stroke_esd_mean Numeric. Mean LOS for stroke patients with ESD.
#' @param stroke_esd_sd Numeric. SD LOS for stroke patients with ESD.
#' @param stroke_mortality_mean Numeric. Mean LOS for stroke patients who pass
Expand All @@ -61,15 +61,15 @@ create_rehab_arrivals <- function(
#' @export

create_asu_los <- function(
stroke_noesd_mean = 7.4, stroke_noesd_sd = 8.61,
stroke_no_esd_mean = 7.4, stroke_no_esd_sd = 8.61,
stroke_esd_mean = 4.6, stroke_esd_sd = 4.8,
stroke_mortality_mean = 7.0, stroke_mortality_sd = 8.7,
tia_mean = 1.8, tia_sd = 2.3,
neuro_mean = 4.0, neuro_sd = 5.0,
other_mean = 3.8, other_sd = 5.2
) {
list(
stroke_noesd = list(mean = stroke_noesd_mean, sd = stroke_noesd_sd),
stroke_no_esd = list(mean = stroke_no_esd_mean, sd = stroke_no_esd_sd),
stroke_esd = list(mean = stroke_esd_mean, sd = stroke_esd_sd),
stroke_mortality = list(mean = stroke_mortality_mean,
sd = stroke_mortality_sd),
Expand All @@ -81,9 +81,9 @@ create_asu_los <- function(

#' Rehabilitation unit length of stay (LOS) distributions (days).
#'
#' @param stroke_noesd_mean Numeric. Mean LOS for stroke patients without early
#' @param stroke_no_esd_mean Numeric. Mean LOS for stroke patients without early
#' supported discharged (ESD).
#' @param stroke_noesd_sd Numeric. SD LOS for stroke patients without ESD.
#' @param stroke_no_esd_sd Numeric. SD LOS for stroke patients without ESD.
#' @param stroke_esd_mean Numeric. Mean LOS for stroke patients with ESD.
#' @param stroke_esd_sd Numeric. SD LOS for stroke patients with ESD.
#' @param tia_mean Numeric. Mean LOS for transient ischemic attack (TIA)
Expand All @@ -98,14 +98,14 @@ create_asu_los <- function(
#' @export

create_rehab_los <- function(
stroke_noesd_mean = 28.4, stroke_noesd_sd = 27.2,
stroke_no_esd_mean = 28.4, stroke_no_esd_sd = 27.2,
stroke_esd_mean = 30.3, stroke_esd_sd = 23.1,
tia_mean = 18.7, tia_sd = 23.5,
neuro_mean = 27.6, neuro_sd = 28.4,
other_mean = 16.1, other_sd = 14.1
) {
list(
stroke_noesd = list(mean = stroke_noesd_mean, sd = stroke_noesd_sd),
stroke_no_esd = list(mean = stroke_no_esd_mean, sd = stroke_no_esd_sd),
stroke_esd = list(mean = stroke_esd_mean, sd = stroke_esd_sd),
tia = list(mean = tia_mean, sd = tia_sd),
neuro = list(mean = neuro_mean, sd = neuro_sd),
Expand Down
47 changes: 40 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,45 @@ renv::snapshot()

The simulation code is in the `R/` folder as a local package. There are files executing the model and analysing the results in `rmarkdown/`.

To run the model with base parameters once or with replications:
**Install the local package:**

```{.r}
# TODO
devtools::install() # Needed if running in parallel
devtools::load_all() # Sufficient if running sequentially

library(simulation)
```

**Run a single simulation:**

```{.r}
param <- create_parameters(number_of_runs = 1L)
single_results <- runner(param = param)
```

Example altering the model parameters:
**Run multiple replications:**

```{.r}
# TODO
param <- create_parameters(number_of_runs = 5L)
single_results <- runner(param = param)
```

**Run all analyses (from command line):**

```{.r}
bash run_rmarkdown.sh
```

**Run tests:**

```{.r}
devtools::test()
```

**Lint code:**

```{.r}
lintr::lint_dir()
```

### Generating the results from the article
Expand All @@ -87,23 +116,27 @@ To generate these, simply execute `rmarkdown/analysis.Rmd`.

Original:

![](docs/article/fig1.png)

From this repository:

**TODO**
![](outputs/figure1_asu.png)

**Figure 3**

Original:

![](docs/article/fig3.png)

From this repository:

**TODO**
![](outputs/figure3_asu.png)

<br>

## Run time and machine specification

The run time for this analysis (`notebooks/analysis.Rm`) is **TODO** seconds. This was on an Intel Core i7-12700H, 32GB RAM, Ubuntu 24.04.1.
The run time for this analysis (`notebooks/analysis.Rmd`) is **1m 38s** seconds. This was on an Intel Core i7-12700H, 32GB RAM, Ubuntu 24.04.1.

The other notebooks generate results for tests and illustrate other functionality (e.g. importing parameters from csv, running with logs), and these just take a second or two.

Expand Down
Binary file added docs/article/article_monks_etal_2016.pdf
Binary file not shown.
Binary file added docs/article/fig1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/article/fig2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/article/fig3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/article/supplementary_monks_etal_2016.docx
Binary file not shown.
Binary file added docs/article/supplementary_monks_etal_2016.pdf
Binary file not shown.
38 changes: 38 additions & 0 deletions docs/heather_2025.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Reproducibility recommendations from Heather et al. 2025

As part of the project STARS (Sharing Tools and Artefacts for Reproducible Simulations), a series of computational reproducibility assessments were conducted by Heather et al. 2025 (**TODO: add DOI of pre-print**). From these, several recommendations were shared to support reproducibility of healthcare discrete-event simulation (DES) models. These are copied below. Those marked with a star (⭐) were identified as having the greatest impact in Heather et al. 2025.

## Recommendations to support reproduction

| Recommendation | Completion | Further details |
| - | - | - |
| **Set-up** |
| Share code with an open licence (⭐) | ✅ | `LICENSE` and `LICENSE.md` |
| Link publication to a specific version of the code | ✅ | - |
| List dependencies and versions | ✅ | `renv.lock` and `DESCRIPTION` |
| **Running the model** |
| Provide code for all scenarios and sensitivity analyses (⭐) | ✅ | `analysis.Rmd` |
| Ensure model parameters are correct (⭐) | ✅ | - |
| Control randomness | ✅ | - |
| **Outputs** |
| Include code to calculate all required model outputs (⭐) | ✅ | - |
| Include code to generate the tables, figures, and other reported results (⭐) | ✅ | `analysis.Rmd` |

## Recommendations to support troubleshooting and reuse

| Recommendation | Completion | Further details |
| - | - | - |
| **Design** |
| Separate model code from applications | ✅ | - |
| Avoid hard-coded parameters | ✅ | - |
| Minimise code duplication | ✅ | - |
| **Clarity** |
| Comment sufficiently | ✅ | - |
| Ensure clarity and consistency in the model results tables | ✅ | - |
| Include run instructions | ✅ | - |
| State run times and machine specifications | ✅ | In `README.md` and `.Rmd` files. |
| **Functionality** |
| Optimise model run time | ✅ | Provides option for parallel processing. |
| Save outputs to a file | ✅ | - |
| Avoid excessive output files | ✅ | - |
| Address large file sizes | N/A | - |
50 changes: 50 additions & 0 deletions docs/nhs_rap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# 'Levels of RAP' Maturity Framework

The following framework has been directly copied from the RAP Community of Practice repository/website: [NHS RAP Levels of RAP Framework](https://nhsdigital.github.io/rap-community-of-practice/introduction_to_RAP/levels_of_RAP/).

This framework is maintained by the NHS RAP Community of Practice and is © 2024 Crown Copyright (NHS England), shared by them under the terms of the [Open Government 3.0 licence](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/).

The specific version of the framework copied below is that from commit [2549256](https://github.com/NHSDigital/rap-community-of-practice/commit/2549256498886d6d7ea4cdb736e2a2864c8bb461) (9th September 2024).

## 🥉 Baseline

RAP fundamentals offering resilience against future change.

| Criteria | Completion | Further details |
| - | - | - |
| Data produced by code in an open-source language (e.g., Python, R, SQL). | ✅ | R |
| Code is version controlled (see [Git basics](https://nhsdigital.github.io/rap-community-of-practice/training_resources/git/introduction-to-git/) and [using Git collaboratively](https://nhsdigital.github.io/rap-community-of-practice/training_resources/git/using-git-collaboratively/) guides). | ✅ | [GitHub](https://github.com/pythonhealthdatascience/rdesrap_stroke) |
| Repository includes a README.md file (or equivalent) that clearly details steps a user must follow to reproduce the code (use [NHS Open Source Policy section on Readmes](https://github.com/nhsx/open-source-policy/blob/main/open-source-policy.md#b-readmes) as a guide). | ✅ | - |
| Code has been [peer reviewed](https://nhsdigital.github.io/rap-community-of-practice/implementing_RAP/workflow/code-review/). | ✅ | Peer reviewed by Tom Monks |
| Code is [published in the open](https://nhsdigital.github.io/rap-community-of-practice/implementing_RAP/publishing_code/how-to-publish-your-code-in-the-open/) and linked to & from accompanying publication (if relevant). | ✅ | - |

## 🥈 Silver

Implementing best practice by following good analytical and software engineering standards.

Meeting all of the above requirements, plus:https://github.com/pythonhealthdatascience/rdesrap_mms

| Criteria | Completion | Further details |
| - | - | - |
| Outputs are produced by code with minimal manual intervention. | ✅ | - |
| Code is well-documented including user guidance, explanation of code structure & methodology and [docstrings](https://nhsdigital.github.io/rap-community-of-practice/training_resources/python/python-functions/#documentation) for functions. | ✅ | - |
| Code is well-organised following [standard directory format](https://nhsdigital.github.io/rap-community-of-practice/training_resources/python/project-structure-and-packaging/). | ✅ | - |
| [Reusable functions](https://nhsdigital.github.io/rap-community-of-practice/training_resources/python/python-functions/) and/or classes are used where appropriate. | ✅ | - |
| Code adheres to agreed coding standards (e.g PEP8, [style guide for Pyspark](https://nhsdigital.github.io/rap-community-of-practice/training_resources/pyspark/pyspark-style-guide/)). | ✅ | - |
| Pipeline includes a testing framework ([unit tests](https://nhsdigital.github.io/rap-community-of-practice/training_resources/python/unit-testing/), [back tests](https://nhsdigital.github.io/rap-community-of-practice/training_resources/python/backtesting/)). | ✅ | `tests/` contains unit, functional and back tests. |
| Repository includes dependency information (e.g. [requirements.txt](https://pip.pypa.io/en/stable/user_guide/#requirements-files), [PipFile](https://github.com/pypa/pipfile/blob/main/README.rst), [environment.yml](https://nhsdigital.github.io/rap-community-of-practice/training_resources/python/virtual-environments/conda/)). | ✅ | `renv` |
| [Logs](https://nhsdigital.github.io/rap-community-of-practice/training_resources/python/logging-and-error-handling/) are automatically recorded by the pipeline to ensure outputs are as expected. | ✅ | - |
| Data is handled and output in a [Tidy data format](https://medium.com/@kimrodrikwa/untidy-data-a90b6e3ebe4c). | ✅ | Meets the requirements of tidy data (each variable forms a column, each observation forms a row, each type of observational unit forms a table). |

## 🥇 Gold

Analysis as a product to further elevate your analytical work and enhance its reusability to the public.

Meeting all of the above requirements, plus:

| Criteria | Completion | Further details |
| - | - | - |
| Code is fully [packaged](https://packaging.python.org/en/latest/). | ✅ | - |
| Repository automatically runs tests etc. via CI/CD or a different integration/deployment tool e.g. [GitHub Actions](https://docs.github.com/en/actions). | ✅ | `.github/workflows/R-CMD-check.yaml` |
| Process runs based on event-based triggers (e.g., new data in database) or on a schedule. | N/A | - |
| Changes to the RAP are clearly signposted. E.g. a changelog in the package, releases etc. (See gov.uk info on [Semantic Versioning](https://github.com/alphagov/govuk-frontend/blob/main/docs/contributing/versioning.md)). | ✅ | `NEWS.md` and GitHub releases. |
Loading