Files
EquationMiner/docs/SPEC.md
T
davideandClaude Sonnet 5.5 d92bcd198b Semplifica: CLI a due comandi, moduli piatti, solo modelli usati; test unitari su segnale sintetico
- rimossi scripts/, stadi.py, docs/USO.md, modelli non usati, partenze casuali, output ridondanti
- uscita unica (report.md con grafici per dominio, risultati.json, proposta.png)
- test: unitari su segnale sintetico, integrazione su dati/gen_*.csv (saltati se mancano)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-29 10:13:01 +01:00

5.8 KiB
Raw Blame History

fitseg — specifica

Obiettivo: leggere un CSV (t_ms,T_C,dT_C, p.es. da gen_data), riconoscere riposo, riscaldamento (flusso in entrata: gradini di temperatura) e raffreddamento, dividere il tempo in domini e trovare per ogni (dominio, serie) l'equazione che lo approssima meglio. Valori configurabili: solo in config.toml. Uso: README.

1. Flusso

CSV ─► [DOMINI] gradini ⇒ riposo | riscaldamento… | raffreddamento ─► lavoro/domini.toml (modificabile), proposta.png
        ▼
       [FIT] per (dominio, serie): modelli del tipo ─► regola di scelta ─► lavoro/out/report.md, risultati.json, dominio*_*.png

Tutto il calcolo è deterministico (nessuna partenza casuale, nessun LLM).

2. Domini (domini.py)

Struttura fisica (vedi gen_data/docs/SPEC.md): T parte dall'ambiente, gradini istantanei positivi (riscaldamento, 2–4 s uno dall'altro) ognuno seguito da un decadimento esponenziale; dopo l'ultimo resta solo il raffreddamento esponenziale verso l'ambiente. Compaiono anche scarti casuali (±4 °C, rientro < 1 s).

  1. d = diff(y) sulla serie_riferimento; gradino = d > soglia_gradino_c; rilevazioni più vicine di distanza_min_salti_campioni sono lo stesso gradino.
  2. Il gradino parte dal primo campione già in salita (si arretra finché d > soglia_bordo_sigma · σ_d, σ_d = MAD dei salti). Quel campione apre il nuovo dominio; i primi scarta_dopo_salto_n campioni sono esclusi dal fit (transizione del sensore).
  3. Prima del primo gradino riposo; tra due gradini riscaldamento; dopo l'ultimo raffreddamento. Senza gradini: un solo riposo.

Ipotesi: tempo crescente; rumore circa gaussiano, σ stimato per dominio da 1.4826·MAD(d²y)/√6; le serie condividono i domini; i gradini sono salti positivi ≫ rumore e scarti casuali (soglia_gradino_c ≫ ampiezza degli scarti).

domini.toml è modificabile (tipo, t0_s incluso, t1_s escluso; ultimo dominio fino a fine dati); i domini devono essere contigui, altrimenti exit 6.

3. Modelli (modelli.py, t' = t − t0 del dominio)

Id Equazione Parametri Tipi di dominio ([fit.modelli_per_tipo])
costante y = a a riposo
lineare y = a + b·t' a, b riposo
esp_decad y = c + A·exp(−t'/τ) c, A, τ riposo, riscaldamento, raffreddamento

Riscaldamento e raffreddamento sono esponenziali. Nel raffreddamento c è l'asintoto (≈ ambiente) e τ = 1/k. Nuovo modello = voce in MODELLI, riga qui, nome in config.

4. Fit (fit.py)

  1. Dati del dominio senza i primi scarta_dopo_salto_n campioni (se non riposo); tempo traslato.
  2. Partenza: polinomi per minimi quadrati; esponenziale con griglia log-spaziata su τ (tau_min_rel·L … tau_max_rel·L, L = durata) e c, A lineari.
  3. scipy.optimize.least_squares, perdita perdita (robusta soft_l1, scala scala_perdita_sigma·σ), limiti su τ.
  4. IC 95 % = ±1.96·σ_p da s²(JᵀJ)⁻¹, moltiplicati per √((1+ρ)/(1−ρ)) se ACF1 > soglia_acf (correggi_autocorrelazione).
  5. Metriche: RSS, RMSE, R², AICc, BIC, ACF1, parametri a limite, numero di condizione. Non identificabile se condizione > soglia_condizione o un parametro (esclusi a, c) ha IC 95 % > |valore|.

4.1 Costanti condivise tra riscaldamento e raffreddamento (analisi.py)

Dopo ogni gradino la temperatura decade con la stessa legge del raffreddamento finale. I domini di raffreddamento si fittano per primi; nei domini di riscaldamento i parametri di riscaldamento_fissa_da_raffreddamento (default c, tau) sono fissati ai loro valori e resta libera solo A. Motivo: con gli scarti casuali del sensore, in 2–4 s di dati τ non si identifica da solo (su dati puliti sì). Gli IC di A sono condizionati ai valori fissi; i parametri fissi sono marcati «(fisso)» nel report. Se manca un raffreddamento valido, o la lista è vuota, i parametri restano liberi.

4.2 Regola di scelta (analisi.scegli)

Scarta non convergenti, con parametri a limite o non identificabili. Se esistono modelli con RMSE ≤ rmse_vs_rumore_max·σ («adeguati») si sceglie tra questi, altrimenti tra tutti i validi; tra i modelli entro soglia_delta_aicc dal miglior AICc vince quello con meno parametri. Nessun modello valido ⇒ indeterminato; meno di n_min_punti campioni ⇒ non fittato. Scelto ma con RMSE > soglia·σ ⇒ «non adeguato» nel report.

5. CLI e file

Comando Funzione
fitseg domini CSV propone i domini: tabella, lavoro/domini.toml, lavoro/proposta.png
fitseg analizza CSV [--domini FILE] domini (proposti o da FILE) + fit + lavoro/out/{report.md, risultati.json, dominio<k>_<serie>.png}

Opzioni globali prima del sottocomando: --config PATH, --lavoro DIR. Exit: 0 ok · 3 config non valida · 4 CSV illeggibile · 6 domini non validi.

6. Test

Unitari su un segnale sintetico (tests/conftest.py: τ = 16 s, 3 gradini, nessun disturbo a salto) e di integrazione su dati/gen_{1,2,3}.csv (saltati se mancano). Dettaglio: README, «Test». Coperto: domini (3, 0, 1 gradino, sotto soglia, confini), recupero di τ/c/A, parametri fissi e ereditati dal raffreddamento, regola di scelta, errori di config/CSV/domini.toml, CLI.

7. Limiti noti

  • Residui autocorrelati nel raffreddamento (ACF1 ≈ 0.7, RMSE ≈ 0.36 contro σ ≈ 0.15): scarti casuali e deriva lenta non sono nel modello; parametri buoni, IC troppo stretti, dominio «non adeguato».
  • Riscaldamento: secondo tratto con ACF1 ≈ 0.7 e RMSE ≈ 2σ per gli scarti: «non adeguato» anche se la forma è giusta.
  • soglia_gradino_c va adattata se i gradini reali sono più piccoli di 20 °C o gli scarti più grandi.
  • Nessun vincolo di continuità tra domini. Provato su pochi seed e con la config d'esempio di gen_data.