add new old fourier
This commit is contained in:
@ -6,7 +6,7 @@ from typing import Optional, Tuple
|
||||
|
||||
import numpy as np
|
||||
|
||||
from rfg_adc_plotter.constants import C_M_S, FFT_LEN
|
||||
from rfg_adc_plotter.constants import C_M_S, FFT_LEN, SWEEP_FREQ_MAX_GHZ, SWEEP_FREQ_MIN_GHZ
|
||||
|
||||
|
||||
def prepare_fft_segment(
|
||||
@ -48,6 +48,45 @@ def prepare_fft_segment(
|
||||
return resampled, take_fft
|
||||
|
||||
|
||||
def build_symmetric_ifft_spectrum(
|
||||
sweep: np.ndarray,
|
||||
freqs: Optional[np.ndarray],
|
||||
fft_len: int = FFT_LEN,
|
||||
) -> Optional[np.ndarray]:
|
||||
"""Build a centered symmetric spectrum over [-f_max, f_max] for IFFT."""
|
||||
if fft_len <= 0:
|
||||
return None
|
||||
|
||||
freq_axis = np.linspace(-SWEEP_FREQ_MAX_GHZ, SWEEP_FREQ_MAX_GHZ, int(fft_len), dtype=np.float64)
|
||||
neg_idx_all = np.flatnonzero(freq_axis <= (-SWEEP_FREQ_MIN_GHZ))
|
||||
pos_idx_all = np.flatnonzero(freq_axis >= SWEEP_FREQ_MIN_GHZ)
|
||||
band_len = int(min(neg_idx_all.size, pos_idx_all.size))
|
||||
if band_len <= 1:
|
||||
return None
|
||||
|
||||
neg_idx = neg_idx_all[:band_len]
|
||||
pos_idx = pos_idx_all[-band_len:]
|
||||
prepared = prepare_fft_segment(sweep, freqs, fft_len=band_len)
|
||||
if prepared is None:
|
||||
return None
|
||||
|
||||
fft_seg, take_fft = prepared
|
||||
if take_fft != band_len:
|
||||
fft_seg = np.asarray(fft_seg[:band_len], dtype=np.float32)
|
||||
if fft_seg.size < band_len:
|
||||
padded = np.zeros((band_len,), dtype=np.float32)
|
||||
padded[: fft_seg.size] = fft_seg
|
||||
fft_seg = padded
|
||||
|
||||
window = np.hanning(band_len).astype(np.float32)
|
||||
band = np.nan_to_num(fft_seg, nan=0.0).astype(np.float32, copy=False) * window
|
||||
|
||||
spectrum = np.zeros((int(fft_len),), dtype=np.float32)
|
||||
spectrum[pos_idx] = band
|
||||
spectrum[neg_idx] = band[::-1]
|
||||
return spectrum
|
||||
|
||||
|
||||
def fft_mag_to_db(mag: np.ndarray) -> np.ndarray:
|
||||
"""Convert magnitude to dB with safe zero handling."""
|
||||
mag_arr = np.asarray(mag, dtype=np.float32)
|
||||
@ -55,15 +94,11 @@ def fft_mag_to_db(mag: np.ndarray) -> np.ndarray:
|
||||
return (20.0 * np.log10(safe_mag + 1e-9)).astype(np.float32, copy=False)
|
||||
|
||||
|
||||
def compute_fft_mag_row(
|
||||
def _compute_fft_mag_row_direct(
|
||||
sweep: np.ndarray,
|
||||
freqs: Optional[np.ndarray],
|
||||
bins: int,
|
||||
) -> np.ndarray:
|
||||
"""Compute a linear FFT magnitude row."""
|
||||
if bins <= 0:
|
||||
return np.zeros((0,), dtype=np.float32)
|
||||
|
||||
prepared = prepare_fft_segment(sweep, freqs, fft_len=FFT_LEN)
|
||||
if prepared is None:
|
||||
return np.full((bins,), np.nan, dtype=np.float32)
|
||||
@ -79,28 +114,56 @@ def compute_fft_mag_row(
|
||||
return mag
|
||||
|
||||
|
||||
def compute_fft_mag_row(
|
||||
sweep: np.ndarray,
|
||||
freqs: Optional[np.ndarray],
|
||||
bins: int,
|
||||
*,
|
||||
symmetric: bool = True,
|
||||
) -> np.ndarray:
|
||||
"""Compute a linear FFT magnitude row."""
|
||||
if bins <= 0:
|
||||
return np.zeros((0,), dtype=np.float32)
|
||||
|
||||
if not symmetric:
|
||||
return _compute_fft_mag_row_direct(sweep, freqs, bins)
|
||||
|
||||
spectrum_centered = build_symmetric_ifft_spectrum(sweep, freqs, fft_len=FFT_LEN)
|
||||
if spectrum_centered is None:
|
||||
return np.full((bins,), np.nan, dtype=np.float32)
|
||||
|
||||
spec = np.fft.ifft(np.fft.ifftshift(spectrum_centered))
|
||||
mag = np.abs(spec).astype(np.float32)
|
||||
if mag.shape[0] != bins:
|
||||
mag = mag[:bins]
|
||||
return mag
|
||||
|
||||
|
||||
def compute_fft_row(
|
||||
sweep: np.ndarray,
|
||||
freqs: Optional[np.ndarray],
|
||||
bins: int,
|
||||
*,
|
||||
symmetric: bool = True,
|
||||
) -> np.ndarray:
|
||||
"""Compute a dB FFT row."""
|
||||
return fft_mag_to_db(compute_fft_mag_row(sweep, freqs, bins))
|
||||
return fft_mag_to_db(compute_fft_mag_row(sweep, freqs, bins, symmetric=symmetric))
|
||||
|
||||
|
||||
def compute_distance_axis(freqs: Optional[np.ndarray], bins: int) -> np.ndarray:
|
||||
def compute_distance_axis(freqs: Optional[np.ndarray], bins: int, *, symmetric: bool = True) -> np.ndarray:
|
||||
"""Compute the one-way distance axis for IFFT output."""
|
||||
if bins <= 0:
|
||||
return np.zeros((0,), dtype=np.float64)
|
||||
if freqs is None:
|
||||
return np.arange(bins, dtype=np.float64)
|
||||
|
||||
freq_arr = np.asarray(freqs, dtype=np.float64)
|
||||
finite = freq_arr[np.isfinite(freq_arr)]
|
||||
if finite.size < 2:
|
||||
return np.arange(bins, dtype=np.float64)
|
||||
|
||||
df_ghz = float((finite[-1] - finite[0]) / max(1, finite.size - 1))
|
||||
if symmetric:
|
||||
df_ghz = (2.0 * float(SWEEP_FREQ_MAX_GHZ)) / max(1, FFT_LEN - 1)
|
||||
else:
|
||||
if freqs is None:
|
||||
return np.arange(bins, dtype=np.float64)
|
||||
freq_arr = np.asarray(freqs, dtype=np.float64)
|
||||
finite = freq_arr[np.isfinite(freq_arr)]
|
||||
if finite.size < 2:
|
||||
return np.arange(bins, dtype=np.float64)
|
||||
df_ghz = float((finite[-1] - finite[0]) / max(1, finite.size - 1))
|
||||
df_hz = abs(df_ghz) * 1e9
|
||||
if not np.isfinite(df_hz) or df_hz <= 0.0:
|
||||
return np.arange(bins, dtype=np.float64)
|
||||
|
||||
Reference in New Issue
Block a user