From 597a27eadc97cd4df777dd5a26b654ff0d6ec4e0 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Fri, 16 Apr 2021 09:14:46 +0200 Subject: [PATCH 1/3] Prepare the repository for an Apache 2.0 license. --- LICENSE | 13 +++ .../cern/templates/calculator.report.html.j2 | 4 +- cara/apps/templates/layout.html.j2 | 16 +++- cara/models.py | 67 ++++++++------- cara/tests/models/test_concentration_model.py | 1 - cara/tests/models/test_piecewiseconstant.py | 85 +++++++++++++++++++ cara/tests/test_known_quantities.py | 64 -------------- cara/tests/test_ventilation.py | 38 ++++++++- requirements.txt | 1 + setup.cfg | 3 + setup.py | 2 + 11 files changed, 187 insertions(+), 107 deletions(-) create mode 100644 LICENSE create mode 100644 cara/tests/models/test_piecewiseconstant.py diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..c87de812 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright 2020-2021 CERN + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. 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 f4c93509..4d6769f8 100644 --- a/cara/apps/calculator/themes/cern/templates/calculator.report.html.j2 +++ b/cara/apps/calculator/themes/cern/templates/calculator.report.html.j2 @@ -85,9 +85,7 @@ {% block disclaimer %} {{ super() }}

- CARA is made available for internal CERN use only. - It is intended for Members of Personnel with roles related to Supervision, Health & Safety or Space Management, in order to simulate the concerned workplaces on CERN sites. - For use outside of this scope, it has to be performed under a pre-defined framework and licence agreement issued by CERN Knowledge Transfer (kt@cern.ch). + At CERN, CARA is intended for Members of Personnel with roles related to Supervision, Health & Safety or Space Management, in order to simulate the concerned workplaces on CERN sites.

{% endblock disclaimer %} diff --git a/cara/apps/templates/layout.html.j2 b/cara/apps/templates/layout.html.j2 index e7658ad2..566c545d 100644 --- a/cara/apps/templates/layout.html.j2 +++ b/cara/apps/templates/layout.html.j2 @@ -193,7 +193,6 @@ policy issues. Any initiative is conducted on a best effort and as-is basis, without liability or warranty.

