ampl parser
This commit is contained in:
@ -65,6 +65,7 @@ TTY_CODE_SCALE_DENOM = 32767.0
|
||||
TTY_RANGE_DEFAULT_V = 5.0
|
||||
TTY_RANGE_MIN_V = 1e-6
|
||||
TTY_RANGE_MAX_V = 1_000_000.0
|
||||
LOGDET_EXP_INPUT_LIMIT = 80.0
|
||||
|
||||
|
||||
def sanitize_curve_data_for_display(
|
||||
@ -515,6 +516,30 @@ def convert_tty_i16_to_voltage(codes: np.ndarray, range_v: float) -> np.ndarray:
|
||||
return np.clip(volt, -range_abs_v, range_abs_v).astype(np.float32, copy=False)
|
||||
|
||||
|
||||
def build_logdet_voltage_fft_input(
|
||||
codes: np.ndarray,
|
||||
range_v: float,
|
||||
*,
|
||||
exp_input_limit: float = LOGDET_EXP_INPUT_LIMIT,
|
||||
) -> Tuple[np.ndarray, np.ndarray]:
|
||||
"""Convert 1a00 log-detector codes to raw volts and a real FFT input ``exp(V)``."""
|
||||
volts = convert_tty_i16_to_voltage(codes, range_v)
|
||||
if volts.size <= 0:
|
||||
empty = np.zeros((0,), dtype=np.float32)
|
||||
return empty, empty
|
||||
|
||||
try:
|
||||
limit_v = abs(float(exp_input_limit))
|
||||
except Exception:
|
||||
limit_v = float(LOGDET_EXP_INPUT_LIMIT)
|
||||
if (not np.isfinite(limit_v)) or limit_v <= 0.0:
|
||||
limit_v = float(LOGDET_EXP_INPUT_LIMIT)
|
||||
|
||||
clipped_v = np.clip(volts, -limit_v, limit_v).astype(np.float32, copy=False)
|
||||
fft_input = np.exp(clipped_v).astype(np.float32, copy=False)
|
||||
return volts, fft_input
|
||||
|
||||
|
||||
def decimate_curve_for_display(
|
||||
xs: Optional[np.ndarray],
|
||||
ys: Optional[np.ndarray],
|
||||
@ -1211,6 +1236,50 @@ def run_pyqtgraph(args) -> None:
|
||||
path = ""
|
||||
return path or "fft_background.npy"
|
||||
|
||||
def get_signal_kind(info: Optional[SweepInfo] = None) -> Optional[str]:
|
||||
payload = runtime.current_info if info is None else info
|
||||
if not isinstance(payload, dict):
|
||||
return None
|
||||
signal_kind = payload.get("signal_kind")
|
||||
if signal_kind in {"bin_iq", "bin_logdet"}:
|
||||
return str(signal_kind)
|
||||
return None
|
||||
|
||||
def current_packet_is_complex() -> bool:
|
||||
return bool(complex_sweep_mode) and get_signal_kind() != "bin_logdet"
|
||||
|
||||
def refresh_signal_mode_labels() -> None:
|
||||
signal_kind = get_signal_kind()
|
||||
active_complex = current_packet_is_complex()
|
||||
is_logdet = signal_kind == "bin_logdet"
|
||||
is_bin_iq = signal_kind == "bin_iq"
|
||||
|
||||
try:
|
||||
if is_logdet:
|
||||
p_line.setTitle("Лог-детектор (В)")
|
||||
p_line.setLabel("left", "В")
|
||||
p_fft.setTitle("FFT: exp(V)")
|
||||
parsed_data_cb.setText("Сырые log-detector (В)")
|
||||
elif is_bin_iq:
|
||||
p_line.setTitle("Сырые CH1/CH2 (В) и CH1^2 + CH2^2 (В^2)")
|
||||
p_line.setLabel("left", "CH1^2 + CH2^2, В^2")
|
||||
p_fft.setTitle("FFT: CH1 + i*CH2")
|
||||
parsed_data_cb.setText("Сырые CH1/CH2 (В)")
|
||||
elif complex_sweep_mode:
|
||||
p_line.setTitle("Сырые данные до FFT")
|
||||
p_line.setLabel("left", "Y")
|
||||
p_fft.setTitle("FFT: Re / Im / Abs")
|
||||
parsed_data_cb.setText("Сырые Re/Im")
|
||||
else:
|
||||
p_line.setTitle("Сырые данные")
|
||||
p_line.setLabel("left", "Y")
|
||||
p_fft.setTitle("FFT")
|
||||
parsed_data_cb.setText("данные после парсинга")
|
||||
p_fft.setLabel("left", "Амплитуда" if active_complex else "дБ")
|
||||
p_complex_calib.setVisible(bool(active_complex))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def rebuild_tty_voltage_curves_from_codes() -> bool:
|
||||
if (not bin_iq_power_mode) or runtime.full_current_aux_curves_codes is None:
|
||||
return False
|
||||
@ -1230,8 +1299,28 @@ def run_pyqtgraph(args) -> None:
|
||||
ch_1_v_f64 = ch_1_v.astype(np.float64, copy=False)
|
||||
ch_2_v_f64 = ch_2_v.astype(np.float64, copy=False)
|
||||
runtime.full_current_sweep_raw = np.asarray((ch_1_v_f64 * ch_1_v_f64) + (ch_2_v_f64 * ch_2_v_f64), dtype=np.float32)
|
||||
runtime.full_current_sweep_codes = None
|
||||
return True
|
||||
|
||||
def rebuild_logdet_voltage_curve_from_codes() -> bool:
|
||||
if (not bin_iq_power_mode) or runtime.full_current_sweep_codes is None:
|
||||
return False
|
||||
code_arr = np.asarray(runtime.full_current_sweep_codes, dtype=np.float32).reshape(-1)
|
||||
if code_arr.size <= 0:
|
||||
return False
|
||||
sweep_raw_v, fft_input = build_logdet_voltage_fft_input(code_arr, tty_range_v)
|
||||
runtime.full_current_aux_curves = None
|
||||
runtime.full_current_aux_curves_codes = None
|
||||
runtime.full_current_sweep_raw = sweep_raw_v
|
||||
runtime.full_current_fft_source = fft_input
|
||||
return True
|
||||
|
||||
def rebuild_bin_scaled_curves_from_codes() -> bool:
|
||||
signal_kind = get_signal_kind()
|
||||
if signal_kind == "bin_logdet":
|
||||
return rebuild_logdet_voltage_curve_from_codes()
|
||||
return rebuild_tty_voltage_curves_from_codes()
|
||||
|
||||
def reset_background_state(*, clear_profile: bool = True) -> None:
|
||||
runtime.background_buffer.reset()
|
||||
if clear_profile:
|
||||
@ -1522,7 +1611,7 @@ def run_pyqtgraph(args) -> None:
|
||||
tty_range_spin.setValue(tty_range_v)
|
||||
finally:
|
||||
tty_range_change_in_progress = False
|
||||
if rebuild_tty_voltage_curves_from_codes():
|
||||
if rebuild_bin_scaled_curves_from_codes():
|
||||
reset_background_state(clear_profile=True)
|
||||
refresh_current_window(push_to_ring=True, reset_ring=True)
|
||||
set_status_note(f"tty диапазон: ±{tty_range_v:.6g} В")
|
||||
@ -1790,6 +1879,7 @@ def run_pyqtgraph(args) -> None:
|
||||
set_fft_curve_visibility()
|
||||
set_fft_mode()
|
||||
set_fft_low_cut_percent()
|
||||
refresh_signal_mode_labels()
|
||||
|
||||
try:
|
||||
range_min_spin.valueChanged.connect(lambda _v: set_working_range())
|
||||
@ -2031,10 +2121,23 @@ def run_pyqtgraph(args) -> None:
|
||||
f"ui short sweep width:{int(sweep.size)} expected:{int(runtime.ring.width)}",
|
||||
)
|
||||
base_freqs = np.linspace(SWEEP_FREQ_MIN_GHZ, SWEEP_FREQ_MAX_GHZ, sweep.size, dtype=np.float64)
|
||||
runtime.current_info = info
|
||||
runtime.full_current_aux_curves = None
|
||||
runtime.full_current_aux_curves_codes = None
|
||||
runtime.full_current_sweep_codes = None
|
||||
runtime.full_current_fft_source = None
|
||||
if complex_sweep_mode and aux_curves is not None:
|
||||
signal_kind = get_signal_kind(info)
|
||||
if signal_kind == "bin_logdet":
|
||||
calibrated = calibrate_freqs(
|
||||
{
|
||||
"F": base_freqs,
|
||||
"I": sweep,
|
||||
}
|
||||
)
|
||||
runtime.full_current_freqs = np.asarray(calibrated["F"], dtype=np.float64)
|
||||
runtime.full_current_sweep_codes = np.asarray(calibrated["I"], dtype=np.float32)
|
||||
rebuild_logdet_voltage_curve_from_codes()
|
||||
elif complex_sweep_mode and aux_curves is not None:
|
||||
try:
|
||||
aux_1, aux_2 = aux_curves
|
||||
calibrated_aux_1_payload = calibrate_freqs({"F": base_freqs, "I": aux_1})
|
||||
@ -2083,7 +2186,8 @@ def run_pyqtgraph(args) -> None:
|
||||
except Exception:
|
||||
runtime.full_current_aux_curves = None
|
||||
runtime.full_current_aux_curves_codes = None
|
||||
runtime.current_info = info
|
||||
runtime.full_current_sweep_codes = None
|
||||
refresh_signal_mode_labels()
|
||||
refresh_current_window(push_to_ring=True)
|
||||
processed_frames += 1
|
||||
last_packet_processed_at = time.time()
|
||||
@ -2139,6 +2243,9 @@ def run_pyqtgraph(args) -> None:
|
||||
)
|
||||
|
||||
if redraw_needed:
|
||||
refresh_signal_mode_labels()
|
||||
active_signal_kind = get_signal_kind()
|
||||
active_complex_mode = current_packet_is_complex()
|
||||
xs = resolve_curve_xs(
|
||||
runtime.current_sweep_raw.size
|
||||
if runtime.current_sweep_raw is not None
|
||||
@ -2202,7 +2309,7 @@ def run_pyqtgraph(args) -> None:
|
||||
curve_norm.setData([], [])
|
||||
|
||||
if fixed_ylim is None:
|
||||
if bin_iq_power_mode:
|
||||
if active_signal_kind == "bin_iq":
|
||||
y_series = [
|
||||
runtime.current_sweep_raw,
|
||||
displayed_calib,
|
||||
@ -2237,7 +2344,7 @@ def run_pyqtgraph(args) -> None:
|
||||
|
||||
complex_calib_plot_signal: Optional[np.ndarray] = None
|
||||
if (
|
||||
complex_sweep_mode
|
||||
active_complex_mode
|
||||
and complex_calib_enabled
|
||||
and runtime.current_fft_input is not None
|
||||
and np.iscomplexobj(runtime.current_fft_input)
|
||||
@ -2274,7 +2381,7 @@ def run_pyqtgraph(args) -> None:
|
||||
or runtime.current_fft_mag.size != distance_axis.size
|
||||
or runtime.plot_dirty
|
||||
or (
|
||||
complex_sweep_mode
|
||||
active_complex_mode
|
||||
and (
|
||||
runtime.current_fft_complex is None
|
||||
or runtime.current_fft_complex.size != distance_axis.size
|
||||
@ -2317,7 +2424,7 @@ def run_pyqtgraph(args) -> None:
|
||||
fft_vals_db = fft_mag_to_db(fft_mag_plot)
|
||||
ref_curve_for_range = None
|
||||
|
||||
if complex_sweep_mode:
|
||||
if active_complex_mode:
|
||||
visible_abs, visible_real, visible_imag = resolve_visible_fft_curves(
|
||||
fft_complex_plot,
|
||||
fft_mag_plot,
|
||||
|
||||
Reference in New Issue
Block a user