how use fft in accelemetros data to transform in spectrum power?

Question:

I placed vibrations of a component using accelerometers, then produced a dataframe with accelerations, that is, dataframe with the following columns: accX, accY and accZ. It is a variable in time, that is, a time series.

My idea is to transform the domain (time (s)) of this variable into the frequency domain (Hz) using fast transform furrier. And for that, I’ve been researching how I can do it, and one of the most used is fft from the numpy library. However, I couldn’t bring it to mine.

dataframe of vibrations data


I have been trying:

# Apply the FFT function to each column
fft_result_X = np.fft.fft(accX)
fft_result_Y = np.fft.fft(accY)
fft_result_Z = np.fft.fft(accZ)

# Calculate the magnitude of the power spectrum of each column
power_spectrum_X = np.abs(fft_result_X) ** 2
power_spectrum_Y = np.abs(fft_result_Y) ** 2
power_spectrum_Z = np.abs(fft_result_Z) ** 2

# Frequencies corresponding to the spectrum
frequencies = np.fft.fftfreq(len(accX), 1/62.5)

result this frequencies and power_spectruns

But, scaling up the accY power spectrum plot, there is a strange behavior in my eyes, see:

accY power spectrum plot

I’ve also been using:

data = dado['accX'].values
ps = np.abs(np.fft.fft(data))**2

time_step = 1 / 62.5 # sampling frequency
freqs = np.fft.fftfreq(data.size, time_step)
idx = np.argsort(freqs)

plt.plot(freqs[idx], ps[idx])
plt.show()

accX power spectrum

Answers:

The numpy.fft.fft() will return both conjugate pairs. What you want to use is the numpy.fft.rfft(). Same thing for numpy.fft.rfftfreq(). Additionally, you should probably normalize your results as well. See the below for a similar example I made.

from datetime import datetime as dt
start=dt.now()

import numpy as np
import pandas as pd
from scipy.fft import rfft, rfftfreq  
import matplotlib.pyplot as plt


data_filepath = "Lab 3 Data.xlsx"
df = pd.read_excel(data_filepath)

V1 = np.array(list(df["Voltage Data 1"]))
V2 = np.array(list(df["Voltage Data 2"]))
V3 = np.array(list(df["Voltage Data 3"]))

V1_fft = (abs(rfft(V1) / V1.size))[0:601]
V2_fft = (abs(rfft(V2) / V2.size))[0:601]
V3_fft = (abs(rfft(V3) / V3.size))[0:601]

t1 = np.linspace(0, V1.size / 1200, V1.size)
t2 = np.linspace(0, V2.size / 1200, V2.size)
t3 = np.linspace(0, V3.size / 1200, V3.size)

f1 = rfftfreq(1200, 1 / 1200)
f2 = rfftfreq(1200, 1 / 1200)
f3 = rfftfreq(1200, 1 / 1200)

fig1, ax1 = plt.subplots(3, 1, figsize = (6.5, 6), dpi = 80)

ax1[0].plot(t1, V1, color = "blue", alpha = 0.5, label = "Data Set 1")
ax1[0].axvspan(4, 4.2, color = "blue", alpha = 0.2, label = "Data Set 1 Limits")

ax1[1].plot(t2, V2, color = "red", alpha = 0.5, label = "Data Set 2")
ax1[1].axvspan(1.8, 2, color = "red", alpha = 0.1, label = "Data Set 2 Limits")

ax1[2].plot(t3, V3, color = "green", alpha = 0.5, label = "Data Set 3")

fig1.suptitle("Figure 1: Voltage over Time Comparison,n Selected Fourier Transform Data Limits")

plt.setp(ax1[1], xlabel= "Time (s)")
plt.setp(ax1[:], ylabel = "Voltage (V)")

fig2, ax2 = plt.subplots(3, 1, figsize = (6.5, 6), dpi = 80)
ax2[0].plot(f1, V1_fft)
ax2[1].plot(f2, V2_fft)
ax2[2].plot(f3, V3_fft)


print("Runtime: {0}".format(dt.now()-start))
plt.show()
Answered By: Jacob Ivanov
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.