Replacing the use of hours2timestring by datetimes, in the x-axis of the plots generated in report_generator

This commit is contained in:
Nicolas Mounet 2021-05-03 14:27:29 +00:00 committed by Philip James Elson
parent 99152f7e44
commit 26d7ef9f5d
3 changed files with 27 additions and 26 deletions

View file

@ -458,14 +458,10 @@ class FormData:
present_intervals = []
def hours2time(hours: float):
# Convert times like 14.5 to strings, like "14:30"
return f"{int(np.floor(hours)):02d}:{int(np.round((hours % 1) * 60)):02d}"
# def add_interval(start, end):
current_time = start
LOG.debug(f"starting time march at {hours2time(current_time/60)} to {hours2time(finish/60)}")
LOG.debug(f"starting time march at {_hours2timestring(current_time/60)} to {_hours2timestring(finish/60)}")
# As we step through the breaks. For each break there are 6 important cases
# we must cover. Let S=start; E=end; Bs=Break start; Be=Break end:
@ -480,8 +476,8 @@ class FormData:
if current_time >= finish:
break
LOG.debug(f"handling break {hours2time(current_break[0]/60)}-{hours2time(current_break[1]/60)} "
f" (current time: {hours2time(current_time/60)})")
LOG.debug(f"handling break {_hours2timestring(current_break[0]/60)}-{_hours2timestring(current_break[1]/60)} "
f" (current time: {_hours2timestring(current_time/60)})")
break_s, break_e = current_break
case1 = finish <= break_s
@ -494,22 +490,22 @@ class FormData:
if case1:
LOG.debug(f"case 1: interval entirely before break")
present_intervals.append((current_time / 60, finish / 60))
LOG.debug(f" + added interval {hours2time(present_intervals[-1][0])} "
f"- {hours2time(present_intervals[-1][1])}")
LOG.debug(f" + added interval {_hours2timestring(present_intervals[-1][0])} "
f"- {_hours2timestring(present_intervals[-1][1])}")
current_time = finish
elif case2:
LOG.debug(f"case 2: interval straddles start of break")
present_intervals.append((current_time / 60, break_s / 60))
LOG.debug(f" + added interval {hours2time(present_intervals[-1][0])} "
f"- {hours2time(present_intervals[-1][1])}")
LOG.debug(f" + added interval {_hours2timestring(present_intervals[-1][0])} "
f"- {_hours2timestring(present_intervals[-1][1])}")
current_time = break_e
elif case3:
LOG.debug(f"case 3: break entirely inside interval")
# We add the bit before the break, but not the bit afterwards,
# as it may hit another break.
present_intervals.append((current_time / 60, break_s / 60))
LOG.debug(f" + added interval {hours2time(present_intervals[-1][0])} "
f"- {hours2time(present_intervals[-1][1])}")
LOG.debug(f" + added interval {_hours2timestring(present_intervals[-1][0])} "
f"- {_hours2timestring(present_intervals[-1][1])}")
current_time = break_e
elif case4:
LOG.debug(f"case 4: interval entirely inside break")
@ -652,6 +648,11 @@ WINDOWS_TYPES = {'window_sliding', 'window_hinged', 'not-applicable'}
COFFEE_OPTIONS_INT = {'coffee_break_0': 0, 'coffee_break_1': 1, 'coffee_break_2': 2, 'coffee_break_4': 4}
def _hours2timestring(hours: float):
# Convert times like 14.5 to strings, like "14:30"
return f"{int(np.floor(hours)):02d}:{int(np.round((hours % 1) * 60)):02d}"
def time_string_to_minutes(time: str) -> minutes_since_midnight:
"""
Converts time from string-format to an integer number of minutes after 00:00

View file

@ -1,6 +1,6 @@
import base64
import dataclasses
from datetime import datetime
from datetime import datetime, timedelta
import io
import typing
import zlib
@ -126,18 +126,20 @@ def img2base64(img_data) -> str:
def plot(times, concentrations, model: models.ExposureModel):
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(times, concentrations, lw=2, color='#1f77b4', label='Concentration')
datetimes = [datetime(1970, 1, 1) + timedelta(hours=time) for time in times]
ax.plot(datetimes, concentrations, lw=2, color='#1f77b4', label='Concentration')
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.set_xlabel('Time (hour of day)')
ax.set_xlabel('Time of day')
ax.set_ylabel('Concentration ($q/m^3$)')
ax.set_title('Concentration of infectious quanta')
ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter("%H:%M"))
# Plot presence of exposed person
for i, (presence_start, presence_finish) in enumerate(model.exposed.presence.boundaries()):
plt.fill_between(
times, concentrations, 0,
datetimes, concentrations, 0,
where=(np.array(times) > presence_start) & (np.array(times) < presence_finish),
color="#1f77b4", alpha=0.1,
label="Presence of exposed person(s)" if i == 0 else ""
@ -240,19 +242,21 @@ def comparison_plot(scenarios: typing.Dict[str, models.ExposureModel]):
if times is None:
t_start, t_end = model_start_end(model)
times = np.linspace(t_start, t_end, resolution)
datetimes = [datetime(1970, 1, 1) + timedelta(hours=time) for time in times]
concentrations = [model.concentration_model.concentration(time) for time in times]
if name in dash_styled_scenarios:
ax.plot(times, concentrations, label=name, linestyle='--')
ax.plot(datetimes, concentrations, label=name, linestyle='--')
else:
ax.plot(times, concentrations, label=name, linestyle='-', alpha=0.5)
ax.plot(datetimes, concentrations, label=name, linestyle='-', alpha=0.5)
# Place a legend outside of the axes itself.
ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter("%H:%M"))
ax.set_xlabel('Time (hour of day)')
ax.set_xlabel('Time of day')
ax.set_ylabel('Concentration ($q/m^3$)')
ax.set_title('Concentration of infectious quanta')

View file

@ -3,6 +3,7 @@ import dataclasses
import pytest
from cara.apps.calculator import model_generator
from cara.apps.calculator.model_generator import _hours2timestring
from cara.apps.calculator.model_generator import minutes_since_midnight
from cara import models
from cara import data
@ -272,13 +273,8 @@ def time2mins(time: str) -> minutes_since_midnight:
return minutes_since_midnight(int(time.split(':')[0]) * 60 + int(time.split(':')[1]))
def hours2time(hours: float):
# Convert times like 14.5 to strings, like "14:30"
return f"{int(np.floor(hours)):02d}:{int(np.round((hours % 1) * 60)):02d}"
def assert_boundaries(interval, boundaries_in_time_string_form):
boundaries = [(hours2time(start), hours2time(end))
boundaries = [(_hours2timestring(start), _hours2timestring(end))
for start, end in interval.boundaries()]
assert boundaries == boundaries_in_time_string_form