diff --git a/caimira/apps/calculator/__init__.py b/caimira/apps/calculator/__init__.py
index 427cd867..a0da651b 100644
--- a/caimira/apps/calculator/__init__.py
+++ b/caimira/apps/calculator/__init__.py
@@ -18,6 +18,7 @@ import traceback
import typing
import uuid
import zlib
+import matplotlib.pyplot as plt
import jinja2
import loky
@@ -372,7 +373,15 @@ class CO2Data(BaseRequestHandler):
co2_model_generator.CO2FormData.build_model, form,
)
report = await asyncio.wrap_future(report_task)
- self.finish(dict(report.CO2_fit_params()))
+
+ def generate_image():
+ fig = plt.figure(figsize=(4, 4), dpi=110)
+ plt.plot(form.CO2_data['times'], form.CO2_data['CO2'])
+ return fig
+
+ result = dict(report.CO2_fit_params())
+ result['CO2_plot'] = img2base64(_figure2bytes(generate_image()))
+ self.finish(result)
def get_url(app_root: str, relative_path: str = '/'):
diff --git a/caimira/apps/calculator/static/js/co2_form.js b/caimira/apps/calculator/static/js/co2_form.js
new file mode 100644
index 00000000..594b7079
--- /dev/null
+++ b/caimira/apps/calculator/static/js/co2_form.js
@@ -0,0 +1,154 @@
+const CO2_data = [
+ 'CO2_data',
+ 'specific_breaks',
+ 'exposed_coffee_break_option',
+ 'exposed_coffee_duration',
+ 'exposed_finish',
+ 'exposed_lunch_finish',
+ 'exposed_lunch_option',
+ 'exposed_lunch_start',
+ 'exposed_start',
+ 'infected_coffee_break_option',
+ 'infected_coffee_duration',
+ 'infected_dont_have_breaks_with_exposed',
+ 'infected_finish',
+ 'infected_lunch_finish',
+ 'infected_lunch_option',
+ 'infected_lunch_start',
+ 'infected_people',
+ 'infected_start',
+ 'room_volume',
+ 'total_people',
+ 'windows_duration',
+ 'windows_frequency',
+]
+
+// Method to upload a valid excel file
+function upload_file() {
+ var files = document.getElementById("file_upload").files;
+ if (files.length == 0) {
+ alert("Please choose any file...");
+ return;
+ }
+ var filename = files[0].name;
+ var extension = filename.substring(filename.lastIndexOf(".")).toUpperCase();
+ if (extension == ".XLS" || extension == ".XLSX") {
+ //Here calling another method to read excel file into json
+ excelFileToJSON(files[0]);
+ } else {
+ alert("Please select a valid excel file.");
+ }
+}
+
+//Method to read excel file and convert it into JSON
+function excelFileToJSON(file) {
+ try {
+ var reader = new FileReader();
+ reader.readAsBinaryString(file);
+ reader.onload = function (e) {
+ var data = e.target.result;
+ var workbook = XLSX.read(data, { type: "binary" });
+ var result = {};
+ var firstSheetName = workbook.SheetNames[0];
+ //reading only first sheet data
+ var jsonData = XLSX.utils.sheet_to_json(workbook.Sheets[firstSheetName]);
+ //displaying the json result into HTML table
+ displayJsonToHtmlTable(jsonData);
+ };
+ } catch (e) {
+ console.error(e);
+ }
+}
+
+//Method to display the data in HTML Table
+function displayJsonToHtmlTable(jsonData) {
+ var table = document.getElementById("display_excel_data");
+ var format = document.getElementById("formatted_data");
+ let structure = { times: [], CO2: [] };
+ if (jsonData.length > 0) {
+ var htmlData = "
| Time | CO2 Value |
";
+ for (var i = 0; i < jsonData.length; i++) {
+ var row = jsonData[i];
+ htmlData +=
+ "| " +
+ Math.round(row["Times"] * 10) / 10 +
+ " | " +
+ Math.round(row["CO2"] * 10) / 10 +
+ " |
";
+ structure["times"].push(row["Times"]);
+ structure["CO2"].push(row["CO2"]);
+ }
+ table.innerHTML = htmlData;
+ console.log(structure);
+ format.value = JSON.stringify(structure);
+ } else {
+ table.innerHTML = "There is no data in Excel";
+ }
+}
+
+function insertErrorFor(referenceNode, text) {
+ var element = document.createElement("span");
+ element.setAttribute("class", "error_text");
+ element.classList.add("red_text");
+ element.innerHTML = " " + text;
+ $(referenceNode).before(element);
+}
+
+function validate() {
+ $('span.' + "error_text").remove();
+ let submit = true;
+ for (var i = 0; i < CO2_data.length; i++) {
+ let element = $(`[name=${CO2_data[i]}]`);
+ if (element[0].value === '') {
+ insertErrorFor($('#CO2_input_data_div'), `'${element[0].name}' must be defined.`); // raise error for total number and room volume.
+ submit = false;
+ };
+ }
+ return submit;
+}
+
+function submit_fitting_algorithm(url) {
+ if (validate()) {
+ let CO2_mapping = {};
+ CO2_data.map(el => {
+ let element = $(`[name=${el}]`);
+ // Validate radio buttons
+ if (element.length != 1) CO2_mapping[element[0].name] = $(`[name=${element[0].name}]:checked`)[0].value
+ else CO2_mapping[element[0].name] = element[0].value;
+ })
+ $('#CO2_input_data_div').show();
+ $("#generate_fitting_data").html(
+ `Loading...`
+ );
+ $('#CO2_input_data').html(JSON.stringify(CO2_mapping, null, "\t"))
+ fetch(url, {
+ method: "POST",
+ body: JSON.stringify(CO2_mapping),
+ })
+ .then((response) => response.json())
+ .then((json_response) => {
+ console.log(json_response)
+ $("#DIV_CO2_fitting_result").show();
+ $("#CO2_fitting_result").val(JSON.stringify(json_response));
+ $("#exhalation_rate_fit").html(String(json_response['exhalation_rate']));
+ // $("#ventilation_rate_fit").html(json_response['ventilation_values']);
+ $("#CO2_data_plot").attr("src", json_response['CO2_plot']);
+ $("#generate_fitting_data").html('Fit data');
+ $("#save_and_dismiss_dialog").show();
+ });
+ }
+}
+
+function clear_fitting_algorithm() {
+ $("#display_excel_data tbody").remove();
+ $('#CO2_fitting_result').val('');
+ $('#formatted_data').val('');
+ $('span.' + "error_text").remove();
+ $('#DIV_CO2_fitting_result').hide();
+ $('#CO2_input_data_div').hide();
+ $('#CO2_data_no').click();
+}
+
+function dismiss_co2_dialog() {
+ $('#CO2_data_no').click();
+}
\ No newline at end of file
diff --git a/caimira/apps/templates/base/calculator.form.html.j2 b/caimira/apps/templates/base/calculator.form.html.j2
index 83b30069..3b5cb371 100644
--- a/caimira/apps/templates/base/calculator.form.html.j2
+++ b/caimira/apps/templates/base/calculator.form.html.j2
@@ -12,6 +12,7 @@
{% block body_scripts %}
+
{% endblock body_scripts %}
@@ -191,23 +192,6 @@
?
-
-
-
-
-
-
Ventilation type:
@@ -676,11 +660,62 @@
- Coffee breaks are spread evenly throughout the day.
+ Coffee breaks are spread evenly throughout the day.
+
+
+
+
+
+
+
+
+
+
+
Upload an excel file to display in HTML Table
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+ {#
#}
+
+
+
+
+
+
+
-
diff --git a/caimira/apps/templates/base/calculator.report.html.j2 b/caimira/apps/templates/base/calculator.report.html.j2
index fada1175..08a4596f 100644
--- a/caimira/apps/templates/base/calculator.report.html.j2
+++ b/caimira/apps/templates/base/calculator.report.html.j2
@@ -181,9 +181,6 @@
let short_range_expirations = {{ short_range_expirations | JSONify }};
draw_plot("concentration_plot");
-

-
Emission rate = {{ ex }}
-
Ventilation = {{ airs }}