Skip to content

Commit

Permalink
changed files directory and added remaining store items
Browse files Browse the repository at this point in the history
  • Loading branch information
lrdossan committed Oct 24, 2023
1 parent 82adc10 commit 741046a
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 47 deletions.
24 changes: 0 additions & 24 deletions caimira/apps/calculator/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
from . import markdown_tools
from . import model_generator
from .report_generator import ReportGenerator, calculate_report_data
from .data_service import DataService
from .user import AuthenticatedUser, AnonymousUser

# The calculator version is based on a combination of the model version and the
Expand Down Expand Up @@ -106,17 +105,6 @@ async def post(self) -> None:
pprint(requested_model_config)
start = datetime.datetime.now()

# Data Service API Integration
fetched_service_data = None
data_service: DataService = self.settings["data_service"]
if self.settings["data_service"]:
try:
fetched_service_data = await data_service.fetch()
except Exception as err:
error_message = f"Something went wrong with the data service: {str(err)}"
LOG.error(error_message, exc_info=True)
self.send_error(500, reason=error_message)

try:
form = model_generator.FormData.from_dict(requested_model_config)
except Exception as err:
Expand Down Expand Up @@ -429,15 +417,6 @@ def make_app(
)
template_environment.globals['get_url']=get_root_url
template_environment.globals['get_calculator_url']=get_root_calculator_url

data_service_credentials = {
'data_service_client_email': os.environ.get('DATA_SERVICE_CLIENT_EMAIL', None),
'data_service_client_password': os.environ.get('DATA_SERVICE_CLIENT_PASSWORD', None),
}
data_service = None
data_service_enabled = os.environ.get('DATA_SERVICE_ENABLED', 'False').lower() == 'true'
if data_service_enabled:
data_service = DataService(data_service_credentials)

if debug:
tornado.log.enable_pretty_logging()
Expand All @@ -456,9 +435,6 @@ def make_app(
arve_client_secret=os.environ.get('ARVE_CLIENT_SECRET', None),
arve_api_key=os.environ.get('ARVE_API_KEY', None),

# Data Service Integration
data_service=data_service,

# Process parallelism controls. There is a balance between serving a single report
# requests quickly or serving multiple requests concurrently.
# The defaults are: handle one report at a time, and allow parallelism
Expand Down
9 changes: 5 additions & 4 deletions caimira/apps/calculator/model_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,10 +315,10 @@ def initialize_room(self) -> models.Room:

if self.arve_sensors_option == False:
if self.room_heating_option:
humidity = 0.3
humidity = constants.room['defaults']['humidity_with_heating']
else:
humidity = 0.5
inside_temp = 293.
humidity = constants.room['defaults']['humidity_without_heating']
inside_temp = constants.room['defaults']['inside_temp']
else:
humidity = float(self.humidity)
inside_temp = self.inside_temp
Expand Down Expand Up @@ -472,7 +472,8 @@ def ventilation(self) -> models._VentilationBase:
# 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 = constants.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))
Expand Down
59 changes: 56 additions & 3 deletions caimira/global_store/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,46 @@
'sigma': {'B': 0.262364, 'L': 0.506818, 'O': 0.585005},
}

short_range_model = {
'exhalation_coefficient': 2,
'mouth_diameter': 0.02,
'penetration_coefficients': {'𝛽r1': 0.18, '𝛽r2': 0.2, '𝛽x1': 2.4},
'tstar': 2
}

concentration_model = {
'CO2_concentration_model': {
'CO2_atmosphere_concentration': 440.44,
'CO2_fraction_exhaled': 0.042
},
'min_background_concentration': 0.0
}

population_with_virus = {
'fraction_of_infectious_virus': 1,
}

particle = {
'evaporation_factor': 0.3,
}

ventilation = {
'natural': {
'discharge_factor': {
'sliding': 0.6,
},
},
'infiltration_ventilation': 0.25,
}

room = {
'defaults': {
'inside_temp': 293,
'humidity_with_heating': 0.3,
'humidity_without_heating': 0.5,
},
}

