""" Data-schema inspector. Prints exactly what raw signals are available so we can decide which FEATURES to add. The current model (batteryswap_example/train.py, BaseRULModel) only uses value_cols=('voltage', 'temperature') from the timeseries and ignores device metadata entirely -- if the parquet or devices.csv carry more predictive signal (current, soc, resistance, cycle count, install age, ...) we are leaving accuracy on the table, and late_swap + early_swap (84% of total cost) is now a prediction-accuracy problem. Run: BATTERYSWAP_DATASET_PATH=BatterySwapAI-2026-Public \ venv/bin/python3 inspect_data.py """ import os from pathlib import Path import pandas as pd from batteryswap_example.train import load_dataset def main(): dataset_path = os.environ.get("BATTERYSWAP_DATASET_PATH") assert dataset_path, "set BATTERYSWAP_DATASET_PATH (e.g. BatterySwapAI-2026-Public)" split_path = Path(dataset_path) / "train" locations, timeseries, eol_times, scenarios = load_dataset(split_path) print("=" * 70) print("TIMESERIES (battery_metrics) -- one row per device per timestamp") print("=" * 70) print("index names :", list(timeseries.index.names)) print("columns :", list(timeseries.columns)) print("dtypes :\n", timeseries.dtypes) print("shape :", timeseries.shape) print("head:\n", timeseries.head(3)) # Numeric columns beyond voltage/temperature are candidate new features. numeric = timeseries.select_dtypes("number").columns.tolist() used = ["voltage", "temperature"] unused = [c for c in numeric if c not in used] print("\nnumeric columns NOT currently used as features:", unused) print("\n" + "=" * 70) print("LOCATIONS -- per-device placement the planner sees") print("=" * 70) print("columns:", list(locations.columns)) print(locations.head(3)) print("\n" + "=" * 70) print("devices.csv -- has install start_time => TRUE device AGE feature") print("=" * 70) dev = pd.read_csv(split_path / "devices.csv") print("columns:", list(dev.columns)) print(dev.head(3)) # How old are devices? (age = plan time - install time). Strong RUL signal. if "start_time" in dev.columns: st = pd.to_datetime(dev["start_time"], utc=True, errors="coerce") span = (pd.Timestamp.utcnow() - st).dt.days print("\ninstall-age (days) distribution:") print(span.describe()) print("\n" + "=" * 70) print("eol_times -- censoring rate") print("=" * 70) eol = pd.Series(eol_times) n = len(eol) n_obs = eol.notna().sum() print(f"devices={n} observed_eol={n_obs} censored(blank)={n - n_obs} " f"({100 * (n - n_obs) / max(n, 1):.1f}% censored)") if __name__ == "__main__": main()