phase graph
This commit is contained in:
@ -465,6 +465,23 @@ def resolve_visible_aux_curves(aux_curves: SweepAuxCurves, enabled: bool) -> Swe
|
||||
return aux_1_arr, aux_2_arr
|
||||
|
||||
|
||||
def compute_aux_phase_curve(aux_curves: SweepAuxCurves) -> Optional[np.ndarray]:
|
||||
"""Compute phase-like curve atan2(aux_2, aux_1) for raw CH2/CH1 display."""
|
||||
if aux_curves is None:
|
||||
return None
|
||||
try:
|
||||
aux_1, aux_2 = aux_curves
|
||||
except Exception:
|
||||
return None
|
||||
aux_1_arr = np.asarray(aux_1, dtype=np.float32).reshape(-1)
|
||||
aux_2_arr = np.asarray(aux_2, dtype=np.float32).reshape(-1)
|
||||
width = min(aux_1_arr.size, aux_2_arr.size)
|
||||
if width <= 0:
|
||||
return None
|
||||
phase = np.arctan2(aux_2_arr[:width], aux_1_arr[:width]).astype(np.float32, copy=False)
|
||||
return phase
|
||||
|
||||
|
||||
def decimate_curve_for_display(
|
||||
xs: Optional[np.ndarray],
|
||||
ys: Optional[np.ndarray],
|
||||
@ -717,6 +734,21 @@ def run_pyqtgraph(args) -> None:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
p_line_phase = win.addPlot(row=2, col=0, title="Raw phase: atan(CH2/CH1)")
|
||||
p_line_phase.showGrid(x=True, y=True, alpha=0.3)
|
||||
curve_phase = p_line_phase.plot(pen=pg.mkPen((230, 180, 40), width=1))
|
||||
p_line_phase.setLabel("bottom", "ГГц")
|
||||
p_line_phase.setLabel("left", "рад")
|
||||
try:
|
||||
p_line_phase.setXLink(p_line)
|
||||
except Exception:
|
||||
pass
|
||||
if not complex_sweep_mode:
|
||||
try:
|
||||
p_line_phase.hide()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
p_img = win.addPlot(row=0, col=1, title="Сырые данные водопад")
|
||||
p_img.invertY(False)
|
||||
p_img.showGrid(x=False, y=False)
|
||||
@ -1820,6 +1852,7 @@ def run_pyqtgraph(args) -> None:
|
||||
)
|
||||
displayed_calib = None
|
||||
displayed_aux = resolve_visible_aux_curves(runtime.current_aux_curves, parsed_data_enabled)
|
||||
displayed_phase = compute_aux_phase_curve(displayed_aux)
|
||||
|
||||
if runtime.current_sweep_raw is not None:
|
||||
raw_x, raw_y = decimate_curve_for_display(xs, runtime.current_sweep_raw)
|
||||
@ -1841,6 +1874,14 @@ def run_pyqtgraph(args) -> None:
|
||||
curve_aux_1.setData([], [])
|
||||
curve_aux_2.setData([], [])
|
||||
|
||||
if displayed_phase is not None:
|
||||
phase_width = min(xs.size, displayed_phase.size)
|
||||
phase_x, phase_y = decimate_curve_for_display(xs[:phase_width], displayed_phase[:phase_width])
|
||||
phase_x, phase_y = sanitize_curve_data_for_display(phase_x, phase_y)
|
||||
curve_phase.setData(phase_x, phase_y, autoDownsample=False)
|
||||
else:
|
||||
curve_phase.setData([], [])
|
||||
|
||||
if runtime.calib_envelope is not None:
|
||||
if runtime.current_sweep_raw is not None:
|
||||
displayed_calib = resample_envelope(runtime.calib_envelope, runtime.current_sweep_raw.size)
|
||||
@ -1887,10 +1928,14 @@ def run_pyqtgraph(args) -> None:
|
||||
)
|
||||
if aux_limits is not None:
|
||||
p_line_aux_vb.setYRange(aux_limits[0], aux_limits[1], padding=0)
|
||||
phase_limits = compute_auto_ylim(displayed_phase)
|
||||
if phase_limits is not None:
|
||||
p_line_phase.setYRange(phase_limits[0], phase_limits[1], padding=0)
|
||||
|
||||
line_x_bounds = resolve_axis_bounds(xs)
|
||||
if line_x_bounds is not None:
|
||||
p_line.setXRange(line_x_bounds[0], line_x_bounds[1], padding=0)
|
||||
p_line_phase.setXRange(line_x_bounds[0], line_x_bounds[1], padding=0)
|
||||
|
||||
sweep_for_fft = runtime.current_fft_input
|
||||
if sweep_for_fft is None:
|
||||
|
||||
@ -13,6 +13,7 @@ from rfg_adc_plotter.gui.pyqtgraph_backend import (
|
||||
build_main_window_layout,
|
||||
coalesce_packets_for_ui,
|
||||
compute_background_subtracted_bscan_levels,
|
||||
compute_aux_phase_curve,
|
||||
decimate_curve_for_display,
|
||||
resolve_axis_bounds,
|
||||
resolve_heavy_refresh_stride,
|
||||
@ -217,6 +218,19 @@ class ProcessingTests(unittest.TestCase):
|
||||
self.assertTrue(np.allclose(visible[0], aux[0]))
|
||||
self.assertTrue(np.allclose(visible[1], aux[1]))
|
||||
|
||||
def test_compute_aux_phase_curve_returns_atan2_of_aux_channels(self):
|
||||
aux = (
|
||||
np.asarray([1.0, 1.0, -1.0, 0.0], dtype=np.float32),
|
||||
np.asarray([0.0, 1.0, 1.0, 1.0], dtype=np.float32),
|
||||
)
|
||||
|
||||
phase = compute_aux_phase_curve(aux)
|
||||
|
||||
self.assertIsNotNone(phase)
|
||||
expected = np.asarray([0.0, np.pi / 4.0, 3.0 * np.pi / 4.0, np.pi / 2.0], dtype=np.float32)
|
||||
self.assertEqual(phase.shape, expected.shape)
|
||||
self.assertTrue(np.allclose(phase, expected, atol=1e-6))
|
||||
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user