Skip to content

Commit ebde0e1

Browse files
committed
extracted CO2 logic to a dedicated route
1 parent 41ea92c commit ebde0e1

16 files changed

+692
-682
lines changed

README.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ python -m cern_caimira.apps.calculator
109109
To run with a specific template theme created:
110110

111111
```
112-
python -m cern_caimira.apps.calculator --theme=ui/apps/templates/{theme}
112+
python -m cern_caimira.apps.calculator --theme=cern_caimira/src/cern_caimira/apps/templates/{theme}
113113
```
114114

115115
To run the entire app in a different `APPLICATION_ROOT` path:
@@ -168,9 +168,11 @@ Running with Visual Studio Code (VSCode):
168168

169169
### Running the tests
170170

171+
Make sure you are in the root directory of the project. Then:
172+
171173
```
172-
pip install -e .[test]
173-
pytest ./caimira
174+
pip install -e .[test]
175+
python -m pytest
174176
```
175177

176178
### Running the profiler

caimira/src/caimira/api/app.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,25 @@
88
from tornado.options import define, options
99
import logging
1010

11-
from caimira.api.routes.report_routes import ReportHandler
11+
from caimira.api.routes.report_routes import VirusReportHandler, CO2ReportHandler
1212

1313
define("port", default=8088, help="Port to listen on", type=int)
1414

1515
logging.basicConfig(format="%(message)s", level=logging.INFO)
1616

17+
1718
class Application(tornado.web.Application):
1819
def __init__(self):
1920
handlers = [
20-
(r"/report", ReportHandler),
21+
(r"/co2_report", CO2ReportHandler),
22+
(r"/virus_report", VirusReportHandler),
2123
]
2224
settings = dict(
2325
debug=True,
2426
)
2527
super(Application, self).__init__(handlers, **settings)
2628

29+
2730
if __name__ == "__main__":
2831
app = Application()
2932
app.listen(options.port)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from caimira.calculator.validators.co2.co2_validator import CO2FormData
2+
from caimira.calculator.store.data_registry import DataRegistry
3+
4+
5+
def generate_form_obj(form_data, data_registry):
6+
return CO2FormData.from_dict(form_data=form_data, data_registry=data_registry)
7+
8+
9+
def generate_model(form_obj, data_registry):
10+
sample_size = data_registry.monte_carlo['sample_size']
11+
return form_obj.build_model(sample_size=sample_size)
12+
13+
14+
def generate_report(model):
15+
return dict(model.CO2_fit_params())
16+
17+
18+
def submit_CO2_form(form_data):
19+
data_registry = DataRegistry()
20+
21+
form_obj = generate_form_obj(
22+
form_data=form_data, data_registry=data_registry)
23+
model = generate_model(form_obj=form_obj, data_registry=data_registry)
24+
report_data = generate_report(model=model)
25+
26+
return report_data

caimira/src/caimira/api/controller/report_controller.py

-30
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import concurrent.futures
2+
import functools
3+
4+
from caimira.calculator.validators.virus.virus_validator import VirusFormData
5+
from caimira.calculator.store.data_registry import DataRegistry
6+
import caimira.calculator.report.virus_report_data as rg
7+
8+
9+
def generate_form_obj(form_data, data_registry):
10+
return VirusFormData.from_dict(
11+
form_data=form_data,
12+
data_registry=data_registry,
13+
)
14+
15+
16+
def generate_model(form_obj, data_registry):
17+
sample_size = data_registry.monte_carlo['sample_size']
18+
return form_obj.build_model(sample_size=sample_size)
19+
20+
21+
def generate_report_results(form_obj, model):
22+
return rg.calculate_report_data(
23+
form=form_obj,
24+
model=model,
25+
executor_factory=functools.partial(
26+
concurrent.futures.ThreadPoolExecutor, None, # TODO define report_parallelism
27+
),
28+
)
29+
30+
31+
def submit_virus_form(form_data):
32+
data_registry = DataRegistry
33+
34+
form_obj = generate_form_obj(form_data=form_data, data_registry=data_registry)
35+
model = generate_model(form_obj=form_obj, data_registry=data_registry)
36+
report_data = generate_report_results(form_obj=form_obj, model=model)
37+
38+
return report_data

caimira/src/caimira/api/routes/report_routes.py

+35-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
11
import json
22
import traceback
33
import tornado.web
4+
import sys
45

