I am using the FFT function in NumPy to do some signal processing. I have array called signal
which has one data point for each hour and has a total of 576 data points. I use the following code on signal
to look at its fourier transform.
t = len(signal)
ft = fft(signal,n=t)
mgft=abs(ft)
plot(mgft[0:t/2+1])
I see two peaks but I am unsure as to what the units of the x axis are i.e., how they map onto hours? Any help would be appreciated.
Result of fft transformation doesn't map to HOURS, but to frequencies contained in your dataset. It would be beneficial to have your transformed graph so we can see where the spikes are.
You might be having spike at the beginning of the transformed buffer, since you didn't do any windowing.
Given sampling rate
FSample
and transform blocksizeN
, you can calculate the frequency resolutiondeltaF
, sampling intervaldeltaT
, and total capture timecapT
using the relationships:Keep in mind also that the FFT returns value from
0
toFSample
, or equivalently-FSample/2
toFSample/2
. In your plot, you're already dropping the-FSample/2
to0
part. NumPy includes a helper function to calculate all this for you: fftfreq.For your values of
deltaT = 1 hour
andN = 576
, you getdeltaF = 0.001736 cycles/hour = 0.04167 cycles/day
, from-0.5 cycles/hour
to0.5 cycles/hour
. So if you have a magnitude peak at, say, bin 48 (and bin 528), that corresponds to a frequency component at48*deltaF = 0.0833 cycles/hour = 2 cycles/day.
In general, you should apply a window function to your time domain data before calculating the FFT, to reduce spectral leakage. The Hann window is almost never a bad choice. You can also use the
rfft
function to skip the-FSample/2, 0
part of the output. So then, your code would be:In general, the dimensional units of frequency from an FFT are the same as the dimensional units of the sample rate attributed to the data fed to the FFT, for example: per meter, per radian, per second, or in your case, per hour.
The scaled units of frequency, per FFT result bin index, are N / theSampleRate, with the same dimensional units as above, where N is the length of the full FFT (you might only be plotting half of this length in the case of strictly real data).
Note that each FFT result peak bin represents a filter with a non-zero bandwidth, so you might want to add some uncertainty or error bounds to the result points you map onto frequency values. Or even use an interpolation estimation method, if needed and appropriate for the source data.