J.schmidt
J.schmidt

Reputation: 719

Fast Fourier Plot in Python

I have a vibration data in time domain and want to convert it to frequency domain with fft. However the plot of the FFT only shows a big spike at zero and nothing else.

This is my vibration data: https://pastebin.com/7RK57kJW

enter image description here

My code:

import numpy as np
import matplotlib.pyplot as plt

t = np.arange(3000)
a1_fft= np.fft.fft(a1, axis=0)
freq = np.fft.fftfreq(t.shape[-1])
plt.plot(freq, a1_fft)

My FFT Plot:

enter image description here

What am I doing wrong here? I am pretty sure my data is uniform, which provoces in other cases a similar problem with fft.

Upvotes: 2

Views: 2091

Answers (2)

Mad Physicist
Mad Physicist

Reputation: 114290

The bins of the FFT correspond to the frequencies at 0, df, 2df, 3df, ..., F-2df, F-df, where df is determined by the number of bins and F is 1 cycle per bin.

Notice the zero frequency at the beginning. This is called the DC offset. It's the mean of your data. In the data that you show, the mean is ~1.32, while the amplitude of the sine wave is around 0.04. It's not surprising that you can't see a peak that's 33x smaller than the DC term.

There are some common ways to visualize the data that help you get around this. One common methods is to keep the DC offset but use a log scale, at least for the y-axis:

plt.semilogy(freq, a1_fft)

OR

plt.loglog(freq, a1_fft)

Another thing you can do is zoom in on the bottom 1/33rd or so of the plot. You can do this manually, or by adjusting the span of the displayed Y-axis:

p = np.abs(a1_fft[1:]).max() * [-1.1, 1.1]
plt.ylim(p)

If you are plotting the absolute values already, use

p = np.abs(a1_fft[1:]).max() * [-0.1, 1.1]

Another method is to remove the DC offset. A more elegant way of doing this than what @J. Schmidt suggests is to simply not display the DC term:

plt.plot(freq[1:], a1_fft[1:])

Or for the positive frequencies only:

n = freq.size
plt.plot(freq[1:n//2], a1_fft[1:n//2])

The cutoff at n // 2 is only approximate. The correct cutoff depends on whether the FFT has an even or odd number of elements. For even numbers, the middle bin actual has energy from both sides of the spectrum and often gets special treatment.

Upvotes: 2

Bas
Bas

Reputation: 163

The peak at 0 is the DC-gain, which is very high since you didn't normalize your data. Also, the Fourier transform is a complex number, you should plot the absolute value and phase separately. In this code I also plotted only the positive frequencies:

import numpy as np
import matplotlib.pyplot as plt

#Import data
a1 = np.loadtxt('a1.txt')
plt.plot(a1)

#Normalize a1
a1 -= np.mean(a1)

#Your code
t = np.arange(3000)
a1_fft= np.fft.fft(a1, axis=0)
freq = np.fft.fftfreq(t.shape[-1])

#Only plot positive frequencies
plt.figure()
plt.plot(freq[freq>=0], np.abs(a1_fft)[freq>=0])

Upvotes: 0

Related Questions