From d0b5e9b2a7396e49a31331e3cd140821acfc5cb3 Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Tue, 14 Jun 2022 14:48:55 +0200 Subject: [PATCH 1/5] Added colors to printable report --- cara/apps/calculator/static/css/report.css | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cara/apps/calculator/static/css/report.css b/cara/apps/calculator/static/css/report.css index dfd11ff6..99efd20c 100644 --- a/cara/apps/calculator/static/css/report.css +++ b/cara/apps/calculator/static/css/report.css @@ -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 { @@ -111,6 +113,9 @@ p.notes { #rules, #data { display: contents!important; + .card { + page-break-inside: avoid!important; + break-inside: avoid!important; } #link_reproduce_results { display: none!important; @@ -133,9 +138,6 @@ p.notes { .icon_button { display: none!important; } - .card { - page-break-inside: avoid; - } .pi-image { max-height: 9em; } @@ -172,6 +174,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 { From e777a71d2a10ac064c3c1dd3accee5f8b12a6956 Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Tue, 14 Jun 2022 16:16:26 +0200 Subject: [PATCH 2/5] Added missing conditions to alternative scenarios and. bug fix --- cara/apps/calculator/static/css/report.css | 25 +++---------------- .../templates/cern/calculator.report.html.j2 | 12 ++++----- 2 files changed, 10 insertions(+), 27 deletions(-) diff --git a/cara/apps/calculator/static/css/report.css b/cara/apps/calculator/static/css/report.css index 99efd20c..f0e07d90 100644 --- a/cara/apps/calculator/static/css/report.css +++ b/cara/apps/calculator/static/css/report.css @@ -63,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; @@ -113,9 +95,6 @@ p.notes { #rules, #data { display: contents!important; - .card { - page-break-inside: avoid!important; - break-inside: avoid!important; } #link_reproduce_results { display: none!important; @@ -144,6 +123,10 @@ p.notes { .pi-box { max-width: 260px!important; } + .card { + page-break-inside: avoid!important; + break-inside: avoid!important; + } #link-results { display: none; } diff --git a/cara/apps/templates/cern/calculator.report.html.j2 b/cara/apps/templates/cern/calculator.report.html.j2 index c55cd6dd..c7c4bfdc 100644 --- a/cara/apps/templates/cern/calculator.report.html.j2 +++ b/cara/apps/templates/cern/calculator.report.html.j2 @@ -135,12 +135,12 @@ {% for scenario_name, scenario_stats in alternative_scenarios.stats.items() %} - {%if (( scenario_stats.probability_of_infection > 15) or (scenario_stats.expected_new_cases >= 1)) %} - - {% elif (5 <= scenario_stats.probability_of_infection <= 15) %} - - {% elif (scenario_stats.probability_of_infection < 5) %} - + {%if (( scenario_stats.probability_of_infection > 10) or (scenario_stats.expected_new_cases >= 1)) %} + + {% elif (2 <= scenario_stats.probability_of_infection <= 10) %} + + {% elif (scenario_stats.probability_of_infection < 2) %} + {% endif%} {{ scenario_name }} {{ scenario_stats.probability_of_infection | non_zero_percentage }} From ba10c23727928c849854aad21199a5b88f05ad72 Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Tue, 14 Jun 2022 16:55:14 +0200 Subject: [PATCH 3/5] Added current scenario for the alternative scenarios (from current scenario data, to avoid the re-calculation) --- cara/apps/calculator/report_generator.py | 36 +++++++++++++++++------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/cara/apps/calculator/report_generator.py b/cara/apps/calculator/report_generator.py index 789d8865..5731e6cb 100644 --- a/cara/apps/calculator/report_generator.py +++ b/cara/apps/calculator/report_generator.py @@ -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 From 27237c410310db0da4979999cae50ee2bd681648 Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Tue, 14 Jun 2022 17:33:44 +0200 Subject: [PATCH 4/5] Bug on alternative scenario width --- cara/apps/calculator/static/js/report.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cara/apps/calculator/static/js/report.js b/cara/apps/calculator/static/js/report.js index bd41d380..a6010221 100644 --- a/cara/apps/calculator/static/js/report.js +++ b/cara/apps/calculator/static/js/report.js @@ -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)); } From 1d0182c1522a9a21ca61ea9a39bbb014a44e78d6 Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Thu, 16 Jun 2022 14:40:08 +0200 Subject: [PATCH 5/5] Added limits as variables in cern applicable rules --- .../templates/cern/calculator.report.html.j2 | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/cara/apps/templates/cern/calculator.report.html.j2 b/cara/apps/templates/cern/calculator.report.html.j2 index c7c4bfdc..04092ed6 100644 --- a/cara/apps/templates/cern/calculator.report.html.j2 +++ b/cara/apps/templates/cern/calculator.report.html.j2 @@ -1,6 +1,8 @@ {% extends "base/calculator.report.html.j2" %} {% set cern_level = 'green-1' %} +{% 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,11 +137,11 @@ {% for scenario_name, scenario_stats in alternative_scenarios.stats.items() %} - {%if (( scenario_stats.probability_of_infection > 10) or (scenario_stats.expected_new_cases >= 1)) %} + {%if (( scenario_stats.probability_of_infection > red_prob_lim) or (scenario_stats.expected_new_cases >= 1)) %} - {% elif (2 <= scenario_stats.probability_of_infection <= 10) %} + {% elif (orange_prob_lim <= scenario_stats.probability_of_infection <= red_prob_lim) %} - {% elif (scenario_stats.probability_of_infection < 2) %} + {% elif (scenario_stats.probability_of_infection < orange_prob_lim) %} {% endif%} {{ scenario_name }}