diff --git a/inverse/__init__.py b/inverse/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/inverse/sample_sensors.py b/inverse/sample_sensors.py new file mode 100644 index 0000000..d588c70 --- /dev/null +++ b/inverse/sample_sensors.py @@ -0,0 +1,112 @@ +""" +Campionamento sensori dalla soluzione FDM. + +Legge results/fdm/fdm_solution.csv (o lancia il solver FDM se non esiste), +chiede le posizioni dei sensori e la frequenza di campionamento, salva +results/fdm/measurements.csv con colonne: x, t, T. +""" + +import sys +import os + +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +import numpy as np +import pandas as pd + +FDM_CSV = "results/fdm/fdm_solution.csv" +OUT_CSV = "results/measurements.csv" + + +def _load_or_solve(): + if os.path.exists(FDM_CSV): + print(f"Carico soluzione FDM da {FDM_CSV} ...") + df = pd.read_csv(FDM_CSV) + x_vals = np.sort(df["x"].unique()) + t_vals = np.sort(df["t"].unique()) + T_matrix = df.pivot(index="x", columns="t", values="T").values + return T_matrix, x_vals, t_vals + else: + print(f"{FDM_CSV} non trovato. Lancio il solver FDM ...") + from fdm.solver import solve, save_csv + T_matrix, x_vals, t_vals = solve() + save_csv(T_matrix, x_vals, t_vals, FDM_CSV) + return T_matrix, x_vals, t_vals + + +def _ask_sensors(L: float) -> list[float]: + print(f"\nDominio spaziale: [0, {L}] m") + print("Inserisci le posizioni dei sensori separate da virgola (es: 0.2, 0.5, 0.8):") + while True: + raw = input(" x sensori [m]: ").strip() + try: + positions = [float(v.strip()) for v in raw.split(",") if v.strip()] + if not positions: + raise ValueError + out_of_range = [p for p in positions if p < 0 or p > L] + if out_of_range: + print(f" Valori fuori range [0, {L}]: {out_of_range}. Riprova.") + continue + return positions + except ValueError: + print(" Input non valido. Usa numeri separati da virgola.") + + +def _ask_freq(dt_fdm: float) -> float: + max_freq = 1.0 / dt_fdm + print(f"\nFrequenza massima (passo FDM): {max_freq:.2f} Hz") + print("Inserisci la frequenza di campionamento [Hz]:") + while True: + raw = input(" f [Hz]: ").strip() + try: + f = float(raw) + if f <= 0: + raise ValueError + if f > max_freq: + print(f" Frequenza troppo alta (max {max_freq:.2f} Hz). Viene usata la frequenza massima.") + f = max_freq + return f + except ValueError: + print(" Input non valido. Inserisci un numero positivo.") + + +def main(): + print("=" * 40) + print(" Campionamento sensori FDM") + print("=" * 40) + + import config + T_matrix, x_vals, t_vals = _load_or_solve() + + sensor_positions = _ask_sensors(config.L) + freq = _ask_freq(t_vals[1] - t_vals[0]) + + # Indici temporali al passo di campionamento + dt_sample = 1.0 / freq + t_sampled = np.arange(t_vals[0], t_vals[-1] + dt_sample * 0.5, dt_sample) + t_indices = [int(np.argmin(np.abs(t_vals - t))) for t in t_sampled] + t_indices = sorted(set(t_indices)) + + # Campionamento + rows = [] + for x_s in sensor_positions: + i_x = int(np.argmin(np.abs(x_vals - x_s))) + x_actual = x_vals[i_x] + for i_t in t_indices: + rows.append({"x": x_actual, "t": t_vals[i_t], "T": T_matrix[i_x, i_t]}) + + df_out = pd.DataFrame(rows).sort_values(["x", "t"]).reset_index(drop=True) + + os.makedirs(os.path.dirname(os.path.abspath(OUT_CSV)), exist_ok=True) + df_out.to_csv(OUT_CSV, index=False) + + n_sensors = len(sensor_positions) + n_times = len(t_indices) + print(f"\nSalvato: {OUT_CSV}") + print(f" Sensori: {n_sensors} | Istanti: {n_times} | Righe totali: {len(df_out)}") + print(f" Posizioni effettive: {sorted(df_out['x'].unique().tolist())}") + print(f" Intervallo T: [{df_out['T'].min():.2f}, {df_out['T'].max():.2f}] °C") + + +if __name__ == "__main__": + main()