Skip to content

Commit 4230a5e

Browse files
committed
refactor(class): renamed Trial to Runner, run_trial() to run_reps(), trial to experiment, trial_results_df to run_results_df, etc.
1 parent 2363f8f commit 4230a5e

13 files changed

+268
-260
lines changed

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,12 @@ This section describes the purposes of each class in the simulation.
184184
* `generate_patient_arrivals()` to handle patient creation, then sending them on to `attend_clinic()`.
185185
* `interval_audit()` to record utilisation and wait times at specified intervals during the simulation.
186186

187-
**Trial Class Usage:**
187+
**Runner Class Usage:**
188188

189-
* **Single Run:** Use `trial.run_single()` to execute a single model run.
190-
* **Multiple Runs:** Use `trial.run_trial()` to perform multiple replications of the model.
189+
Having set up `experiment = Runner()`...
190+
191+
* **Single Run:** Use `experiment.run_single()` to execute a single model run.
192+
* **Multiple Runs:** Use `experiment.run_reps()` to perform multiple replications of the model.
191193

192194
<br>
193195

docs/hsma_changes.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,9 @@ param.patient_inter = 10
132132
model = Model(param)
133133
```
134134

135-
## Saving trial results
135+
## Saving replication results
136136

137-
To save trial-level results in the HSMA models, an empty dataframe is initialised during the __init__ method of the `Trial` class.
137+
To save results from each run in the HSMA models, an empty dataframe is initialised during the __init__ method of the `Trial` class (equivalent to the `Runner` class in this template).
138138

139139
```
140140
self.df_trial_results = pd.DataFrame()
@@ -164,7 +164,7 @@ In the template, results are instead saved as a dictionary into a list as the ru
164164
Also, some of the calculations have been performed directly during the `run_single()` method, instead of from a seperate method `calculate_run_results()`. This is to help simplify the code, as it makes clear how each metric was calculated in one place, rather than needing to refer elsewhere.
165165

166166
```
167-
trial_results = {
167+
run_results = {
168168
'run_number': run,
169169
'scenario': self.param.scenario_name,
170170
'arrivals': len(patient_results),
@@ -176,7 +176,7 @@ trial_results = {
176176
177177
...
178178
179-
self.trial_results_df = pd.DataFrame(trial_results_list)
179+
self.run_results_df = pd.DataFrame(run_results_list)
180180
```
181181

182182
## Extra features

images/model_structure.drawio

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

images/model_structure.png

7.99 KB
Loading

notebooks/analysis.ipynb

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

notebooks/choosing_parameters.ipynb

Lines changed: 29 additions & 28 deletions
Large diffs are not rendered by default.

notebooks/generate_exp_results.ipynb

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
"outputs": [],
6868
"source": [
6969
"# Import required packages\n",
70-
"from simulation.model import Defaults, Trial\n",
70+
"from simulation.model import Defaults, Runner\n",
7171
"import os\n",
7272
"import time"
7373
]
@@ -131,9 +131,9 @@
131131
"param.scenario_name = 0\n",
132132
"param.cores = 1\n",
133133
"\n",
134-
"# Run the trial\n",
135-
"trial = Trial(param)\n",
136-
"trial.run_trial()"
134+
"# Run the replications\n",
135+
"experiment = Runner(param)\n",
136+
"experiment.run_reps()"
137137
]
138138
},
139139
{
@@ -286,8 +286,8 @@
286286
],
287287
"source": [
288288
"# Patient-level results\n",
289-
"display(trial.patient_results_df)\n",
290-
"trial.patient_results_df.to_csv(\n",
289+
"display(experiment.patient_results_df)\n",
290+
"experiment.patient_results_df.to_csv(\n",
291291
" os.path.join(tests, 'patient.csv'), index=False)"
292292
]
293293
},
@@ -396,10 +396,10 @@
396396
}
397397
],
398398
"source": [
399-
"# Trial-level results\n",
400-
"display(trial.trial_results_df)\n",
401-
"trial.trial_results_df.to_csv(\n",
402-
" os.path.join(tests, 'trial.csv'), index=False)"
399+
"# Run results\n",
400+
"display(experiment.run_results_df)\n",
401+
"experiment.run_results_df.to_csv(\n",
402+
" os.path.join(tests, 'run.csv'), index=False)"
403403
]
404404
},
405405
{
@@ -577,8 +577,8 @@
577577
],
578578
"source": [
579579
"# Interval audit results\n",
580-
"display(trial.interval_audit_df)\n",
581-
"trial.interval_audit_df.to_csv(\n",
580+
"display(experiment.interval_audit_df)\n",
581+
"experiment.interval_audit_df.to_csv(\n",
582582
" os.path.join(tests, 'interval.csv'), index=False)"
583583
]
584584
},
@@ -667,8 +667,8 @@
667667
],
668668
"source": [
669669
"# Overall results\n",
670-
"display(trial.overall_results_df)\n",
671-
"trial.overall_results_df.to_csv(\n",
670+
"display(experiment.overall_results_df)\n",
671+
"experiment.overall_results_df.to_csv(\n",
672672
" os.path.join(tests, 'overall.csv'), index=True)"
673673
]
674674
},

