Commit cf2ca077 authored by Markus Kongstein Rognlien's avatar Markus Kongstein Rognlien
Browse files

Merge branch 'covid-calculator' into 'master'

Covid calculator

See merge request !8
parents b48a2961 b7bd89dc
%% Cell type:code id: tags:
``` python
import ipywidgets as w
```
%% Cell type:code id: tags:
``` python
name_text = w.Text(placeholder="E.g. Workshop without masks", description="Simulation name:",
style={'description_width': 'auto'}, layout=w.Layout(width='auto'))
room_number_text = w.Text(placeholder="E.g. 17/R-033", description="Room number:",
style={'description_width': 'auto'}, layout=w.Layout(width='auto'))
intro_box = w.VBox(children=(w.HTML(value='<font size="+2"><b>CARA</b> Covid Calculator</font>'),
name_text,
room_number_text),
layout=w.Layout(padding='0px 0px 50px 0px'))
```
%% Cell type:code id: tags:
``` python
volume_text = w.Text(placeholder="Room volume (m³)", description="Room volume", layout=w.Layout(width='auto'))
area_text = w.Text(placeholder="Room floor area (m²)", description="Floor area", layout=w.Layout(width='auto'))
height_text = w.Text(placeholder="Room ceiling height (m²)", description="Ceiling height", layout=w.Layout(width='auto'))
room_dimensions_box = w.VBox(children=(volume_text, w.Label(value="------- OR -------"),area_text, height_text),
layout=w.Layout(padding='0px 0px 50px 0px'))
def manage_room_text_fields(_):
volume_text.disabled = bool(area_text.value) or bool(height_text.value)
area_text.disabled = bool(volume_text.value)
height_text.disabled = bool(volume_text.value)
for text in [volume_text, area_text, height_text]:
text.observe(manage_room_text_fields)
text.style.description_width = "auto"
volume_text.observe(manage_room_text_fields)
area_text.observe(manage_room_text_fields)
height_text.observe(manage_room_text_fields)
```
%% Cell type:code id: tags:
``` python
ventilation_label = w.Label("Ventilation type:")
mechanical_button = w.ToggleButton(value=False, description='Mechanical', layout={'width': 'auto'})
natural_button = w.ToggleButton(value=False, description='Natural', layout={'width': 'auto'})
acph_text = w.Text(description="Air changes per hour", style={'description_width': 'auto'}, layout=w.Layout(width='auto'))
asfr_text = w.Text(description="Air supply flow rate", style={'description_width': 'auto'}, layout=w.Layout(width='auto'))
w.jsdlink((acph_text, 'value'), (asfr_text, 'disabled'))
w.jsdlink((asfr_text, 'value'), (acph_text, 'disabled'))
mech_vent_box = w.VBox(
children=(acph_text, w.Label(value="------- OR -------"), asfr_text),
layout=w.Layout(display='none', width='auto')
)
number_of_windows_text = w.Text(description='Number of windows:', style={'description_width': 'auto'},
layout=w.Layout(width='auto'))
height_of_window_text = w.Text(description='Height of window:', placeholder='meters',
style={'description_width': 'auto'}, layout=w.Layout(width='auto'))
width_of_window_text = w.Text(description='Width of window:', placeholder='meters', style={'description_width': 'auto'},
layout=w.Layout(width='auto'))
opening_distance_text = w.Text(description='Opening distance:', placeholder='centimeters', style={'description_width': 'auto'},
layout=w.Layout(width='auto'))
window_open_buttons = w.RadioButtons(options=('Always', '15 min / 2h'), layout=w.Layout(width='auto'))
nat_vent_box = w.VBox(
children=(
number_of_windows_text,
opening_distance_text,
width_of_window_text,
opening_distance_text,
w.HBox(children=(
w.Label('Windows open', layout=w.Layout(width='auto')),
window_open_buttons
))
),
layout=w.Layout(display='none', width='auto'),
)
tab_bar = w.HBox(children=(mechanical_button, natural_button))
ventilation_type_menu = w.VBox(children=(ventilation_label, tab_bar), layout=w.Layout(padding='0px 0px 20px 0px'))
ventilation_box = w.VBox(children=(ventilation_type_menu, mech_vent_box, nat_vent_box),
layout=w.Layout(padding='0px 0px 50px 0px'))
def handle_natural_toggle(_):
if natural_button.value:
mechanical_button.value = False
ventilation_box.children[2].layout.display = 'contents'
else:
ventilation_box.children[2].layout.display = 'none'
def handle_mechanical_toggle(_):
if mechanical_button.value:
natural_button.value = False
ventilation_box.children[1].layout.display = 'contents'
else:
ventilation_box.children[1].layout.display = 'none'
natural_button.observe(handle_natural_toggle)
mechanical_button.observe(handle_mechanical_toggle)
left_column = w.VBox(children=(intro_box, room_dimensions_box, ventilation_box),
layout=w.Layout(width='25%', padding="0px 20px 0px 0px"))
```
%% Cell type:code id: tags:
``` python
event_data_label = w.Label("Event data:")
attendees_label = w.Label("Attendees:")
total_people_text = w.Text(description="Total number of people:", style={'description_width': 'auto'},
layout=w.Layout(width='auto'))
infected_people_text = w.Text(description="Number of infected people:", style={'description_width': 'auto'},
layout=w.Layout(width='auto'))
activity_dropdown = w.Dropdown(description="Activity type:", options=["Training", "Workshop", "Office"], value=None,
layout=w.Layout(width='auto'))
start_hour = w.Dropdown(options=["HH"] + [("0" + str(i)) if len(str(i)) == 1 else str(i) for i in range(24)], value="HH")
start_minute = w.Dropdown(options=["MM"] + [("0" + str(i)) if len(str(i)) == 1 else str(i) for i in range(60)], value="MM")
finish_hour = w.Dropdown(options=["HH"] + [("0" + str(i)) if len(str(i)) == 1 else str(i) for i in range(24)], value="HH")
finish_minute = w.Dropdown(options=["MM"] + [("0" + str(i)) if len(str(i)) == 1 else str(i) for i in range(60)], value="MM")
start_box = w.VBox(children=(w.Label("Start:"),
w.HBox(children=(start_hour, start_minute))),
layout=w.Layout(padding="0px 20px 0px 0px"))
finish_box = w.VBox(children=(w.Label("Finish:"),
w.HBox(children=(finish_hour, finish_minute))))
event_time_box = w.HBox(children=(start_box, finish_box), layout=w.Layout(width='auto'))
event_intro_box = w.VBox(children=(event_data_label,
attendees_label,
total_people_text,
infected_people_text,
activity_dropdown,
event_time_box),
layout=w.Layout(padding="50px 0px 20px 0px"))
months = ("january", "february", "march", "april", "may", "june",
"july", "august", "september", "october", "november", "december")
single_button = w.ToggleButton(value=False, description='Single event', layout={'width': 'auto'})
recurrent_button = w.ToggleButton(value=False, description='Recurrent usage', layout={'width': 'auto'})
single_recurrent_selection_bar = w.HBox(children=(single_button, recurrent_button), layout=w.Layout(width='auto'), style={'description_width': 'auto'})
month_dropdown = w.Dropdown(options=months, value=None, description="Month:", layout=w.Layout(width='auto'), style={'description_width': 'auto'})
day_dropdown = w.Dropdown(options=[i for i in range(1, 32)], value=None, description="Day:", layout=w.Layout(width='auto'))
date_selector = w.HBox(children=(month_dropdown, day_dropdown), layout=w.Layout(display='none', width='auto'))
months_bar = w.HBox(children=[w.ToggleButton(value=False, description=month[0].upper()) for month in months],
layout = w.Layout(display='none'))
def handle_single_click(_):
if single_button.value:
date_selector.layout.display = 'contents'
recurrent_button.value = False
else:
date_selector.layout.display = 'none'
def handle_recurrent_click(_):
if recurrent_button.value:
months_bar.layout.display = 'contents'
single_button.value = False
else:
months_bar.layout.display = 'none'
single_button.observe(handle_single_click)
recurrent_button.observe(handle_recurrent_click)
date_box = w.VBox(children=(w.HBox(children=(single_button, recurrent_button)),
w.HBox(children=(date_selector, months_bar))),
layout=w.Layout(padding="0px 0px 30px 0px"))
lunch_start_hour = w.Dropdown(options=["HH"] + [("0" + str(i)) if len(str(i)) == 1 else str(i) for i in range(24)],
value="HH", disabled=True)
lunch_start_minute = w.Dropdown(options=["MM"] + [("0" + str(i)) if len(str(i)) == 1 else str(i) for i in range(60)],
value="MM", disabled=True)
lunch_finish_hour = w.Dropdown(options=["HH"] + [("0" + str(i)) if len(str(i)) == 1 else str(i) for i in range(24)],
value="HH", disabled=True)
lunch_finish_minute = w.Dropdown(options=["MM"] + [("0" + str(i)) if len(str(i)) == 1 else str(i) for i in range(60)],
value="MM", disabled=True)
lunch_start_box = w.VBox(children=(w.Label("Start:"),
w.HBox(children=(lunch_start_hour, lunch_start_minute))),
layout=w.Layout(padding="0px 20px 0px 0px"))
lunch_finish_box = w.VBox(children=(w.Label("Finish:"),
w.HBox(children=(lunch_finish_hour, lunch_finish_minute))))
lunch_time_box = w.HBox(children=(lunch_start_box, lunch_finish_box), layout=w.Layout(width='auto'))
lunch_button = w.ToggleButton(value=False, description="Lunch break")
def handle_lunch(_):
for dropdown in (lunch_start_hour, lunch_start_minute, lunch_finish_hour, lunch_finish_minute):
dropdown.disabled = not lunch_button.value
lunch_button.observe(handle_lunch)
lunch_break_box = w.VBox(children=(lunch_button, lunch_time_box), layout=w.Layout(padding='0px 0px 20px 0px'))
coffee_button = w.ToggleButton(value=False, description="Coffee breaks")
coffee_breaks_text = w.Text(description="Number of breaks:", disabled=True, style={'description_width': 'auto'},
layout=w.Layout(width='auto'))
coffee_duration = w.Dropdown(description="Duration:", options=["MM"] + [str(i) for i in range(1, 31)], value="MM",
disabled=True, style={'description_width': 'auto'}, layout=w.Layout(width='auto'))
regular_breaks_label = w.Label("Regular breaks are spread evenly throughout the day")
coffee_break_box = w.VBox(children=(coffee_button, coffee_breaks_text, coffee_duration, regular_breaks_label))
def handle_coffee_button(_):
coffee_duration.disabled = not coffee_button.value
coffee_breaks_text.disabled = not coffee_button.value
coffee_button.observe(handle_coffee_button)
break_box = w.VBox(children=(lunch_break_box, coffee_break_box))
middle_column = w.VBox(children=(event_intro_box, date_box, break_box),
layout=w.Layout(width='40%', padding='0px 20px 0px 0px'))
```
%% Cell type:code id: tags:
``` python
mask_label = w.Label("Mask wearing:")
mask_buttons = w.ToggleButtons(options=["Continuous", "Removed when seated >2m"])
mask_box = w.VBox(children=(mask_label, mask_buttons), layout=w.Layout(padding='50px 0px 30px 0px'))
info_box = w.HTML(value='<style>p{font-size:0.875em; line-height:1.2}</style>'
'<p>This tool estimates the risk of COVID-19 spread. It is based on current scientific data and '
'can be used to provide an illustration for different real world scenarios.</p><p><br></p>'
'<p style="text-align: center;"><strong>How to use this tool:</strong></p>'
'<p style="text-align: center;"><strong>Room data</strong></p>'
'<p>Enter the data about the area you wish to study. You can find these in GIS, or by measuring '
'them yourself.</p><p>For mechanical ventilation, you should check with a specialist for the '
'air flow or air change rate.</p><p><br></p>'
'<p style="text-align: center;"><strong>Event data</strong></p>'
'<p>Enter the total number of people and how many you assume are infected.</p><p><br></p>'
'<p style="text-align: center;"><strong>Activity types:</strong></p>'
'<p>Office = typical scenario all persons seated, talking quietly.</p>'
'<p>Workshop = assembly workshop environment, all persons doing light exercise, talking.</p>'
'<p>Training = one person standing, talking, all others seated, breathing normally.</p>'
'<p>Seminar = As training, but all participants take turns in standing and talking.</p>'
'<p>You should specify if the event is a one off (give date) or recurrent use of the same space '
'for the same activity, in which case tick the months when the activity takes place.</p>'
'<p>Specify if a lunch break should be included, and when it starts/stops.</p>'
'<p>If you will take coffee breaks, they are spread out evenly throughout the day, '
'in addition to lunch.</p><p>Mask wearing: Specify if they are worn all the time, '
'or only when less than 2 meters apart.</p>',
layout=w.Layout(padding='0px 0px 30px 0px'))
report_button = w.Button(description="Generate report")
right_column = w.VBox(children=(mask_box, info_box, report_button), layout=w.Layout(width='35%'))
components = {'name_text', 'room_number_text', 'volume_text', 'area_text', 'height_text', 'mechanical_button',
'acph_text', 'asfr_text', 'natural_button', 'number_of_windows_text', 'height_of_window_text',
'width_of_window_text', 'opening_distance_text', 'opening_distance_text', 'window_open_buttons',
'total_people_text', 'infected_people_text', 'activity_dropdown', 'start_hour', 'start_minute',
'finish_hour', 'finish_minute', 'single_button', 'recurrent_button', 'month_dropdown', 'day_dropdown',
'lunch_button', 'lunch_start_hour', 'lunch_start_minute', 'lunch_finish_hour', 'lunch_finish_minute',
'coffee_button', 'coffee_breaks_text', 'coffee_duration', 'mask_buttons'}
components.update(set(months))
def get_value(component_name: str):
assert component_name in components, f"{component_name} is not the name of any UI-element with a value-attribute. " \
"Valid names are:\n" + '\n'.join(sorted(components))
if component_name in months:
return months_bar.children[months.index(component_name)].value
return globals()[component_name].value
```
%% Cell type:code id: tags:
``` python
w.HBox(children=(left_column, middle_column, right_column))
```
%%%% Output: display_data
%% Cell type:code id: tags:
``` python
```
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment