backend upd

This commit is contained in:
awe
2026-02-04 14:13:01 +03:00
parent 60a35b690f
commit e0f7678c3e
2 changed files with 44 additions and 28 deletions

View File

@ -66,8 +66,11 @@ def run_matplotlib(args):
ref_out_file = getattr(args, 'ref_out', None) ref_out_file = getattr(args, 'ref_out', None)
ref_in_file = getattr(args, 'ref_in', None) ref_in_file = getattr(args, 'ref_in', None)
ref_out_saved = False # Флаг, что медиана уже сохранена ref_out_saved = False # Флаг, что медиана уже сохранена
# Отдельный буфер для накопления 1000 сырых свипов (не зависит от max_sweeps)
ref_ring: Optional[np.ndarray] = None
ref_ring_head = 0
ref_ring_count = 0
# DEBUG: Проверяем что параметр установлен
if ref_out_file: if ref_out_file:
print(f"[ref-out] Автосохранение включено, файл: {ref_out_file}") print(f"[ref-out] Автосохранение включено, файл: {ref_out_file}")
@ -238,6 +241,7 @@ def run_matplotlib(args):
def ensure_buffer(_w: int): def ensure_buffer(_w: int):
nonlocal ring, width, head, x_shared, ring_fft, freq_shared, ring_time nonlocal ring, width, head, x_shared, ring_fft, freq_shared, ring_time
nonlocal ring_phase, prev_phase_per_bin, phase_offset_per_bin nonlocal ring_phase, prev_phase_per_bin, phase_offset_per_bin
nonlocal ref_ring
if ring is not None: if ring is not None:
return return
width = WF_WIDTH width = WF_WIDTH
@ -265,6 +269,9 @@ def run_matplotlib(args):
img_phase_obj.set_extent((0, max_sweeps - 1, FREQ_MIN_GHZ, FREQ_MAX_GHZ)) img_phase_obj.set_extent((0, max_sweeps - 1, FREQ_MIN_GHZ, FREQ_MAX_GHZ))
ax_phase_wf.set_xlim(0, max_sweeps - 1) ax_phase_wf.set_xlim(0, max_sweeps - 1)
ax_phase_wf.set_ylim(FREQ_MIN_GHZ, FREQ_MAX_GHZ) ax_phase_wf.set_ylim(FREQ_MIN_GHZ, FREQ_MAX_GHZ)
# Буфер для медианы (отдельный от ring, размер всегда 1000)
if ref_out_file and ref_ring is None:
ref_ring = np.full((1000, width), np.nan, dtype=np.float32)
def _visible_levels_matplotlib(data: np.ndarray, axis) -> Optional[Tuple[float, float]]: def _visible_levels_matplotlib(data: np.ndarray, axis) -> Optional[Tuple[float, float]]:
"""(vmin, vmax) по текущей видимой области imshow (без накопления по времени).""" """(vmin, vmax) по текущей видимой области imshow (без накопления по времени)."""
@ -301,9 +308,18 @@ def run_matplotlib(args):
def push_sweep(s: np.ndarray): def push_sweep(s: np.ndarray):
nonlocal ring, head, ring_fft, y_min_fft, y_max_fft, ring_time nonlocal ring, head, ring_fft, y_min_fft, y_max_fft, ring_time
nonlocal ring_phase, prev_phase_per_bin, phase_offset_per_bin, y_min_phase, y_max_phase nonlocal ring_phase, prev_phase_per_bin, phase_offset_per_bin, y_min_phase, y_max_phase
nonlocal ref_ring_head, ref_ring_count
if s is None or s.size == 0 or ring is None: if s is None or s.size == 0 or ring is None:
return return
# Сохраняем сырой свип в буфер медианы (до вычитания)
if ref_out_file and not ref_out_saved and ref_ring is not None:
w_ref = ref_ring.shape[1]
take_ref = min(w_ref, s.size)
ref_ring[ref_ring_head, :take_ref] = s[:take_ref]
ref_ring_head = (ref_ring_head + 1) % 1000
ref_ring_count = min(ref_ring_count + 1, 1000)
# Применяем вычитание медианы если включено # Применяем вычитание медианы если включено
if median_subtract_enabled and median_data is not None: if median_subtract_enabled and median_data is not None:
take_median = min(s.size, median_data.size) take_median = min(s.size, median_data.size)
@ -594,26 +610,13 @@ def run_matplotlib(args):
if changed and current_info: if changed and current_info:
status_text.set_text(format_status_kv(current_info)) status_text.set_text(format_status_kv(current_info))
# Автоматическое сохранение медианы при накоплении 1000+ свипов # Автоматическое сохранение медианы при накоплении 1000 сырых свипов
# DEBUG: Проверяем условия каждые 100 кадров if ref_out_file and not ref_out_saved and ref_ring is not None:
if _frame is not None and _frame % 100 == 0: if ref_ring_count >= 1000:
print(f"[ref-out DEBUG] _frame={_frame}, ref_out_file={bool(ref_out_file)}, ref_out_saved={ref_out_saved}, ring={'OK' if ring is not None else 'None'}")
if ref_out_file and not ref_out_saved and ring is not None:
filled_count = np.count_nonzero(~np.isnan(ring[:, 0]))
# DEBUG: Выводим прогресс каждые 100 свипов
if filled_count % 100 == 0 and filled_count > 0:
print(f"[ref-out] Прогресс: {filled_count}/1000 свипов накоплено")
if filled_count >= 1000:
print(f"[ref-out] Достигнуто 1000 свипов, начинаем сохранение...")
try: try:
# Получаем последние 1000 свипов ordered = ref_ring if ref_ring_head == 0 else np.roll(ref_ring, -ref_ring_head, axis=0)
ordered = ring if head == 0 else np.roll(ring, -head, axis=0) median_sweep = np.nanmedian(ordered, axis=0)
recent_sweeps = ordered[-1000:, :]
median_sweep = np.nanmedian(recent_sweeps, axis=0)
print(f"[ref-out] Медиана вычислена, размер: {len(median_sweep)}")
# Сохраняем в файл
with open(ref_out_file, 'w', newline='') as f: with open(ref_out_file, 'w', newline='') as f:
writer = csv.writer(f) writer = csv.writer(f)
writer.writerow(['Index', 'Median_Value']) writer.writerow(['Index', 'Median_Value'])

