How do I deconstruct a signal with fast fourier transformation in Python?

I want to use the fast Fourier transformation in python to deconstruct a periodic signal into its harmonic periodicities.

Since the FFT of the original signal is the same as adding the FFT of the periodicities, I was calculating the power spectrum of the FFT of the original signal and then tried to extract the several signals. You can see my code for the extraction below:

def harmonic_period_calc(old_fft, peak_index, peak_value):
"""
description: this function recalculates the fft so that only one peak in
the psd should be visible

furthermore it uses the ifft to calculate a harmonic signal,
from which you are able to calculate the time indexes via
its peaks

old_fft: the old fourier tansformation of our signal
peak_index: the index, of peaks in the power spectrum
peak_value: scalar-factor, with which we are going to shorten the other
values with

"""

new_fft_one = old_fft[:int(len(old_fft)/2)]
new_fft_two = old_fft[int(len(old_fft)/2):]

new_fft_one[np.delete(np.arange(new_fft_one.shape[0]), peak_index)] *= 1/peak_value
new_fft_two[np.delete(np.arange(new_fft_two.shape[0]), -peak_index)] *= 1/peak_value

new_fft = np.concatenate((new_fft_one, new_fft_two))

period = scipy.fftpack.ifft(new_fft)

return period


Unfortunately this is only working okay. Because the peaks of the inverse FFT is slightly off from the original period.

So my question is, does anybody know, how I will be able to do this?

If necessary, this is how I calculate the FFT and the power spectrum:

temp_fft = scipy.fftpack.fft(signal)
temp_psd = np.abs(temp_fft) ** 2
fftfreq = scipy.fftpack.fftfreq(len(temp_psd), 1/len(signal))
i = fftfreq > 0


Also the technical information from me:

Python 3.7 scipy 1.3.1 pandas 0.25.3 numpy 1.17.2

• Probably not a valid EE question.
– Andy aka
Mar 2, 2020 at 15:41
• The output frequencies are in certain discrete bins. Is the signal frequency exactly equal to one of these bins? If not, it is not possible to get the exact frequency value. You can increase the number of bins to get a closer approximation, though. Mar 2, 2020 at 16:32
• Yes, the signal is equal to one of these bins. Mar 3, 2020 at 7:56
• @Justin This is not true. See my commentary here: dsp.stackexchange.com/questions/64336/… Mar 5, 2020 at 4:11
• @CedronDawg - That looks interesting. I only glanced at the paper, but I assume the essential idea is that you have to use the values from multiple bins to determine the frequency? The simple method of just choosing the bin that has the highest magnitude will still suffer from the discretization error, right? Does your method also work for non-sinusoids (e.g., square waves)? Mar 5, 2020 at 13:50

If you have a periodic signal, that is a repeating waveform, you can most easily find the constituent component parameters by aligning the Discrete Fourier Transform (DFT) frame on a whole number of cycles. Suppose you chose four. Then bins 0, 4, 8, 12, etc. contain the relevant values.

For a signal:

$$x[n] = A \cos( \omega n + \phi )$$

If

$$\omega = \frac{2\pi}{N} k$$

where $$k$$ (cycles per frame) is an integer, then the $$k$$th bin will have a value of

$$X[k] = \frac{A}{2} e^{i\phi}$$

So, you can read the tone's parameters right from the magnitude and angle of the DFT bin. (FFT is an implementation of DFT)

If you aren't aligned on a whole number of bins, there is an interative process you can do with the formulas found in my blog articles. This takes considerably more calculations though.