Search code examples
pythonscipysignal-processingfftvibration

Fast Fourier Transform of subset of vibration dataset


I am new at signal processing. I am trying to compute and plot FFT of a given dataset. The dataset corresponds to vibration signals captured using accelerometer. Dataset contains amplitude in x, y and z direction along with time.

The problem that I am facing is when I try to take a subset of the data, the FFT gives a straight line, I cannot see the frequencies and amplitude in those. Below is the code that I am using:

import matplotlib.pyplot as plt
import numpy as np
from scipy.fftpack import fft
from scipy import signal
import tkinter as tk
from tkinter import filedialog
import time

#Prompt user for file
root = tk.Tk()
root.withdraw()
file_path = filedialog.askopenfilename(filetypes=[("Two Column CSV","*.csv")])
print(file_path)
title = input("Enter Experiment Name: ")

#Load Data (assumes two column array
tic = time.process_time()
x, y, z, t = np.genfromtxt(file_path,delimiter=',', unpack=True)
print(t)
toc = time.process_time()
print("Load Time:",toc-tic)

#Determine variables
N = np.int(np.prod(t.shape))#length of the array
Fs = 1/((t[1]-t[0])/10**9)  #sample rate (Hz)
total_duration = (t[-1] - t[0])/10**9
T = 1/Fs
t_sec = [(t[i+1] - t[0])/10**9 for i in range(0,len(t)-1)]
print('Total Duration: ', total_duration)
print("# Samples:",N)
print('Sampling rate: ',Fs)

tic = time.process_time()
fig_fft, host_fft = plt.subplots()
fig_fft.set_size_inches(16,9)
plt.figure(3)  
xf = np.linspace(0.0, 1.0/(2.0*T), N//2)
yf = fft(x)
plt.plot(xf, 2.0/N * np.abs(yf[0:np.int(N/2)]))
plt.grid()
plt.xlabel('Frequency (Hz)', fontsize=14)
plt.ylabel('Acc (m/$sec^2$)', fontsize=14)
plt.title('FFT (X)- ' + title, fontsize=18)
plt.savefig('FFT (X) {}'.format(title), dpi=300, bbox_inches='tight')
plt.show()

here is the link to main dataset

here is the link to 10sec data extracted from above dataset

Time series plot for subset

enter image description here

please let me know how to fix this problem. Thank you


Solution

  • I frequently had this problem. The zeroth entry of the Fourier transform contains the integral (or the sum) of the signal. If your signal is not centered around zero, this entry will be always very large.

    There are two easy ways to get around this: Either center the measured data around zero (but maybe you want to keep that information of the center for something else)

    x = x - np.mean(x)
    

    Alternatively, simply set the zeroth component to zero:

    yf[0] = 0
    

    A third way would be not to plot the zeroth entry of the array.