arccos to apply

This commit is contained in:
awe
2026-02-26 14:00:56 +03:00
parent f1652d072e
commit 00323af0f0
9 changed files with 472 additions and 74 deletions

View File

@ -7,9 +7,7 @@ from typing import Optional, Tuple
import numpy as np
from rfg_adc_plotter.constants import FFT_LEN, FREQ_SPAN_GHZ, IFFT_LEN
_IFFT_T_MAX_NS = float((IFFT_LEN - 1) / (FREQ_SPAN_GHZ * 1e9) * 1e9)
from rfg_adc_plotter.constants import FFT_LEN, FREQ_MAX_GHZ, FREQ_MIN_GHZ, IFFT_LEN
from rfg_adc_plotter.io.sweep_reader import SweepReader
from rfg_adc_plotter.processing.normalizer import build_calib_envelopes
from rfg_adc_plotter.state.app_state import AppState, format_status
@ -146,8 +144,8 @@ def run_matplotlib(args):
# График спектра
fft_line_obj, = ax_fft.plot([], [], lw=1)
ax_fft.set_title("FFT", pad=1)
ax_fft.set_xlabel("Время, нс")
ax_fft.set_ylabel("Мощность, дБ")
ax_fft.set_xlabel("Глубина, м")
ax_fft.set_ylabel("Амплитуда")
# Водопад сырых данных
img_obj = ax_img.imshow(
@ -166,8 +164,8 @@ def run_matplotlib(args):
np.zeros((1, 1), dtype=np.float32),
aspect="auto", interpolation="nearest", origin="lower", cmap=args.cmap,
)
ax_spec.set_title("B-scan (дБ)", pad=12)
ax_spec.set_ylabel("Время, нс")
ax_spec.set_title("B-scan", pad=12)
ax_spec.set_ylabel("Глубина, м")
try:
ax_spec.tick_params(axis="x", labelbottom=False)
except Exception:
@ -176,7 +174,7 @@ def run_matplotlib(args):
# Слайдеры и чекбокс
contrast_slider = None
try:
fft_bins = ring.fft_bins
fft_bins = ring.fft_bins if ring.fft_bins > 0 else IFFT_LEN
ax_smin = fig.add_axes([0.92, 0.55, 0.02, 0.35])
ax_smax = fig.add_axes([0.95, 0.55, 0.02, 0.35])
ax_sctr = fig.add_axes([0.98, 0.55, 0.02, 0.35])
@ -440,23 +438,36 @@ def run_matplotlib(args):
calib_cb = None
line_mode_state = {"value": "raw"}
FREQ_MIN = 3.323
FREQ_MAX = 14.323
FREQ_MIN = float(FREQ_MIN_GHZ)
FREQ_MAX = float(FREQ_MAX_GHZ)
def _fft_depth_max() -> float:
axis = ring.fft_depth_axis_m
if axis is None or axis.size == 0:
return 1.0
try:
vmax = float(axis[-1])
except Exception:
vmax = float(np.nanmax(axis))
if not np.isfinite(vmax) or vmax <= 0.0:
return 1.0
return vmax
# --- Инициализация imshow при первом свипе ---
def _init_imshow_extents():
w = ring.width
ms = ring.max_sweeps
fb = ring.fft_bins
fb = max(1, int(ring.fft_bins))
depth_max = _fft_depth_max()
img_obj.set_data(np.zeros((w, ms), dtype=np.float32))
img_obj.set_extent((0, ms - 1, FREQ_MIN, FREQ_MAX))
ax_img.set_xlim(0, ms - 1)
ax_img.set_ylim(FREQ_MIN, FREQ_MAX)
img_fft_obj.set_data(np.zeros((fb, ms), dtype=np.float32))
img_fft_obj.set_extent((0, ms - 1, 0.0, _IFFT_T_MAX_NS))
img_fft_obj.set_extent((0, ms - 1, 0.0, depth_max))
ax_spec.set_xlim(0, ms - 1)
ax_spec.set_ylim(0.0, _IFFT_T_MAX_NS)
ax_fft.set_xlim(0.0, _IFFT_T_MAX_NS)
ax_spec.set_ylim(0.0, depth_max)
ax_fft.set_xlim(0.0, depth_max)
_imshow_initialized = [False]
@ -544,13 +555,16 @@ def run_matplotlib(args):
ax_line.autoscale_view(scalex=False, scaley=True)
ax_line.set_ylabel("Y")
# Спектр — используем уже вычисленный в ring IFFT (временной профиль)
if ring.last_fft_vals is not None and ring.fft_time_axis is not None:
# Профиль по глубине — используем уже вычисленный в ring IFFT.
if ring.last_fft_vals is not None and ring.fft_depth_axis_m is not None:
fft_vals = ring.last_fft_vals
xs_fft = ring.fft_time_axis
xs_fft = ring.fft_depth_axis_m
n = min(fft_vals.size, xs_fft.size)
fft_line_obj.set_data(xs_fft[:n], fft_vals[:n])
if np.isfinite(np.nanmin(fft_vals)) and np.isfinite(np.nanmax(fft_vals)):
if n > 0:
fft_line_obj.set_data(xs_fft[:n], fft_vals[:n])
else:
fft_line_obj.set_data([], [])
if n > 0 and np.isfinite(np.nanmin(fft_vals)) and np.isfinite(np.nanmax(fft_vals)):
ax_fft.set_xlim(0, float(xs_fft[n - 1]))
ax_fft.set_ylim(float(np.nanmin(fft_vals)), float(np.nanmax(fft_vals)))
@ -572,6 +586,9 @@ def run_matplotlib(args):
disp_fft = ring.get_display_ring_fft()
disp_fft = ring.subtract_recent_mean_fft(disp_fft, spec_mean_sec)
img_fft_obj.set_data(disp_fft)
depth_max = _fft_depth_max()
img_fft_obj.set_extent((0, ring.max_sweeps - 1, 0.0, depth_max))
ax_spec.set_ylim(0.0, depth_max)
levels = ring.compute_fft_levels(disp_fft, spec_clip)
if levels is not None:
try:

