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.
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)
But, scaling up the accY power spectrum plot, there is a strange behavior in my eyes, see:
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()
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()