numpy – Plotting power spectrum in python
numpy – Plotting power spectrum in python
Numpy has a convenience function, np.fft.fftfreq
to compute the frequencies associated with FFT components:
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
data = np.random.rand(301) - 0.5
ps = np.abs(np.fft.fft(data))**2
time_step = 1 / 30
freqs = np.fft.fftfreq(data.size, time_step)
idx = np.argsort(freqs)
plt.plot(freqs[idx], ps[idx])
Note that the largest frequency you see in your case is not 30 Hz, but
In [7]: max(freqs)
Out[7]: 14.950166112956811
You never see the sampling frequency in a power spectrum. If you had had an even number of samples, then you would have reached the Nyquist frequency, 15 Hz in your case (although numpy would have calculated it as -15).
if rate is the sampling rate(Hz), then np.linspace(0, rate/2, n)
is the frequency array of every point in fft. You can use rfft
to calculate the fft in your data is real values:
import numpy as np
import pylab as pl
rate = 30.0
t = np.arange(0, 10, 1/rate)
x = np.sin(2*np.pi*4*t) + np.sin(2*np.pi*7*t) + np.random.randn(len(t))*0.2
p = 20*np.log10(np.abs(np.fft.rfft(x)))
f = np.linspace(0, rate/2, len(p))
plot(f, p)
signal x contains 4Hz & 7Hz sin wave, so there are two peaks at 4Hz & 7Hz.
numpy – Plotting power spectrum in python
You can also use scipy.signal.welch to estimate the power spectral density using Welch’s method.
Here is an comparison between np.fft.fft and scipy.signal.welch:
from scipy import signal
import numpy as np
import matplotlib.pyplot as plt
fs = 10e3
N = 1e5
amp = 2*np.sqrt(2)
freq = 1234.0
noise_power = 0.001 * fs / 2
time = np.arange(N) / fs
x = amp*np.sin(2*np.pi*freq*time)
x += np.random.normal(scale=np.sqrt(noise_power), size=time.shape)
# np.fft.fft
freqs = np.fft.fftfreq(time.size, 1/fs)
idx = np.argsort(freqs)
ps = np.abs(np.fft.fft(x))**2
plt.figure()
plt.plot(freqs[idx], ps[idx])
plt.title(Power spectrum (np.fft.fft))
# signal.welch
f, Pxx_spec = signal.welch(x, fs, flattop, 1024, scaling=spectrum)
plt.figure()
plt.semilogy(f, np.sqrt(Pxx_spec))
plt.xlabel(frequency [Hz])
plt.ylabel(Linear spectrum [V RMS])
plt.title(Power spectrum (scipy.signal.welch))
plt.show()