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
|
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(
|
def decimate_curve_for_display(
|
||||||
xs: Optional[np.ndarray],
|
xs: Optional[np.ndarray],
|
||||||
ys: Optional[np.ndarray],
|
ys: Optional[np.ndarray],
|
||||||
@ -717,6 +734,21 @@ def run_pyqtgraph(args) -> None:
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
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 = win.addPlot(row=0, col=1, title="Сырые данные водопад")
|
||||||
p_img.invertY(False)
|
p_img.invertY(False)
|
||||||
p_img.showGrid(x=False, y=False)
|
p_img.showGrid(x=False, y=False)
|
||||||
@ -1820,6 +1852,7 @@ def run_pyqtgraph(args) -> None:
|
|||||||
)
|
)
|
||||||
displayed_calib = None
|
displayed_calib = 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)
|
||||||
|
displayed_phase = compute_aux_phase_curve(displayed_aux)
|
||||||
|
|
||||||
if runtime.current_sweep_raw is not None:
|
if runtime.current_sweep_raw is not None:
|
||||||
raw_x, raw_y = decimate_curve_for_display(xs, runtime.current_sweep_raw)
|
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_1.setData([], [])
|
||||||
curve_aux_2.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.calib_envelope is not None:
|
||||||
if runtime.current_sweep_raw is not None:
|
if runtime.current_sweep_raw is not None:
|
||||||
displayed_calib = resample_envelope(runtime.calib_envelope, runtime.current_sweep_raw.size)
|
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:
|
if aux_limits is not None:
|
||||||
p_line_aux_vb.setYRange(aux_limits[0], aux_limits[1], padding=0)
|
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)
|
line_x_bounds = resolve_axis_bounds(xs)
|
||||||
if line_x_bounds is not None:
|
if line_x_bounds is not None:
|
||||||
p_line.setXRange(line_x_bounds[0], line_x_bounds[1], padding=0)
|
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
|
sweep_for_fft = runtime.current_fft_input
|
||||||
if sweep_for_fft is None:
|
if sweep_for_fft is None:
|
||||||
|
|||||||
@ -13,6 +13,7 @@ from rfg_adc_plotter.gui.pyqtgraph_backend import (
|
|||||||
build_main_window_layout,
|
build_main_window_layout,
|
||||||
coalesce_packets_for_ui,
|
coalesce_packets_for_ui,
|
||||||
compute_background_subtracted_bscan_levels,
|
compute_background_subtracted_bscan_levels,
|
||||||
|
compute_aux_phase_curve,
|
||||||
decimate_curve_for_display,
|
decimate_curve_for_display,
|
||||||
resolve_axis_bounds,
|
resolve_axis_bounds,
|
||||||
resolve_heavy_refresh_stride,
|
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[0], aux[0]))
|
||||||
self.assertTrue(np.allclose(visible[1], aux[1]))
|
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):
|
def test_decimate_curve_for_display_preserves_small_series(self):
|
||||||
xs = np.linspace(3.3, 14.3, 64, dtype=np.float64)
|
xs = np.linspace(3.3, 14.3, 64, dtype=np.float64)
|
||||||
ys = np.linspace(-1.0, 1.0, 64, dtype=np.float32)
|
ys = np.linspace(-1.0, 1.0, 64, dtype=np.float32)
|
||||||
|
|||||||
Reference in New Issue
Block a user