Paul Paul - 4 months ago 19
Python Question

numpy's fast Fourier transform yields unexpected results

I am struggling with

numpy
's implementation of the fast Fourier transform. My signal is not of periodic nature and therefore certainly not an ideal candidate, the result of the FFT however is far from what I was expecting. It is the same signal, simply stretched by some factor. I plotted a sinus curve, approximating my signal next to it which should illustrate, that I use the FFT function correctly:

import numpy as np
from matplotlib import pyplot as plt

signal = array([[ 0.], [ 0.1667557 ], [ 0.31103874], [ 0.44339886], [ 0.50747922],
[ 0.47848347], [ 0.64544846], [ 0.67861755], [ 0.69268326], [ 0.71581176],
[ 0.726552 ], [ 0.75032795], [ 0.77133769], [ 0.77379966], [ 0.80519187],
[ 0.78756476], [ 0.84179849], [ 0.85406538], [ 0.82852684], [ 0.87172407],
[ 0.9055542 ], [ 0.90563205], [ 0.92073452], [ 0.91178145], [ 0.8795554 ],
[ 0.89155587], [ 0.87965686], [ 0.91819571], [ 0.95774404], [ 0.95432073],
[ 0.96326252], [ 0.99480947], [ 0.94754962], [ 0.9818627 ], [ 0.9804966 ],
[ 1.], [ 0.99919711], [ 0.97202208], [ 0.99065786], [ 0.90567128],
[ 0.94300558], [ 0.89839004], [ 0.87312245], [ 0.86288378], [ 0.87301008],
[ 0.78184963], [ 0.73774451], [ 0.7450479 ], [ 0.67291666], [ 0.63518575],
[ 0.57036157], [ 0.5709147 ], [ 0.63079811], [ 0.61821523], [ 0.49526048],
[ 0.4434457 ], [ 0.29746173], [ 0.13024641], [ 0.17631683], [ 0.08590552]])

sinus = np.sin(np.linspace(0, np.pi, 60))

plt.plot(signal)
plt.plot(sinus)


The blue line is my signal, the green line is the sinus.

raw.pdf

transformed_signal = abs(np.fft.fft(signal)[:30] / len(signal))
transformed_sinus = abs(np.fft.fft(sinus)[:30] / len(sinus))

plt.plot(transformed_signal)
plt.plot(transformed_sinus)


The blue line is
transformed_signal
, the green line is the
transformed_sinus
.

fft.pdf

Plotting only
transformed_signal
illustrates the behavior described above:

enter image description here

Can someone explain to me what's going on here?

UPDATE

I was indeed a problem of calling the FFT. This is the correct call and the correct result:

transformed_signal = abs(np.fft.fft(signal,axis=0)[:30] / len(signal))


enter image description here

Answer

Numpy's fft is by default applied over rows. Since your signal variable is a column vector, fft is applied over the rows consisting of one element and returns the one-point FFT of each element.

Use the axis option of fft to specify that you want FFT applied over the columns of signal, i.e.,

transformed_signal = abs(np.fft.fft(signal,axis=0)[:30] / len(signal))