| **A1** | Il tempo è **strettamente crescente**, anche non uniforme (jitter del campionamento) | `dati.leggi_csv` | il CSV è rifiutato (exit 4). Il programma non riordina né deduplica |
| **A2** | Il CSV ha l'intestazione e tutte le colonne richieste da `[dati]` (tempo e serie), tutte numeriche, senza celle vuote | `dati.leggi_csv` | exit 4 con il nome della colonna mancante |
| **A3** | Il tempo è in `ms` o `s` come dichiarato in `[dati] unita_tempo` | `dati.leggi_csv` | tutti i tempi e le costanti $\tau$ risultano scalati di 1000 senza avvisi: controlla l'unità |
| **A4** | Le serie condividono gli **stessi domini** (stessi istanti di rottura) | `analisi.analizza_domini`, `domini.proponi` | i domini sono cercati solo su `serie_riferimento` (default `T_C`); una serie con gradini diversi non è gestita: si lancia l'analisi due volte |
| **A5** | I **gradini di riscaldamento** sono salite positive molto più grandi del rumore **e** degli scarti casuali: la **salita complessiva** dei campioni consecutivi in salita supera `soglia_gradino_c` (20 °C), mentre uno scarto casuale è ≤ 4 °C | `domini.trova_gradini` | gradini con salita complessiva sotto la soglia non sono visti (il segnale resta un unico tratto); scarti consecutivi che sommati superano la soglia sono scambiati per gradini. Soluzione: adattare la soglia o correggere `domini.toml` a mano. La soglia è un valore fisso, non derivato dai dati: misure e alternative in [limiti.md](limiti.md) |
| **A6** | La **salita dura pochi campioni** (2–4): la costante di tempo del sensore ($\tau_\text{sensore} \approx 0.04$–$0.12$ s) è dell'ordine dell'intervallo di campionamento (≈ 0.15 s), quindi un gradino si distribuisce su 2–4 campioni, anche ognuno sotto la soglia | `domini.trova_gradini` (campioni in salita raggruppati, soglia sulla salita complessiva), `analisi._gradino` | con un sensore più lento la salita avrebbe più campioni: sarebbe comunque raggruppata finché ogni salto supera `soglia_bordo_sigma`$\cdot\sigma_d$ e i campioni in salita distano meno di `distanza_min_salti_campioni`, ma non sarebbe fittata |
| **A7** | Dopo ogni gradino la temperatura **decade esponenzialmente** verso un asintoto: $y = c + A\,e^{-t'/\tau}$ | `modelli.MODELLI["esp_decad"]` | residui sistematici, `ρ₁` alto, «modello non adeguato». Con più processi di raffreddamento servirebbe un modello a più esponenziali (non presente, vedi [limiti.md](limiti.md)) |
| **A8** | Tutti i raffreddamenti hanno la **stessa costante di tempo $\tau$ e lo stesso asintoto $c$** (stesso processo fisico: dispersione verso l'ambiente). Anche nel generatore il decadimento dopo più gradini è la somma di esponenziali con lo stesso $k$, quindi un'unica esponenziale | `analisi.analizza_domini` (parametri `raffreddamento_intermedio_fissa_da_finale`) | gli intermedi sono forzati a $\tau$ e $c$ del finale: se in realtà differiscono, il fit dell'ampiezza $A$ è distorto e i residui lo mostrano. Per rimuovere il vincolo: `raffreddamento_intermedio_fissa_da_finale = []` |
| **A9** | Il **raffreddamento finale** è l'ultimo dominio ed è abbastanza lungo (centinaia di campioni) da stimare $c$, $A$, $\tau$ **liberamente**; i raffreddamenti intermedi, anche di 4–6 campioni, bastano per stimare la sola $A$ con $c$ e $\tau$ fissi (`n_min_punti_parametri_fissi`) | `analisi.analizza_domini`, `analisi._serie` | se il CSV finisce subito dopo un gradino, il finale è corto e $\tau$ può risultare non identificabile; allora anche gli intermedi restano liberi (con `n_min_punti`) e possono essere indeterminati. Tratti intermedi con meno di 4 campioni (gradini a meno di ≈ 1.2 s) restano indeterminati |
| **A10** | Il **riposo** (prima del primo gradino) è una baseline costante, lineare o esponenziale lenta (l'ambiente che si assesta) | `[fit.modelli_per_tipo] riposo` | il modello scelto è solo descrittivo: con una deriva lenta vince `lineare` o `esp_decad` |
| **A11** | Ogni dominio è **indipendente**: nessun vincolo di continuità tra domini | `analisi` | i modelli adiacenti possono non combaciare ai confini; il «salto» tra due raffreddamenti è il gradino |
| **A12** | Non esistono gradini **discendenti** (un calo brusco non è un evento): si cercano solo salti positivi | `domini.trova_gradini` (`d > soglia`) | un calo brusco resterebbe dentro un raffreddamento, aumentando RMSE e $\rho_1$ |
| **A25** | Il **ritardo di risposta del sensore** ($\tau_\text{sensore} \approx 0.04$–$0.12$ s) è trascurabile rispetto a $\tau$ del raffreddamento: il modello `esp_decad` non lo include | `modelli.MODELLI` (`esp_decad`) | un esponenziale filtrato da un filtro del primo ordine ha lo stesso $\tau$ ma ampiezza moltiplicata per $1/(1-\tau_\text{sensore}/\tau)$: $A$ risulta sovrastimata di circa $\tau_\text{sensore}/\tau \approx 0.5$ % (misurato: +0.45 % in media su 60 seed). $\tau$ non è affetta |
| **A13** | Il rumore è circa **gaussiano bianco**, con $\sigma$ stimabile per dominio da $\sigma = 1.4826\,\mathrm{MAD}(\Delta^2 y)/\sqrt{6}$ **su almeno 8 campioni**: con meno, la MAD di pochi $\Delta^2 y$ quantizzati può annullarsi | `domini.sigma_rumore` (`N_MIN_SIGMA`) | $\sigma$ sottostimata: l'adeguatezza è valutata male. Sotto 8 campioni $\sigma$ è «non stimabile» (`null`): scala della perdita 1, adeguatezza non valutabile. La stima ignora la parte lenta del rumore (vedi A14) |
| **A14** | Sul rumore bianco si aggiungono **disturbi che il modello non descrive**: deriva lenta (Ornstein–Uhlenbeck, $\tau \approx 3.5$ s) e **scarti casuali** (±4 °C, rientro < 1 s) | `fit.adatta` (perdita robusta), `uscita` (residui) | sono trattati come outlier dalla perdita `soft_l1` (non spostano molto il fit) ma lasciano residui autocorrelati ($\rho_1 \approx 0.7$) e intervalli di confidenza troppo stretti. Non è un errore del fit |
| **A15** | La **quantizzazione** (T a 0.01 °C, ambiente a 0.1 °C) è trascurabile rispetto al rumore | — | nessun trattamento specifico |
## Statistica
| ID | Assunzione | Dove | Se è falsa |
|---|---|---|---|
| **A16** | Gli intervalli al 95 % sono **gaussiani asintotici**: $\pm 1.96\,\sigma_p$ con $\mathrm{cov} = s^2 (J^\top J)^{-1}$, $s^2 = \mathrm{RSS}/(n-k)$ | `fit.adatta` | con pochi campioni o residui non gaussiani sono approssimati |
| **A17** | L'autocorrelazione dei residui è di tipo AR(1): gli errori si allargano di $\sqrt{(1+\rho_1)/(1-\rho_1)}$ se $\rho_1$ supera `soglia_acf` | `fit.adatta` | **approssimazione insufficiente**: su 60 seed il $\tau$ vero cade nell'intervallo al 95 % nel 73 % dei casi. La deviazione standard dell'errore su $\tau$ è 3.7 volte l'errore standard non corretto, perché gli scarti casuali sono concentrati all'inizio del raffreddamento (dove la sensibilità a $\tau$ è massima), quindi non stazionari. Provate e scartate: correzione a più lag di Bartlett (77 %) e stimatore sandwich HAC (≤ 62 %). Vedi [limiti.md](limiti.md) |
| **A18** | Per i parametri **fissi** l'incertezza non si propaga: gli intervalli di $A$ nei raffreddamenti intermedi sono **condizionati** a $c$ e $\tau$ del finale | `fit.adatta`, `uscita._params` | sono sottostimati rispetto all'incertezza totale |
| **A19** | AICc e BIC si calcolano da $\mathrm{RSS}$ come se i residui fossero gaussiani, anche se il fit usa la perdita robusta | `fit.adatta` | confronto tra modelli approssimato; sensibile agli outlier |
| **A20** | Se $\sigma$ non è stimabile (meno di 8 campioni, o nulla) la scala della perdita robusta è 1 e l'adeguatezza non è valutabile | `fit.adatta`, `analisi.scegli` | solo robustezza ridotta; il fit resta valido |
| **A21** | La **suddivisione in domini la decide l'utente**: la proposta automatica è modificabile (`domini.toml`) e il fit non la cambia mai | `cli._passo_domini`, `domini.leggi_toml` |
| **A22** | Il programma è **deterministico**: nessuna partenza casuale, nessun seme | `fit._partenza` (griglia su $\tau$, minimi quadrati lineari) |
| **A23** | Il **riscaldamento non si fitta** (2–4 campioni). Il salto $\Delta$ si stima nell'ordine da: modelli dei domini adiacenti valutati all'istante del gradino; misura riportata a quell'istante con $c$ e $\tau$ del raffreddamento finale; misura sui campioni ($y_\text{fine salita} - y_\text{prima}$), che è per difetto (fino a ≈ 10–20 %: parte della salita cade sul campione precedente e l'ultimo campione è già decaduto) | `analisi._gradino`, `analisi._affina_salti` |
| intervallo di campionamento | 150.5 ms con jitter ±0.6 ms (fisso) | A1, A6 |
| numero e istanti dei gradini | 1–3; il primo a 8–25 s, distanza tra gradini 1–6 s | A5, A9 |
| ampiezza dei gradini | 40–90 °C | A5, A7 |
| raffreddamento | $k = 0.05$–$0.09\ \mathrm{s^{-1}}$, cioè $ au = 1/k = 11$–$20$ s | A7, A8 |
| risposta del sensore | filtro del primo ordine, $ au_ ext{sensore} = 0.04$–$0.12$ s | A6 |
| rumore bianco | $\sigma = 0.06$–$0.16$ °C a freddo, $0.15$–$0.30$ a caldo | A13 |
| deriva lenta | Ornstein–Uhlenbeck, $\sigma = 0.02$–$0.08$ °C, $ au = 2$–$6$ s | A14 |
| scarti casuali | in riscaldamento: 0.4–1.2 Hz, $\sigma$ 1.5–3.5 °C, rientro 0.3 s; in raffreddamento: 0.1–0.5 Hz, media −1 °C, $\sigma$ 1.5–3.5 °C, rientro 0.7 s; ampiezza ≤ 4 °C | A5, A14 |
| ambiente | 20–26 °C a regime, deriva iniziale ±0.8 °C con $ au$ 30–90 s; non sale quando T è alta | A10; $c$ di `dT_C` ≈ 0 |