Skip to content

Commit 50f2946

Browse files
authored
Merge pull request #29 from pythonhealthdatascience/amy
Amy
2 parents d002ee3 + 9dff66e commit 50f2946

28 files changed

+4628
-1841
lines changed

README.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ Table of contents:
3232

3333
## 📌  Introduction
3434

35-
<!--TODO: Add links to STARS, relevant publication, and https://github.com/pythonhealthdatascience/rap_des/ -->
36-
3735
This repository provides a template for building discrete-event simulation (DES) models in Python.
3836

3937
😊 **Simple:** Easy-to-follow code structure using [SimPy](https://simpy.readthedocs.io/en/latest/). Implements a simple M/M/s queueing model in which patients arrive, wait to see a nurse, have a consultation with the nurse and then leave. Follows a modular structure: uses object-oriented programming, with the simulation implemented through classes.
@@ -43,7 +41,7 @@ This repository provides a template for building discrete-event simulation (DES)
4341
* ["Levels of RAP" framework](https://nhsdigital.github.io/rap-community-of-practice/introduction_to_RAP/levels_of_RAP/) from the NHS RAP Community of Practice (`docs/nhs_rap.md`).
4442
* Recommendations from [Heather et al. 2025](https://doi.org/10.48550/arXiv.2501.13137) "*On the reproducibility of discrete-event simulation studies in health research: an empirical study using open models*" (`docs/heather_2025.md`).
4543

46-
🚀 **Extendable:** This template adapts from Sammi Rosser and Dan Chalk (2024) ["HSMA - the little book of DES"](https://github.com/hsma-programme/hsma6_des_book). The book includes additional advanced features that can be used to extend the model in this template, including:
44+
🚀 **Extendable:** This template is partly adapted from Sammi Rosser and Dan Chalk (2024) ["HSMA - the little book of DES"](https://github.com/hsma-programme/hsma6_des_book). The book includes additional advanced features that can be used to extend the model in this template, including:
4745

4846
* Multiple activities
4947
* Branching paths
@@ -247,10 +245,12 @@ repo/
247245
The overall run time will vary depending on how the template model is used. A few example implementations are provided in `notebooks/` and the run times for these were:
248246

249247
* `analysis.ipynb` - 23s
250-
* `choosing_parameters.ipynb` - 22s
248+
* `choosing_cores.ipynb` - 21s
249+
* `choosing_replications.ipynb` - 11s
250+
* `choosing_warmup.ipynb` - 2s
251251
* `generate_exp_results.ipynb` - 0s
252252

253-
<!--TODO: Add test times -->
253+
<!--TODO: Update run times -->
254254

255255
These times were obtained on an Intel Core i7-12700H with 32GB RAM running Ubuntu 24.04.1 Linux.
256256

@@ -268,10 +268,10 @@ You can also cite the GitHub repository:
268268
269269
Researcher details:
270270

271-
| Contributor | Role | ORCID | GitHub |
272-
| --- | --- | --- | --- |
273-
| Amy Heather | Author | [![ORCID: Heather](https://img.shields.io/badge/ORCID-0000--0002--6596--3479-brightgreen)](https://orcid.org/0000-0002-6596-3479) | https://github.com/amyheather |
274-
| Tom Monks | Code review | [![ORCID: Monks](https://img.shields.io/badge/ORCID-0000--0003--2631--4481-brightgreen)](https://orcid.org/0000-0003-2631-4481) | https://github.com/TomMonks |
271+
| Contributor | ORCID | GitHub |
272+
| --- | --- | --- |
273+
| Amy Heather | [![ORCID: Heather](https://img.shields.io/badge/ORCID-0000--0002--6596--3479-brightgreen)](https://orcid.org/0000-0002-6596-3479) | https://github.com/amyheather |
274+
| Tom Monks | [![ORCID: Monks](https://img.shields.io/badge/ORCID-0000--0003--2631--4481-brightgreen)](https://orcid.org/0000-0003-2631-4481) | https://github.com/TomMonks |
275275

276276
<br>
277277

docs/hsma_changes.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Changes from the HSMA model
22

3-
This template model is adapted from Sammi Rosser and Dan Chalk (2024) HSMA - the little book of DES (https://github.com/hsma-programme/hsma6_des_book) (MIT Licence). It also uses an exponentional distribution class from Monks (2021) sim-tools: fundamental tools to support the simulation process in python (https://github.com/TomMonks/sim-tools) (MIT Licence).
3+
This template model is based on a few sources - including: Sammi Rosser and Dan Chalk (2024) HSMA - the little book of DES (https://github.com/hsma-programme/hsma6_des_book) (MIT Licence).
44

55
This page explains some of the differences between the models in the HSMA book, and this template.
66

images/replications_algorithm.drawio

Lines changed: 411 additions & 0 deletions
Large diffs are not rendered by default.

images/replications_algorithm.png

1.04 MB
Loading

images/replications_statistics.drawio

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36" version="26.0.13">
2+
<diagram name="Page-1" id="ynTKS2v_TZv17swCPKiS">
3+
<mxGraphModel dx="1630" dy="915" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
4+
<root>
5+
<mxCell id="0" />
6+
<mxCell id="1" parent="0" />
7+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-42" value="" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=none;fillColor=#EEEEEE;fontStyle=1;opacity=50;" vertex="1" parent="1">
8+
<mxGeometry x="336.5" y="40" width="543.5" height="436.5" as="geometry" />
9+
</mxCell>
10+
<mxCell id="ltitkqDnKHNBnyyiyaz9-67" value="" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=none;fillColor=#EEEEEE;fontStyle=1;opacity=50;" parent="1" vertex="1">
11+
<mxGeometry x="40" y="111" width="270" height="565.5" as="geometry" />
12+
</mxCell>
13+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="ltitkqDnKHNBnyyiyaz9-6" target="q0k77vlWbUJt_Vhd_Qly-5">
14+
<mxGeometry relative="1" as="geometry" />
15+
</mxCell>
16+
<mxCell id="ltitkqDnKHNBnyyiyaz9-6" value="&lt;font style=&quot;font-size: 18px;&quot;&gt;OnlineStatistics&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#68A9D4;" parent="1" vertex="1">
17+
<mxGeometry x="353.26" y="56.5" width="154.75" height="40" as="geometry" />
18+
</mxCell>
19+
<mxCell id="ltitkqDnKHNBnyyiyaz9-41" value="Key:" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=1;fontStyle=1;" parent="1" vertex="1">
20+
<mxGeometry x="756.5" y="495.5" width="45" height="25" as="geometry" />
21+
</mxCell>
22+
<mxCell id="ltitkqDnKHNBnyyiyaz9-43" value="Methods or properties" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F2A25C;" parent="1" vertex="1">
23+
<mxGeometry x="711.5" y="608.5" width="135" height="30" as="geometry" />
24+
</mxCell>
25+
<mxCell id="ltitkqDnKHNBnyyiyaz9-44" value="Instance of class" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#A9E4F5;" parent="1" vertex="1">
26+
<mxGeometry x="711.5" y="569.5" width="135" height="30" as="geometry" />
27+
</mxCell>
28+
<mxCell id="ltitkqDnKHNBnyyiyaz9-45" value="Class" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#68A9D4;" parent="1" vertex="1">
29+
<mxGeometry x="711.5" y="531" width="135" height="30" as="geometry" />
30+
</mxCell>
31+
<mxCell id="ltitkqDnKHNBnyyiyaz9-88" value="" style="curved=1;endArrow=classic;html=1;rounded=1;dashed=1;exitX=1;exitY=0;exitDx=0;exitDy=0;" parent="1" edge="1">
32+
<mxGeometry width="50" height="50" relative="1" as="geometry">
33+
<mxPoint x="292.8199999999998" y="505" as="sourcePoint" />
34+
<mxPoint x="620" y="366.5" as="targetPoint" />
35+
<Array as="points">
36+
<mxPoint x="660" y="526.5" />
37+
<mxPoint x="550" y="386.5" />
38+
</Array>
39+
</mxGeometry>
40+
</mxCell>
41+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-1" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;init()&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F2A25C;" vertex="1" parent="1">
42+
<mxGeometry x="398.43999999999994" y="206.5" width="64.37" height="30" as="geometry" />
43+
</mxCell>
44+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-34" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.75;entryY=0;entryDx=0;entryDy=0;curved=0;" edge="1" parent="1" source="q0k77vlWbUJt_Vhd_Qly-3" target="q0k77vlWbUJt_Vhd_Qly-32">
45+
<mxGeometry relative="1" as="geometry" />
46+
</mxCell>
47+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-3" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;update()&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F2A25C;" vertex="1" parent="1">
48+
<mxGeometry x="389.85" y="356.5" width="81.56" height="30" as="geometry" />
49+
</mxCell>
50+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="q0k77vlWbUJt_Vhd_Qly-5" target="q0k77vlWbUJt_Vhd_Qly-1">
51+
<mxGeometry relative="1" as="geometry" />
52+
</mxCell>
53+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-22" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;curved=0;" edge="1" parent="1" source="q0k77vlWbUJt_Vhd_Qly-5">
54+
<mxGeometry relative="1" as="geometry">
55+
<mxPoint x="730" y="196.5" as="targetPoint" />
56+
</mxGeometry>
57+
</mxCell>
58+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-5" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;stats&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#A9E4F5;" vertex="1" parent="1">
59+
<mxGeometry x="391.38" y="127.5" width="78.5" height="30" as="geometry" />
60+
</mxCell>
61+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" target="q0k77vlWbUJt_Vhd_Qly-3">
62+
<mxGeometry relative="1" as="geometry">
63+
<mxPoint x="431.01" y="306.5" as="sourcePoint" />
64+
</mxGeometry>
65+
</mxCell>
66+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-8" value="Sets up class, including empty variables to store results, and calls update() for each value in data (if provided)" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=1;" vertex="1" parent="1">
67+
<mxGeometry x="343.13" y="251.5" width="175" height="40" as="geometry" />
68+
</mxCell>
69+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-10" value="Updates count and running calculation of mean and variance.&lt;div&gt;Will call observer.update().&lt;/div&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=1;" vertex="1" parent="1">
70+
<mxGeometry x="336.5" y="386.5" width="188.25" height="50" as="geometry" />
71+
</mxCell>
72+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-12" value="&lt;span style=&quot;font-size: 14px;&quot;&gt;variance()&lt;/span&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F2A25C;" vertex="1" parent="1">
73+
<mxGeometry x="580" y="287" width="90" height="30" as="geometry" />
74+
</mxCell>
75+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-13" value="&lt;span style=&quot;font-size: 14px;&quot;&gt;std()&lt;/span&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F2A25C;" vertex="1" parent="1">
76+
<mxGeometry x="680.5" y="287" width="90" height="30" as="geometry" />
77+
</mxCell>
78+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-14" value="&lt;span style=&quot;font-size: 14px;&quot;&gt;std_error()&lt;/span&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F2A25C;" vertex="1" parent="1">
79+
<mxGeometry x="778" y="287" width="90" height="30" as="geometry" />
80+
</mxCell>
81+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-15" value="&lt;span style=&quot;font-size: 14px;&quot;&gt;half_width()&lt;/span&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F2A25C;" vertex="1" parent="1">
82+
<mxGeometry x="635.5" y="326" width="90" height="30" as="geometry" />
83+
</mxCell>
84+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-16" value="&lt;span style=&quot;font-size: 14px;&quot;&gt;lci()&lt;/span&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F2A25C;" vertex="1" parent="1">
85+
<mxGeometry x="734" y="325" width="90" height="30" as="geometry" />
86+
</mxCell>
87+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-17" value="&lt;span style=&quot;font-size: 14px;&quot;&gt;uci()&lt;/span&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F2A25C;" vertex="1" parent="1">
88+
<mxGeometry x="635.5" y="362" width="90" height="30" as="geometry" />
89+
</mxCell>
90+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-18" value="&lt;span style=&quot;font-size: 14px;&quot;&gt;deviation()&lt;/span&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F2A25C;" vertex="1" parent="1">
91+
<mxGeometry x="734" y="362" width="90" height="30" as="geometry" />
92+
</mxCell>
93+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-19" value="Can calculate various statistics based on the current count, mean and variance. These are marked @property meaning they are returned by e.g. stats.std rather than stats.std()" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=1;" vertex="1" parent="1">
94+
<mxGeometry x="620.5" y="217" width="210" height="50" as="geometry" />
95+
</mxCell>
96+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-27" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="q0k77vlWbUJt_Vhd_Qly-24" target="q0k77vlWbUJt_Vhd_Qly-25">
97+
<mxGeometry relative="1" as="geometry" />
98+
</mxCell>
99+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-24" value="&lt;font style=&quot;font-size: 18px;&quot;&gt;ReplicationTabulizer&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#68A9D4;" vertex="1" parent="1">
100+
<mxGeometry x="80" y="127.5" width="190" height="40" as="geometry" />
101+
</mxCell>
102+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-35" style="edgeStyle=orthogonalEdgeStyle;shape=connector;curved=0;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=default;align=center;verticalAlign=middle;fontFamily=Helvetica;fontSize=11;fontColor=default;labelBackgroundColor=default;endArrow=classic;" edge="1" parent="1" source="q0k77vlWbUJt_Vhd_Qly-25" target="q0k77vlWbUJt_Vhd_Qly-29">
103+
<mxGeometry relative="1" as="geometry" />
104+
</mxCell>
105+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-36" style="edgeStyle=orthogonalEdgeStyle;shape=connector;curved=0;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=default;align=center;verticalAlign=middle;fontFamily=Helvetica;fontSize=11;fontColor=default;labelBackgroundColor=default;endArrow=classic;" edge="1" parent="1" source="q0k77vlWbUJt_Vhd_Qly-25" target="q0k77vlWbUJt_Vhd_Qly-32">
106+
<mxGeometry relative="1" as="geometry">
107+
<Array as="points">
108+
<mxPoint x="166" y="376.5" />
109+
<mxPoint x="235" y="376.5" />
110+
</Array>
111+
</mxGeometry>
112+
</mxCell>
113+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-41" style="edgeStyle=orthogonalEdgeStyle;shape=connector;curved=0;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=default;align=center;verticalAlign=middle;fontFamily=Helvetica;fontSize=11;fontColor=default;labelBackgroundColor=default;endArrow=classic;" edge="1" parent="1" source="q0k77vlWbUJt_Vhd_Qly-25" target="q0k77vlWbUJt_Vhd_Qly-37">
114+
<mxGeometry relative="1" as="geometry">
115+
<Array as="points">
116+
<mxPoint x="166" y="556.5" />
117+
<mxPoint x="238" y="556.5" />
118+
</Array>
119+
</mxGeometry>
120+
</mxCell>
121+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-25" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;observer&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#A9E4F5;" vertex="1" parent="1">
122+
<mxGeometry x="127.13" y="202" width="78.5" height="30" as="geometry" />
123+
</mxCell>
124+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-29" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;init()&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F2A25C;" vertex="1" parent="1">
125+
<mxGeometry x="205.62999999999994" y="282" width="64.37" height="30" as="geometry" />
126+
</mxCell>
127+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-31" value="Creates empty lists to store results" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=1;" vertex="1" parent="1">
128+
<mxGeometry x="182.82" y="312" width="110" height="40" as="geometry" />
129+
</mxCell>
130+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-32" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;update()&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F2A25C;" vertex="1" parent="1">
131+
<mxGeometry x="200" y="456.5" width="70" height="30" as="geometry" />
132+
</mxCell>
133+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-33" value="Add statistics from stats to the lists" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=1;" vertex="1" parent="1">
134+
<mxGeometry x="180" y="488" width="110" height="40" as="geometry" />
135+
</mxCell>
136+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-37" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;summary_table()&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F2A25C;" vertex="1" parent="1">
137+
<mxGeometry x="179.22999999999996" y="590" width="117.18" height="30" as="geometry" />
138+
</mxCell>
139+
<mxCell id="q0k77vlWbUJt_Vhd_Qly-39" value="Converts lists into a dataframe" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=1;" vertex="1" parent="1">
140+
<mxGeometry x="179.23000000000002" y="617" width="110" height="41.5" as="geometry" />
141+
</mxCell>
142+
</root>
143+
</mxGraphModel>
144+
</diagram>
145+
</mxfile>

images/replications_statistics.png

410 KB
Loading

0 commit comments

Comments
 (0)