# /// script # requires-python = ">=3.11" # dependencies = ["numpy", "matplotlib"] # /// """Mostra o salva il grafico di T e ΔT di un CSV prodotto da genera.py.""" import argparse import sys from pathlib import Path import matplotlib import numpy as np CARTELLA_OUTPUT = Path("output") def errore(msg): print(f"Errore: {msg}", file=sys.stderr) sys.exit(1) def ultimo_csv(): csv = sorted(CARTELLA_OUTPUT.glob("*.csv"), key=lambda p: p.stat().st_mtime) if not csv: errore(f"nessun CSV in '{CARTELLA_OUTPUT}': genera prima i dati con genera.py") return csv[-1] def main(): ap = argparse.ArgumentParser(description="Grafico di T e ΔT da un CSV di genera.py.") ap.add_argument("csv", nargs="?", type=Path, help="CSV da disegnare (default: l'ultimo in output/)") ap.add_argument("-o", "--output", type=Path, help="salva l'immagine (png, pdf, svg) invece di aprire la finestra") args = ap.parse_args() percorso = args.csv or ultimo_csv() try: t_ms, T, dT = np.loadtxt(percorso, delimiter=",", skiprows=1, unpack=True) except OSError as e: errore(f"impossibile leggere '{percorso}': {e.strerror}") except ValueError: errore(f"'{percorso}' non ha il formato t_ms,T_C,dT_C") if args.output: matplotlib.use("Agg") import matplotlib.pyplot as plt fig, (ax_T, ax_dT) = plt.subplots(2, 1, sharex=True, figsize=(10, 6)) t_s = t_ms / 1000 ax_T.plot(t_s, T, lw=0.8) ax_T.set_ylabel("T [°C]") ax_dT.plot(t_s, dT, lw=0.8, color="tab:orange") ax_dT.set_ylabel("ΔT = T − T_amb [°C]") ax_dT.set_xlabel("tempo [s]") for ax in (ax_T, ax_dT): ax.grid(alpha=0.3) fig.suptitle(percorso.name) fig.tight_layout() if args.output: try: fig.savefig(args.output, dpi=150) except OSError as e: errore(f"impossibile scrivere '{args.output}': {e.strerror}") print(f"scritto: {args.output}", file=sys.stderr) else: plt.show() if __name__ == "__main__": main()