From 2cf7543bbe9142ca30b0f4dd0e1e2b017da0ddc2 Mon Sep 17 00:00:00 2001 From: awe Date: Mon, 13 Jul 2026 17:58:40 +0100 Subject: [PATCH] fix --- rfg_adc_plotter/gui/pyqtgraph_backend.py | 18 ++++++------------ rfg_adc_plotter/state/ring_buffer.py | 14 +++++++++++++- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/rfg_adc_plotter/gui/pyqtgraph_backend.py b/rfg_adc_plotter/gui/pyqtgraph_backend.py index 5d73cdb..277c33f 100644 --- a/rfg_adc_plotter/gui/pyqtgraph_backend.py +++ b/rfg_adc_plotter/gui/pyqtgraph_backend.py @@ -1640,6 +1640,7 @@ def run_pyqtgraph(args) -> None: changed = runtime.ring.ensure_init(sweep_width) if not changed: return + log_debug_event("ring_resize", f"ring resized to width {int(sweep_width)}", every=1) f_min = float(runtime.range_min_ghz) f_max = float(runtime.range_max_ghz) freq_bounds = resolve_axis_bounds(runtime.current_freqs) @@ -1657,18 +1658,11 @@ def run_pyqtgraph(args) -> None: padding=0, ) set_x_range_if_changed("line_x", p_line, f_min, f_max, padding=0) - disp_fft = fft_bscan_image_to_db(runtime.ring.get_display_fft_linear()) - if disp_fft is not None: - img_fft.setImage(disp_fft, autoLevels=False) - set_image_rect_if_changed("fft_waterfall_rect", img_fft, 0.0, 0.0, float(max_sweeps), 1.0) - set_xy_range_if_changed( - "fft_waterfall_range", - p_spec, - x_bounds=(0, max_sweeps - 1), - y_bounds=(0.0, 1.0), - padding=0, - ) - set_x_range_if_changed("fft_x", p_fft, 0.0, 1.0, padding=0) + # NOTE: do NOT reset the B-scan (fft_waterfall) rect/range to a (0,1) + # placeholder here. The real distance geometry (0..~12 m) is applied every + # frame by update_physical_axes() and the B-scan draw block using the stable + # axis. Writing the placeholder on every ring resize made the B-scan y-axis + # thrash between height 1 and 12 → the flicker. def _active_distance_axis() -> Optional[np.ndarray]: if runtime.current_distances is not None and runtime.current_distances.size > 0: diff --git a/rfg_adc_plotter/state/ring_buffer.py b/rfg_adc_plotter/state/ring_buffer.py index e26855f..5056288 100644 --- a/rfg_adc_plotter/state/ring_buffer.py +++ b/rfg_adc_plotter/state/ring_buffer.py @@ -10,6 +10,13 @@ import numpy as np from rfg_adc_plotter.constants import FFT_LEN, SWEEP_FREQ_MAX_GHZ, SWEEP_FREQ_MIN_GHZ from rfg_adc_plotter.processing.fft import compute_distance_axis, compute_fft_mag_row, fft_mag_to_db +# The device sweep length jitters by a few percent (e.g. 896..920). Only treat a +# shrink as real when the new width drops below this fraction of the current width; +# genuine format changes (e.g. 2048 -> 256, or halving) fall well below it. This +# stops the ring from reallocating every frame — which churned the buffer and made +# the B-scan flicker. +RING_WIDTH_SHRINK_FRACTION = 0.8 + class RingBuffer: """Store raw sweeps, FFT rows, and matching time markers.""" @@ -103,7 +110,12 @@ class RingBuffer: self.ring_fft_input = np.full((self.max_sweeps, self.width), np.nan + 0j, dtype=np.complex64) self.head = 0 changed = True - elif target_width != self.width: + elif target_width > self.width or target_width < int(self.width * RING_WIDTH_SHRINK_FRACTION): + # Resize when the sweep grows, or shrinks by a meaningful fraction (a real + # format change). Ignore small shrinks: the device sweep length jitters by + # a few percent (e.g. 896 vs 920). Resizing on every such shrink churned + # the ring every frame and made the B-scan flicker. A shorter sweep just + # fills fewer columns (the rest stays NaN); the width converges to the max. new_ring = np.full((self.max_sweeps, target_width), np.nan, dtype=np.float32) new_fft_input = np.full((self.max_sweeps, target_width), np.nan + 0j, dtype=np.complex64) take = min(self.width, target_width)