Merge branch 'feature/github_issues' into 'master'

Added current scenario for the alternative scenarios & GitHub issues

See merge request cara/cara!367
This commit is contained in:
Andre Henriques 2022-06-27 16:45:32 +02:00
commit 379b5091a8
4 changed files with 50 additions and 45 deletions

View file

@ -227,12 +227,14 @@ def manufacture_alternative_scenarios(form: FormData) -> typing.Dict[str, mc.Exp
FFP2_being_worn = bool(form.mask_wearing_option == 'mask_on' and form.mask_type == 'FFP2')
if FFP2_being_worn and form.hepa_option:
FFP2andHEPAalternative = dataclass_utils.replace(form, mask_type='Type I')
scenarios['Base scenario with HEPA filter and Type I masks'] = FFP2andHEPAalternative.build_mc_model()
if not (form.hepa_option and form.mask_wearing_option == 'mask_on' and form.mask_type == 'Type I'):
scenarios['Base scenario with HEPA filter and Type I masks'] = FFP2andHEPAalternative.build_mc_model()
if not FFP2_being_worn and form.hepa_option:
noHEPAalternative = dataclass_utils.replace(form, mask_type = 'FFP2')
noHEPAalternative = dataclass_utils.replace(noHEPAalternative, mask_wearing_option = 'mask_on')
noHEPAalternative = dataclass_utils.replace(noHEPAalternative, hepa_option=False)
scenarios['Base scenario without HEPA filter, with FFP2 masks'] = noHEPAalternative.build_mc_model()
if not (not form.hepa_option and FFP2_being_worn):
scenarios['Base scenario without HEPA filter, with FFP2 masks'] = noHEPAalternative.build_mc_model()
# The remaining scenarios are based on Type I masks (possibly not worn)
# and no HEPA filtration.
@ -245,17 +247,22 @@ def manufacture_alternative_scenarios(form: FormData) -> typing.Dict[str, mc.Exp
if form.ventilation_type == 'mechanical_ventilation':
#scenarios['Mechanical ventilation with Type I masks'] = with_mask.build_mc_model()
scenarios['Mechanical ventilation without masks'] = without_mask.build_mc_model()
if not (form.mask_wearing_option == 'mask_off'):
scenarios['Mechanical ventilation without masks'] = without_mask.build_mc_model()
elif form.ventilation_type == 'natural_ventilation':
#scenarios['Windows open with Type I masks'] = with_mask.build_mc_model()
scenarios['Windows open without masks'] = without_mask.build_mc_model()
if not (form.mask_wearing_option == 'mask_off'):
scenarios['Windows open without masks'] = without_mask.build_mc_model()
# No matter the ventilation scheme, we include scenarios which don't have any ventilation.
with_mask_no_vent = dataclass_utils.replace(with_mask, ventilation_type='no_ventilation')
without_mask_or_vent = dataclass_utils.replace(without_mask, ventilation_type='no_ventilation')
scenarios['No ventilation with Type I masks'] = with_mask_no_vent.build_mc_model()
scenarios['Neither ventilation nor masks'] = without_mask_or_vent.build_mc_model()
if not (form.mask_wearing_option == 'mask_on' and form.mask_type == 'Type I' and form.ventilation_type == 'no_ventilation'):
scenarios['No ventilation with Type I masks'] = with_mask_no_vent.build_mc_model()
if not (form.mask_wearing_option == 'mask_off' and form.ventilation_type == 'no_ventilation'):
scenarios['Neither ventilation nor masks'] = without_mask_or_vent.build_mc_model()
else:
no_short_range_alternative = dataclass_utils.replace(form, short_range_interactions=[])
@ -278,11 +285,19 @@ def scenario_statistics(mc_model: mc.ExposureModel, sample_times: typing.List[fl
def comparison_report(
report_data: typing.Dict[str, typing.Any],
scenarios: typing.Dict[str, mc.ExposureModel],
sample_times: typing.List[float],
executor_factory: typing.Callable[[], concurrent.futures.Executor],
):
statistics = {}
statistics = {
'Current scenario' : {
'probability_of_infection': report_data['prob_inf'],
'expected_new_cases': report_data['expected_new_cases'],
'concentrations': report_data['concentrations'],
}
}
with executor_factory() as executor:
results = executor.map(
scenario_statistics,
@ -293,6 +308,7 @@ def comparison_report(
for (name, model), model_stats in zip(scenarios.items(), results):
statistics[name] = model_stats
return {
'stats': statistics,
}
@ -330,11 +346,11 @@ class ReportGenerator:
}
scenario_sample_times = interesting_times(model)
context.update(calculate_report_data(form, model))
report_data = calculate_report_data(form, model)
context.update(report_data)
alternative_scenarios = manufacture_alternative_scenarios(form)
context['alternative_scenarios'] = comparison_report(
alternative_scenarios, scenario_sample_times, executor_factory=executor_factory,
report_data, alternative_scenarios, scenario_sample_times, executor_factory=executor_factory,
)
context['permalink'] = generate_permalink(base_url, self.calculator_prefix, form)
context['calculator_prefix'] = self.calculator_prefix

View file

@ -4,6 +4,8 @@
bottom: 20px;
right: 20px;
padding: 20px;
-webkit-print-color-adjust: exact; /* chrome & webkit browsers */
print-color-adjust: exact; /*firefox & IE */
}
h1 {
@ -61,24 +63,6 @@ p.notes {
width: 100pt;
}
.red_bkg {
color: #000000;
background-color: #CD5C5C;
text-decoration: none;
}
.yellow_bkg {
color: #000000;
background-color: #FFFF00;
text-decoration: none;
}
.green_bkg {
color: #000000;
background-color: #90EE90;
text-decoration: none;
}
.icon_button {
border: none;
background: none;
@ -133,15 +117,16 @@ p.notes {
.icon_button {
display: none!important;
}
.card {
page-break-inside: avoid;
}
.pi-image {
max-height: 9em;
}
.pi-box {
max-width: 260px!important;
}
.card {
page-break-inside: avoid!important;
break-inside: avoid!important;
}
#link-results {
display: none;
}
@ -172,6 +157,7 @@ p.notes {
border-radius: 100px;
z-index: 1;
-webkit-print-color-adjust: exact!important;
print-color-adjust: exact!important;
}
.intro-banner-vdo-play-btn i {

View file

@ -605,8 +605,9 @@ function draw_alternative_scenarios_plot(concentration_plot_svg_id, alternative_
.text('Mean concentration (virions/m³)');
// Legend bounding box.
max_key_length = Math.max(...(Object.keys(data_for_scenarios).map(el => el.length)));
var legendBBox = vis.append('rect')
.attr('width', 275)
.attr('width', 8.25 * max_key_length )
.attr('height', 25 * (Object.keys(data_for_scenarios).length))
.attr('stroke', 'lightgrey')
.attr('stroke-width', '2')
@ -711,10 +712,10 @@ function draw_alternative_scenarios_plot(concentration_plot_svg_id, alternative_
var div_height = document.getElementById(concentration_plot_svg_id).clientHeight;
graph_width = div_width;
graph_height = div_height
if (div_width >= 900) { // For screens with width > 900px legend can be on the graph's right side.
if (div_width >= 1200) { // For screens with width > 900px legend can be on the graph's right side.
var margins = { top: 30, right: 20, bottom: 50, left: 60 };
div_width = 900;
graph_width = div_width * (2/3);
div_width = 1200;
graph_width = 600;
const svg_margins = {'margin-left': '0rem'};
Object.entries(svg_margins).forEach(([prop,val]) => vis.style(prop,val));
}

View file

@ -1,6 +1,8 @@
{% extends "base/calculator.report.html.j2" %}
{% set cern_level = 'green-1' %} <!-- green-1, yellow-2, orange-3, red-4 -->
{% set orange_prob_lim = 2 %}
{% set red_prob_lim = 10 %}
{% if form.short_range_option == "short_range_yes" %}
{% set scenario = alternative_scenarios.stats.values() | first %}
@ -9,10 +11,10 @@
{% set long_range_prob_inf = prob_inf %}
{% endif %}
{% if ((long_range_prob_inf > 10) or (expected_new_cases >= 1)) %}
{% if ((long_range_prob_inf > red_prob_lim) or (expected_new_cases >= 1)) %}
{% set long_range_scale_warning = 'red' %}
{% set long_range_warning_color= 'bg-danger' %}
{% elif (2 <= long_range_prob_inf <= 10) %}
{% elif (orange_prob_lim <= long_range_prob_inf <= red_prob_lim) %}
{% set long_range_scale_warning = 'orange' %}
{% set long_range_warning_color = 'bg-warning' %}
{% else %}
@ -20,8 +22,8 @@
{% set long_range_warning_color = 'bg-success' %}
{% endif %}
{% if ((prob_inf > 10) or (expected_new_cases >= 1)) %} {% set scale_warning = 'red' %}
{% elif (2 <= prob_inf <= 10) %} {% set scale_warning = 'orange' %}
{% if ((prob_inf > red_prob_lim) or (expected_new_cases >= 1)) %} {% set scale_warning = 'red' %}
{% elif (orange_prob_lim <= prob_inf <= red_prob_lim) %} {% set scale_warning = 'orange' %}
{% else %} {% set scale_warning = 'green' %}
{% endif %}
@ -135,12 +137,12 @@
</thead>
<tbody>
{% for scenario_name, scenario_stats in alternative_scenarios.stats.items() %}
{%if (( scenario_stats.probability_of_infection > 15) or (scenario_stats.expected_new_cases >= 1)) %}
<tr class="red_bkg">
{% elif (5 <= scenario_stats.probability_of_infection <= 15) %}
<tr class="yellow_bkg">
{% elif (scenario_stats.probability_of_infection < 5) %}
<tr class="green_bkg">
{%if (( scenario_stats.probability_of_infection > red_prob_lim) or (scenario_stats.expected_new_cases >= 1)) %}
<tr class="alert-danger">
{% elif (orange_prob_lim <= scenario_stats.probability_of_infection <= red_prob_lim) %}
<tr class="alert-warning">
{% elif (scenario_stats.probability_of_infection < orange_prob_lim) %}
<tr class="alert-success">
{% endif%}
<td> {{ scenario_name }}</td>
<td> {{ scenario_stats.probability_of_infection | non_zero_percentage }}</td>