Search code examples
pythonscipysignal-processing

Amplitude envelope of hilbert transform does not plot on bandpassed signal


Data clip I'm using

I'm trying to bandpass the attached EEG signal, then apply a hilbert transform and take the absolute of the hilbert to get the instantaneous power (e.g., here). The bandpassed signal looks fine (first plot), and the hilbert of the raw signal looks fine (second plot), but the hilbert of the bandpassed signal does not show up (last plot). The resulting array is: [nan+nanj nan+nanj nan+nanj ... nan+nanj nan+nanj nan+nanj].

Reproducible error with:enter image description here

import numpy as np
from neurodsp.filt import filter_signal
from scipy import signal
import matplotlib.pyplot as plt
Fs = 1024
LBP, HBP = 1, 100
Chan1 = np.loadtxt('SampleData')
Chan1_BP = filter_signal(Chan1, Fs, 'bandpass', (LBP,HBP))
analytical_signal = signal.hilbert(Chan1)
amplitude_envelope = np.abs(analytical_signal)

#Show bandpassed signal works:
fig0 = plt.figure(figsize=(10, 8))
plt.plot(Chan1)
plt.plot(Chan1_BP)


fig1 = plt.figure(figsize=(10, 8))
plt.plot(Chan1)
plt.plot(amplitude_envelope)

# Now with bandpassed signal
analytical_signal = signal.hilbert(Chan1_BP)
amplitude_envelope = np.abs(analytical_signal)

fig2 = plt.figure(figsize=(10, 8))
plt.plot(Chan1_BP)
plt.plot(amplitude_envelope)

Solution

  • Take a closer look at the values in Chan1_BP. You'll see that the values at the beginning and end of the array are nan. The nans were generated by neurodsp.filt.filter_signal. The default filter used by filter_signal is a FIR filter, and the default behavior is to pad the output with nans for values that cannot be computed with the full length of the FIR filter.

    You can change that behavior by passing remove_edges=False, e.g.

    Chan1_BP = filter_signal(Chan1, Fs, 'bandpass', (LBP,HBP), remove_edges=False)
    

    With that change, the plots should look like you expected.