diff --git a/cara/apps/calculator/report_generator.py b/cara/apps/calculator/report_generator.py index a07b1f0b..a4d88bd9 100644 --- a/cara/apps/calculator/report_generator.py +++ b/cara/apps/calculator/report_generator.py @@ -1,17 +1,15 @@ import concurrent.futures import base64 import dataclasses -from datetime import datetime, timedelta +from datetime import datetime import io +import json import typing import urllib import zlib -import loky import jinja2 import numpy as np -import qrcode -import json from cara import models from ... import monte_carlo as mc @@ -128,7 +126,7 @@ def calculate_report_data(model: models.ExposureModel): } -def generate_qr_code(base_url, calculator_prefix, form: FormData): +def generate_permalink(base_url, calculator_prefix, form: FormData): form_dict = FormData.to_dict(form, strip_defaults=True) # Generate the calculator URL arguments that would be needed to re-create this @@ -141,20 +139,9 @@ def generate_qr_code(base_url, calculator_prefix, form: FormData): qr_url = f"{base_url}/_c/{compressed_args}" url = f"{base_url}{calculator_prefix}?{args}" - qr = qrcode.QRCode( - version=1, - error_correction=qrcode.constants.ERROR_CORRECT_H, - box_size=10, - border=4, - ) - qr.add_data(qr_url) - qr.make(fit=True) - img = qr.make_image(fill_color="black", back_color="white").convert('RGB') - return { - 'image': img2base64(_img2bytes(img)), 'link': url, - 'qr_url': qr_url, + 'shortened': qr_url, } @@ -318,7 +305,7 @@ class ReportGenerator: context['alternative_scenarios'] = comparison_report( alternative_scenarios, scenario_sample_times, executor_factory=executor_factory, ) - context['qr_code'] = generate_qr_code(base_url, self.calculator_prefix, form) + context['permalink'] = generate_permalink(base_url, self.calculator_prefix, form) context['calculator_prefix'] = self.calculator_prefix context['scale_warning'] = { 'level': 'yellow-2', diff --git a/cara/apps/calculator/static/css/report.css b/cara/apps/calculator/static/css/report.css index 0e0a7cf7..52aeb1ea 100644 --- a/cara/apps/calculator/static/css/report.css +++ b/cara/apps/calculator/static/css/report.css @@ -56,7 +56,7 @@ p.notes { margin: 1% } -#pdf-qr-code { +#pdf_qrcode_aref { margin-right: 1%; width: 100pt; } @@ -102,11 +102,6 @@ p.notes { border-radius: 5px; } -.print-button { - margin-left: auto; - margin-right: 1%; -} - /* @media (width: 1200px) { */ @media print { /* #body { @@ -120,7 +115,7 @@ p.notes { #link_reproduce_results { display: none!important; } - #pdf-qr-code { + #pdf_qrcode_aref { visibility: inherit!important; } .collapse { @@ -138,17 +133,12 @@ p.notes { .icon_button { display: none!important; } - .print-button { - display: none!important; - } .card { page-break-inside: avoid; } - /* CSS styling to avoid page breaks. */ - .break-after { - page-break-after: always; - } - .break-avoid { + #disclaimer { + border: 2px solid black; + padding: 15px; page-break-inside: avoid; } } @@ -162,7 +152,8 @@ p.notes { position: relative; text-align: center; border-radius: 100px; - z-index: 1 + z-index: 1; + -webkit-print-color-adjust: exact!important; } .intro-banner-vdo-play-btn i { diff --git a/cara/apps/calculator/static/js/pdf.js b/cara/apps/calculator/static/js/pdf.js deleted file mode 100644 index 6afb4fea..00000000 --- a/cara/apps/calculator/static/js/pdf.js +++ /dev/null @@ -1,29 +0,0 @@ -function generate_pdf_version(qr_link) { - const pdf_version = this.document.getElementById("body"); - - // PDF styling - var opt = { - filename: 'myfile.pdf', - image: { type: 'jpeg', quality: 0.98 }, - html2canvas: { scale: 2, width: 1200, windowWidth: 1200 }, - enableLinks: false, - jsPDF: { - unit: 'pt', - format: 'letter', - orientation: 'portrait', - }, - pagebreak: { mode: '', avoid: '.break-avoid' }, - }; - html2pdf().set(opt).from(pdf_version).toPdf().get('pdf').then(function(pdf) { - var totalPages = pdf.internal.getNumberOfPages(); - pdf.setPage(1); - pdf.link(530, 25, 60, 60, { url: qr_link }); //Hyperlink to reproduce results - - for (i = 1; i <= totalPages; i++) { - pdf.setPage(i); - pdf.setFontSize(10); - pdf.setTextColor(150); - pdf.text('Page ' + i + ' of ' + totalPages, (pdf.internal.pageSize.getWidth() / 2.25), (pdf.internal.pageSize.getHeight() - 10)); - } - }).save(); -}; \ No newline at end of file diff --git a/cara/apps/calculator/templates/base/calculator.report.html.j2 b/cara/apps/calculator/templates/base/calculator.report.html.j2 index 6e7056a6..e609c0b5 100644 --- a/cara/apps/calculator/templates/base/calculator.report.html.j2 +++ b/cara/apps/calculator/templates/base/calculator.report.html.j2 @@ -23,9 +23,8 @@