- @@ -231,9 +230,22 @@ +
  • + + Source code + +
  • + +

    + CARA is Apache 2.0 licensed open-source + software developed at CERN. + You can find the source code at https://gitlab.cern.ch/cara/cara, + where we welcome contributions, feature requests and issue reports. +

    + @@ -283,7 +295,7 @@  © - 2020 + 2020 - CERN diff --git a/cara/models.py b/cara/models.py index bee4a0ff..d761b0c3 100644 --- a/cara/models.py +++ b/cara/models.py @@ -31,9 +31,11 @@ the same for all parameters of a single model. """ from dataclasses import dataclass -import numpy as np import typing +import numpy as np +from scipy.interpolate import interp1d + if not typing.TYPE_CHECKING: from memoization import cached else: @@ -133,15 +135,18 @@ class PiecewiseConstant: transition_times: typing.Tuple[float, ...] #: values of the function between transitions - values: typing.Tuple[float, ...] + values: typing.Tuple[_VectorisedFloat, ...] def __post_init__(self): if len(self.transition_times) != len(self.values)+1: raise ValueError("transition_times should contain one more element than values") if tuple(sorted(set(self.transition_times))) != self.transition_times: raise ValueError("transition_times should not contain duplicated elements and should be sorted") + shapes = [np.array(v).shape for v in self.values] + if not all(shapes[0] == shape for shape in shapes): + raise ValueError("All values must have the same shape") - def value(self, time) -> float: + def value(self, time) -> _VectorisedFloat: if time <= self.transition_times[0]: return self.values[0] elif time > self.transition_times[-1]: @@ -159,21 +164,21 @@ class PiecewiseConstant: for t1, t2, value in zip(self.transition_times[:-1], self.transition_times[1:], self.values): if value: - present_times.append((t1,t2)) + present_times.append((t1, t2)) return SpecificInterval(present_times=tuple(present_times)) - def refine(self, refine_factor=10): + def refine(self, refine_factor=10) -> "PiecewiseConstant": # build a new PiecewiseConstant object with a refined mesh, # using a linear interpolation in-between the initial mesh points refined_times = np.linspace(self.transition_times[0], self.transition_times[-1], (len(self.transition_times)-1) * refine_factor+1) + interpolator = interp1d( + self.transition_times, + np.concatenate([self.values, self.values[-1:]], axis=0), + axis=0) return PiecewiseConstant( tuple(refined_times), - tuple(np.interp( - refined_times[:-1], - self.transition_times, - self.values + (self.values[-1], ), - )), + tuple(interpolator(refined_times)[:-1]), ) @@ -254,10 +259,10 @@ class WindowOpening(Ventilation): outside_temp: PiecewiseConstant #: The height of the window (m). - window_height: float + window_height: _VectorisedFloat #: The length of the opening-gap when the window is open (m). - opening_length: float + opening_length: _VectorisedFloat #: The number of windows of the given dimensions. number_of_windows: int = 1 @@ -266,7 +271,7 @@ class WindowOpening(Ventilation): min_deltaT: float = 0.1 @property - def discharge_coefficient(self) -> float: + def discharge_coefficient(self) -> _VectorisedFloat: """ Discharge coefficient (or cd_b): what portion effective area is used to exchange air (0 <= discharge_coefficient <= 1). @@ -286,14 +291,14 @@ class WindowOpening(Ventilation): return 0. # Reminder, no dependence on time in the resulting calculation. - inside_temp = self.inside_temp.value(time) - outside_temp = self.outside_temp.value(time) + inside_temp: _VectorisedFloat = self.inside_temp.value(time) + outside_temp: _VectorisedFloat = self.outside_temp.value(time) # The inside_temperature is forced to be always at least min_deltaT degree # warmer than the outside_temperature. Further research needed to # handle the buoyancy driven ventilation when the temperature gradient # is inverted. - inside_temp = max(inside_temp, outside_temp + self.min_deltaT) + inside_temp = np.maximum(inside_temp, outside_temp + self.min_deltaT) # type: ignore temp_gradient = (inside_temp - outside_temp) / outside_temp root = np.sqrt(9.81 * self.window_height * temp_gradient) window_area = self.window_height * self.opening_length * self.number_of_windows @@ -307,7 +312,7 @@ class SlidingWindow(WindowOpening): the horizontal plane). """ @property - def discharge_coefficient(self) -> float: + def discharge_coefficient(self) -> _VectorisedFloat: """ Average measured value of discharge coefficient for sliding or side-hung windows. @@ -322,14 +327,14 @@ class HingedWindow(WindowOpening): horizontal plane). """ #: Window width (m). - window_width: float = 0.0 + window_width: _VectorisedFloat = 0.0 def __post_init__(self): - if not self.window_width > 0: + if self.window_width is 0.0: raise ValueError('window_width must be set') @property - def discharge_coefficient(self) -> float: + def discharge_coefficient(self) -> _VectorisedFloat: """ Simple model to compute discharge coefficient for top or bottom hung hinged windows, in the absence of empirical test results @@ -339,19 +344,15 @@ class HingedWindow(WindowOpening): see Section 8.3 of BB101 and Section 11.3 of ESFA Output Specification Annex 2F on Ventilation opening areas. """ - window_ratio = self.window_width / self.window_height - if window_ratio < 0.5: - M = 0.06 - cd_max = 0.612 - elif window_ratio < 1: - M = 0.048 - cd_max = 0.589 - elif window_ratio < 2: - M = 0.04 - cd_max = 0.563 - else: - M = 0.038 - cd_max = 0.548 + window_ratio = np.array(self.window_width / self.window_height) + coefs = np.empty(window_ratio.shape + (2, ), dtype=np.float64) + + coefs[window_ratio < 0.5] = (0.06, 0.612) + coefs[np.bitwise_and(0.5 <= window_ratio, window_ratio < 1)] = (0.048, 0.589) + coefs[np.bitwise_and(1 <= window_ratio, window_ratio < 2)] = (0.04, 0.563) + coefs[window_ratio >= 2] = (0.038, 0.548) + M, cd_max = coefs.T + window_angle = 2.*np.rad2deg(np.arcsin(self.opening_length/(2.*self.window_height))) return cd_max*(1-np.exp(-M*window_angle)) diff --git a/cara/tests/models/test_concentration_model.py b/cara/tests/models/test_concentration_model.py index 3d4f0fdc..9be1cbbf 100644 --- a/cara/tests/models/test_concentration_model.py +++ b/cara/tests/models/test_concentration_model.py @@ -13,7 +13,6 @@ import cara.models {'coefficient_of_infectivity': np.array([0.02, 0.05])}, {'η_exhale': np.array([0.92, 0.95])}, {'η_leaks': np.array([0.15, 0.20])}, - ] ) def test_concentration_model_vectorisation(override_params): diff --git a/cara/tests/models/test_piecewiseconstant.py b/cara/tests/models/test_piecewiseconstant.py new file mode 100644 index 00000000..a0ba14f0 --- /dev/null +++ b/cara/tests/models/test_piecewiseconstant.py @@ -0,0 +1,85 @@ +import numpy as np +import pytest + +from cara import models +from cara import data + + +def test_piecewiseconstantfunction_wrongarguments(): + # number of values should be 1+number of transition times + pytest.raises(ValueError, models.PiecewiseConstant, (0, 1), (0, 0)) + pytest.raises(ValueError, models.PiecewiseConstant, (0,), (0, 0)) + # two transition times cannot be equal + pytest.raises(ValueError, models.PiecewiseConstant, (0, 2, 2), (0, 0)) + # unsorted transition times are not allowed + pytest.raises(ValueError, models.PiecewiseConstant, (2, 0), (0, 0)) + + # If vectors, must all be same length. + with pytest.raises(ValueError, match="All values must have the same shape"): + models.PiecewiseConstant( + (0, 8, 16), (np.array([5, 7]), np.array([8, 9, 10])), + ) + + + +@pytest.mark.parametrize( + "time, expected_value", + [ + [10, 5], + [20.5, 8], + [8, 2], + [0, 2], + [24, 8], + [-1, 2], + [25, 8], + ], +) +def test_piecewiseconstant(time, expected_value): + transition_times = (0, 8, 16, 24) + values = (2, 5, 8) + fun = models.PiecewiseConstant(transition_times, values) + assert fun.value(time) == expected_value + + +def test_piecewiseconstant_interp(): + transition_times = (0, 8, 16, 24) + values = (2, 5, 8) + refined_fun = models.PiecewiseConstant(transition_times, values).refine(refine_factor=2) + assert refined_fun.transition_times == (0, 4, 8, 12, 16, 20, 24) + assert refined_fun.values == (2, 3.5, 5, 6.5, 8, 8) + + +def test_piecewiseconstant_interp_vectorised(): + transition_times = (0, 8, 16, 24) + values = (np.array([2, 3]), np.array([5, 7]), np.array([8, 9])) + refined_fun = models.PiecewiseConstant(transition_times, values).refine(refine_factor=2) + assert refined_fun.transition_times == (0, 4, 8, 12, 16, 20, 24) + np.testing.assert_almost_equal( + refined_fun.values, ((2, 3), (3.5, 5), (5, 7), (6.5, 8), (8, 9), (8, 9)), + ) + + +def test_constantfunction(): + transition_times = (0, 24) + values = (20,) + fun = models.PiecewiseConstant(transition_times, values) + for t in [0, 1, 8, 10, 16, 20.1, 24]: + assert (fun.value(t) == 20) + + +@pytest.mark.parametrize( + "time", + [0, 1, 8, 10, 16, 20.1, 24], +) +def test_piecewiseconstant_vs_interval(time): + transition_times = (0, 8, 16, 24) + values = (0, 1, 0) + fun = models.PiecewiseConstant(transition_times, values) + interval = models.SpecificInterval(present_times=[(8,16)]) + assert interval.transition_times() == fun.interval().transition_times() + assert fun.interval().triggered(time) == interval.triggered(time) + + +def test_piecewiseconstant_transition_times(): + outside_temp = data.GenevaTemperatures['Jan'] + assert set(outside_temp.transition_times) == outside_temp.interval().transition_times() diff --git a/cara/tests/test_known_quantities.py b/cara/tests/test_known_quantities.py index 042d9db0..cc3a6249 100644 --- a/cara/tests/test_known_quantities.py +++ b/cara/tests/test_known_quantities.py @@ -190,70 +190,6 @@ def test_expiration_aerosols(): npt.assert_allclose(exp1.aerosols(mask), exp2.aerosols(mask), rtol=1e-5) -def test_piecewiseconstantfunction_wrongarguments(): - # number of values should be 1+number of transition times - pytest.raises(ValueError,models.PiecewiseConstant,(0,1),(0,0)) - pytest.raises(ValueError,models.PiecewiseConstant,(0,),(0,0)) - # two transition times cannot be equal - pytest.raises(ValueError,models.PiecewiseConstant,(0,2,2),(0,0)) - # unsorted transition times are not allowed - pytest.raises(ValueError,models.PiecewiseConstant,(2,0),(0,0)) - - -@pytest.mark.parametrize( - "time, expected_value", - [ - [10, 5], - [20.5, 8], - [8, 2], - [0, 2], - [24, 8], - [-1, 2], - [25, 8], - ], -) -def test_piecewiseconstant(time, expected_value): - transition_times = (0, 8, 16, 24) - values = (2, 5, 8) - fun = models.PiecewiseConstant(transition_times,values) - assert fun.value(time) == expected_value - - -def test_piecewiseconstant_interp(): - transition_times = (0, 8, 16, 24) - values = (2, 5, 8) - fun = models.PiecewiseConstant(transition_times,values) - refined_fun = models.PiecewiseConstant(transition_times,values).refine(refine_factor=2) - assert refined_fun.transition_times == (0, 4, 8, 12, 16, 20 ,24) - assert refined_fun.values == (2, 3.5, 5, 6.5, 8, 8) - - -def test_constantfunction(): - transition_times = (0,24) - values = (20,) - fun = models.PiecewiseConstant(transition_times,values) - for t in [0,1,8,10,16,20.1,24]: - assert (fun.value(t) == 20) - - -@pytest.mark.parametrize( - "time", - [0,1,8,10,16,20.1,24], -) -def test_piecewiseconstant_vs_interval(time): - transition_times = (0,8,16,24) - values = (0,1,0) - fun = models.PiecewiseConstant(transition_times,values) - interval = models.SpecificInterval(present_times=[(8,16)]) - assert interval.transition_times() == fun.interval().transition_times() - assert fun.interval().triggered(time) == interval.triggered(time) - - -def test_piecewiseconstant_transition_times(): - outside_temp=data.GenevaTemperatures['Jan'] - assert set(outside_temp.transition_times) == outside_temp.interval().transition_times() - - @pytest.mark.parametrize( "time, expected_value", [ diff --git a/cara/tests/test_ventilation.py b/cara/tests/test_ventilation.py index d98fdff8..f10a6263 100644 --- a/cara/tests/test_ventilation.py +++ b/cara/tests/test_ventilation.py @@ -46,9 +46,8 @@ def test_number_of_windows(baseline_slidingwindow): [4., 0.308], ], ) -def test_hinged_window(baseline_hingedwindow,window_width, +def test_hinged_window(baseline_hingedwindow, window_width, expected_discharge_coefficient): - room = models.Room(75) hinged_window = dataclasses.replace(baseline_hingedwindow, window_width=window_width) @@ -56,9 +55,40 @@ def test_hinged_window(baseline_hingedwindow,window_width, expected_discharge_coefficient, rtol=1e-2) -def test_sliding_window(baseline_slidingwindow): - room = models.Room(75) +@pytest.mark.parametrize( + "override_params", [ + {'window_height': np.array([0.15, 0.20, 0.25])}, + {'window_width': np.array([0.15, 0.20, 0.25])}, + {'opening_length': np.array([0.15, 0.20, 0.25])}, + {'outside_temp': models.PiecewiseConstant( + (0, 2, 3), (np.array([20, 30, 28]), np.array([25, 30, 27])) + )}, + {'inside_temp': models.PiecewiseConstant( + (0, 20), (np.array([20, 30, 25]), ) + )}, + ] +) +def test_HingedWindow_vectorisation(override_params): + defaults = { + 'window_height': 0.15, + 'window_width': 0.15, + 'opening_length': 0.15, + 'inside_temp': models.PiecewiseConstant((0, 2, 3), (20, 25)), + 'outside_temp': models.PiecewiseConstant((0, 2, 3), (10, 15)), + } + defaults.update(override_params) + room = models.Room(volume=75) + t = 0.5 + window = models.HingedWindow(models.PeriodicInterval(60, 30), **defaults) + if {'window_height', 'opening_length', 'window_width'}.intersection(override_params): + assert isinstance(window.discharge_coefficient, np.ndarray) + else: + assert isinstance(window.discharge_coefficient, float) + assert isinstance(window.air_exchange(room, t), np.ndarray) + + +def test_sliding_window(baseline_slidingwindow): assert baseline_slidingwindow.discharge_coefficient == 0.6 diff --git a/requirements.txt b/requirements.txt index 2c87413a..1bbecfe1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -61,6 +61,7 @@ pyrsistent==0.17.3 python-dateutil==2.8.1 pyzmq==22.0.3 qrcode==6.1 +scipy==1.5.4 Send2Trash==1.5.0 six==1.15.0 sniffio==1.2.0 diff --git a/setup.cfg b/setup.cfg index 7dac8522..f40978b4 100644 --- a/setup.cfg +++ b/setup.cfg @@ -19,3 +19,6 @@ ignore_missing_imports = True [mypy-qrcode.*] ignore_missing_imports = True + +[mypy-scipy.*] +ignore_missing_imports = True diff --git a/setup.py b/setup.py index bf44d292..8868599f 100644 --- a/setup.py +++ b/setup.py @@ -26,6 +26,7 @@ REQUIREMENTS: dict = { 'mistune', 'numpy', 'qrcode[pil]', + 'scipy', 'tornado', 'voila >=0.2.4', ], @@ -58,6 +59,7 @@ setup( classifiers=[ "Programming Language :: Python :: 3", "Operating System :: OS Independent", + "License :: OSI Approved :: Apache Software License", # Apache 2.0 ], install_requires=REQUIREMENTS['core'], From 5eb87372be7c160f37743735049725c1a7bb309e Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Thu, 29 Apr 2021 19:47:10 +0200 Subject: [PATCH 2/3] Update the pages based on the open source requirements. --- LICENSE | 2 +- README.md | 41 +++++++++++------ app/cara.ipynb | 4 +- .../templates/base/calculator.report.html.j2 | 35 ++++++++++++--- .../templates/calculator.form.html.j2 | 42 +++++++++++++----- .../calculator/templates/userguide.html.j2 | 41 ++++++++++++----- cara/apps/templates/index.html.j2 | 44 +++++++++++-------- cara/apps/templates/layout.html.j2 | 4 +- 8 files changed, 151 insertions(+), 62 deletions(-) diff --git a/LICENSE b/LICENSE index c87de812..de49c2af 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2020-2021 CERN +Copyright 2020-2021 CERN. All rights not expressly granted are reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index be1f81f9..383ebef2 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,47 @@ # CARA - COVID Airborne Risk Assessment +CARA is a risk assessment tool developed to model the concentration of viruses in enclosed spaces, in order to inform space-management decisions. + +CARA models the concentration profile of potential infectious viruses in enclosed spaces with clear and intuitive graphs. +The user can set a number of parameters, including room volume, exposure time, activity type, mask-wearing and ventilation. +The report generated indicates how to avoid exceeding critical concentrations and chains of airborne transmission in spaces such as individual offices, meeting rooms and labs. + +The risk assessment tool simulates the long-range airborne spread SARS-CoV-2 virus in a finite volume, assuming a homogenous mixture, and estimates the risk of COVID-19 infection therein. +The results DO NOT include short-range airborne exposure (where the physical distance is a significant factor) nor the other known modes of SARS-CoV-2 transmission. +Hence, the output from this model is only valid when the other recommended public health & safety instructions are observed, such as adequate physical distancing, good hand hygiene and other barrier measures. + +The model used is based on scientific publications relating to airborne transmission of infectious diseases, dose-response exposures and aerosol science, as of February 2021. +It can be used to compare the effectiveness of different airborne-related risk mitigation measures. + +Note that this model applies a deterministic approach, i.e., it is assumed at least one person is infected and shedding viruses into the simulated volume. +Nonetheless, it is also important to understand that the absolute risk of infection is uncertain, as it will depend on the probability that someone infected attends the event. +The model is most useful for comparing the impact and effectiveness of different mitigation measures such as ventilation, filtration, exposure time, physical activity and +the size of the room, only considering long-range airborne transmission of COVID-19 in indoor settings. + +This tool is designed to be informative, allowing the user to adapt different settings and model the relative impact on the estimated infection probabilities. +The objective is to facilitate targeted decision-making and investment through comparisons, rather than a singular determination of absolute risk. +While the SARS-CoV-2 virus is in circulation among the population, the notion of 'zero risk' or 'completely safe scenario' does not exist. +Each event modelled is unique, and the results generated therein are only as accurate as the inputs and assumptions. + + ## Applications ### COVID Calculator -A risk assessment tool which simulates the long range airborne spread of the -SARS-CoV-2 virus for space managers. +A risk assessment tool which simulates the long range airborne spread of the SARS-CoV-2 virus for space managers. -You can find the CARA COVID Calculator at https://cara.web.cern.ch/calculator/. -Please see the [COVID Calculator README for detailed usage instructions](cara/apps/calculator/README.md). ### CARA Expert App A tool to interact with various parameters of the CARA model. -This is currently in beta, and can be found at https://cara.web.cern.ch/expert-app. ## Disclaimer -The code and data of this repository are provided to promote reproducible research. -They are not intended for clinical care or commercial use. +CARA has not undergone review, approval or certification by competent authorities, and as a result, it cannot be considered as a fully endorsed and reliable tool, namely in the assessment of potential viral emissions from infected hosts to be modelled. -The software is provided "as is", without warranty of any kind, express or implied, -including but not limited to the warranties of merchantability, fitness for a particular -purpose and non infringement. -In no event shall the authors or copyright holders be liable for any claim, damages -or other liability, whether in an action of contract, tort or otherwise, arising from, -out of or in connection with the software or the use or other dealings in the software. +The software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and non-infringement. +In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software. ## Development guide diff --git a/app/cara.ipynb b/app/cara.ipynb index 967bcbbc..01ac0106 100644 --- a/app/cara.ipynb +++ b/app/cara.ipynb @@ -8,7 +8,9 @@ "\n", "

    \n", "Airborne Transmission of SARS-CoV-2\n", - "

    " + "

    \n", + "

    \n", + "Please see the CARA homepage for details on the methodology, assumptions and limitations of CARA.

    " ] }, { diff --git a/cara/apps/calculator/templates/base/calculator.report.html.j2 b/cara/apps/calculator/templates/base/calculator.report.html.j2 index bb4e57a4..1471e6b4 100644 --- a/cara/apps/calculator/templates/base/calculator.report.html.j2 +++ b/cara/apps/calculator/templates/base/calculator.report.html.j2 @@ -293,11 +293,36 @@
    {% block disclaimer %}

    Disclaimer:

    -

    The risk assessment tool simulates the long-range airborne spread SARS-CoV-2 virus in a finite volume, assuming a homogenous mixture, and estimates the risk of COVID-19 infection therein. The results DO NOT include short-range airborne exposure (where the physical distance plays a factor) nor the other known modes of SARS-CoV-2 transmission. Hence, the output from this model is only valid when the other recommended public health & safety instructions are observed, such as adequate physical distancing, good hand hygiene and other barrier measures.

    - The model used is based on scientific publications relating to airborne transmission of infectious diseases, dose-response exposures and aerosol science, as of December 2020 . It can be used to compare the effectiveness of different airborne-related risk mitigation measures.

    - Note that this model applies a deterministic approach, i.e., it is assumed at least one person is infected and shedding viruses into the simulated volume. Nonetheless, it is also important to understand that the absolute risk of infection is uncertain, as it will depend on the probability that someone infected attends the event. The model is most useful for comparing the impact and effectiveness of different mitigation measures such as ventilation, filtration, exposure time, physical activity and the size of the room, only considering long-range airborne transmission of COVID-19 in indoor settings.

    - This tool is designed to be informative, allowing the user to adapt different settings and model the relative impact on the estimated infection probabilities. The objective is to facilitate targeted decision-making and investment through comparisons, rather than a singular determination of absolute risk. While the SARS-CoV-2 virus is in circulation among the population, the notion of 'zero risk' or a 'completely safe scenario' does not exist. Each event modelled is unique and the results generated therein are only as accurate as the inputs and assumptions. -

    + +

    + CARA is a risk assessment tool developed to model the concentration of viruses in enclosed spaces, in order to inform space-management decisions. +

    +

    + CARA models the concentration profile of potential infectious viruses in enclosed spaces with clear and intuitive graphs. + The user can set a number of parameters, including room volume, exposure time, activity type, mask-wearing and ventilation. + The report generated indicates how to avoid exceeding critical concentrations and chains of airborne transmission in spaces such as individual offices, meeting rooms and labs. +

    +

    + The risk assessment tool simulates the long-range airborne spread SARS-CoV-2 virus in a finite volume, assuming a homogenous mixture, and estimates the risk of COVID-19 infection therein. + The results DO NOT include short-range airborne exposure (where the physical distance is a significant factor) nor the other known modes of SARS-CoV-2 transmission. + Hence, the output from this model is only valid when the other recommended public health & safety instructions are observed, such as adequate physical distancing, good hand hygiene and other barrier measures. +

    +

    + The model used is based on scientific publications relating to airborne transmission of infectious diseases, dose-response exposures and aerosol science, as of February 2021. + It can be used to compare the effectiveness of different airborne-related risk mitigation measures. +

    +

    + Note that this model applies a deterministic approach, i.e., it is assumed at least one person is infected and shedding viruses into the simulated volume. + Nonetheless, it is also important to understand that the absolute risk of infection is uncertain, as it will depend on the probability that someone infected attends the event. + The model is most useful for comparing the impact and effectiveness of different mitigation measures such as ventilation, filtration, exposure time, physical activity and + the size of the room, only considering long-range airborne transmission of COVID-19 in indoor settings. +

    +

    + This tool is designed to be informative, allowing the user to adapt different settings and model the relative impact on the estimated infection probabilities. + The objective is to facilitate targeted decision-making and investment through comparisons, rather than a singular determination of absolute risk. + While the SARS-CoV-2 virus is in circulation among the population, the notion of 'zero risk' or 'completely safe scenario' does not exist. + Each event modelled is unique, and the results generated therein are only as accurate as the inputs and assumptions. +

    {% endblock disclaimer %}
    {% endblock disclaimer_container %} diff --git a/cara/apps/calculator/templates/calculator.form.html.j2 b/cara/apps/calculator/templates/calculator.form.html.j2 index a47e8812..c551eb77 100644 --- a/cara/apps/calculator/templates/calculator.form.html.j2 +++ b/cara/apps/calculator/templates/calculator.form.html.j2 @@ -318,17 +318,37 @@ v{{ calculator_version }} Please sen



    - -
    -

    This software is provided with a disclaimer and code license.


    -

    +
    +

    Disclaimer:

    +

    + CARA is a risk assessment tool developed to model the concentration of viruses in enclosed spaces, in order to inform space-management decisions. +

    +

    + CARA models the concentration profile of potential infectious viruses in enclosed spaces with clear and intuitive graphs. + The user can set a number of parameters, including room volume, exposure time, activity type, mask-wearing and ventilation. + The report generated indicates how to avoid exceeding critical concentrations and chains of airborne transmission in spaces such as individual offices, meeting rooms and labs. +

    +

    + The risk assessment tool simulates the long-range airborne spread SARS-CoV-2 virus in a finite volume, assuming a homogenous mixture, and estimates the risk of COVID-19 infection therein. + The results DO NOT include short-range airborne exposure (where the physical distance is a significant factor) nor the other known modes of SARS-CoV-2 transmission. + Hence, the output from this model is only valid when the other recommended public health & safety instructions are observed, such as adequate physical distancing, good hand hygiene and other barrier measures. +

    +

    + The model used is based on scientific publications relating to airborne transmission of infectious diseases, dose-response exposures and aerosol science, as of February 2021. + It can be used to compare the effectiveness of different airborne-related risk mitigation measures. +

    +

    + Note that this model applies a deterministic approach, i.e., it is assumed at least one person is infected and shedding viruses into the simulated volume. + Nonetheless, it is also important to understand that the absolute risk of infection is uncertain, as it will depend on the probability that someone infected attends the event. + The model is most useful for comparing the impact and effectiveness of different mitigation measures such as ventilation, filtration, exposure time, physical activity and + the size of the room, only considering long-range airborne transmission of COVID-19 in indoor settings. +

    +

    + This tool is designed to be informative, allowing the user to adapt different settings and model the relative impact on the estimated infection probabilities. + The objective is to facilitate targeted decision-making and investment through comparisons, rather than a singular determination of absolute risk. + While the SARS-CoV-2 virus is in circulation among the population, the notion of 'zero risk' or 'completely safe scenario' does not exist. + Each event modelled is unique, and the results generated therein are only as accurate as the inputs and assumptions. +

    diff --git a/cara/apps/calculator/templates/userguide.html.j2 b/cara/apps/calculator/templates/userguide.html.j2 index d78295a6..3d59ab5f 100644 --- a/cara/apps/calculator/templates/userguide.html.j2 +++ b/cara/apps/calculator/templates/userguide.html.j2 @@ -9,16 +9,37 @@ If you are using the expert version of the tool, you should look at the expert notes.

    For more information on the Airborne Transmission of SARS-CoV-2, feel free to check out the HSE Seminar: https://cds.cern.ch/record/2743403

    Disclaimer

    -

    The risk assessment tool simulates the long-range airborne spread SARS-CoV-2 virus in a finite volume, assuming a homogenous mixture, and estimates the risk of COVID-19 infection therein. -The results DO NOT include short-range airborne exposure (where the physical distance plays a factor) nor the other known modes of SARS-CoV-2 transmission. -Hence, the output from this model is only valid when the other recommended public health & safety instructions are observed, such as adequate physical distancing, good hand hygiene and other barrier measures.

    -

    The model used is based on scientific publications relating to airborne transmission of infectious diseases, dose-response exposures and aerosol science, as of December 2020 . It can be used to compare the effectiveness of different airborne-related risk mitigation measures.

    -

    Note that this model applies a deterministic approach, i.e., it is assumed at least one person is infected and shedding viruses into the simulated volume. -Nonetheless, it is also important to understand that the absolute risk of infection is uncertain, as it will depend on the probability that someone infected attends the event. -The model is most useful for comparing the impact and effectiveness of different mitigation measures such as ventilation, filtration, exposure time, physical activity and the size of the room, only considering long-range airborne transmission of COVID-19 in indoor settings.

    -

    This tool is designed to be informative, allowing the user to adapt different settings and model the relative impact on the estimated infection probabilities. -The objective is to facilitate targeted decision-making and investment through comparisons, rather than a singular determination of absolute risk. While the SARS-CoV-2 virus is in circulation among the population, the notion of 'zero risk' or a 'completely safe scenario' does not exist. -Each event modelled is unique and the results generated therein are only as accurate as the inputs and assumptions.

    + +

    + CARA is a risk assessment tool developed to model the concentration of viruses in enclosed spaces, in order to inform space-management decisions. +

    +

    + CARA models the concentration profile of potential infectious viruses in enclosed spaces with clear and intuitive graphs. + The user can set a number of parameters, including room volume, exposure time, activity type, mask-wearing and ventilation. + The report generated indicates how to avoid exceeding critical concentrations and chains of airborne transmission in spaces such as individual offices, meeting rooms and labs. +

    +

    + The risk assessment tool simulates the long-range airborne spread SARS-CoV-2 virus in a finite volume, assuming a homogenous mixture, and estimates the risk of COVID-19 infection therein. + The results DO NOT include short-range airborne exposure (where the physical distance is a significant factor) nor the other known modes of SARS-CoV-2 transmission. + Hence, the output from this model is only valid when the other recommended public health & safety instructions are observed, such as adequate physical distancing, good hand hygiene and other barrier measures. +

    +

    + The model used is based on scientific publications relating to airborne transmission of infectious diseases, dose-response exposures and aerosol science, as of February 2021. + It can be used to compare the effectiveness of different airborne-related risk mitigation measures. +

    +

    + Note that this model applies a deterministic approach, i.e., it is assumed at least one person is infected and shedding viruses into the simulated volume. + Nonetheless, it is also important to understand that the absolute risk of infection is uncertain, as it will depend on the probability that someone infected attends the event. + The model is most useful for comparing the impact and effectiveness of different mitigation measures such as ventilation, filtration, exposure time, physical activity and + the size of the room, only considering long-range airborne transmission of COVID-19 in indoor settings. +

    +

    + This tool is designed to be informative, allowing the user to adapt different settings and model the relative impact on the estimated infection probabilities. + The objective is to facilitate targeted decision-making and investment through comparisons, rather than a singular determination of absolute risk. + While the SARS-CoV-2 virus is in circulation among the population, the notion of 'zero risk' or 'completely safe scenario' does not exist. + Each event modelled is unique, and the results generated therein are only as accurate as the inputs and assumptions. +

    +

    How to use this tool

    Simulation Name & Room number

    In order to be able to trace back the simulations in your workplace risk assessments, performed with the tool, you can give each one a unique name - for example "Office use on Tuesday mornings". diff --git a/cara/apps/templates/index.html.j2 b/cara/apps/templates/index.html.j2 index 9713067c..a5e4fc3c 100644 --- a/cara/apps/templates/index.html.j2 +++ b/cara/apps/templates/index.html.j2 @@ -16,16 +16,31 @@

    CARA: COVID Airborne Risk Assessment Tools

    -
    - -

    Please try out the CARA COVID calculator here. - Your feedback is most welcome at CARA-dev@cern.ch

    - - - + +

    Introduction


    +
    +

    + CARA is a risk assessment tool developed to model the concentration of viruses in enclosed spaces, in order to inform space-management decisions. + It does this by simulating the long-range airborne spread SARS-CoV-2 virus in a finite volume, assuming homogenous mixing, and it estimates the risk of COVID-19 infection therein. + Please see the about page for more details on the methodology, assumptions and limitations of CARA. +

    +

    + The full CARA source code can be accessed freely under an Apache 2.0 open source license from our code repository. + It includes detailed instructions on how to run your own version of this tool. +

    -

    Authors:


    +
    +

    CARA@CERN


    +
    +

    + CARA has been developed by CERN with the intention of allowing members of personnel with roles related to supervision, health & safety or space management to simulate the concerned workplaces on CERN sites. + A hosted CERN version of the CARA Covid Calculator is available on this site to members of the CERN personnel. +

    +
    + +
    +

    Authors

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


    @@ -35,25 +50,18 @@ 3Experimental Physics Department, Safety Office, CERN
    4Beams Department, Controls Group, CERN
    5Information Technology Department, Collaboration, Devices & Applications Group, CERN
    -

    -

    Acknowledgements:


    +
    +

    Acknowledgements:

    We thank CERN’s HSE Unit, Beams Department, Experimental Physics Department and Information Technology Department for their continuous support. Thanks to Doris Forkel-Wirth, Olga Beltramello, Letizia Di Giulio, Evelyne Dho and the other members of the office occupancy working group for providing expert advice and extensively testing the tool. We thank Fabienne Landua and the Design and Visual Identity Service for preparing the logo. Thanks also to colleagues like Oriol Rios, Marco Andreini, Lina Dimovasili for the technical discussions and advice. Many thanks to 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 – their contribution was indispensable for this project. - +

    - -

    Intended Users:

    -

    - CARA is made available for internal CERN use only. It is intended for Members of Personnel with roles related to Supervision, Health & Safety or Space Management, in order to simulate the concerned workplaces on CERN sites. For use outside of this scope, please contact CERN Knowledge Transfer (kt@cern.ch). - -

    -
    diff --git a/cara/apps/templates/layout.html.j2 b/cara/apps/templates/layout.html.j2 index 566c545d..d668b3ee 100644 --- a/cara/apps/templates/layout.html.j2 +++ b/cara/apps/templates/layout.html.j2 @@ -294,9 +294,7 @@ d="M56 6H44c-1.1 0-2 0.9-2 2s0.9 2 2 2h7.2L30.6 30.6c-0.8 0.8-0.8 2 0 2.8C31 33.8 31.5 34 32 34s1-0.2 1.4-0.6L54 12.8V20c0 1.1 0.9 2 2 2s2-0.9 2-2V8C58 6.9 57.1 6 56 6z"> -  © - 2020 - - CERN
    +  © 2020 - 2021 CERN From 93d91e0d4d24764cbd4a60e4105045e5fcf3a971 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Thu, 29 Apr 2021 23:47:47 +0200 Subject: [PATCH 3/3] Review actions. --- .../templates/base/calculator.report.html.j2 | 5 +++++ .../apps/calculator/templates/calculator.form.html.j2 | 4 ++++ cara/apps/calculator/templates/userguide.html.j2 | 4 ++++ cara/apps/static/css/colors.css | 4 ++-- cara/apps/templates/index.html.j2 | 11 +++++------ cara/apps/templates/layout.html.j2 | 2 +- 6 files changed, 21 insertions(+), 9 deletions(-) diff --git a/cara/apps/calculator/templates/base/calculator.report.html.j2 b/cara/apps/calculator/templates/base/calculator.report.html.j2 index 1471e6b4..27bdacf9 100644 --- a/cara/apps/calculator/templates/base/calculator.report.html.j2 +++ b/cara/apps/calculator/templates/base/calculator.report.html.j2 @@ -323,6 +323,11 @@ While the SARS-CoV-2 virus is in circulation among the population, the notion of 'zero risk' or 'completely safe scenario' does not exist. Each event modelled is unique, and the results generated therein are only as accurate as the inputs and assumptions.

    +

    + CARA has not undergone review, approval or certification by competent authorities, and as a result, it cannot be considered + as a fully endorsed and reliable tool, namely in the assessment of potential viral emissions from infected hosts to be modelled. +

    + {% endblock disclaimer %} {% endblock disclaimer_container %} diff --git a/cara/apps/calculator/templates/calculator.form.html.j2 b/cara/apps/calculator/templates/calculator.form.html.j2 index c551eb77..063a1c46 100644 --- a/cara/apps/calculator/templates/calculator.form.html.j2 +++ b/cara/apps/calculator/templates/calculator.form.html.j2 @@ -349,6 +349,10 @@ v{{ calculator_version }} Please sen While the SARS-CoV-2 virus is in circulation among the population, the notion of 'zero risk' or 'completely safe scenario' does not exist. Each event modelled is unique, and the results generated therein are only as accurate as the inputs and assumptions.

    +

    + CARA has not undergone review, approval or certification by competent authorities, and as a result, it cannot be considered + as a fully endorsed and reliable tool, namely in the assessment of potential viral emissions from infected hosts to be modelled. +

    diff --git a/cara/apps/calculator/templates/userguide.html.j2 b/cara/apps/calculator/templates/userguide.html.j2 index 3d59ab5f..b434365a 100644 --- a/cara/apps/calculator/templates/userguide.html.j2 +++ b/cara/apps/calculator/templates/userguide.html.j2 @@ -39,6 +39,10 @@ If you are using the expert version of the tool, you should look at the expert While the SARS-CoV-2 virus is in circulation among the population, the notion of 'zero risk' or 'completely safe scenario' does not exist. Each event modelled is unique, and the results generated therein are only as accurate as the inputs and assumptions.

    +

    + CARA has not undergone review, approval or certification by competent authorities, and as a result, it cannot be considered + as a fully endorsed and reliable tool, namely in the assessment of potential viral emissions from infected hosts to be modelled. +

    How to use this tool

    Simulation Name & Room number

    diff --git a/cara/apps/static/css/colors.css b/cara/apps/static/css/colors.css index 73c62e29..c7ced46d 100644 --- a/cara/apps/static/css/colors.css +++ b/cara/apps/static/css/colors.css @@ -136,9 +136,9 @@ body > footer { color: #fffeee !important; } body > footer h2:after { background: #fffeee !important; } - body > footer nav ul.menu.nav li a { + body > footer a, footer a { color: #fffefe; } - body > footer nav ul.menu.nav li a:hover, body > footer nav ul.menu.nav li a.is-active { + body > footer a:hover, body > footer a.is-active { color: #fffefe; } body > footer nav ul.menu.nav li a:hover:before, body > footer nav ul.menu.nav li a.is-active:before { color: #2d8af1; } diff --git a/cara/apps/templates/index.html.j2 b/cara/apps/templates/index.html.j2 index a5e4fc3c..2e814fd1 100644 --- a/cara/apps/templates/index.html.j2 +++ b/cara/apps/templates/index.html.j2 @@ -43,7 +43,7 @@

    Authors

    -

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


    +

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


    1HSE Unit, Occupational Health & Safety Group, CERN
    2Beams Department, Accelerators and Beam Physics Group, CERN
    @@ -55,11 +55,10 @@

    Acknowledgements:

    - We thank CERN’s HSE Unit, Beams Department, Experimental Physics Department and Information Technology Department for their continuous support. - Thanks to Doris Forkel-Wirth, Olga Beltramello, Letizia Di Giulio, Evelyne Dho and the other members of the office occupancy working group for providing expert advice and extensively testing the tool. - We thank Fabienne Landua and the Design and Visual Identity Service for preparing the logo. - Thanks also to colleagues like Oriol Rios, Marco Andreini, Lina Dimovasili for the technical discussions and advice. - Many thanks to 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 – their contribution was indispensable for this project. + 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/layout.html.j2 b/cara/apps/templates/layout.html.j2 index d668b3ee..be46f836 100644 --- a/cara/apps/templates/layout.html.j2 +++ b/cara/apps/templates/layout.html.j2 @@ -240,7 +240,7 @@

    - CARA is Apache 2.0 licensed open-source + CARA is Apache 2.0 licensed open-source software developed at CERN. You can find the source code at https://gitlab.cern.ch/cara/cara, where we welcome contributions, feature requests and issue reports.