mcluka
mcluka

Reputation: 285

Smoothing FFT graph in Python

I would like to smooth my FFT graphs that are obtained at 200Hz (I capture 500 points at the moment) so that the representative peaks would be shown close to THIS.

This is my code:

N = 500
T = 5/1000
y1 = np.array(data_Ax)
yf1 = scipy.fftpack.fft(y1)
xf1 = np.linspace(0.0, 1.0/(2.0*T), N/2)
yfft1 = 2.0/N * np.abs(yf1[:N//2])

plt.figure(figsize=(20, 3), dpi= 100, facecolor='w', edgecolor='k')
plt.plot(xf1, yfft1, 'g-', label ="FFT for Ax")
plt.xlabel('Frequency [Hz]')
plt.legend(loc=1)

For smoothing I tried to use this:

rft = np.fft.rfft(yfft1)
y_smooth = np.fft.irfft(rft)

But it didn't have any effect.

I'm well aware that 200Hz is a low sampling frequency and 500 measurements aren't much, but it is just to get the hang of the program. Here is the obtained graph: enter image description here

I would like to know:

  1. how to smooth the graph?
  2. how to remove the peaks at 0Hz (High pass filter)?
  3. From the theoretical point of view, is there a minimum number requirement of measurements for a representative FFT graph?

Thank you for any given help!

L

Upvotes: 2

Views: 9125

Answers (3)

Shibe
Shibe

Reputation: 41

First of all I would suggest you get significantly more than 500 samples. That is only 2.5 periods

Using Welch's method should help get a smoother graph.

doc scipy

Upvotes: 2

Gerges
Gerges

Reputation: 6519

Smooth Graph:

I supposed what you are really looking after is increasing the number of points. So just specify the number of points you want to make it look smoother.

For example here is the FFT with the same number of points as the measurements:

n = 500
nfft = n

t = np.linspace(0, 0.1, n)
y = 0.5 + np.sin(2*np.pi*60*t)
yf = fftshift(fft(y, nfft))

f = fftshift(fftfreq(nfft, np.mean(np.diff(t))))

pyplot.plot(f, abs(yf))
pyplot.grid()
pyplot.xlim([-100, 100])

enter image description here

If you change the number of fft points to 4096, i.e. nfft=2**12, then you get a smoother graph. enter image description here

Remove peaks at 0 Hz

If the DC value is all you care about, then just subtract the mean. Based on the example above you can change line 5 to

yf = fftshift(fft(y - np.mean(y), nfft))

and you get the FFT without the baseband. enter image description here

Minimum number of points

From theoretical standpoint, you just need to satisfy Nyquist rate. However for the visual effects, the frequency spacing in the FFT is Fs/N. So if you have a sampling rate of 500 Hz and 500 points, then spacing is 1 Hz between points, If your bandwidth is 5 Hz, this might not be sufficient, so you increase number of points for FFT by zero padding the signal, or decrease the sampling rate (as long as it is above Nyquist)...

Upvotes: 4

Dragon
Dragon

Reputation: 1284

Have you tried using the gaussian filter of the scipy module. Give it a try: https://docs.scipy.org/doc/scipy-0.16.1/reference/generated/scipy.ndimage.filters.gaussian_filter.html

Upvotes: 0

Related Questions