View File

@ -281,6 +281,10 @@ def run_pyqtgraph(args):
ref_out_file = getattr(args, 'ref_out', None) ref_out_file = getattr(args, 'ref_out', None)
ref_in_file = getattr(args, 'ref_in', None) ref_in_file = getattr(args, 'ref_in', None)
ref_out_saved = False # Флаг, что медиана уже сохранена ref_out_saved = False # Флаг, что медиана уже сохранена
# Отдельный буфер для накопления 1000 сырых свипов (не зависит от max_sweeps)
ref_ring: Optional[np.ndarray] = None
ref_ring_head = 0
ref_ring_count = 0
# Автоматическая загрузка медианы при старте # Автоматическая загрузка медианы при старте
if ref_in_file: if ref_in_file:
@ -331,6 +335,7 @@ def run_pyqtgraph(args):
def ensure_buffer(_w: int): def ensure_buffer(_w: int):
nonlocal ring, head, width, x_shared, ring_fft, freq_shared nonlocal ring, head, width, x_shared, ring_fft, freq_shared
nonlocal ring_phase, prev_phase_per_bin, phase_offset_per_bin nonlocal ring_phase, prev_phase_per_bin, phase_offset_per_bin
nonlocal ref_ring
if ring is not None: if ring is not None:
return return
width = WF_WIDTH width = WF_WIDTH
@ -354,6 +359,9 @@ def run_pyqtgraph(args):
img_phase.setImage(ring_phase.T, autoLevels=False) img_phase.setImage(ring_phase.T, autoLevels=False)
p_phase_wf.setRange(xRange=(0, max_sweeps - 1), yRange=(0, max(1, fft_bins - 1)), padding=0) p_phase_wf.setRange(xRange=(0, max_sweeps - 1), yRange=(0, max(1, fft_bins - 1)), padding=0)
p_phase.setXRange(0, max(1, fft_bins - 1), padding=0) p_phase.setXRange(0, max(1, fft_bins - 1), padding=0)
# Буфер для медианы (отдельный от ring, размер всегда 1000)
if ref_out_file and ref_ring is None:
ref_ring = np.full((1000, width), np.nan, dtype=np.float32)
def _visible_levels_pyqtgraph(data: np.ndarray) -> Optional[Tuple[float, float]]: def _visible_levels_pyqtgraph(data: np.ndarray) -> Optional[Tuple[float, float]]:
"""(vmin, vmax) по текущей видимой области ImageItem (без накопления по времени).""" """(vmin, vmax) по текущей видимой области ImageItem (без накопления по времени)."""
@ -389,9 +397,18 @@ def run_pyqtgraph(args):
def push_sweep(s: np.ndarray): def push_sweep(s: np.ndarray):
nonlocal ring, head, ring_fft, y_min_fft, y_max_fft nonlocal ring, head, ring_fft, y_min_fft, y_max_fft
nonlocal ring_phase, prev_phase_per_bin, phase_offset_per_bin, y_min_phase, y_max_phase nonlocal ring_phase, prev_phase_per_bin, phase_offset_per_bin, y_min_phase, y_max_phase
nonlocal ref_ring_head, ref_ring_count
if s is None or s.size == 0 or ring is None: if s is None or s.size == 0 or ring is None:
return return
# Сохраняем сырой свип в буфер медианы (до вычитания)
if ref_out_file and not ref_out_saved and ref_ring is not None:
w_ref = ref_ring.shape[1]
take_ref = min(w_ref, s.size)
ref_ring[ref_ring_head, :take_ref] = s[:take_ref]
ref_ring_head = (ref_ring_head + 1) % 1000
ref_ring_count = min(ref_ring_count + 1, 1000)
# Применяем вычитание медианы если включено # Применяем вычитание медианы если включено
if median_subtract_enabled and median_data is not None: if median_subtract_enabled and median_data is not None:
# Вычитаем медиану из сигнала # Вычитаем медиану из сигнала
@ -593,17 +610,13 @@ def run_pyqtgraph(args):
except Exception: except Exception:
pass pass
# Автоматическое сохранение медианы при накоплении 1000+ свипов # Автоматическое сохранение медианы при накоплении 1000 сырых свипов
if ref_out_file and not ref_out_saved and ring is not None: if ref_out_file and not ref_out_saved and ref_ring is not None:
filled_count = np.count_nonzero(~np.isnan(ring[:, 0])) if ref_ring_count >= 1000:
if filled_count >= 1000:
try: try:
# Получаем последние 1000 свипов ordered = ref_ring if ref_ring_head == 0 else np.roll(ref_ring, -ref_ring_head, axis=0)
ordered = ring if head == 0 else np.roll(ring, -head, axis=0) median_sweep = np.nanmedian(ordered, axis=0)
recent_sweeps = ordered[-1000:, :]
median_sweep = np.nanmedian(recent_sweeps, axis=0)
# Сохраняем в файл
with open(ref_out_file, 'w', newline='') as f: with open(ref_out_file, 'w', newline='') as f:
writer = csv.writer(f) writer = csv.writer(f)
writer.writerow(['Index', 'Median_Value']) writer.writerow(['Index', 'Median_Value'])