diff --git a/content/02_model_code/04_model.ipynb b/content/02_model_code/04_model.ipynb
index 078b224..0a42e4b 100644
--- a/content/02_model_code/04_model.ipynb
+++ b/content/02_model_code/04_model.ipynb
@@ -492,22 +492,110 @@
" \n",
" Passed to a model and its process classes\n",
" '''\n",
- " def __init__(self, random_number_set=DEFAULT_RNG_SET):\n",
+ " def __init__(self, random_number_set=DEFAULT_RNG_SET,\n",
+ " n_triage=DEFAULT_N_TRIAGE,\n",
+ " n_reg=DEFAULT_N_REG,\n",
+ " n_exam=DEFAULT_N_EXAM,\n",
+ " n_trauma=DEFAULT_N_TRAUMA,\n",
+ " n_cubicles_1=DEFAULT_N_CUBICLES_1,\n",
+ " n_cubicles_2=DEFAULT_N_CUBICLES_2,\n",
+ " triage_mean=DEFAULT_TRIAGE_MEAN,\n",
+ " reg_mean=DEFAULT_REG_MEAN,\n",
+ " reg_var=DEFAULT_REG_VAR,\n",
+ " exam_mean=DEFAULT_EXAM_MEAN,\n",
+ " exam_var=DEFAULT_EXAM_VAR,\n",
+ " trauma_mean=DEFAULT_TRAUMA_MEAN,\n",
+ " trauma_treat_mean=DEFAULT_TRAUMA_TREAT_MEAN,\n",
+ " trauma_treat_var=DEFAULT_TRAUMA_TREAT_VAR,\n",
+ " non_trauma_treat_mean=DEFAULT_NON_TRAUMA_TREAT_MEAN,\n",
+ " non_trauma_treat_var=DEFAULT_NON_TRAUMA_TREAT_VAR,\n",
+ " non_trauma_treat_p=DEFAULT_NON_TRAUMA_TREAT_P,\n",
+ " prob_trauma=DEFAULT_PROB_TRAUMA):\n",
" '''\n",
- " The init method sets up our defaults.\n",
+ " Create a scenario to parameterise the simulation model\n",
" \n",
" Parameters:\n",
" -----------\n",
" random_number_set: int, optional (default=DEFAULT_RNG_SET)\n",
" Set to control the initial seeds of each stream of pseudo\n",
" random numbers used in the model.\n",
+ " \n",
+ " n_triage: int\n",
+ " The number of triage cubicles\n",
+ " \n",
+ " n_reg: int\n",
+ " The number of registration clerks\n",
+ " \n",
+ " n_exam: int\n",
+ " The number of examination rooms\n",
+ " \n",
+ " n_trauma: int\n",
+ " The number of trauma bays for stablisation\n",
+ " \n",
+ " n_cubicles_1: int\n",
+ " The number of non-trauma treatment cubicles\n",
+ " \n",
+ " n_cubicles_2: int\n",
+ " The number of trauma treatment cubicles\n",
+ " \n",
+ " triage_mean: float\n",
+ " Mean duration of the triage distribution (Exponential)\n",
+ " \n",
+ " reg_mean: float\n",
+ " Mean duration of the registration distribution (Lognormal)\n",
+ " \n",
+ " reg_var: float\n",
+ " Variance of the registration distribution (Lognormal)\n",
+ " \n",
+ " exam_mean: float\n",
+ " Mean of the examination distribution (Normal)\n",
+ " \n",
+ " exam_var: float\n",
+ " Variance of the examination distribution (Normal)\n",
+ " \n",
+ " trauma_mean: float\n",
+ " Mean of the trauma stabilisation distribution (Exponential)\n",
+ " \n",
+ " trauma_treat_mean: float\n",
+ " Mean of the trauma cubicle treatment distribution (Lognormal)\n",
+ " \n",
+ " trauma_treat_var: float\n",
+ " Variance of the trauma cubicle treatment distribution (Lognormal)\n",
+ " \n",
+ " non_trauma_treat_mean: float\n",
+ " Mean of the non trauma treatment distribution\n",
+ " \n",
+ " non_trauma_treat_var: float\n",
+ " Variance of the non trauma treatment distribution\n",
+ " \n",
+ " non_trauma_treat_p: float\n",
+ " Probability non trauma patient requires treatment\n",
+ " \n",
+ " prob_trauma: float\n",
+ " probability that a new arrival is a trauma patient.\n",
" '''\n",
" # sampling\n",
" self.random_number_set = random_number_set\n",
+ " \n",
+ " # store parameters for sampling\n",
+ " self.triage_mean = triage_mean\n",
+ " self.reg_mean = reg_mean\n",
+ " self.reg_var = reg_var\n",
+ " self.exam_mean= exam_mean\n",
+ " self.exam_var = exam_var\n",
+ " self.trauma_mean = trauma_mean\n",
+ " self.trauma_treat_mean = trauma_treat_mean\n",
+ " self.trauma_treat_var = trauma_treat_var\n",
+ " self.non_trauma_treat_mean = non_trauma_treat_mean\n",
+ " self.non_trauma_treat_var = non_trauma_treat_var\n",
+ " self.non_trauma_treat_p = non_trauma_treat_p\n",
+ " self.prob_trauma = prob_trauma\n",
+ " \n",
" self.init_sampling()\n",
" \n",
" # count of each type of resource\n",
- " self.init_resourse_counts()\n",
+ " self.init_resourse_counts(n_triage, n_reg, n_exam, n_trauma,\n",
+ " n_cubicles_1, n_cubicles_2)\n",
" \n",
" def set_random_no_set(self, random_number_set):\n",
" '''\n",
@@ -521,18 +609,19 @@
" self.random_number_set = random_number_set\n",
" self.init_sampling()\n",
"\n",
- " def init_resourse_counts(self):\n",
+ " def init_resourse_counts(self, n_triage, n_reg, n_exam, n_trauma,\n",
+ " n_cubicles_1, n_cubicles_2):\n",
" '''\n",
" Init the counts of resources to default values...\n",
" '''\n",
- " self.n_triage = DEFAULT_N_TRIAGE\n",
- " self.n_reg = DEFAULT_N_REG\n",
- " self.n_exam = DEFAULT_N_EXAM\n",
- " self.n_trauma = DEFAULT_N_TRAUMA\n",
+ " self.n_triage = n_triage\n",
+ " self.n_reg = n_reg\n",
+ " self.n_exam = n_exam\n",
+ " self.n_trauma = n_trauma\n",
" \n",
" # non-trauma (1), trauma (2) treatment cubicles\n",
- " self.n_cubicles_1 = DEFAULT_N_CUBICLES_1\n",
- " self.n_cubicles_2 = DEFAULT_N_CUBICLES_2\n",
+ " self.n_cubicles_1 = n_cubicles_1\n",
+ " self.n_cubicles_2 = n_cubicles_2\n",
"\n",
" def init_sampling(self):\n",
" '''\n",
@@ -546,40 +635,40 @@
" # create distributions\n",
" \n",
" # Triage duration\n",
- " self.triage_dist = Exponential(DEFAULT_TRIAGE_MEAN, \n",
+ " self.triage_dist = Exponential(self.triage_mean, \n",
" random_seed=self.seeds[0])\n",
" \n",
" # Registration duration (non-trauma only)\n",
- " self.reg_dist = Lognormal(DEFAULT_REG_MEAN, \n",
- " np.sqrt(DEFAULT_REG_VAR),\n",
+ " self.reg_dist = Lognormal(self.reg_mean, \n",
+ " np.sqrt(self.reg_var),\n",
" random_seed=self.seeds[1])\n",
" \n",
" # Evaluation (non-trauma only)\n",
- " self.exam_dist = Normal(DEFAULT_EXAM_MEAN,\n",
- " np.sqrt(DEFAULT_EXAM_VAR),\n",
+ " self.exam_dist = Normal(self.exam_mean,\n",
+ " np.sqrt(self.exam_var),\n",
" random_seed=self.seeds[2])\n",
" \n",
" # Trauma/stablisation duration (trauma only)\n",
- " self.trauma_dist = Exponential(DEFAULT_TRAUMA_MEAN, \n",
+ " self.trauma_dist = Exponential(self.trauma_mean, \n",
" random_seed=self.seeds[3])\n",
" \n",
" # Non-trauma treatment\n",
- " self.nt_treat_dist = Lognormal(DEFAULT_NON_TRAUMA_TREAT_MEAN, \n",
- " np.sqrt(DEFAULT_NON_TRAUMA_TREAT_VAR),\n",
+ " self.nt_treat_dist = Lognormal(self.non_trauma_treat_mean, \n",
+ " np.sqrt(self.non_trauma_treat_var),\n",
" random_seed=self.seeds[4])\n",
" \n",
" # treatment of trauma patients\n",
- " self.treat_dist = Lognormal(DEFAULT_TRAUMA_TREAT_MEAN, \n",
- " np.sqrt(DEFAULT_TRAUMA_TREAT_VAR),\n",
+ " self.treat_dist = Lognormal(self.trauma_treat_mean, \n",
+ " np.sqrt(self.non_trauma_treat_var),\n",
" random_seed=self.seeds[5])\n",
" \n",
" # probability of non-trauma patient requiring treatment\n",
- " self.nt_p_treat_dist = Bernoulli(DEFAULT_NON_TRAUMA_TREAT_P, \n",
+ " self.nt_p_treat_dist = Bernoulli(self.non_trauma_treat_p, \n",
" random_seed=self.seeds[6])\n",
" \n",
" \n",
" # probability of non-trauma versus trauma patient\n",
- " self.p_trauma_dist = Bernoulli(DEFAULT_PROB_TRAUMA, \n",
+ " self.p_trauma_dist = Bernoulli(self.prob_trauma, \n",
" random_seed=self.seeds[7])\n",
" \n",
" # init sampling for non-stationary poisson process\n",
@@ -752,7 +841,7 @@
"metadata": {},
"outputs": [],
"source": [
- "class NonTraumaPathway(object):\n",
+ "class NonTraumaPathway:\n",
" '''\n",
" Encapsulates the process a patient with minor injuries and illness.\n",
" \n",
@@ -1536,8 +1625,8 @@
"text": [
"Running multiple replications => done.\n",
"\n",
- "CPU times: user 2.52 s, sys: 42.7 ms, total: 2.56 s\n",
- "Wall time: 3.88 s\n"
+ "CPU times: user 2.09 s, sys: 12.9 ms, total: 2.11 s\n",
+ "Wall time: 3.46 s\n"
]
},
{
@@ -1821,20 +1910,16 @@
" scenarios['base'] = Scenario()\n",
" \n",
" # extra triage capacity\n",
- " scenarios['triage+1'] = Scenario()\n",
- " scenarios['triage+1'].n_triage += 1\n",
+ " scenarios['triage+1'] = Scenario(n_triage=DEFAULT_N_TRIAGE+1)\n",
" \n",
" # extra examination capacity\n",
- " scenarios['exam+1'] = Scenario()\n",
- " scenarios['exam+1'].n_exam += 1\n",
+ " scenarios['exam+1'] = Scenario(n_exam=DEFAULT_N_EXAM+1)\n",
" \n",
" # extra non-trauma treatment capacity\n",
- " scenarios['treat+1'] = Scenario()\n",
- " scenarios['treat+1'].n_cubicles_1 += 1\n",
+ " scenarios['treat+1'] = Scenario(n_cubicles_1=DEFAULT_N_CUBICLES_1+1)\n",
" \n",
- " scenarios['triage+exam'] = Scenario()\n",
- " scenarios['triage+exam'].n_triage += 1\n",
- " scenarios['triage+exam'].n_exam += 1\n",
+ " scenarios['triage+exam'] = Scenario(n_triage=DEFAULT_N_TRIAGE+1,\n",
+ " n_exam=DEFAULT_N_EXAM+1)\n",
" \n",
" return scenarios"
]
@@ -2170,7 +2255,7 @@
},
{
"cell_type": "code",
- "execution_count": 91,
+ "execution_count": 26,
"id": "4d2d0e59",
"metadata": {},
"outputs": [
@@ -2272,7 +2357,7 @@
"5 Trauma treatment 168.27 209.12 195.16 150.37 193.69"
]
},
- "execution_count": 91,
+ "execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
@@ -2298,7 +2383,7 @@
},
{
"cell_type": "code",
- "execution_count": 123,
+ "execution_count": 27,
"id": "e6453c53",
"metadata": {},
"outputs": [
diff --git a/src/requirements.txt b/src/requirements.txt
index 39f94b1..1dfdeff 100644
--- a/src/requirements.txt
+++ b/src/requirements.txt
@@ -1,5 +1,5 @@
- matplotlib==3.3.4
- numpy==1.19.2
- pandas==1.2.3
- scipy==1.6.1
- simpy==4.0.1
+ matplotlib>=3.3.4
+ numpy>=1.19.2
+ pandas>=1.2.3
+ scipy>=1.6.1
+ simpy>=4.0.1
diff --git a/src/test_pacakge.ipynb b/src/test_pacakge.ipynb
deleted file mode 100644
index e69de29..0000000
diff --git a/src/test_package.ipynb b/src/test_package.ipynb
new file mode 100644
index 0000000..a492577
--- /dev/null
+++ b/src/test_package.ipynb
@@ -0,0 +1,613 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "6b983b2d-37be-4418-a71c-3f61bcd09f82",
+ "metadata": {},
+ "source": [
+ "# Test package\n",
+ "\n",
+ "This notebook is a simple test script for the simulation model."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b67e319d-7f3f-42a2-9f2e-176a6bbb0a43",
+ "metadata": {},
+ "source": [
+ "# Aggregate test: run all scenarios"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "cf77eab0-8038-4e89-b0a8-abae02c61046",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from treat_sim.model import (get_scenarios, run_scenario_analysis,\n",
+ " scenario_summary_frame, \n",
+ " DEFAULT_RESULTS_COLLECTION_PERIOD)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "a4427a5c-a048-4e78-81ad-9a72a62b982f",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Scenario Analysis\n",
+ "No. Scenario: 6\n",
+ "Replications: 50\n",
+ "Running base => done.\n",
+ "\n",
+ "Running triage+1 => done.\n",
+ "\n",
+ "Running exam+1 => done.\n",
+ "\n",
+ "Running treat+1 => done.\n",
+ "\n",
+ "Running swap_exam_treat => done.\n",
+ "\n",
+ "Running short_exam => done.\n",
+ "\n",
+ "Scenario analysis complete.\n"
+ ]
+ }
+ ],
+ "source": [
+ "results = run_scenario_analysis(get_scenarios(), DEFAULT_RESULTS_COLLECTION_PERIOD,\n",
+ " n_reps=50)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "42d1d046-102e-4edc-8f22-98ea40429e27",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " base | \n",
+ " triage+1 | \n",
+ " exam+1 | \n",
+ " treat+1 | \n",
+ " swap_exam_treat | \n",
+ " short_exam | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 00_arrivals | \n",
+ " 223.900000 | \n",
+ " 223.900000 | \n",
+ " 223.900000 | \n",
+ " 223.900000 | \n",
+ " 223.900000 | \n",
+ " 223.900000 | \n",
+ "
\n",
+ " \n",
+ " | 01a_triage_wait | \n",
+ " 35.272640 | \n",
+ " 1.591082 | \n",
+ " 35.272640 | \n",
+ " 35.272640 | \n",
+ " 1.591082 | \n",
+ " 1.591082 | \n",
+ "
\n",
+ " \n",
+ " | 01b_triage_util | \n",
+ " 0.583945 | \n",
+ " 0.291972 | \n",
+ " 0.583945 | \n",
+ " 0.583945 | \n",
+ " 0.291972 | \n",
+ " 0.291972 | \n",
+ "
\n",
+ " \n",
+ " | 02a_registration_wait | \n",
+ " 106.992158 | \n",
+ " 136.547677 | \n",
+ " 106.992158 | \n",
+ " 106.992158 | \n",
+ " 136.547677 | \n",
+ " 136.547677 | \n",
+ "
\n",
+ " \n",
+ " | 02b_registration_util | \n",
+ " 0.830571 | \n",
+ " 0.837294 | \n",
+ " 0.830571 | \n",
+ " 0.830571 | \n",
+ " 0.837294 | \n",
+ " 0.837294 | \n",
+ "
\n",
+ " \n",
+ " | 03a_examination_wait | \n",
+ " 27.527119 | \n",
+ " 28.238646 | \n",
+ " 0.150533 | \n",
+ " 27.527119 | \n",
+ " 156.243354 | \n",
+ " 70.804411 | \n",
+ "
\n",
+ " \n",
+ " | 03b_examination_util | \n",
+ " 0.842010 | \n",
+ " 0.844921 | \n",
+ " 0.662485 | \n",
+ " 0.842010 | \n",
+ " 0.885413 | \n",
+ " 0.865748 | \n",
+ "
\n",
+ " \n",
+ " | 04a_treatment_wait(non_trauma) | \n",
+ " 141.596946 | \n",
+ " 145.386882 | \n",
+ " 158.289641 | \n",
+ " 2.539007 | \n",
+ " 33.407448 | \n",
+ " 116.539079 | \n",
+ "
\n",
+ " \n",
+ " | 04b_treatment_util(non_trauma) | \n",
+ " 0.851111 | \n",
+ " 0.852151 | \n",
+ " 0.853278 | \n",
+ " 0.627436 | \n",
+ " 0.830502 | \n",
+ " 0.855542 | \n",
+ "
\n",
+ " \n",
+ " | 05_total_time(non-trauma) | \n",
+ " 240.195093 | \n",
+ " 237.010351 | \n",
+ " 228.377890 | \n",
+ " 195.550827 | \n",
+ " 288.135496 | \n",
+ " 251.677548 | \n",
+ "
\n",
+ " \n",
+ " | 06a_trauma_wait | \n",
+ " 100.379713 | \n",
+ " 123.372108 | \n",
+ " 100.379713 | \n",
+ " 100.379713 | \n",
+ " 123.372108 | \n",
+ " 123.372108 | \n",
+ "
\n",
+ " \n",
+ " | 06b_trauma_util | \n",
+ " 0.786821 | \n",
+ " 0.786666 | \n",
+ " 0.786821 | \n",
+ " 0.786821 | \n",
+ " 0.786666 | \n",
+ " 0.786666 | \n",
+ "
\n",
+ " \n",
+ " | 07a_treatment_wait(trauma) | \n",
+ " 199.937931 | \n",
+ " 233.482451 | \n",
+ " 199.937931 | \n",
+ " 199.937931 | \n",
+ " 233.482451 | \n",
+ " 233.482451 | \n",
+ "
\n",
+ " \n",
+ " | 07b_treatment_util(trauma) | \n",
+ " 0.879220 | \n",
+ " 0.899172 | \n",
+ " 0.879220 | \n",
+ " 0.879220 | \n",
+ " 0.899172 | \n",
+ " 0.899172 | \n",
+ "
\n",
+ " \n",
+ " | 08_total_time(trauma) | \n",
+ " 418.140509 | \n",
+ " 430.158680 | \n",
+ " 418.140509 | \n",
+ " 418.140509 | \n",
+ " 430.158680 | \n",
+ " 430.158680 | \n",
+ "
\n",
+ " \n",
+ " | 09_throughput | \n",
+ " 151.500000 | \n",
+ " 151.400000 | \n",
+ " 155.500000 | \n",
+ " 185.700000 | \n",
+ " 127.800000 | \n",
+ " 145.400000 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " base triage+1 exam+1 \\\n",
+ "00_arrivals 223.900000 223.900000 223.900000 \n",
+ "01a_triage_wait 35.272640 1.591082 35.272640 \n",
+ "01b_triage_util 0.583945 0.291972 0.583945 \n",
+ "02a_registration_wait 106.992158 136.547677 106.992158 \n",
+ "02b_registration_util 0.830571 0.837294 0.830571 \n",
+ "03a_examination_wait 27.527119 28.238646 0.150533 \n",
+ "03b_examination_util 0.842010 0.844921 0.662485 \n",
+ "04a_treatment_wait(non_trauma) 141.596946 145.386882 158.289641 \n",
+ "04b_treatment_util(non_trauma) 0.851111 0.852151 0.853278 \n",
+ "05_total_time(non-trauma) 240.195093 237.010351 228.377890 \n",
+ "06a_trauma_wait 100.379713 123.372108 100.379713 \n",
+ "06b_trauma_util 0.786821 0.786666 0.786821 \n",
+ "07a_treatment_wait(trauma) 199.937931 233.482451 199.937931 \n",
+ "07b_treatment_util(trauma) 0.879220 0.899172 0.879220 \n",
+ "08_total_time(trauma) 418.140509 430.158680 418.140509 \n",
+ "09_throughput 151.500000 151.400000 155.500000 \n",
+ "\n",
+ " treat+1 swap_exam_treat short_exam \n",
+ "00_arrivals 223.900000 223.900000 223.900000 \n",
+ "01a_triage_wait 35.272640 1.591082 1.591082 \n",
+ "01b_triage_util 0.583945 0.291972 0.291972 \n",
+ "02a_registration_wait 106.992158 136.547677 136.547677 \n",
+ "02b_registration_util 0.830571 0.837294 0.837294 \n",
+ "03a_examination_wait 27.527119 156.243354 70.804411 \n",
+ "03b_examination_util 0.842010 0.885413 0.865748 \n",
+ "04a_treatment_wait(non_trauma) 2.539007 33.407448 116.539079 \n",
+ "04b_treatment_util(non_trauma) 0.627436 0.830502 0.855542 \n",
+ "05_total_time(non-trauma) 195.550827 288.135496 251.677548 \n",
+ "06a_trauma_wait 100.379713 123.372108 123.372108 \n",
+ "06b_trauma_util 0.786821 0.786666 0.786666 \n",
+ "07a_treatment_wait(trauma) 199.937931 233.482451 233.482451 \n",
+ "07b_treatment_util(trauma) 0.879220 0.899172 0.899172 \n",
+ "08_total_time(trauma) 418.140509 430.158680 430.158680 \n",
+ "09_throughput 185.700000 127.800000 145.400000 "
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "scenario_summary_frame(results)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9dacbdbe-2d3a-4eb9-b6d4-6976291ddec3",
+ "metadata": {},
+ "source": [
+ "## Test: single scenario"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "cda7e07f-7ab7-45a9-9559-62073c3a4fc0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from treat_sim.model import Scenario, multiple_replications"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "cdb93109-1054-4493-b4c6-743d70be8a8c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "base_case = Scenario()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "id": "f1b2bdd9-4015-49db-9ca7-92c32c70935e",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " count | \n",
+ " mean | \n",
+ " std | \n",
+ " min | \n",
+ " 25% | \n",
+ " 50% | \n",
+ " 75% | \n",
+ " max | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 00_arrivals | \n",
+ " 5.0 | \n",
+ " 224.20 | \n",
+ " 22.59 | \n",
+ " 188.00 | \n",
+ " 218.00 | \n",
+ " 233.00 | \n",
+ " 236.00 | \n",
+ " 246.00 | \n",
+ "
\n",
+ " \n",
+ " | 01a_triage_wait | \n",
+ " 5.0 | \n",
+ " 27.79 | \n",
+ " 23.65 | \n",
+ " 3.24 | \n",
+ " 13.04 | \n",
+ " 28.01 | \n",
+ " 29.25 | \n",
+ " 65.41 | \n",
+ "
\n",
+ " \n",
+ " | 01b_triage_util | \n",
+ " 5.0 | \n",
+ " 0.56 | \n",
+ " 0.07 | \n",
+ " 0.48 | \n",
+ " 0.53 | \n",
+ " 0.54 | \n",
+ " 0.62 | \n",
+ " 0.65 | \n",
+ "
\n",
+ " \n",
+ " | 02a_registration_wait | \n",
+ " 5.0 | \n",
+ " 112.53 | \n",
+ " 34.71 | \n",
+ " 63.31 | \n",
+ " 91.14 | \n",
+ " 128.49 | \n",
+ " 130.09 | \n",
+ " 149.64 | \n",
+ "
\n",
+ " \n",
+ " | 02b_registration_util | \n",
+ " 5.0 | \n",
+ " 0.83 | \n",
+ " 0.05 | \n",
+ " 0.75 | \n",
+ " 0.83 | \n",
+ " 0.84 | \n",
+ " 0.85 | \n",
+ " 0.88 | \n",
+ "
\n",
+ " \n",
+ " | 03a_examination_wait | \n",
+ " 5.0 | \n",
+ " 26.98 | \n",
+ " 9.31 | \n",
+ " 16.33 | \n",
+ " 18.40 | \n",
+ " 28.48 | \n",
+ " 35.42 | \n",
+ " 36.25 | \n",
+ "
\n",
+ " \n",
+ " | 03b_examination_util | \n",
+ " 5.0 | \n",
+ " 0.84 | \n",
+ " 0.03 | \n",
+ " 0.80 | \n",
+ " 0.82 | \n",
+ " 0.85 | \n",
+ " 0.85 | \n",
+ " 0.88 | \n",
+ "
\n",
+ " \n",
+ " | 04a_treatment_wait(non_trauma) | \n",
+ " 5.0 | \n",
+ " 145.01 | \n",
+ " 16.96 | \n",
+ " 125.02 | \n",
+ " 134.20 | \n",
+ " 145.41 | \n",
+ " 150.89 | \n",
+ " 169.50 | \n",
+ "
\n",
+ " \n",
+ " | 04b_treatment_util(non_trauma) | \n",
+ " 5.0 | \n",
+ " 0.85 | \n",
+ " 0.01 | \n",
+ " 0.83 | \n",
+ " 0.84 | \n",
+ " 0.85 | \n",
+ " 0.85 | \n",
+ " 0.86 | \n",
+ "
\n",
+ " \n",
+ " | 05_total_time(non-trauma) | \n",
+ " 5.0 | \n",
+ " 236.64 | \n",
+ " 43.75 | \n",
+ " 178.80 | \n",
+ " 206.95 | \n",
+ " 247.87 | \n",
+ " 260.80 | \n",
+ " 288.80 | \n",
+ "
\n",
+ " \n",
+ " | 06a_trauma_wait | \n",
+ " 5.0 | \n",
+ " 109.07 | \n",
+ " 86.61 | \n",
+ " 8.60 | \n",
+ " 65.15 | \n",
+ " 78.13 | \n",
+ " 168.01 | \n",
+ " 225.47 | \n",
+ "
\n",
+ " \n",
+ " | 06b_trauma_util | \n",
+ " 5.0 | \n",
+ " 0.78 | \n",
+ " 0.24 | \n",
+ " 0.37 | \n",
+ " 0.82 | \n",
+ " 0.84 | \n",
+ " 0.88 | \n",
+ " 0.98 | \n",
+ "
\n",
+ " \n",
+ " | 07a_treatment_wait(trauma) | \n",
+ " 5.0 | \n",
+ " 161.30 | \n",
+ " 102.68 | \n",
+ " 13.24 | \n",
+ " 95.60 | \n",
+ " 214.20 | \n",
+ " 231.60 | \n",
+ " 251.84 | \n",
+ "
\n",
+ " \n",
+ " | 07b_treatment_util(trauma) | \n",
+ " 5.0 | \n",
+ " 0.96 | \n",
+ " 0.24 | \n",
+ " 0.65 | \n",
+ " 0.78 | \n",
+ " 0.98 | \n",
+ " 1.19 | \n",
+ " 1.19 | \n",
+ "
\n",
+ " \n",
+ " | 08_total_time(trauma) | \n",
+ " 5.0 | \n",
+ " 377.22 | \n",
+ " 23.66 | \n",
+ " 339.82 | \n",
+ " 369.28 | \n",
+ " 385.75 | \n",
+ " 392.06 | \n",
+ " 399.20 | \n",
+ "
\n",
+ " \n",
+ " | 09_throughput | \n",
+ " 5.0 | \n",
+ " 151.40 | \n",
+ " 8.08 | \n",
+ " 139.00 | \n",
+ " 148.00 | \n",
+ " 154.00 | \n",
+ " 157.00 | \n",
+ " 159.00 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " count mean std min 25% 50% \\\n",
+ "00_arrivals 5.0 224.20 22.59 188.00 218.00 233.00 \n",
+ "01a_triage_wait 5.0 27.79 23.65 3.24 13.04 28.01 \n",
+ "01b_triage_util 5.0 0.56 0.07 0.48 0.53 0.54 \n",
+ "02a_registration_wait 5.0 112.53 34.71 63.31 91.14 128.49 \n",
+ "02b_registration_util 5.0 0.83 0.05 0.75 0.83 0.84 \n",
+ "03a_examination_wait 5.0 26.98 9.31 16.33 18.40 28.48 \n",
+ "03b_examination_util 5.0 0.84 0.03 0.80 0.82 0.85 \n",
+ "04a_treatment_wait(non_trauma) 5.0 145.01 16.96 125.02 134.20 145.41 \n",
+ "04b_treatment_util(non_trauma) 5.0 0.85 0.01 0.83 0.84 0.85 \n",
+ "05_total_time(non-trauma) 5.0 236.64 43.75 178.80 206.95 247.87 \n",
+ "06a_trauma_wait 5.0 109.07 86.61 8.60 65.15 78.13 \n",
+ "06b_trauma_util 5.0 0.78 0.24 0.37 0.82 0.84 \n",
+ "07a_treatment_wait(trauma) 5.0 161.30 102.68 13.24 95.60 214.20 \n",
+ "07b_treatment_util(trauma) 5.0 0.96 0.24 0.65 0.78 0.98 \n",
+ "08_total_time(trauma) 5.0 377.22 23.66 339.82 369.28 385.75 \n",
+ "09_throughput 5.0 151.40 8.08 139.00 148.00 154.00 \n",
+ "\n",
+ " 75% max \n",
+ "00_arrivals 236.00 246.00 \n",
+ "01a_triage_wait 29.25 65.41 \n",
+ "01b_triage_util 0.62 0.65 \n",
+ "02a_registration_wait 130.09 149.64 \n",
+ "02b_registration_util 0.85 0.88 \n",
+ "03a_examination_wait 35.42 36.25 \n",
+ "03b_examination_util 0.85 0.88 \n",
+ "04a_treatment_wait(non_trauma) 150.89 169.50 \n",
+ "04b_treatment_util(non_trauma) 0.85 0.86 \n",
+ "05_total_time(non-trauma) 260.80 288.80 \n",
+ "06a_trauma_wait 168.01 225.47 \n",
+ "06b_trauma_util 0.88 0.98 \n",
+ "07a_treatment_wait(trauma) 231.60 251.84 \n",
+ "07b_treatment_util(trauma) 1.19 1.19 \n",
+ "08_total_time(trauma) 392.06 399.20 \n",
+ "09_throughput 157.00 159.00 "
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "multiple_replications(base_case).describe().round(2).T"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.12"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/src/treat_sim/__init__.py b/src/treat_sim/__init__.py
index 63755d2..986ae5e 100644
--- a/src/treat_sim/__init__.py
+++ b/src/treat_sim/__init__.py
@@ -1,2 +1,2 @@
__author__ = 'T.Monks'
-__version__ = '0.1.0'
+__version__ = '1.0.0'
diff --git a/src/treat_sim/model.py b/src/treat_sim/model.py
index 086cb94..d911574 100644
--- a/src/treat_sim/model.py
+++ b/src/treat_sim/model.py
@@ -159,39 +159,117 @@ def trace(msg):
# ## Model parameterisation
-
class Scenario:
'''
Container class for scenario parameters/arguments
-
- For convienience a container class is used to hold the large number of model
- parameters. The `Scenario` class includes defaults these can easily be
- changed and at runtime to experiments with different designs.
Passed to a model and its process classes
'''
- def __init__(self, random_number_set=DEFAULT_RNG_SET):
+ def __init__(self, random_number_set=DEFAULT_RNG_SET,
+ n_triage=DEFAULT_N_TRIAGE,
+ n_reg=DEFAULT_N_REG,
+ n_exam=DEFAULT_N_EXAM,
+ n_trauma=DEFAULT_N_TRAUMA,
+ n_cubicles_1=DEFAULT_N_CUBICLES_1,
+ n_cubicles_2=DEFAULT_N_CUBICLES_2,
+ triage_mean=DEFAULT_TRIAGE_MEAN,
+ reg_mean=DEFAULT_REG_MEAN,
+ reg_var=DEFAULT_REG_VAR,
+ exam_mean=DEFAULT_EXAM_MEAN,
+ exam_var=DEFAULT_EXAM_VAR,
+ trauma_mean=DEFAULT_TRAUMA_MEAN,
+ trauma_treat_mean=DEFAULT_TRAUMA_TREAT_MEAN,
+ trauma_treat_var=DEFAULT_TRAUMA_TREAT_VAR,
+ non_trauma_treat_mean=DEFAULT_NON_TRAUMA_TREAT_MEAN,
+ non_trauma_treat_var=DEFAULT_NON_TRAUMA_TREAT_VAR,
+ non_trauma_treat_p=DEFAULT_NON_TRAUMA_TREAT_P,
+ prob_trauma=DEFAULT_PROB_TRAUMA):
'''
- The init method sets up our defaults.
+ Create a scenario to parameterise the simulation model
Parameters:
-----------
random_number_set: int, optional (default=DEFAULT_RNG_SET)
Set to control the initial seeds of each stream of pseudo
random numbers used in the model.
+
+ n_triage: int
+ The number of triage cubicles
+
+ n_reg: int
+ The number of registration clerks
+
+ n_exam: int
+ The number of examination rooms
+
+ n_trauma: int
+ The number of trauma bays for stablisation
+
+ n_cubicles_1: int
+ The number of non-trauma treatment cubicles
+
+ n_cubicles_2: int
+ The number of trauma treatment cubicles
+
+ triage_mean: float
+ Mean duration of the triage distribution (Exponential)
+
+ reg_mean: float
+ Mean duration of the registration distribution (Lognormal)
+
+ reg_var: float
+ Variance of the registration distribution (Lognormal)
+
+ exam_mean: float
+ Mean of the examination distribution (Normal)
+
+ exam_var: float
+ Variance of the examination distribution (Normal)
+
+ trauma_mean: float
+ Mean of the trauma stabilisation distribution (Exponential)
+
+ trauma_treat_mean: float
+ Mean of the trauma cubicle treatment distribution (Lognormal)
+
+ trauma_treat_var: float
+ Variance of the trauma cubicle treatment distribution (Lognormal)
+
+ non_trauma_treat_mean: float
+ Mean of the non trauma treatment distribution
+
+ non_trauma_treat_var: float
+ Variance of the non trauma treatment distribution
+
+ non_trauma_treat_p: float
+ Probability non trauma patient requires treatment
+
+ prob_trauma: float
+ probability that a new arrival is a trauma patient.
'''
# sampling
self.random_number_set = random_number_set
-
- # count of each type of resource
- self.init_resourse_counts()
-
- # pathway variables
- self.init_pathway_variables()
-
- # sampling distributions
+
+ # store parameters for sampling
+ self.triage_mean = triage_mean
+ self.reg_mean = reg_mean
+ self.reg_var = reg_var
+ self.exam_mean= exam_mean
+ self.exam_var = exam_var
+ self.trauma_mean = trauma_mean
+ self.trauma_treat_mean = trauma_treat_mean
+ self.trauma_treat_var = trauma_treat_var
+ self.non_trauma_treat_mean = non_trauma_treat_mean
+ self.non_trauma_treat_var = non_trauma_treat_var
+ self.non_trauma_treat_p = non_trauma_treat_p
+ self.prob_trauma = prob_trauma
+
self.init_sampling()
-
+
+ # count of each type of resource
+ self.init_resourse_counts(n_triage, n_reg, n_exam, n_trauma,
+ n_cubicles_1, n_cubicles_2)
+
def set_random_no_set(self, random_number_set):
'''
Controls the random sampling
@@ -204,65 +282,19 @@ def set_random_no_set(self, random_number_set):
self.random_number_set = random_number_set
self.init_sampling()
- def init_resourse_counts(self):
+ def init_resourse_counts(self, n_triage, n_reg, n_exam, n_trauma,
+ n_cubicles_1, n_cubicles_2):
'''
Init the counts of resources to default values...
'''
- self.n_triage = DEFAULT_N_TRIAGE
- self.n_reg = DEFAULT_N_REG
- self.n_exam = DEFAULT_N_EXAM
- self.n_trauma = DEFAULT_N_TRAUMA
+ self.n_triage = n_triage
+ self.n_reg = n_reg
+ self.n_exam = n_exam
+ self.n_trauma = n_trauma
# non-trauma (1), trauma (2) treatment cubicles
- self.n_cubicles_1 = DEFAULT_N_CUBICLES_1
- self.n_cubicles_2 = DEFAULT_N_CUBICLES_2
-
- def init_pathway_variables(self):
- # trauma pathway
- self.prob_trauma = DEFAULT_PROB_TRAUMA
- self.treat_trauma_mean = DEFAULT_TRAUMA_TREAT_MEAN
- self.treat_trauma_var = DEFAULT_TRAUMA_TREAT_VAR
-
- #non trauma pathway
- self.exam_mean = DEFAULT_EXAM_MEAN
- self.exam_var = DEFAULT_EXAM_VAR
-
- self.nt_treat_prob = DEFAULT_NON_TRAUMA_TREAT_P
- self.nt_treat_mean = DEFAULT_NON_TRAUMA_TREAT_MEAN
- self.nt_treat_var = DEFAULT_NON_TRAUMA_TREAT_VAR
-
- # def __eq__(self, other):
- # return self.n_triage == other.n_triage and \
- # self.n_reg == other.n_reg and \
- # self.n_exam == other.n_exam and \
- # self.n_trauma == other.n_trauma and \
- # self.n_cubicles_1 == other.n_cubicles_1 and \
- # self.n_cubicles_2 == other.n_cubicles_2 and \
- # self.prob_trauma == other.prob_trauma and \
- # self.treat_trauma_mean == other.treat_trauma_mean and \
- # self.treat_trauma_var == other.treat_trauma_var and \
- # self.exam_mean == other.exam_mean and \
- # self.exam_var == other.exam_var and \
- # self.nt_treat_prob == other.nt_treat_prob and \
- # self.nt_treat_mean == other.self.nt_treat_mean and \
- # self.nt_treat_var == other.nt_treat_var
-
- # def __hash__(self):
- # ''''''
- # return hash((self.n_triage,
- # self.n_reg,
- # self.n_exam,
- # self.n_trauma,
- # self.n_cubicles_1,
- # self.n_cubicles_2,
- # self.prob_trauma,
- # self.treat_trauma_mean,
- # self.treat_trauma_var,
- # self.exam_mean,
- # self.exam_var,
- # self.nt_treat_prob,
- # self.nt_treat_mean,
- # self.nt_treat_var))
+ self.n_cubicles_1 = n_cubicles_1
+ self.n_cubicles_2 = n_cubicles_2
def init_sampling(self):
'''
@@ -276,12 +308,12 @@ def init_sampling(self):
# create distributions
# Triage duration
- self.triage_dist = Exponential(DEFAULT_TRIAGE_MEAN,
+ self.triage_dist = Exponential(self.triage_mean,
random_seed=self.seeds[0])
# Registration duration (non-trauma only)
- self.reg_dist = Lognormal(DEFAULT_REG_MEAN,
- np.sqrt(DEFAULT_REG_VAR),
+ self.reg_dist = Lognormal(self.reg_mean,
+ np.sqrt(self.reg_var),
random_seed=self.seeds[1])
# Evaluation (non-trauma only)
@@ -290,21 +322,21 @@ def init_sampling(self):
random_seed=self.seeds[2])
# Trauma/stablisation duration (trauma only)
- self.trauma_dist = Exponential(DEFAULT_TRAUMA_MEAN,
+ self.trauma_dist = Exponential(self.trauma_mean,
random_seed=self.seeds[3])
# Non-trauma treatment
- self.nt_treat_dist = Lognormal(self.nt_treat_mean,
- np.sqrt(self.nt_treat_var),
+ self.nt_treat_dist = Lognormal(self.non_trauma_treat_mean,
+ np.sqrt(self.non_trauma_treat_var),
random_seed=self.seeds[4])
# treatment of trauma patients
- self.treat_dist = Lognormal(self.treat_trauma_mean,
- np.sqrt(self.treat_trauma_var),
+ self.treat_dist = Lognormal(self.trauma_treat_mean,
+ np.sqrt(self.non_trauma_treat_var),
random_seed=self.seeds[5])
# probability of non-trauma patient requiring treatment
- self.nt_p_treat_dist = Bernoulli(self.nt_treat_prob,
+ self.nt_p_treat_dist = Bernoulli(self.non_trauma_treat_p,
random_seed=self.seeds[6])
@@ -314,8 +346,7 @@ def init_sampling(self):
# init sampling for non-stationary poisson process
self.init_nspp()
-
-
+
def init_nspp(self):
# read arrival profile
@@ -1028,31 +1059,26 @@ def get_scenarios():
scenarios['base'] = Scenario()
# extra triage capacity
- scenarios['triage+1'] = Scenario()
- scenarios['triage+1'].n_triage += 1
+ scenarios['triage+1'] = Scenario(n_triage=DEFAULT_N_TRIAGE+1)
# extra examination capacity
- scenarios['exam+1'] = Scenario()
- scenarios['exam+1'].n_exam += 1
+ scenarios['exam+1'] = Scenario(n_exam=DEFAULT_N_EXAM+1)
# extra non-trauma treatment capacity
- scenarios['treat+1'] = Scenario()
- scenarios['treat+1'].n_cubicles_1 += 1
+ scenarios['treat+1'] = Scenario(n_cubicles_1=DEFAULT_N_CUBICLES_1+1)
- #swap over 1 exam room for extra treat cubicle
- scenarios['swap_exam_treat'] = Scenario()
- scenarios['swap_exam_treat'].n_cubicles_1 += 1
- scenarios['swap_exam_treat'].n_exam -= 1
-
- #scenario + 3 min short mean exam times.
- scenarios['short_exam'] = Scenario()
- scenarios['short_exam'].n_cubicles_1 += 1
- scenarios['short_exam'].n_exam -= 1
- scenarios['short_exam'].exam_mean = 12.0
+ # swap over 1 exam room for extra treat cubicle
+ scenarios['swap_exam_treat'] = Scenario(n_triage=DEFAULT_N_TRIAGE+1,
+ n_exam=DEFAULT_N_EXAM-1)
+ # scenario + 3 min short mean exam times.
+ scenarios['short_exam'] = Scenario(n_triage=DEFAULT_N_TRIAGE+1,
+ n_exam=DEFAULT_N_EXAM-1,
+ exam_mean=12.0)
return scenarios
+
def run_scenario_analysis(scenarios, rc_period, n_reps):
'''
Run each of the scenarios for a specified results