Reputation: 415
When a signal's frequency falls exactly on an FFT bin, the amplitude becomes 0! But if I offset the signal frequency a little bit off, the result is ok.
Reproducing code:
Here the signal's frequency is 30
import numpy as np
import matplotlib.pyplot as plt
N = 1024
Freq = 30
t = np.arange(N)
x = np.sin(2*np.pi*Freq/N*t)
f = np.fft.fft(x)
plt.plot(t, x)
plt.plot(t, f)
I would expect the output to have a huge spike in the 30th bin, but it's flat, as in the following figure.
However, if just slightly change the frequency to 30.1 to not let it fall on the exact bin,
import numpy as np
import matplotlib.pyplot as plt
N = 1024
Freq = 30.1
t = np.arange(N)
x = np.sin(2*np.pi*Freq/N*t)
f = np.fft.fft(x)
plt.plot(t, x)
plt.plot(t, f)
The result is correct as in the following figure:
WHY? Is this a numpy FFT implementation issue? Or is it a limitation of the standard FFT algorithm?
Upvotes: 1
Views: 192
Reputation: 534
import numpy as np
import matplotlib.pyplot as plt
T = 1 # Total signal duration (s)
N = 1024 # samples over signal duration
Freq = 30 # frequency: (Hz)
t = np.arange(N)/N*T # time array
df = 1.0/T # resolution of angular frequency
f = np.arange(N)*df
x = np.sin(2*np.pi*Freq*t)
xhat = np.fft.fft(x) # Fourier series of x
plt.plot(t, x)
plt.xlabel("t (s)")
plt.ylabel("x")
plt.savefig("fig1.png")
plt.cla()
plt.plot(f, np.abs(xhat))
plt.xlabel("f (Hz)")
plt.ylabel("|fft(x)|")
plt.savefig("fig2.png")
Upvotes: 1
Reputation: 415
f is complex number, I should be using abs(f) for plotting. It had slipped my mind :P
Upvotes: 1