8.8 KiB
Moduli
Mappa del codice in src/fitseg/. Un modulo ha una sola responsabilità; le dipendenze vanno in una sola direzione.
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.
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 §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 |
leggi_toml(percorso, t) |
rilegge e valida i domini (tipi, intervalli, contiguità); ValueError se non validi |
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 §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 §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 §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 §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 §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.