injected parameters in models, model and report generator

This commit is contained in:
Luis Aleixo 2023-10-26 16:29:20 +02:00
parent 3cc90593c2
commit 3f75fc77cd
3 changed files with 32 additions and 47 deletions

View file

@ -19,6 +19,7 @@ from caimira.monte_carlo.data import expiration_distribution, expiration_BLO_fac
from .defaults import (NO_DEFAULT, DEFAULT_MC_SAMPLE_SIZE, DEFAULTS, ACTIVITIES, ACTIVITY_TYPES, COFFEE_OPTIONS_INT, CONFIDENCE_LEVEL_OPTIONS,
MECHANICAL_VENTILATION_TYPES, MASK_TYPES, MASK_WEARING_OPTIONS, MONTH_NAMES, VACCINE_BOOSTER_TYPE, VACCINE_TYPE,
VENTILATION_TYPES, VIRUS_TYPES, VOLUME_TYPES, WINDOWS_OPENING_REGIMES, WINDOWS_TYPES)
from caimira.store.configuration import config
LOG = logging.getLogger(__name__)
@ -314,10 +315,10 @@ class FormData:
if self.arve_sensors_option == False:
if self.room_heating_option:
humidity = 0.3
humidity = config.room['defaults']['humidity_with_heating']
else:
humidity = 0.5
inside_temp = 293.
humidity = config.room['defaults']['humidity_without_heating']
inside_temp = config.room['defaults']['inside_temp']
else:
humidity = float(self.humidity)
inside_temp = self.inside_temp
@ -373,7 +374,7 @@ class FormData:
if (self.activity_type == 'precise'):
activity_defn, _ = self.generate_precise_activity_expiration()
else:
activity_defn = ACTIVITIES[ACTIVITY_TYPES.index(self.activity_type)]['activity']
activity_defn = activity_defn = ACTIVITIES[self.activity_type]['activity']
population = mc.SimplePopulation(
number=models.IntPiecewiseConstant(transition_times=tuple(transition_times), values=tuple(total_people)),
@ -476,7 +477,8 @@ class FormData:
# This is a minimal, always present source of ventilation, due
# to the air infiltration from the outside.
# See CERN-OPEN-2021-004, p. 12.
infiltration_ventilation = models.AirChange(active=always_on, air_exch=0.25)
residual_vent: float = config.ventilation['infiltration_ventilation'] # type: ignore
infiltration_ventilation = models.AirChange(active=always_on, air_exch=residual_vent)
if self.hepa_option:
hepa = models.HEPAFilter(active=always_on, q_air_mech=self.hepa_amount)
return models.MultipleVentilation((ventilation, hepa, infiltration_ventilation))
@ -511,9 +513,8 @@ class FormData:
# Initializes the virus
virus = virus_distributions[self.virus_type]
activity_index = ACTIVITY_TYPES.index(self.activity_type)
activity_defn = ACTIVITIES[activity_index]['activity']
expiration_defn = ACTIVITIES[activity_index]['expiration']
activity_defn = ACTIVITIES[self.activity_type]['activity']
expiration_defn = ACTIVITIES[self.activity_type]['expiration']
if (self.activity_type == 'smallmeeting'):
# Conversation of N people is approximately 1/N% of the time speaking.
@ -538,29 +539,9 @@ class FormData:
return infected
def exposed_population(self) -> mc.Population:
scenario_activity = {
'office': 'Seated',
'controlroom-day': 'Seated',
'controlroom-night': 'Seated',
'smallmeeting': 'Seated',
'largemeeting': 'Standing',
'callcentre': 'Seated',
'library': 'Seated',
'training': 'Standing',
'training_attendee': 'Seated',
'lab':'Light activity',
'workshop': 'Moderate activity',
'gym':'Heavy exercise',
'household-day': 'Light activity',
'household-night': 'Seated',
'primary-school': 'Light activity',
'secondary-school': 'Light activity',
'university': 'Seated',
'restaurant': 'Seated',
'precise': self.precise_activity['physical_activity'] if self.activity_type == 'precise' else None,
}
activity_defn = scenario_activity[self.activity_type]
activity_defn = (self.precise_activity['physical_activity']
if self.activity_type == 'precise'
else str(config.population_scenario_activity[self.activity_type]['activity']))
activity = activity_distributions[activity_defn]
infected_occupants = self.infected_people

View file

@ -17,6 +17,7 @@ from caimira.apps.calculator import markdown_tools
from ... import monte_carlo as mc
from .model_generator import FormData, DEFAULT_MC_SAMPLE_SIZE
from ... import dataclass_utils
from caimira.store.configuration import config
def model_start_end(model: models.ExposureModel):
@ -201,8 +202,8 @@ def conditional_prob_inf_given_vl_dist(infection_probability: models._Vectorised
for vl_log in viral_loads:
specific_prob = infection_probability[np.where((vl_log-step/2-specific_vl)*(vl_log+step/2-specific_vl)<0)[0]] #type: ignore
pi_means.append(specific_prob.mean())
lower_percentiles.append(np.quantile(specific_prob, 0.05))
upper_percentiles.append(np.quantile(specific_prob, 0.95))
lower_percentiles.append(np.quantile(specific_prob, config.conditional_prob_inf_given_viral_load['lower_percentile']))
upper_percentiles.append(np.quantile(specific_prob, config.conditional_prob_inf_given_viral_load['upper_percentile']))
return pi_means, lower_percentiles, upper_percentiles
@ -210,7 +211,9 @@ def conditional_prob_inf_given_vl_dist(infection_probability: models._Vectorised
def manufacture_conditional_probability_data(exposure_model: models.ExposureModel,
infection_probability: models._VectorisedFloat):
min_vl, max_vl, step = 2, 10, 8/100
min_vl = config.conditional_prob_inf_given_viral_load['min_vl']
max_vl = config.conditional_prob_inf_given_viral_load['max_vl']
step = (max_vl - min_vl)/100
viral_loads = np.arange(min_vl, max_vl, step)
specific_vl = np.log10(exposure_model.concentration_model.virus.viral_load_in_sputum)
pi_means, lower_percentiles, upper_percentiles = conditional_prob_inf_given_vl_dist(infection_probability, viral_loads,

View file

@ -49,6 +49,7 @@ else:
from .utils import method_cache
from .dataclass_utils import nested_replace
from caimira.store.configuration import config
oneoverln2 = 1 / np.log(2)
# Define types for items supporting vectorisation. In the future this may be replaced
@ -347,7 +348,7 @@ class SlidingWindow(WindowOpening):
Average measured value of discharge coefficient for sliding or
side-hung windows.
"""
return 0.6
return config.ventilation['natural']['discharge_factor']['sliding']
@dataclass(frozen=True)
@ -860,7 +861,7 @@ class _PopulationWithVirus(Population):
The fraction of infectious virus.
"""
return 1.
return config.population_with_virus['fraction_of_infectious_virus']
def aerosols(self):
"""
@ -1032,7 +1033,7 @@ class _ConcentrationModelBase:
(in the same unit as the concentration). Its the value towards which
the concentration will decay to.
"""
return 0.
return config.concentration_model['min_background_concentration']
def normalization_factor(self) -> _VectorisedFloat:
"""
@ -1220,7 +1221,7 @@ class ConcentrationModel(_ConcentrationModelBase):
#: evaporation factor: the particles' diameter is multiplied by this
# factor as soon as they are in the air (but AFTER going out of the,
# mask, if any).
evaporation_factor: float = 0.3
evaporation_factor: float = config.particle['evaporation_factor']
@property
def population(self) -> InfectedPopulation:
@ -1260,10 +1261,10 @@ class CO2ConcentrationModel(_ConcentrationModelBase):
CO2_emitters: SimplePopulation
#: CO2 concentration in the atmosphere (in ppm)
CO2_atmosphere_concentration: float = 440.44
CO2_atmosphere_concentration: float = config.concentration_model['CO2_concentration_model']['CO2_atmosphere_concentration']
#: CO2 fraction in the exhaled air
CO2_fraction_exhaled: float = 0.042
CO2_fraction_exhaled: float = config.concentration_model['CO2_concentration_model']['CO2_fraction_exhaled']
@property
def population(self) -> SimplePopulation:
@ -1309,14 +1310,14 @@ class ShortRangeModel:
The dilution factor for the respective expiratory activity type.
'''
# Average mouth opening diameter (m)
mouth_diameter = 0.02
mouth_diameter: float = config.short_range_model['dilution_factor']['mouth_diameter']
# Breathing rate, from m3/h to m3/s
BR = np.array(self.activity.exhalation_rate/3600.)
# Exhalation coefficient. Ratio between the duration of a breathing cycle and the duration of
# the exhalation.
φ = 2
φ: float = config.short_range_model['dilution_factor']['exhalation_coefficient']
# Exhalation airflow, as per Jia et al. (2022)
Q_exh: _VectorisedFloat = φ * BR
@ -1328,12 +1329,12 @@ class ShortRangeModel:
u0 = np.array(Q_exh/Am)
# Duration of the expiration period(s), assuming a 4s breath-cycle
tstar = 2.0
tstar: float = config.short_range_model['dilution_factor']['tstar']
# Streamwise and radial penetration coefficients
𝛽r1 = 0.18
𝛽r2 = 0.2
𝛽x1 = 2.4
𝛽r1: float = config.short_range_model['dilution_factor']['penetration_coefficients']['𝛽r1']
𝛽r2: float = config.short_range_model['dilution_factor']['penetration_coefficients']['𝛽r2']
𝛽x1: float = config.short_range_model['dilution_factor']['penetration_coefficients']['𝛽x1']
# Parameters in the jet-like stage
# Position of virtual origin
@ -1489,7 +1490,7 @@ class ExposureModel:
geographical_data: Cases
#: The number of times the exposure event is repeated (default 1).
repeats: int = 1
repeats: int = config.exposure_model['repeats']
def __post_init__(self):
"""