Persist FFT settings, fix backend naming, parallelise batch DC caching
- FFT backend and pad factor persist across sessions via QSettings
(IniFormat; tests redirect the settings path for hermeticity).
- The default backend was labelled "NumPy FFT" but always dispatched to
scipy.fft — rename the canonical value to "scipy" ("numpy" stays as a
legacy alias) and fix the dialog label.
- cache_file: DC caching fans out over angles via _parallel_map with
per-angle budgets (the DcPrecomputeWorker pattern); FFT caching stays
serial per angle because compute_rf_image now parallelises internally
over blocks. Documented that the v7 FFT cache is natural-resolution
(pad 1) by design.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+24
-9
@@ -35,15 +35,17 @@ try:
|
||||
except ImportError:
|
||||
threadpool_limits = None
|
||||
|
||||
_fft_backend = "numpy" # "numpy" (scipy.fft) or "pyfftw"; set via set_fft_backend()
|
||||
_fft_backend = "scipy" # "scipy" or "pyfftw"; set via set_fft_backend()
|
||||
|
||||
|
||||
def set_fft_backend(name: str):
|
||||
"""Select the rfft implementation. Module-level state, so it must be set
|
||||
explicitly inside each multiprocessing child — it does not survive a
|
||||
spawn."""
|
||||
spawn. "numpy" is accepted as a legacy alias for "scipy"."""
|
||||
global _fft_backend
|
||||
_fft_backend = name if (name != "pyfftw" or PYFFTW_AVAILABLE) else "numpy"
|
||||
if name == "numpy":
|
||||
name = "scipy"
|
||||
_fft_backend = name if (name == "pyfftw" and PYFFTW_AVAILABLE) else "scipy"
|
||||
|
||||
|
||||
def get_fft_backend() -> str:
|
||||
@@ -599,13 +601,17 @@ def compute_rf_image(sras: SrasFile, angle_idx: int,
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def cache_file(path: str, mode: str, apply_bg_sub: bool,
|
||||
fft_backend: str = "numpy", max_workers: int = 0) -> str:
|
||||
fft_backend: str = "scipy", max_workers: int = 0) -> str:
|
||||
"""Compute and store DC or FFT images for every angle of one file,
|
||||
converting v6 → v7 in place. Returns "" on success or an error message.
|
||||
|
||||
Module-level and picklable so it can run in a ProcessPoolExecutor. The
|
||||
FFT backend and worker cap are passed explicitly because module globals
|
||||
do not survive a spawn.
|
||||
|
||||
The stored FFT cache is always natural-resolution (pad 1): the v7 SFFT
|
||||
block records no pad factor, and padded views compute live fast enough
|
||||
(see _peak_bins_zoom) that caching them is not worth a format change.
|
||||
"""
|
||||
global _MAX_WORKERS
|
||||
try:
|
||||
@@ -621,17 +627,26 @@ def cache_file(path: str, mode: str, apply_bg_sub: bool,
|
||||
"can be batch-cached")
|
||||
|
||||
n = sras.n_angles
|
||||
n_workers, angle_budget = plan_angle_level(sras)
|
||||
if mode == "dc":
|
||||
dc3 = [adc_to_mv(compute_dc_image(sras, a, CH3_IDX), *sras.cal(CH3_IDX))
|
||||
for a in range(n)]
|
||||
dc4 = [adc_to_mv(compute_dc_image(sras, a, CH4_IDX), *sras.cal(CH4_IDX))
|
||||
for a in range(n)]
|
||||
dc3 = _parallel_map(
|
||||
lambda a: adc_to_mv(
|
||||
compute_dc_image(sras, a, CH3_IDX, max_workers=1,
|
||||
budget=angle_budget), *sras.cal(CH3_IDX)),
|
||||
range(n), n_workers)
|
||||
dc4 = _parallel_map(
|
||||
lambda a: adc_to_mv(
|
||||
compute_dc_image(sras, a, CH4_IDX, max_workers=1,
|
||||
budget=angle_budget), *sras.cal(CH4_IDX)),
|
||||
range(n), n_workers)
|
||||
sras.write_v7_cache(new_dc3_mv=dc3, new_dc4_mv=dc4)
|
||||
else:
|
||||
effective_bg = apply_bg_sub and sras.background is not None
|
||||
# dc_threshold_mv=None: store unmasked images and mask at display
|
||||
# time (same convention as v5's PREC block). Skipping the mask
|
||||
# also skips reading CH4 entirely.
|
||||
# also skips reading CH4 entirely. The FFT path parallelises
|
||||
# internally over blocks, so angles run one at a time with the
|
||||
# full budget.
|
||||
freq = [compute_rf_image(sras, a, dc_threshold_mv=None,
|
||||
apply_bg_sub=effective_bg)
|
||||
for a in range(n)]
|
||||
|
||||
Reference in New Issue
Block a user