dose list implementation

This commit is contained in:
Luis Aleixo 2023-06-08 16:46:00 +02:00
parent c42c2b0b8b
commit 422d2245c5
2 changed files with 41 additions and 53 deletions

View file

@ -1700,41 +1700,11 @@ class ExposureModel:
else:
return 0
def dynamic_total_probability_rule(self) -> _VectorisedFloat:
if (self.geographical_data.geographic_population != 0 and self.geographical_data.geographic_cases != 0):
total_probability_rule_list = []
population_change_times = self.population_state_change_times()
for start, stop in zip(population_change_times[:-1], population_change_times[1:]):
sum_probability = 0.0
exposed_present = self.exposed.people_present(stop)
infected_present = self.concentration_model.infected.people_present(stop)
# Create an equivalent exposure model but changing the number of infected cases.
total_people = exposed_present + infected_present
max_num_infected = (total_people if total_people < 10 else 10)
# The influence of a higher number of simultainious infected people (> 4 - 5) yields an almost negligible contirbution to the total probability.
# To be on the safe side, a hard coded limit with a safety margin of 2x was set.
# Therefore we decided a hard limit of 10 infected people.
for num_infected in range(1, max_num_infected + 1):
exposure_model = nested_replace(
self, {'concentration_model.infected.number':
IntPiecewiseConstant((start, stop), (num_infected,)),
}
)
prob_ind = exposure_model.infection_probability().mean() / 100
n = total_people - num_infected
# By means of the total probability rule
prob_at_least_one_infected = 1 - (1 - prob_ind)**n
sum_probability += (prob_at_least_one_infected *
self.geographical_data.probability_meet_infected_person(self.concentration_model.infected.virus, num_infected, total_people))
total_probability_rule_list.append(sum_probability)
return (1 - np.prod([(1 - prob) for prob in total_probability_rule_list], axis = 0)) * 100
else:
return 0
def expected_new_cases(self) -> _VectorisedFloat:
if (isinstance(self.concentration_model.infected.number, IntPiecewiseConstant) or
isinstance(self.exposed.number, IntPiecewiseConstant)):
raise NotImplementedError("Cannot compute expected new cases "
"with dynamic occupancy")
# Create an equivalent exposure model without short-range interactions, if any.
if (len(self.short_range) == 0):
exposure_model = nested_replace(self, {'short_range': ()})
@ -1750,13 +1720,19 @@ class ExposureModel:
cases directly generated by one infected case in a population.
"""
if (isinstance(self.concentration_model.infected.number, IntPiecewiseConstant) or
isinstance(self.exposed.number, IntPiecewiseConstant)):
raise NotImplementedError("Cannot compute reproduction number "
"with dynamic occupancy")
if self.concentration_model.infected.number == 1:
return self.expected_new_cases()
# Create an equivalent exposure model but with precisely
# one infected case.
single_exposure_model = nested_replace(
self, {'concentration_model.infected.number': 1}
self, {
'concentration_model.infected.number': 1}
)
return single_exposure_model.expected_new_cases()

View file

@ -32,11 +32,7 @@ def full_exposure_model():
activity=models.Activity.types['Seated'],
host_immunity=0.
),
geographical_data=models.Cases(
geographic_population=50_000,
geographic_cases=52,
ascertainment_bias=1,
),
geographical_data=(),
)
@ -213,19 +209,35 @@ def test_infection_probability(
npt.assert_almost_equal(base_infection_probability, dynamic_population_exposure_model.infection_probability())
# def test_dynamic_total_probability_rule(
# full_exposure_model: models.ExposureModel,
# dynamic_infected_single_exposure_model: models.ExposureModel,
# dynamic_exposed_single_exposure_model: models.ExposureModel,
# dynamic_population_exposure_model: models.ExposureModel):
def test_dynamic_total_probability_rule(
dynamic_infected_single_exposure_model: models.ExposureModel,
dynamic_exposed_single_exposure_model: models.ExposureModel,
dynamic_population_exposure_model: models.ExposureModel):
# full_model_total_prob_rule = full_exposure_model.total_probability_rule()
# npt.assert_almost_equal(full_model_total_prob_rule,
# dynamic_population_exposure_model.dynamic_total_probability_rule())
with pytest.raises(NotImplementedError, match=re.escape("Cannot compute total probability "
"(including incidence rate) with dynamic occupancy")):
dynamic_infected_single_exposure_model.total_probability_rule()
dynamic_exposed_single_exposure_model.total_probability_rule()
dynamic_population_exposure_model.total_probability_rule()
# npt.assert_almost_equal(full_model_total_prob_rule,
# dynamic_infected_single_exposure_model.dynamic_total_probability_rule())
def test_dynamic_expected_new_cases(
dynamic_infected_single_exposure_model: models.ExposureModel,
dynamic_exposed_single_exposure_model: models.ExposureModel,
dynamic_population_exposure_model: models.ExposureModel):
# npt.assert_almost_equal(full_model_total_prob_rule,
# dynamic_exposed_single_exposure_model.dynamic_total_probability_rule())
with pytest.raises(NotImplementedError, match=re.escape("Cannot compute expected new cases "
"with dynamic occupancy")):
dynamic_infected_single_exposure_model.expected_new_cases()
dynamic_exposed_single_exposure_model.expected_new_cases()
dynamic_population_exposure_model.expected_new_cases()
def test_dynamic_reproduction_number(
dynamic_infected_single_exposure_model: models.ExposureModel,
dynamic_exposed_single_exposure_model: models.ExposureModel,
dynamic_population_exposure_model: models.ExposureModel):
with pytest.raises(NotImplementedError, match=re.escape("Cannot compute reproduction number "
"with dynamic occupancy")):
dynamic_infected_single_exposure_model.reproduction_number()
dynamic_exposed_single_exposure_model.reproduction_number()
dynamic_population_exposure_model.reproduction_number()