now waterfalls are horisontal and fancy. Next step --invert yaxes
This commit is contained in:
@ -480,8 +480,8 @@ def main():
|
|||||||
cmap=args.cmap,
|
cmap=args.cmap,
|
||||||
)
|
)
|
||||||
ax_img.set_title("Сырые данные водопад")
|
ax_img.set_title("Сырые данные водопад")
|
||||||
ax_img.set_xlabel("X")
|
ax_img.set_xlabel("Время (новое слева)")
|
||||||
ax_img.set_ylabel("Время →")
|
ax_img.set_ylabel("X")
|
||||||
|
|
||||||
# Водопад спектров
|
# Водопад спектров
|
||||||
img_fft_obj = ax_spec.imshow(
|
img_fft_obj = ax_spec.imshow(
|
||||||
@ -492,8 +492,8 @@ def main():
|
|||||||
cmap=args.cmap,
|
cmap=args.cmap,
|
||||||
)
|
)
|
||||||
ax_spec.set_title("B-scan (дБ)")
|
ax_spec.set_title("B-scan (дБ)")
|
||||||
ax_spec.set_xlabel("Бин")
|
ax_spec.set_xlabel("Время (новое слева)")
|
||||||
ax_spec.set_ylabel("Время →")
|
ax_spec.set_ylabel("Бин")
|
||||||
|
|
||||||
# Для контроля частоты обновления
|
# Для контроля частоты обновления
|
||||||
max_fps = max(1.0, float(args.max_fps))
|
max_fps = max(1.0, float(args.max_fps))
|
||||||
@ -508,17 +508,17 @@ def main():
|
|||||||
x_shared = np.arange(width, dtype=np.int32)
|
x_shared = np.arange(width, dtype=np.int32)
|
||||||
ring = np.full((max_sweeps, width), np.nan, dtype=np.float32)
|
ring = np.full((max_sweeps, width), np.nan, dtype=np.float32)
|
||||||
head = 0
|
head = 0
|
||||||
# Обновляем изображение под новые размеры
|
# Обновляем изображение под новые размеры: время по X (горизонталь), X по Y
|
||||||
img_obj.set_data(ring)
|
img_obj.set_data(np.zeros((width, max_sweeps), dtype=np.float32))
|
||||||
img_obj.set_extent((0, width - 1 if width > 0 else 1, 0, max_sweeps - 1))
|
img_obj.set_extent((0, max_sweeps - 1, 0, width - 1 if width > 0 else 1))
|
||||||
ax_img.set_xlim(0, max(1, width - 1))
|
ax_img.set_xlim(0, max_sweeps - 1)
|
||||||
ax_img.set_ylim(max_sweeps - 1, 0)
|
ax_img.set_ylim(0, max(1, width - 1))
|
||||||
# FFT буферы
|
# FFT буферы: время по X, бин по Y
|
||||||
ring_fft = np.full((max_sweeps, fft_bins), np.nan, dtype=np.float32)
|
ring_fft = np.full((max_sweeps, fft_bins), np.nan, dtype=np.float32)
|
||||||
img_fft_obj.set_data(ring_fft)
|
img_fft_obj.set_data(np.zeros((fft_bins, max_sweeps), dtype=np.float32))
|
||||||
img_fft_obj.set_extent((0, fft_bins - 1, 0, max_sweeps - 1))
|
img_fft_obj.set_extent((0, max_sweeps - 1, 0, fft_bins - 1))
|
||||||
ax_spec.set_xlim(0, max(1, fft_bins - 1))
|
ax_spec.set_xlim(0, max_sweeps - 1)
|
||||||
ax_spec.set_ylim(max_sweeps - 1, 0)
|
ax_spec.set_ylim(0, max(1, fft_bins - 1))
|
||||||
freq_shared = np.arange(fft_bins, dtype=np.int32)
|
freq_shared = np.arange(fft_bins, dtype=np.int32)
|
||||||
|
|
||||||
def push_sweep(s: np.ndarray):
|
def push_sweep(s: np.ndarray):
|
||||||
@ -587,19 +587,17 @@ def main():
|
|||||||
return drained
|
return drained
|
||||||
|
|
||||||
def make_display_ring():
|
def make_display_ring():
|
||||||
# Возвращаем буфер с правильным порядком строк (старые сверху, новые снизу)
|
# Возвращаем буфер с правильным порядком по времени (старые→новые) и осью времени по X
|
||||||
if ring is None:
|
if ring is None:
|
||||||
return np.zeros((1, 1), dtype=np.float32)
|
return np.zeros((1, 1), dtype=np.float32)
|
||||||
if head == 0:
|
base = ring if head == 0 else np.roll(ring, -head, axis=0)
|
||||||
return ring
|
return base.T # (width, time)
|
||||||
return np.roll(ring, -head, axis=0)
|
|
||||||
|
|
||||||
def make_display_ring_fft():
|
def make_display_ring_fft():
|
||||||
if ring_fft is None:
|
if ring_fft is None:
|
||||||
return np.zeros((1, 1), dtype=np.float32)
|
return np.zeros((1, 1), dtype=np.float32)
|
||||||
if head == 0:
|
base = ring_fft if head == 0 else np.roll(ring_fft, -head, axis=0)
|
||||||
return ring_fft
|
return base.T # (bins, time)
|
||||||
return np.roll(ring_fft, -head, axis=0)
|
|
||||||
|
|
||||||
def update(_frame):
|
def update(_frame):
|
||||||
nonlocal frames_since_ylim_update
|
nonlocal frames_since_ylim_update
|
||||||
@ -651,6 +649,8 @@ def main():
|
|||||||
# Обновление водопада
|
# Обновление водопада
|
||||||
if changed and ring is not None:
|
if changed and ring is not None:
|
||||||
disp = make_display_ring()
|
disp = make_display_ring()
|
||||||
|
# Новые данные слева: реверсируем время по X
|
||||||
|
disp = disp[:, ::-1]
|
||||||
img_obj.set_data(disp)
|
img_obj.set_data(disp)
|
||||||
# Актуализируем цветовую шкалу только при расширении экстремумов
|
# Актуализируем цветовую шкалу только при расширении экстремумов
|
||||||
if y_min is not None and y_max is not None and np.isfinite(y_min) and np.isfinite(y_max):
|
if y_min is not None and y_max is not None and np.isfinite(y_min) and np.isfinite(y_max):
|
||||||
@ -660,10 +660,12 @@ def main():
|
|||||||
# Обновление водопада спектров
|
# Обновление водопада спектров
|
||||||
if changed and ring_fft is not None:
|
if changed and ring_fft is not None:
|
||||||
disp_fft = make_display_ring_fft()
|
disp_fft = make_display_ring_fft()
|
||||||
|
disp_fft = disp_fft[:, ::-1]
|
||||||
img_fft_obj.set_data(disp_fft)
|
img_fft_obj.set_data(disp_fft)
|
||||||
# Автодиапазон по средним (по видимым данным): берём средний спектр по времени
|
# Автодиапазон по среднему спектру за видимый интервал (как в хорошей версии)
|
||||||
try:
|
try:
|
||||||
mean_spec = np.nanmean(disp_fft, axis=0)
|
# disp_fft имеет форму (bins, time); берём среднее по времени
|
||||||
|
mean_spec = np.nanmean(disp_fft, axis=1)
|
||||||
vmin_v = float(np.nanmin(mean_spec))
|
vmin_v = float(np.nanmin(mean_spec))
|
||||||
vmax_v = float(np.nanmax(mean_spec))
|
vmax_v = float(np.nanmax(mean_spec))
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -735,10 +737,10 @@ def run_pyqtgraph(args):
|
|||||||
|
|
||||||
# Водопад (справа-сверху)
|
# Водопад (справа-сверху)
|
||||||
p_img = win.addPlot(row=0, col=1, title="Сырые данные водопад")
|
p_img = win.addPlot(row=0, col=1, title="Сырые данные водопад")
|
||||||
p_img.invertY(True) # 0 сверху, новые снизу
|
p_img.invertY(False)
|
||||||
p_img.showGrid(x=False, y=False)
|
p_img.showGrid(x=False, y=False)
|
||||||
p_img.setLabel("bottom", "X")
|
p_img.setLabel("bottom", "Время (новое слева)")
|
||||||
p_img.setLabel("left", "Время →")
|
p_img.setLabel("left", "X")
|
||||||
img = pg.ImageItem()
|
img = pg.ImageItem()
|
||||||
p_img.addItem(img)
|
p_img.addItem(img)
|
||||||
|
|
||||||
@ -751,10 +753,10 @@ def run_pyqtgraph(args):
|
|||||||
|
|
||||||
# Водопад спектров (справа-снизу)
|
# Водопад спектров (справа-снизу)
|
||||||
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.invertY(False)
|
||||||
p_spec.showGrid(x=False, y=False)
|
p_spec.showGrid(x=False, y=False)
|
||||||
p_spec.setLabel("bottom", "Бин")
|
p_spec.setLabel("bottom", "Время (новое слева)")
|
||||||
p_spec.setLabel("left", "Время →")
|
p_spec.setLabel("left", "Бин")
|
||||||
img_fft = pg.ImageItem()
|
img_fft = pg.ImageItem()
|
||||||
p_spec.addItem(img_fft)
|
p_spec.addItem(img_fft)
|
||||||
|
|
||||||
@ -791,13 +793,14 @@ def run_pyqtgraph(args):
|
|||||||
x_shared = np.arange(width, dtype=np.int32)
|
x_shared = np.arange(width, dtype=np.int32)
|
||||||
ring = np.full((max_sweeps, width), np.nan, dtype=np.float32)
|
ring = np.full((max_sweeps, width), np.nan, dtype=np.float32)
|
||||||
head = 0
|
head = 0
|
||||||
img.setImage(ring, autoLevels=False)
|
# Водопад: время по оси X, X по оси Y
|
||||||
p_img.setRange(xRange=(0, max(1, width - 1)), yRange=(0, max_sweeps - 1), padding=0)
|
img.setImage(ring.T, autoLevels=False)
|
||||||
|
p_img.setRange(xRange=(0, max_sweeps - 1), yRange=(0, max(1, width - 1)), padding=0)
|
||||||
p_line.setXRange(0, max(1, width - 1), padding=0)
|
p_line.setXRange(0, max(1, width - 1), padding=0)
|
||||||
# FFT
|
# FFT: время по оси X, бин по оси Y
|
||||||
ring_fft = np.full((max_sweeps, fft_bins), np.nan, dtype=np.float32)
|
ring_fft = np.full((max_sweeps, fft_bins), np.nan, dtype=np.float32)
|
||||||
img_fft.setImage(ring_fft, autoLevels=False)
|
img_fft.setImage(ring_fft.T, autoLevels=False)
|
||||||
p_spec.setRange(xRange=(0, max(1, fft_bins - 1)), yRange=(0, max_sweeps - 1), padding=0)
|
p_spec.setRange(xRange=(0, max_sweeps - 1), yRange=(0, max(1, fft_bins - 1)), padding=0)
|
||||||
p_fft.setXRange(0, max(1, fft_bins - 1), padding=0)
|
p_fft.setXRange(0, max(1, fft_bins - 1), padding=0)
|
||||||
freq_shared = np.arange(fft_bins, dtype=np.int32)
|
freq_shared = np.arange(fft_bins, dtype=np.int32)
|
||||||
|
|
||||||
@ -898,6 +901,7 @@ def run_pyqtgraph(args):
|
|||||||
|
|
||||||
if changed and ring is not None:
|
if changed and ring is not None:
|
||||||
disp = ring if head == 0 else np.roll(ring, -head, axis=0)
|
disp = ring if head == 0 else np.roll(ring, -head, axis=0)
|
||||||
|
disp = disp.T[:, ::-1] # (width, time with newest at left)
|
||||||
if y_min is not None and y_max is not None and y_min != y_max and np.isfinite(y_min) and np.isfinite(y_max):
|
if y_min is not None and y_max is not None and y_min != y_max and np.isfinite(y_min) and np.isfinite(y_max):
|
||||||
img.setImage(disp, autoLevels=False, levels=(y_min, y_max))
|
img.setImage(disp, autoLevels=False, levels=(y_min, y_max))
|
||||||
else:
|
else:
|
||||||
@ -905,10 +909,11 @@ def run_pyqtgraph(args):
|
|||||||
|
|
||||||
if changed and ring_fft is not None:
|
if changed and ring_fft is not None:
|
||||||
disp_fft = ring_fft if head == 0 else np.roll(ring_fft, -head, axis=0)
|
disp_fft = ring_fft if head == 0 else np.roll(ring_fft, -head, axis=0)
|
||||||
# Автодиапазон по среднему спектру за видимый интервал
|
disp_fft = disp_fft.T[:, ::-1]
|
||||||
|
# Автодиапазон по среднему спектру за видимый интервал (как в хорошей версии)
|
||||||
levels = None
|
levels = None
|
||||||
try:
|
try:
|
||||||
mean_spec = np.nanmean(disp_fft, axis=0)
|
mean_spec = np.nanmean(disp_fft, axis=1)
|
||||||
vmin_v = float(np.nanmin(mean_spec))
|
vmin_v = float(np.nanmin(mean_spec))
|
||||||
vmax_v = float(np.nanmax(mean_spec))
|
vmax_v = float(np.nanmax(mean_spec))
|
||||||
if np.isfinite(vmin_v) and np.isfinite(vmax_v) and vmin_v != vmax_v:
|
if np.isfinite(vmin_v) and np.isfinite(vmax_v) and vmin_v != vmax_v:
|
||||||
|
|||||||
Reference in New Issue
Block a user