user3445058
user3445058

Reputation: 21

Extracting meaning from an FFT analysis of data

My question is about Fast Fourier Transforms, since this is the first time i'm using them. So, I have a set of data by years (from 1700 - 2009) and each year corresponding to a certain value (a reading). when i plot the readings against the years it gives me the first plot below. Now, my aim is to find the dominant period with the highest readings using FFT with python (From the graph it seems that it is around 1940 - 1950). So i performed an FFT and got its amplitude and power spectra (see second plot for power spectrum). The power spectrum shows that the dominant frequencies are between 0.08 and 0.1 (cycles/year). My question is, how do i link this to the Readings vs. years ? i.e how do i know from this dominant frequency what year (or period of years) is the dominant one (or how can i use it to find it) ?

The data list can be found here: http://www.physics.utoronto.ca/%7Ephy225h/web-pages/sunspot_yearly.txt

the code i wrote is:

from pylab import *
from numpy import *
from scipy import *
from scipy.optimize import leastsq
import numpy.fft

#-------------------------------------------------------------------------------
# Defining the time array
tmin = 0
tmax = 100 * pi
delta = 0.1
t = arange(tmin, tmax, delta)

# Loading the data from the text file
year, N_sunspots = loadtxt('/Users/.../Desktop/sunspot_yearly.txt', unpack = True) # years and number of sunspots

# Ploting the data
figure(1)
plot(year, N_sunspots)
title('Number of Sunspots vs. Year')
xlabel('time(year)')
ylabel('N')

# Computing the FFT
N_w = fft(N_sunspots)

# Obtaining the frequencies 
n = len(N_sunspots)
freq = fftfreq(n) # dt is default to 1

# keeping only positive terms
N = N_w[1:len(N_w)/2.0]/float(len(N_w[1:len(N_w)/2.0]))
w = freq[1:len(freq)/2.0]

figure(2)
plot(w, real(N))
plot(w, imag(N))
title('The data function f(w) vs. frequency')
xlabel('frequency(cycles/year)')
ylabel('f(w)')
grid(True)

# Amplitude spectrum
Amp_spec = abs(N)

figure(3)
plot(w, Amp_spec)
title('Amplitude spectrum')
xlabel('frequency(cycles/year)')
ylabel('Amplitude')
grid(True)

# Power spectrum
Pwr_spec = abs(N)**2

figure(4)
plot(w, Pwr_spec 'o')
title('Power spectrum')
xlabel('frequency(cycles/year)')
ylabel('Power')
grid(True)

show()

Upvotes: 1

Views: 1921

Answers (1)

Babson
Babson

Reputation: 949

The graph below shows the data input to the FFT. The original data file contains a total of 309 samples. The zero values at the right end are added automatically by the FFT, to pad the number of input samples to the next higher power of two (2^9 = 512).

Time Domain graph - annual sun spot data - sooeet.com FFT calculator

The graph below shows the data input to the FFT, with the Kaiser-Bessel a=3.5 window function applied. The window function reduces the spectral leakage errors in the FFT, when the input to the FFT is a non-periodic signal over the sampling interval, as in this case.

Annual sun spot data with Kaiser-Bessel window applied- sooeet.com FFT calculator

The graph below shows the FFT output at full scale. Without the window function. The peak is at 0.0917968 (47/512) frequency units, which corresponds to a time value of 10.89 years (1/0.0917968).

FFT of annual sun spot data, no window applied - sooeet.com FFT calculator

The graph below shows the FFT output at full scale. With the Kaiser-Bessel a=3.5 window applied. The peak remains in the same frequency location at 0.0917968 (47/512) frequency units, which corresponds to a time value of 10.89 years (1/0.0917968). The peak is more clearly visible above the background, due to the reduction in spectral leakage provided by the window function.

FFT of annual sun spot data, Kaiser-Bessel window applied - sooeet.com FFT calculator

In conclusion, we can say with high certainty that the Sun spot data, provided in the original post, is periodic with a fundamental period of 10.89 years.

FFT and graphs were done with the Sooeet FFT calculator

Upvotes: 1

Related Questions