added logic behing ER and concentration (model)
This commit is contained in:
parent
0935056df2
commit
f6340d7986
6 changed files with 38 additions and 39 deletions
|
|
@ -685,15 +685,14 @@ class InfectedPopulation(Population):
|
|||
ER = (self.virus.viral_load_in_sputum *
|
||||
self.activity.exhalation_rate *
|
||||
10 ** 6 *
|
||||
aerosols /
|
||||
self.virus.infectious_dose)
|
||||
aerosols)
|
||||
|
||||
# For superspreading event, where ejection_factor is infinite we fix the ER
|
||||
# based on Miller et al. (2020).
|
||||
if isinstance(aerosols, np.ndarray):
|
||||
ER[np.isinf(aerosols)] = 970
|
||||
ER[np.isinf(aerosols)] = 970 * self.virus.infectious_dose
|
||||
elif np.isinf(aerosols):
|
||||
ER = 970
|
||||
ER = 970 * self.virus.infectious_dose
|
||||
|
||||
return ER
|
||||
|
||||
|
|
@ -867,7 +866,7 @@ class ExposureModel:
|
|||
#: The fraction of viruses actually deposited in the respiratory tract
|
||||
fraction_deposited: _VectorisedFloat = 0.6
|
||||
|
||||
def quanta_exposure(self) -> _VectorisedFloat:
|
||||
def exposure(self) -> _VectorisedFloat:
|
||||
"""The number of virus quanta per meter^3."""
|
||||
exposure = 0.0
|
||||
|
||||
|
|
@ -877,7 +876,7 @@ class ExposureModel:
|
|||
return exposure * self.repeats
|
||||
|
||||
def infection_probability(self) -> _VectorisedFloat:
|
||||
exposure = self.quanta_exposure()
|
||||
exposure = self.exposure()
|
||||
|
||||
inf_aero = (
|
||||
self.exposed.activity.inhalation_rate *
|
||||
|
|
@ -886,7 +885,7 @@ class ExposureModel:
|
|||
)
|
||||
|
||||
# Probability of infection.
|
||||
return (1 - np.exp(-inf_aero)) * 100
|
||||
return (1 - np.exp(-(inf_aero/self.concentration_model.virus.infectious_dose))) * 100
|
||||
|
||||
def expected_new_cases(self) -> _VectorisedFloat:
|
||||
prob = self.infection_probability()
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ def test_exposure_model_ndarray(population, cm, f_dep,
|
|||
expected_exposure, expected_probability):
|
||||
model = ExposureModel(cm, population, fraction_deposited = f_dep)
|
||||
np.testing.assert_almost_equal(
|
||||
model.quanta_exposure(), expected_exposure
|
||||
model.exposure(), expected_exposure
|
||||
)
|
||||
np.testing.assert_almost_equal(
|
||||
model.infection_probability(), expected_probability, decimal=10
|
||||
|
|
@ -94,7 +94,7 @@ def test_exposure_model_ndarray_and_float_mix(population):
|
|||
|
||||
expected_exposure = np.array([14.4, 14.4])
|
||||
np.testing.assert_almost_equal(
|
||||
model.quanta_exposure(), expected_exposure
|
||||
model.exposure(), expected_exposure
|
||||
)
|
||||
|
||||
assert isinstance(model.infection_probability(), np.ndarray)
|
||||
|
|
@ -109,10 +109,10 @@ def test_exposure_model_compare_scalar_vector(population):
|
|||
model_array = ExposureModel(cm_array, population)
|
||||
expected_exposure = 14.4
|
||||
np.testing.assert_almost_equal(
|
||||
model_scalar.quanta_exposure(), expected_exposure
|
||||
model_scalar.exposure(), expected_exposure
|
||||
)
|
||||
np.testing.assert_almost_equal(
|
||||
model_array.quanta_exposure(), np.array([expected_exposure]*2)
|
||||
model_array.exposure(), np.array([expected_exposure]*2)
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -152,4 +152,4 @@ def test_exposure_model_integral_accuracy(exposed_time_interval,
|
|||
models.Activity.types['Standing'],
|
||||
)
|
||||
model = ExposureModel(conc_model, population, fraction_deposited=1.)
|
||||
np.testing.assert_allclose(model.quanta_exposure(), expected_quanta)
|
||||
np.testing.assert_allclose(model.exposure(), expected_quanta)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import cara.models
|
|||
def test_infected_population_vectorisation(override_params):
|
||||
defaults = {
|
||||
'viral_load_in_sputum': 1e9,
|
||||
'infectious_dose': 50,
|
||||
'quantum_infectious_dose': 50,
|
||||
'exhalation_rate': 0.75,
|
||||
}
|
||||
defaults.update(override_params)
|
||||
|
|
@ -33,7 +33,7 @@ def test_infected_population_vectorisation(override_params):
|
|||
),
|
||||
virus=cara.models.Virus(
|
||||
viral_load_in_sputum=defaults['viral_load_in_sputum'],
|
||||
infectious_dose=defaults['infectious_dose'],
|
||||
infectious_dose=defaults['quantum_infectious_dose'],
|
||||
),
|
||||
expiration=cara.models.Expiration((1., 0., 0.)),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import cara.data as data
|
|||
|
||||
|
||||
def test_no_mask_superspeading_emission_rate(baseline_model):
|
||||
expected_rate = 970.
|
||||
expected_rate = 48500.
|
||||
npt.assert_allclose(
|
||||
[baseline_model.infected.emission_rate(t) for t in [0, 1, 4, 4.5, 5, 8, 9]],
|
||||
[0, expected_rate, expected_rate, 0, 0, expected_rate, 0],
|
||||
|
|
@ -44,7 +44,7 @@ def test_concentrations(baseline_model):
|
|||
concentrations = [baseline_model.concentration(t) for t in ts]
|
||||
npt.assert_allclose(
|
||||
concentrations,
|
||||
[0.000000e+00, 0.41611256, 1.3205628e-14, 0.41611256, 4.1909001e-28],
|
||||
[0.000000e+00, 20.805628, 6.602814e-13, 20.805628, 2.09545e-26],
|
||||
rtol=1e-6
|
||||
)
|
||||
|
||||
|
|
@ -354,16 +354,16 @@ def build_exposure_model(concentration_model):
|
|||
)
|
||||
|
||||
|
||||
# expected quanta were computed with a trapezoidal integration, using
|
||||
# expected exposure were computed with a trapezoidal integration, using
|
||||
# a mesh of 100'000 pts per exposed presence interval.
|
||||
@pytest.mark.parametrize(
|
||||
"month, expected_quanta",
|
||||
"month, expected_exposure",
|
||||
[
|
||||
['Jan', 9.930854],
|
||||
['Jun', 37.962708],
|
||||
['Jan', 496.5427],
|
||||
['Jun', 1898.1354],
|
||||
],
|
||||
)
|
||||
def test_quanta_hourly_dep(month,expected_quanta):
|
||||
def test_exposure_hourly_dep(month,expected_exposure):
|
||||
m = build_exposure_model(
|
||||
build_hourly_dependent_model(
|
||||
month,
|
||||
|
|
@ -371,20 +371,20 @@ def test_quanta_hourly_dep(month,expected_quanta):
|
|||
intervals_presence_infected=((8, 12), (13, 17))
|
||||
)
|
||||
)
|
||||
quanta = m.quanta_exposure()
|
||||
npt.assert_allclose(quanta, expected_quanta)
|
||||
exposure = m.exposure()
|
||||
npt.assert_allclose(exposure, expected_exposure)
|
||||
|
||||
# expected quanta were computed with a trapezoidal integration, using
|
||||
# expected exposure were computed with a trapezoidal integration, using
|
||||
# a mesh of 100'000 pts per exposed presence interval and 25 pts per hour
|
||||
# for the temperature discretization.
|
||||
@pytest.mark.parametrize(
|
||||
"month, expected_quanta",
|
||||
"month, expected_exposure",
|
||||
[
|
||||
['Jan', 9.993842],
|
||||
['Jun', 40.151985],
|
||||
['Jan', 499.6921],
|
||||
['Jun', 2007.59925],
|
||||
],
|
||||
)
|
||||
def test_quanta_hourly_dep_refined(month,expected_quanta):
|
||||
def test_exposure_hourly_dep_refined(month,expected_exposure):
|
||||
m = build_exposure_model(
|
||||
build_hourly_dependent_model(
|
||||
month,
|
||||
|
|
@ -393,5 +393,5 @@ def test_quanta_hourly_dep_refined(month,expected_quanta):
|
|||
temperatures=data.GenevaTemperatures,
|
||||
)
|
||||
)
|
||||
quanta = m.quanta_exposure()
|
||||
npt.assert_allclose(quanta, expected_quanta, rtol=0.02)
|
||||
exposure = m.exposure()
|
||||
npt.assert_allclose(exposure, expected_exposure, rtol=0.02)
|
||||
|
|
|
|||
|
|
@ -84,6 +84,6 @@ def test_build_concentration_model(baseline_mc_model: cara.monte_carlo.Concentra
|
|||
def test_build_exposure_model(baseline_mc_exposure_model: cara.monte_carlo.ExposureModel):
|
||||
model = baseline_mc_exposure_model.build_model(7)
|
||||
assert isinstance(model, cara.models.ExposureModel)
|
||||
prob = model.quanta_exposure()
|
||||
prob = model.exposure()
|
||||
assert isinstance(prob, np.ndarray)
|
||||
assert prob.shape == (7, )
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ def skagit_chorale_mc():
|
|||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"mc_model, expected_pi, expected_new_cases, expected_dose, expected_qR",
|
||||
"mc_model, expected_pi, expected_new_cases, expected_dose, expected_ER",
|
||||
[
|
||||
["shared_office_mc", 10.7, 0.32, 0.954, 10.9],
|
||||
["classroom_mc", 36.1, 6.85, 13.0, 474.4],
|
||||
|
|
@ -244,22 +244,22 @@ def skagit_chorale_mc():
|
|||
]
|
||||
)
|
||||
def test_report_models(mc_model, expected_pi, expected_new_cases,
|
||||
expected_dose, expected_qR, request):
|
||||
expected_dose, expected_ER, 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(),
|
||||
npt.assert_allclose(exposure_model.exposure().mean(),
|
||||
expected_dose, rtol=TOLERANCE)
|
||||
npt.assert_allclose(
|
||||
exposure_model.concentration_model.infected.emission_rate_when_present().mean(),
|
||||
expected_qR, rtol=TOLERANCE)
|
||||
expected_ER, rtol=TOLERANCE)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"mask_type, month, expected_pi, expected_dose, expected_qR",
|
||||
"mask_type, month, expected_pi, expected_dose, expected_ER",
|
||||
[
|
||||
["No mask", "Jul", 30.0, 6.764, 64.9],
|
||||
["Type I", "Jul", 10.2, 1.223, 11.7],
|
||||
|
|
@ -268,7 +268,7 @@ def test_report_models(mc_model, expected_pi, expected_new_cases,
|
|||
],
|
||||
)
|
||||
def test_small_shared_office_Geneva(mask_type, month, expected_pi,
|
||||
expected_dose, expected_qR):
|
||||
expected_dose, expected_ER):
|
||||
concentration_mc = mc.ConcentrationModel(
|
||||
room=models.Room(volume=33, humidity=0.5),
|
||||
ventilation=models.MultipleVentilation(
|
||||
|
|
@ -309,8 +309,8 @@ def test_small_shared_office_Geneva(mask_type, month, expected_pi,
|
|||
exposure_model = exposure_mc.build_model(size=SAMPLE_SIZE)
|
||||
npt.assert_allclose(exposure_model.infection_probability().mean(),
|
||||
expected_pi, rtol=TOLERANCE)
|
||||
npt.assert_allclose(exposure_model.quanta_exposure().mean(),
|
||||
npt.assert_allclose(exposure_model.exposure().mean(),
|
||||
expected_dose, rtol=TOLERANCE)
|
||||
npt.assert_allclose(
|
||||
exposure_model.concentration_model.infected.emission_rate_when_present().mean(),
|
||||
expected_qR, rtol=TOLERANCE)
|
||||
expected_ER, rtol=TOLERANCE)
|
||||
|
|
|
|||
Loading…
Reference in a new issue