"""Windowed feature extraction shared by predictor training and the Space.""" import numpy as np import pandas as pd CHANNELS = ["rpm", "speed_kph", "coolant_temp_c", "engine_load_pct", "throttle_pct", "intake_temp_c", "maf_gps", "map_kpa", "stft_pct", "ltft_pct", "o2_b1s2_v", "control_module_voltage_v", "timing_advance_deg", "catalyst_temp_c", "commanded_egr_pct", "evap_purge_pct"] STATS = ["mean", "std", "slope", "min", "max"] FEATURE_NAMES = [f"{c}_{s}" for c in CHANNELS for s in STATS] + [ "idle_frac", "highload_frac", "coolant_at_idle_mean", "stft_at_load_mean"] def extract(window: pd.DataFrame) -> np.ndarray: """window: rows at 1 Hz with all CHANNELS columns.""" feats = [] n = len(window) dur_min = max(n / 60.0, 1e-6) for c in CHANNELS: v = window[c].to_numpy(dtype=float) feats += [v.mean(), v.std(), (v[-1] - v[0]) / dur_min, v.min(), v.max()] idle = window["speed_kph"] < 5 load = window["engine_load_pct"] > 60 feats.append(idle.mean()) feats.append(load.mean()) feats.append(window.loc[idle, "coolant_temp_c"].mean() if idle.any() else window["coolant_temp_c"].mean()) feats.append(window.loc[load, "stft_pct"].mean() if load.any() else window["stft_pct"].mean()) return np.array(feats, dtype=np.float32)