Fourier transform has a wide range of applications. One of these applications include Vibration analysis for predictive maintenance as discussed in my previous blog. Introduction to Predictive Maintenance Solution
In this blog, I am going to explain what Fourier transform is and how we can use Fast Fourier Transform (FFT) in Python to convert our time series data into the frequency domain.
1.0 Fourier Transform
Fourier transform is a function that transforms a time domain signal into frequency domain. The function accepts a time signal as input and produces the frequency representation of the signal as an output.
Every signal in the real world is a time signal and is made up of many sinusoids of different frequencies. So, time domain signal can be converted into the frequency domain to view different frequency components.
Fourier transform doesn’t change the signal. It just provides a different view to analyze your time signal because some properties and features of the signal can be fully explored in the frequency domain.
The most important application of Fourier transform in context of predictive maintenance is vibration analysis which makes use of the fact that all rotating equipment vibrates to a certain degree. The incoming vibration data from the sensors is converted into the frequency domain where you can analyze the frequency of vibration and compare it to the standard baseline to see if your equipment is functioning optimally or not.
Now let me demonstrate an example of using SciPy module to perform Fourier transform on our time series data.
- Open your IDE for Python and install the modules we will be using if you have not installed already.
- pip install scipy
- pip install matplotlib
- Include the modules in your project file.
import numpy as np
import matplotlib.pyplot as plt
from scipy import pi
from scipy.fftpack import fft
- numpy is used for generating arrays
- matplotlib is used for graphs to visualize our data
- scipy is used for fft algorithm which is used for Fourier transform
- The first step is to prepare a time domain signal.
sample_rate = 1024
N = (2 - 0) * sample_rate
- sample_rate is defined as number of samples taken per second. Sample rate of 1024 means, 1024 values of the signal are recorded in one second.
- N is the size of the array. (2 – 0) indicates that only 2 seconds data is available. So, if the sample rate is 1024 and we have 2 seconds data, the size of the array will be (2 – 0) * 1024 which is 2048.
- The x-axis of our time domain signal will be time values and it will contain each time-stamp where the value was recorded.
time = np.linspace(0, 2, N)
- linspace is a function of numpy that takes three arguments; the starting value, ending value, size and returns an array of the size specified with evenly spaced samples, calculated from starting value to ending value.
- Now let’s create our time data. We will add frequency components in our time signal, so we can see the resultant effect after transforming our data into frequency domain.
freq1 = 60
magnitude1 = 25
freq2 = 270
magnitude2 = 2
waveform1 = magnitude1 * np.sin (2 * pi * freq1 * time)
waveform2 = magnitude2 * np.sin (2 * pi * freq2 * time)
- There are two sine waveforms; one with magnitude of 25 at 60Hz frequency and other with magnitude of 2 at 270Hz frequency.
- Let’s add some noise component in our signal.
noise = np.random.normal (0, 3, N)
- normal is a numpy function. The first argument 0 indicates the noise is uniformly distributed, the second argument 3 is the magnitude of noise and N is the size of the array produced by this function with noise data.
- Let’s finally add the waveforms and noise to make up our time data.
time_data = waveform1 + waveform2 + noise
- Now, when we have our data ready so let’s plot our data to see how it looks:
plt.plot (time [0:100], time_data [0:100])
plt.title ('Time Domain Signal')
- We have time on the x-axis (Note that we have used only 100 values to plot, this makes our graph less dense, you could use of full 2048 values to plot) and on the y-axis we have time data. Matplotlib is used for plotting the data.
- The result of this plotting is shown below:
- This is our time domain signal made up of 2 sine waveforms and random noise which makes the signal distorted. Notice that we are not exactly able to see the frequency peaks and magnitude in this signal because everything is so jumbled up here. So, let’s transform it into the frequency domain to see the frequency components.
- To convert this data into frequency domain, let’s use the function fft from scipy.fftpack that takes an array as input and converts that into the frequency domain.
frequency = np.linspace (0.0, 512, int (N/2))
freq_data = fft(time_data)
y = 2/N * np.abs (freq_data [0:np.int (N/2)])
- First, we have created an array with frequencies to plot on the x-axis using the same numpy linspace function as discussed above. Note that we have end-point of 512 even though our sampling rate was 1024. That’s because according to Nyquist-Shannon Sampling theorem, we can only analyze frequency components up to half of the sampling rate.
- After having our x-axis ready with frequencies, we need to transform our time data into frequency data using the fft function. We pass the time data and it returns an array of the same size with values of frequency domain.
- The function will return both positive frequencies and negative frequencies, but as we are only looking for positive frequencies, we have used numpy absolute function to get rid of negative frequencies.
- Now we have the complete frequency spectrum to plot. We have the frequencies on the x-axis and frequency data for y-axis. Let’s plot to see the result:
plt.title('Frequency domain Signal')
plt.xlabel('Frequency in Hz')
- We used matplotlib function again to plot the spectrum with frequencies on the x-axis and y as our y-axis frequency data.
- The graph looks like this:
- You can see there are two frequency components; one at 90Hz with magnitude of 25 and the other one at 270Hz with magnitude of 2.
Feel free to comment below if you have any questions!