fix carry

This commit is contained in:
awe
2026-05-05 09:29:29 +03:00
parent d437ab1642
commit 5591e80c53
2 changed files with 75 additions and 21 deletions

View File

@ -102,6 +102,32 @@ def display_distance_axis(
return (float(zero_at_m) - axis_arr).astype(np.float64, copy=False)
def display_distance_transform_enabled(mode: str | None) -> bool:
"""Only the exact positive-only IFFT mode uses the shifted/reversed display axis."""
return str(mode or "").strip().lower() == "positive_only_exact"
def display_distance_value_for_mode(distance_m: float, mode: str | None) -> float:
if display_distance_transform_enabled(mode):
return display_distance_value(distance_m)
try:
distance_val = float(distance_m)
except Exception:
return float("nan")
return distance_val if np.isfinite(distance_val) else float("nan")
def display_distance_axis_for_mode(distance_axis: Optional[np.ndarray], mode: str | None) -> np.ndarray:
if display_distance_transform_enabled(mode):
return display_distance_axis(distance_axis)
if distance_axis is None:
return np.zeros((0,), dtype=np.float64)
axis_arr = np.asarray(distance_axis, dtype=np.float64).reshape(-1)
if axis_arr.size <= 0:
return np.zeros((0,), dtype=np.float64)
return axis_arr
def sanitize_curve_data_for_display(
xs: Optional[np.ndarray],
ys: Optional[np.ndarray],
@ -1022,7 +1048,7 @@ def run_pyqtgraph(args) -> None:
fft_bg_line.setVisible(False)
fft_left_line.setVisible(False)
fft_right_line.setVisible(False)
p_fft.setLabel("bottom", "Расстояние, м (0 = 9 м)")
p_fft.setLabel("bottom", "Расстояние, м")
p_fft.setLabel("left", "Амплитуда" if complex_sweep_mode else "дБ")
if complex_sweep_mode:
try:
@ -1043,7 +1069,7 @@ def run_pyqtgraph(args) -> None:
p_spec.getAxis("bottom").setStyle(showValues=False)
except Exception:
pass
p_spec.setLabel("left", "Расстояние, м (0 = 9 м)")
p_spec.setLabel("left", "Расстояние, м")
img_fft = pg.ImageItem()
p_spec.addItem(img_fft)
spec_left_line = pg.InfiniteLine(angle=0, movable=False, pen=peak_pen)
@ -1441,6 +1467,18 @@ def run_pyqtgraph(args) -> None:
set_item_visible_if_changed("spec_left_line", spec_left_line, visible)
set_item_visible_if_changed("spec_right_line", spec_right_line, visible)
def refresh_distance_axis_labels() -> None:
distance_label = (
"Расстояние, м (0 = 9 м)"
if display_distance_transform_enabled(fft_mode)
else "Расстояние, м"
)
try:
p_fft.setLabel("bottom", distance_label)
p_spec.setLabel("left", distance_label)
except Exception:
pass
fixed_ylim: Optional[Tuple[float, float]] = None
if args.ylim:
try:
@ -1498,7 +1536,7 @@ def run_pyqtgraph(args) -> None:
text = f"{fft_low_cut_percent:.1f}%"
cut_start = _active_distance_cut_start()
if cut_start is not None and np.isfinite(cut_start):
text = f"{text} (~{display_distance_value(cut_start):.4g} м)"
text = f"{text} (~{display_distance_value_for_mode(cut_start, fft_mode):.4g} м)"
if text == last_fft_low_cut_label_text:
return
try:
@ -1527,7 +1565,7 @@ def run_pyqtgraph(args) -> None:
distance_bounds = resolve_axis_bounds(runtime.ring.distance_axis)
if distance_bounds is not None:
display_axis_full = display_distance_axis(runtime.ring.distance_axis)
display_axis_full = display_distance_axis_for_mode(runtime.ring.distance_axis, fft_mode)
display_bounds = resolve_axis_bounds(display_axis_full)
if display_bounds is not None:
d_min_display, d_max_display = display_bounds
@ -1549,7 +1587,7 @@ def run_pyqtgraph(args) -> None:
d_cut = _active_distance_cut_start()
fft_axis_physical, _fft_keep = apply_distance_cut_to_axis(runtime.ring.distance_axis, d_cut)
fft_display_bounds = resolve_axis_bounds(display_distance_axis(fft_axis_physical))
fft_display_bounds = resolve_axis_bounds(display_distance_axis_for_mode(fft_axis_physical, fft_mode))
if fft_display_bounds is not None:
set_x_range_if_changed("fft_x", p_fft, fft_display_bounds[0], fft_display_bounds[1], padding=0)
refresh_fft_low_cut_label()
@ -2398,6 +2436,7 @@ def run_pyqtgraph(args) -> None:
"positive_only": "IFFT: нули [-max,+min]",
"positive_only_exact": "IFFT: нули [-max,+min] точный",
}.get(fft_mode, f"IFFT: {fft_mode}")
refresh_distance_axis_labels()
set_status_note(mode_label)
update_physical_axes()
runtime.mark_dirty()
@ -2457,7 +2496,7 @@ def run_pyqtgraph(args) -> None:
if idx < len(peaks):
peak = peaks[idx]
lines.append(f"peak {idx + 1}:")
lines.append(f" X: {display_distance_value(peak['x']):.4g} m")
lines.append(f" X: {display_distance_value_for_mode(peak['x'], fft_mode):.4g} m")
lines.append(f" H: {peak['height']:.4g} dB")
lines.append(f" W: {peak['width']:.4g} m")
else:
@ -3186,7 +3225,7 @@ def run_pyqtgraph(args) -> None:
fft_complex_plot = fft_complex_plot[fft_keep_mask]
elif fft_complex_plot is not None:
fft_complex_plot = None
xs_fft_display = display_distance_axis(xs_fft)
xs_fft_display = display_distance_axis_for_mode(xs_fft, fft_mode)
fft_x_bounds = resolve_axis_bounds(xs_fft_display)
if fft_x_bounds is not None:
set_x_range_if_changed("fft_x", p_fft, fft_x_bounds[0], fft_x_bounds[1], padding=0)
@ -3244,11 +3283,12 @@ def run_pyqtgraph(args) -> None:
set_curve_data(
f"fft_peak_box_{idx}",
box,
display_distance_axis(
display_distance_axis_for_mode(
np.asarray(
[peak["left"], peak["left"], peak["right"], peak["right"], peak["left"]],
dtype=np.float64,
)
),
fft_mode,
),
y_box,
)
@ -3270,10 +3310,10 @@ def run_pyqtgraph(args) -> None:
markers = find_peak_width_markers(xs_fft, fft_vals_db)
if markers is not None:
fft_bg_line.setValue(float(_db_to_linear_amplitude(np.asarray([markers["background"]]))[0]))
fft_left_line.setValue(display_distance_value(markers["left"]))
fft_right_line.setValue(display_distance_value(markers["right"]))
spec_left_line.setValue(display_distance_value(markers["left"]))
spec_right_line.setValue(display_distance_value(markers["right"]))
fft_left_line.setValue(display_distance_value_for_mode(markers["left"], fft_mode))
fft_right_line.setValue(display_distance_value_for_mode(markers["right"], fft_mode))
spec_left_line.setValue(display_distance_value_for_mode(markers["left"], fft_mode))
spec_right_line.setValue(display_distance_value_for_mode(markers["right"], fft_mode))
set_peak_marker_visibility(True)
runtime.current_peak_width = markers["width"]
runtime.current_peak_amplitude = markers["amplitude"]
@ -3314,11 +3354,12 @@ def run_pyqtgraph(args) -> None:
set_curve_data(
f"fft_peak_box_{idx}",
box,
display_distance_axis(
display_distance_axis_for_mode(
np.asarray(
[peak["left"], peak["left"], peak["right"], peak["right"], peak["left"]],
dtype=np.float64,
)
),
fft_mode,
),
[peak["ref"], peak["peak_y"], peak["peak_y"], peak["ref"], peak["ref"]],
)
@ -3349,10 +3390,10 @@ def run_pyqtgraph(args) -> None:
markers = find_peak_width_markers(xs_fft, fft_vals_db)
if markers is not None:
fft_bg_line.setValue(markers["background"])
fft_left_line.setValue(display_distance_value(markers["left"]))
fft_right_line.setValue(display_distance_value(markers["right"]))
spec_left_line.setValue(display_distance_value(markers["left"]))
spec_right_line.setValue(display_distance_value(markers["right"]))
fft_left_line.setValue(display_distance_value_for_mode(markers["left"], fft_mode))
fft_right_line.setValue(display_distance_value_for_mode(markers["right"], fft_mode))
spec_left_line.setValue(display_distance_value_for_mode(markers["left"], fft_mode))
spec_right_line.setValue(display_distance_value_for_mode(markers["right"], fft_mode))
set_peak_marker_visibility(True)
runtime.current_peak_width = markers["width"]
runtime.current_peak_amplitude = markers["amplitude"]
@ -3540,8 +3581,8 @@ def run_pyqtgraph(args) -> None:
and runtime.ring.y_min_fft != runtime.ring.y_max_fft
):
levels = (runtime.ring.y_min_fft, runtime.ring.y_max_fft)
disp_fft_display_axis = display_distance_axis(disp_fft_axis)
if disp_fft_display_axis.size == disp_fft.shape[0]:
disp_fft_display_axis = display_distance_axis_for_mode(disp_fft_axis, fft_mode)
if display_distance_transform_enabled(fft_mode) and disp_fft_display_axis.size == disp_fft.shape[0]:
disp_fft = disp_fft[::-1, :]
disp_fft_display_axis = disp_fft_display_axis[::-1]
distance_bounds = resolve_axis_bounds(disp_fft_display_axis)

