try to speed up

This commit is contained in:
awe
2026-04-09 19:35:07 +03:00
parent afd8538900
commit bc48b9d432
2 changed files with 67 additions and 5 deletions

View File

@ -37,6 +37,8 @@ from rfg_adc_plotter.processing.peaks import (
from rfg_adc_plotter.state import RingBuffer, RuntimeState from rfg_adc_plotter.state import RingBuffer, RuntimeState
from rfg_adc_plotter.types import SweepAuxCurves, SweepInfo, SweepPacket from rfg_adc_plotter.types import SweepAuxCurves, SweepInfo, SweepPacket
RAW_PLOT_MAX_POINTS = 4096
def _visible_levels_pyqtgraph(data: np.ndarray, plot_item) -> Optional[Tuple[float, float]]: def _visible_levels_pyqtgraph(data: np.ndarray, plot_item) -> Optional[Tuple[float, float]]:
"""Compute vmin/vmax from the currently visible part of an ImageItem.""" """Compute vmin/vmax from the currently visible part of an ImageItem."""
@ -205,6 +207,38 @@ def resolve_visible_aux_curves(aux_curves: SweepAuxCurves, enabled: bool) -> Swe
return aux_1_arr, aux_2_arr return aux_1_arr, aux_2_arr
def decimate_curve_for_display(
xs: Optional[np.ndarray],
ys: Optional[np.ndarray],
*,
max_points: int = RAW_PLOT_MAX_POINTS,
) -> Tuple[np.ndarray, np.ndarray]:
"""Reduce a dense line series before sending it to pyqtgraph."""
if xs is None or ys is None:
return (
np.zeros((0,), dtype=np.float64),
np.zeros((0,), dtype=np.float32),
)
x_arr = np.asarray(xs).reshape(-1)
y_arr = np.asarray(ys).reshape(-1)
width = min(x_arr.size, y_arr.size)
if width <= 0:
return (
np.zeros((0,), dtype=np.float64),
np.zeros((0,), dtype=np.float32),
)
x_arr = x_arr[:width]
y_arr = y_arr[:width]
if max_points <= 1 or width <= int(max_points):
return x_arr, y_arr
display_idx = np.linspace(0, width - 1, int(max_points), dtype=np.int64)
display_idx = np.unique(display_idx)
return x_arr[display_idx], y_arr[display_idx]
def resolve_visible_fft_curves( def resolve_visible_fft_curves(
fft_complex: Optional[np.ndarray], fft_complex: Optional[np.ndarray],
fft_mag: Optional[np.ndarray], fft_mag: Optional[np.ndarray],
@ -1302,15 +1336,18 @@ def run_pyqtgraph(args) -> None:
displayed_aux = resolve_visible_aux_curves(runtime.current_aux_curves, parsed_data_enabled) displayed_aux = resolve_visible_aux_curves(runtime.current_aux_curves, parsed_data_enabled)
if runtime.current_sweep_raw is not None: if runtime.current_sweep_raw is not None:
curve.setData(xs[: runtime.current_sweep_raw.size], runtime.current_sweep_raw, autoDownsample=True) raw_x, raw_y = decimate_curve_for_display(xs, runtime.current_sweep_raw)
curve.setData(raw_x, raw_y, autoDownsample=False)
else: else:
curve.setData([], []) curve.setData([], [])
if displayed_aux is not None: if displayed_aux is not None:
aux_1, aux_2 = displayed_aux aux_1, aux_2 = displayed_aux
aux_width = min(xs.size, aux_1.size, aux_2.size) aux_width = min(xs.size, aux_1.size, aux_2.size)
curve_aux_1.setData(xs[:aux_width], aux_1[:aux_width], autoDownsample=True) aux_x_1, aux_y_1 = decimate_curve_for_display(xs[:aux_width], aux_1[:aux_width])
curve_aux_2.setData(xs[:aux_width], aux_2[:aux_width], autoDownsample=True) aux_x_2, aux_y_2 = decimate_curve_for_display(xs[:aux_width], aux_2[:aux_width])
curve_aux_1.setData(aux_x_1, aux_y_1, autoDownsample=False)
curve_aux_2.setData(aux_x_2, aux_y_2, autoDownsample=False)
else: else:
curve_aux_1.setData([], []) curve_aux_1.setData([], [])
curve_aux_2.setData([], []) curve_aux_2.setData([], [])
@ -1322,13 +1359,15 @@ def run_pyqtgraph(args) -> None:
else: else:
displayed_calib = runtime.calib_envelope displayed_calib = runtime.calib_envelope
xs_calib = resolve_curve_xs(displayed_calib.size) xs_calib = resolve_curve_xs(displayed_calib.size)
curve_calib.setData(xs_calib, displayed_calib, autoDownsample=True) calib_x, calib_y = decimate_curve_for_display(xs_calib, displayed_calib)
curve_calib.setData(calib_x, calib_y, autoDownsample=False)
else: else:
curve_calib.setData([], []) curve_calib.setData([], [])
if runtime.current_sweep_norm is not None: if runtime.current_sweep_norm is not None:
norm_display = runtime.current_sweep_norm * norm_display_scale norm_display = runtime.current_sweep_norm * norm_display_scale
curve_norm.setData(xs[: norm_display.size], norm_display, autoDownsample=True) norm_x, norm_y = decimate_curve_for_display(xs[: norm_display.size], norm_display)
curve_norm.setData(norm_x, norm_y, autoDownsample=False)
else: else:
curve_norm.setData([], []) curve_norm.setData([], [])

View File

@ -10,6 +10,7 @@ from rfg_adc_plotter.gui.pyqtgraph_backend import (
apply_working_range, apply_working_range,
apply_working_range_to_aux_curves, apply_working_range_to_aux_curves,
compute_background_subtracted_bscan_levels, compute_background_subtracted_bscan_levels,
decimate_curve_for_display,
resolve_visible_fft_curves, resolve_visible_fft_curves,
resolve_visible_aux_curves, resolve_visible_aux_curves,
) )
@ -205,6 +206,28 @@ class ProcessingTests(unittest.TestCase):
self.assertTrue(np.allclose(visible[0], aux[0])) self.assertTrue(np.allclose(visible[0], aux[0]))
self.assertTrue(np.allclose(visible[1], aux[1])) self.assertTrue(np.allclose(visible[1], aux[1]))
def test_decimate_curve_for_display_preserves_small_series(self):
xs = np.linspace(3.3, 14.3, 64, dtype=np.float64)
ys = np.linspace(-1.0, 1.0, 64, dtype=np.float32)
decimated_x, decimated_y = decimate_curve_for_display(xs, ys, max_points=128)
self.assertTrue(np.allclose(decimated_x, xs))
self.assertTrue(np.allclose(decimated_y, ys))
def test_decimate_curve_for_display_limits_points_and_keeps_endpoints(self):
xs = np.linspace(3.3, 14.3, 10000, dtype=np.float64)
ys = np.sin(np.linspace(0.0, 12.0 * np.pi, 10000)).astype(np.float32)
decimated_x, decimated_y = decimate_curve_for_display(xs, ys, max_points=512)
self.assertLessEqual(decimated_x.size, 512)
self.assertEqual(decimated_x.shape, decimated_y.shape)
self.assertAlmostEqual(float(decimated_x[0]), float(xs[0]), places=12)
self.assertAlmostEqual(float(decimated_x[-1]), float(xs[-1]), places=12)
self.assertAlmostEqual(float(decimated_y[0]), float(ys[0]), places=6)
self.assertAlmostEqual(float(decimated_y[-1]), float(ys[-1]), places=6)
def test_background_subtracted_bscan_levels_ignore_zero_floor(self): def test_background_subtracted_bscan_levels_ignore_zero_floor(self):
disp_fft_lin = np.zeros((4, 8), dtype=np.float32) disp_fft_lin = np.zeros((4, 8), dtype=np.float32)
disp_fft_lin[1, 2:6] = np.asarray([0.05, 0.1, 0.5, 2.0], dtype=np.float32) disp_fft_lin[1, 2:6] = np.asarray([0.05, 0.1, 0.5, 2.0], dtype=np.float32)