checkbox log det raw
This commit is contained in:
@ -112,6 +112,64 @@ def apply_working_range(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def apply_working_range_to_aux_curves(
|
||||||
|
freqs: Optional[np.ndarray],
|
||||||
|
sweep: Optional[np.ndarray],
|
||||||
|
aux_curves: SweepAuxCurves,
|
||||||
|
range_min_ghz: float,
|
||||||
|
range_max_ghz: float,
|
||||||
|
) -> SweepAuxCurves:
|
||||||
|
"""Crop parser-side auxiliary curves using the same mask as the raw sweep."""
|
||||||
|
if freqs is None or sweep is None or aux_curves is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
aux_1, aux_2 = aux_curves
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
freq_arr = np.asarray(freqs, dtype=np.float64).reshape(-1)
|
||||||
|
sweep_arr = np.asarray(sweep, dtype=np.float32).reshape(-1)
|
||||||
|
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(freq_arr.size, sweep_arr.size, aux_1_arr.size, aux_2_arr.size)
|
||||||
|
if width <= 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
freq_arr = freq_arr[:width]
|
||||||
|
sweep_arr = sweep_arr[:width]
|
||||||
|
aux_1_arr = aux_1_arr[:width]
|
||||||
|
aux_2_arr = aux_2_arr[:width]
|
||||||
|
valid = (
|
||||||
|
np.isfinite(freq_arr)
|
||||||
|
& np.isfinite(sweep_arr)
|
||||||
|
& (freq_arr >= float(range_min_ghz))
|
||||||
|
& (freq_arr <= float(range_max_ghz))
|
||||||
|
)
|
||||||
|
if not np.any(valid):
|
||||||
|
return None
|
||||||
|
|
||||||
|
return (
|
||||||
|
aux_1_arr[valid].astype(np.float32, copy=False),
|
||||||
|
aux_2_arr[valid].astype(np.float32, copy=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_visible_aux_curves(aux_curves: SweepAuxCurves, enabled: bool) -> SweepAuxCurves:
|
||||||
|
"""Return auxiliary curves only when their display is enabled."""
|
||||||
|
if (not enabled) or 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)
|
||||||
|
if aux_1_arr.size <= 0 or aux_2_arr.size <= 0:
|
||||||
|
return None
|
||||||
|
return aux_1_arr, aux_2_arr
|
||||||
|
|
||||||
|
|
||||||
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))
|
||||||
@ -192,6 +250,8 @@ def run_pyqtgraph(args) -> None:
|
|||||||
p_line = win.addPlot(row=0, col=0, title="Сырые данные")
|
p_line = win.addPlot(row=0, col=0, title="Сырые данные")
|
||||||
p_line.showGrid(x=True, y=True, alpha=0.3)
|
p_line.showGrid(x=True, y=True, alpha=0.3)
|
||||||
curve = p_line.plot(pen=pg.mkPen((80, 120, 255), width=1))
|
curve = p_line.plot(pen=pg.mkPen((80, 120, 255), width=1))
|
||||||
|
curve_aux_1 = p_line.plot(pen=pg.mkPen((255, 170, 40), width=1))
|
||||||
|
curve_aux_2 = p_line.plot(pen=pg.mkPen((170, 70, 255), width=1))
|
||||||
curve_calib = p_line.plot(pen=pg.mkPen((220, 60, 60), width=1))
|
curve_calib = p_line.plot(pen=pg.mkPen((220, 60, 60), width=1))
|
||||||
curve_norm = p_line.plot(pen=pg.mkPen((60, 180, 90), width=1))
|
curve_norm = p_line.plot(pen=pg.mkPen((60, 180, 90), width=1))
|
||||||
p_line.setLabel("bottom", "ГГц")
|
p_line.setLabel("bottom", "ГГц")
|
||||||
@ -328,12 +388,14 @@ def run_pyqtgraph(args) -> None:
|
|||||||
background_buttons_row.addWidget(background_save_btn)
|
background_buttons_row.addWidget(background_save_btn)
|
||||||
background_buttons_row.addWidget(background_load_btn)
|
background_buttons_row.addWidget(background_load_btn)
|
||||||
background_group_layout.addLayout(background_buttons_row)
|
background_group_layout.addLayout(background_buttons_row)
|
||||||
|
parsed_data_cb = QtWidgets.QCheckBox("данные после парсинга")
|
||||||
try:
|
try:
|
||||||
settings_layout.addWidget(QtWidgets.QLabel("Настройки"))
|
settings_layout.addWidget(QtWidgets.QLabel("Настройки"))
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
settings_layout.addWidget(range_group)
|
settings_layout.addWidget(range_group)
|
||||||
settings_layout.addWidget(calib_group)
|
settings_layout.addWidget(calib_group)
|
||||||
|
settings_layout.addWidget(parsed_data_cb)
|
||||||
settings_layout.addWidget(background_group)
|
settings_layout.addWidget(background_group)
|
||||||
settings_layout.addWidget(fft_mode_label)
|
settings_layout.addWidget(fft_mode_label)
|
||||||
settings_layout.addWidget(fft_mode_combo)
|
settings_layout.addWidget(fft_mode_combo)
|
||||||
@ -343,6 +405,7 @@ def run_pyqtgraph(args) -> None:
|
|||||||
win.addItem(status, row=3, col=0, colspan=2)
|
win.addItem(status, row=3, col=0, colspan=2)
|
||||||
|
|
||||||
calib_enabled = False
|
calib_enabled = False
|
||||||
|
parsed_data_enabled = False
|
||||||
background_enabled = False
|
background_enabled = False
|
||||||
fft_mode = "symmetric"
|
fft_mode = "symmetric"
|
||||||
status_note = ""
|
status_note = ""
|
||||||
@ -489,6 +552,7 @@ def run_pyqtgraph(args) -> None:
|
|||||||
if runtime.full_current_freqs is None or runtime.full_current_sweep_raw is None:
|
if runtime.full_current_freqs is None or runtime.full_current_sweep_raw is None:
|
||||||
runtime.current_freqs = None
|
runtime.current_freqs = None
|
||||||
runtime.current_sweep_raw = None
|
runtime.current_sweep_raw = None
|
||||||
|
runtime.current_aux_curves = None
|
||||||
runtime.current_sweep_norm = None
|
runtime.current_sweep_norm = None
|
||||||
runtime.current_fft_mag = None
|
runtime.current_fft_mag = None
|
||||||
runtime.current_fft_db = None
|
runtime.current_fft_db = None
|
||||||
@ -503,12 +567,20 @@ def run_pyqtgraph(args) -> None:
|
|||||||
)
|
)
|
||||||
runtime.current_freqs = current_freqs
|
runtime.current_freqs = current_freqs
|
||||||
runtime.current_sweep_raw = current_sweep
|
runtime.current_sweep_raw = current_sweep
|
||||||
|
runtime.current_aux_curves = apply_working_range_to_aux_curves(
|
||||||
|
runtime.full_current_freqs,
|
||||||
|
runtime.full_current_sweep_raw,
|
||||||
|
runtime.full_current_aux_curves,
|
||||||
|
runtime.range_min_ghz,
|
||||||
|
runtime.range_max_ghz,
|
||||||
|
)
|
||||||
|
|
||||||
if runtime.current_sweep_raw.size == 0:
|
if runtime.current_sweep_raw.size == 0:
|
||||||
if push_to_ring:
|
if push_to_ring:
|
||||||
reset_ring_buffers()
|
reset_ring_buffers()
|
||||||
runtime.current_freqs = None
|
runtime.current_freqs = None
|
||||||
runtime.current_sweep_raw = None
|
runtime.current_sweep_raw = None
|
||||||
|
runtime.current_aux_curves = None
|
||||||
runtime.current_sweep_norm = None
|
runtime.current_sweep_norm = None
|
||||||
runtime.current_fft_mag = None
|
runtime.current_fft_mag = None
|
||||||
runtime.current_fft_db = None
|
runtime.current_fft_db = None
|
||||||
@ -559,6 +631,14 @@ def run_pyqtgraph(args) -> None:
|
|||||||
recompute_current_processed_sweep(push_to_ring=False)
|
recompute_current_processed_sweep(push_to_ring=False)
|
||||||
runtime.mark_dirty()
|
runtime.mark_dirty()
|
||||||
|
|
||||||
|
def set_parsed_data_enabled() -> None:
|
||||||
|
nonlocal parsed_data_enabled
|
||||||
|
try:
|
||||||
|
parsed_data_enabled = bool(parsed_data_cb.isChecked())
|
||||||
|
except Exception:
|
||||||
|
parsed_data_enabled = False
|
||||||
|
runtime.mark_dirty()
|
||||||
|
|
||||||
def restore_range_controls() -> None:
|
def restore_range_controls() -> None:
|
||||||
nonlocal range_change_in_progress
|
nonlocal range_change_in_progress
|
||||||
range_change_in_progress = True
|
range_change_in_progress = True
|
||||||
@ -760,6 +840,7 @@ def run_pyqtgraph(args) -> None:
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
restore_range_controls()
|
restore_range_controls()
|
||||||
|
set_parsed_data_enabled()
|
||||||
set_background_enabled()
|
set_background_enabled()
|
||||||
set_fft_mode()
|
set_fft_mode()
|
||||||
|
|
||||||
@ -767,6 +848,7 @@ def run_pyqtgraph(args) -> None:
|
|||||||
range_min_spin.valueChanged.connect(lambda _v: set_working_range())
|
range_min_spin.valueChanged.connect(lambda _v: set_working_range())
|
||||||
range_max_spin.valueChanged.connect(lambda _v: set_working_range())
|
range_max_spin.valueChanged.connect(lambda _v: set_working_range())
|
||||||
calib_cb.stateChanged.connect(lambda _v: set_calib_enabled())
|
calib_cb.stateChanged.connect(lambda _v: set_calib_enabled())
|
||||||
|
parsed_data_cb.stateChanged.connect(lambda _v: set_parsed_data_enabled())
|
||||||
calib_pick_btn.clicked.connect(lambda _checked=False: pick_calib_file())
|
calib_pick_btn.clicked.connect(lambda _checked=False: pick_calib_file())
|
||||||
calib_save_btn.clicked.connect(lambda _checked=False: save_current_calibration())
|
calib_save_btn.clicked.connect(lambda _checked=False: save_current_calibration())
|
||||||
calib_load_btn.clicked.connect(lambda _checked=False: load_calibration_file())
|
calib_load_btn.clicked.connect(lambda _checked=False: load_calibration_file())
|
||||||
@ -953,15 +1035,28 @@ def run_pyqtgraph(args) -> None:
|
|||||||
except Empty:
|
except Empty:
|
||||||
break
|
break
|
||||||
drained += 1
|
drained += 1
|
||||||
|
base_freqs = np.linspace(SWEEP_FREQ_MIN_GHZ, SWEEP_FREQ_MAX_GHZ, sweep.size, dtype=np.float64)
|
||||||
calibrated = calibrate_freqs(
|
calibrated = calibrate_freqs(
|
||||||
{
|
{
|
||||||
"F": np.linspace(SWEEP_FREQ_MIN_GHZ, SWEEP_FREQ_MAX_GHZ, sweep.size, dtype=np.float64),
|
"F": base_freqs,
|
||||||
"I": sweep,
|
"I": sweep,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
runtime.full_current_freqs = np.asarray(calibrated["F"], dtype=np.float64)
|
runtime.full_current_freqs = np.asarray(calibrated["F"], dtype=np.float64)
|
||||||
runtime.full_current_sweep_raw = np.asarray(calibrated["I"], dtype=np.float32)
|
runtime.full_current_sweep_raw = np.asarray(calibrated["I"], dtype=np.float32)
|
||||||
runtime.current_aux_curves = aux_curves
|
if aux_curves is None:
|
||||||
|
runtime.full_current_aux_curves = None
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
aux_1, aux_2 = aux_curves
|
||||||
|
calibrated_aux_1 = calibrate_freqs({"F": base_freqs, "I": aux_1})["I"]
|
||||||
|
calibrated_aux_2 = calibrate_freqs({"F": base_freqs, "I": aux_2})["I"]
|
||||||
|
runtime.full_current_aux_curves = (
|
||||||
|
np.asarray(calibrated_aux_1, dtype=np.float32),
|
||||||
|
np.asarray(calibrated_aux_2, dtype=np.float32),
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
runtime.full_current_aux_curves = None
|
||||||
runtime.current_info = info
|
runtime.current_info = info
|
||||||
refresh_current_window(push_to_ring=True)
|
refresh_current_window(push_to_ring=True)
|
||||||
if drained > 0:
|
if drained > 0:
|
||||||
@ -996,12 +1091,22 @@ def run_pyqtgraph(args) -> None:
|
|||||||
else (runtime.calib_envelope.size if runtime.calib_envelope is not None else 0)
|
else (runtime.calib_envelope.size if runtime.calib_envelope is not None else 0)
|
||||||
)
|
)
|
||||||
displayed_calib = None
|
displayed_calib = None
|
||||||
|
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)
|
curve.setData(xs[: runtime.current_sweep_raw.size], runtime.current_sweep_raw, autoDownsample=True)
|
||||||
else:
|
else:
|
||||||
curve.setData([], [])
|
curve.setData([], [])
|
||||||
|
|
||||||
|
if displayed_aux is not None:
|
||||||
|
aux_1, aux_2 = displayed_aux
|
||||||
|
aux_width = min(xs.size, aux_1.size, aux_2.size)
|
||||||
|
curve_aux_1.setData(xs[:aux_width], aux_1[:aux_width], autoDownsample=True)
|
||||||
|
curve_aux_2.setData(xs[:aux_width], aux_2[:aux_width], autoDownsample=True)
|
||||||
|
else:
|
||||||
|
curve_aux_1.setData([], [])
|
||||||
|
curve_aux_2.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)
|
||||||
@ -1022,6 +1127,8 @@ def run_pyqtgraph(args) -> None:
|
|||||||
if fixed_ylim is None:
|
if fixed_ylim is None:
|
||||||
y_series = [
|
y_series = [
|
||||||
runtime.current_sweep_raw,
|
runtime.current_sweep_raw,
|
||||||
|
displayed_aux[0] if displayed_aux is not None else None,
|
||||||
|
displayed_aux[1] if displayed_aux is not None else None,
|
||||||
displayed_calib,
|
displayed_calib,
|
||||||
(runtime.current_sweep_norm * norm_display_scale) if runtime.current_sweep_norm is not None else None,
|
(runtime.current_sweep_norm * norm_display_scale) if runtime.current_sweep_norm is not None else None,
|
||||||
]
|
]
|
||||||
|
|||||||
@ -20,6 +20,7 @@ class RuntimeState:
|
|||||||
range_max_ghz: float = 0.0
|
range_max_ghz: float = 0.0
|
||||||
full_current_freqs: Optional[np.ndarray] = None
|
full_current_freqs: Optional[np.ndarray] = None
|
||||||
full_current_sweep_raw: Optional[np.ndarray] = None
|
full_current_sweep_raw: Optional[np.ndarray] = None
|
||||||
|
full_current_aux_curves: SweepAuxCurves = None
|
||||||
current_freqs: Optional[np.ndarray] = None
|
current_freqs: Optional[np.ndarray] = None
|
||||||
current_distances: Optional[np.ndarray] = None
|
current_distances: Optional[np.ndarray] = None
|
||||||
current_sweep_raw: Optional[np.ndarray] = None
|
current_sweep_raw: Optional[np.ndarray] = None
|
||||||
|
|||||||
@ -6,7 +6,11 @@ import numpy as np
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from rfg_adc_plotter.constants import FFT_LEN, SWEEP_FREQ_MAX_GHZ, SWEEP_FREQ_MIN_GHZ
|
from rfg_adc_plotter.constants import FFT_LEN, SWEEP_FREQ_MAX_GHZ, SWEEP_FREQ_MIN_GHZ
|
||||||
from rfg_adc_plotter.gui.pyqtgraph_backend import apply_working_range
|
from rfg_adc_plotter.gui.pyqtgraph_backend import (
|
||||||
|
apply_working_range,
|
||||||
|
apply_working_range_to_aux_curves,
|
||||||
|
resolve_visible_aux_curves,
|
||||||
|
)
|
||||||
from rfg_adc_plotter.processing.calibration import (
|
from rfg_adc_plotter.processing.calibration import (
|
||||||
build_calib_envelope,
|
build_calib_envelope,
|
||||||
calibrate_freqs,
|
calibrate_freqs,
|
||||||
@ -146,6 +150,36 @@ class ProcessingTests(unittest.TestCase):
|
|||||||
self.assertEqual(cropped_freqs.shape, (0,))
|
self.assertEqual(cropped_freqs.shape, (0,))
|
||||||
self.assertEqual(cropped_sweep.shape, (0,))
|
self.assertEqual(cropped_sweep.shape, (0,))
|
||||||
|
|
||||||
|
def test_apply_working_range_to_aux_curves_uses_same_mask_as_raw_sweep(self):
|
||||||
|
freqs = np.linspace(3.3, 14.3, 6, dtype=np.float64)
|
||||||
|
sweep = np.asarray([0.0, 1.0, np.nan, 3.0, 4.0, 5.0], dtype=np.float32)
|
||||||
|
aux = (
|
||||||
|
np.asarray([10.0, 11.0, 12.0, 13.0, 14.0, 15.0], dtype=np.float32),
|
||||||
|
np.asarray([20.0, 21.0, 22.0, 23.0, 24.0, 25.0], dtype=np.float32),
|
||||||
|
)
|
||||||
|
|
||||||
|
cropped_freqs, cropped_sweep = apply_working_range(freqs, sweep, 4.0, 12.5)
|
||||||
|
cropped_aux = apply_working_range_to_aux_curves(freqs, sweep, aux, 4.0, 12.5)
|
||||||
|
|
||||||
|
self.assertIsNotNone(cropped_aux)
|
||||||
|
self.assertEqual(cropped_aux[0].shape, cropped_freqs.shape)
|
||||||
|
self.assertEqual(cropped_aux[1].shape, cropped_freqs.shape)
|
||||||
|
self.assertEqual(cropped_aux[0].shape, cropped_sweep.shape)
|
||||||
|
self.assertTrue(np.allclose(cropped_aux[0], np.asarray([11.0, 13.0, 14.0], dtype=np.float32)))
|
||||||
|
self.assertTrue(np.allclose(cropped_aux[1], np.asarray([21.0, 23.0, 24.0], dtype=np.float32)))
|
||||||
|
|
||||||
|
def test_resolve_visible_aux_curves_obeys_checkbox_state(self):
|
||||||
|
aux = (
|
||||||
|
np.asarray([1.0, 2.0], dtype=np.float32),
|
||||||
|
np.asarray([3.0, 4.0], dtype=np.float32),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertIsNone(resolve_visible_aux_curves(aux, enabled=False))
|
||||||
|
visible = resolve_visible_aux_curves(aux, enabled=True)
|
||||||
|
self.assertIsNotNone(visible)
|
||||||
|
self.assertTrue(np.allclose(visible[0], aux[0]))
|
||||||
|
self.assertTrue(np.allclose(visible[1], aux[1]))
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
Reference in New Issue
Block a user