From f9bca446b2383171091a618738317ad27b344388 Mon Sep 17 00:00:00 2001 From: awe Date: Wed, 29 Apr 2026 19:44:47 +0300 Subject: [PATCH] db format --- rfg_adc_plotter/gui/pyqtgraph_backend.py | 17 +++++++++++++---- tests/test_processing.py | 12 ++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/rfg_adc_plotter/gui/pyqtgraph_backend.py b/rfg_adc_plotter/gui/pyqtgraph_backend.py index bc23802..d2570b5 100644 --- a/rfg_adc_plotter/gui/pyqtgraph_backend.py +++ b/rfg_adc_plotter/gui/pyqtgraph_backend.py @@ -788,6 +788,14 @@ def compute_background_subtracted_bscan_levels( return (vmin, vmax) +def fft_bscan_image_to_db(fft_mag: Optional[np.ndarray]) -> Optional[np.ndarray]: + """Convert linear FFT magnitudes to the logarithmic B-scan display image.""" + lin = sanitize_image_for_display(fft_mag) + if lin is None: + return None + return sanitize_image_for_display(fft_mag_to_db(lin)) + + def run_pyqtgraph(args) -> None: """Start the PyQtGraph GUI.""" peak_calibrate_mode = bool(getattr(args, "calibrate", False)) @@ -1357,7 +1365,7 @@ def run_pyqtgraph(args) -> None: padding=0, ) set_x_range_if_changed("line_x", p_line, f_min, f_max, padding=0) - disp_fft = sanitize_image_for_display(runtime.ring.get_display_fft_linear()) + 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) @@ -1693,7 +1701,9 @@ def run_pyqtgraph(args) -> None: runtime.current_peak_amplitude = None runtime.peak_candidates = [] img.setImage(runtime.ring.get_display_raw_decimated(RAW_WATERFALL_MAX_POINTS), autoLevels=False) - img_fft.setImage(runtime.ring.get_display_fft_linear(), autoLevels=False) + 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) update_physical_axes() def refresh_current_window(push_to_ring: bool = False, *, reset_ring: bool = False) -> None: @@ -3334,8 +3344,7 @@ def run_pyqtgraph(args) -> None: except Exception as exc: set_status_note(f"фон: не удалось применить ({exc})") active_background = None - disp_fft = fft_mag_to_db(disp_fft_lin) - disp_fft = sanitize_image_for_display(disp_fft) + disp_fft = fft_bscan_image_to_db(disp_fft_lin) if disp_fft is None: set_status_note("b-scan: кадр пропущен", ttl_s=2.0) log_debug_event("invalid_fft_image", "ui invalid FFT waterfall suppressed") diff --git a/tests/test_processing.py b/tests/test_processing.py index 5493f4d..11fc46b 100644 --- a/tests/test_processing.py +++ b/tests/test_processing.py @@ -20,6 +20,7 @@ from rfg_adc_plotter.gui.pyqtgraph_backend import ( convert_tty_i16_to_voltage, decimate_bscan_rows_for_display, decimate_curve_for_display, + fft_bscan_image_to_db, is_short_sweep, resolve_axis_bounds, resolve_bscan_refresh_stride, @@ -599,6 +600,17 @@ class ProcessingTests(unittest.TestCase): self.assertIsNone(levels) + def test_fft_bscan_image_to_db_converts_linear_magnitudes(self): + linear = np.asarray([[1.0, 10.0], [0.0, 100.0]], dtype=np.float32) + + displayed = fft_bscan_image_to_db(linear) + + self.assertIsNotNone(displayed) + self.assertTrue(np.allclose(displayed, fft_mag_to_db(linear))) + self.assertAlmostEqual(float(displayed[0, 0]), 0.0, places=5) + self.assertGreater(float(displayed[1, 0]), -181.0) + self.assertLess(float(displayed[1, 0]), -179.0) + def test_fft_helpers_return_expected_shapes(self): sweep = np.sin(np.linspace(0.0, 4.0 * np.pi, 128)).astype(np.float32) freqs = np.linspace(3.3, 14.3, 128, dtype=np.float64)