Skip to content
Merged

Dev #190

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
5046acf
chore(ci): add run-name
amyheather Feb 4, 2026
177cee1
style(diagrams): finish converting to text in drawings (#169)
amyheather Feb 4, 2026
abe3f8a
feat(warmup): addressing tom's feedback (#177)
amyheather Feb 4, 2026
d212f1d
feat(impact): add two more case studies
amyheather Feb 6, 2026
a7d33ad
feat(package): remind to save (#149)
amyheather Feb 6, 2026
1e8c3d3
feat(patients): add note about imports (#149)
amyheather Feb 6, 2026
99b53b1
feat(outputs): addressing nav's feedback including to provide python …
amyheather Feb 6, 2026
ad776ec
feat(outputs): r summary version of measures (#149)
amyheather Feb 6, 2026
485d068
feat(guide): addressing nav's feedback (e.g. clearer imports) (#149)
amyheather Feb 6, 2026
14cc753
feat(n_reps): addressing nav's feedback (#149)
amyheather Feb 6, 2026
24edec6
fix(outputs): correct description of area under curve (tom - #177)
amyheather Feb 6, 2026
1cd6143
chore(full_run): typo (#178)
amyheather Feb 6, 2026
508aca7
feat(tables_figures): addressing tom's feedback (#178)
amyheather Feb 6, 2026
fbf077a
feat(v+v/math): addressing tom's feedback (#179)
amyheather Feb 6, 2026
5fa5617
fix(tables_figures): show good practice list on python page too
amyheather Feb 6, 2026
d7520ad
feat(changelog): add to site (#170)
amyheather Feb 9, 2026
fa48685
feat(dissemination): add advertising plan (#170)
amyheather Feb 9, 2026
c3ca883
chore(license): update date and copyright holder
amyheather Feb 9, 2026
fe83659
docs(accessibility): state framework used in README and CONTRIBUTING …
amyheather Feb 9, 2026
963f36e
feat(scenarios): addressing nav's feedback (#150)
amyheather Feb 9, 2026
3ad9a98
chore(line-highlight): add filter to pages missing it
amyheather Feb 9, 2026
0059fdf
feat(tables_figures): addressing nav's feedback (#150)
amyheather Feb 9, 2026
1159936
build(env): add nbconvert (#150)
amyheather Feb 9, 2026
3781b1c
feat(full_run): addressing nav's feedback (#150)
amyheather Feb 9, 2026
2d7eef9
feat(v+v): addressing nav's feedback (#158)
amyheather Feb 9, 2026
3b0164e
feat(general): addressing nav + tom feedback
amyheather Feb 11, 2026
583959f
build(env): add nbconvert (#189)
amyheather Feb 12, 2026
894e1e9
feat(docstrings): addressing tom's feedback (#180)
amyheather Feb 12, 2026
8c0e38b
chore(tests): minor language change
amyheather Feb 12, 2026
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
1 change: 1 addition & 0 deletions .github/workflows/docker_quarto.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
name: Publish docker on GHCR and quarto on GitHub pages
run-name: Publish docker on GHCR and quarto on GitHub pages

on:
push:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/lint_alt_text.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
name: Check Alt Text
run-name: Check Alt Text

on:
push:
Expand Down
2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ sudo docker image rm -f desrapbookdocker

## Accessibility

This site uses [W3C's Web Accessibility Initiative (WAI) Easy Checks](https://www.w3.org/WAI/test-evaluate/easy-checks/) as a lightweight accessibility framework. Please see this [GitHub issue](https://github.com/pythonhealthdatascience/des_rap_book/issues/188) for a record of which checks are currently met and any known limitations.

Quarto's supported accessibility checker `axe` is not used because it is difficult to read, and it mostly flagged things that cannot be changed (i.e., Quarto defaults and built-ins). As such, other approaches are used.

### `lint_alt_text.py`
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2025 Reproducible Healthcare Simulations in Python and R
Copyright (c) 2026 STARS (Sharing Tools and Artefacts for Reproducible Simulations in healthcare) project team

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ You can also cite the archived version of this work on Zenodo: https://doi.org/1

<br>

## Accessibility

This site uses [W3C's Web Accessibility Initiative (WAI) Easy Checks](https://www.w3.org/WAI/test-evaluate/easy-checks/) as a lightweight accessibility framework. Please see this [GitHub issue](https://github.com/pythonhealthdatascience/des_rap_book/issues/188) for a record of which checks are currently met and any known limitations.

<br>

## Contributors

If you're interested in contributing (or just viewing this website locally), check out the `CONTRIBUTING.md` file.
Expand Down
3 changes: 2 additions & 1 deletion _quarto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ website:
- text: |
Part of the <a href="https://pythonhealthdatascience.github.io/stars/" target="_blank" rel="noopener">STARS research project</a>.<br>
Code licence: <a href="https://opensource.org/license/mit" target="_blank" rel="noopener">MIT</a>.
Text licence: <a href="https://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener">CC-BY-SA 4.0</a>.
Text licence: <a href="https://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener">CC-BY-SA 4.0</a>.<br>
<a href="/pages/changelog.qmd">Changelog</a>
right:
- text: |
Heather, A., Monks, T., Mustafee, N., Harper, A., Alidoost, F., Challen, R., & Slater, T. (2025). DES RAP Book: Reproducible Discrete-Event Simulation in Python and R. https://github.com/pythonhealthdatascience/des_rap_book. https://doi.org/10.5281/zenodo.17094155.
Expand Down
24 changes: 24 additions & 0 deletions dissemination.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Dissemination / Advertising Plan

This document outlines how this training resource is and will be shared with its target audience.

## Publication and formal channels

* Submit a journal publication describing the resource and its intended use, including a persistent link to the online book.
* Embed and describe the resource within the [HDR UK Futures](https://hdruklearn.org/) training platform, so it appears alongside related training materials.

## Professional and community networks

* Share the resource on:
* NHS-OA community Slack.
* RSE community Slack.
* LinkedIn.
* PenARC comms.
* Open Research champions network / UK Reproducibility Network.
* Write a blog post for the NHS-OA community about the resource.

## Web presence and catalogues

* Link the resource from the [STARS project site](https://pythonhealthdatascience.github.io/stars/).
* Register in training resource catalogues [TESS](https://tess.elixir-europe.org/) and [Glittr](https://glittr.org/).
* Include on the [Coding For Reproducible Research resource list](https://coding-for-reproducible-research.github.io/CfRR_Courses/resources/resources.html).
1 change: 1 addition & 0 deletions environment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ dependencies:
- flake8=7.3.0
- itables=2.5.2
- jupyter=1.1.1
- nbconvert=7.17.0
- openssl=3.3.0
- pandas=2.3.1
- plotly=6.3.0
Expand Down
18 changes: 18 additions & 0 deletions pages/changelog.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
pagetitle: Changelog
---

{{< include /CHANGELOG.md >}}

<!--Adjust spacing before headers-->
<style>
section.level2 {
padding-top: 0.5em;
}
h3 {
margin-top: 0.2em;
}
h4 {
margin-top: 0em;
}
</style>
1 change: 1 addition & 0 deletions pages/guide/environment-full.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ dependencies:
- flake8=7.3.0
- itables=2.5.2
- jupyter=1.1.1
- nbconvert-core=7.16.6
- openssl=3.3.0
- pandas=2.3.1
- plotly=6.3.0
Expand Down
54 changes: 45 additions & 9 deletions pages/guide/experiments/full_run.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,37 @@ A bash script is a plain text file that contains a list of terminal commands, wr

### Where to put the script?

Save the script below as `run_notebooks.sh` in the root of your project, alongside the `notebooks/` folder.

::: {.python-content}

This allows the script to loop over `rmarkdown/*.Rmd` without extra path adjustments.
Save the script below as `run_notebooks.sh` in the project root - for example:

```
├── run_notebooks.sh
├── notebooks/
| └── ...
├── simulation/
| └── ...
├── ...
```

This allows the script to loop over all `.ipynb` in the `notebooks/` folder using `notebooks/*.ipynb` without extra path adjustments.

:::

::: {.r-content}

This allows the script to loop over `notebooks/*.ipynb` without extra path adjustments.
Save the script below as `run_rmarkdown.sh` in the project root - for example:

```
├── run_rmarkdown.sh
├── R/
| └── ...
├── rmarkdown/
| └── ...
├── ...
```

This allows the script to loop over all `.Rmd` files in the `rmarkdown/` folder using `rmarkdown/*.Rmd` without extra path adjustments.

:::

Expand Down Expand Up @@ -140,6 +160,17 @@ CONDA_JUPYTER=$(dirname "$(which python)")/jupyter

This line finds the `jupyter` executable linked to your current python environment. This ensures it uses the correct version of Jupyter (i.e., instead of trying to run a system-wide or different environment's Jupyter).

::: {.callout-note title="Alternative path for Windows users"}

On Windows, `jupyter.exe` is usually in the `Scripts` folder of your conda environment, not directly next to `python.exe`. For example, if `which python` returns `envs/des-example/python.exe`, then `jupyter.exe` is typically at `env/des-example/Scripts/jupyter.exe`.
You will want to change the line above to:

```{.bash}
CONDA_JUPYTER=$(dirname "$(which python)")/Scripts/jupyter`
```

:::

<br>

```{.bash}
Expand Down Expand Up @@ -186,15 +217,17 @@ The Jupyter nbconvert command (a single command, though split across several lin

* `"${CONDA_JUPYTER}" nbconvert`: Execute nbconvert from your environment.
* `--to notebook --inplace --execute`: Run the notebook, overwrite in place, and execute all cells from scratch.
* By using `--inplace`, nbconvert overwrites the existing notebook file with the executed version. If you prefer to keep the original notebook and write the executed result to a new file, remove `--inplace` and use `--output`.
* You can also change `--to notebook` to another format (e.g., `--to html` generates HTML).
* `--ClearMetadataPreprocessor.enabled=True`: Enable pre-processor that can clear notebook metadata.
* `--ClearMetadataPreprocessor.clear_notebook_metadata=True`: Remove notebook metadata.
* `"$nb"`: Specifies the notebook file to run.

::: {.callout title="Why do we have the metadata settings?" collapse="true"}

These are to **avoid changes in files that have been re-run**, when all the results and code are still the same, **just the notebook metadata has changed**.
Jupyter stores a lot of extra metadata in notebooks (kernel name, environment IDs, timing info, UI state, etc.). These fields often change even when the code and outputs are identical, which creates noisy diffs in version control. The metadata options in the command tell nbconvert to strip most of this metadata so that the file only changes when the code or outputs really change.

With these settings in our bash script, the output notebook metadata will be:
*Note: One side effect is that clearing all notebook metadata can change how the Jupyter interface behaves (e.g., some menu items like "Clear All Outputs" may disappear or look different), because the frontend relies on metadata like the kernelspec and language information.*

```{.bash}
{
Expand Down Expand Up @@ -331,13 +364,14 @@ if __name__ == "__main__":
main()
```

These can then be easily run from bash scripts like so:
These can then be easily run from the command line:

```{.bash}
#!/bin/bash
python filename.py
```

You could put your whole pipeline inside a single `main()` function and avoid bash scripts altogether. However, a separate bash script becomes useful when you want to mix different tools (e.g., `.ipynb` and `.py`) and languages in one pipeline.

:::

::: {.r-content}
Expand Down Expand Up @@ -406,6 +440,8 @@ You can run this R script from a Bash script or terminal with the following comm
Rscript analysis/filename.R
```

You could call your whole pipeline from inside a single R script and avoid bash scripts altogether. However, a separate bash script becomes useful when you want to mix different tools (e.g., `.Rmd` and `R` files) and languages in one pipeline.

:::

## Literate programming
Expand All @@ -430,7 +466,7 @@ Rscript analysis/filename.R

::::

This style of working can be really handy for **reproducibility**, a all the parameter choices, steps and outputs are documented alongside explanatory text.
This style of working can be really handy for **reproducibility**, as all the parameter choices, steps and outputs are documented alongside explanatory text.

There are several common ways to use literate programming in research workflows:

Expand Down
40 changes: 35 additions & 5 deletions pages/guide/experiments/scenarios.qmd
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
---
title: Scenario and sensitivity analysis
filters:
- line-highlight
bibliography: scenarios_resources/references.bib
date: "2025-11-06T10:44:04+00:00"
---
Expand Down Expand Up @@ -36,17 +38,24 @@ This page continues on from: [Parallel processing](../output_analysis/parallel.q

**Required packages:**

These should be available from environment setup on the [Structuring as a package](/pages/guide/setup/package.qmd) page.
The following imports are required. These should be available from environment setup on the [Structuring as a package](/pages/guide/setup/package.qmd) page.

We have one new package: `itertools`.

::: {.python-content}

```{python}
import itertools

# For display purposes:
from IPython.display import HTML
from itables import to_html_datatable

# For the simulation modelling and analysis:
import itertools#<<
import time
from joblib import Parallel, delayed, cpu_count
import numpy as np
import pandas as pd
import plotly.express as px
import scipy.stats as st
import simpy
from sim_tools.distributions import Exponential
Expand Down Expand Up @@ -78,7 +87,7 @@ library(tidyr)

## Running and sharing scenarios

When creating a DES, you won't just run one model - you run scenarios, which are different parameter set-ups. These are used to test how outcomes change under varying conditions.
When creating a DES, you won't just run one model - you run scenarios, which can involve different parameter setups and/or changes to the process flow or simulation logic (e.g., alternative configurations of resources, routing, or priority rules). These are used to test how outcomes change under varying conditions.

When running scenarios, there are two important things to remember:

Expand All @@ -88,7 +97,14 @@ When running scenarios, there are two important things to remember:

:::

Don't duplicate whole scripts just to test different set-ups. The idea is to build the model with functions and classes so you only need to change the parameters and re-run. That's why we guide you through building the model this way in this book.
**Don't duplicate whole scripts** just to test different set-ups.

Using functions and classes is important here, as:

* If your scenarios only change **parameters**, you just run the same model with different inputs.
* If your scenarios change the **configuration** of the system (e.g., routing or scheduling), you can create alternative methods, functions, or configuration objects.

On this page, we only show examples where scenarios differ by parameters.

::: {.cream}

Expand Down Expand Up @@ -378,7 +394,11 @@ scenario_results = run_scenarios(
"number_of_doctors": [3, 4, 5]},
param_factory=Parameters
)
```

We'll save results to CSV - you can change the file path listed, or otherwise, you'll just need to create the `scenarios_resources` directory first.

```{python}
# Save to CSV
scenario_results.to_csv(
"scenarios_resources/python_scenario_results.csv", index=False
Expand Down Expand Up @@ -452,7 +472,11 @@ sensitivity_results = run_scenarios(
scenarios={"interarrival_time": [4, 4.5, 5, 5.5, 6, 6.5, 7]},
param_factory=Parameters
)
```

We'll save results to CSV - you can change the file path listed, or otherwise, you'll just need to ensure you have already made the `scenarios_resources` directory first.

```{python}
# Save to CSV
sensitivity_results.to_csv(
"scenarios_resources/python_sensitivity_results.csv", index=False
Expand Down Expand Up @@ -483,6 +507,12 @@ kable(sensitivity_results) |> scroll_box(height = "400px")

:::

::: {.callout-note title="Sensitivity analysis across scenarios"}

In practice, sensitivity analysis is often performed within each scenario - for example, you might define several scenarios (different configurations of arrivals, capacity, or routing) and then vary a key parameter (such as interarrival time) around each of them. In this book, for simplicity, we show sensitivity analysis for a single scenario at a time, and you can repeat the same approach for any other plausible scenarios you define.

:::

## Saving results

Saving your simulation results to file is important for reproducility, as it allows others to verify your findings and generate consistent (or new) figures and analyses, even if they can't re-run your simulation.
Expand Down
Loading