CARA - CALCULATOR REPORT

Created {{ creation_date }} using CARA calculator version v{{ form.calculator_version }}

- - {# To be replaced by "Generate PDF" #} - + + {% endblock report_header %} @@ -163,10 +162,10 @@
- +

- Click the QR code to regenerate the report and get a shareable link.
Alternatively, scan to regenerate the report.
Mobile-friendly app coming soon! + Click the QR code to regenerate the report and get a shareable link.
Alternatively, scan to regenerate the report.

@@ -392,7 +391,7 @@ {% block disclaimer_container %}


-
+
{% block disclaimer %}

Disclaimer:

@@ -434,11 +433,26 @@
{% endblock disclaimer_container %} - + + + diff --git a/cara/apps/calculator/themes/cern/templates/calculator.report.html.j2 b/cara/apps/calculator/themes/cern/templates/calculator.report.html.j2 index 3871c6b9..8d482839 100644 --- a/cara/apps/calculator/themes/cern/templates/calculator.report.html.j2 +++ b/cara/apps/calculator/themes/cern/templates/calculator.report.html.j2 @@ -145,7 +145,6 @@
-
{% endblock report_preamble %} {% block report_footer %} diff --git a/cara/apps/templates/about.html.j2 b/cara/apps/templates/about.html.j2 index 8bb5cde9..41ce45c2 100644 --- a/cara/apps/templates/about.html.j2 +++ b/cara/apps/templates/about.html.j2 @@ -40,8 +40,11 @@ Although the user is able to calculate the infection probability of a stand-alon
  • Etc…
  • -

    Authors:


    -{{ text_blocks['Authors'] }} +

    Main Developers:


    +{{ text_blocks['Main Developers'] }} + +

    Code Contributors:


    +{{ text_blocks['Code Contributors'] }}

    Acknowledgements:


    {{ text_blocks['Acknowledgements'] }} diff --git a/cara/apps/templates/common_text.md.j2 b/cara/apps/templates/common_text.md.j2 index ac8829d7..826eb91e 100644 --- a/cara/apps/templates/common_text.md.j2 +++ b/cara/apps/templates/common_text.md.j2 @@ -1,6 +1,6 @@ -## Authors +## Main Developers -

    Andre Henriques1, Marco Andreini1, Gabriella Azzopardi2, James Devine3, Philip Elson4, Nicolas Mounet2, Markus Kongstein Rognlien2,6, Nicola Tarocco5


    +

    Andre Henriques1, Luis Aleixo1, Marco Andreini1, Gabriella Azzopardi2, James Devine3, Philip Elson4, Nicolas Mounet2, Markus Kongstein Rognlien2,6, Nicola Tarocco5


    1HSE Unit, Occupational Health & Safety Group, CERN
    2Beams Department, Accelerators and Beam Physics Group, CERN
    @@ -9,6 +9,12 @@ 5Information Technology Department, Collaboration, Devices & Applications Group, CERN
    6Norwegian University of Science and Technology (NTNU)
    +## Code Contributors + +

    Anna Efimova1, Anel Massalimova1, Cole Austin Coughlin1

    + +1Summer Students, CERN
    + ## Acknowledgements We wish to thank CERN’s HSE Unit, Beams Department, Experimental Physics Department, Information Technology Department, Industry, Procurement and Knowledge Transfer Department and International Relations Sector for their support to the study. Thanks to Doris Forkel-Wirth, Benoit Delille, Walid Fadel, Olga Beltramello, Letizia Di Giulio, Evelyne Dho, Wayne Salter, Benoit Salvant and colleagues from the COVID working group for providing expert advice and extensively testing the model. Finally, we wish to thank Fabienne Landua and the design service for preparing the illustrations and Alessandro Raimondo, Ana Padua and Manuela Cirilli from the Knowledge Transfer Group for their continuous support. Our compliments towards the work and research performed by world leading scientists in this domain: Prof. Manuel Gameiro, Prof. Shelly Miller, Prof. Linsey Marr, Prof. Jose Jimenez, Dr. Lidia Morawska, Prof Yuguo Li et al. – their scientific contribution was indispensable for this project. diff --git a/cara/apps/templates/index.html.j2 b/cara/apps/templates/index.html.j2 index c774420c..5bcec3d2 100644 --- a/cara/apps/templates/index.html.j2 +++ b/cara/apps/templates/index.html.j2 @@ -40,29 +40,6 @@
    -

    Authors

    -
    -

    -

    Andre Henriques1, Luis Aleixo1, Marco Andreini1, Gabriella Azzopardi2, James Devine3, Philip Elson4, Nicolas Mounet2, Markus Kongstein Rognlien2,6, Nicola Tarocco5


    - - 1HSE Unit, Occupational Health & Safety Group, CERN
    - 2Beams Department, Accelerators and Beam Physics Group, CERN
    - 3Experimental Physics Department, Safety Office, CERN
    - 4Beams Department, Controls Group, CERN
    - 5Information Technology Department, Collaboration, Devices & Applications Group, CERN
    - 6Norwegian University of Science and Technology (NTNU)
    -

    - -
    -

    Acknowledgements:

    -

    - We wish to thank CERN’s HSE Unit, Beams Department, Experimental Physics Department, Information Technology Department, Industry, Procurement and Knowledge Transfer Department and International Relations Sector for their support to the study. - Thanks to Doris Forkel-Wirth, Benoit Delille, Walid Fadel, Olga Beltramello, Letizia Di Giulio, Evelyne Dho, Wayne Salter, Benoit Salvant and colleagues from the COVID working group for providing expert advice and extensively testing the model. - Finally, we wish to thank Fabienne Landua and the design service for preparing the illustrations and Alessandro Raimondo, Ana Padua and Manuela Cirilli from the Knowledge Transfer Group for their continuous support. - Our compliments towards the work and research performed by world leading scientists in this domain: Prof. Manuel Gameiro, Prof. Shelly Miller, Prof. Linsey Marr, Prof. Jose Jimenez, Dr. Lidia Morawska, Prof Yuguo Li et al. – their scientific contribution was indispensable for this project. - -

    -
    diff --git a/cara/models.py b/cara/models.py index 1e2dcbcc..c3f716d2 100644 --- a/cara/models.py +++ b/cara/models.py @@ -872,7 +872,7 @@ class ConcentrationModel: @method_cache def normed_integrated_concentration(self, start: float, stop: float) -> _VectorisedFloat: """ - Get the integrated concentration dose between the times start and stop, + Get the integrated concentration of viruses in the air between the times start and stop, normalized by the emission rate. """ if stop <= self._first_presence_time(): @@ -901,7 +901,7 @@ class ConcentrationModel: def integrated_concentration(self, start: float, stop: float) -> _VectorisedFloat: """ - Get the integrated concentration dose between the times start and stop. + Get the integrated concentration of viruses in the air between the times start and stop. """ return (self.normed_integrated_concentration(start, stop) * self.infected.emission_rate_when_present()) diff --git a/cara/tests/apps/calculator/test_webapp.py b/cara/tests/apps/calculator/test_webapp.py index 40b75595..09bc104c 100644 --- a/cara/tests/apps/calculator/test_webapp.py +++ b/cara/tests/apps/calculator/test_webapp.py @@ -4,7 +4,7 @@ import pytest import tornado.testing import cara.apps.calculator -from cara.apps.calculator.report_generator import generate_qr_code +from cara.apps.calculator.report_generator import generate_permalink _TIMEOUT = 20. @@ -97,26 +97,26 @@ class TestOpenApp(tornado.testing.AsyncHTTPTestCase): assert response.code == 404 -async def test_qrcode_urls(http_server_client, baseline_form): +async def test_permalink_urls(http_server_client, baseline_form): base_url = 'proto://hostname/prefix' - qr_data = generate_qr_code(base_url, "/calculator", baseline_form) + permalink_data = generate_permalink(base_url, "/calculator", baseline_form) expected = f'{base_url}/calculator?exposed_coffee_break_option={baseline_form.exposed_coffee_break_option}&' - assert qr_data['link'].startswith(expected) + assert permalink_data['link'].startswith(expected) # We should get a 200 for the link. - response = await http_server_client.fetch(qr_data['link'].replace(base_url, '')) + response = await http_server_client.fetch(permalink_data['link'].replace(base_url, '')) assert response.code == 200 # And a 302 for the QR url itself. The redirected URL should be the same as # in the link. - assert qr_data['qr_url'].startswith(base_url) + assert permalink_data['shortened'].startswith(base_url) response = await http_server_client.fetch( - qr_data['qr_url'].replace(base_url, ''), + permalink_data['shortened'].replace(base_url, ''), max_redirects=0, raise_error=False, ) assert response.code == 302 - assert response.headers['Location'] == qr_data['link'].replace(base_url, '') + assert response.headers['Location'] == permalink_data['link'].replace(base_url, '') async def test_invalid_compressed_url(http_server_client, baseline_form): diff --git a/requirements.txt b/requirements.txt index 457a69b7..724bf5cc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -62,7 +62,6 @@ pyparsing==2.4.7 pyrsistent==0.18.0 python-dateutil==2.8.2 pyzmq==22.1.0 -qrcode==7.2 requests==2.26.0 requests-unixsocket==0.2.0 scikit-learn==0.24.2 diff --git a/setup.py b/setup.py index e5a28303..e8136836 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ REQUIREMENTS: dict = { 'core': [ 'dataclasses; python_version < "3.7"', 'ipykernel', - 'ipympl == 0.7.0', + 'ipympl != 0.8.0, != 0.8.1', 'ipywidgets', 'Jinja2', 'loky', @@ -30,7 +30,6 @@ REQUIREMENTS: dict = { 'numpy', 'psutil', 'python-dateutil', - 'qrcode[pil]', 'scipy', 'sklearn', 'timezonefinder',