diff --git a/calib_envelope.npy b/calib_envelope.npy index 1628af6..394f3f9 100644 Binary files a/calib_envelope.npy and b/calib_envelope.npy differ diff --git a/rfg_adc_plotter/constants.py b/rfg_adc_plotter/constants.py index e1e8855..e4f47ba 100644 --- a/rfg_adc_plotter/constants.py +++ b/rfg_adc_plotter/constants.py @@ -1,5 +1,5 @@ WF_WIDTH = 1000 # максимальное число точек в ряду водопада -FFT_LEN = 2048 # длина БПФ для спектра/водопада спектров +FFT_LEN = 4096 # длина БПФ для спектра/водопада спектров LOG_EXP = 2.0 # основание экспоненты для опции --logscale # Порог для инверсии сырых данных: если среднее значение свипа ниже порога — # считаем, что сигнал «меньше нуля» и домножаем свип на -1 diff --git a/rfg_adc_plotter/processing/fourier.py b/rfg_adc_plotter/processing/fourier.py index 65cd733..48b37b4 100644 --- a/rfg_adc_plotter/processing/fourier.py +++ b/rfg_adc_plotter/processing/fourier.py @@ -69,7 +69,7 @@ def build_frequency_axis_hz(sweep_width: int) -> np.ndarray: """Построить частотную сетку (Гц) для текущей длины свипа.""" n = int(sweep_width) if n <= 0: - return np.zeros((0,), dtype=np.float64) + return np.zeros((0,), dtype=np.float128) if n == 1: return np.array([FREQ_MIN_GHZ * 1e9], dtype=np.float64) return np.linspace(FREQ_MIN_GHZ * 1e9, FREQ_MAX_GHZ * 1e9, n, dtype=np.float64) @@ -101,7 +101,6 @@ def unwrap_arccos_phase_continuous(x_norm: np.ndarray) -> np.ndarray: phi0 = np.arccos(x) out = np.empty_like(phi0, dtype=np.float64) - out[0] = float(phi0[0]) for i in range(1, phi0.size): base_phi = float(phi0[i]) prev = float(out[i - 1]) @@ -125,7 +124,7 @@ def unwrap_arccos_phase_continuous(x_norm: np.ndarray) -> np.ndarray: out[i] = prev if best_cand is None else float(best_cand) return out - + return phi0 def reconstruct_complex_spectrum_from_real_trace(sweep: np.ndarray) -> np.ndarray: """Восстановить комплексный спектр из вещественного следа через arccos+Euler.""" @@ -238,7 +237,7 @@ def compute_ifft_profile_from_sweep(sweep: Optional[np.ndarray]) -> tuple[np.nda n = min(depth_m.size, y.size) if n <= 0: return _fallback_depth_response(s.size, s) - return depth_m[:n].astype(np.float32, copy=False), y[:n].astype(np.float32, copy=False) + return depth_m[:n].astype(np.float128, copy=False), y[:n].astype(np.float128, copy=False) *20 except Exception as exc: # noqa: BLE001 logger.error("compute_ifft_profile_from_sweep failed: %r", exc) return _fallback_depth_response(np.asarray(sweep).size if sweep is not None else 1, sweep) diff --git a/rfg_adc_plotter/state/ring_buffer.py b/rfg_adc_plotter/state/ring_buffer.py index d7dc09b..52675e9 100644 --- a/rfg_adc_plotter/state/ring_buffer.py +++ b/rfg_adc_plotter/state/ring_buffer.py @@ -85,6 +85,13 @@ class RingBuffer: if n != depth_axis_m.size: depth_axis_m = depth_axis_m[:n] + # Для отображения храним только первую половину IFFT-профиля: + # вторая половина для текущей схемы симметрична и визуально избыточна. + n_keep = max(1, (n + 1) // 2) + fft_row = fft_row[:n_keep] + depth_axis_m = depth_axis_m[:n_keep] + n = n_keep + needs_reset = ( self.ring_fft is None or self.fft_depth_axis_m is None