diff --git a/cara/apps/calculator/model_generator.py b/cara/apps/calculator/model_generator.py index 06c29229..39edb387 100644 --- a/cara/apps/calculator/model_generator.py +++ b/cara/apps/calculator/model_generator.py @@ -246,7 +246,8 @@ class FormData: ventilation=self.ventilation(), infected=self.infected_population(), ), - exposed=self.exposed_population() + exposed=self.exposed_population(), + fraction_deposited=self. ) def build_model(self, sample_size=_DEFAULT_MC_SAMPLE_SIZE) -> models.ExposureModel: diff --git a/cara/model_scenarios_paper.py b/cara/model_scenarios_paper.py index ea717244..2ff79e9e 100644 --- a/cara/model_scenarios_paper.py +++ b/cara/model_scenarios_paper.py @@ -486,4 +486,100 @@ def shouting_heavy_exercise_exposure(): mask=models.Mask.types["No mask"], ), ) + return exposure_mc + +########## Concentration curves ########### +def classroom_no_mask_windows_closed_exposure(): + exposure_mc = mc.ExposureModel( + concentration_model=mc.ConcentrationModel( + room=models.Room(volume=100, humidity=0.5), + ventilation=models.AirChange( + active=models.SpecificInterval(((0, 24),)), + air_exch=0.25, + ), + infected=mc.InfectedPopulation( + number=1, + virus=mc.SARSCoV2( + viral_load_in_sputum=symptomatic_vl_frequencies, + infectious_dose=infectious_dose_distribution, + viable_to_RNA=infectious_virus_distribution, + ), + presence=models.SpecificInterval(((0, 1.5), (2, 3.5), (4.5, 6), (6.5, 8))), + mask=models.Mask.types["No mask"], + activity=activity_distributions['Light activity'], + expiration=models.Expiration.types['Talking'], + ), + ), + exposed=mc.Population( + number=14, + presence=models.SpecificInterval(((0, 1.5), (2, 3.5), (4.5, 6), (6.5, 8))), + activity=models.Activity.types['Seated'], + mask=models.Mask.types["No mask"], + ), + ) + return exposure_mc + +def classrom_no_mask_windows_open_breaks(): + exposure_mc = mc.ExposureModel( + concentration_model=mc.ConcentrationModel( + room=models.Room(volume=100, humidity=0.5), + ventilation=models.SlidingWindow( + active=models.SpecificInterval(((1.5, 2), (3.5, 4.5), (6, 6.5))), + inside_temp=models.PiecewiseConstant((0, 24), (295,)), + outside_temp=models.PiecewiseConstant((0, 24), (291,)), + window_height=1.6, + opening_length=0.6, + ), + infected=mc.InfectedPopulation( + number=1, + virus=mc.SARSCoV2( + viral_load_in_sputum=symptomatic_vl_frequencies, + infectious_dose=infectious_dose_distribution, + viable_to_RNA=infectious_virus_distribution, + ), + presence=models.SpecificInterval(((0, 1.5), (2, 3.5), (4.5, 6), (6.5, 8))), + mask=models.Mask.types["No mask"], + activity=activity_distributions['Light activity'], + expiration=models.Expiration.types['Talking'], + ), + ), + exposed=mc.Population( + number=14, + presence=models.SpecificInterval(((0, 1.5), (2, 3.5), (4.5, 6), (6.5, 8))), + activity=models.Activity.types['Seated'], + mask=models.Mask.types["No mask"], + ), + ) + return exposure_mc + +def classrom_no_mask_windows_open_alltimes(): + exposure_mc = mc.ExposureModel( + concentration_model=mc.ConcentrationModel( + room=models.Room(volume=100, humidity=0.5), + ventilation=models.SlidingWindow( + active=models.PeriodicInterval(period=120, duration=120), + inside_temp=models.PiecewiseConstant((0, 24), (295,)), + outside_temp=models.PiecewiseConstant((0, 24), (291,)), + window_height=1.6, opening_length=0.6, + ), + infected=mc.InfectedPopulation( + number=1, + virus=mc.SARSCoV2( + viral_load_in_sputum=symptomatic_vl_frequencies, + infectious_dose=infectious_dose_distribution, + viable_to_RNA=infectious_virus_distribution, + ), + presence=models.SpecificInterval(((0, 1.5), (2, 3.5), (4.5, 6), (6.5, 8))), + mask=models.Mask.types["No mask"], + activity=activity_distributions['Light activity'], + expiration=models.Expiration.types['Talking'], + ), + ), + exposed=mc.Population( + number=14, + presence=models.SpecificInterval(((0, 1.5), (2, 3.5), (4.5, 6), (6.5, 8))), + activity=models.Activity.types['Seated'], + mask=models.Mask.types["No mask"], + ), + ) return exposure_mc \ No newline at end of file diff --git a/cara/plot_output.py b/cara/plot_output.py index 8797554c..9d6002a0 100644 --- a/cara/plot_output.py +++ b/cara/plot_output.py @@ -13,25 +13,25 @@ from itertools import product from dataclasses import dataclass # Exhaled virions while talking, seated # -print('\n<<<<<<<<<<< Vlout for Talking, seated >>>>>>>>>>>') +#print('\n<<<<<<<<<<< Vlout for Talking, seated >>>>>>>>>>>') #exposure_model_from_vl_talking() # Exhaled virions while breathing, seated # -print('\n<<<<<<<<<<< Vlout for Breathing, seated >>>>>>>>>>>') +#print('\n<<<<<<<<<<< Vlout for Breathing, seated >>>>>>>>>>>') #exposure_model_from_vl_breathing() # Exhaled virions while breathing, light activity # -print('\n<<<<<<<<<<< Vlout for Shouting, light activity >>>>>>>>>>>') +#print('\n<<<<<<<<<<< Vlout for Shouting, light activity >>>>>>>>>>>') #exposure_model_from_vl_shouting() # Exhaled virions while talking according to BLO model, seated # -print('\n<<<<<<<<<<< Vlout for Talking, seated with chosen Cn,L >>>>>>>>>>>') +#print('\n<<<<<<<<<<< Vlout for Talking, seated with chosen Cn,L >>>>>>>>>>>') #exposure_model_from_vl_talking_cn() # Exhaled virions while breathing according to BLO model, seated # -print('\n<<<<<<<<<<< Vlout for Breathing, seated with chosen Cn,B >>>>>>>>>>>') +#print('\n<<<<<<<<<<< Vlout for Breathing, seated with chosen Cn,B >>>>>>>>>>>') #exposure_model_from_vl_breathing_cn() -print('\n') +#print('\n') ############ Plots with viral loads and emission rates + statistical data ############ #present_vl_er_histograms(activity='Seated', mask='No mask') @@ -42,8 +42,20 @@ print('\n') #generate_cdf_curves() ############ Deposition Fraction Graph ############ -print('\n<<<<<<<<<<< Deposition Fraction for Breathing, seated >>>>>>>>>>>') -calculate_deposition_factor() +#print('\n<<<<<<<<<<< Deposition Fraction for Breathing, seated >>>>>>>>>>>') +#calculate_deposition_factor() + +############ Comparison between concentration curves ############ +# compare_concentration_curves_virus([classroom_model_IGH_no_mask_windows_closed[0],classroom_model_IGH_no_mask_windows_open_breaks[0], +# classroom_model_IGH_no_mask_windows_open_alltimes[0]], +# labels=['Windows closed', 'Window open during breaks', 'Window open at all times'], +# colors=['tomato', 'lightskyblue', 'limegreen', '#1f77b4', 'seagreen', 'lightskyblue', 'deepskyblue'], +# title='No mask - Spring/Summer period' +# ) +# print_qd_info(classroom_model_IGH_no_mask_windows_closed[0]) +# print_qd_info(classroom_model_IGH_no_mask_windows_open_breaks[0]) +# print_qd_info(classroom_model_IGH_no_mask_windows_open_alltimes[0]) +compare_concentration_curves() ############ Used for testing ############ #exposure_model_from_vl_talking_new_points() diff --git a/cara/results_paper.py b/cara/results_paper.py index 0658940c..b7a63724 100644 --- a/cara/results_paper.py +++ b/cara/results_paper.py @@ -469,8 +469,7 @@ def generate_cdf_curves(): fig.set_figwidth(5) plt.show() -############ Deposition Fraction Graph ############ -# +############ Deposition Fraction Graph ############# def calculate_deposition_factor(): fig = plt.figure() @@ -526,6 +525,54 @@ def calculate_deposition_factor(): plt.tight_layout() plt.show() +############ Compare concentration curves ############ +def compare_concentration_curves(): + + exp_models=[classroom_no_mask_windows_closed_exposure().build_model(size=SAMPLE_SIZE), + classrom_no_mask_windows_open_breaks().build_model(size=SAMPLE_SIZE), + classrom_no_mask_windows_open_alltimes().build_model(size=SAMPLE_SIZE)] + + labels=['Windows closed', 'Window open during breaks', 'Window open at all times'] + colors=['tomato', 'lightskyblue', 'limegreen', '#1f77b4', 'seagreen', 'lightskyblue', 'deepskyblue'] + + start=min(min(model.concentration_model.infected.presence.transition_times()) for model in exp_models) + stop=max(max(model.concentration_model.infected.presence.transition_times()) for model in exp_models) + + TIMESTEP = 0.01 + times=np.arange(start, stop, TIMESTEP) + + concentrations = [[np.mean(model.concentration_model.concentration(t)) for t in times] for model in exp_models] + fig, ax = plt.subplots() + for c, label, color in zip(concentrations, labels, colors): + ax.plot(times, c, label=label, color=color) + + ax.legend(loc='upper left') + ax.set_ylim(ax.get_ylim()[0], ax.get_ylim()[1] * 1.2) + ax.spines["right"].set_visible(False) + + # When merged, use the integrated_concentration function. + factors = [0.6 * model.exposed.activity.inhalation_rate * (1 - model.exposed.mask.η_inhale) for model in exp_models] + present_indexes = np.array([exp_models[0].exposed.person_present(t) for t in times]) + modified_concentrations = [np.array(c) for c in concentrations] + for mc in modified_concentrations: + mc[~present_indexes] = 0 + + cumulative_doses = [[np.trapz(c[:i + 1], times[:i + 1]) * factor for i in range(len(times))] + for c, factor in zip(modified_concentrations, factors)] + + plt.xlabel("Exposure time ($h$)", fontsize=14) + plt.ylabel("Mean viral concentration\n(virion m$^{-3}$)", fontsize=14) + + ax1 = ax.twinx() + for qd, label, color in zip(cumulative_doses, labels, colors): + ax1.plot(times, qd, label='qD - ' + label, color=color, linestyle='dotted') + ax1.spines["right"].set_linestyle("--") + ax1.spines["right"].set_linestyle((0,(1,5))) + ax1.set_ylabel('Mean cumulative dose\n(virion)', fontsize=14) + ax1.set_ylim(ax1.get_ylim()[0], ax1.get_ylim()[1] * 1.2) + + plt.show() + ######### Auxiliar functions ######### def get_enclosure_points(x_coordinates, y_coordinates): @@ -647,8 +694,6 @@ def build_breathing_legend(fig): def print_er_info(er: np.array, log_er: np.array): """ Prints statistical parameters of a given distribution of ER-values - :param er: A numpy-array of the ER-values - :return: Nothing, parameters are printed """ print(f"MEAN of ER = {np.mean(er)}\n" f"MEAN of log ER = {np.mean(log_er)}\n" @@ -661,3 +706,6 @@ def print_er_info(er: np.array, log_er: np.array): print(f"ER_{quantile} = {np.quantile(er, quantile)}") return + + +