Skip to content

Commit

Permalink
added tests for all the different scenarios
Browse files Browse the repository at this point in the history
  • Loading branch information
lrdossan committed Aug 29, 2024
1 parent 41bdeca commit 75ef982
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 18 deletions.
9 changes: 8 additions & 1 deletion caimira/apps/calculator/co2_model_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ def find_change_points(self) -> list:
"""
Perform change point detection using scipy library (find_peaks method) with rolling average of data.
Incorporate existing state change candidates and adjust the result accordingly.
Returns a list of the detected ventilation state changes.
Returns a list of the detected ventilation state changes, discarding any contribution
of occupancy state changes.
"""
times: list = self.CO2_data['times']
CO2_values: list = self.CO2_data['CO2']
Expand Down Expand Up @@ -169,6 +170,12 @@ def population_present_changes(self, infected_presence: models.Interval, exposed
return sorted(state_change_times)

def ventilation_transition_times(self) -> typing.List[float]:
'''
Check if the last time from the input data is
included in the ventilation ventilations state.
Given that the last time is a required state change,
if not included, this method adds it.
'''
vent_states = self.fitting_ventilation_states
last_time_from_input = self.CO2_data['times'][-1]
if (vent_states and last_time_from_input != vent_states[-1]): # The last time value is always needed for the last ACH interval.
Expand Down
57 changes: 40 additions & 17 deletions caimira/tests/models/test_co2_concentration_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,40 +47,62 @@ def test_integrated_concentration(simple_co2_conc_model):


@pytest.mark.parametrize(
"scenario_data, room_volume, total_people, start, finish, state_changes", [
["office_scenario_1_sensor_data", 102, 4, "14:00", "17:30", (14.78, 15.10, 15.53, 15.87, 16.52, 16.83)],
["office_scenario_2_sensor_data", 60, 2, "08:38", "17:30", (10.17, 12.45, 14.50)], # Second should be 12.87
"scenario_data, room_volume, max_total_people, start, finish, state_changes", [
["office_scenario_1_sensor_data", 102, 4, "14:00", "17:30", (14.78, 15.1, 15.53, 15.87, 16.52, 16.83)],
["office_scenario_2_sensor_data", 60, 2, "08:38", "17:30", (10.17, 12.45, 14.5)], # Second should be 12.87
["meeting_scenario_1_sensor_data", 83, 3, "09:04", "11:45", (10.37, 11.07)],
["meeting_scenario_2_sensor_data", 83, 4, "13:40", "16:40", (14.37, 14.70, 14.98, 15.33, 15.68, 16.02)]
["meeting_scenario_2_sensor_data", 83, 4, "13:40", "16:40", (14.37, 14.72, 15, 15.33, 15.68, 16.03)]
]
)
def test_find_change_points(scenario_data, room_volume, total_people, start, finish, state_changes, request):
def test_find_change_points(scenario_data, room_volume, max_total_people, start, finish, state_changes, request):
'''
Specific test of the find_change_points method using the
scipy find_peaks and specific smoothing techniques. Only
the ventilation state changes are target for detection.
'''
CO2_form_model: CO2FormData = CO2FormData(
CO2_data=request.getfixturevalue(scenario_data),
fitting_ventilation_states=[],
exposed_start=start,
exposed_finish=finish,
total_people=total_people,
total_people=max_total_people,
room_volume=room_volume,
)
find_points = CO2_form_model.find_change_points()
assert np.allclose(find_points, state_changes, rtol=1e-2)


def test_predictive_model_accuracy(data_registry, office_scenario_2_sensor_data):
@pytest.mark.parametrize(
"scenario_data, room_volume, occupancy, presence_interval, all_state_changes", [
["office_scenario_1_sensor_data", 102, (4,), (14, 17.5), (14, 14.25, 14.78, 15.1, 15.53, 15.87, 16.52, 16.83, 17.5)],
["office_scenario_2_sensor_data", 60, (2, 0, 2), (8.62, 11.93, 12.42, 17.5), (8.62, 10.17, 12.45, 14.5, 17.5, 20.)],
["meeting_scenario_1_sensor_data", 83, (2, 3, 2, 3), (9.07, 9.32, 9.75, 10.75, 11.75), (9.07, 10.37, 11.07, 11.75)],
["meeting_scenario_2_sensor_data", 83, (2, 3, 4), (13.67, 13.75, 15.87, 16.67), (13.67, 14.37, 14.72, 15.00, 15.33, 15.68, 16.03, 16.67)]
]
)
def test_predictive_model_accuracy(data_registry, scenario_data, room_volume, occupancy, presence_interval, all_state_changes, request):
'''
Specific test corresponding to the template data from a simulation day
in one office in Geneva. The room volume, number of people and ventilation
transition times correspond to the real occurencies in the simulation day.
Specific test corresponding to specific data files of four
different occurencies (2 office and 2 meeting room scenarios).
The room volume, number of people and ventilation transition times
correspond to the real occurencies in the simulation days.
Note that the last time from the input file is considered as a ventilation
state change.
'''
input_fitting_data = request.getfixturevalue(scenario_data)

fitting_model: models.CO2DataModel = models.CO2DataModel(
data_registry=data_registry,
room_volume=59.787,
number=2,
presence=models.SpecificInterval(((8.63, 11.95), (12.42, 17.5))),
ventilation_transition_times=(8.63, 10.17, 12.89, 14.5, 17.5, 22.),
times=office_scenario_2_sensor_data['times'],
CO2_concentrations=office_scenario_2_sensor_data['CO2'],
room_volume=room_volume,
number=models.IntPiecewiseConstant(
transition_times=presence_interval,
values=occupancy
),
presence=None,
ventilation_transition_times=all_state_changes,
times=input_fitting_data['times'],
CO2_concentrations=input_fitting_data['CO2'],
)
# Get fitting results
fitting_results: typing.Dict = fitting_model.CO2_fit_params()
Expand All @@ -90,7 +112,8 @@ def root_mean_square_error_percentage(actual, predicted) -> float:
return np.sqrt(np.mean(((actual - predicted) / actual) ** 2)) * 100

# Calculate RMSEP metric
rmsep = root_mean_square_error_percentage(np.array(office_scenario_2_sensor_data['CO2']), np.array(predictive_CO2))
rmsep = root_mean_square_error_percentage(np.array(input_fitting_data['CO2']), np.array(predictive_CO2))

acceptable_rmsep = 10 # Threshold of 10% for the accepted error margin
assert rmsep <= acceptable_rmsep, f"RMSEP {rmsep} exceeds acceptable threshold {acceptable_rmsep}"

0 comments on commit 75ef982

Please sign in to comment.