From 5b639f433c71c912d84f26ed3108ccef0f6578b6 Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Tue, 5 Oct 2021 15:44:37 +0200 Subject: [PATCH 01/10] Updated tests variables (transmissibility_factor, evaporation_factor and host_immunity) --- cara/apps/calculator/model_generator.py | 3 ++- cara/apps/expert.py | 1 + cara/models.py | 2 +- cara/tests/conftest.py | 4 +++- cara/tests/models/test_concentration_model.py | 7 ++++-- cara/tests/models/test_exposure_model.py | 23 +++++++++++-------- cara/tests/test_infected_population.py | 1 + cara/tests/test_known_quantities.py | 10 +++++++- cara/tests/test_monte_carlo.py | 2 ++ cara/tests/test_monte_carlo_full_models.py | 7 ++++++ 10 files changed, 44 insertions(+), 16 deletions(-) diff --git a/cara/apps/calculator/model_generator.py b/cara/apps/calculator/model_generator.py index ad2c27bb..1cb3c5d3 100644 --- a/cara/apps/calculator/model_generator.py +++ b/cara/apps/calculator/model_generator.py @@ -246,8 +246,9 @@ class FormData: room=room, ventilation=self.ventilation(), infected=self.infected_population(), + evaporation_factor=0.3, ), - exposed=self.exposed_population() + exposed=self.exposed_population(), ) def build_model(self, sample_size=_DEFAULT_MC_SAMPLE_SIZE) -> models.ExposureModel: diff --git a/cara/apps/expert.py b/cara/apps/expert.py index b06c8702..a5f11f86 100644 --- a/cara/apps/expert.py +++ b/cara/apps/expert.py @@ -501,6 +501,7 @@ baseline_model = models.ExposureModel( expiration=models.Expiration.types['Talking'], host_immunity=0., ), + evaporation_factor=0.3, ), exposed=models.Population( number=10, diff --git a/cara/models.py b/cara/models.py index b7c1ff95..b64eea7d 100644 --- a/cara/models.py +++ b/cara/models.py @@ -777,7 +777,7 @@ class ConcentrationModel: #: evaporation factor: the particles' diameter is multiplied by this # factor as soon as they are in the air (but AFTER going out of the, # mask, if any). - evaporation_factor: float = 0.3 + evaporation_factor: float #= 0.3 @property def virus(self): diff --git a/cara/tests/conftest.py b/cara/tests/conftest.py index e828e0cd..27ce9f1d 100644 --- a/cara/tests/conftest.py +++ b/cara/tests/conftest.py @@ -20,9 +20,11 @@ def baseline_model(): mask=models.Mask.types['No mask'], activity=models.Activity.types['Light activity'], known_individual_emission_rate=970 * 50, + host_immunity=0., # superspreading event, where ejection factor is fixed based # on Miller et al. (2020) - 50 represents the infectious dose. ), + evaporation_factor=0.3, ) return model @@ -36,8 +38,8 @@ def baseline_exposure_model(baseline_model): presence=baseline_model.infected.presence, activity=baseline_model.infected.activity, mask=baseline_model.infected.mask, + host_immunity=0., ), - fraction_deposited=1., ) diff --git a/cara/tests/models/test_concentration_model.py b/cara/tests/models/test_concentration_model.py index 27bb21f0..432b4d80 100644 --- a/cara/tests/models/test_concentration_model.py +++ b/cara/tests/models/test_concentration_model.py @@ -43,10 +43,12 @@ def test_concentration_model_vectorisation(override_params): viral_load_in_sputum=defaults['viral_load_in_sputum'], infectious_dose=50., viable_to_RNA_ratio = 0.5, + transmissibility_factor=1.0, ), expiration=models._ExpirationBase.types['Breathing'], host_immunity=0., - ) + ), + evaporation_factor=0.3, ) concentrations = c_model.concentration(10) assert isinstance(concentrations, np.ndarray) @@ -67,7 +69,8 @@ def simple_conc_model(): virus=models.Virus.types['SARS_CoV_2'], expiration=models.Expiration.types['Breathing'], host_immunity=0., - ) + ), + evaporation_factor=0.3, ) diff --git a/cara/tests/models/test_exposure_model.py b/cara/tests/models/test_exposure_model.py index 3ffe1fe4..0a39d90c 100644 --- a/cara/tests/models/test_exposure_model.py +++ b/cara/tests/models/test_exposure_model.py @@ -41,17 +41,17 @@ populations = [ # A simple scalar population. models.Population( 10, halftime, models.Mask.types['Type I'], - models.Activity.types['Standing'], + models.Activity.types['Standing'], host_immunity=0., ), # A population with some array component for η_inhale. models.Population( 10, halftime, models.Mask(np.array([0.3, 0.35])), - models.Activity.types['Standing'], + models.Activity.types['Standing'], host_immunity=0. ), # A population with some array component for inhalation_rate. models.Population( 10, halftime, models.Mask.types['Type I'], - models.Activity(np.array([0.51, 0.57]), 0.57), + models.Activity(np.array([0.51, 0.57]), 0.57), host_immunity=0. ), ] @@ -70,7 +70,7 @@ def known_concentrations(func): ) normed_func = lambda x: func(x) / dummy_infected_population.emission_rate_when_present() return KnownNormedconcentration(dummy_room, dummy_ventilation, - dummy_infected_population, normed_func) + dummy_infected_population, 0.3, normed_func) @pytest.mark.parametrize( @@ -92,7 +92,7 @@ def known_concentrations(func): ]) def test_exposure_model_ndarray(population, cm, f_dep, expected_exposure, expected_probability): - model = ExposureModel(cm, population, fraction_deposited=f_dep) + model = ExposureModel(cm, population) np.testing.assert_almost_equal( model.exposure(), expected_exposure ) @@ -154,7 +154,9 @@ def conc_model(): known_individual_emission_rate=970 * 50, # superspreading event, where ejection factor is fixed based # on Miller et al. (2020) - 50 represents the infectious dose. - ) + host_immunity=0., + ), + evaporation_factor=0.3, ) @@ -176,9 +178,9 @@ def test_exposure_model_integral_accuracy(exposed_time_interval, presence_interval = models.SpecificInterval((exposed_time_interval,)) population = models.Population( 10, presence_interval, models.Mask.types['Type I'], - models.Activity.types['Standing'], + models.Activity.types['Standing'], 0., ) - model = ExposureModel(conc_model, population, fraction_deposited=1.) + model = ExposureModel(conc_model, population) np.testing.assert_allclose(model.exposure(), expected_exposure) @@ -192,6 +194,7 @@ def test_infectious_dose_vectorisation(): viral_load_in_sputum=1e9, infectious_dose=np.array([50, 20, 30]), viable_to_RNA_ratio = 0.5, + transmissibility_factor=1.0, ), expiration=models.Expiration.types['Speaking'], host_immunity=0., @@ -202,9 +205,9 @@ def test_infectious_dose_vectorisation(): presence_interval = models.SpecificInterval(((0., 1.),)) population = models.Population( 10, presence_interval, models.Mask.types['Type I'], - models.Activity.types['Standing'], + models.Activity.types['Standing'], 0., ) - model = ExposureModel(cm, population, fraction_deposited=1.0) + model = ExposureModel(cm, population) #, fraction_deposited=1.0 inf_probability = model.infection_probability() assert isinstance(inf_probability, np.ndarray) assert inf_probability.shape == (3, ) diff --git a/cara/tests/test_infected_population.py b/cara/tests/test_infected_population.py index 4aafbef3..8856d312 100644 --- a/cara/tests/test_infected_population.py +++ b/cara/tests/test_infected_population.py @@ -33,6 +33,7 @@ def test_infected_population_vectorisation(override_params): viral_load_in_sputum=defaults['viral_load_in_sputum'], infectious_dose=50., viable_to_RNA_ratio = 0.5, + transmissibility_factor=1.0, ), expiration=cara.models._ExpirationBase.types['Breathing'], host_immunity=0., diff --git a/cara/tests/test_known_quantities.py b/cara/tests/test_known_quantities.py index d1db42c2..e9ce8168 100644 --- a/cara/tests/test_known_quantities.py +++ b/cara/tests/test_known_quantities.py @@ -73,9 +73,11 @@ def build_model(interval_duration): mask=models.Mask.types['No mask'], activity=models.Activity.types['Light activity'], known_individual_emission_rate=970 * 50, + host_immunity=0., # superspreading event, where ejection factor is fixed based # on Miller et al. (2020) - 50 represents the infectious dose. ), + evaporation_factor=0.3, ) return model @@ -235,7 +237,9 @@ def build_hourly_dependent_model( mask=models.Mask.types['No mask'], activity=models.Activity.types['Light activity'], known_individual_emission_rate=970 * 50, + host_immunity=0, ), + evaporation_factor=0.3, ) return model @@ -256,7 +260,9 @@ def build_constant_temp_model(outside_temp, intervals_open=((7.5, 8.5),)): mask=models.Mask.types['No mask'], activity=models.Activity.types['Light activity'], known_individual_emission_rate=970 * 50, + host_immunity=0., ), + evaporation_factor=0.3, ) return model @@ -284,7 +290,9 @@ def build_hourly_dependent_model_multipleventilation(month, intervals_open=((7.5 mask=models.Mask.types['No mask'], activity=models.Activity.types['Light activity'], known_individual_emission_rate=970 * 50, + host_immunity=0., ), + evaporation_factor=0.3, ) return model @@ -368,8 +376,8 @@ def build_exposure_model(concentration_model): presence=infected.presence, activity=infected.activity, mask=infected.mask, + host_immunity=0., ), - fraction_deposited=1., ) diff --git a/cara/tests/test_monte_carlo.py b/cara/tests/test_monte_carlo.py index 383aed34..1a7fc8a9 100644 --- a/cara/tests/test_monte_carlo.py +++ b/cara/tests/test_monte_carlo.py @@ -56,6 +56,7 @@ def baseline_mc_model() -> cara.monte_carlo.ConcentrationModel: expiration=cara.models.Expiration.types['Breathing'], host_immunity=0., ), + evaporation_factor=0.3, ) return mc_model @@ -69,6 +70,7 @@ def baseline_mc_exposure_model(baseline_mc_model) -> cara.monte_carlo.ExposureMo presence=baseline_mc_model.infected.presence, activity=baseline_mc_model.infected.activity, mask=baseline_mc_model.infected.mask, + host_immunity=0., ) ) diff --git a/cara/tests/test_monte_carlo_full_models.py b/cara/tests/test_monte_carlo_full_models.py index 58ed94fe..6b32ad94 100644 --- a/cara/tests/test_monte_carlo_full_models.py +++ b/cara/tests/test_monte_carlo_full_models.py @@ -47,6 +47,7 @@ def shared_office_mc(): expiration=build_expiration({'Speaking': 0.3, 'Breathing': 0.7}), host_immunity=0., ), + evaporation_factor=0.3, ) return mc.ExposureModel( concentration_model=concentration_mc, @@ -90,6 +91,7 @@ def classroom_mc(): expiration=expiration_distributions['Speaking'], host_immunity=0., ), + evaporation_factor=0.3, ) return mc.ExposureModel( concentration_model=concentration_mc, @@ -123,6 +125,7 @@ def ski_cabin_mc(): expiration=expiration_distributions['Speaking'], host_immunity=0., ), + evaporation_factor=0.3, ) return mc.ExposureModel( concentration_model=concentration_mc, @@ -158,6 +161,7 @@ def gym_mc(): expiration=expiration_distributions['Breathing'], host_immunity=0., ), + evaporation_factor=0.3, ) return mc.ExposureModel( concentration_model=concentration_mc, @@ -192,6 +196,7 @@ def waiting_room_mc(): expiration=build_expiration({'Speaking': 0.3, 'Breathing': 0.7}), host_immunity=0., ), + evaporation_factor=0.3, ) return mc.ExposureModel( concentration_model=concentration_mc, @@ -227,6 +232,7 @@ def skagit_chorale_mc(): expiration=expiration_distribution((5., 5., 5.)), host_immunity=0., ), + evaporation_factor=0.3, ) return mc.ExposureModel( concentration_model=concentration_mc, @@ -302,6 +308,7 @@ def test_small_shared_office_Geneva(mask_type, month, expected_pi, expiration=build_expiration({'Speaking': 0.33, 'Breathing': 0.67}), host_immunity=0., ), + evaporation_factor=0.3, ) exposure_mc = mc.ExposureModel( concentration_model=concentration_mc, From 1feec5a050762ead47f01b7460b6f3b93392dba1 Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Tue, 5 Oct 2021 15:45:23 +0200 Subject: [PATCH 02/10] Updated test_r0 test with new value from trapezoidal integration --- cara/tests/test_known_quantities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cara/tests/test_known_quantities.py b/cara/tests/test_known_quantities.py index e9ce8168..b157490f 100644 --- a/cara/tests/test_known_quantities.py +++ b/cara/tests/test_known_quantities.py @@ -95,7 +95,7 @@ def test_r0(baseline_exposure_model): # expected r0 was computed with a trapezoidal integration, using # a mesh of 100'000 pts per exposed presence interval. r0 = baseline_exposure_model.reproduction_number() - npt.assert_allclose(r0, 972.880852) + npt.assert_allclose(r0, 776.9419902161412) def test_periodic_window(baseline_periodic_window, baseline_room): From 2c3b267af0f97f5ca516566e1c7572db2c818292 Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Tue, 5 Oct 2021 15:57:18 +0200 Subject: [PATCH 03/10] Updated probability of infection values on tests --- cara/tests/models/test_exposure_model.py | 24 +++++++++++----------- cara/tests/test_monte_carlo_full_models.py | 20 +++++++++--------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/cara/tests/models/test_exposure_model.py b/cara/tests/models/test_exposure_model.py index 0a39d90c..c65b0990 100644 --- a/cara/tests/models/test_exposure_model.py +++ b/cara/tests/models/test_exposure_model.py @@ -74,23 +74,23 @@ def known_concentrations(func): @pytest.mark.parametrize( - "population, cm, f_dep, expected_exposure, expected_probability", [ - [populations[1], known_concentrations(lambda t: 36.), 1., - np.array([432, 432]), np.array([99.6803184113, 99.5181053773])], + "population, cm, expected_exposure, expected_probability", [ + [populations[1], known_concentrations(lambda t: 36.), + np.array([432, 432]), np.array([77.2191556943, 74.6803506895])], - [populations[2], known_concentrations(lambda t: 36.), 1., - np.array([432, 432]), np.array([97.4574432074, 98.3493482895])], + [populations[2], known_concentrations(lambda t: 36.), + np.array([432, 432]), np.array([61.1470214407, 65.2366759251])], - [populations[0], known_concentrations(lambda t: np.array([36., 72.])), 1., - np.array([432, 864]), np.array([98.3493482895, 99.9727534893])], + [populations[0], known_concentrations(lambda t: np.array([36., 72.])), + np.array([432, 864]), np.array([65.2366759251, 87.9151129926])], - [populations[1], known_concentrations(lambda t: np.array([36., 72.])), 1., - np.array([432, 864]), np.array([99.6803184113, 99.9976777757])], + [populations[1], known_concentrations(lambda t: np.array([36., 72.])), + np.array([432, 864]), np.array([77.2191556943, 93.589153588])], - [populations[0], known_concentrations(lambda t: 72.), np.array([0.5, 1.]), - 864, np.array([98.3493482895, 99.9727534893])], + [populations[2], known_concentrations(lambda t: np.array([36., 72.])), + np.array([432, 864]), np.array([61.1470214407, 87.9151129926])], ]) -def test_exposure_model_ndarray(population, cm, f_dep, +def test_exposure_model_ndarray(population, cm, expected_exposure, expected_probability): model = ExposureModel(cm, population) np.testing.assert_almost_equal( diff --git a/cara/tests/test_monte_carlo_full_models.py b/cara/tests/test_monte_carlo_full_models.py index 6b32ad94..de3e6f0d 100644 --- a/cara/tests/test_monte_carlo_full_models.py +++ b/cara/tests/test_monte_carlo_full_models.py @@ -249,12 +249,12 @@ def skagit_chorale_mc(): @pytest.mark.parametrize( "mc_model, expected_pi, expected_new_cases, expected_dose, expected_ER", [ - ["shared_office_mc", 10.7, 0.32, 57.24, 654], - ["classroom_mc", 36.1, 6.85, 780.0, 28464], - ["ski_cabin_mc", 16.3, 0.49, 35.94, 7404], - ["gym_mc", 2.25, 0.63, 0.7842, 1968], - ["waiting_room_mc", 9.72, 1.36, 34.26, 3534], - ["skagit_chorale_mc",29.9, 17.9, 190.0, 141400], + ["shared_office_mc", 2.3, 0.32, 57.24, 654], + ["classroom_mc", 16.1, 6.85, 780.0, 28464], + ["ski_cabin_mc", 4.4, 0.49, 35.94, 7404], + ["gym_mc", 0.57, 0.63, 0.7842, 1968], + ["waiting_room_mc", 2.02, 1.36, 34.26, 3534], + ["skagit_chorale_mc",11.42, 17.9, 190.0, 141400], ] ) def test_report_models(mc_model, expected_pi, expected_new_cases, @@ -275,10 +275,10 @@ def test_report_models(mc_model, expected_pi, expected_new_cases, @pytest.mark.parametrize( "mask_type, month, expected_pi, expected_dose, expected_ER", [ - ["No mask", "Jul", 30.0, 405.84, 3894], - ["Type I", "Jul", 10.2, 73.38, 702], - ["FFP2", "Jul", 4.0, 73.38, 702], - ["Type I", "Feb", 4.25, 21.42, 702], + ["No mask", "Jul", 11.68, 405.84, 3894], + ["Type I", "Jul", 2.12, 73.38, 702], + ["FFP2", "Jul", 0.66, 73.38, 702], + ["Type I", "Feb", 0.73, 21.42, 702], ], ) def test_small_shared_office_Geneva(mask_type, month, expected_pi, From bf351f62069e11a60c89d04ac2f06c51e76ceb36 Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Tue, 5 Oct 2021 15:59:50 +0200 Subject: [PATCH 04/10] updated expected dose values on tests --- cara/tests/test_monte_carlo_full_models.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cara/tests/test_monte_carlo_full_models.py b/cara/tests/test_monte_carlo_full_models.py index de3e6f0d..411a2778 100644 --- a/cara/tests/test_monte_carlo_full_models.py +++ b/cara/tests/test_monte_carlo_full_models.py @@ -249,12 +249,12 @@ def skagit_chorale_mc(): @pytest.mark.parametrize( "mc_model, expected_pi, expected_new_cases, expected_dose, expected_ER", [ - ["shared_office_mc", 2.3, 0.32, 57.24, 654], - ["classroom_mc", 16.1, 6.85, 780.0, 28464], - ["ski_cabin_mc", 4.4, 0.49, 35.94, 7404], - ["gym_mc", 0.57, 0.63, 0.7842, 1968], - ["waiting_room_mc", 2.02, 1.36, 34.26, 3534], - ["skagit_chorale_mc",11.42, 17.9, 190.0, 141400], + ["shared_office_mc", 2.3, 0.069, 57.24, 654], + ["classroom_mc", 16.1, 3.06, 780.0, 28464], + ["ski_cabin_mc", 4.4, 0.13, 35.94, 7404], + ["gym_mc", 0.57, 0.16, 0.7842, 1968], + ["waiting_room_mc", 2.02, 0.28, 34.26, 3534], + ["skagit_chorale_mc",11.42, 6.85, 190.0, 141400], ] ) def test_report_models(mc_model, expected_pi, expected_new_cases, @@ -275,10 +275,10 @@ def test_report_models(mc_model, expected_pi, expected_new_cases, @pytest.mark.parametrize( "mask_type, month, expected_pi, expected_dose, expected_ER", [ - ["No mask", "Jul", 11.68, 405.84, 3894], - ["Type I", "Jul", 2.12, 73.38, 702], - ["FFP2", "Jul", 0.66, 73.38, 702], - ["Type I", "Feb", 0.73, 21.42, 702], + ["No mask", "Jul", 11.68, 4.93, 3894], + ["Type I", "Jul", 2.12, 15.41, 702], + ["FFP2", "Jul", 0.66, 15.62, 702], + ["Type I", "Feb", 0.73, 4.58, 702], ], ) def test_small_shared_office_Geneva(mask_type, month, expected_pi, From ed48d2e33193906d8b732ade57c360da1dbbe1f1 Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Tue, 5 Oct 2021 16:03:36 +0200 Subject: [PATCH 05/10] updated expected dose on tests --- cara/tests/test_monte_carlo_full_models.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cara/tests/test_monte_carlo_full_models.py b/cara/tests/test_monte_carlo_full_models.py index 411a2778..52dcf46b 100644 --- a/cara/tests/test_monte_carlo_full_models.py +++ b/cara/tests/test_monte_carlo_full_models.py @@ -249,12 +249,12 @@ def skagit_chorale_mc(): @pytest.mark.parametrize( "mc_model, expected_pi, expected_new_cases, expected_dose, expected_ER", [ - ["shared_office_mc", 2.3, 0.069, 57.24, 654], - ["classroom_mc", 16.1, 3.06, 780.0, 28464], - ["ski_cabin_mc", 4.4, 0.13, 35.94, 7404], - ["gym_mc", 0.57, 0.16, 0.7842, 1968], - ["waiting_room_mc", 2.02, 0.28, 34.26, 3534], - ["skagit_chorale_mc",11.42, 6.85, 190.0, 141400], + ["shared_office_mc", 2.3, 0.069, 12.18, 138], + ["classroom_mc", 16.1, 3.06, 151.28, 5907], + ["ski_cabin_mc", 4.4, 0.13, 7.23, 1507], + ["gym_mc", 0.57, 0.16, 0.4852, 1145], + ["waiting_room_mc", 2.02, 0.28, 7.23, 779], + ["skagit_chorale_mc",11.42, 6.85, 36.55, 28572], ] ) def test_report_models(mc_model, expected_pi, expected_new_cases, @@ -275,10 +275,10 @@ def test_report_models(mc_model, expected_pi, expected_new_cases, @pytest.mark.parametrize( "mask_type, month, expected_pi, expected_dose, expected_ER", [ - ["No mask", "Jul", 11.68, 4.93, 3894], - ["Type I", "Jul", 2.12, 15.41, 702], - ["FFP2", "Jul", 0.66, 15.62, 702], - ["Type I", "Feb", 0.73, 4.58, 702], + ["No mask", "Jul", 11.68, 84.93, 838], + ["Type I", "Jul", 2.12, 15.41, 147], + ["FFP2", "Jul", 0.66, 15.62, 160], + ["Type I", "Feb", 0.73, 4.58, 151], ], ) def test_small_shared_office_Geneva(mask_type, month, expected_pi, From 7aa2e3f187b27bd31811d3a6a735869f1cd691c3 Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Tue, 5 Oct 2021 16:20:07 +0200 Subject: [PATCH 06/10] Re-enable pipeline --- .gitlab-ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0e81d047..8e3ddd0b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -11,13 +11,13 @@ variables: # A full installation of CARA, tested with pytest. -# test_install: -# extends: .acc_py_full_test +test_install: + extends: .acc_py_full_test # A development installation of CARA tested with pytest. -# test_dev: -# extends: .acc_py_dev_test +test_dev: + extends: .acc_py_dev_test # A development installation of CARA tested with pytest. @@ -69,10 +69,10 @@ check_openshift_config_prod: # A development installation of CARA tested with pytest. -# test_dev-39: -# variables: -# PY_VERSION: "3.9" -# extends: .acc_py_dev_test +test_dev-39: + variables: + PY_VERSION: "3.9" + extends: .acc_py_dev_test .image_builder: From 34ad2af425fb995d86a4dec7bcc1377c463d3f25 Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Thu, 4 Nov 2021 16:41:26 +0100 Subject: [PATCH 07/10] Evaporation factor default value is back --- cara/models.py | 2 +- cara/tests/models/test_exposure_model.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cara/models.py b/cara/models.py index b64eea7d..b7c1ff95 100644 --- a/cara/models.py +++ b/cara/models.py @@ -777,7 +777,7 @@ class ConcentrationModel: #: evaporation factor: the particles' diameter is multiplied by this # factor as soon as they are in the air (but AFTER going out of the, # mask, if any). - evaporation_factor: float #= 0.3 + evaporation_factor: float = 0.3 @property def virus(self): diff --git a/cara/tests/models/test_exposure_model.py b/cara/tests/models/test_exposure_model.py index c65b0990..bdde0129 100644 --- a/cara/tests/models/test_exposure_model.py +++ b/cara/tests/models/test_exposure_model.py @@ -17,7 +17,7 @@ class KnownNormedconcentration(models.ConcentrationModel): which therefore doesn't need other components. Useful for testing. """ - normed_concentration_function: typing.Callable + normed_concentration_function: typing.Callable = lambda x: 0 def infectious_virus_removal_rate(self, time: float) -> models._VectorisedFloat: # very large decay constant -> same as constant concentration From 9f2017221459db6df6b1568f1640d0460b8829b3 Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Mon, 8 Nov 2021 14:58:55 +0100 Subject: [PATCH 08/10] Adapted tests according to CARA paper --- cara/apps/expert.py | 2 +- cara/data/__init__.py | 39 +++- cara/models.py | 2 +- cara/tests/models/test_exposure_model.py | 12 +- cara/tests/test_monte_carlo_full_models.py | 243 ++++++++++++--------- 5 files changed, 183 insertions(+), 115 deletions(-) diff --git a/cara/apps/expert.py b/cara/apps/expert.py index a5f11f86..261afe75 100644 --- a/cara/apps/expert.py +++ b/cara/apps/expert.py @@ -498,7 +498,7 @@ baseline_model = models.ExposureModel( presence=models.SpecificInterval(((8., 12.), (13., 17.))), mask=models.Mask.types['No mask'], activity=models.Activity.types['Seated'], - expiration=models.Expiration.types['Talking'], + expiration=models.Expiration.types['Speaking'], host_immunity=0., ), evaporation_factor=0.3, diff --git a/cara/data/__init__.py b/cara/data/__init__.py index 353992e6..eea6f5c8 100644 --- a/cara/data/__init__.py +++ b/cara/data/__init__.py @@ -3,7 +3,7 @@ from cara import models # TODO: The values in this module to be removed and instead use the cara.data.weather functionality. -# average temperature of each month, hour per hour (from midnight to 11 pm) +# Geneva average temperature of each month, hour per hour (from midnight to 11 pm) Geneva_hourly_temperatures_celsius_per_hour = { 'Jan': [0.2, -0.3, -0.5, -0.9, -1.1, -1.4, -1.5, -1.5, -1.1, 0.1, 1.5, 2.8, 3.8, 4.4, 4.5, 4.4, 4.4, 3.9, 3.1, 2.7, 2.2, 1.7, 1.5, 1.1], @@ -31,6 +31,22 @@ Geneva_hourly_temperatures_celsius_per_hour = { 4.7, 5.2, 5.3, 5.2, 5.2, 4.7, 4.0, 3.7, 3.2, 2.8, 2.6, 2.2] } +# Toronto average temperature of each month, hour per hour (from midnight to 11 pm) +Toronto_hourly_temperatures_celsius_per_hour = { + "Jan": [ -2.9, -3.0, -3.2, -3.3, -3.3, -3.5, -3.7, -3.8, -3.9, -4.0, -4.1, -4.3, -4.3, -4.3, -4.1, -3.7, -3.2, -2.8, -2.6, -2.3, -2.2, -2.3, -2.6, -2.8], + "Feb": [ -2.4, -2.6, -2.8, -2.9, -2.9, -3.1, -3.3, -3.4, -3.6, -3.8, -3.9, -4.0, -4.3, -4.2, -3.7, -3.2, -2.6, -2.1, -1.7, -1.5, -1.3, -1.4, -1.6, -2.1], + "Mar": [ 1.3, 1.0, 0.7, 0.5, 0.4, 0.1, -0.0, -0.2, -0.4, -0.5, -0.7, -0.8, -0.9, -0.3, 0.4, 1.0, 1.6, 2.0, 2.3, 2.7, 2.7, 2.7, 2.4, 1.9], + "Apr": [ 6.8, 6.5, 6.3, 5.9, 5.7, 5.4, 5.1, 4.9, 4.6, 4.4, 4.2, 4.3, 4.8, 5.5, 6.1, 6.7, 7.1, 7.6, 7.8, 8.1, 8.2, 8.2, 8.0, 7.6 ], + "May": [ 13.0, 12.6, 12.2, 11.8, 11.5, 11.2, 10.8, 10.5, 10.2, 9.9, 9.8, 10.0, 10.9, 11.6, 12.2, 12.7, 13.2, 13.6, 13.9, 14.3, 14.4, 14.3, 14.2, 13.8], + "Jun": [ 18.9, 18.2, 17.8, 17.4, 17.0, 16.6, 16.2, 15.9, 15.6, 15.4, 15.3, 15.8, 16.5, 17.3, 17.9, 18.4, 18.9, 19.4, 19.7, 20.1, 20.3, 20.3, 20.1, 19.7], + "Jul": [ 22.1, 21.4, 20.9, 20.5, 20.0, 19.6, 19.1, 18.9, 18.6, 18.3, 18.1, 18.5, 19.4, 20.3, 21.0, 21.6, 22.2, 22.7, 23.1, 23.4, 23.6, 23.5, 23.3, 22.9], + "Aug": [ 22.0, 21.4, 21.0, 20.7, 20.3, 20.0, 19.6, 19.3, 19.1, 18.8, 18.5, 18.4, 19.4, 20.3, 21.1, 21.7, 22.2, 22.8, 23.1, 23.4, 23.5, 23.3, 23.1, 22.6], + "Sep": [ 18.2, 17.8, 17.4, 17.3, 17.0, 16.6, 16.3, 16.0, 15.8, 15.5, 15.4, 15.0, 15.6, 16.6, 17.5, 18.2, 18.7, 19.2, 19.6, 19.8, 19.7, 19.6, 19.2, 18.6], + "Oct": [ 11.1, 10.9, 10.6, 10.5, 10.2, 10.1, 9.8, 9.7, 9.5, 9.3, 9.2, 9.0, 9.0, 9.7, 10.5, 11.2, 11.7, 12.2, 12.4, 12.6, 12.6, 12.3, 11.8, 11.3], + "Nov": [ 5.3, 5.1, 5.0, 4.7, 4.6, 4.4, 4.3, 4.2, 4.1, 4.0, 3.9, 3.8, 3.7, 4.0, 4.6, 5.2, 5.7, 6.1, 6.2, 6.4, 6.3, 6.0, 5.5, 5.3], + "Dec": [ 0.4, 0.3, 0.2, 0.0, -0.1, -0.2, -0.4, -0.5, -0.6, -0.7, -0.8, -0.8, -0.9, -0.9, -0.6, -0.2, 0.3, 0.7, 0.9, 1.1, 1.1, 0.9, 0.6, 0.5] + } + # Geneva hourly temperatures as piecewise constant function (in Kelvin). GenevaTemperatures_hourly = { @@ -44,8 +60,27 @@ GenevaTemperatures_hourly = { } -# Same temperatures on a finer temperature mesh (every 6 minutes). +# Toronto hourly temperatures as piecewise constant function (in Kelvin). +TorontoTemperatures_hourly = { + month: models.PiecewiseConstant( + # NOTE: It is important that the time type is float, not np.float, in + # order to allow hashability (for caching). + tuple(float(time) for time in range(25)), + tuple(273.15 + np.array(temperatures)), + ) + for month, temperatures in Toronto_hourly_temperatures_celsius_per_hour.items() +} + + +# Same Geneva temperatures on a finer temperature mesh (every 6 minutes). GenevaTemperatures = { month: GenevaTemperatures_hourly[month].refine(refine_factor=10) for month, temperatures in Geneva_hourly_temperatures_celsius_per_hour.items() } + + +# Same Toronto temperatures on a finer temperature mesh (every 6 minutes). +TorontoTemperatures = { + month: TorontoTemperatures_hourly[month].refine(refine_factor=10) + for month, temperatures in Toronto_hourly_temperatures_celsius_per_hour.items() +} \ No newline at end of file diff --git a/cara/models.py b/cara/models.py index b7c1ff95..6d484be4 100644 --- a/cara/models.py +++ b/cara/models.py @@ -628,7 +628,7 @@ class MultipleExpiration(_ExpirationBase): # The correspondence with the BLO coefficients is given. _ExpirationBase.types = { 'Breathing': Expiration(1.3844), # corresponds to B/L/O coefficients of (1, 0, 0) - 'Talking': Expiration(5.8925), # corresponds to B/L/O coefficients of (1, 1, 1) + 'Speaking': Expiration(5.8925), # corresponds to B/L/O coefficients of (1, 1, 1) 'Shouting': Expiration(10.0411), # corresponds to B/L/O coefficients of (1, 5, 5) 'Singing': Expiration(10.0411), # corresponds to B/L/O coefficients of (1, 5, 5) } diff --git a/cara/tests/models/test_exposure_model.py b/cara/tests/models/test_exposure_model.py index bdde0129..5976e659 100644 --- a/cara/tests/models/test_exposure_model.py +++ b/cara/tests/models/test_exposure_model.py @@ -64,7 +64,7 @@ def known_concentrations(func): presence=halftime, mask=models.Mask.types['Type I'], activity=models.Activity.types['Standing'], - virus=models.Virus.types['SARS_CoV_2_B117'], + virus=models.Virus.types['SARS_CoV_2_ALPHA'], expiration=models.Expiration.types['Speaking'], host_immunity=0., ) @@ -76,19 +76,19 @@ def known_concentrations(func): @pytest.mark.parametrize( "population, cm, expected_exposure, expected_probability", [ [populations[1], known_concentrations(lambda t: 36.), - np.array([432, 432]), np.array([77.2191556943, 74.6803506895])], + np.array([432, 432]), np.array([67.9503762594, 65.2366759251])], [populations[2], known_concentrations(lambda t: 36.), - np.array([432, 432]), np.array([61.1470214407, 65.2366759251])], + np.array([432, 432]), np.array([51.6749232285, 55.6374622042])], [populations[0], known_concentrations(lambda t: np.array([36., 72.])), - np.array([432, 864]), np.array([65.2366759251, 87.9151129926])], + np.array([432, 864]), np.array([55.6374622042, 80.3196524031])], [populations[1], known_concentrations(lambda t: np.array([36., 72.])), - np.array([432, 864]), np.array([77.2191556943, 93.589153588])], + np.array([432, 864]), np.array([67.9503762594, 87.9151129926])], [populations[2], known_concentrations(lambda t: np.array([36., 72.])), - np.array([432, 864]), np.array([61.1470214407, 87.9151129926])], + np.array([432, 864]), np.array([51.6749232285, 80.3196524031])], ]) def test_exposure_model_ndarray(population, cm, expected_exposure, expected_probability): diff --git a/cara/tests/test_monte_carlo_full_models.py b/cara/tests/test_monte_carlo_full_models.py index 52dcf46b..7e83df25 100644 --- a/cara/tests/test_monte_carlo_full_models.py +++ b/cara/tests/test_monte_carlo_full_models.py @@ -4,8 +4,7 @@ import pytest import cara.monte_carlo as mc from cara import models,data -from cara.monte_carlo.data import activity_distributions, virus_distributions -from cara.monte_carlo.data import expiration_distribution, expiration_distributions +from cara.monte_carlo.data import activity_distributions, virus_distributions, expiration_distributions, infectious_dose_distribution, viable_to_RNA_ratio_distribution from cara.apps.calculator.model_generator import build_expiration # TODO: seed better the random number generators @@ -19,32 +18,29 @@ TOLERANCE = 0.05 @pytest.fixture def shared_office_mc(): """ - Corresponds to the 1st line of Table 5 in CERN-OPEN-2021-04, but - speaking 30% of the time (instead of 1/3) + Corresponds to the 1st line of Table 4 in CERN-OPEN-2021-04 """ concentration_mc = mc.ConcentrationModel( - room=models.Room(volume=50, humidity=0.3), - ventilation=models.MultipleVentilation( - ( + room=models.Room(volume=50, humidity=0.5), + ventilation = models.MultipleVentilation( + ventilations=( models.SlidingWindow( - active=models.PeriodicInterval(period=120, duration=10), - inside_temp=models.PiecewiseConstant((0., 24.), (293,)), - outside_temp=models.PiecewiseConstant((0., 24.), (283,)), - window_height=1.6, opening_length=0.6, + active=models.PeriodicInterval(period=120, duration=120), + inside_temp=models.PiecewiseConstant((0., 24.), (298,)), + outside_temp=data.GenevaTemperatures['Jun'], + window_height=1.6, + opening_length=0.2, ), - models.AirChange( - active=models.SpecificInterval(((0., 24.), )), - air_exch=0.25, - ), - ), + models.AirChange(active=models.PeriodicInterval(period=120, duration=120), air_exch=0.25), + ) ), infected=mc.InfectedPopulation( number=1, - virus=virus_distributions['SARS_CoV_2_ALPHA'], - presence=mc.SpecificInterval(((0., 2.), (2.1, 4.), (5., 7.), (7.1, 9.))), - mask=models.Mask(η_inhale=0.3), + presence=mc.SpecificInterval(present_times = ((0, 3.5), (4.5, 9))), + virus=virus_distributions['SARS_CoV_2_DELTA'], + mask=models.Mask.types['No mask'], activity=activity_distributions['Seated'], - expiration=build_expiration({'Speaking': 0.3, 'Breathing': 0.7}), + expiration=build_expiration({'Speaking': 0.33, 'Breathing': 0.67}), host_immunity=0., ), evaporation_factor=0.3, @@ -53,42 +49,40 @@ def shared_office_mc(): concentration_model=concentration_mc, exposed=mc.Population( number=3, - presence=concentration_mc.infected.presence, - activity=models.Activity.types['Seated'], - mask=concentration_mc.infected.mask, + presence=mc.SpecificInterval(present_times = ((0, 3.5), (4.5, 9))), + activity=activity_distributions['Seated'], + mask=models.Mask.types['No mask'], host_immunity=0., - ), + ) ) @pytest.fixture def classroom_mc(): """ - Corresponds to the 2nd line of Table 5 in CERN-OPEN-2021-04 + Corresponds to the 2nd line of Table 4 in CERN-OPEN-2021-04 """ concentration_mc = mc.ConcentrationModel( room=models.Room(volume=160, humidity=0.3), - ventilation=models.MultipleVentilation( - ( + ventilation = models.MultipleVentilation( + ventilations=( models.SlidingWindow( - active=models.PeriodicInterval(period=120, duration=10), + active=models.PeriodicInterval(period=120, duration=120), inside_temp=models.PiecewiseConstant((0., 24.), (293,)), - outside_temp=models.PiecewiseConstant((0., 24.), (283,)), - window_height=1.6, opening_length=0.6, + outside_temp=data.TorontoTemperatures['Dec'], + window_height=1.6, + opening_length=0.2, ), - models.AirChange( - active=models.SpecificInterval(((0., 24.),)), - air_exch=0.25, - ), - ), + models.AirChange(active=models.PeriodicInterval(period=120, duration=120), air_exch=0.25), + ) ), infected=mc.InfectedPopulation( number=1, + presence=models.SpecificInterval(((0, 2), (2.5, 4), (5, 7), (7.5, 9))), virus=virus_distributions['SARS_CoV_2_ALPHA'], - presence=mc.SpecificInterval(((0., 2.), (2.5, 4.), (5., 7.), (7.5, 9.))), - mask=models.Mask.types['No mask'], + mask=models.Mask.types["No mask"], activity=activity_distributions['Light activity'], - expiration=expiration_distributions['Speaking'], + expiration=build_expiration('Speaking'), host_immunity=0., ), evaporation_factor=0.3, @@ -97,9 +91,9 @@ def classroom_mc(): concentration_model=concentration_mc, exposed=mc.Population( number=19, - presence=concentration_mc.infected.presence, - activity=models.Activity.types['Seated'], - mask=concentration_mc.infected.mask, + presence=models.SpecificInterval(((0, 2), (2.5, 4), (5, 7), (7.5, 9))), + activity=activity_distributions['Seated'], + mask=models.Mask.types["No mask"], host_immunity=0., ), ) @@ -108,21 +102,20 @@ def classroom_mc(): @pytest.fixture def ski_cabin_mc(): """ - Corresponds to the 3rd line of Table 5 in CERN-OPEN-2021-04 + Corresponds to the 3rd line of Table 4 in CERN-OPEN-2021-04 """ concentration_mc = mc.ConcentrationModel( - room=models.Room(volume=10, humidity=0.5), - ventilation=models.AirChange( - active=models.SpecificInterval(((0., 24.),)), - air_exch=0, - ), + room=models.Room(volume=10, humidity=0.3), + ventilation=models.MultipleVentilation( + (models.AirChange(active=models.PeriodicInterval(period=120, duration=120), air_exch=0.0), + models.AirChange(active=models.PeriodicInterval(period=120, duration=120), air_exch=0.25))), infected=mc.InfectedPopulation( number=1, - virus=virus_distributions['SARS_CoV_2_ALPHA'], - presence=mc.SpecificInterval(((0., 1/3),)), - mask=models.Mask(η_inhale=0.3), + presence=models.SpecificInterval(((0, 20/60),)), + virus=virus_distributions['SARS_CoV_2_DELTA'], + mask=models.Mask.types['No mask'], activity=activity_distributions['Moderate activity'], - expiration=expiration_distributions['Speaking'], + expiration=build_expiration('Speaking'), host_immunity=0., ), evaporation_factor=0.3, @@ -131,20 +124,96 @@ def ski_cabin_mc(): concentration_model=concentration_mc, exposed=mc.Population( number=3, - presence=concentration_mc.infected.presence, - activity=models.Activity.types['Moderate activity'], - mask=concentration_mc.infected.mask, + presence=models.SpecificInterval(((0, 20/60),)), + activity=activity_distributions['Moderate activity'], + mask=models.Mask.types['No mask'], host_immunity=0., ), ) +@pytest.fixture +def skagit_chorale_mc(): + """ + Corresponds to the 4th line of Table 4 in CERN-OPEN-2021-04, + assuming viral is 10**9 instead of a LogCustomKernel distribution. + """ + concentration_mc = mc.ConcentrationModel( + room=models.Room(volume=810, humidity=0.5), + ventilation=models.AirChange( + active=models.PeriodicInterval(period=120, duration=120), + air_exch=0.7), + infected=mc.InfectedPopulation( + number=1, + presence=models.SpecificInterval(((0, 2.5), )), + virus=mc.SARSCoV2( + viral_load_in_sputum=10**9, + infectious_dose=infectious_dose_distribution, + viable_to_RNA_ratio=viable_to_RNA_ratio_distribution, + transmissibility_factor=1., + ), + mask=models.Mask.types['No mask'], + activity=activity_distributions['Moderate activity'], + expiration=build_expiration('Shouting'), + host_immunity=0., + ), + evaporation_factor=0.3, + ) + return mc.ExposureModel( + concentration_model=concentration_mc, + exposed=mc.Population( + number=60, + presence=models.SpecificInterval(((0, 2.5), )), + activity=activity_distributions['Moderate activity'], + mask=models.Mask.types['No mask'], + host_immunity=0., + ), + ) + + +@pytest.fixture +def bus_ride_mc(): + """ + Corresponds to the 5th line of Table 4 in CERN-OPEN-2021-04, + assuming viral is 5*10**8 instead of a LogCustomKernel distribution. + """ + concentration_mc = mc.ConcentrationModel( + room=models.Room(volume=45, humidity=0.5), + ventilation=models.AirChange( + active=models.PeriodicInterval(period=120, duration=120), + air_exch=1.25), + infected=mc.InfectedPopulation( + number=1, + presence=models.SpecificInterval(((0, 1.67), )), + virus=mc.SARSCoV2( + viral_load_in_sputum=5*10**8, + infectious_dose=infectious_dose_distribution, + viable_to_RNA_ratio=viable_to_RNA_ratio_distribution, + transmissibility_factor=1., + ), + mask=models.Mask.types['No mask'], + activity=activity_distributions['Seated'], + expiration=build_expiration('Speaking'), + host_immunity=0., + ), + evaporation_factor=0.3, + ) + return mc.ExposureModel( + concentration_model=concentration_mc, + exposed=mc.Population( + number=67, + presence=models.SpecificInterval(((0, 1.67), )), + activity=activity_distributions['Seated'], + mask=models.Mask.types['No mask'], + host_immunity=0., + ), + ) + + @pytest.fixture def gym_mc(): """ - Corresponds to the 4th line of Table 5 in CERN-OPEN-2021-04, - but there the expected number of cases is wrongly reported as 0.56 - while it should be 0.63. + Gym model for testing """ concentration_mc = mc.ConcentrationModel( room=models.Room(volume=300, humidity=0.5), @@ -178,8 +247,7 @@ def gym_mc(): @pytest.fixture def waiting_room_mc(): """ - Corresponds to the 5th line of Table 5 in CERN-OPEN-2021-04, but - speaking 30% of the time (instead of 20%) + Waiting room model for testing """ concentration_mc = mc.ConcentrationModel( room=models.Room(volume=100, humidity=0.5), @@ -210,51 +278,16 @@ def waiting_room_mc(): ) -@pytest.fixture -def skagit_chorale_mc(): - """ - Corresponds to the 6th line of Table 5 in CERN-OPEN-2021-04, but - infection probability should be 29.8% instead of 32%, and number of - new cases 17.9 instead of 21. - """ - concentration_mc = mc.ConcentrationModel( - room=models.Room(volume=810, humidity=0.5), - ventilation=models.AirChange( - active=models.SpecificInterval(((0,24),)), - air_exch=0.7, - ), - infected=mc.InfectedPopulation( - number=1, - virus=virus_distributions['SARS_CoV_2'], - presence=mc.SpecificInterval(((0., 2.5),)), - mask=models.Mask.types["No mask"], - activity=activity_distributions['Light activity'], - expiration=expiration_distribution((5., 5., 5.)), - host_immunity=0., - ), - evaporation_factor=0.3, - ) - return mc.ExposureModel( - concentration_model=concentration_mc, - exposed=mc.Population( - number=60, - presence=concentration_mc.infected.presence, - activity=models.Activity.types['Moderate activity'], - mask=concentration_mc.infected.mask, - host_immunity=0., - ), - ) - - @pytest.mark.parametrize( "mc_model, expected_pi, expected_new_cases, expected_dose, expected_ER", [ - ["shared_office_mc", 2.3, 0.069, 12.18, 138], - ["classroom_mc", 16.1, 3.06, 151.28, 5907], - ["ski_cabin_mc", 4.4, 0.13, 7.23, 1507], - ["gym_mc", 0.57, 0.16, 0.4852, 1145], - ["waiting_room_mc", 2.02, 0.28, 7.23, 779], - ["skagit_chorale_mc",11.42, 6.85, 36.55, 28572], + ["shared_office_mc", 6.03, 0.18, 24.55, 809], + ["classroom_mc", 10.0, 2.0, 79.98, 5624], + ["ski_cabin_mc", 17.0, 0.5, 40.25, 7966], + ["skagit_chorale_mc",70, 42.5, 241.28, 190422], + ["bus_ride_mc", 12.0, 8.0, 63.79, 5419], + ["gym_mc", 0.45, 0.13, 0.4852, 1145], + ["waiting_room_mc", 1.59, 0.22, 7.23, 737], ] ) def test_report_models(mc_model, expected_pi, expected_new_cases, @@ -275,10 +308,10 @@ def test_report_models(mc_model, expected_pi, expected_new_cases, @pytest.mark.parametrize( "mask_type, month, expected_pi, expected_dose, expected_ER", [ - ["No mask", "Jul", 11.68, 84.93, 838], - ["Type I", "Jul", 2.12, 15.41, 147], - ["FFP2", "Jul", 0.66, 15.62, 160], - ["Type I", "Feb", 0.73, 4.58, 151], + ["No mask", "Jul", 10.02, 84.54, 809], + ["Type I", "Jul", 1.7, 15.64, 149], + ["FFP2", "Jul", 0.51, 15.64, 149], + ["Type I", "Feb", 0.57, 4.59, 149], ], ) def test_small_shared_office_Geneva(mask_type, month, expected_pi, From bf58d529a6a13ebaf59a8334b40df70dc2e7813f Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Wed, 10 Nov 2021 16:49:32 +0100 Subject: [PATCH 09/10] Paper reference changed on tests --- cara/tests/test_monte_carlo_full_models.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cara/tests/test_monte_carlo_full_models.py b/cara/tests/test_monte_carlo_full_models.py index 7e83df25..7a644e37 100644 --- a/cara/tests/test_monte_carlo_full_models.py +++ b/cara/tests/test_monte_carlo_full_models.py @@ -18,7 +18,7 @@ TOLERANCE = 0.05 @pytest.fixture def shared_office_mc(): """ - Corresponds to the 1st line of Table 4 in CERN-OPEN-2021-04 + Corresponds to the 1st line of Table 4 in https://doi.org/10.1101/2021.10.14.21264988 """ concentration_mc = mc.ConcentrationModel( room=models.Room(volume=50, humidity=0.5), @@ -60,7 +60,7 @@ def shared_office_mc(): @pytest.fixture def classroom_mc(): """ - Corresponds to the 2nd line of Table 4 in CERN-OPEN-2021-04 + Corresponds to the 2nd line of Table 4 in https://doi.org/10.1101/2021.10.14.21264988 """ concentration_mc = mc.ConcentrationModel( room=models.Room(volume=160, humidity=0.3), @@ -102,7 +102,7 @@ def classroom_mc(): @pytest.fixture def ski_cabin_mc(): """ - Corresponds to the 3rd line of Table 4 in CERN-OPEN-2021-04 + Corresponds to the 3rd line of Table 4 in https://doi.org/10.1101/2021.10.14.21264988 """ concentration_mc = mc.ConcentrationModel( room=models.Room(volume=10, humidity=0.3), @@ -135,7 +135,7 @@ def ski_cabin_mc(): @pytest.fixture def skagit_chorale_mc(): """ - Corresponds to the 4th line of Table 4 in CERN-OPEN-2021-04, + Corresponds to the 4th line of Table 4 in https://doi.org/10.1101/2021.10.14.21264988, assuming viral is 10**9 instead of a LogCustomKernel distribution. """ concentration_mc = mc.ConcentrationModel( @@ -174,7 +174,7 @@ def skagit_chorale_mc(): @pytest.fixture def bus_ride_mc(): """ - Corresponds to the 5th line of Table 4 in CERN-OPEN-2021-04, + Corresponds to the 5th line of Table 4 in https://doi.org/10.1101/2021.10.14.21264988, assuming viral is 5*10**8 instead of a LogCustomKernel distribution. """ concentration_mc = mc.ConcentrationModel( From d966e911538039f2cb23b36aba146db967563c0d Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Wed, 10 Nov 2021 16:59:02 +0100 Subject: [PATCH 10/10] Updated references throughout the code --- cara/models.py | 8 +++++--- cara/monte_carlo/data.py | 6 +++--- cara/tests/test_predefined_distributions.py | 6 +++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/cara/models.py b/cara/models.py index 6d484be4..26cbf548 100644 --- a/cara/models.py +++ b/cara/models.py @@ -788,14 +788,16 @@ class ConcentrationModel: if (isinstance(self.infected, InfectedPopulation) and isinstance(self.infected.expiration, Expiration)): d = self.infected.expiration.diameter * self.evaporation_factor - vg = 1.88e-4 * (d / 2.5)**2 # see CERN-OPEN-2021-04 + vg = 1.88e-4 * (d / 2.5)**2 + # see https://doi.org/10.1101/2021.10.14.21264988 # (velocity of 1.88e-4 corresponds to diameter of 2.5 microns) else: # model is not evaluated for specific values of aerosol # diameters - we choose a single velocity value # corresponding to that obtained with a diameter of 2.5 microns # (geometric average of the breathing expiration distribution, - # taking evaporation into account, see CERN-OPEN-2021-04) + # taking evaporation into account, see + # https://doi.org/10.1101/2021.10.14.21264988) vg = 1.88e-4 # Height of the emission source to the floor - i.e. mouth/nose (m) h = 1.5 @@ -983,7 +985,7 @@ class ExposureModel: and isinstance(self.concentration_model.infected.expiration,Expiration)): # model is not evaluated for specific values of aerosol # diameters - we choose a single "average" deposition factor, - # as in CERN-OPEN-2021-04. + # as in https://doi.org/10.1101/2021.10.14.21264988. fdep = 0.6 else: # deposition factor depends on aerosol particle diameter. diff --git a/cara/monte_carlo/data.py b/cara/monte_carlo/data.py index 6d4dded6..ea4977b1 100644 --- a/cara/monte_carlo/data.py +++ b/cara/monte_carlo/data.py @@ -65,7 +65,7 @@ class BLOmodel: return result -# From CERN-OPEN-2021-04 and refererences therein +# From https://doi.org/10.1101/2021.10.14.21264988 and refererences therein activity_distributions = { 'Seated': mc.Activity(LogNormal(-0.6872121723362303, 0.10498338229297108), LogNormal(-0.6872121723362303, 0.10498338229297108)), @@ -84,7 +84,7 @@ activity_distributions = { } -# From CERN-OPEN-2021-04 and refererences therein +# From https://doi.org/10.1101/2021.10.14.21264988 and refererences therein symptomatic_vl_frequencies = LogCustomKernel( np.array((2.46032, 2.67431, 2.85434, 3.06155, 3.25856, 3.47256, 3.66957, 3.85979, 4.09927, 4.27081, 4.47631, 4.66653, 4.87204, 5.10302, 5.27456, 5.46478, 5.6533, 5.88428, 6.07281, 6.30549, @@ -105,7 +105,7 @@ viable_to_RNA_ratio_distribution = Uniform(0.15, 0.45) # From discussion with virologists infectious_dose_distribution = Uniform(10., 100.) -# From CERN-OPEN-2021-04 and refererences therein +# From https://doi.org/10.1101/2021.10.14.21264988 and refererences therein virus_distributions = { 'SARS_CoV_2': mc.SARSCoV2( viral_load_in_sputum=symptomatic_vl_frequencies, diff --git a/cara/tests/test_predefined_distributions.py b/cara/tests/test_predefined_distributions.py index 524cfcfe..b576b7e3 100644 --- a/cara/tests/test_predefined_distributions.py +++ b/cara/tests/test_predefined_distributions.py @@ -8,7 +8,7 @@ from cara.monte_carlo.data import activity_distributions, virus_distributions np.random.seed(2000) -# mean & std deviations from CERN-OPEN-2021-04 (Table 4) +# mean & std deviations from https://doi.org/10.1101/2021.10.14.21264988 (Table 3) # NOTE: a mistake was corrected for the std deviation of the # "Moderate exercise" case (0.37 in the report, but should be 0.34) @pytest.mark.parametrize( @@ -30,8 +30,8 @@ def test_activity_distributions(distribution, mean, std): npt.assert_allclose(activity.inhalation_rate.std(), std, atol=0.01) -# mean & std deviations from CERN-OPEN-2021-04 (Table 4) - with a refined -# precision on the values +# mean & std deviations from https://doi.org/10.1101/2021.10.14.21264988 (Table 3) +# - with a refined precision on the values @pytest.mark.parametrize( "distribution, mean, std",[ ['SARS_CoV_2', 6.59, 1.74],