|
17 | 17 | "import plotly.express as px\n", |
18 | 18 | "\n", |
19 | 19 | "from simulation.parameters import Param\n", |
20 | | - "from simulation.model import Model" |
| 20 | + "from simulation.model import Model\n", |
| 21 | + "from simulation.runner import Runner" |
21 | 22 | ] |
22 | 23 | }, |
23 | 24 | { |
|
43 | 44 | "metadata": {}, |
44 | 45 | "outputs": [], |
45 | 46 | "source": [ |
46 | | - "# Run the model\n", |
47 | | - "model = Model(param=Param(), run_number=0)\n", |
48 | | - "model.run()" |
| 47 | + "# Set up runner\n", |
| 48 | + "runner = Runner(param=Param(cores=8))" |
49 | 49 | ] |
50 | 50 | }, |
51 | 51 | { |
|
55 | 55 | "outputs": [ |
56 | 56 | { |
57 | 57 | "data": { |
| 58 | + "text/html": [ |
| 59 | + "<div>\n", |
| 60 | + "<style scoped>\n", |
| 61 | + " .dataframe tbody tr th:only-of-type {\n", |
| 62 | + " vertical-align: middle;\n", |
| 63 | + " }\n", |
| 64 | + "\n", |
| 65 | + " .dataframe tbody tr th {\n", |
| 66 | + " vertical-align: top;\n", |
| 67 | + " }\n", |
| 68 | + "\n", |
| 69 | + " .dataframe thead th {\n", |
| 70 | + " text-align: right;\n", |
| 71 | + " }\n", |
| 72 | + "</style>\n", |
| 73 | + "<table border=\"1\" class=\"dataframe\">\n", |
| 74 | + " <thead>\n", |
| 75 | + " <tr style=\"text-align: right;\">\n", |
| 76 | + " <th></th>\n", |
| 77 | + " <th>beds</th>\n", |
| 78 | + " <th>freq</th>\n", |
| 79 | + " <th>pct</th>\n", |
| 80 | + " <th>c_pct</th>\n", |
| 81 | + " <th>prob_delay</th>\n", |
| 82 | + " </tr>\n", |
| 83 | + " </thead>\n", |
| 84 | + " <tbody>\n", |
| 85 | + " <tr>\n", |
| 86 | + " <th>0</th>\n", |
| 87 | + " <td>1</td>\n", |
| 88 | + " <td>1</td>\n", |
| 89 | + " <td>0.000548</td>\n", |
| 90 | + " <td>0.000548</td>\n", |
| 91 | + " <td>1.000000</td>\n", |
| 92 | + " </tr>\n", |
| 93 | + " <tr>\n", |
| 94 | + " <th>1</th>\n", |
| 95 | + " <td>2</td>\n", |
| 96 | + " <td>12</td>\n", |
| 97 | + " <td>0.006575</td>\n", |
| 98 | + " <td>0.007123</td>\n", |
| 99 | + " <td>0.923077</td>\n", |
| 100 | + " </tr>\n", |
| 101 | + " <tr>\n", |
| 102 | + " <th>2</th>\n", |
| 103 | + " <td>3</td>\n", |
| 104 | + " <td>39</td>\n", |
| 105 | + " <td>0.021370</td>\n", |
| 106 | + " <td>0.028493</td>\n", |
| 107 | + " <td>0.750000</td>\n", |
| 108 | + " </tr>\n", |
| 109 | + " <tr>\n", |
| 110 | + " <th>3</th>\n", |
| 111 | + " <td>4</td>\n", |
| 112 | + " <td>76</td>\n", |
| 113 | + " <td>0.041644</td>\n", |
| 114 | + " <td>0.070137</td>\n", |
| 115 | + " <td>0.593750</td>\n", |
| 116 | + " </tr>\n", |
| 117 | + " <tr>\n", |
| 118 | + " <th>4</th>\n", |
| 119 | + " <td>5</td>\n", |
| 120 | + " <td>134</td>\n", |
| 121 | + " <td>0.073425</td>\n", |
| 122 | + " <td>0.143562</td>\n", |
| 123 | + " <td>0.511450</td>\n", |
| 124 | + " </tr>\n", |
| 125 | + " </tbody>\n", |
| 126 | + "</table>\n", |
| 127 | + "</div>" |
| 128 | + ], |
58 | 129 | "text/plain": [ |
59 | | - "[{'time': 1095, 'asu_occupancy': 7, 'rehab_occupancy': 12},\n", |
60 | | - " {'time': 1096, 'asu_occupancy': 5, 'rehab_occupancy': 11},\n", |
61 | | - " {'time': 1097, 'asu_occupancy': 5, 'rehab_occupancy': 10},\n", |
62 | | - " {'time': 1098, 'asu_occupancy': 4, 'rehab_occupancy': 10},\n", |
63 | | - " {'time': 1099, 'asu_occupancy': 5, 'rehab_occupancy': 10}]" |
| 130 | + " beds freq pct c_pct prob_delay\n", |
| 131 | + "0 1 1 0.000548 0.000548 1.000000\n", |
| 132 | + "1 2 12 0.006575 0.007123 0.923077\n", |
| 133 | + "2 3 39 0.021370 0.028493 0.750000\n", |
| 134 | + "3 4 76 0.041644 0.070137 0.593750\n", |
| 135 | + "4 5 134 0.073425 0.143562 0.511450" |
64 | 136 | ] |
65 | 137 | }, |
66 | 138 | "execution_count": 4, |
|
69 | 141 | } |
70 | 142 | ], |
71 | 143 | "source": [ |
72 | | - "# Preview some of the results\n", |
73 | | - "model.audit_list[0:5]" |
| 144 | + "# Run once and preview results\n", |
| 145 | + "single_results = runner.run_single(run=0)\n", |
| 146 | + "single_results[\"asu\"].head()" |
74 | 147 | ] |
75 | 148 | }, |
76 | 149 | { |
77 | | - "cell_type": "markdown", |
| 150 | + "cell_type": "code", |
| 151 | + "execution_count": 5, |
78 | 152 | "metadata": {}, |
| 153 | + "outputs": [], |
79 | 154 | "source": [ |
80 | | - "## Figure 1\n", |
81 | | - "\n", |
82 | | - "**Figure 1.** Simulation probability density function for occupancy of an acute stroke unit.\n", |
83 | | - "\n", |
84 | | - "**Relevant functions...**" |
| 155 | + "# Run replications\n", |
| 156 | + "rep_results = runner.run_reps()" |
85 | 157 | ] |
86 | 158 | }, |
87 | 159 | { |
88 | | - "cell_type": "code", |
89 | | - "execution_count": 5, |
| 160 | + "cell_type": "markdown", |
90 | 161 | "metadata": {}, |
91 | | - "outputs": [], |
92 | 162 | "source": [ |
93 | | - "def get_occupancy_freq(unit):\n", |
94 | | - " \"\"\"\n", |
95 | | - " Count the frequency each occupancy level was observed at within the\n", |
96 | | - " interval audit for the specified unit.\n", |
97 | | - "\n", |
98 | | - " Parameters\n", |
99 | | - " ----------\n", |
100 | | - " unit: str\n", |
101 | | - " Name of unit to plot (\"asu\", \"rehab\").\n", |
102 | | - "\n", |
103 | | - " Returns\n", |
104 | | - " -------\n", |
105 | | - " df: pd.DataFrame\n", |
106 | | - " Dataframe with two columns: the number of beds (\"beds\") and the\n", |
107 | | - " frequency this was observed in the audit (\"freq\").\n", |
108 | | - " \"\"\"\n", |
109 | | - " # Get occupancy audit results\n", |
110 | | - " occ_audit = pd.DataFrame(model.audit_list)\n", |
111 | | - "\n", |
112 | | - " # Get the frequency of each number of beds in the specified unit\n", |
113 | | - " frequency = Counter(occ_audit[f\"{unit}_occupancy\"])\n", |
114 | | - "\n", |
115 | | - " # Fill in any gaps - find the maximum bed count, then create complete\n", |
116 | | - " # dictionary include bed counts which were never observed\n", |
117 | | - " min_bed_count = min(frequency.keys())\n", |
118 | | - " max_bed_count = max(frequency.keys())\n", |
119 | | - " complete_frequency = {i: frequency.get(i, 0)\n", |
120 | | - " for i in range(min_bed_count, max_bed_count + 1)}\n", |
121 | | - "\n", |
122 | | - " # Convert into a dataframe\n", |
123 | | - " df = pd.DataFrame(\n", |
124 | | - " complete_frequency.items(), columns=[\"beds\", \"freq\"])\n", |
125 | | - "\n", |
126 | | - " # Add column with frequencies converted to proportions\n", |
127 | | - " df[\"pct\"] = df[\"freq\"] / df[\"freq\"].sum()\n", |
128 | | - "\n", |
129 | | - " # Add column with the cumulative percentage\n", |
130 | | - " df[\"c_pct\"] = df[\"pct\"].cumsum()\n", |
| 163 | + "## Figure 1\n", |
131 | 164 | "\n", |
132 | | - " return df" |
| 165 | + "**Figure 1.** Simulation probability density function for occupancy of an acute stroke unit." |
133 | 166 | ] |
134 | 167 | }, |
135 | 168 | { |
|
1900 | 1933 | ], |
1901 | 1934 | "source": [ |
1902 | 1935 | "# Acute stroke unit\n", |
1903 | | - "asu_occupancy = get_occupancy_freq(\"asu\")\n", |
1904 | | - "plot_occupancy_freq(asu_occupancy, unit=\"asu\",\n", |
| 1936 | + "plot_occupancy_freq(single_results[\"asu\"], unit=\"asu\",\n", |
1905 | 1937 | " file=\"occupancy_freq_asu.png\")\n", |
1906 | 1938 | "\n", |
1907 | 1939 | "# Rehabilitation unit\n", |
1908 | | - "rehab_occupancy = get_occupancy_freq(\"rehab\")\n", |
1909 | | - "plot_occupancy_freq(rehab_occupancy, unit=\"rehab\",\n", |
| 1940 | + "plot_occupancy_freq(single_results[\"rehab\"], unit=\"rehab\",\n", |
1910 | 1941 | " file=\"occupancy_freq_rehab.png\")" |
1911 | 1942 | ] |
1912 | 1943 | }, |
|
1918 | 1949 | "\n", |
1919 | 1950 | "**Figure 3**. Simulated trade-off between the probability that a patient is delayed and the no. of acute beds available.\n", |
1920 | 1951 | "\n", |
1921 | | - "### Explanation of the method for calculating blocking probability\n", |
1922 | | - "\n", |
1923 | 1952 | "We can use our frequency and cumulative frequency of occupied beds from the simulation to calculate blocking probability.\n", |
1924 | 1953 | "\n", |
1925 | | - "Above, we created the tables..." |
| 1954 | + "Our model output these tables..." |
1926 | 1955 | ] |
1927 | 1956 | }, |
1928 | 1957 | { |
|
1955 | 1984 | " <th>freq</th>\n", |
1956 | 1985 | " <th>pct</th>\n", |
1957 | 1986 | " <th>c_pct</th>\n", |
| 1987 | + " <th>prob_delay</th>\n", |
1958 | 1988 | " </tr>\n", |
1959 | 1989 | " </thead>\n", |
1960 | 1990 | " <tbody>\n", |
|
1964 | 1994 | " <td>1</td>\n", |
1965 | 1995 | " <td>0.000548</td>\n", |
1966 | 1996 | " <td>0.000548</td>\n", |
| 1997 | + " <td>1.000000</td>\n", |
1967 | 1998 | " </tr>\n", |
1968 | 1999 | " <tr>\n", |
1969 | 2000 | " <th>1</th>\n", |
1970 | 2001 | " <td>2</td>\n", |
1971 | 2002 | " <td>12</td>\n", |
1972 | 2003 | " <td>0.006575</td>\n", |
1973 | 2004 | " <td>0.007123</td>\n", |
| 2005 | + " <td>0.923077</td>\n", |
1974 | 2006 | " </tr>\n", |
1975 | 2007 | " <tr>\n", |
1976 | 2008 | " <th>2</th>\n", |
1977 | 2009 | " <td>3</td>\n", |
1978 | 2010 | " <td>39</td>\n", |
1979 | 2011 | " <td>0.021370</td>\n", |
1980 | 2012 | " <td>0.028493</td>\n", |
| 2013 | + " <td>0.750000</td>\n", |
1981 | 2014 | " </tr>\n", |
1982 | 2015 | " <tr>\n", |
1983 | 2016 | " <th>3</th>\n", |
1984 | 2017 | " <td>4</td>\n", |
1985 | 2018 | " <td>76</td>\n", |
1986 | 2019 | " <td>0.041644</td>\n", |
1987 | 2020 | " <td>0.070137</td>\n", |
| 2021 | + " <td>0.593750</td>\n", |
1988 | 2022 | " </tr>\n", |
1989 | 2023 | " <tr>\n", |
1990 | 2024 | " <th>4</th>\n", |
1991 | 2025 | " <td>5</td>\n", |
1992 | 2026 | " <td>134</td>\n", |
1993 | 2027 | " <td>0.073425</td>\n", |
1994 | 2028 | " <td>0.143562</td>\n", |
| 2029 | + " <td>0.511450</td>\n", |
1995 | 2030 | " </tr>\n", |
1996 | 2031 | " </tbody>\n", |
1997 | 2032 | "</table>\n", |
1998 | 2033 | "</div>" |
1999 | 2034 | ], |
2000 | 2035 | "text/plain": [ |
2001 | | - " beds freq pct c_pct\n", |
2002 | | - "0 1 1 0.000548 0.000548\n", |
2003 | | - "1 2 12 0.006575 0.007123\n", |
2004 | | - "2 3 39 0.021370 0.028493\n", |
2005 | | - "3 4 76 0.041644 0.070137\n", |
2006 | | - "4 5 134 0.073425 0.143562" |
| 2036 | + " beds freq pct c_pct prob_delay\n", |
| 2037 | + "0 1 1 0.000548 0.000548 1.000000\n", |
| 2038 | + "1 2 12 0.006575 0.007123 0.923077\n", |
| 2039 | + "2 3 39 0.021370 0.028493 0.750000\n", |
| 2040 | + "3 4 76 0.041644 0.070137 0.593750\n", |
| 2041 | + "4 5 134 0.073425 0.143562 0.511450" |
2007 | 2042 | ] |
2008 | 2043 | }, |
2009 | 2044 | "execution_count": 8, |
|
2012 | 2047 | } |
2013 | 2048 | ], |
2014 | 2049 | "source": [ |
2015 | | - "asu_occupancy.head()" |
| 2050 | + "single_results[\"asu\"].head()" |
2016 | 2051 | ] |
2017 | 2052 | }, |
2018 | 2053 | { |
|
2045 | 2080 | "* Any new patients arriving when 8 beds are occupied would experience a delay.\n", |
2046 | 2081 | "* So 0.6 represents the probability that, given we're at or below capacity (7 or 8 beds), we're actually at full capacity (8 beds)\n", |
2047 | 2082 | "\n", |
2048 | | - "In other words, `pct/c_pct` is the probability that a new arrival will experience a delay when the system has exactly x beds occupied, given that the capacity of the system is x beds.\n", |
2049 | | - "\n", |
2050 | | - "### Implementing this method" |
| 2083 | + "In other words, `pct/c_pct` is the probability that a new arrival will experience a delay when the system has exactly x beds occupied, given that the capacity of the system is x beds." |
2051 | 2084 | ] |
2052 | 2085 | }, |
2053 | 2086 | { |
|
2073 | 2106 | " path: str\n", |
2074 | 2107 | " Path to save file to (excluding filename).\n", |
2075 | 2108 | " \"\"\"\n", |
2076 | | - " # Calculate the probability of delay\n", |
2077 | | - " df[\"prob_delay\"] = df[\"pct\"] / df[\"c_pct\"]\n", |
2078 | | - "\n", |
2079 | 2109 | " # Create the step plot\n", |
2080 | 2110 | " fig = px.line(df, x=\"beds\", y=\"prob_delay\",\n", |
2081 | 2111 | " color_discrete_sequence=[\"black\"])\n", |
|
3902 | 3932 | } |
3903 | 3933 | ], |
3904 | 3934 | "source": [ |
3905 | | - "plot_delay_prob(asu_occupancy, unit=\"asu\", file=\"delay_prob_asu.png\")\n", |
3906 | | - "plot_delay_prob(rehab_occupancy, unit=\"rehab\", file=\"delay_prob_rehab.png\")" |
| 3935 | + "plot_delay_prob(single_results[\"asu\"], unit=\"asu\", file=\"delay_prob_asu.png\")\n", |
| 3936 | + "plot_delay_prob(single_results[\"rehab\"], unit=\"rehab\",\n", |
| 3937 | + " file=\"delay_prob_rehab.png\")" |
3907 | 3938 | ] |
3908 | 3939 | } |
3909 | 3940 | ], |
|
0 commit comments