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