5-
from caimira.api.controller.report_controller import submit_virus_form
6+
from caimira.api.controller.virus_report_controller import submit_virus_form
7+
from caimira.api.controller.co2_report_controller import submit_CO2_form
68

7-
class ReportHandler(tornado.web.RequestHandler):
9+
10+
class BaseReportHandler(tornado.web.RedirectHandler):
811
def set_default_headers(self):
912
self.set_header("Access-Control-Allow-Origin", "*")
1013
self.set_header("Access-Control-Allow-Headers", "x-requested-with")
1114
self.set_header("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
1215

16+
def write_error(self, status_code, **kwargs):
17+
self.set_status(status_code)
18+
self.write({"message": kwargs.get('exc_info')[1].__str__()})
19+
20+
21+
class VirusReportHandler(BaseReportHandler):
1322
def post(self):
1423
try:
1524
form_data = json.loads(self.request.body)
@@ -24,5 +33,27 @@ def post(self):
2433
self.write(response_data)
2534
except Exception as e:
2635
traceback.print_exc()
27-
self.set_status(400)
28-
self.write({"message": str(e)})
36+
self.write_error(status_code=400, exc_info=sys.exc_info())
37+
38+
39+
class CO2ReportHandler(tornado.web.RequestHandler):
40+
def set_default_headers(self):
41+
self.set_header("Access-Control-Allow-Origin", "*")
42+
self.set_header("Access-Control-Allow-Headers", "x-requested-with")
43+
self.set_header("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
44+
45+
def post(self):
46+
try:
47+
form_data = json.loads(self.request.body)
48+
report_data = submit_CO2_form(form_data)
49+
50+
response_data = {
51+
"status": "success",
52+
"message": "Results generated successfully",
53+
"report_data": report_data,
54+
}
55+
56+
self.write(response_data)
57+
except Exception as e:
58+
traceback.print_exc()
59+
self.write_error(status_code=400, exc_info=sys.exc_info())
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from caimira.calculator.validators.co2.co2_validator import CO2FormData
2+
from caimira.calculator.models.models import CO2DataModel
3+
4+
5+
def build_initial_plot(
6+
form: CO2FormData,
7+
) -> dict:
8+
'''
9+
Initial plot with the suggested ventilation state changes.
10+
This method receives the form input and returns the CO2
11+
plot with the respective transition times.
12+
'''
13+
CO2model: CO2DataModel = form.build_model()
14+
15+
occupancy_transition_times = list(CO2model.occupancy.transition_times)
16+
17+
ventilation_transition_times: list = form.find_change_points()
18+
# The entire ventilation changes consider the initial and final occupancy state change
19+
all_vent_transition_times: list = sorted(
20+
[occupancy_transition_times[0]] +
21+
[occupancy_transition_times[-1]] +
22+
ventilation_transition_times)
23+
24+
ventilation_plot: str = form.generate_ventilation_plot(
25+
ventilation_transition_times=all_vent_transition_times,
26+
occupancy_transition_times=occupancy_transition_times
27+
)
28+
29+
context = {
30+
'CO2_plot': ventilation_plot,
31+
'transition_times': [round(el, 2) for el in all_vent_transition_times],
32+
}
33+
34+
return context
35+
36+
37+
def build_fitting_results(
38+
form: CO2FormData,
39+
) -> dict:
40+
'''
41+
Final fitting results with the respective predictive CO2.
42+
This method receives the form input and returns the fitting results
43+
along with the CO2 plot with the predictive CO2.
44+
'''
45+
CO2model: CO2DataModel = form.build_model()
46+
47+
# Ventilation times after user manipulation from the suggested ventilation state change times.
48+
ventilation_transition_times = list(CO2model.ventilation_transition_times)
49+
50+
# The result of the following method is a dict with the results of the fitting
51+
# algorithm, namely the breathing rate and ACH values. It also returns the
52+
# predictive CO2 result based on the fitting results.
53+
context = dict(CO2model.CO2_fit_params())
54+
55+
# Add the transition times and CO2 plot to the results.
56+
context['transition_times'] = ventilation_transition_times
57+
context['CO2_plot'] = form.generate_ventilation_plot(ventilation_transition_times=ventilation_transition_times[:-1],
58+
predictive_CO2=context['predictive_CO2'])
59+
60+
return context

caimira/src/caimira/calculator/report/co2_report_generator.py

-1
This file was deleted.

0 commit comments

Comments
 (0)