diff --git a/caimira/apps/calculator/model_generator.py b/caimira/apps/calculator/model_generator.py index 49fb639a..4896e485 100644 --- a/caimira/apps/calculator/model_generator.py +++ b/caimira/apps/calculator/model_generator.py @@ -807,7 +807,7 @@ def baseline_raw_form_data() -> typing.Dict[str, typing.Union[str, float]]: ACTIVITY_TYPES = {'office', 'smallmeeting', 'largemeeting', 'training', 'training_attendee', 'callcentre', 'controlroom-day', 'controlroom-night', 'library', 'workshop', 'lab', 'gym'} MECHANICAL_VENTILATION_TYPES = {'mech_type_air_changes', 'mech_type_air_supply', 'not-applicable'} -MASK_TYPES = {'Type I', 'FFP2'} +MASK_TYPES = {'Type I', 'FFP2', 'Cloth'} MASK_WEARING_OPTIONS = {'mask_on', 'mask_off'} VENTILATION_TYPES = {'natural_ventilation', 'mechanical_ventilation', 'no_ventilation'} VIRUS_TYPES = {'SARS_CoV_2', 'SARS_CoV_2_ALPHA', 'SARS_CoV_2_BETA','SARS_CoV_2_GAMMA', 'SARS_CoV_2_DELTA', 'SARS_CoV_2_OMICRON'} diff --git a/caimira/apps/static/images/masks/cloth.png b/caimira/apps/static/images/masks/cloth.png new file mode 100644 index 00000000..40481b68 Binary files /dev/null and b/caimira/apps/static/images/masks/cloth.png differ diff --git a/caimira/apps/templates/base/calculator.form.html.j2 b/caimira/apps/templates/base/calculator.form.html.j2 index b1dc9534..665527f6 100644 --- a/caimira/apps/templates/base/calculator.form.html.j2 +++ b/caimira/apps/templates/base/calculator.form.html.j2 @@ -295,6 +295,13 @@ +
+ + +

diff --git a/caimira/models.py b/caimira/models.py index 86808236..4a96be97 100644 --- a/caimira/models.py +++ b/caimira/models.py @@ -526,6 +526,9 @@ class Mask: #: Filtration efficiency of masks when inhaling. η_inhale: _VectorisedFloat + #: Filtration efficiency of masks when exhaling. + η_exhale: typing.Union[None, _VectorisedFloat] = None + #: Global factor applied to filtration efficiency of masks when exhaling. factor_exhale: float = 1. @@ -541,6 +544,10 @@ class Mask: the leakage through the sides. Diameter is in microns. """ + if self.η_exhale is not None: + # When η_exhale is specified, return it directly + return self.η_exhale + d = np.array(diameter) intermediate_range1 = np.bitwise_and(0.5 <= d, d < 0.94614) intermediate_range2 = np.bitwise_and(0.94614 <= d, d < 3.) @@ -570,6 +577,10 @@ Mask.types = { 'FFP2': Mask( η_inhale=0.865, # (94% penetration efficiency + 8% max inward leakage -> EN 149) ), + 'Cloth': Mask( # https://doi.org/10.1080/02786826.2021.1890687 + η_inhale=0.225, + η_exhale=0.35, + ), } diff --git a/caimira/monte_carlo/data.py b/caimira/monte_carlo/data.py index 8ad2fcfc..e0eaa09a 100644 --- a/caimira/monte_carlo/data.py +++ b/caimira/monte_carlo/data.py @@ -167,9 +167,11 @@ virus_distributions = { # https://doi.org/10.1080/02786826.2021.1890687 # https://doi.org/10.1016/j.jhin.2013.02.007 # https://doi.org/10.4209/aaqr.2020.08.0531 +# https://doi.org/10.1080/02786826.2021.1890687 mask_distributions = { - 'Type I': mc.Mask(Uniform(0.25, 0.80)), - 'FFP2': mc.Mask(Uniform(0.83, 0.91)), + 'Type I': mc.Mask(η_inhale=Uniform(0.25, 0.80)), + 'FFP2': mc.Mask(η_inhale=Uniform(0.83, 0.91)), + 'Cloth': mc.Mask(η_inhale=Uniform(0.05, 0.40), η_exhale=Uniform(0.20, 0.50)), } diff --git a/caimira/tests/apps/calculator/test_model_generator.py b/caimira/tests/apps/calculator/test_model_generator.py index 1dbb4961..787e7a8e 100644 --- a/caimira/tests/apps/calculator/test_model_generator.py +++ b/caimira/tests/apps/calculator/test_model_generator.py @@ -30,6 +30,7 @@ def test_model_from_dict_invalid(baseline_form_data): [ ["No mask"], ["Type I"], + ["Cloth"], ] ) def test_blend_expiration(mask_type): diff --git a/caimira/tests/test_monte_carlo_full_models.py b/caimira/tests/test_monte_carlo_full_models.py index 0e333526..9ce540e0 100644 --- a/caimira/tests/test_monte_carlo_full_models.py +++ b/caimira/tests/test_monte_carlo_full_models.py @@ -347,6 +347,8 @@ def test_report_models(mc_model, expected_pi, expected_new_cases, ["Type I", "Jul", 1.663, 0.938, 193.52], ["FFP2", "Jul", 0.523, 0.253, 193.52], ["Type I", "Feb", 0.659, 0.325, 193.52], + ["Cloth", "Feb", 2.653, 1.741, 673.10], + ["Cloth", "Jul", 5.322, 5.064, 673.10], ], ) def test_small_shared_office_Geneva(mask_type, month, expected_pi,