backend: initial commit

This commit is contained in:
Davide Scaini
2026-03-28 13:57:12 +01:00
commit 38c5423aeb
36 changed files with 2463 additions and 0 deletions
+88
View File
@@ -0,0 +1,88 @@
"""Extract stage configuration — loaded from extract_config.yaml."""
from dataclasses import dataclass, field
from pathlib import Path
from typing import Optional
import yaml
@dataclass
class TrackConfig:
simplify: str = "rdp"
rdp_epsilon: float = 0.0001
timeseries_hz: int = 1
@dataclass
class SensorsConfig:
heart_rate: bool = True
cadence: bool = True
temperature: bool = True
power: bool = True
@dataclass
class ClassifierConfig:
enabled: bool = False # off by default; opt-in
@dataclass
class ExtractConfig:
input_dirs: list[Path]
output_dir: Path
metadata_csv: Optional[Path] = None
default_privacy: str = "public"
sensors: SensorsConfig = field(default_factory=SensorsConfig)
track: TrackConfig = field(default_factory=TrackConfig)
classifier: ClassifierConfig = field(default_factory=ClassifierConfig)
incremental: bool = True
owner_handle: str = "me"
owner_display_name: str = "Me"
def load_config(path: Path) -> ExtractConfig:
raw = yaml.safe_load(path.read_text())
inp = raw.get("input", {})
dirs = [Path(d).expanduser() for d in inp.get("dirs", [])]
csv_path = inp.get("metadata_csv")
out = Path(raw.get("output", {}).get("dir", "./bincio_data")).expanduser()
owner = raw.get("owner", {})
sensors_raw = raw.get("sensors", {})
sensors = SensorsConfig(
heart_rate=sensors_raw.get("heart_rate", True),
cadence=sensors_raw.get("cadence", True),
temperature=sensors_raw.get("temperature", True),
power=sensors_raw.get("power", True),
)
track_raw = raw.get("track", {})
track = TrackConfig(
simplify=track_raw.get("simplify", "rdp"),
rdp_epsilon=track_raw.get("rdp_epsilon", 0.0001),
timeseries_hz=track_raw.get("timeseries_hz", 1),
)
cls_raw = raw.get("classifier", {})
classifier = ClassifierConfig(enabled=cls_raw.get("enabled", False))
return ExtractConfig(
input_dirs=dirs,
output_dir=out,
metadata_csv=Path(csv_path).expanduser() if csv_path else None,
default_privacy=raw.get("default_privacy", "public"),
sensors=sensors,
track=track,
classifier=classifier,
incremental=raw.get("incremental", True),
owner_handle=owner.get("handle", "me"),
owner_display_name=owner.get("display_name", "Me"),
)
def default_config(input_dir: Path, output_dir: Path) -> ExtractConfig:
return ExtractConfig(input_dirs=[input_dir], output_dir=output_dir)