import numpy as np import pytest from retry import retry import caimira.monte_carlo as mc from caimira import models from caimira.dataclass_utils import nested_replace from caimira.apps.calculator import report_generator from caimira.monte_carlo.data import activity_distributions, virus_distributions, expiration_distributions @pytest.fixture def baseline_exposure_model(): concentration_mc = mc.ConcentrationModel( room=models.Room(volume=50, inside_temp=models.PiecewiseConstant((0., 24.), (298,)), humidity=0.5), ventilation=models.MultipleVentilation( ventilations=( models.AirChange(active=models.PeriodicInterval(period=120, duration=120), air_exch=0.25), ) ), infected=mc.InfectedPopulation( number=1, presence=mc.SpecificInterval(present_times=((0, 3.5), (4.5, 9))), virus=virus_distributions['SARS_CoV_2_DELTA'], mask=models.Mask.types['No mask'], activity=activity_distributions['Seated'], expiration=expiration_distributions['Breathing'], host_immunity=0., ), evaporation_factor=0.3, ) return mc.ExposureModel( concentration_model=concentration_mc, short_range=(), exposed=mc.Population( number=3, presence=mc.SpecificInterval(present_times=((0, 3.5), (4.5, 9))), activity=activity_distributions['Seated'], mask=models.Mask.types['No mask'], host_immunity=0., ), geographical_data=models.Cases(), ) @retry(tries=10) def test_conditional_prob_inf_given_vl_dist(baseline_exposure_model): viral_loads = np.array([3., 5., 7., 9.,]) mc_model: models.ExposureModel = baseline_exposure_model.build_model(1_000_000) expected_pi_means = [] expected_lower_percentiles = [] expected_upper_percentiles = [] for vl in viral_loads: model_vl: models.ExposureModel = nested_replace( mc_model, { 'concentration_model.infected.virus.viral_load_in_sputum' : 10**vl, } ) pi = model_vl.infection_probability()/100 expected_pi_means.append(np.mean(pi)) expected_lower_percentiles.append(np.quantile(pi, 0.05)) expected_upper_percentiles.append(np.quantile(pi, 0.95)) infection_probability = mc_model.infection_probability() / 100 specific_vl = np.log10(mc_model.concentration_model.infected.virus.viral_load_in_sputum) step = (max(viral_loads) - min(viral_loads))/100 actual_pi_means, actual_lower_percentiles, actual_upper_percentiles = ( report_generator.conditional_prob_inf_given_vl_dist(infection_probability, viral_loads, specific_vl, step) ) assert np.allclose(actual_pi_means, expected_pi_means, rtol=0.1) assert np.allclose(actual_lower_percentiles, expected_lower_percentiles, rtol=0.1) assert np.allclose(actual_upper_percentiles, expected_upper_percentiles, rtol=0.1)