3

I'm trying to do Fourier transformation using Python.

There is nice library numpy that have the function fft that supposed according the doc to get series of dots and return the Fourier transformation of them.

Now I try to make it work - but it's looking wrong...

I created simple sine wave 1Hz , Amplitude=1. I sample it with 8Hz (so 8 samples)

These are the samples:

[0,0.707,1,0.707,0,-0.707,-1,-0.707]

Now I expect to get in return the ens. [0,4,0,0,0,0,0,4] or [0,8,0,0] that represents that the frequency is 1Hz (depends if it's does the trimming needed according to Nyquist limit).

But in reality I get the following:

[0.00000000e+00+0.00000000e+00j, -2.22044605e-16-3.99969798e+00j,
 0.00000000e+00+0.00000000e+00j, -2.22044605e-16+3.02022804e-04j,
 0.00000000e+00+0.00000000e+00j,  2.22044605e-16-3.02022804e-04j,
 0.00000000e+00+0.00000000e+00j,  2.22044605e-16+3.99969798e+00j]

This is my code:

import numpy
signal = numpy.array([0,0.707,1,0.707,0,-0.707,-1,-0.707], dtype=float)
f =  numpy.fft.fft(signal)
print (f)

Why am I getting this results? What I do wrong?

Warren Weckesser
  • 110,654
  • 19
  • 194
  • 214

1 Answers1

1

The output of a Fourier transform

The output of nummpy.fft.fft (and every other Fourier transform method) has a complex value. This output encodes information about both the amplitude and phase shift of every frequency component in the input. The complex numbers that you're getting in your output are correct.

How to get the frequency spectrum from the output of fft.fft

From your examples, the output that you seem to be trying to get is actually the frequency spectrum (technically, the energy spectral density). You can calculate this by just taking the absolute value of the result returned from numpy.fft.fft:

import numpy
signal = numpy.array([0,0.707,1,0.707,0,-0.707,-1,-0.707], dtype=float)
f =  numpy.fft.fft(signal)
print(np.abs(f))

Output:

[0.00000000e+00 3.99969798e+00 0.00000000e+00 3.02022804e-04
 0.00000000e+00 3.02022804e-04 0.00000000e+00 3.99969798e+00]

which is exactly what you expected, within some numerical inaccuracy.

As per Warren Weckesser's comment, you can reduce the numerical inaccuracy somewhat by using the "real" value of 2**.5/2 in place of your shorthand .707s:

signal = numpy.array([0, 2**.5/2, 1, 2**.5/2, 0, -2**.5/2, -1, -2**.5/2])
f =  numpy.fft.fft(signal)
print(np.abs(f))

Output:

[0.00000000e+00 4.00000000e+00 0.00000000e+00 2.22044605e-16
 0.00000000e+00 2.22044605e-16 0.00000000e+00 4.00000000e+00]

The absolute value of a complex number is its magnitude. As per the Fourier transform wiki:

the magnitude of the Fourier transform at a point is how much frequency content there is

tel
  • 13,005
  • 2
  • 44
  • 62
  • Taking the absolute value *seemingly* solves the problem, but is not correct and does not generalize to other input functions. The problem is a wrong expectation of OP for where the origin of the input signal is (and also the output). See the proposed duplicate question. – Cris Luengo Dec 19 '18 at 13:45