Merge branch 'develop/calculator_inf_vs_exp_times' into 'master'

Disentangle infected and exposed presence times in model_generator

See merge request cara/cara!87
This commit is contained in:
Philip James Elson 2020-11-13 14:07:08 +00:00
commit 8c3bd0dad8
3 changed files with 31 additions and 11 deletions

View file

@ -172,7 +172,7 @@ class FormData:
coffee_times.append((start, end))
return tuple(coffee_times)
def present_interval(self) -> models.Interval:
def present_interval(self, start, finish) -> models.Interval:
leave_times = []
enter_times = []
if self.lunch_option:
@ -193,19 +193,19 @@ class FormData:
# representing the infected person entering and leaving the room. Note that if one of the evenly spaced coffee-
# breaks happens to coincide with the lunch-break, it is simply ignored.
present_intervals = []
time = self.infected_start
time = start
is_present = True
while time < self.infected_finish:
while time < finish:
if is_present:
if not leave_times:
present_intervals.append((time / 60, self.infected_finish / 60))
present_intervals.append((time / 60, finish / 60))
break
if leave_times[-1] <= time:
leave_times.pop()
else:
new_time = leave_times.pop()
present_intervals.append((time / 60, min(new_time, self.infected_finish) / 60))
present_intervals.append((time / 60, min(new_time, finish) / 60))
is_present = False
time = new_time
@ -221,6 +221,12 @@ class FormData:
return models.SpecificInterval(tuple(present_intervals))
def infected_present_interval(self) -> models.Interval:
return self.present_interval(self.infected_start, self.infected_finish)
def exposed_present_interval(self) -> models.Interval:
return self.present_interval(self.activity_start, self.activity_finish)
def model_from_form(form: FormData) -> models.ExposureModel:
# Initializes room with volume either given directly or as product of area and height
@ -262,7 +268,7 @@ def model_from_form(form: FormData) -> models.ExposureModel:
infected=models.InfectedPopulation(
number=infected_occupants,
virus=virus,
presence=form.present_interval(),
presence=form.infected_present_interval(),
mask=mask,
activity=infected_activity,
expiration=infected_expiration
@ -270,7 +276,7 @@ def model_from_form(form: FormData) -> models.ExposureModel:
),
exposed=models.Population(
number=exposed_occupants,
presence=form.present_interval(),
presence=form.exposed_present_interval(),
activity=exposed_activity,
mask=mask,
)

View file

@ -24,8 +24,10 @@ class RepeatEvents:
def calculate_report_data(model: models.ExposureModel):
resolution = 600
t_start = model.exposed.presence.boundaries()[0][0]
t_end = model.exposed.presence.boundaries()[-1][1]
t_start = min(model.exposed.presence.boundaries()[0][0],
model.concentration_model.infected.presence.boundaries()[0][0])
t_end = max(model.exposed.presence.boundaries()[-1][1],
model.concentration_model.infected.presence.boundaries()[-1][1])
times = list(np.linspace(t_start, t_end, resolution))
concentrations = [model.concentration_model.concentration(time) for time in times]

View file

@ -98,7 +98,7 @@ def test_ventilation_window_hepa(baseline_form):
[baseline_form.ventilation().air_exchange(room, t) for t in ts])
def test_present_intervals(baseline_form):
def test_infected_present_intervals(baseline_form):
baseline_form.coffee_duration = 15
baseline_form.coffee_breaks = 2
baseline_form.activity_start = 9 * 60
@ -108,9 +108,21 @@ def test_present_intervals(baseline_form):
baseline_form.infected_start = 10 * 60
baseline_form.infected_finish = 15 * 60
correct = ((10, 11), (11.25, 12.5), (13.5, 15.0))
assert baseline_form.present_interval().present_times == correct
assert baseline_form.infected_present_interval().present_times == correct
def test_exposed_present_intervals(baseline_form):
baseline_form.coffee_duration = 15
baseline_form.coffee_breaks = 2
baseline_form.activity_start = 9 * 60
baseline_form.activity_finish = 17 * 60
baseline_form.lunch_start = 12 * 60 + 30
baseline_form.lunch_finish = 13 * 60 + 30
baseline_form.infected_start = 10 * 60
baseline_form.infected_finish = 15 * 60
correct = ((9, 11), (11.25, 12.5), (13.5, 15), (15.25, 17.0))
assert baseline_form.exposed_present_interval().present_times == correct
def test_key_validation(baseline_form_data):
baseline_form_data['activity_type'] = 'invalid key'
with pytest.raises(ValueError):