First implementation of data chart.

This commit is contained in:
Filip 2025-09-28 11:31:32 +02:00
parent fb8883c185
commit fc25be87e9
3 changed files with 125 additions and 0 deletions

87
src/corchestrate/chart.py Normal file
View file

@ -0,0 +1,87 @@
from datetime import datetime
from plotly.subplots import make_subplots
from corchestrate.chart_data import ChartData
from corchestrate.indexed_input import IndexedInput
from corchestrate.measurement import Measurement
def plot_over_time(input_data: list[ChartData]):
indexed_inputs = [
IndexedInput(data.name, data.measurements) for data in input_data
]
datetime_indices = []
fig = make_subplots(5, 1)
while True:
min_datetime: datetime | None = None
# Find min_datetime
for indexed_input in indexed_inputs:
current_measurement = indexed_input.current()
if current_measurement == None:
continue
if min_datetime == None:
min_datetime = current_measurement.measured_at
continue
if current_measurement.measured_at < min_datetime:
min_datetime = current_measurement.measured_at
# If no valid measurement is available, break the loop
if min_datetime == None:
break
datetime_indices.append(min_datetime)
# Extract data at minimum datetime
for indexed_input in indexed_inputs:
current_measurement = indexed_input.current()
if current_measurement is None:
continue
if current_measurement.measured_at == min_datetime:
indexed_input.extracted_heart_rate.append(
current_measurement.heart_rate)
indexed_input.extracted_speed.append(current_measurement.speed)
indexed_input.extracted_cadence.append(
current_measurement.cadence)
indexed_input.extracted_power.append(current_measurement.power)
indexed_input.extracted_temperature.append(
current_measurement.temperature)
# Advance to next index
indexed_input.next()
# Plot
for indexed_input in indexed_inputs:
fig.add_scatter(x=datetime_indices,
y=indexed_input.extracted_heart_rate,
row=1,
col=1,
name=f"Heart rate - {indexed_input.name}")
fig.add_scatter(x=datetime_indices,
y=indexed_input.extracted_speed,
row=2,
col=1,
name=f"Speed - {indexed_input.name}")
fig.add_scatter(x=datetime_indices,
y=indexed_input.extracted_cadence,
row=3,
col=1,
name=f"Cadence - {indexed_input.name}")
fig.add_scatter(x=datetime_indices,
y=indexed_input.extracted_power,
row=4,
col=1,
name=f"Power - {indexed_input.name}")
fig.add_scatter(x=datetime_indices,
y=indexed_input.extracted_temperature,
row=5,
col=1,
name=f"Temperature - {indexed_input.name}")
fig.update_layout(height=3000)
fig.show()

View file

@ -0,0 +1,9 @@
from dataclasses import dataclass
from corchestrate.measurement import Measurement
@dataclass
class ChartData:
name: str
measurements: list[Measurement]

View file

@ -0,0 +1,29 @@
from numpy import double
from corchestrate.measurement import Measurement
class IndexedInput:
def __init__(self, name: str, measurements: list[Measurement]) -> None:
self.index: int = 0
self.name = name
self.measurements: list[Measurement] = measurements
self.extracted_heart_rate: list[float | None] = []
self.extracted_speed: list[float | None] = []
self.extracted_cadence: list[float | None] = []
self.extracted_power: list[float | None] = []
self.extracted_temperature: list[float | None] = []
def is_out_of_range(self) -> bool:
return len(self.measurements) <= self.index
def current(self):
if self.is_out_of_range():
return None
return self.measurements[self.index]
def next(self):
self.index += 1
self.current()