diff --git a/main.py b/main.py index d3fa504..ec55bdb 100755 --- a/main.py +++ b/main.py @@ -42,6 +42,9 @@ STANDARD_FOURIER_COLS = 100 MAX_PROCESSING_TIME_MS = 250 FILES_STORED_N_MAX = 100 +# Минимально допустимое число точек F0 для принятия данных +MIN_F0_POINTS = 100 + # ПЕРЕЧИСЛЕНИЕ ТИПОВ ДАННЫХ DATA_TYPE_RAW = "RAW" DATA_TYPE_SYNC_DET = "SYNC_DET" @@ -123,6 +126,14 @@ def resize_2d_interpolate(data, target_rows, target_cols): return data_resampled +def is_all_zero(arr: np.ndarray, eps: float = 0.0) -> bool: + """Возвращает True, если все значения массива близки к нулю.""" + try: + return not np.any(np.abs(arr) > eps) + except Exception: + return False + + def BF_fft_postprocessor(spectrum: np.ndarray) -> np.ndarray: """Болванка постобработки FFT-данных, полученных из файла (F4). @@ -201,6 +212,20 @@ def parse_hex_file(filename): seg_sync = [] seg_fourier = [] + def _is_all_zero_local(arr_like) -> bool: + try: + arr = np.asarray(arr_like, dtype=float) + return not np.any(np.abs(arr) > 0) + except Exception: + return False + + def _f0_is_valid_local(f0_like) -> bool: + try: + arr = np.asarray(f0_like, dtype=float) + return arr.size >= MIN_F0_POINTS and (not _is_all_zero_local(arr)) + except Exception: + return False + def finalize_segment(): nonlocal cur # Приоритет выбора сегмента: @@ -213,7 +238,7 @@ def parse_hex_file(filename): # FOURIER данные получены напрямую из файла (F4) col = np.asarray(cur["F4"], dtype=float) col = BF_fft_postprocessor(col) - if cur["F0"]: + if cur["F0"] and _f0_is_valid_local(cur["F0"]): # Сохраняем F0 рядом с F4 для отображения (без расчёта FFT) f0 = np.asarray(cur["F0"], dtype=float) seg_fourier.append((col, f0)) @@ -227,7 +252,8 @@ def parse_hex_file(filename): arr = np.asarray(cur["F3"], dtype=float) seg_fourier.append(np.sqrt(np.maximum(0.0, arr))) elif cur["F0"]: - seg_sync.append(np.asarray(cur["F0"], dtype=float)) + if _f0_is_valid_local(cur["F0"]): + seg_sync.append(np.asarray(cur["F0"], dtype=float)) elif cur["D0"]: seg_raw.append(np.asarray(cur["D0"], dtype=float)) # Сброс @@ -1300,6 +1326,47 @@ class DataAnalyzerApp: else: original_size = 0 + # Фильтрация неполных/нулевых данных + if data_type == DATA_TYPE_SYNC_DET: + # SYNC_DET соответствует F0; проверяем минимальную длину и ненулевость + if isinstance(A, np.ndarray): + arr = A.ravel() + if arr.size < MIN_F0_POINTS or is_all_zero(arr): + timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3] + reason = f"len={arr.size} < {MIN_F0_POINTS}" if arr.size < MIN_F0_POINTS else "all zeros" + print(f"[{timestamp}] ⏭️ SKIP {fname} (SYNC_DET invalid: {reason})") + self.skipped_count += 1 + self.processed_files.add(fname) + continue + elif isinstance(A, list): + filtered = [] + for seg in A: + try: + arr = np.asarray(seg, dtype=float).ravel() + if arr.size >= MIN_F0_POINTS and (not is_all_zero(arr)): + filtered.append(arr) + except Exception: + continue + if not filtered: + timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3] + print(f"[{timestamp}] ⏭️ SKIP {fname} (SYNC_DET segments invalid)") + self.skipped_count += 1 + self.processed_files.add(fname) + continue + A = filtered + original_size = len(A[0]) if len(A) > 0 else 0 + + if data_type == DATA_TYPE_FOURIER: + # Для FOURIER: пропускаем полностью пустые/нулевые массивы + if isinstance(A, np.ndarray): + arr = A.ravel() + if arr.size == 0 or is_all_zero(arr): + timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3] + print(f"[{timestamp}] ⏭️ SKIP {fname} (FOURIER empty or all zeros)") + self.skipped_count += 1 + self.processed_files.add(fname) + continue + # Если после парсинга данных нет — пропускаем файл if (isinstance(A, list) and len(A) == 0) or (isinstance(A, np.ndarray) and A.size == 0): timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]