Source code for chaotic_pfc.analysis.sweep._io
"""Sweep I/O: save, load, and path-inference helpers."""
from __future__ import annotations
import warnings
from pathlib import Path
import numpy as np
from ._types import FILTER_TYPES, WINDOW_DISPLAY_NAMES, SweepResult
[docs]
def save_sweep(result: SweepResult, path: str | Path) -> Path:
"""Save a :class:`SweepResult` to a compressed ``.npz``."""
path = Path(path)
path.parent.mkdir(parents=True, exist_ok=True)
payload = {
"h": result.h,
"h_desvio": result.h_std,
"wcorte": result.cutoffs,
"coef": result.orders,
"window": result.window,
"filter_type": result.filter_type,
"metadata": np.array(list(result.metadata.items()), dtype=object),
}
if result.n_iters_used is not None:
payload["n_iters_used"] = result.n_iters_used
np.savez(path, **payload) # type: ignore[arg-type]
return path
[docs]
def load_sweep(path: str | Path) -> SweepResult:
"""Load a sweep from ``.npz`` produced by :func:`save_sweep`."""
path = Path(path)
data = np.load(path, allow_pickle=True)
if "window" in data.files and "filter_type" in data.files:
window = str(data["window"])
filter_type = str(data["filter_type"])
else:
try:
window, filter_type = _infer_config_from_path(path)
except ValueError:
raise ValueError(
f"cannot determine window/filter_type for {path}; "
f"the .npz file has no 'window'/'filter_type' entries "
f"and the parent directory name does not match any known "
f"<(filter_type)> pattern"
) from None
metadata: dict = {}
if "metadata" in data.files:
try:
metadata = dict(data["metadata"].tolist())
except (TypeError, ValueError):
warnings.warn(
f"corrupted metadata in {path} — using empty dict",
RuntimeWarning,
stacklevel=2,
)
n_iters_used = data["n_iters_used"] if "n_iters_used" in data.files else None
return SweepResult(
h=data["h"],
h_std=data["h_desvio"],
orders=data["coef"],
cutoffs=data["wcorte"],
window=window,
filter_type=filter_type,
n_iters_used=n_iters_used,
metadata=metadata,
)
def _infer_config_from_path(path: Path) -> tuple[str, str]:
"""Infer (window, filter_type) from a directory name like ``Hamming (lowpass)``.
Raises
------
ValueError
If the parent directory name does not match any known
``<display_name> (<filter_type>)`` pattern.
"""
name = path.parent.name
for key, pretty in WINDOW_DISPLAY_NAMES.items():
for ft in FILTER_TYPES:
if name == f"{pretty} ({ft})":
return key, ft
raise ValueError(
f"cannot infer (window, filter_type) from directory name {name!r}; "
f"expected pattern '<display_name> (<filter_type>)'"
)