Domini corretti: riscaldamento = salita rapida, raffreddamento = decadimento dopo ogni gradino
- 1 + 2N domini: riposo, poi (riscaldamento, raffreddamento) per ogni gradino - riscaldamento non fittato: descritto come salto (delta, da -> a, durata) - raffreddamenti intermedi fissano c e tau a quelli del raffreddamento finale - un colore per ogni raffreddamento nei grafici, zoom sui gradini - sigma None (non NaN) nei domini non fittati: JSON valido Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
da0964be4d
commit
b49af5c112
12 files changed
+277
-142
No files matched your search
+11
-3
@@ -14,13 +14,21 @@ def tipi(t, serie, cfg):
|
||||
|
||||
def test_tre_gradini(sintetico, cfg):
|
||||
t, serie = sintetico
|
||||
assert tipi(t, serie, cfg) == ["riposo", "riscaldamento", "riscaldamento", "raffreddamento"]
|
||||
assert tipi(t, serie, cfg) == ["riposo", "riscaldamento", "raffreddamento", "riscaldamento", "raffreddamento",
|
||||
"riscaldamento", "raffreddamento"]
|
||||
|
||||
|
||||
def test_riscaldamento_e_la_salita_rapida(sintetico, cfg):
|
||||
t, serie = sintetico
|
||||
for d in domini.proponi(t, serie, cfg):
|
||||
if d["tipo"] == "riscaldamento":
|
||||
assert d["i1"] - d["i0"] <= 3 # pochi campioni
|
||||
|
||||
|
||||
def test_confini_vicini_agli_istanti_dei_gradini(sintetico, cfg):
|
||||
t, serie = sintetico
|
||||
ds = domini.proponi(t, serie, cfg)
|
||||
for d, (tj, _) in zip(ds[1:], GRADINI, strict=True):
|
||||
for d, (tj, _) in zip(ds[1::2], GRADINI, strict=True): # i riscaldamenti sono i domini 2, 4, 6
|
||||
assert abs(t[d["i0"]] - tj) < 0.5
|
||||
|
||||
|
||||
@@ -38,7 +46,7 @@ def test_senza_gradini_un_solo_riposo(cfg):
|
||||
|
||||
def test_un_solo_gradino(cfg):
|
||||
t, serie = segnale(gradini=[(20.0, 80.0)])
|
||||
assert tipi(t, serie, cfg) == ["riposo", "raffreddamento"]
|
||||
assert tipi(t, serie, cfg) == ["riposo", "riscaldamento", "raffreddamento"]
|
||||
|
||||
|
||||
def test_gradino_sotto_soglia_ignorato(cfg):
|
||||
|
||||
+29
-18
@@ -55,28 +55,39 @@ def test_tau_libero_non_identificabile_su_tratto_corto_e_rumoroso(cfg, seed):
|
||||
def test_analisi_completa_sintetico(sintetico, cfg):
|
||||
t, serie = sintetico
|
||||
ris = analizza_domini(t, serie, domini.proponi(t, serie, cfg), cfg)
|
||||
assert [r["tipo"] for r in ris] == ["riposo", "riscaldamento", "riscaldamento", "raffreddamento"]
|
||||
assert [r["tipo"] for r in ris] == ["riposo", "riscaldamento", "raffreddamento", "riscaldamento", "raffreddamento",
|
||||
"riscaldamento", "raffreddamento"]
|
||||
for nome in serie:
|
||||
assert ris[0]["serie"][nome]["scelta"] in ("costante", "lineare")
|
||||
raff = next(x for x in ris[3]["serie"][nome]["fit"] if x["modello"] == "esp_decad")["parametri"]
|
||||
assert raff["tau"] == pytest.approx(TAU, rel=0.03)
|
||||
for r in ris[1:3]: # riscaldamento: c e τ ereditati dal raffreddamento
|
||||
fit = next(x for x in r["serie"][nome]["fit"] if x["modello"] == "esp_decad")
|
||||
assert r["serie"][nome]["scelta"] == "esp_decad" and fit["fissi"] == ["c", "tau"]
|
||||
assert fit["parametri"]["tau"] == raff["tau"] and fit["parametri"]["c"] == raff["c"]
|
||||
# ampiezza del secondo tratto = somma dei decadimenti dei gradini precedenti + il nuovo, in t'=0
|
||||
t1 = ris[1]["t0_s"]
|
||||
attesa = sum(a * np.exp(-(t1 - tj) / TAU) for tj, a in GRADINI[:1])
|
||||
fit1 = next(x for x in ris[1]["serie"]["dT_C"]["fit"] if x["modello"] == "esp_decad")
|
||||
assert fit1["parametri"]["A"] == pytest.approx(attesa, rel=0.05)
|
||||
finale = next(x for x in ris[6]["serie"][nome]["fit"] if x["modello"] == "esp_decad")
|
||||
assert finale["fissi"] == [] and finale["parametri"]["tau"] == pytest.approx(TAU, rel=0.03)
|
||||
for i in (2, 4): # raffreddamenti intermedi: c e τ ereditati dal finale
|
||||
fit = next(x for x in ris[i]["serie"][nome]["fit"] if x["modello"] == "esp_decad")
|
||||
assert ris[i]["serie"][nome]["scelta"] == "esp_decad" and fit["fissi"] == ["c", "tau"]
|
||||
assert fit["parametri"]["tau"] == finale["parametri"]["tau"] and fit["parametri"]["c"] == finale["parametri"]["c"]
|
||||
# ampiezza dei raffreddamenti intermedi = somma dei decadimenti dei gradini già avvenuti, in t' = 0
|
||||
for i, n_gradini in ((2, 1), (4, 2)):
|
||||
t0 = ris[i]["t0_s"]
|
||||
attesa = sum(a * np.exp(-(t0 - tj) / TAU) for tj, a in GRADINI[:n_gradini])
|
||||
fit = next(x for x in ris[i]["serie"]["dT_C"]["fit"] if x["modello"] == "esp_decad")
|
||||
assert fit["parametri"]["A"] == pytest.approx(attesa, rel=0.05)
|
||||
|
||||
|
||||
def test_senza_raffreddamento_riscaldamento_resta_libero(cfg):
|
||||
t, serie = segnale(gradini=[(20.0, 80.0)], durata=40.0)
|
||||
ds = [{"tipo": "riposo", "i0": 0, "i1": 100}, {"tipo": "riscaldamento", "i0": 100, "i1": len(t)}]
|
||||
ris = analizza_domini(t, serie, ds, cfg) # nessun dominio di raffreddamento: niente parametri da ereditare
|
||||
for x in ris[1]["serie"]["T_C"]["fit"]:
|
||||
assert x["fissi"] == []
|
||||
def test_riscaldamento_descritto_come_salto_non_fittato(sintetico, cfg):
|
||||
t, serie = sintetico
|
||||
ris = analizza_domini(t, serie, domini.proponi(t, serie, cfg), cfg)
|
||||
for i, (_, ampiezza) in zip((1, 3, 5), GRADINI, strict=True):
|
||||
vs = ris[i]["serie"]["dT_C"]
|
||||
assert vs["fit"] == [] and vs["scelta"] is None
|
||||
assert vs["gradino"]["delta"] == pytest.approx(ampiezza, rel=0.15) # salto sul canale ΔT, meno il decadimento
|
||||
assert vs["gradino"]["n"] <= 3
|
||||
|
||||
|
||||
def test_un_solo_raffreddamento_resta_libero(cfg):
|
||||
t, serie = segnale(gradini=[(20.0, 80.0)], durata=60.0)
|
||||
ris = analizza_domini(t, serie, domini.proponi(t, serie, cfg), cfg)
|
||||
assert [r["tipo"] for r in ris] == ["riposo", "riscaldamento", "raffreddamento"]
|
||||
assert all(x["fissi"] == [] for x in ris[2]["serie"]["T_C"]["fit"])
|
||||
|
||||
|
||||
def test_dominio_troppo_corto_indeterminato(sintetico, cfg):
|
||||
|
||||
@@ -15,7 +15,8 @@ def analizza(csv, cfg):
|
||||
|
||||
def test_domini_su_csv_gen(csv_gen, cfg):
|
||||
ds, _ = analizza(csv_gen, cfg)
|
||||
assert [d["tipo"] for d in ds] == ["riposo", "riscaldamento", "riscaldamento", "raffreddamento"]
|
||||
assert [d["tipo"] for d in ds] == ["riposo", "riscaldamento", "raffreddamento", "riscaldamento", "raffreddamento",
|
||||
"riscaldamento", "raffreddamento"]
|
||||
|
||||
|
||||
def test_raffreddamento_tau_nominale(csv_gen, cfg):
|
||||
@@ -26,13 +27,13 @@ def test_raffreddamento_tau_nominale(csv_gen, cfg):
|
||||
assert fit["parametri"]["tau"] == pytest.approx(15.9, rel=0.1)
|
||||
|
||||
|
||||
def test_riscaldamento_eredita_costanti(csv_gen, cfg):
|
||||
def test_raffreddamenti_intermedi_ereditano_costanti(csv_gen, cfg):
|
||||
_, ris = analizza(csv_gen, cfg)
|
||||
for nome in ris[0]["serie"]:
|
||||
raff = next(x for x in ris[-1]["serie"][nome]["fit"] if x["modello"] == "esp_decad")["parametri"]
|
||||
for r in ris[1:3]:
|
||||
fit = next(x for x in r["serie"][nome]["fit"] if x["modello"] == "esp_decad")
|
||||
assert fit["fissi"] == ["c", "tau"] and fit["parametri"]["tau"] == raff["tau"] and fit["parametri"]["A"] > 0
|
||||
finale = next(x for x in ris[-1]["serie"][nome]["fit"] if x["modello"] == "esp_decad")["parametri"]
|
||||
for i in (2, 4):
|
||||
fit = next(x for x in ris[i]["serie"][nome]["fit"] if x["modello"] == "esp_decad")
|
||||
assert fit["fissi"] == ["c", "tau"] and fit["parametri"]["tau"] == finale["tau"] and fit["parametri"]["A"] > 0
|
||||
|
||||
|
||||
def test_cli_domini_e_analizza(tmp_path, capsys):
|
||||
@@ -45,12 +46,12 @@ def test_cli_domini_e_analizza(tmp_path, capsys):
|
||||
assert (out / "01_domini/domini.toml").exists() and (out / "01_domini/domini.png").exists()
|
||||
assert not (out / "03_report").exists() or not any((out / "03_report").iterdir()) # `domini` non fa nessun fit
|
||||
cli.main([*base, "analizza", str(csv), "--domini", str(out / "01_domini/domini.toml")]) # domini corretti a mano
|
||||
for f in ("02_sovrapposizione/sovrapposizione_T_C.png", "02_sovrapposizione/dominio4_T_C.png",
|
||||
for f in ("02_sovrapposizione/sovrapposizione_T_C.png", "02_sovrapposizione/dominio7_T_C.png",
|
||||
"03_report/report.md", "03_report/risultati.json"):
|
||||
assert (out / f).exists(), f
|
||||
report = (out / "03_report/report.md").read_text()
|
||||
assert "../01_domini/domini.png" in report and "../02_sovrapposizione/dominio4_T_C.png" in report
|
||||
assert "dominio 4 raffreddamento" in capsys.readouterr().out
|
||||
assert "../01_domini/domini.png" in report and "../02_sovrapposizione/dominio7_T_C.png" in report
|
||||
assert "dominio 7 raffreddamento" in capsys.readouterr().out
|
||||
|
||||
|
||||
def test_cli_errori(tmp_path):
|
||||
|
||||
Reference in new issue
Block a user