Sunday, September 17, 2017

discrete signals - Negative values of the FFT


I try to describe a simple signal in the frequency domain with the use of FFT function:


from scipy.fftpack import fftfreq, rfft

def spectrum(sig, t):

"""
:param sig: signal.
:param t: time scale.
:return:
"""
f = fftfreq(sig.size, d=t[1]-t[0])
y = rfft(sig)
return f, y

Signal:



enter image description here


...and it's FFT:


enter image description here


Why I'm getting negative values of the FFT? Do I even use the FFT function well? I want to check "how many" frequencies are in the shown above signal. Thank you in advance.



Answer



The rfft function returns complex values ordered in specific way. In order to retrieve the amplitude of your DFT you must take the absolute value of it. Easiest way to do that is to call y_a = np.abs(y).


I also noticed in your case that you are using fftfreq function to obtain corresponding frequency vector. In case of rfft you must use the rfftfreq. This will eliminate this nasty wrap-around on your plot. Also you should not forget about amplitude normalization by half of your window energy.


Here is the complete example:


from scipy.fftpack import rfftfreq, rfft
import numpy as np

import matplotlib.pyplot as plt


def spectrum(sig, t):
f = rfftfreq(sig.size, d=t[1]-t[0])
y = rfft(sig)

return f, y



if __name__ == "__main__":
N = 1000
t = np.linspace(0, 4*np.pi, N)
x = np.sin(10*np.pi*t)+np.random.randn(N)


f, y = spectrum(x, t)

plt.subplot(211)
plt.plot(t,x)

plt.grid(True)
plt.subplot(212)
y_a = np.abs(y)/N*2 # Scale accordingly
plt.plot(f, y_a)
plt.grid(True)
plt.show()

No comments:

Post a Comment

periodic trends - Comparing radii in lithium, beryllium, magnesium, aluminium and sodium ions

Apparently the of last four, $\ce{Mg^2+}$ is closest in radius to $\ce{Li+}$. Is this true, and if so, why would a whole larger shell ($\ce{...