Files

104 lines
4.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""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
def test_equazione_lineare_con_segno():
from fitseg.uscita import _eq_numerica
fit = {"modello": "lineare", "parametri": {"a": 20.0, "b": -0.5}}
assert _eq_numerica(fit) == r"y = 20 - 0.5\,t'"
assert _eq_numerica({"modello": "lineare", "parametri": {"a": 20.0, "b": 0.25}}) == r"y = 20 + 0.25\,t'"
def test_salto_solo_misurato_nel_report():
from fitseg.uscita import _salto
g = {"n": 3, "durata_s": 0.3, "stima": "misura", "delta": 70.0, "delta_misurato": 70.0}
testo = _salto({"gradino": g})
assert "misurato sui campioni" in testo and "modelli adiacenti non disponibili" in testo and testo.count("$") % 2 == 0
def test_grafici_con_campioni_esclusi_e_modelli_alternativi(tmp_path):
# riposo con deriva (costante, lineare ed esponenziale validi → curve tratteggiate) e scarta_dopo_salto_n > 0 (campioni grigi)
from conftest import RADICE
testo = (RADICE / "config.toml").read_text().replace("scarta_dopo_salto_n = 0", "scarta_dopo_salto_n = 2")
(tmp_path / "c.toml").write_text(testo)
t, serie = segnale(gradini=[(40.0, 70.0)], durata=80.0, rumore=0.3)
deriva = 0.02 * t
serie = {"T_C": serie["T_C"] + deriva, "dT_C": serie["dT_C"] + deriva}
csv = tmp_path / "sint.csv"
scrivi_csv(csv, t, serie)
cli.main(["--config", str(tmp_path / "c.toml"), "--output", str(tmp_path / "out"), "analizza", str(csv)])
cartella = tmp_path / "out/sint/02_sovrapposizione"
assert (cartella / "dominio1_T_C.png").stat().st_size > 0 and (cartella / "dominio3_T_C.png").stat().st_size > 0