Reputation: 2405
I'm trying to understand the output of scipy.fftpack.fft. I created a signal and did an fft of it. Here is the code for the fft:
import numpy as np
from scipy.fftpack import fft
import matplotlib.pyplot as plt
# Number of samplepoints
N = 600
# sample spacing
T = 1.0 / 800.0
x = np.linspace(0.0, N*T, N)
y = 5.0 * np.sin(50.0 * 2.0*np.pi*x) + 1.0*np.sin(80.0 * 2.0*np.pi*x) #unit is V
yf = fft(y)
xf = np.linspace(0.0, 1.0/(2.0*T), N/2)
plt.close()
plt.plot(xf, 2.0/N * np.abs(yf[0:N/2]))
plt.grid()
plt.show()
Which creates this:
I know the unit on the magnitude of the signal strength is the same as the signal unit on the waveform it is created from (V). I don't understand the relationship between the magnitude of the fft frequencies to the amplitude of the original signal. For example, the amplitude of the 50 Hz sine part is 5.0 V, then why is the magnitude of the 50 hz on the fft around 3.6 V?
Upvotes: 3
Views: 4300
Reputation: 14577
The peak magnitude in the frequency domain will generally only match the amplitude of a tone in the time domain if the tone's frequency is an integer multiple of the FFT frequency spacing 1.0/(N*T)
. When the tone frequency is not an integer multiple of the frequency spacing, the energy of the tone appears spread out over multiple bins in what is called Spectral leakage.
With your specific scenario the frequency spacing is 800/600 = 1.333Hz
. Correspondingly the 80Hz tone happens to be 60 times the frequency spacing, and the FFT shows a peak of the same magnitude as the amplitude of the associated time domain component 1.0*np.sin(80.0 * 2.0*np.pi*x)
.
On the other hand, the 50Hz tone corresponds to 37.5 times the frequency spacing. In this case the energy is spread over multiple bins and the peak is correspondingly reduced, showing a maximum peak at 3.6 instead of the full 5.0 amplitude of the 5.0 * np.sin(50.0 * 2.0*np.pi*x)
time domain component.
Upvotes: 6