from __future__ import annotations import json from pathlib import Path from typing import Dict, List import numpy as np METRICS = ["st_i", "st_a", "si_a", "msci"] class CoherenceStats: """ Learns statistical thresholds from previous run logs. """ def __init__(self) -> None: self.stats: Dict[str, Dict[str, float]] = {} def fit(self, runs: List[Dict]) -> None: """ Learn mean, std, and percentiles from past runs. """ for metric in METRICS: values = [ r["scores"][metric] for r in runs if metric in r.get("scores", {}) ] if not values: continue arr = np.array(values) self.stats[metric] = { "mean": float(np.mean(arr)), "std": float(np.std(arr)), "p25": float(np.percentile(arr, 25)), "p50": float(np.percentile(arr, 50)), "p75": float(np.percentile(arr, 75)), } def save(self, path: Path) -> None: path.write_text(json.dumps(self.stats, indent=2)) @classmethod def load(cls, path: Path) -> "CoherenceStats": obj = cls() obj.stats = json.loads(path.read_text()) return obj