I am working with time series data, and applying FFT to calculate the power spectrum. The data is something like this:
$y = \sum_{k=1}^{5} \cos(10 k x)$
All the peaks in the FFT output should have identical magnitudes, similar to the pattern shown in the graph below:
However, the FFT output I am getting is different, as shown in the graph below:
The magnitudes of the peaks in my data slightly differ. Increasing the sampling rate or using a Hamming window reduces but doesn't fully eliminate these differences. How can I completely remove these differences?
N = 1000
t = np.linspace(0,2*np.pi,N)
y = np.zeros(N)
for freq in [10,20,30,40,50]:
y = y + np.cos(freq * t)
h = scipy.signal.windows.hamming(N)
yfft = np.abs(np.fft.fft(y*h) / N)**2
xfft = np.hstack([np.arange(0,N//2), np.arange(-(N//2),0)])
d = np.array(sorted(zip(xfft,yfft))).reshape(-1,2)
xfft = d[:,0]
yfft = d[:,1]
plt.plot(xfft,yfft,color="red")
plt.show()
for freq in [10,20,30,40,50]:
print(f"freq={freq} magnitude={yfft[xfft==freq]}")





The ideal Fourier transform here would be the sum of 10 Dirac delta functions that has spikes with infinite peaks. It’s not surprising you didn’t get infinite peaks in practice (because that’s impossible), and the width (and so height) of your peaks depends on the specific implementation details and precision of your FFT. If you integrate your FFT’s individual peaks, you’ll probably get totals which are close to each other.
If you really want results that match theory closely, use finite functions. I.e. the (unnormalized) Fourier transform of a limited height pulse is $\sin(x)/x$, so you can use something like $\sum_{k=1}^5 (\sin(x)/x)\cos(10kx)$ which should give spikes with a mostly consistent width/height, but you’ll still get some small differences. You can bound these differences using various theorems related to sampling error in signal analysis.