为什么 numpy 的 fft 的第二个系数与它应该是的相反?
Why is every second coefficient of numpy's fft the inverse of what it should be?
这就是我尝试使用 numpy 获取单位脉冲的 DFT 的方法(图中显示了单位脉冲):
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
def plot_complex(space, arr):
plt.figure()
plt.plot(space, arr.real, label="real")
plt.plot(space, arr.imag, label="imag")
plt.legend(loc='upper left')
f = lambda x: 1 if abs(x) < 0.5 else 0
lo = -10
hi = 10
num_samples = 1000
sample_freq = num_samples/(hi-lo)
linspace = np.linspace(lo, hi, num_samples)
array = np.vectorize(f)(linspace)
coeff = np.fft.fft(array, num_samples)
# we need to shift the coefficients because otherwise negative frequencies are in the right half of the array
coeff_shifted = np.fft.fftshift(coeff)
plot_complex(linspace, array)
plt.title("The unit pulse")
Unit pulse plot
这似乎有效,因为使用反函数 fft 可以恢复原始单位脉冲:
icoeff = np.fft.ifft(coeff)
plot_complex(linspace, icoeff)
plt.title("The recovered signal")
Recovered pulse plot
但是,当查看信号时,它看起来不像我期望的连续傅里叶变换的 sinc 函数:
freqspace = np.vectorize(lambda x: x * sample_freq)(np.fft.fftshift(np.fft.fftfreq(1000)))
plot_complex(freqspace, coeff_shifted)
plt.title("DFT coefficients")
plot_complex(freqspace[450:550], coeff_shifted[450:550])
plt.title("Zoomed in")
Plot of the coefficients
Zoomed in plot
每隔一个系数乘以-1,看起来就像sinc函数:
# multiplies every second number in the array by -1
def flip_seconds(coeff):
return np.array([(1 if i%2 == 0 else -1) * s for (i,s) in enumerate(coeff)])
plot_complex(freqspace, flip_seconds(coeff_shifted))
Plot of the altered coefficients
这是为什么?
这有点手忙脚乱,也许其他人想用数学来解决它 :) 但基本上你已经 window 将你的 "pulse domain" 编辑为 [-X/2 , X/2] 而 fft 期望它是 windowed [0, X]。不同之处在于 "pulse domain" 的偏移,这会导致频域中的相移。因为您已经移动了 window 的一半,相移正好是 exp(-pi * f * i / sampling_freq)
(或类似的东西)所以它显示为每个其他项目都乘以 exp(-pi * i)
。您可以通过在应用 fft 之前移动 "pulse space" 来解决此问题。
import matplotlib.pyplot as plt
import numpy as np
def plot_complex(space, arr):
plt.figure()
plt.plot(space, arr.real, label="real")
plt.plot(space, arr.imag, label="imag")
plt.legend(loc='upper left')
lo = -10
hi = 10
num_samples = 1000
sample_freq = num_samples/(hi-lo)
linspace = np.linspace(lo, hi, num_samples)
array = abs(linspace) < .5
array_shifted = np.fft.fftshift(array)
coeff = np.fft.fft(array_shifted, num_samples)
# we need to shift the coefficients because otherwise negative frequencies are in the right half of the array
coeff_shifted = np.fft.fftshift(coeff)
plot_complex(linspace, array_shifted)
plt.title("The unit pulse (shifted)")
icoeff = np.ftt.ifftshift(np.fft.ifft(coeff))
plot_complex(linspace, icoeff)
plt.title("The recovered signal")
freqspace = np.fft.fftshift(np.fft.fftfreq(1000)) * sample_freq
plot_complex(freqspace, coeff_shifted)
plt.title("DFT coefficients")
plot_complex(freqspace[450:550], coeff_shifted[450:550])
plt.title("Zoomed in")
def flip_seconds(coeff):
return np.array([(1 if i%2 == 0 else -1) * s for (i,s) in enumerate(coeff)])
plot_complex(freqspace, flip_seconds(coeff_shifted))
plt.show()
这就是我尝试使用 numpy 获取单位脉冲的 DFT 的方法(图中显示了单位脉冲):
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
def plot_complex(space, arr):
plt.figure()
plt.plot(space, arr.real, label="real")
plt.plot(space, arr.imag, label="imag")
plt.legend(loc='upper left')
f = lambda x: 1 if abs(x) < 0.5 else 0
lo = -10
hi = 10
num_samples = 1000
sample_freq = num_samples/(hi-lo)
linspace = np.linspace(lo, hi, num_samples)
array = np.vectorize(f)(linspace)
coeff = np.fft.fft(array, num_samples)
# we need to shift the coefficients because otherwise negative frequencies are in the right half of the array
coeff_shifted = np.fft.fftshift(coeff)
plot_complex(linspace, array)
plt.title("The unit pulse")
Unit pulse plot
这似乎有效,因为使用反函数 fft 可以恢复原始单位脉冲:
icoeff = np.fft.ifft(coeff)
plot_complex(linspace, icoeff)
plt.title("The recovered signal")
Recovered pulse plot
但是,当查看信号时,它看起来不像我期望的连续傅里叶变换的 sinc 函数:
freqspace = np.vectorize(lambda x: x * sample_freq)(np.fft.fftshift(np.fft.fftfreq(1000)))
plot_complex(freqspace, coeff_shifted)
plt.title("DFT coefficients")
plot_complex(freqspace[450:550], coeff_shifted[450:550])
plt.title("Zoomed in")
Plot of the coefficients
Zoomed in plot
每隔一个系数乘以-1,看起来就像sinc函数:
# multiplies every second number in the array by -1
def flip_seconds(coeff):
return np.array([(1 if i%2 == 0 else -1) * s for (i,s) in enumerate(coeff)])
plot_complex(freqspace, flip_seconds(coeff_shifted))
Plot of the altered coefficients
这是为什么?
这有点手忙脚乱,也许其他人想用数学来解决它 :) 但基本上你已经 window 将你的 "pulse domain" 编辑为 [-X/2 , X/2] 而 fft 期望它是 windowed [0, X]。不同之处在于 "pulse domain" 的偏移,这会导致频域中的相移。因为您已经移动了 window 的一半,相移正好是 exp(-pi * f * i / sampling_freq)
(或类似的东西)所以它显示为每个其他项目都乘以 exp(-pi * i)
。您可以通过在应用 fft 之前移动 "pulse space" 来解决此问题。
import matplotlib.pyplot as plt
import numpy as np
def plot_complex(space, arr):
plt.figure()
plt.plot(space, arr.real, label="real")
plt.plot(space, arr.imag, label="imag")
plt.legend(loc='upper left')
lo = -10
hi = 10
num_samples = 1000
sample_freq = num_samples/(hi-lo)
linspace = np.linspace(lo, hi, num_samples)
array = abs(linspace) < .5
array_shifted = np.fft.fftshift(array)
coeff = np.fft.fft(array_shifted, num_samples)
# we need to shift the coefficients because otherwise negative frequencies are in the right half of the array
coeff_shifted = np.fft.fftshift(coeff)
plot_complex(linspace, array_shifted)
plt.title("The unit pulse (shifted)")
icoeff = np.ftt.ifftshift(np.fft.ifft(coeff))
plot_complex(linspace, icoeff)
plt.title("The recovered signal")
freqspace = np.fft.fftshift(np.fft.fftfreq(1000)) * sample_freq
plot_complex(freqspace, coeff_shifted)
plt.title("DFT coefficients")
plot_complex(freqspace[450:550], coeff_shifted[450:550])
plt.title("Zoomed in")
def flip_seconds(coeff):
return np.array([(1 if i%2 == 0 else -1) * s for (i,s) in enumerate(coeff)])
plot_complex(freqspace, flip_seconds(coeff_shifted))
plt.show()