Commit Graph

5 Commits

Author SHA1 Message Date
Thomas Ales 158f60d2a7 Stop recomputing images on display-only setting changes; cache and lazily compute
Colormap, DC threshold, velocity grating, and FFT pad-factor changes were
all routing through a full recompute, which is unworkable on large v6
scans where a single angle's FFT can take minutes. These are now applied
as cheap post-processing on cached data instead:

- ComputeWorker computes CH1/Velocity as an unmasked raw FFT plus its DC4
  mask image, cached per (angle, bg_sub, n_fft). Threshold masking and
  grating scaling are applied to the cached array on redraw, so neither
  needs a recompute; colormap changes only touch matplotlib.
- New DcPrecomputeWorker fills a per-angle DC (CH3/CH4) cache in the
  background right after load, since DC images are cheap (mean, no FFT)
  and make switching angles instant once cached. Progress is shown in the
  Scan Info panel.
- New _refresh_display()/_show_image_now() route every settings-changed
  handler through the cache first, falling back to the existing threaded
  _start_compute() (with a progress popup, now FFT- vs DC-specific) only
  on a genuine cache miss.
- File load now defaults to a DC channel instead of CH1/FFT, so opening a
  large file shows something in seconds instead of minutes.

Verified against a real 532 GB / 17-angle file: DC compute for one angle
takes ~100s+ (I/O-bound over USB) the first time, but switching to an
already-cached angle takes 0.4s with no compute thread spun up at all.

Audited every widget signal connection for this pass; the spinboxes
already correctly used editingFinished rather than valueChanged — the
recompute-on-every-change bug was in the handlers, not the event type.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 20:36:44 -05:00
Thomas Ales 912ae2d15f added gitignore 2026-07-30 20:05:03 -05:00
Thomas Ales 9f92d1826e Fix crash on angle switch with large v6 scans: bound chunk memory, harden thread teardown
Root cause: compute_dc_image/compute_rf_image chunked processing by a fixed
32-row count, sized for old small-format scans. A real v6 file with
spf=2500 and up to ~7500 frames/angle needed ~6-7 GB for a single chunk's
core buffers, on a 17 GB machine — pushing past available memory on every
angle and aborting the process (not a clean MemoryError) when switching to
a new angle piled more allocations on top. Chunk size is now computed from
actual scan dimensions to hit a fixed ~128 MB budget instead of a fixed row
count, cutting peak footprint by roughly 16-18x (verified against the real
532 GB / 17-angle dataset: ~400 MB peak, no crash).

Also hardens QThread lifecycle handling, found while chasing this crash:
- _on_compute_thread_finished/_on_load_thread_finished/
  _on_preprocess_thread_finished now call wait() before dropping the last
  reference to a finished QThread, avoiding "QThread: Destroyed while
  thread is still running" aborts if the OS thread hasn't fully joined
  when finished() fires.
- _start_compute/_load_file/_on_preprocess now claim their QThread
  immediately after the busy-guard check, before any call that can pump
  the Qt event loop (e.g. first QProgressDialog.show()), closing a
  reentrancy window where a second call could start a thread that the
  first call's own assignment would then clobber mid-run.
- faulthandler is enabled at startup so any future native crash prints a
  real stack trace instead of a bare "Aborted".

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 20:04:39 -05:00
Thomas Ales 4a4e588097 Remove Time Gate and SAW pipeline; add SRAS v6 format support
Drops the legacy Time Gate FFT-windowing feature and the SAW matched-filter
pipeline (SawPipeline, SawDiagnosticWindow, TemplateBuildWorker, and the
associated UI panels/channel modes) to simplify the viewer.

Adds native support for the SRAS v6 file format (scan_format.md), which
scans a different bounding box per angle instead of a uniform AABB. Scan
geometry (n_rows, n_frames, x_start) is now exposed per-angle in SrasFile,
with v2-v5 files populating those arrays uniformly so both formats share
one code path. Waveform data is memory-mapped per angle to handle v6's
ragged layout, and aborted/truncated v6 scans are handled gracefully.
"Pre-process and Save as v5" is disabled for v6 files since the flat v5
layout can't represent per-angle geometry.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 19:17:38 -05:00
Thomas Ales f97adba1c0 original program 2026-07-30 18:45:40 -05:00