Sjotroll
Sjotroll

Reputation: 344

Incorrect Fourier coefficients signs resulting from scipy.fft.fft

I analysed a triangle wave using the Fourier series by hand, and then using the scipy.fft package. What I'm getting are the same absolute values of the coefficients, but with opposite signs.
Triangular wave

By hand:
I took the interval [-1,1], calculated the integral to get a0 = 1, then a1, a3 and a5 using the result of integration:
integral1

And all the bn are 0.
Then I simply constructed the series, where the 1st term is a0/2, the second a1×cos(n Pi t/T) and so on, and plotted these waves, which summed give a good approximation of the original signal.
The coefficients are:

a0 = 0.5  
a1 = -0.4053  
a3 = -0.0450  
a5 = -0.0162

individual waves summed waves

Scipy.fft:
I defined the sampling frequency fs=50, and created the space for the function with space=np.linspace(-1,1,2*fs).
Then defined the fft1 = fft.fft(triang(space)), where "triang" is the function which generates the signal. I immediately scaled the results by dividing by the number of samples (100) and multiplying each term except the 0th by 2. Next were the frequencies freq1 = fft.fftfreq(space.shape[-1], d=1/fs). The resulting coefficients (the real parts pertaining to an) are:

a0 = 0.5051  
a1 = 0.4091  
a3 = 0.0452  
a5 = 0.0161

As you can see, the absolute values are correct, but the signs are not. What am I missing?
individual waves-scipy summed waves-scipy

And one bonus question if I may - when doing it this way (using scipy) and plotting each wave separately, should I add the phase angle from np.angle(fft1[n]) into each term, like a1×cos(n Pi t/T + theta) + b1×sin(n Pi t/T + theta)? I'd say yes, but in this example all the bn are 0, and so are the phase angles, so I couldn't really test it.

Upvotes: 2

Views: 99

Answers (1)

Cris Luengo
Cris Luengo

Reputation: 60635

Note that when you call fft(), you don’t pass in the time axis (space). So how is the function supposed to know you sampled from -1 to 1? It doesn’t! It assumes you sampled at 0, 1, 2, 3, … N-1.

This means that the FFT function sees the signal as shifted compared to your manual calculation, and a shift means the phase in the frequency domain changes.

If you sample your triangle function from 0 to 2, instead of -1 to 1, you should get a matching phase.

The difference between sampling with a frequency of 1, or any other frequency (ie samples not being at integer locations) is taken care of by fftfreq(), which just tells you the frequency that corresponds to each bin given your sampling frequency.

Upvotes: 4

Related Questions