diff --git a/cara/apps/calculator/report_generator.py b/cara/apps/calculator/report_generator.py
index e0904dd4..a4fc0c36 100644
--- a/cara/apps/calculator/report_generator.py
+++ b/cara/apps/calculator/report_generator.py
@@ -1,7 +1,12 @@
+import base64
from datetime import datetime
+import io
from pathlib import Path
import jinja2
+import matplotlib
+matplotlib.use('agg')
+import matplotlib.pyplot as plt
import numpy as np
from cara import models
@@ -10,13 +15,19 @@ from .model_generator import FormData
def calculate_report_data(model: models.Model):
resolution = 600
- times = list(np.linspace(0, 10, resolution))
+
+ # TODO: Have this for exposed not infected.
+ t_start = model.infected.presence.boundaries()[0][0]
+ t_end = model.infected.presence.boundaries()[-1][1]
+
+ times = list(np.linspace(t_start, t_end, resolution))
concentrations = [model.concentration(time) for time in times]
highest_const = max(concentrations)
prob = model.infection_probability()
er = model.infected.emission_rate(0.1)
exposed_occupants = model.exposed_occupants
r0 = prob * exposed_occupants / 100
+
return {
"times": times,
"concentrations": concentrations,
@@ -25,14 +36,46 @@ def calculate_report_data(model: models.Model):
"emission_rate": er,
"exposed_occupants": exposed_occupants,
"R0": r0,
+ "scenario_plot_src": embed_figure(plot(times, concentrations)),
}
+
+def embed_figure(figure) -> str:
+ # Draw the scenario graph.
+ img_data = io.BytesIO()
+
+ figure.savefig(img_data, format='png', bbox_inches="tight")
+ plt.close()
+ img_data.seek(0)
+ pic_hash = base64.b64encode(img_data.read()).decode('ascii')
+ # A src suitable for a tag such as f'.
+ return f'data:image/png;base64,{pic_hash}'
+
+
+def plot(times, concentrations):
+ fig = plt.figure()
+ ax = fig.add_subplot(1, 1, 1)
+ ax.plot(times, concentrations)
+ ax.spines['right'].set_visible(False)
+ ax.spines['top'].set_visible(False)
+
+ ax.set_xlabel('Hours from start of event')
+ ax.set_ylabel('Concentration ($q/m^3$)')
+ ax.set_title('Concentration of infectious quanta aerosols')
+
+ # top = max([0.75, max(concentrations)])
+ # print(max(concentrations))
+ # ax.set_ylim(bottom=1e-4, top=top)
+ return fig
+
+
def build_report(model: models.Model, form: FormData):
now = datetime.now()
time = now.strftime("%d/%m/%Y %H:%M:%S")
request = {"the": "form", "request": "data"}
+
context = {
- 'model': model,
+ 'model': model,
'request': request,
'creation_date': time,
'model_version': 'Beta v1.0.0',
@@ -65,8 +108,6 @@ def build_report(model: models.Model, form: FormData):
'coffee_duration': form.coffee_duration,
'coffee_times': [['00:00','00:00'], ['00:00','00:00'], ['00:00','00:00'], ['00:00','00:00']],
'mask_wearing': form.mask_wearing,
- 'infection_probability': round(model.infection_probability(), 2),
- 'reproduction_rate': 2
}
context.update(calculate_report_data(model))
diff --git a/cara/apps/calculator/templates/report.html.j2 b/cara/apps/calculator/templates/report.html.j2
index 86a7af7e..b716814f 100644
--- a/cara/apps/calculator/templates/report.html.j2
+++ b/cara/apps/calculator/templates/report.html.j2
@@ -121,8 +121,11 @@
Results:
-In this scenario, the estimated probability of one exposed occupant getting infected P(i) is {{ infection_probability }} % and the estimated basic reproduction rate (R0) is {{ reproduction_rate }}.
+
+ In this scenario, the estimated probability of one exposed occupant getting infected P(i) is {{ "{:#.2g}".format(prob_inf) }}% and the estimated basic reproduction rate (R0) is {{ "{:#.2g}".format(R0) }}. +
Exposure graph:
+