From bcb1d1012a21e5728a652d1fa352de734f11dc58 Mon Sep 17 00:00:00 2001 From: Luis Aleixo Date: Thu, 6 Apr 2023 12:27:39 +0200 Subject: [PATCH] modified dynamic tests for InfectedPopulation --- caimira/models.py | 10 +-- .../tests/models/test_dynamic_population.py | 62 ++++++++++++++----- 2 files changed, 51 insertions(+), 21 deletions(-) diff --git a/caimira/models.py b/caimira/models.py index 38924f8c..98e3e9a5 100644 --- a/caimira/models.py +++ b/caimira/models.py @@ -818,7 +818,7 @@ class Population: raise TypeError(f'The presence argument must be an "Interval". Got {type(self.presence)}') else: if self.presence is not None: - raise TypeError(f'The presence argument must be None for a IntPiecewiseConstant number.') + raise TypeError(f'The presence argument must be None for a IntPiecewiseConstant number') def person_present(self, time: float): # Allow back-compatibility @@ -1656,11 +1656,13 @@ class ExposureModel: self.concentration_model.virus.transmissibility_factor)))) * 100 def total_probability_rule(self) -> _VectorisedFloat: - if (self.geographical_data.geographic_population != 0 and self.geographical_data.geographic_cases != 0): - sum_probability = 0.0 - if not isinstance(self.concentration_model.infected.number, int): + if (isinstance(self.concentration_model.infected.number, IntPiecewiseContant) or + isinstance(self.exposed.number, IntPiecewiseContant)): raise NotImplementedError("Cannot compute total probability " "(including incidence rate) with dynamic occupancy") + + if (self.geographical_data.geographic_population != 0 and self.geographical_data.geographic_cases != 0): + sum_probability = 0.0 # Create an equivalent exposure model but changing the number of infected cases. total_people = self.concentration_model.infected.number + self.exposed.number diff --git a/caimira/tests/models/test_dynamic_population.py b/caimira/tests/models/test_dynamic_population.py index e2737e10..41137c34 100644 --- a/caimira/tests/models/test_dynamic_population.py +++ b/caimira/tests/models/test_dynamic_population.py @@ -1,3 +1,5 @@ +import re + import numpy as np import numpy.testing as npt import pytest @@ -48,17 +50,6 @@ def baseline_infected_population_number(): ) -@pytest.fixture -def baseline_exposed_population_number(): - return models.Population( - number=models.IntPiecewiseContant( - (8, 12, 13, 17), (1, 0, 1)), - presence=None, - mask=models.Mask.types['No mask'], - activity=models.Activity.types['Seated'], - host_immunity=0., - ) - @pytest.mark.parametrize( "time", [4., 8., 10., 12., 13., 14., 16., 20., 24.], @@ -74,6 +65,22 @@ def test_population_number(full_exposure_model: models.ExposureModel, assert isinstance(piecewise_population_number.number, models.IntPiecewiseContant) assert piecewise_population_number.presence is None + + with pytest.raises( + TypeError, + match=f'The presence argument must be an "Interval". Got {type(None)}' + ): + dc_utils.nested_replace( + int_population_number, {'presence': None} + ) + + with pytest.raises( + TypeError, + match="The presence argument must be None for a IntPiecewiseConstant number" + ): + dc_utils.nested_replace( + piecewise_population_number, {'presence': models.SpecificInterval(((8, 12), ))} + ) assert int_population_number.person_present(time) == piecewise_population_number.person_present(time) assert int_population_number.people_present(time) == piecewise_population_number.people_present(time) @@ -85,14 +92,12 @@ def test_population_number(full_exposure_model: models.ExposureModel, ) def test_concentration_model_dynamic_population(full_exposure_model: models.ExposureModel, baseline_infected_population_number: models.InfectedPopulation, - baseline_exposed_population_number: models.Population, time: float): dynamic_model: models.ExposureModel = dc_utils.nested_replace( full_exposure_model, { 'concentration_model.infected': baseline_infected_population_number, - 'exposed': baseline_exposed_population_number, } ) assert full_exposure_model.concentration(time) == dynamic_model.concentration(time) @@ -107,7 +112,7 @@ def test_concentration_model_dynamic_population(full_exposure_model: models.Expo [13., 4], [15., 5], ]) -def test_sum_of_models(full_exposure_model: models.ExposureModel, +def test_linearity_with_number_of_infected(full_exposure_model: models.ExposureModel, baseline_infected_population_number: models.InfectedPopulation, time: float, number_of_infected: int): @@ -128,9 +133,13 @@ def test_sum_of_models(full_exposure_model: models.ExposureModel, ) npt.assert_almost_equal(static_multiple_exposure_model.concentration(time), dynamic_single_exposure_model.concentration(time) * number_of_infected) + npt.assert_almost_equal(static_multiple_exposure_model.deposited_exposure(), dynamic_single_exposure_model.deposited_exposure() * number_of_infected) -def test_dynamic_dose(full_exposure_model): +@pytest.mark.parametrize( + "time", (8., 9., 10., 11., 12., 13., 14.), +) +def test_dynamic_dose(full_exposure_model, time): dynamic_infected: models.ExposureModel = dc_utils.nested_replace( full_exposure_model, @@ -172,7 +181,26 @@ def test_dynamic_dose(full_exposure_model): } ) + dynamic_concentration = dynamic_infected.concentration(time) dynamic_exposure = dynamic_infected.deposited_exposure() - static_exposure = np.sum([model.deposited_exposure() for model in (single_infected, two_infected, three_infected)]) - npt.assert_almost_equal(dynamic_exposure, static_exposure) + static_concentration, static_exposure = [], [] + for model in (single_infected, two_infected, three_infected): + static_concentration.append(model.concentration(time)) + static_exposure.append(model.deposited_exposure()) + + npt.assert_almost_equal(dynamic_concentration, np.sum(np.array(static_concentration))) + npt.assert_almost_equal(dynamic_exposure, np.sum(np.array(static_exposure))) + + +def test_dynamic_total_probability_rule(full_exposure_model: models.ExposureModel, + baseline_infected_population_number: models.InfectedPopulation): + + model = dc_utils.nested_replace(full_exposure_model, + {'concentration_model.infected': baseline_infected_population_number }) + with pytest.raises( + NotImplementedError, + match=re.escape("Cannot compute total probability " + "(including incidence rate) with dynamic occupancy") + ): + model.total_probability_rule()