Source code for adctoolbox.spectrum.extract_freq_components

"""Ideal brickwall FFT filter for extracting frequency band components.

Applies FFT-based brickwall filters to extract specified frequency bands
from input signals. Each column is filtered independently.
"""

import numpy as np
from ..fundamentals.frequency import fold_frequency_to_nyquist


[docs] def extract_freq_components(din, bands): """ Extract signal components within specified frequency bands. Parameters ---------- din : np.ndarray Input data matrix (N x M or M x N). Must be real-valued. bands : np.ndarray Frequency bands matrix (P x 2), each row [low_freq, high_freq]. Frequencies normalized: 0 = DC, 0.5 = Nyquist. Returns ------- np.ndarray Output data with only components in specified bands. """ if not np.isrealobj(din): raise ValueError('input signal must be real-valued') din = np.asarray(din, dtype=float) bands = np.asarray(bands, dtype=float) if din.ndim == 1: din = din[:, np.newaxis] N, M = din.shape if N < M: din = din.T N, M = din.shape if bands.ndim == 1: bands = bands.reshape(1, -1) P, Q = bands.shape if Q != 2: raise ValueError('bands must have exactly 2 columns [fLow, fHigh]') if not np.isrealobj(bands) or np.any(bands < 0) or np.any(bands > 0.5): raise ValueError('band frequencies must be real and in range [0, 0.5]') spec = np.fft.fft(din, axis=0) mask = np.zeros(N) for i in range(P): n1 = int(round(min(bands[i, :]) * N)) n2 = int(round(max(bands[i, :]) * N)) freq_indices = np.arange(n1, n2 + 1) ids = np.round(fold_frequency_to_nyquist(freq_indices, N)).astype(int) # Set positive frequency bins mask[ids] = 1 # Set negative frequency bins (Hermitian symmetry) # Exclude DC (0) and Nyquist (N/2) to avoid double-setting valid = ids[(ids > 0) & (ids < N // 2)] mask[N - valid] = 1 # Apply mask to all columns spec = spec * mask[:, np.newaxis] dout = np.real(np.fft.ifft(spec, axis=0)) return dout