"""Преобразование свипа в IFFT-временной профиль (дБ).""" from typing import Optional import numpy as np from rfg_adc_plotter.constants import FREQ_SPAN_GHZ, IFFT_LEN, SWEEP_LEN, ZEROS_LOW, ZEROS_MID def build_ifft_time_axis_ns() -> np.ndarray: """Временная ось IFFT в наносекундах.""" return ( np.arange(IFFT_LEN, dtype=np.float64) / (FREQ_SPAN_GHZ * 1e9) * 1e9 ).astype(np.float32) def compute_ifft_db_profile(sweep: Optional[np.ndarray]) -> np.ndarray: """Построить IFFT-профиль свипа в дБ. Цепочка: raw/processed sweep -> двусторонний спектр (заполнение нулями) -> ifftshift -> ifft -> |x| -> 20log10. """ bins = IFFT_LEN if sweep is None: return np.full((bins,), np.nan, dtype=np.float32) s = np.asarray(sweep) if s.size == 0: return np.full((bins,), np.nan, dtype=np.float32) sig = np.zeros(SWEEP_LEN, dtype=np.float32) take = min(int(s.size), SWEEP_LEN) seg = np.nan_to_num(s[:take], nan=0.0).astype(np.float32, copy=False) sig[:take] = seg data = np.zeros(IFFT_LEN, dtype=np.complex64) data[ZEROS_LOW + ZEROS_MID :] = sig spec = np.fft.ifftshift(data) result = np.fft.ifft(spec) mag = np.abs(result).astype(np.float32) return (mag + 1e-9).astype(np.float32)