diff --git a/cara/tests/test_monte_carlo_full_models.py b/cara/tests/test_monte_carlo_full_models.py index 8a43afd6..7c08757f 100644 --- a/cara/tests/test_monte_carlo_full_models.py +++ b/cara/tests/test_monte_carlo_full_models.py @@ -8,15 +8,18 @@ from cara.monte_carlo.data import activity_distributions, virus_distributions # TODO: seed better the random number generators np.random.seed(2000) -SAMPLE_SIZE = 20000 +SAMPLE_SIZE = 50000 TOLERANCE = 0.05 # references values for infection_probability and expected new cases # in the following tests, were obtained from the feature/mc branch -def test_shared_office(): - # corresponds to the 1st line of Table 5 in CERN-OPEN-2021-04, but - # speaking 30% of the time (instead of 1/3) +@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) + """ concentration_mc = mc.ConcentrationModel( room=models.Room(volume=50, humidity=0.3), ventilation=models.MultipleVentilation( @@ -45,7 +48,7 @@ def test_shared_office(): weights=(0.3, 0.7)), ), ) - exposure_mc = mc.ExposureModel( + return mc.ExposureModel( concentration_model=concentration_mc, exposed=mc.Population( number=3, @@ -54,15 +57,13 @@ def test_shared_office(): mask=concentration_mc.infected.mask, ), ) - exposure_model = exposure_mc.build_model(size=SAMPLE_SIZE) - npt.assert_allclose(exposure_model.infection_probability().mean(), - 10.7, rtol=TOLERANCE) - npt.assert_allclose(exposure_model.expected_new_cases().mean(), - 0.32, rtol=TOLERANCE) -def test_classroom(): - # corresponds to the 2nd line of Table 5 in CERN-OPEN-2021-04 +@pytest.fixture +def classroom_mc(): + """ + Corresponds to the 2nd line of Table 5 in CERN-OPEN-2021-04 + """ concentration_mc = mc.ConcentrationModel( room=models.Room(volume=160, humidity=0.3), ventilation=models.MultipleVentilation( @@ -88,7 +89,7 @@ def test_classroom(): expiration=models.Expiration.types['Talking'], ), ) - exposure_mc = mc.ExposureModel( + return mc.ExposureModel( concentration_model=concentration_mc, exposed=mc.Population( number=19, @@ -97,15 +98,13 @@ def test_classroom(): mask=concentration_mc.infected.mask, ), ) - exposure_model = exposure_mc.build_model(size=SAMPLE_SIZE) - npt.assert_allclose(exposure_model.infection_probability().mean(), - 36.1, rtol=TOLERANCE) - npt.assert_allclose(exposure_model.expected_new_cases().mean(), - 6.87, rtol=TOLERANCE) -def test_skicabin(): - # corresponds to the 3rd line of Table 5 in CERN-OPEN-2021-04 +@pytest.fixture +def ski_cabin_mc(): + """ + Corresponds to the 3rd line of Table 5 in CERN-OPEN-2021-04 + """ concentration_mc = mc.ConcentrationModel( room=models.Room(volume=10, humidity=0.5), ventilation=models.AirChange( @@ -121,7 +120,7 @@ def test_skicabin(): expiration=models.Expiration.types['Talking'], ), ) - exposure_mc = mc.ExposureModel( + return mc.ExposureModel( concentration_model=concentration_mc, exposed=mc.Population( number=3, @@ -130,17 +129,15 @@ def test_skicabin(): mask=concentration_mc.infected.mask, ), ) - exposure_model = exposure_mc.build_model(size=SAMPLE_SIZE) - npt.assert_allclose(exposure_model.infection_probability().mean(), - 16.2, rtol=TOLERANCE) - npt.assert_allclose(exposure_model.expected_new_cases().mean(), - 0.49, rtol=TOLERANCE) -def test_gym(): - # 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. +@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. + """ concentration_mc = mc.ConcentrationModel( room=models.Room(volume=300, humidity=0.5), ventilation=models.AirChange( @@ -156,7 +153,7 @@ def test_gym(): expiration=models.Expiration.types['Breathing'], ), ) - exposure_mc = mc.ExposureModel( + return mc.ExposureModel( concentration_model=concentration_mc, exposed=mc.Population( number=28, @@ -165,16 +162,14 @@ def test_gym(): mask=concentration_mc.infected.mask, ), ) - exposure_model = exposure_mc.build_model(size=SAMPLE_SIZE) - npt.assert_allclose(exposure_model.infection_probability().mean(), - 2.2, rtol=TOLERANCE) - npt.assert_allclose(exposure_model.expected_new_cases().mean(), - 0.63, rtol=TOLERANCE) -def test_waiting_room(): - # corresponds to the 5th line of Table 5 in CERN-OPEN-2021-04, but - # speaking 30% of the time (instead of 20%) +@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%) + """ concentration_mc = mc.ConcentrationModel( room=models.Room(volume=100, humidity=0.5), ventilation=models.AirChange( @@ -193,7 +188,7 @@ def test_waiting_room(): weights=(0.3, 0.7)), ), ) - exposure_mc = mc.ExposureModel( + return mc.ExposureModel( concentration_model=concentration_mc, exposed=mc.Population( number=14, @@ -202,17 +197,15 @@ def test_waiting_room(): mask=concentration_mc.infected.mask, ), ) - exposure_model = exposure_mc.build_model(size=SAMPLE_SIZE) - npt.assert_allclose(exposure_model.infection_probability().mean(), - 9.7, rtol=TOLERANCE) - npt.assert_allclose(exposure_model.expected_new_cases().mean(), - 1.36, rtol=TOLERANCE) -def test_skagit_chorale(): - # 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. +@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( @@ -228,7 +221,7 @@ def test_skagit_chorale(): expiration=models.Expiration((5., 5., 5.)), ), ) - exposure_mc = mc.ExposureModel( + return mc.ExposureModel( concentration_model=concentration_mc, exposed=mc.Population( number=60, @@ -237,23 +230,45 @@ def test_skagit_chorale(): mask=concentration_mc.infected.mask, ), ) - exposure_model = exposure_mc.build_model(size=SAMPLE_SIZE) - npt.assert_allclose(exposure_model.infection_probability().mean(), - 29.8, rtol=TOLERANCE) - npt.assert_allclose(exposure_model.expected_new_cases().mean(), - 17.9, rtol=TOLERANCE) @pytest.mark.parametrize( - "mask_type, month, expected_probability", + "mc_model, expected_pi, expected_new_cases, expected_dose, expected_qR", [ - ["No mask", "Jul", 30], - ["Type I", "Jul", 10.2], - ["FFP2", "Jul", 4], - ["Type I", "Feb", 4.3], + ["shared_office_mc", 10.7, 0.32, 0.954, 10.9], + ["classroom_mc", 36.1, 6.85, 13.0, 474.4], + ["ski_cabin_mc", 16.3, 0.49, 0.599, 123.4], + ["gym_mc", 2.25, 0.63, 0.01307, 16.4], + ["waiting_room_mc", 9.72, 1.36, 0.571, 58.9], + ["skagit_chorale_mc",29.9, 17.9, 1.90, 1414], + ] +) +def test_report_models(mc_model, expected_pi, expected_new_cases, + expected_dose, expected_qR, request): + mc_model = request.getfixturevalue(mc_model) + exposure_model = mc_model.build_model(size=SAMPLE_SIZE) + npt.assert_allclose(exposure_model.infection_probability().mean(), + expected_pi, rtol=TOLERANCE) + npt.assert_allclose(exposure_model.expected_new_cases().mean(), + expected_new_cases, rtol=TOLERANCE) + npt.assert_allclose(exposure_model.quanta_exposure().mean(), + expected_dose, rtol=TOLERANCE) + npt.assert_allclose( + exposure_model.concentration_model.infected.emission_rate_when_present().mean(), + expected_qR, rtol=TOLERANCE) + + +@pytest.mark.parametrize( + "mask_type, month, expected_pi, expected_dose, expected_qR", + [ + ["No mask", "Jul", 30.0, 6.764, 64.9], + ["Type I", "Jul", 10.2, 1.223, 11.7], + ["FFP2", "Jul", 4.0, 1.223, 11.7], + ["Type I", "Feb", 4.25, 0.357, 11.7], ], ) -def test_small_shared_office_Geneva(mask_type,month,expected_probability): +def test_small_shared_office_Geneva(mask_type, month, expected_pi, + expected_dose, expected_qR): concentration_mc = mc.ConcentrationModel( room=models.Room(volume=33, humidity=0.5), ventilation=models.MultipleVentilation( @@ -293,4 +308,9 @@ def test_small_shared_office_Geneva(mask_type,month,expected_probability): ) exposure_model = exposure_mc.build_model(size=SAMPLE_SIZE) npt.assert_allclose(exposure_model.infection_probability().mean(), - expected_probability, rtol=TOLERANCE) + expected_pi, rtol=TOLERANCE) + npt.assert_allclose(exposure_model.quanta_exposure().mean(), + expected_dose, rtol=TOLERANCE) + npt.assert_allclose( + exposure_model.concentration_model.infected.emission_rate_when_present().mean(), + expected_qR, rtol=TOLERANCE)