db format

This commit is contained in:
awe
2026-04-29 19:44:47 +03:00
parent a136a6dbf9
commit f9bca446b2
2 changed files with 25 additions and 4 deletions

View File

@ -788,6 +788,14 @@ def compute_background_subtracted_bscan_levels(
return (vmin, vmax) 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: def run_pyqtgraph(args) -> None:
"""Start the PyQtGraph GUI.""" """Start the PyQtGraph GUI."""
peak_calibrate_mode = bool(getattr(args, "calibrate", False)) peak_calibrate_mode = bool(getattr(args, "calibrate", False))
@ -1357,7 +1365,7 @@ def run_pyqtgraph(args) -> None:
padding=0, padding=0,
) )
set_x_range_if_changed("line_x", p_line, f_min, f_max, 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: if disp_fft is not None:
img_fft.setImage(disp_fft, autoLevels=False) 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_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.current_peak_amplitude = None
runtime.peak_candidates = [] runtime.peak_candidates = []
img.setImage(runtime.ring.get_display_raw_decimated(RAW_WATERFALL_MAX_POINTS), autoLevels=False) 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() update_physical_axes()
def refresh_current_window(push_to_ring: bool = False, *, reset_ring: bool = False) -> None: 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: except Exception as exc:
set_status_note(f"фон: не удалось применить ({exc})") set_status_note(f"фон: не удалось применить ({exc})")
active_background = None active_background = None
disp_fft = fft_mag_to_db(disp_fft_lin) disp_fft = fft_bscan_image_to_db(disp_fft_lin)
disp_fft = sanitize_image_for_display(disp_fft)
if disp_fft is None: if disp_fft is None:
set_status_note("b-scan: кадр пропущен", ttl_s=2.0) set_status_note("b-scan: кадр пропущен", ttl_s=2.0)
log_debug_event("invalid_fft_image", "ui invalid FFT waterfall suppressed") log_debug_event("invalid_fft_image", "ui invalid FFT waterfall suppressed")

View File

@ -20,6 +20,7 @@ from rfg_adc_plotter.gui.pyqtgraph_backend import (
convert_tty_i16_to_voltage, convert_tty_i16_to_voltage,
decimate_bscan_rows_for_display, decimate_bscan_rows_for_display,
decimate_curve_for_display, decimate_curve_for_display,
fft_bscan_image_to_db,
is_short_sweep, is_short_sweep,
resolve_axis_bounds, resolve_axis_bounds,
resolve_bscan_refresh_stride, resolve_bscan_refresh_stride,
@ -599,6 +600,17 @@ class ProcessingTests(unittest.TestCase):
self.assertIsNone(levels) 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): def test_fft_helpers_return_expected_shapes(self):
sweep = np.sin(np.linspace(0.0, 4.0 * np.pi, 128)).astype(np.float32) 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) freqs = np.linspace(3.3, 14.3, 128, dtype=np.float64)