View File

@ -21,7 +21,9 @@ from rfg_adc_plotter.gui.pyqtgraph_backend import (
decimate_bscan_rows_for_display,
decimate_curve_for_display,
display_distance_axis,
display_distance_axis_for_mode,
display_distance_value,
display_distance_value_for_mode,
fft_bscan_image_to_db,
is_short_sweep,
resolve_axis_bounds,
@ -555,6 +557,17 @@ class ProcessingTests(unittest.TestCase):
np.testing.assert_allclose(display_axis, np.asarray([9.0, 4.5, 0.0], dtype=np.float64))
self.assertAlmostEqual(display_distance_value(9.0), 0.0, places=12)
def test_display_distance_axis_transform_only_for_positive_only_exact_mode(self):
axis = np.asarray([0.0, 4.5, 9.0], dtype=np.float64)
np.testing.assert_allclose(display_distance_axis_for_mode(axis, "symmetric"), axis)
np.testing.assert_allclose(
display_distance_axis_for_mode(axis, "positive_only_exact"),
np.asarray([9.0, 4.5, 0.0], dtype=np.float64),
)
self.assertAlmostEqual(display_distance_value_for_mode(9.0, "symmetric"), 9.0, places=12)
self.assertAlmostEqual(display_distance_value_for_mode(9.0, "positive_only_exact"), 0.0, places=12)
def test_resolve_initial_window_size_stays_within_small_screen(self):
width, height = resolve_initial_window_size(800, 480)