In Python, I consider a dummy signal as follows:
fs = 512
sig = np.random.standard_normal((fs,))
sig
corresponds to 1s of data at 512Hz.
To check Parseval theorem on the whole signal, I do:
fft = np.fft.fft(sig)
f = np.fft.fftfreqs(sig.size, d=1. / fs)
m = np.sum((np.abs(fft) ** 2) / sig.size)
e = np.sum(sig ** 2)
print('diff = %1.5f' % (m - e))
This actually returns 0.0
. Now, to compute the energy of the signal in a given frequency band (say 5Hz - 15Hz), I would filter the signal using a bandpass filter and compute its energy as above:
def _butter(lowcut, highcut, fs, order=5, btype='bandpass'):
nyq = 0.5 * fs
low = lowcut / nyq
high = highcut / nyq
b, a = butter(order, [low, high], btype=btype)
return b, a
def _filter(data, lowcut, highcut, fs, order=5, btype='bandpass'):
b, a = _butter(lowcut, highcut, fs, order=order, btype=btype)
y = filtfilt(b, a, data)
return y
filtered_sig = _filter(sig, 5., 15., fs)
e_band = np.sum(filtered_sig ** 2)
My question is: can I use Parseval theorem to compute the energy of the signal (in the 5Hz-15Hz) band using fft
as above? I naively tried:
mask = np.logical_and(np.abs(f) >= 5, np.abs(f) <= 15)
m_band = np.sum((np.abs(fft[mask]) ** 2) / sig.size)
But the quantities m_band
and e_band
are not equal.
Where did I make a mistake?