"""Validazione contro i parametri VERI di gen_data: ../gen_data sorteggia i parametri di ogni corsa dal seed, quindi per ogni seed si conoscono gradini, ampiezze e costante di tempo. Richiede il repository fratello ../gen_data (altrimenti i test sono saltati).""" import sys import numpy as np import pytest from conftest import RADICE from fitseg import dati, domini from fitseg.analisi import analizza_domini, fit_scelto GEN = RADICE.parent / "gen_data" pytestmark = pytest.mark.skipif(not (GEN / "genera.py").exists(), reason="repository ../gen_data non trovato") @pytest.fixture(scope="module") def genera(): sys.path.insert(0, str(GEN)) import genera as g yield g sys.path.remove(str(GEN)) @pytest.mark.parametrize("seed", range(1, 21)) def test_risultati_contro_i_parametri_veri(seed, genera, cfg, tmp_path): gcfg = genera.leggi_config(GEN / "config.toml") veri = genera.sorteggia(gcfg, np.random.default_rng(seed)) ordine = np.argsort(veri["t_impulsi_s"]) tj = np.array(veri["t_impulsi_s"], float)[ordine] aj = np.array(veri["dT_impulsi_c"], float)[ordine] k = veri["k_raffreddamento_hz"] t_ms, T, dT = genera.genera(gcfg, np.random.default_rng(seed)) with open(tmp_path / "d.csv", "w") as f: genera.scrivi(f, t_ms, T, dT) t, serie = dati.leggi_csv(tmp_path / "d.csv", cfg) ris = analizza_domini(t, serie, domini.proponi(t, serie, cfg), cfg) # gradini: numero giusto e istanti entro un paio di campioni risc = [r for r in ris if r["tipo"] == "riscaldamento"] assert len(risc) == len(tj) for r, x in zip(risc, tj, strict=True): assert abs(r["t0_s"] - x) < 0.3 for nome in serie: raff = [r for r in ris if r["tipo"] == "raffreddamento"] # costante di tempo del raffreddamento finale (libero) finale = fit_scelto(raff[-1]["serie"][nome]) assert finale is not None and finale["parametri"]["tau"] * k == pytest.approx(1.0, abs=0.03) for r in raff: fit = fit_scelto(r["serie"][nome]) if fit is None: # indeterminato solo se i campioni sono meno del minimo assert r["n_fit"] < cfg["domini"]["n_min_punti_parametri_fissi"] continue atteso = float(sum(a * np.exp(-k * (r["t0_s"] - x)) for x, a in zip(tj, aj, strict=True) if x <= r["t0_s"])) if nome == "dT_C": # ampiezza A al netto dell'asintoto: confrontabile con la somma dei decadimenti dei gradini assert fit["parametri"]["A"] == pytest.approx(atteso, rel=0.04) # salti: stimati dai modelli (o dalla misura corretta con c e τ del finale) entro il 5 % dall'ampiezza vera del gradino for r, a in zip(risc, aj, strict=True): g = r["serie"]["dT_C"]["gradino"] if g["stima"] in ("modelli", "misura corretta"): assert g["delta"] == pytest.approx(a, rel=0.05)