added correct pelt suggestion for transition times

This commit is contained in:
Luis Aleixo 2023-08-08 16:03:45 +02:00
parent 69c1c10f6e
commit c83b5cdcab
3 changed files with 26 additions and 12 deletions

View file

@ -359,14 +359,13 @@ class CO2Data(BaseRequestHandler):
Returns a list of tuples containing (index, X-axis value) for the detected significant changes.
"""
times = CO2_data['times']
CO2_values = CO2_data['CO2']
times: list = CO2_data['times']
CO2_values: list = CO2_data['CO2']
if len(times) != len(CO2_values):
raise ValueError("times and CO2 values must have the same length.")
# Convert the input lists to numpy arrays for use with the ruptures library
times_np = np.array(times)
# Convert the input list to a numpy array for use with the ruptures library
CO2_np = np.array(CO2_values)
# Define the model for change point detection (Radial Basis Function kernel)
@ -378,7 +377,14 @@ class CO2Data(BaseRequestHandler):
# Predict change points using the Pelt algorithm with a penalty value of 15
result = algo.predict(pen=15)
return [times_np[idx] for idx in result[:-1]]
# Find local minima and maxima
segments = np.split(np.arange(len(CO2_values)), result)
merged_segments = [np.hstack((segments[i], segments[i + 1])) for i in range(len(segments) - 1)]
result_set = set()
for segment in merged_segments[:-2]:
result_set.add(times[CO2_values.index(min(CO2_np[segment]))])
result_set.add(times[CO2_values.index(max(CO2_np[segment]))])
return list(result_set)
def generate_ventilation_plot(self, CO2_data: dict, transition_times: typing.Optional[list] = None, ventilation_values: typing.Optional[list] = None):
times = CO2_data['times']
@ -411,7 +417,9 @@ class CO2Data(BaseRequestHandler):
return
if endpoint.rstrip('/') == 'plot':
self.finish({'CO2_plot': self.generate_ventilation_plot(form.CO2_data, self.find_change_points_with_pelt(form.CO2_data))})
transition_times = self.find_change_points_with_pelt(form.CO2_data)
self.finish({'CO2_plot': self.generate_ventilation_plot(form.CO2_data, transition_times),
'transition_times': [round(el, 2) for el in transition_times]})
else:
executor = loky.get_reusable_executor(
max_workers=self.settings['handler_worker_pool_size'],

View file

@ -190,7 +190,9 @@ class CO2FormData(model_generator.FormData):
def ventilation_transition_times(self) -> typing.Tuple[float, ...]:
# Check what type of ventilation is considered for the fitting
if self.fitting_ventilation_type == 'fitting_natural_ventilation':
return tuple(self.fitting_ventilation_states)
vent_states = self.fitting_ventilation_states
vent_states.append(self.CO2_data['times'][-1])
return tuple(vent_states)
else:
return tuple((self.CO2_data['times'][0], self.CO2_data['times'][-1]))

View file

@ -215,10 +215,10 @@ function validateCO2Form() {
const max_presence_time = Math.max(elapsed_time_infected, elapsed_time_exposed);
const max_transition_time = parsedValue[parsedValue.length - 1] * 60;
if (max_transition_time < max_presence_time) {
if (max_transition_time > max_presence_time) {
insertErrorFor(
$("#DIVCO2_fitting_result"),
`The last transition time (${parsedValue[parsedValue.length - 1]}) should be after the last presence time (${max_presence_time / 60}).<br />`
`The last transition time (${parsedValue[parsedValue.length - 1]}) should be before the last presence time (${max_presence_time / 60}).<br />`
);
submit = false;
}
@ -297,6 +297,7 @@ function formatCO2DataForm(CO2_data_form) {
let CO2_mapping = {};
CO2_data_form.map((el) => {
let element = $(`[name=${el}]`).first();
// Validate checkboxes
if (element.prop('type') == "checkbox") {
CO2_mapping[element.attr('name')] = String(+element.prop('checked'));
@ -306,7 +307,9 @@ function formatCO2DataForm(CO2_data_form) {
CO2_mapping[element.attr('name')] = $(
`[name=${element.attr('name')}]:checked`
).first().val();
else CO2_mapping[element.attr('name')] = element.val();
else {
CO2_mapping[element.attr('name')] = element.val();
}
});
return CO2_mapping;
}
@ -320,9 +323,10 @@ function plotCO2Data(url) {
}).then((response) =>
response
.json()
.then((json_response) =>
.then((json_response) => {
$("#CO2_data_plot").attr("src", json_response["CO2_plot"])
)
$("#fitting_ventilation_states").val(`[${json_response["transition_times"]}]`)
})
.then($("#DIVCO2_fitting_to_submit").show())
.catch((error) => console.log(error))
);