# [Tutor] fourier transform (fwd)

Danny Yoo dyoo at hkn.eecs.berkeley.edu
Tue Aug 2 03:31:31 CEST 2005

Hi Jeff,

> Yes, for an odd square wave the b's of the fourier series are non zero
> for even values and zero for odd values of n. these are the coefficients
> for the fourier series.  Although I beleive the fft (fourier transform)
> should return the amplitude of frequencies that exist. so for example a
> fft on a 10 hz sin wave with amplitude equal 2 should return all zero
> amplitudes except for at 10 hz there should be a spike with amplitude 2.

Up to this point, I agree with you.

> although... this would be bn = 2 for n=1 in the fourier series.

But at this point, I'm not so sure.

I was expecting coefficient bn to be the contribution at n hertz.  n=0 is
the contribution from the steady state, so for n=1, I didn't expect to get
the contribution from the 10hz wave, but the 1hz one instead.  I'm
hesitant about this because I really don't remember anything from my EE
intro class... *grin*

I think we're straying a bit wildly from Python tutorial material, but
let's try an example and check something out.  I want to sample points
from the function:

f(x) = sin(x) + sin(2x) + sin(3x)

between [0, 2pi].  Let's see...

######
>>> import math
>>> def f(x):
...     return math.sin(x) + math.sin(2*x) + math.sin(3*x)
...
>>> def build_sample(f, n):
...     sample = []
...     x = 0
...     while x < 2*math.pi:
...         sample.append(f(x))
...         x = x + 2*math.pi / float(n)
...     return sample
...
######

This build_sample function will make things nicer to take arbitrary
samples of any function.

######
>>> sample = build_sample(f, 2000)
######

I'll take a sample of 2000 points, just to make the function sorta smooth
to the FFT function.  Ok, let's see what the FFT gives us here:

######
>>> import numarray.fft
>>> frequences = numarray.fft.fft(sample)
>>> frequences[0].real
-5.0942902674044888e-11
>>> frequences[1].real
1.5720366156507799
>>> frequences[2].real
3.1424651347438695
>>> frequences[3].real
4.7037495618800307
>>> frequences[4].real
-0.016650764926842861
>>> frequences[5].real
-0.012744203044761522
>>> frequences[6].real
-0.011435677529394448
######

And to me, this looks like frequences[0] contains the steady state values,
frequences[1] the frequency contribution from 1Hz, and so on.  (I have to
admit that I don't quite understand what the values mean yet.)

Let's try another test:

######
>>> def f(x):
...     return 42 + math.sin(2*x)
...
>>> sample = build_sample(f, 20000)
>>> frequences = numarray.fft.fft(sample)
>>> frequences[0].real
840041.99999999814
>>> frequences[1].real
0.00010469890965382478
>>> frequences[2].real
3.1415140090902716
>>> frequences[3].real
-0.00056553943694630812
>>> frequences[4].real
-0.00041889401962948863
######

Again, I have to plead a huge amount of ignorance here: I don't quite
understand what the real components of the frequencies is supposed to
mean.  *grin*

But it does look like the FFT is sensitive to our f() function at the
right frequences --- it's giving us some honking huge value at the steady
state, and another blip at frequences[2].

Finally, we can try a square wave:

######
>>> def square(x):
...     if x > math.pi:
...         return -1
...     return 1
...
>>> freqs = numarray.fft.fft(build_sample(square, 1000))
>>> freqs[0].real
-1.0
>>> freqs[1].real
2.9999901501133008
>>> freqs[2].real
-0.99996060055012559
>>> freqs[3].real
2.9999113516016997
>>> freqs[4].real
-0.99984240375361688
######

Interesting: I do see some kind of oscillation here, but don't quite
understand what it means.  What happens if we push the sample rate higher?

######
>>> t = numarray.fft.fft(build_sample(square, 100000))
>>> t = numarray.fft.fft(build_sample(square, 100000))
>>> t[0].real
-1.0
>>> t[1].real
2.999999999013506
>>> t[2].real
-0.99999999604174983
>>> t[3].real
2.9999999911217117
>>> t[4].real
-0.99999998418203995
>>> t[5].real
2.9999999753002307
>>> t[6].real
-0.999999964464928
>>> t[7].real
2.9999999516338782
######

Hmmm... the numbers seem to be about the same.  What if we drop them down
really low?

######
>>> t = numarray.fft.fft(build_sample(square, 10))
>>> t[0].real
2.0
>>> t[1].real
-4.4408920985006262e-15
>>> t[2].real
2.0
>>> t[3].real
-1.2382749738730321e-15
>>> t[4].real
2.0
>>> t[5].real
2.2764082277776284e-17
>>> t[6].real
2.0
######

Odd.  Now the odd components look really small!  So sample rate does
appear to be pretty important: otherwise, we get some weird results from
the FFT.

Then again, maybe they're not "weird": maybe I'm just misinterpreting the
results again.  *grin* I wish I knew more about the FFT!  I do have the
excellently whimsical book "Who is Fourier?" in my bookshelf, but haven't
made the time to read it yet.

Talk to you later!

More information about the Tutor mailing list