outputs/choose_param_cores.png

990 Bytes
Loading
File renamed without changes.

simulation/model.py

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,20 @@
2222
more details.
2323
2424
Typical usage example:
25-
trial = Trial(param=Defaults())
26-
trial.run_trial()
27-
print(trial.trial_results_df)
25+
experiment = Runner(param=Defaults())
26+
experiment.run_reps()
27+
print(experiment.run_results_df)
2828
"""
2929

3030
from joblib import Parallel, delayed
31-
from simulation.logging import SimLogger
3231
import numpy as np
3332
import pandas as pd
3433
import scipy.stats as st
3534
import simpy
35+
from simulation.logging import SimLogger
3636

3737

38-
class Defaults():
38+
class Defaults:
3939
"""
4040
Default parameters for simulation.
4141
@@ -433,25 +433,28 @@ def run(self):
433433
self.results_list = [x.__dict__ for x in self.patients]
434434

435435

436-
class Trial:
436+
class Runner:
437437
"""
438-
Manages multiple simulation runs.
438+
Run the simulation.
439+
440+
Manages simulation runs, either running the model once or multiple times
441+
(replications).
439442
440443
Attributes:
441444
param (Defaults):
442445
Simulation parameters.
443446
patient_results_df (pandas.DataFrame):
444447
Dataframe to store patient-level results.
445-
trial_results_df (pandas.DataFrame):
446-
Dataframe to store trial-level results.
448+
run_results_df (pandas.DataFrame):
449+
Dataframe to store results from each run.
447450
interval_audit_df (pandas.DataFrame):
448451
Dataframe to store interval audit results.
449452
overall_results_df (pandas.DataFrame):
450-
Dataframe to store average results from runs of the trial.
453+
Dataframe to store average results from across the runs.
451454
"""
452455
def __init__(self, param):
453456
'''
454-
Initialise a new instance of the trial class.
457+
Initialise a new instance of the Runner class.
455458
456459
Arguments:
457460
param (Defaults):
@@ -461,7 +464,7 @@ def __init__(self, param):
461464
self.param = param
462465
# Initialise empty dataframes to store results
463466
self.patient_results_df = pd.DataFrame()
464-
self.trial_results_df = pd.DataFrame()
467+
self.run_results_df = pd.DataFrame()
465468
self.interval_audit_df = pd.DataFrame()
466469
self.overall_results_df = pd.DataFrame()
467470

@@ -475,8 +478,8 @@ def run_single(self, run):
475478
476479
Returns:
477480
dict:
478-
A dictionary containing the patient-level results, trial-level
479-
results, and interval audit results.
481+
A dictionary containing the patient-level results, results
482+
from each run, and interval audit results.
480483
"""
481484
# Run model
482485
model = Model(param=self.param, run_number=run)
@@ -486,8 +489,8 @@ def run_single(self, run):
486489
patient_results = pd.DataFrame(model.results_list)
487490
patient_results['run'] = run
488491

489-
# Create dictionary recording the trial-level results
490-
trial_results = {
492+
# Create dictionary recording the run results
493+
run_results = {
491494
'run_number': run,
492495
'scenario': self.param.scenario_name,
493496
'arrivals': len(patient_results),
@@ -504,16 +507,15 @@ def run_single(self, run):
504507

505508
return {
506509
'patient': patient_results,
507-
'trial': trial_results,
510+
'run': run_results,
508511
'interval_audit': interval_audit_df
509512
}
510513

511-
def run_trial(self):
514+
def run_reps(self):
512515
"""
513516
Execute a single model configuration for multiple runs/replications.
514517
515-
This is known as a trial, experiment, batch or scenario. These can be
516-
run sequentially or in parallel.
518+
These can be run sequentially or in parallel.
517519
"""
518520
# Sequential execution
519521
if self.param.cores == 1:
@@ -528,28 +530,28 @@ def run_trial(self):
528530
# Seperate results from each run into appropriate lists
529531
patient_results_list = [
530532
result['patient'] for result in all_results]
531-
trial_results_list = [
532-
result['trial'] for result in all_results]
533+
run_results_list = [
534+
result['run'] for result in all_results]
533535
interval_audit_list = [
534536
result['interval_audit'] for result in all_results]
535537

536538
# Convert lists into dataframes
537539
self.patient_results_df = pd.concat(patient_results_list,
538540
ignore_index=True)
539-
self.trial_results_df = pd.DataFrame(trial_results_list)
541+
self.run_results_df = pd.DataFrame(run_results_list)
540542
self.interval_audit_df = pd.concat(interval_audit_list,
541543
ignore_index=True)
542544

543-
# Calculate average results and uncertainty from across all trials
545+
# Calculate average results and uncertainty from across all runs
544546
uncertainty_metrics = {}
545-
trial_col = self.trial_results_df.columns
547+
run_col = self.run_results_df.columns
546548

547-
# Loop through the trial-level performance measure columns
549+
# Loop through the run performance measure columns
548550
# Calculate mean, standard deviation and 95% confidence interval
549-
for col in trial_col[~trial_col.isin(['run_number', 'scenario'])]:
551+
for col in run_col[~run_col.isin(['run_number', 'scenario'])]:
550552
uncertainty_metrics[col] = dict(zip(
551553
['mean', 'std_dev', 'lower_95_ci', 'upper_95_ci'],
552-
summary_stats(self.trial_results_df[col])
554+
summary_stats(self.run_results_df[col])
553555
))
554556
# Convert to dataframe
555557
self.overall_results_df = pd.DataFrame(uncertainty_metrics)
File renamed without changes.

tests/test_backtest.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
1313
"""
1414

15-
from simulation.model import Defaults, Trial
15+
from simulation.model import Defaults, Runner
1616
import pandas as pd
1717
from pathlib import Path
1818

@@ -34,26 +34,26 @@ def test_reproduction():
3434
param.scenario_name = 0
3535
param.cores = 1
3636

37-
# Run the trial
38-
trial = Trial(param)
39-
trial.run_trial()
37+
# Run the replications
38+
experiment = Runner(param)
39+
experiment.run_reps()
4040

4141
# Compare patient-level results
4242
exp_patient = pd.read_csv(
4343
Path(__file__).parent.joinpath('exp_results/patient.csv'))
44-
pd.testing.assert_frame_equal(trial.patient_results_df, exp_patient)
44+
pd.testing.assert_frame_equal(experiment.patient_results_df, exp_patient)
4545

46-
# Compare trial-level results
47-
exp_trial = pd.read_csv(
48-
Path(__file__).parent.joinpath('exp_results/trial.csv'))
49-
pd.testing.assert_frame_equal(trial.trial_results_df, exp_trial)
46+
# Compare run results
47+
exp_run = pd.read_csv(
48+
Path(__file__).parent.joinpath('exp_results/run.csv'))
49+
pd.testing.assert_frame_equal(experiment.run_results_df, exp_run)
5050

5151
# Compare interval audit results
5252
exp_interval = pd.read_csv(
5353
Path(__file__).parent.joinpath('exp_results/interval.csv'))
54-
pd.testing.assert_frame_equal(trial.interval_audit_df, exp_interval)
54+
pd.testing.assert_frame_equal(experiment.interval_audit_df, exp_interval)
5555

5656
# Compare overall results
5757
exp_overall = pd.read_csv(
5858
Path(__file__).parent.joinpath('exp_results/overall.csv'), index_col=0)
59-
pd.testing.assert_frame_equal(trial.overall_results_df, exp_overall)
59+
pd.testing.assert_frame_equal(experiment.overall_results_df, exp_overall)

0 commit comments

Comments
 (0)