From dfc66991f4efe2bfec0b8564c3de431fd8ec6dcf Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Tue, 10 Aug 2021 17:34:37 +0200 Subject: [PATCH 1/8] Move QR generation to the browser, saving some time and effort on the server. --- cara/apps/calculator/report_generator.py | 23 ++++----------- cara/apps/calculator/static/js/pdf.js | 29 ------------------- .../templates/base/calculator.report.html.j2 | 16 ++++++---- cara/tests/apps/calculator/test_webapp.py | 16 +++++----- requirements.txt | 1 - setup.py | 1 - 6 files changed, 24 insertions(+), 62 deletions(-) delete mode 100644 cara/apps/calculator/static/js/pdf.js diff --git a/cara/apps/calculator/report_generator.py b/cara/apps/calculator/report_generator.py index 773481f3..2f55e3eb 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 @@ -123,7 +121,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 @@ -136,20 +134,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, } @@ -313,7 +300,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/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 146478dc..128dd21d 100644 --- a/cara/apps/calculator/templates/base/calculator.report.html.j2 +++ b/cara/apps/calculator/templates/base/calculator.report.html.j2 @@ -24,8 +24,6 @@

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

- {# To be replaced by "Generate PDF" #} - {% endblock report_header %} @@ -162,10 +160,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.

@@ -433,11 +431,19 @@
{% endblock disclaimer_container %} - + + + 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 6be0d0f9..704f923c 100644 --- a/setup.py +++ b/setup.py @@ -30,7 +30,6 @@ REQUIREMENTS: dict = { 'numpy', 'psutil', 'python-dateutil', - 'qrcode[pil]', 'scipy', 'sklearn', 'timezonefinder', From ea3f4abe0b8877ba5c3630774575aba4a1efc22b Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Fri, 10 Sep 2021 13:06:27 +0200 Subject: [PATCH 2/8] Create a new QRcode for the PDF version --- cara/apps/calculator/static/css/report.css | 12 ++---------- .../templates/base/calculator.report.html.j2 | 8 +++++++- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/cara/apps/calculator/static/css/report.css b/cara/apps/calculator/static/css/report.css index 0e0a7cf7..c9b2b3ab 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,9 +133,6 @@ p.notes { .icon_button { display: none!important; } - .print-button { - display: none!important; - } .card { page-break-inside: avoid; } diff --git a/cara/apps/calculator/templates/base/calculator.report.html.j2 b/cara/apps/calculator/templates/base/calculator.report.html.j2 index 128dd21d..a6180770 100644 --- a/cara/apps/calculator/templates/base/calculator.report.html.j2 +++ b/cara/apps/calculator/templates/base/calculator.report.html.j2 @@ -23,7 +23,8 @@

CARA - CALCULATOR REPORT

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

- + + {% endblock report_header %} @@ -443,6 +444,11 @@ width: 330, height: 330} ); + new QRCode(document.getElementById("pdf_qrcode"), { + text: "{{ permalink.shortened }}", + width: 133, + height: 133} + ); From fcfaee2b4afad53ce5871fd919eb39ff5f05d0c5 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Wed, 6 Oct 2021 11:55:27 +0200 Subject: [PATCH 3/8] Handle the case where the URL being encoded by qrcodejs is causing an error with the library (e.g. https://github.com/davidshimjs/qrcodejs/issues/78). --- .../templates/base/calculator.report.html.j2 | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/cara/apps/calculator/templates/base/calculator.report.html.j2 b/cara/apps/calculator/templates/base/calculator.report.html.j2 index a6180770..d06a21bc 100644 --- a/cara/apps/calculator/templates/base/calculator.report.html.j2 +++ b/cara/apps/calculator/templates/base/calculator.report.html.j2 @@ -442,13 +442,15 @@ new QRCode(document.getElementById("qrcode"), { text: "{{ permalink.shortened }}", width: 330, - height: 330} - ); - new QRCode(document.getElementById("pdf_qrcode"), { + height: 330, + correctLevel : QRCode.CorrectLevel.L + }); + new QRCode(document.getElementById("pdf_qrcode"), { text: "{{ permalink.shortened }}", width: 133, - height: 133} - ); + height: 133, + correctLevel : QRCode.CorrectLevel.L + }); From 0840dc43ef45b9654dd78ed860debd9eb3cd4565 Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Wed, 6 Oct 2021 11:58:36 +0200 Subject: [PATCH 4/8] Update concentration docstring --- cara/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cara/models.py b/cara/models.py index 296c260c..b7885768 100644 --- a/cara/models.py +++ b/cara/models.py @@ -873,7 +873,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(): @@ -902,7 +902,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()) From f9a3f2bf5508182860183f6149d66ddbec9b20ee Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Wed, 13 Oct 2021 09:14:55 +0200 Subject: [PATCH 5/8] Added color for the P(I) animation in the printable version fixes #201 --- cara/apps/calculator/static/css/report.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cara/apps/calculator/static/css/report.css b/cara/apps/calculator/static/css/report.css index c9b2b3ab..1f9e5b36 100644 --- a/cara/apps/calculator/static/css/report.css +++ b/cara/apps/calculator/static/css/report.css @@ -154,7 +154,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 { From 2d46ac0b562e6a781e0a9c949f326ecf3b77dd07 Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Wed, 13 Oct 2021 09:21:17 +0200 Subject: [PATCH 6/8] Page break for disclaimer fixes #202 --- cara/apps/calculator/static/css/report.css | 8 +++----- .../calculator/templates/base/calculator.report.html.j2 | 2 +- .../themes/cern/templates/calculator.report.html.j2 | 1 - 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/cara/apps/calculator/static/css/report.css b/cara/apps/calculator/static/css/report.css index 1f9e5b36..52aeb1ea 100644 --- a/cara/apps/calculator/static/css/report.css +++ b/cara/apps/calculator/static/css/report.css @@ -136,11 +136,9 @@ p.notes { .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; } } diff --git a/cara/apps/calculator/templates/base/calculator.report.html.j2 b/cara/apps/calculator/templates/base/calculator.report.html.j2 index d06a21bc..db13e693 100644 --- a/cara/apps/calculator/templates/base/calculator.report.html.j2 +++ b/cara/apps/calculator/templates/base/calculator.report.html.j2 @@ -390,7 +390,7 @@ {% block disclaimer_container %}


-
+
{% block disclaimer %}

Disclaimer:

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 %} From 7149bec458816cb4c65e6f1b37e8f2452bf1eb21 Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Fri, 15 Oct 2021 16:48:21 +0200 Subject: [PATCH 7/8] Moved Authors (Code contributors and Main developers) to "About" page --- cara/apps/templates/about.html.j2 | 7 +++++-- cara/apps/templates/common_text.md.j2 | 10 ++++++++-- cara/apps/templates/index.html.j2 | 23 ----------------------- 3 files changed, 13 insertions(+), 27 deletions(-) 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. - -

    -
    From 5e7d237e16609075557455ca1887811debdc6a3b Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Tue, 19 Oct 2021 16:45:45 +0200 Subject: [PATCH 8/8] Updated ipympl compatible version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 704f923c..e8136836 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ REQUIREMENTS: dict = { 'core': [ 'dataclasses; python_version < "3.7"', 'ipykernel', - 'ipympl != 0.8.0', + 'ipympl != 0.8.0, != 0.8.1', 'ipywidgets', 'Jinja2', 'loky',