import pandas as pd import numpy as np import matplotlib.pyplot as plt from scipy.optimize import curve_fit # --- Dati --- df = pd.read_csv("data.csv") df["time_s"] = df["time since start [ms]"] / 1000.0 T_INF = 22.99 # temperatura ambiente media ponderata [°C] T0 = 117.5 # inizio finestra di fit [s] mask = df["time_s"] >= T0 t_fit = df.loc[mask, "time_s"].values T_fit = df.loc[mask, "temp_obj IR [C]"].values # --- Modello (t0 fisso) --- def modello(t, A, tau): return T_INF + A * np.exp(-(t - T0) / tau) # Stima iniziale: A dal primo punto, tau arbitrario A0 = T_fit[0] - T_INF tau0 = 20.0 popt, pcov = curve_fit( modello, t_fit, T_fit, p0=[A0, tau0], method="trf", bounds=([0, 0.1], [np.inf, np.inf]) ) A_fit, tau_fit = popt # --- R² --- T_pred = modello(t_fit, *popt) ss_res = np.sum((T_fit - T_pred) ** 2) ss_tot = np.sum((T_fit - T_fit.mean()) ** 2) r2 = 1 - ss_res / ss_tot print(f"A = {A_fit:.4f} °C") print(f"tau = {tau_fit:.4f} s") print(f"R² = {r2:.6f}") # --- Curva continua per il plot --- t_curve = np.linspace(T0, df["time_s"].max(), 500) T_curve = modello(t_curve, *popt) # --- Plot --- fig, ax = plt.subplots(figsize=(12, 5)) df_plot = df[df["time_s"] >= 115] ax.plot(df_plot["time_s"], df_plot["temp_obj IR [C]"], color="steelblue", linewidth=0.8, label="Dati raw (temp_obj)") ax.plot(t_curve, T_curve, color="tomato", linewidth=2, linestyle="--", label=f"Fit: $T_{{\\infty}}$ + {A_fit:.2f}·exp(-(t-{T0})/{tau_fit:.1f})") ax.axvline(T0, color="gray", linewidth=0.8, linestyle=":") ax.text(T0 + 0.5, ax.get_ylim()[0], f"t₀ = {T0} s", color="gray", fontsize=8, va="bottom") ax.set_xlabel("Tempo [s]") ax.set_ylabel("Temperatura [°C]") ax.set_title(f"Fit raffreddamento esponenziale | R² = {r2:.4f}") ax.legend() ax.grid(True, alpha=0.3) plt.tight_layout() plt.savefig("fit_raffreddamento_2tratto.png", dpi=150, bbox_inches="tight") plt.show()