diff --git a/cara/apps/calculator/model_generator.py b/cara/apps/calculator/model_generator.py index 06c29229..aa161dbc 100644 --- a/cara/apps/calculator/model_generator.py +++ b/cara/apps/calculator/model_generator.py @@ -303,7 +303,7 @@ class FormData: # 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) + window_interval = models.PeriodicInterval(self.windows_frequency, self.windows_duration, min(self.infected_start, self.exposed_start)) else: window_interval = always_on diff --git a/cara/models.py b/cara/models.py index 272b6b47..012e453e 100644 --- a/cara/models.py +++ b/cara/models.py @@ -123,11 +123,14 @@ class PeriodicInterval(Interval): #: occurring, a value of 0 signifies that the event never happens. duration: float + #: Time at which the first person (infected or exposed) arrives at the enclosed space. + start: float = 0.0 + def boundaries(self) -> BoundarySequence_t: if self.period == 0 or self.duration == 0: return tuple() result = [] - for i in np.arange(0, 24, self.period / 60): + for i in np.arange(self.start, 24, self.period / 60): # NOTE: It is important that the time type is float, not np.float, in # order to allow hashability (for caching). result.append((float(i), float(i+self.duration/60))) diff --git a/cara/tests/apps/calculator/test_model_generator.py b/cara/tests/apps/calculator/test_model_generator.py index 6ee821c0..dd635946 100644 --- a/cara/tests/apps/calculator/test_model_generator.py +++ b/cara/tests/apps/calculator/test_model_generator.py @@ -48,7 +48,7 @@ def test_ventilation_slidingwindow(baseline_form: model_generator.FormData): assert isinstance(baseline_window, models.SlidingWindow) window = models.SlidingWindow( - active=models.PeriodicInterval(period=120, duration=10), + active=models.PeriodicInterval(period=120, duration=10, start=minutes_since_midnight(9 * 60)), inside_temp=models.PiecewiseConstant((0, 24), (293,)), outside_temp=baseline_window.outside_temp, window_height=1.6, opening_length=0.6, @@ -80,7 +80,7 @@ def test_ventilation_hingedwindow(baseline_form: model_generator.FormData): assert isinstance(baseline_window, models.HingedWindow) window = models.HingedWindow( - active=models.PeriodicInterval(period=120, duration=10), + active=models.PeriodicInterval(period=120, duration=10, start=minutes_since_midnight(9 * 60)), inside_temp=models.PiecewiseConstant((0, 24), (293,)), outside_temp=baseline_window.outside_temp, window_height=1.6, window_width=1., opening_length=0.6, @@ -141,7 +141,7 @@ def test_ventilation_window_hepa(baseline_form: model_generator.FormData): # Now build the equivalent ventilation instance directly, and compare. window = models.SlidingWindow( - active=models.PeriodicInterval(period=120, duration=10), + active=models.PeriodicInterval(period=120, duration=10, start=minutes_since_midnight(9 * 60)), inside_temp=models.PiecewiseConstant((0, 24), (293,)), outside_temp=baseline_window.outside_temp, window_height=1.6, opening_length=0.6,