fix
This commit is contained in:
@ -2,9 +2,11 @@
|
|||||||
Визуализация данных с использованием matplotlib.
|
Визуализация данных с использованием matplotlib.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import csv
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
from datetime import datetime
|
||||||
from queue import Empty, Queue
|
from queue import Empty, Queue
|
||||||
from typing import Optional, Tuple
|
from typing import Optional, Tuple
|
||||||
|
|
||||||
@ -57,6 +59,35 @@ def run_matplotlib(args):
|
|||||||
ring = None # type: Optional[np.ndarray]
|
ring = None # type: Optional[np.ndarray]
|
||||||
ring_time = None # type: Optional[np.ndarray]
|
ring_time = None # type: Optional[np.ndarray]
|
||||||
head = 0
|
head = 0
|
||||||
|
# Медианные данные для вычитания
|
||||||
|
median_data: Optional[np.ndarray] = None
|
||||||
|
median_subtract_enabled = False
|
||||||
|
# CLI параметры для автоматического сохранения/загрузки
|
||||||
|
ref_out_file = getattr(args, 'ref_out', None)
|
||||||
|
ref_in_file = getattr(args, 'ref_in', None)
|
||||||
|
ref_out_saved = False # Флаг, что медиана уже сохранена
|
||||||
|
|
||||||
|
# Автоматическая загрузка медианы при старте
|
||||||
|
if ref_in_file:
|
||||||
|
try:
|
||||||
|
data = []
|
||||||
|
with open(ref_in_file, 'r') as f:
|
||||||
|
reader = csv.reader(f)
|
||||||
|
next(reader) # Пропускаем заголовок
|
||||||
|
for row in reader:
|
||||||
|
if len(row) >= 2:
|
||||||
|
try:
|
||||||
|
data.append(float(row[1]))
|
||||||
|
except ValueError:
|
||||||
|
continue
|
||||||
|
if data:
|
||||||
|
median_data = np.array(data, dtype=np.float32)
|
||||||
|
median_subtract_enabled = True
|
||||||
|
print(f"[ref-in] Загружена медиана из {ref_in_file} ({len(median_data)} точек), вычитание включено")
|
||||||
|
else:
|
||||||
|
print(f"[ref-in] Предупреждение: файл {ref_in_file} пустой или неверный формат")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[ref-in] Ошибка загрузки {ref_in_file}: {e}")
|
||||||
# Авто-уровни цветовой шкалы водопада сырых данных пересчитываются по видимой области.
|
# Авто-уровни цветовой шкалы водопада сырых данных пересчитываются по видимой области.
|
||||||
# FFT состояние (полное FFT для отрицательных частот)
|
# FFT состояние (полное FFT для отрицательных частот)
|
||||||
fft_bins = FFT_LEN
|
fft_bins = FFT_LEN
|
||||||
@ -268,6 +299,14 @@ def run_matplotlib(args):
|
|||||||
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
|
||||||
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 median_subtract_enabled and median_data is not None:
|
||||||
|
take_median = min(s.size, median_data.size)
|
||||||
|
s_corrected = s.copy()
|
||||||
|
s_corrected[:take_median] = s[:take_median] - median_data[:take_median]
|
||||||
|
s = s_corrected
|
||||||
|
|
||||||
# Нормализуем длину до фиксированной ширины
|
# Нормализуем длину до фиксированной ширины
|
||||||
w = ring.shape[1]
|
w = ring.shape[1]
|
||||||
row = np.full((w,), np.nan, dtype=np.float32)
|
row = np.full((w,), np.nan, dtype=np.float32)
|
||||||
@ -551,6 +590,31 @@ 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+ свипов
|
||||||
|
if ref_out_file and not ref_out_saved and ring is not None:
|
||||||
|
nonlocal ref_out_saved
|
||||||
|
filled_count = np.count_nonzero(~np.isnan(ring[:, 0]))
|
||||||
|
if filled_count >= 1000:
|
||||||
|
try:
|
||||||
|
# Получаем последние 1000 свипов
|
||||||
|
ordered = ring if head == 0 else np.roll(ring, -head, axis=0)
|
||||||
|
recent_sweeps = ordered[-1000:, :]
|
||||||
|
median_sweep = np.nanmedian(recent_sweeps, axis=0)
|
||||||
|
|
||||||
|
# Сохраняем в файл
|
||||||
|
with open(ref_out_file, 'w', newline='') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerow(['Index', 'Median_Value'])
|
||||||
|
for i, value in enumerate(median_sweep):
|
||||||
|
if np.isfinite(value):
|
||||||
|
writer.writerow([i, float(value)])
|
||||||
|
|
||||||
|
ref_out_saved = True
|
||||||
|
print(f"[ref-out] Сохранена медиана 1000 свипов в {ref_out_file}")
|
||||||
|
status_text.set_text(f"[ref-out] Сохранено в {ref_out_file}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[ref-out] Ошибка сохранения: {e}")
|
||||||
|
|
||||||
# Возвращаем обновлённые артисты
|
# Возвращаем обновлённые артисты
|
||||||
return (line_obj, img_obj, fft_line_obj, img_fft_obj, phase_line_obj, img_phase_obj, status_text)
|
return (line_obj, img_obj, fft_line_obj, img_fft_obj, phase_line_obj, img_phase_obj, status_text)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user