Files

139 lines
8.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Moduli
Mappa del codice in `src/fitseg/`. Un modulo ha una sola responsabilità; le dipendenze vanno in una sola direzione.
```mermaid
flowchart TD
cli[cli.py] --> config[config.py]
cli --> dati[dati.py]
cli --> domini[domini.py]
cli --> analisi[analisi.py]
cli --> uscita[uscita.py]
analisi --> domini
analisi --> fit[fit.py]
analisi --> modelli[modelli.py]
fit --> modelli
uscita --> analisi
uscita --> modelli
```
`config.py`, `dati.py`, `domini.py` e `modelli.py` non importano niente del pacchetto; `fit.py` importa solo `modelli`; `analisi.py` importa `domini`, `fit`, `modelli`;
`uscita.py` importa `analisi` (per `valido` e `fit_scelto`) e `modelli`. Nessun modulo di calcolo scrive file.
## Strutture dati comuni
**Domini** (lista, ordinata e contigua): ogni elemento è `{"tipo": "riposo"|"riscaldamento"|"raffreddamento", "i0": int, "i1": int}`, con
`i0` primo campione e `i1` escluso. `domini[k]["i1"] == domini[k+1]["i0"]`.
**Risultato** (lista, una voce per dominio; è anche il contenuto di `risultati.json`):
| Campo | Significato |
|---|---|
| `k` | numero del dominio (da 1) |
| `tipo`, `t0_s`, `t1_s` | tipo; tempo del primo e dell'ultimo campione del dominio (in secondi) |
| `n`, `n_fit` | campioni del dominio; campioni usati nel fit (meno `scarta_dopo_salto_n` nei raffreddamenti) |
| `serie` | `{nome serie: voce}` (sotto) |
**Voce di serie**: `sigma` (σ del rumore; `null` nel riscaldamento e se non è stimabile, cioè meno di 8 campioni), `fit` (lista dei fit provati), `scelta` (nome del modello o
`null`), `motivo` (testo), `adeguato` (`true`/`false`; `null` se σ non è stimabile; assente nel riscaldamento e nei domini troppo corti); nel riscaldamento al posto dei fit c'è `gradino`:
`{n, da, a, delta, delta_misurato, stima, durata_s, istante_s}`: `delta` è il salto usato; `stima` vale `"modelli"` (differenza dei modelli adiacenti all'istante
`istante_s`), `"misura corretta"` (misura riportata a quell'istante con $c$ e $\tau$ del raffreddamento finale) o `"misura"` (sui campioni); `da`/`a` sono i valori
prima/dopo usati.
**Fit** (elemento di `fit`): `modello`, `equazione` (LaTeX), `n_parametri` ($k$ liberi), `n`, `fissi` (nomi dei parametri fissi), `parametri`
`{nome: valore}`, `ic95` `{nome: ±}`, `rss`, `rmse`, `scala_residui` ($\hat\sigma_\text{res} = 1.4826\,\mathrm{MAD}$ dei residui), `r2`, `aicc`, `bic`, `acf1` ($\rho_1$), `condizione`, `parametri_a_limite`, `non_identificabile`,
`convergenza`. Se la minimizzazione fallisce: solo `modello`, `convergenza: false`, `n_parametri`.
## `cli.py` — punto d'ingresso
| | |
|---|---|
| Responsabilità | argomenti da riga di comando, orchestrazione dei passi, codici di uscita |
| Funzioni | `main(argv)`, `cmd_domini`, `cmd_analizza`, `_passo_domini(args)`, `errore(msg, codice)` |
| Entra | `--config`, `--output`, sottocomando `domini CSV` o `analizza CSV [--domini FILE]` |
| Esce | codici 0 ok, 2 uso errato (argparse), 3 `ErroreConfig`, 4 `ErroreDati`, 6 `domini.toml` non valido |
`_passo_domini` è il passo 1 comune ai due comandi: legge config e dati, crea `output/<nome csv>/` con le tre sottocartelle, ricava i domini
(da `--domini` oppure dalla proposta), scrive `01_domini/domini.toml` e `domini.png`, stampa la tabella dei domini. `cmd_analizza` poi chiama
`analizza_domini` e scrive sovrapposizione e report. Con `--domini` il file passato viene riscritto normalizzato in `01_domini/`.
## `config.py` — configurazione
| | |
|---|---|
| Responsabilità | leggere `config.toml`, rifiutare chiavi mancanti (**nessun default nel codice**) |
| Funzioni | `leggi(percorso) → dict`; costante `CHIAVI` (elenco obbligatorio per sezione); eccezione `ErroreConfig` |
| Controlli | chiavi presenti; `unita_tempo` ∈ {ms, s}; `serie_riferimento` ∈ `serie`; `modelli_per_tipo` ha liste non vuote per `riposo` e `raffreddamento` |
Una chiave nuova va aggiunta a `CHIAVI`, a `config.toml` e a [configurazione.md](configurazione.md).
## `dati.py` — lettura del CSV
| | |
|---|---|
| Funzioni | `leggi_csv(percorso, cfg) → (t, serie)`; eccezione `ErroreDati` |
| Garanzie | `t` in secondi, strettamente crescente (A1); `serie` = `{nome: array}` per le colonne di `[dati] serie`; nessun valore mancante |
## `domini.py` — suddivisione in domini
| Funzione | Cosa fa | Vedi |
|---|---|---|
| `sigma_robusto(d)` | $1.4826\,\mathrm{MAD}$ di un campione | [algoritmi.md](algoritmi.md) §2 |
| `sigma_rumore(y)` | $\sigma$ del rumore bianco da $\Delta^2 y$; `nan` con meno di `N_MIN_SIGMA` = 8 campioni | §2 |
| `trova_gradini(y, cfg)` | lista di $(i_0, i_1)$ dei campioni di salita: campioni in salita raggruppati, gradino se la salita complessiva supera `soglia_gradino_c` | §3 |
| `proponi(t, serie, cfg)` | lista dei domini (riposo + riscaldamento/raffreddamento per gradino) | §4 |
| `scrivi_toml(percorso, domini, t)` | scrive `domini.toml` (tempi con 4 decimali) | [uso.md](uso.md) |
| `leggi_toml(percorso, t)` | rilegge e **valida** i domini (tipi, intervalli, contiguità); `ValueError` se non validi | [uso.md](uso.md) |
Nel `domini.toml` `t1_s` è l'estremo **escluso** (tempo del primo campione del dominio successivo); per l'ultimo dominio è l'ultimo campione. Gli
indici si ricalcolano dal tempo con tolleranza $10^{-6}$ s.
## `modelli.py` — registro dei modelli
| | |
|---|---|
| Dati | `MODELLI = {nome: (funzione, [nomi parametri], equazione LaTeX, indice di τ o None)}` |
| Funzioni | `valuta(nome, t, p)` valuta un modello in $t$ con parametri `p` (lista nell'ordine dei nomi) |
Contiene `costante`, `lineare`, `esp_decad`. **Aggiungere un modello**: una funzione, una voce in `MODELLI`, il nome nelle liste di
`[fit.modelli_per_tipo]`, una riga in [algoritmi.md](algoritmi.md) §5.1; se il modello ha un nuovo tipo di parametro-tempo, indicare l'indice
in `MODELLI` e la partenza in `fit._partenza`; in `uscita._eq_numerica` aggiungere il ramo per l'equazione con i valori.
## `fit.py` — regressione di un modello
| Funzione | Cosa fa |
|---|---|
| `adatta(t, y, nome, sigma, cfg, fissi=None) → dict` | fit di un modello su un dominio; `fissi = {parametro: valore}` tenuti costanti. Restituisce il dizionario *Fit* sopra |
| `_partenza(t, y, nome, cfg, L)` | minimi quadrati per i polinomi, griglia su $\tau$ (VARPRO) per l'esponenziale |
| `_acf1(r)` | autocorrelazione dei residui a lag 1 |
Dettagli: [algoritmi.md](algoritmi.md) §5. Nessun accesso a file, nessuna casualità.
## `analisi.py` — scelta e orchestrazione dei domini
| Funzione | Cosa fa |
|---|---|
| `valido(fit)` | convergente, nessun parametro a limite, identificabile, AICc finito |
| `fit_scelto(voce)` | il fit scelto di una voce di serie, o `None` (indeterminato, riscaldamento) |
| `scegli(fit_list, sigma, cfg) → (fit, motivo, adeguato)` | regola di scelta ([algoritmi.md](algoritmi.md) §6); adeguato = scala robusta dei residui ≤ soglia·σ; `None` se σ non stimabile |
| `_gradino(t, y, d)` | descrive il riscaldamento come salto misurato sui campioni ([algoritmi.md](algoritmi.md) §7) |
| `_valore(dominio, nome, t)`, `_finale(risultati)`, `_affina_salti(t, serie, risultati, domini)` | valore del modello scelto in $t$; raffreddamento finale; sostituisce la misura del salto con la stima dai modelli adiacenti o, in mancanza, con la misura corretta con $c$, $\tau$ del finale (§7) |
| `_serie(ty, yy, sigma, tipo, fissi, cfg)` | fit di tutti i modelli del tipo per una serie e scelta; `indeterminato` se i campioni sono meno di `n_min_punti` (`n_min_punti_parametri_fissi` con parametri fissi) |
| `analizza_domini(t, serie, domini, cfg) → list` | un *Risultato* per dominio; ordine: raffreddamento finale, poi gli altri ([algoritmi.md](algoritmi.md) §5b) |
## `uscita.py` — cartelle, grafici, report
| Funzione | Cosa produce |
|---|---|
| `cartelle(base)` | crea `01_domini`, `02_sovrapposizione`, `03_report` e le restituisce |
| `colori_domini(tipi)` | un colore per dominio (grigio riposo, rosso riscaldamento, colori diversi per ogni raffreddamento) |
| `grafico_domini(percorso, t, serie, domini)` | passo 1: `domini.png` |
| `sovrapposizione_generale(...)` | passo 2a: `sovrapposizione_<serie>.png` |
| `sovrapposizione_domini(...)` | passo 2b: `dominio<k>_<serie>.png` |
| `scrivi_report(cartella, risultati, nome_csv, serie_nomi, cfg)` | passo 3: `report.md` e `risultati.json` |
| `_senza_nan(x)` | copia con NaN/∞ sostituiti da `None`: `risultati.json` è sempre JSON valido (`allow_nan=False`) |
| `_num`, `_params`, `_eq_numerica`, `_salto` | formattazione LaTeX (valori, parametri ± IC, equazione con i valori sostituiti, salto) |
Il report incorpora le immagini con percorsi **relativi** (`../01_domini/domini.png`, …): cambiando nomi di file o cartelle vanno aggiornati
`PASSI` e i riferimenti. Le grandezze matematiche del report sono sempre in LaTeX e i `$` devono restare bilanciati per riga (c'è un test).
Descrizione di file e grafici: [output.md](output.md).