Search code examples
pythonfft

python scipy.fft huge y scale of Fast Fourier Transform


I have a working python script for Fast Fourier Transform (fft) signal which plots the graph and fft correctly, I am fetching data from postgre so I ommited that code. And due to limit of paste i pasted shorter version of signal, but the signal is preatty much the similar on longer timeframe.

The x scale of fft is fine, but what i get is a large y scale which i do not understand.

I have an fft processed by machine directly that looks correct and i have another measurement done by hand held machine. The ffts look almost identical on x scale and relative sizes on y scale, but the actual calculated y scale differ a lot.

data

plot from python

from device

In script data_step is in micro second between two timestamps. The n and datastep cant be wrong since the x axis is fine. From the data i get:

Min of signal(value_points_sensor1): -0.057881687

Max of signal: 0.07810274

Max of fft y: 5522.93

Shouldnt the size of fft be similar to size of amplitude of signal? Also arent the unit of amplitude on fft and signal on y axis the same?

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

figure, axis = plt.subplots(2, 1)
plt.subplots_adjust(hspace=1)
    
time_points_sensor1 = np.array(row[4])
value_points_sensor1 = np.array(row[3])
    
axis[0].plot(time_points_sensor1, value_points_sensor1)

   
n  = len(row[2])
data_step = (abs((int(row[2][-2] - row[2][-1]))) / 1000000)

yf = rfft(value_points_sensor1)
xf = rfftfreq(n,data_step)

axis[1].plot(xf,abs(yf))
    
plt.show()

Solution

  • The value of rfft is proportional both to the magnitude of the data and the number of points. So you should expect the values in yf to be large.

    Compare:

    # One cycle of a cosine curve
    x = rfft(np.cos(np.linspace(0, 2 * np.pi, 1000)))
    max(abs(x))
    500.2493021844711
    
    # Two cycles of a cosine curve, again 1000 points per cycle
    x = rfft(np.cos(np.linspace(0, 4 * np.pi, 2000)))
    max(abs(x))
    1000.2484171710441