"""Forma del report.md e dei grafici su un CSV sintetico (nessun file esterno).""" import numpy as np from conftest import scrivi_csv, segnale from fitseg import cli def esegui(tmp_path, gradini): t, serie = segnale(gradini=gradini, durata=80.0) csv = tmp_path / "sint.csv" scrivi_csv(csv, t, serie) cli.main(["--output", str(tmp_path / "out"), "analizza", str(csv)]) return (tmp_path / "out/sint/03_report/report.md").read_text(), tmp_path / "out/sint/02_sovrapposizione" def test_dominio_indeterminato_senza_ripetizioni_e_con_il_minimo(tmp_path): report, _ = esegui(tmp_path, [(20.0, 80.0), (20.5, 60.0)]) # tratto intermedio di 1-2 campioni assert "indeterminato: indeterminato" not in report and "Indeterminato** — indeterminato" not in report assert "meno del minimo 4 (`n_min_punti_parametri_fissi`)" in report def test_costante_senza_r2_e_senza_zero_negativo(tmp_path): report, _ = esegui(tmp_path, [(20.0, 80.0)]) assert "-0.0000" not in report dettaglio = report.split("### Dominio 1")[1].split("### Dominio 2")[0] assert "`costante`" in dettaglio and "R^2" not in dettaglio # R² non ha senso per un modello costante assert "R^2 = " in report # ma c'è per l'esponenziale def test_intervallo_del_dominio_include_l_ultimo_campione(tmp_path): report, _ = esegui(tmp_path, [(20.0, 80.0)]) assert r"\le t \le" in report and r"\le t <" not in report def test_salto_stimato_dai_modelli_nel_report(tmp_path): report, _ = esegui(tmp_path, [(20.0, 80.0)]) assert "stimato dai modelli adiacenti (misurato sui campioni:" in report def test_motivo_con_un_solo_modello_senza_parsimonia(tmp_path): report, _ = esegui(tmp_path, [(20.0, 80.0)]) finale = report.split("### Dominio 3")[1] assert "1/1 modelli validi" in finale and "meno parametri" not in finale def test_grafico_indeterminato_senza_pannello_residui(tmp_path): _, cartella = esegui(tmp_path, [(20.0, 80.0), (20.5, 60.0)]) from PIL import Image # matplotlib dipende già da Pillow larghezza, altezza = Image.open(cartella / "dominio3_T_C.png").size assert altezza / larghezza < 0.55 # un solo pannello (9×4.2), non due (9×6) larghezza, altezza = Image.open(cartella / "dominio7_T_C.png").size if (cartella / "dominio7_T_C.png").exists() else (1, 1) assert np.isfinite(altezza / larghezza) def test_risultati_json_e_json_valido_anche_con_domini_indeterminati(tmp_path): import json esegui(tmp_path, [(20.0, 80.0), (20.5, 60.0)]) # tratto intermedio con meno di 4 campioni: σ non stimabile testo = (tmp_path / "out/sint/03_report/risultati.json").read_text() def rifiuta(costante): raise ValueError(f"costante non ammessa in JSON: {costante}") dati = json.loads(testo, parse_constant=rifiuta) # NaN / Infinity farebbero fallire assert any(v["sigma"] is None for r in dati for v in r["serie"].values()) def test_senza_nan(): from fitseg.uscita import _senza_nan assert _senza_nan({"a": float("nan"), "b": [1.0, float("inf")], "c": {"d": 2}}) == {"a": None, "b": [1.0, None], "c": {"d": 2}} def test_report_mostra_la_scala_robusta_dei_residui(tmp_path): report, _ = esegui(tmp_path, [(20.0, 80.0)]) assert r"\hat\sigma_\text{res}" in report and "1.4826" in report