View File

@ -8,16 +8,13 @@ from typing import Optional, Tuple
import numpy as np
from rfg_adc_plotter.constants import FREQ_SPAN_GHZ, IFFT_LEN
from rfg_adc_plotter.constants import FREQ_MAX_GHZ, FREQ_MIN_GHZ
from rfg_adc_plotter.io.sweep_reader import SweepReader
from rfg_adc_plotter.processing.normalizer import build_calib_envelopes
from rfg_adc_plotter.state.app_state import AppState, format_status
from rfg_adc_plotter.state.ring_buffer import RingBuffer
from rfg_adc_plotter.types import SweepPacket
# Максимальное значение временной оси IFFT в нс
_IFFT_T_MAX_NS = float((IFFT_LEN - 1) / (FREQ_SPAN_GHZ * 1e9) * 1e9)
def _parse_ylim(ylim_str: Optional[str]) -> Optional[Tuple[float, float]]:
if not ylim_str:
@ -202,11 +199,11 @@ def run_pyqtgraph(args):
p_fft = win.addPlot(row=1, col=0, title="FFT")
p_fft.showGrid(x=True, y=True, alpha=0.3)
curve_fft = p_fft.plot(pen=pg.mkPen((255, 120, 80), width=1))
p_fft.setLabel("bottom", "Время, нс")
p_fft.setLabel("left", "Мощность, дБ")
p_fft.setLabel("bottom", "Глубина, м")
p_fft.setLabel("left", "Амплитуда")
# Водопад спектров (справа-снизу)
p_spec = win.addPlot(row=1, col=1, title="B-scan (дБ)")
p_spec = win.addPlot(row=1, col=1, title="B-scan")
p_spec.invertY(True)
p_spec.showGrid(x=False, y=False)
p_spec.setLabel("bottom", "Время (новое справа)")
@ -214,7 +211,7 @@ def run_pyqtgraph(args):
p_spec.getAxis("bottom").setStyle(showValues=False)
except Exception:
pass
p_spec.setLabel("left", "Время, нс")
p_spec.setLabel("left", "Глубина, м")
img_fft = pg.ImageItem()
p_spec.addItem(img_fft)
@ -470,20 +467,33 @@ def run_pyqtgraph(args):
_imshow_initialized = [False]
FREQ_MIN = 3.323
FREQ_MAX = 14.323
FREQ_MIN = float(FREQ_MIN_GHZ)
FREQ_MAX = float(FREQ_MAX_GHZ)
def _fft_depth_max() -> float:
axis = ring.fft_depth_axis_m
if axis is None or axis.size == 0:
return 1.0
try:
vmax = float(axis[-1])
except Exception:
vmax = float(np.nanmax(axis))
if not np.isfinite(vmax) or vmax <= 0.0:
return 1.0
return vmax
def _init_imshow_extents():
ms = ring.max_sweeps
fb = ring.fft_bins
img.setImage(ring.ring.T, autoLevels=False)
img.setRect(pg.QtCore.QRectF(0.0, FREQ_MIN, float(ms), FREQ_MAX - FREQ_MIN))
p_img.setRange(xRange=(0, ms - 1), yRange=(FREQ_MIN, FREQ_MAX), padding=0)
p_line.setXRange(FREQ_MIN, FREQ_MAX, padding=0)
img_fft.setImage(ring.ring_fft.T, autoLevels=False)
img_fft.setRect(pg.QtCore.QRectF(0.0, 0.0, float(ms), _IFFT_T_MAX_NS))
p_spec.setRange(xRange=(0, ms - 1), yRange=(0.0, _IFFT_T_MAX_NS), padding=0)
p_fft.setXRange(0.0, _IFFT_T_MAX_NS, padding=0)
disp_fft = ring.get_display_ring_fft()
img_fft.setImage(disp_fft, autoLevels=False)
depth_max = _fft_depth_max()
img_fft.setRect(pg.QtCore.QRectF(0.0, 0.0, float(ms), depth_max))
p_spec.setRange(xRange=(0, ms - 1), yRange=(0.0, depth_max), padding=0)
p_fft.setXRange(0.0, depth_max, padding=0)
def _img_rect(ms: int) -> "pg.QtCore.QRectF":
return pg.QtCore.QRectF(0.0, FREQ_MIN, float(ms), FREQ_MAX - FREQ_MIN)
@ -573,13 +583,15 @@ def run_pyqtgraph(args):
p_line.enableAutoRange(axis="y", enable=True)
p_line.setLabel("left", "Y")
# Спектр — используем уже вычисленный в ring IFFT (временной профиль)
if ring.last_fft_vals is not None and ring.fft_time_axis is not None:
# Профиль по глубине — используем уже вычисленный в ring IFFT.
if ring.last_fft_vals is not None and ring.fft_depth_axis_m is not None:
fft_vals = ring.last_fft_vals
xs_fft = ring.fft_time_axis
xs_fft = ring.fft_depth_axis_m
n = min(fft_vals.size, xs_fft.size)
curve_fft.setData(xs_fft[:n], fft_vals[:n])
p_fft.setYRange(float(np.nanmin(fft_vals)), float(np.nanmax(fft_vals)), padding=0)
if n > 0:
curve_fft.setData(xs_fft[:n], fft_vals[:n])
p_fft.setXRange(0.0, float(xs_fft[n - 1]), padding=0)
p_fft.setYRange(float(np.nanmin(fft_vals)), float(np.nanmax(fft_vals)), padding=0)
# Позиция подписи канала
try:
@ -619,7 +631,7 @@ def run_pyqtgraph(args):
img_fft.setImage(disp_fft, autoLevels=False, levels=levels)
else:
img_fft.setImage(disp_fft, autoLevels=False)
img_fft.setRect(pg.QtCore.QRectF(0.0, 0.0, float(ring.max_sweeps), _IFFT_T_MAX_NS))
img_fft.setRect(pg.QtCore.QRectF(0.0, 0.0, float(ring.max_sweeps), _fft_depth_max()))
timer = pg.QtCore.QTimer()
timer.timeout.connect(update)