Refactor/parallel and dedup #1
Reference in New Issue
Block a user
Delete Branch "refactor/parallel-and-dedup"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Structure sras_format.py parsing/writing, calibration, axes (numpy + struct) sras_compute.py DC/FFT images, alignment, batch cache (+ scipy) sras_workers.py Qt background workers sras_viewer.py ROI, canvases, dialog, main window format+compute import in 0.59s with no Qt or matplotlib (vs 2.96s for the full app), which is what makes a spawn-based process pool worth using. Deduplication - SrasFile.cal() and compute.dc_image_mv() replace the ADC->mV calibration incantation that appeared at ten call sites. - _read_preambles/_read_background/_set_calibration are shared by the legacy and v6 parsers instead of duplicated. - v5 PREC images are normalised into the same ragged per-angle list v6/v7 uses, removing four isinstance() branches and shortening compute_rf_image's fast path. - _run_worker replaces five copies of the QThread setup and five near-identical teardown methods; the two lifetime hazards they guarded against are now documented once, authoritatively. - _on_channel_changed defers to _update_controls_enabled rather than re-deriving the same six enable rules. - _corners_in_ref_frame, _CHANNEL_DISPLAY dict, unified progress-dialog helper, dead _on_roi_angle_edited stub removed. - sras_average.py builds on SrasFile instead of carrying a second copy of the header format, and streams per angle instead of loading the whole file (was a ~3x file-size peak). Executable lines: 2390 -> 2254, despite adding all of the below. Parallelism - compute_rf_image/compute_dc_image map row chunks over a thread pool. Worker count is derived from the memory budget rather than the core count: on a large scan chunk_rows is already floored at 1 row (~75 MB of float32 at 7507x2500), so only the worker count can bound peak RAM. - DcPrecomputeWorker computes angles on a pool, emitting each result from its own QThread as it lands. - BatchCacheWorker runs one process per file via cache_file(); only paths and scalars cross the boundary. Per-process thread counts are divided so the two levels don't oversubscribe. Drops the old pass 1, which fully parsed every file just to weight a progress bar. - dc_threshold_mv=None means "no mask" and skips the CH4 read entirely — the batch FFT job previously read all of CH4 to compare against a threshold of -1e9. - Alignment mask and correlation stages map over angles; fft2/ifft2 use workers=-1. Fixes found on the way - A partially-cached v5 file showed an all-zero image for uncached angles: the fast-path check was file-wide, not per-angle. - v7 cached images were read-only big-endian views; now native float32. Verified: tools/check_equivalence.py produces byte-identical hashes for 167 outputs (DC/FFT across channels, angles, bg-sub, pad factors and thresholds, plus the full alignment result) againsted0eba4, on both synthetic files and a real 496 GB 17-angle v6 scan. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>