Modifying condition to trigger the averaging of the exposure in cara/models.py
This commit is contained in:
parent
84fcddcd86
commit
396339f7bb
4 changed files with 27 additions and 27 deletions
|
|
@ -24,7 +24,7 @@ minutes_since_midnight = typing.NewType('minutes_since_midnight', int)
|
|||
# Used to declare when an attribute of a class must have a value provided, and
|
||||
# there should be no default value used.
|
||||
_NO_DEFAULT = object()
|
||||
_DEFAULT_MC_SAMPLE_SIZE = 50000
|
||||
_DEFAULT_MC_SAMPLE_SIZE = 250000
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
|
|
|
|||
|
|
@ -580,7 +580,7 @@ class MultipleExpiration(_ExpirationBase):
|
|||
Group together different modes of expiration, that represent
|
||||
each the main expiration mode for a certain fraction of time (given by
|
||||
the weights).
|
||||
Obsolet class that can only be used with single diameters (it cannot
|
||||
This class can only be used with single diameters (it cannot
|
||||
be used with diameter distributions).
|
||||
"""
|
||||
expirations: typing.Tuple[_ExpirationBase, ...]
|
||||
|
|
@ -900,6 +900,13 @@ class ConcentrationModel:
|
|||
|
||||
@dataclass(frozen=True)
|
||||
class ExposureModel:
|
||||
"""
|
||||
Represents the exposure to a concentration of virions in the air.
|
||||
NOTE: the infection probability formula assumes that if the diameter
|
||||
is an array, then none of the ventilation parameters, room volume or virus
|
||||
decay constant, are arrays as well.
|
||||
TODO: implement a check this is the case, in __post_init__
|
||||
"""
|
||||
#: The virus concentration model which this exposure model should consider.
|
||||
concentration_model: ConcentrationModel
|
||||
|
||||
|
|
@ -932,7 +939,12 @@ class ExposureModel:
|
|||
corresponds to an integration on diameters).
|
||||
"""
|
||||
emission_rate = self.concentration_model.infected.emission_rate_when_present()
|
||||
if np.isscalar(self.concentration_model.infected.expiration.diameter):
|
||||
if (not isinstance(self.concentration_model.infected,InfectedPopulation)
|
||||
or not isinstance(self.concentration_model.infected.expiration,Expiration)
|
||||
or np.isscalar(self.concentration_model.infected.expiration.diameter)
|
||||
):
|
||||
# in all these cases, there is no distribution of
|
||||
# diameters that need to be integrated over
|
||||
return self._normed_exposure() * emission_rate
|
||||
else:
|
||||
# the mean of the diameter-dependent exposure (including
|
||||
|
|
|
|||
|
|
@ -12,10 +12,9 @@ from cara import models
|
|||
from cara.monte_carlo.data import expiration_distributions
|
||||
|
||||
# TODO: seed better the random number generators
|
||||
# this is only for test_blend_expiration
|
||||
np.random.seed(2000)
|
||||
SAMPLE_SIZE = 500000
|
||||
TOLERANCE = 0.01
|
||||
SAMPLE_SIZE = 250000
|
||||
TOLERANCE = 0.02
|
||||
|
||||
def test_model_from_dict(baseline_form_data):
|
||||
form = model_generator.FormData.from_dict(baseline_form_data)
|
||||
|
|
|
|||
|
|
@ -5,10 +5,12 @@ 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.apps.calculator.model_generator import build_expiration
|
||||
|
||||
# TODO: seed better the random number generators
|
||||
np.random.seed(2000)
|
||||
SAMPLE_SIZE = 50000
|
||||
SAMPLE_SIZE = 250000
|
||||
TOLERANCE = 0.05
|
||||
|
||||
# references values for infection_probability and expected new cases
|
||||
|
|
@ -42,10 +44,7 @@ def shared_office_mc():
|
|||
presence=mc.SpecificInterval(((0., 2.), (2.1, 4.), (5., 7.), (7.1, 9.))),
|
||||
mask=models.Mask(η_inhale=0.3),
|
||||
activity=activity_distributions['Seated'],
|
||||
expiration=models.MultipleExpiration(
|
||||
expirations=(models.Expiration.types['Talking'],
|
||||
models.Expiration.types['Breathing']),
|
||||
weights=(0.3, 0.7)),
|
||||
expiration=build_expiration({'Talking': 0.3, 'Breathing': 0.7}),
|
||||
),
|
||||
)
|
||||
return mc.ExposureModel(
|
||||
|
|
@ -86,7 +85,7 @@ def classroom_mc():
|
|||
presence=mc.SpecificInterval(((0., 2.), (2.5, 4.), (5., 7.), (7.5, 9.))),
|
||||
mask=models.Mask.types['No mask'],
|
||||
activity=activity_distributions['Light activity'],
|
||||
expiration=models.Expiration.types['Talking'],
|
||||
expiration=expiration_distributions['Talking'],
|
||||
),
|
||||
)
|
||||
return mc.ExposureModel(
|
||||
|
|
@ -117,7 +116,7 @@ def ski_cabin_mc():
|
|||
presence=mc.SpecificInterval(((0., 1/3),)),
|
||||
mask=models.Mask(η_inhale=0.3),
|
||||
activity=activity_distributions['Moderate activity'],
|
||||
expiration=models.Expiration.types['Talking'],
|
||||
expiration=expiration_distributions['Talking'],
|
||||
),
|
||||
)
|
||||
return mc.ExposureModel(
|
||||
|
|
@ -150,7 +149,7 @@ def gym_mc():
|
|||
presence=mc.SpecificInterval(((0., 1.),)),
|
||||
mask=models.Mask.types["No mask"],
|
||||
activity=activity_distributions['Heavy exercise'],
|
||||
expiration=models.Expiration.types['Breathing'],
|
||||
expiration=expiration_distributions['Breathing'],
|
||||
),
|
||||
)
|
||||
return mc.ExposureModel(
|
||||
|
|
@ -182,10 +181,7 @@ def waiting_room_mc():
|
|||
presence=mc.SpecificInterval(((0., 2.),)),
|
||||
mask=models.Mask.types["No mask"],
|
||||
activity=activity_distributions['Seated'],
|
||||
expiration=models.MultipleExpiration(
|
||||
expirations=(models.Expiration.types['Talking'],
|
||||
models.Expiration.types['Breathing']),
|
||||
weights=(0.3, 0.7)),
|
||||
expiration=build_expiration({'Talking': 0.3, 'Breathing': 0.7})
|
||||
),
|
||||
)
|
||||
return mc.ExposureModel(
|
||||
|
|
@ -218,11 +214,7 @@ def skagit_chorale_mc():
|
|||
presence=mc.SpecificInterval(((0., 2.5),)),
|
||||
mask=models.Mask.types["No mask"],
|
||||
activity=activity_distributions['Light activity'],
|
||||
expiration=models.Expiration(10.0761),
|
||||
# The aerosol diameter given (10.0761 microns) is an equivalent
|
||||
# diameter, chosen in such a way that the aerosol volume is
|
||||
# the same as the total aerosol volume given by the full BLO model
|
||||
# with (5, 5, 5) for the B/L/O weights.
|
||||
expiration=expiration_distribution((5., 5., 5.)),
|
||||
),
|
||||
)
|
||||
return mc.ExposureModel(
|
||||
|
|
@ -295,10 +287,7 @@ def test_small_shared_office_Geneva(mask_type, month, expected_pi,
|
|||
presence=mc.SpecificInterval(((9., 10+2/3), (10+5/6, 12.5), (13.5, 15+2/3), (15+5/6, 18.))),
|
||||
mask=models.Mask.types[mask_type],
|
||||
activity=activity_distributions['Seated'],
|
||||
expiration=models.MultipleExpiration(
|
||||
expirations=(models.Expiration.types['Talking'],
|
||||
models.Expiration.types['Breathing']),
|
||||
weights=(0.33, 0.67)),
|
||||
expiration=build_expiration({'Talking': 0.33, 'Breathing': 0.67}),
|
||||
),
|
||||
)
|
||||
exposure_mc = mc.ExposureModel(
|
||||
|
|
|
|||
Loading…
Reference in a new issue