Make both batch image exports reproduce the view on screen
Two strands, committed together because they touch the same four files and answer the same question: an exported PNG must be the image the user was looking at when they triggered the export. Dropped view settings (bug fix): - BatchExportWorker forwarded the DC threshold, bg-sub, pad and row- averaging to compute_rf_image but never min_freq_mhz, so every RF and Velocity map was exported with no min peak frequency floor. The pixels the floor exists to reject came back at their pre-floor peaks. - That also decided *which source* the image came from: requesting floor 0 makes a stored v7 cache look like a match (cache_mismatch_reasons only rejects a higher stored floor), so a batch-computed file exported the cached peak-frequency block verbatim - numbers from an earlier Batch Compute run, while the screen showed that same cache re-masked against the live floor. The symptom was a newly loaded file exporting a stale-looking velocity map, since the floor is a display control that survives a load while the window's own FFT cache does not. - export_view_image had the same class of defect with a different parameter: it dropped row_avg_n, so a file whose stored cache is row- averaged displayed from the store but exported as a full raw recompute - a different, and much slower, image. It now reads sras.precomputed_row_avg_n per file, mirroring _stored_fft_image and _start_compute, and derived per file for the same reason n_fft is. Export at the live canvas size: - Both exporters now take the canvas's current figure size instead of a hard-coded 7x5. draw_view_image uses aspect="auto", so the figure box is what sets the map's proportions - a view sized wide on screen was being squeezed into a different shape on disk. Read at trigger time, in inches, so a resize mid-batch cannot change images later in the same run and a HiDPI display exports like a standard one. - sanitize_figsize clamps a degenerate size (collapsed splitter pane, minimized window): a wrong-looking aspect ratio must never be the reason a batch loses an image. Tests: BatchExportWorker had no coverage at all. Four new tests cover the floor being applied, a stored cache never being served unfloored, the menu-to-worker wiring, and the row-averaged cache case; each was verified to fail against the unfixed code. 166 passed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1716,6 +1716,25 @@ class SrasViewerWindow(QMainWindow):
|
||||
# Batch export view as images
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _view_figsize(self) -> tuple[float, float]:
|
||||
"""The image canvas's current figure size in inches — handed to every
|
||||
image export so the PNG has the shape the view is being read at.
|
||||
|
||||
The canvas draws with aspect="auto" and expands with the window, so
|
||||
the map's proportions are the widget's, not the data's; a renderer
|
||||
with its own hard-coded size necessarily distorts the export
|
||||
relative to the screen.
|
||||
|
||||
Inches rather than pixels because that is what Figure takes, and
|
||||
matplotlib's Qt canvas keeps size_inches in logical units (it scales
|
||||
figure.dpi by the device pixel ratio and divides physical pixels by
|
||||
it), so the same window gives the same export on a HiDPI display as
|
||||
on a standard one. Read at trigger time: a resize mid-batch must not
|
||||
change the shape of images later in the same run.
|
||||
"""
|
||||
w, h = self.image_canvas.figure.get_size_inches()
|
||||
return (float(w), float(h))
|
||||
|
||||
def _on_batch_export_images(self):
|
||||
if self._job_running(Jobs.BATCH):
|
||||
return
|
||||
@@ -1751,6 +1770,7 @@ class SrasViewerWindow(QMainWindow):
|
||||
highlight_masked=self.chk_highlight_masked.isChecked(),
|
||||
mode_str=mode_str, colorbar_label=colorbar_label,
|
||||
mask_color=_MASKED_HIGHLIGHT_COLOR,
|
||||
figsize=self._view_figsize(),
|
||||
)
|
||||
started = self._run_worker(
|
||||
Jobs.BATCH, worker,
|
||||
@@ -1858,7 +1878,12 @@ class SrasViewerWindow(QMainWindow):
|
||||
cmap=self.combo_cmap.currentText(),
|
||||
apply_bg_sub=self.chk_bg_sub.isChecked(),
|
||||
dc_threshold_mv=self.spin_threshold_mv.value(),
|
||||
n_fft=self._current_n_fft(), grating_um=self.spin_grating_um.value())
|
||||
n_fft=self._current_n_fft(), grating_um=self.spin_grating_um.value(),
|
||||
# Live, like every other display control here and like
|
||||
# _stored_fft_image: the exported RF/Velocity map has to be the
|
||||
# one on screen, floor included.
|
||||
min_freq_mhz=self.spin_min_freq_mhz.value(),
|
||||
figsize=self._view_figsize())
|
||||
started = self._run_worker(
|
||||
Jobs.EXPORT, worker,
|
||||
connect=(
|
||||
|
||||
Reference in New Issue
Block a user