def update_local_reference(local_data, api_data: typing.Union[dict, typing.Any]):
'''
Recursive function that iterates through the keys and values of local and remote dictionaries.
Expand All @@ -240,11 +280,12 @@ def update_local_reference(local_data, api_data: typing.Union[dict, typing.Any])
async def populate_data():
global data_fetched, BLOmodel, covid_overal_vl_data, infectious_dose_distribution, viable_to_RNA_ratio_distribution, virus_distributions, activity_distributions
global mask_distributions, expiration_BLO_factors, long_range_expiration_distributions, short_range_expiration_distributions, short_range_distances
global infected_population_scenario_activity, monte_carlo_sample_size, conditional_prob_inf_given_viral_load, exposure_model
global infected_population_scenario_activity, monte_carlo_sample_size, conditional_prob_inf_given_viral_load, exposure_model, short_range_model
global concentration_model, population_with_virus, particle, ventilation, room

if not data_fetched and os.environ.get('DATA_SERVICE_ENABLED', 'False').lower() == 'true':
# Fetch data if it hasn't been fetched yet
from caimira.global_store.data_store import GlobalStore
from caimira.global_store.global_store import GlobalStore

await GlobalStore.populate_from_api()
data = GlobalStore.get_data()['data']
Expand Down Expand Up @@ -279,7 +320,19 @@ async def populate_data():
conditional_prob_inf_given_viral_load, data['conditional_prob_inf_given_viral_load'])
exposure_model = update_local_reference(
exposure_model, data['exposure_model'])

short_range_model = update_local_reference(
short_range_model, data['short_range_model'])
concentration_model = update_local_reference(
concentration_model, data['concentration_model'])
population_with_virus = update_local_reference(
population_with_virus, data['population_with_virus'])
particle = update_local_reference(
particle, data['particle'])
ventilation = update_local_reference(
ventilation, data['ventilation'])
room = update_local_reference(
room, data['room'])

data_fetched = True

# Executed when this module is imported
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os

from caimira.apps.calculator.data_service import DataService
from caimira.global_store.data_service import DataService


class GlobalStore:
Expand Down
29 changes: 15 additions & 14 deletions caimira/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
# by providing a no-op cache decorator when type-checking.
cached = lambda *cached_args, **cached_kwargs: lambda function: function # noqa

import caimira.global_store.constants as constants

from .utils import method_cache

from .dataclass_utils import nested_replace
Expand Down Expand Up @@ -347,7 +349,7 @@ def discharge_coefficient(self) -> _VectorisedFloat:
Average measured value of discharge coefficient for sliding or
side-hung windows.
"""
return 0.6
return float(constants.ventilation['natural']['discharge_factor']['sliding']) # type: ignore


@dataclass(frozen=True)
Expand Down Expand Up @@ -860,7 +862,7 @@ def fraction_of_infectious_virus(self) -> _VectorisedFloat:
The fraction of infectious virus.
"""
return 1.
return float(constants.population_with_virus['fraction_of_infectious_virus']) # type: ignore

def aerosols(self):
"""
Expand Down Expand Up @@ -1032,7 +1034,7 @@ def min_background_concentration(self) -> _VectorisedFloat:
(in the same unit as the concentration). Its the value towards which
the concentration will decay to.
"""
return 0.
return float(constants.concentration_model['min_background_concentration']) # type: ignore

def normalization_factor(self) -> _VectorisedFloat:
"""
Expand Down Expand Up @@ -1220,7 +1222,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 = constants.particle['evaporation_factor'] # type: ignore

@property
def population(self) -> InfectedPopulation:
Expand Down Expand Up @@ -1260,10 +1262,10 @@ class CO2ConcentrationModel(_ConcentrationModelBase):
CO2_emitters: SimplePopulation

#: CO2 concentration in the atmosphere (in ppm)
CO2_atmosphere_concentration: float = 440.44
CO2_atmosphere_concentration: float = constants.concentration_model['CO2_concentration_model']['CO2_atmosphere_concentration'] # type: ignore

#: CO2 fraction in the exhaled air
CO2_fraction_exhaled: float = 0.042
CO2_fraction_exhaled: float = constants.concentration_model['CO2_concentration_model']['CO2_fraction_exhaled'] # type: ignore

@property
def population(self) -> SimplePopulation:
Expand All @@ -1284,7 +1286,6 @@ def normalization_factor(self) -> _VectorisedFloat:
return (1e6*self.population.activity.exhalation_rate
*self.CO2_fraction_exhaled)


@dataclass(frozen=True)
class ShortRangeModel:
'''
Expand All @@ -1309,14 +1310,14 @@ def dilution_factor(self) -> _VectorisedFloat:
The dilution factor for the respective expiratory activity type.
'''
# Average mouth opening diameter (m)
mouth_diameter = 0.02
mouth_diameter: float = constants.short_range_model['dilution_factor']['mouth_diameter'] # type: ignore

# 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 = constants.short_range_model['dilution_factor']['exhalation_coefficient'] # type: ignore

# Exhalation airflow, as per Jia et al. (2022)
Q_exh: _VectorisedFloat = φ * BR
Expand All @@ -1328,12 +1329,12 @@ def dilution_factor(self) -> _VectorisedFloat:
u0 = np.array(Q_exh/Am)

# Duration of the expiration period(s), assuming a 4s breath-cycle
tstar = 2.0
tstar: float = constants.short_range_model['dilution_factor']['tstar'] # type: ignore

# Streamwise and radial penetration coefficients
𝛽r1 = 0.18
𝛽r2 = 0.2
𝛽x1 = 2.4
𝛽r1: float = constants.short_range_model['dilution_factor']['penetration_coefficients']['𝛽r1'] # type: ignore
𝛽r2: float = constants.short_range_model['dilution_factor']['penetration_coefficients']['𝛽r2'] # type: ignore
𝛽x1: float = constants.short_range_model['dilution_factor']['penetration_coefficients']['𝛽x1'] # type: ignore

# Parameters in the jet-like stage
# Position of virtual origin
Expand Down Expand Up @@ -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 = constants.exposure_model['repeats']

def __post_init__(self):
"""
Expand Down
2 changes: 1 addition & 1 deletion caimira/tests/test_data_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from unittest.mock import patch, MagicMock
from tornado.httpclient import HTTPError

from caimira.apps.calculator.data_service import DataService
from caimira.global_store.data_service import DataService

@dataclass
class MockResponse:
Expand Down

0 comments on commit 741046a

Please sign in to comment.