如何正确缩放Python中的FFT函数以通过矩形函数(rect)与sinc函数对进行验证
Let's break down the problems you're facing with your FFT implementation and fix them step by step:
1. Core Issues Identified
Your main pain points stem from three key mistakes:
- Asymmetric time-domain signal causing phase shifts in the frequency domain
- Misaligned frequency sampling points leading to "double" curve artifacts
- Incorrect scaling factors between DFT (numpy's FFT) and continuous-time Fourier transform (CTFT)
2. Fixed Implementation Code
First, let's rewrite your functions with corrections for symmetry, scaling, and numerical stability:
Helper Functions (Rect & Sinc)
import numpy as np import matplotlib.pyplot as plt from numpy.fft import fft, ifft, fftfreq, fftshift, ifftshift def rect(t, T): # Center the rectangular function at t=0 for real-valued frequency output return np.where(np.abs(t) < T/2, 1.0, 0.0) def Tsinc_hz(f, T): # Handle division by zero at f=0 (sinc(0) = 1, so Tsinc_hz(0, T) = T) with np.errstate(divide='ignore', invalid='ignore'): sinc_val = np.sin(np.pi * f * T) / (np.pi * f) sinc_val[f == 0] = T return sinc_val
FFT & IFFT Conversion Functions
def to_frequency_domain(t, ys): N = len(t) T = t[1] - t[0] # Get actual sample interval (assumes uniform sampling) xf = fftfreq(N, T) xf = fftshift(xf) # Scale by sample interval T to approximate CTFT from DFT yf = fft(ys, N) * T yf = fftshift(yf) return xf, yf def to_time_domain(xf, yf): N = len(xf) Fs = 2 * np.max(np.abs(xf)) # Nyquist frequency is xf[-1], so Fs = 2*xf[-1] T_time = 1 / Fs # Generate symmetric time-domain points matching frequency sampling t = np.linspace(-(N*T_time)/2, (N*T_time)/2 - T_time, N) # Scale by Fs to reverse CTFT approximation and get correct time-domain amplitude ys = ifft(ifftshift(yf)) * Fs return t, ys
Validation Code
# Test 1: Rectangular Signal -> FFT vs Analytic Sinc Fs = 250 duration = 20 N = int(Fs * duration) t = np.linspace(-duration/2, duration/2 - 1/Fs, N) rect_signal = rect(t, 1) xf, yf = to_frequency_domain(t, rect_signal) sinc_analytic = Tsinc_hz(xf, 1) plt.figure(figsize=(10,5)) plt.plot(xf, yf.real, label='FFT Result') plt.plot(xf, sinc_analytic, label='Analytic Sinc', linestyle='--', color='r') plt.xlabel('Frequency (Hz)') plt.ylabel('Magnitude') plt.title('FFT of Rectangular Signal vs Analytic Sinc') plt.legend() plt.xlim(-5,5) # Zoom in on main lobe plt.show() # Test 2: Sinc Signal -> IFFT vs Original Rect t_recovered, rect_recovered = to_time_domain(xf, sinc_analytic) plt.figure(figsize=(10,5)) plt.plot(t_recovered, rect_recovered.real, label='IFFT Result', linewidth=2, alpha=0.7) plt.plot(t, rect_signal, label='Original Rect', linestyle='--', color='r') plt.xlabel('Time (s)') plt.ylabel('Amplitude') plt.title('IFFT of Sinc Signal vs Original Rectangular Signal') plt.legend() plt.xlim(-2,2) # Zoom in on rectangular pulse plt.show()
3. Key Fixes Explained
Symmetry Correction
Your original time-domain signal was defined from 0 to 10, making the rectangular pulse asymmetric around t=0. This introduced a linear phase shift in the frequency domain, causing the real part of your FFT output to mismatch the analytic sinc function. By using a symmetric time interval (-10 to 10), the rectangular signal becomes an even function, resulting in a real-valued frequency spectrum that matches the analytic solution exactly.
Frequency Point Alignment
The "double curve" artifact occurred because your manually generated f = np.linspace(-125,125,2500) had a slightly different interval than the fftfreq output. fftfreq uses exact spacing of Fs/N = 0.1Hz, while linspace uses 250/2499 ≈ 0.10004Hz, leading to misalignment. Using the xf output directly from to_frequency_domain ensures perfect alignment.
Scaling Rules
Numpy's FFT implements an unnormalized DFT. To map between DFT and CTFT:
- Forward FFT: Multiply by the sample interval
Tto approximate the continuous Fourier transform integral. - Inverse FFT: Multiply by the sampling rate
Fs(equivalent to dividing byT) to reverse the CTFT approximation and recover the correct time-domain amplitude.
Sampling Rate & Amplitude Relationship
When fixing N (number of samples) and reducing Fs (sampling rate):
- The time-domain length
N/Fsincreases - The frequency range
Fs/2shrinks (x-axis compression) - The frequency-domain amplitude scales by
1/Fs(y-axis stretching), since the CTFT integral over a longer time interval results in a larger magnitude.
内容的提问来源于stack exchange,提问作者toni

