diff --git a/caimira/apps/calculator/co2_model_generator.py b/caimira/apps/calculator/co2_model_generator.py index 51f34d25..3aa13118 100644 --- a/caimira/apps/calculator/co2_model_generator.py +++ b/caimira/apps/calculator/co2_model_generator.py @@ -100,13 +100,17 @@ class CO2FormData: return instance def build_model(self) -> models.CO2Data: + population_presence=self.population_present_interval() + last_time_present = population_presence.boundaries()[-1][-1] + last_present_time_index = next((index for index, time in enumerate(self.CO2_data['times']) + if time > last_time_present), len(self.CO2_data['times'])) return models.CO2Data( room_volume=self.room_volume, number=self.total_people, - presence=self.population_present_interval(), - ventilation_transition_times=self.ventilation_transition_times(), - times=self.CO2_data['times'], - CO2_concentrations=self.CO2_data['CO2'] + presence=population_presence, + ventilation_transition_times=self.ventilation_transition_times(last_time_present), + times=self.CO2_data['times'][:last_present_time_index], + CO2_concentrations=self.CO2_data['CO2'][:last_present_time_index], ) def _compute_breaks_in_interval(self, start, finish, n_breaks, duration) -> models.BoundarySequence_t: @@ -310,9 +314,10 @@ class CO2FormData: breaks=breaks, ) - def ventilation_transition_times(self) -> typing.Tuple[float, ...]: + def ventilation_transition_times(self, last_present_time) -> typing.Tuple[float, ...]: if self.ventilation_type == 'natural_ventilation' and self.window_opening_regime == 'windows_open_periodically': - return tuple(sorted(set(models.PeriodicInterval(self.windows_frequency, - self.windows_duration, min(self.infected_start, self.exposed_start)/60).transition_times()))) + transition_times = sorted(models.PeriodicInterval(self.windows_frequency, + self.windows_duration, min(self.infected_start, self.exposed_start)/60).transition_times()) + return tuple(filter(lambda x: x < last_present_time, transition_times)) else: - return (min(self.infected_start/60, self.exposed_start/60), max(self.infected_finish/60, self.exposed_finish/60)) # all day long + return tuple((min(self.infected_start, self.exposed_start)/60, max(self.infected_finish, self.exposed_finish)/60), ) # all day long diff --git a/caimira/apps/calculator/model_generator.py b/caimira/apps/calculator/model_generator.py index a953e4e5..230582e3 100644 --- a/caimira/apps/calculator/model_generator.py +++ b/caimira/apps/calculator/model_generator.py @@ -436,10 +436,24 @@ class FormData: def ventilation(self) -> models._VentilationBase: always_on = models.PeriodicInterval(period=120, duration=120) + periodic_interval = models.PeriodicInterval(self.windows_frequency, self.windows_duration, min(self.infected_start, self.exposed_start)/60) + + if self.CO2_data_option: + ventilations = [] + if self.ventilation_type == 'natural_ventilation' and self.window_opening_regime == 'windows_open_periodically': + for index, time in enumerate(sorted(list(periodic_interval.transition_times()))[:-1]): + if index < len(self.CO2_fitting_result['ventilation_values']): + ventilations.append(models.AirChange(active=models.SpecificInterval(present_times=((time, time + self.windows_duration/60), )), + air_exch=self.CO2_fitting_result['ventilation_values'][index])) + else: break + else: + ventilations.append(models.AirChange(active=always_on, air_exch=self.CO2_fitting_result['ventilation_values'][0])) + return models.MultipleVentilation(tuple(ventilations)) + # Initializes a ventilation instance as a window if 'natural_ventilation' is selected, or as a HEPA-filter otherwise if self.ventilation_type == 'natural_ventilation': if self.window_opening_regime == 'windows_open_periodically': - window_interval = models.PeriodicInterval(self.windows_frequency, self.windows_duration, min(self.infected_start, self.exposed_start)/60) + window_interval = periodic_interval else: window_interval = always_on @@ -521,7 +535,7 @@ class FormData: elif (self.activity_type == 'precise'): activity_defn, expiration_defn = self.generate_precise_activity_expiration() - if self.CO2_data_option: + if self.CO2_data_option: activity = mc.Activity(self.CO2_fitting_result['exhalation_rate'], self.CO2_fitting_result['exhalation_rate']) else: activity = activity_distributions[activity_defn] diff --git a/caimira/apps/calculator/static/js/co2_form.js b/caimira/apps/calculator/static/js/co2_form.js index 2a68e0b9..09e7c8c8 100644 --- a/caimira/apps/calculator/static/js/co2_form.js +++ b/caimira/apps/calculator/static/js/co2_form.js @@ -74,9 +74,9 @@ function displayJsonToHtmlTable(jsonData) { if (i < 5) { htmlData += "