11
11
from .parameters import Parameters
12
12
13
13
DATE_FORMAT = "%b, %d" # see https://strftime.org
14
-
14
+ DOCS_URL = "https://code-for-philly.gitbook.io/chime"
15
15
16
16
hide_menu_style = """
17
17
<style>
@@ -63,7 +63,12 @@ def display_header(st, m, p):
63
63
"""**IMPORTANT NOTICE**: Admissions and Census calculations were previously **undercounting**. Please update your reports generated before """ + p .change_date () + """. See more about changes [here](https://github.com/CodeForPhilly/chime/labels/models)."""
64
64
)
65
65
st .markdown (
66
- """*This tool was developed by the [Predictive Healthcare team](http://predictivehealthcare.pennmedicine.org/) at [Penn Medicine](https://www.pennmedicine.org) to assist hospitals and public health officials with hospital capacity planning, but can be used anywhere in the world. Customize it for your region by modifying data inputs in the left pane, or read the [User Documentation](https://code-for-philly.gitbook.io/chime/) to learn more.*"""
66
+ """*This tool was developed by the [Predictive Healthcare team](http://predictivehealthcare.pennmedicine.org/) at
67
+ Penn Medicine to assist hospitals and public health officials with hospital capacity planning,
68
+ but can be used anywhere in the world.
69
+ Customize it for your region by modifying data inputs in the left panel.
70
+ For questions on how to use this tool see the [User docs]({docs_url}). Code can be found on [Github](https://github.com/CodeForPhilly/chime)*.
71
+ """ .format (docs_url = DOCS_URL )
67
72
)
68
73
69
74
st .markdown (
@@ -95,6 +100,7 @@ def display_header(st, m, p):
95
100
r_t = m .r_t ,
96
101
doubling_time_t = abs (m .doubling_time_t ),
97
102
impact_statement = ("halves the infections every" if m .r_t < 1 else "reduces the doubling time to" ),
103
+ docs_url = DOCS_URL ,
98
104
infection_warning_str = infection_warning_str ,
99
105
infected_population_warning_str = infected_population_warning_str
100
106
)
@@ -103,6 +109,30 @@ def display_header(st, m, p):
103
109
return None
104
110
105
111
112
+ class InputWrapper :
113
+ """Helper to separate Streamlit input definition from creation/rendering"""
114
+ def __init__ (self , st_obj , label , value , kwargs ):
115
+ self .st_obj = st_obj
116
+ self .label = label
117
+ self .value = value
118
+ self .kwargs = kwargs
119
+
120
+ def build (self ):
121
+ return self .st_obj (self .label , value = self .value , ** self .kwargs )
122
+
123
+
124
+ class NumberInputWrapper (InputWrapper ):
125
+ def __init__ (self , st_obj , label , min_value = None , max_value = None , value = None , step = None , format = None , key = None ):
126
+ kwargs = dict (min_value = min_value , max_value = max_value , step = step , format = format , key = key )
127
+ super ().__init__ (st_obj .number_input , label , value , kwargs )
128
+
129
+
130
+ class CheckboxWrapper (InputWrapper ):
131
+ def __init__ (self , st_obj , label , value = None , key = None ):
132
+ kwargs = dict (key = key )
133
+ super ().__init__ (st_obj .checkbox , label , value , kwargs )
134
+
135
+
106
136
def display_sidebar (st , d : Constants ) -> Parameters :
107
137
# Initialize variables
108
138
# these functions create input elements and bind the values they are set to
@@ -111,149 +141,163 @@ def display_sidebar(st, d: Constants) -> Parameters:
111
141
112
142
if d .known_infected < 1 :
113
143
raise ValueError ("Known cases must be larger than one to enable predictions." )
114
-
115
- n_days = st .sidebar .number_input (
116
- "Number of days to project" ,
117
- min_value = 30 ,
118
- value = d .n_days ,
119
- step = 10 ,
120
- format = "%i" ,
121
- )
122
-
123
- current_hospitalized = st .sidebar .number_input (
144
+ st_obj = st .sidebar
145
+ current_hospitalized = NumberInputWrapper (
146
+ st_obj ,
124
147
"Currently Hospitalized COVID-19 Patients" ,
125
148
min_value = 0 ,
126
149
value = d .current_hospitalized ,
127
150
step = 1 ,
128
151
format = "%i" ,
129
152
)
130
-
131
- doubling_time = st .sidebar .number_input (
153
+ n_days = NumberInputWrapper (
154
+ st_obj ,
155
+ "Number of days to project" ,
156
+ min_value = 30 ,
157
+ value = d .n_days ,
158
+ step = 10 ,
159
+ format = "%i" ,
160
+ )
161
+ doubling_time = NumberInputWrapper (
162
+ st_obj ,
132
163
"Doubling time before social distancing (days)" ,
133
164
min_value = 0 ,
134
165
value = d .doubling_time ,
135
166
step = 1 ,
136
167
format = "%i" ,
137
168
)
138
-
139
- relative_contact_rate = (
140
- st .sidebar .number_input (
141
- "Social distancing (% reduction in social contact)" ,
142
- min_value = 0 ,
143
- max_value = 100 ,
144
- value = int (d .relative_contact_rate * 100 ),
145
- step = 5 ,
146
- format = "%i" ,
147
- )
148
- / 100.0
149
- )
150
-
151
- hospitalized_rate = (
152
- st .sidebar .number_input (
153
- "Hospitalization %(total infections)" ,
154
- min_value = 0.001 ,
155
- max_value = 100.0 ,
156
- value = d .hospitalized .rate * 100 ,
157
- step = 1.0 ,
158
- format = "%f" ,
159
- )
160
- / 100.0
161
- )
162
- icu_rate = (
163
- st .sidebar .number_input (
164
- "ICU %(total infections)" ,
165
- min_value = 0.0 ,
166
- max_value = 100.0 ,
167
- value = d .icu .rate * 100 ,
168
- step = 1.0 ,
169
- format = "%f" ,
170
- )
171
- / 100.0
172
- )
173
- ventilated_rate = (
174
- st .sidebar .number_input (
175
- "Ventilated %(total infections)" ,
176
- min_value = 0.0 ,
177
- max_value = 100.0 ,
178
- value = d .ventilated .rate * 100 ,
179
- step = 1.0 ,
180
- format = "%f" ,
181
- )
182
- / 100.0
169
+ relative_contact_rate = NumberInputWrapper (
170
+ st_obj ,
171
+ "Social distancing (% reduction in social contact)" ,
172
+ min_value = 0 ,
173
+ max_value = 100 ,
174
+ value = int (d .relative_contact_rate * 100 ),
175
+ step = 5 ,
176
+ format = "%i" ,
183
177
)
184
-
185
- hospitalized_los = st .sidebar .number_input (
178
+ hospitalized_rate = NumberInputWrapper (
179
+ st_obj ,
180
+ "Hospitalization %(total infections)" ,
181
+ min_value = 0.001 ,
182
+ max_value = 100.0 ,
183
+ value = d .hospitalized .rate * 100 ,
184
+ step = 1.0 ,
185
+ format = "%f" ,
186
+ )
187
+ icu_rate = NumberInputWrapper (
188
+ st_obj ,
189
+ "ICU %(total infections)" ,
190
+ min_value = 0.0 ,
191
+ max_value = 100.0 ,
192
+ value = d .icu .rate * 100 ,
193
+ step = 1.0 ,
194
+ format = "%f" ,
195
+ )
196
+ ventilated_rate = NumberInputWrapper (
197
+ st_obj ,
198
+ "Ventilated %(total infections)" ,
199
+ min_value = 0.0 ,
200
+ max_value = 100.0 ,
201
+ value = d .ventilated .rate * 100 ,
202
+ step = 1.0 ,
203
+ format = "%f" ,
204
+ )
205
+ hospitalized_los = NumberInputWrapper (
206
+ st_obj ,
186
207
"Hospital Length of Stay" ,
187
208
min_value = 0 ,
188
209
value = d .hospitalized .length_of_stay ,
189
210
step = 1 ,
190
211
format = "%i" ,
191
212
)
192
- icu_los = st .sidebar .number_input (
213
+ icu_los = NumberInputWrapper (
214
+ st_obj ,
193
215
"ICU Length of Stay" ,
194
216
min_value = 0 ,
195
217
value = d .icu .length_of_stay ,
196
218
step = 1 ,
197
219
format = "%i" ,
198
220
)
199
- ventilated_los = st .sidebar .number_input (
221
+ ventilated_los = NumberInputWrapper (
222
+ st_obj ,
200
223
"Vent Length of Stay" ,
201
224
min_value = 0 ,
202
225
value = d .ventilated .length_of_stay ,
203
226
step = 1 ,
204
227
format = "%i" ,
205
228
)
206
-
207
- market_share = (
208
- st .sidebar .number_input (
209
- "Hospital Market Share (%)" ,
210
- min_value = 0.001 ,
211
- max_value = 100.0 ,
212
- value = d .market_share * 100 ,
213
- step = 1.0 ,
214
- format = "%f" ,
215
- )
216
- / 100.0
217
- )
218
- susceptible = st .sidebar .number_input (
229
+ market_share = NumberInputWrapper (
230
+ st_obj ,
231
+ "Hospital Market Share (%)" ,
232
+ min_value = 0.001 ,
233
+ max_value = 100.0 ,
234
+ value = d .market_share * 100 ,
235
+ step = 1.0 ,
236
+ format = "%f" ,
237
+ )
238
+ susceptible = NumberInputWrapper (
239
+ st_obj ,
219
240
"Regional Population" ,
220
241
min_value = 1 ,
221
242
value = d .region .susceptible ,
222
243
step = 100000 ,
223
244
format = "%i" ,
224
245
)
225
-
226
- known_infected = st . sidebar . number_input (
246
+ known_infected = NumberInputWrapper (
247
+ st_obj ,
227
248
"Currently Known Regional Infections (only used to compute detection rate - does not change projections)" ,
228
249
min_value = 0 ,
229
250
value = d .known_infected ,
230
251
step = 10 ,
231
252
format = "%i" ,
232
253
)
254
+ as_date = CheckboxWrapper (st_obj , "Present result as dates instead of days" , value = False )
255
+ max_y_axis_set = CheckboxWrapper (st_obj , "Set the Y-axis on graphs to a static value" )
233
256
234
- as_date = st .sidebar .checkbox (label = "Present result as dates instead of days" , value = False )
235
-
236
- max_y_axis_set = st .sidebar .checkbox ("Set the Y-axis on graphs to a static value" )
237
257
max_y_axis = None
238
258
if max_y_axis_set :
239
- max_y_axis = st .sidebar .number_input (
240
- "Y-axis static value" , value = 500 , format = "%i" , step = 25 ,
241
- )
259
+ max_y_axis = NumberInputWrapper (st_obj , "Y-axis static value" , value = 500 , format = "%i" , step = 25 )
260
+
261
+ # Build in desired order
262
+ st .sidebar .markdown ("### Regional Parameters [ℹ]({docs_url}/what-is-chime/parameters)" .format (docs_url = DOCS_URL ))
263
+ susceptible .build ()
264
+ market_share .build ()
265
+ known_infected .build ()
266
+ current_hospitalized .build ()
267
+
268
+ st .sidebar .markdown ("### Spread and Contact Parameters [ℹ]({docs_url}/what-is-chime/parameters)"
269
+ .format (docs_url = DOCS_URL ))
270
+ doubling_time .build ()
271
+ relative_contact_rate .build ()
272
+
273
+ st .sidebar .markdown ("### Severity Parameters [ℹ]({docs_url}/what-is-chime/parameters)" .format (docs_url = DOCS_URL ))
274
+ hospitalized_rate .build ()
275
+ icu_rate .build ()
276
+ ventilated_rate .build ()
277
+ hospitalized_los .build ()
278
+ icu_los .build ()
279
+ ventilated_los .build ()
280
+
281
+ st .sidebar .markdown ("### Display Parameters [ℹ]({docs_url}/what-is-chime/parameters)" .format (docs_url = DOCS_URL ))
282
+ n_days .build ()
283
+ max_y_axis .build ()
284
+ as_date .build ()
242
285
243
286
return Parameters (
244
- as_date = as_date ,
245
- current_hospitalized = current_hospitalized ,
246
- doubling_time = doubling_time ,
247
- known_infected = known_infected ,
248
- market_share = market_share ,
249
- max_y_axis = max_y_axis ,
250
- n_days = n_days ,
251
- relative_contact_rate = relative_contact_rate ,
252
- susceptible = susceptible ,
287
+ as_date = as_date .value ,
288
+ current_hospitalized = current_hospitalized .value ,
289
+ market_share = market_share .value ,
290
+ known_infected = known_infected .value ,
291
+ doubling_time = doubling_time .value ,
292
+
293
+ max_y_axis = max_y_axis .value ,
294
+ n_days = n_days .value ,
295
+ relative_contact_rate = relative_contact_rate .value / 100.0 ,
296
+ susceptible = susceptible .value ,
253
297
254
- hospitalized = RateLos (hospitalized_rate , hospitalized_los ),
255
- icu = RateLos (icu_rate , icu_los ),
256
- ventilated = RateLos (ventilated_rate , ventilated_los ),
298
+ hospitalized = RateLos (hospitalized_rate . value / 100.0 , hospitalized_los . value ),
299
+ icu = RateLos (icu_rate . value / 100.0 , icu_los . value ),
300
+ ventilated = RateLos (ventilated_rate . value / 100.0 , ventilated_los . value ),
257
301
)
258
302
259
303
@@ -362,7 +406,7 @@ def write_definitions(st):
362
406
st .subheader ("Guidance on Selecting Inputs" )
363
407
st .markdown (
364
408
"""**This information has been moved to the
365
- [User Documentation](https://code-for-philly.gitbook.io/chime/ what-is-chime/parameters#guidance-on-selecting-inputs)**"""
409
+ [User Documentation]({docs_url}/ what-is-chime/parameters#guidance-on-selecting-inputs)**""" . format ( docs_url = DOCS_URL )
366
410
)
367
411
368
412
0 commit comments