ICA find_bads_ecg Function

Your plot looks exactly like mine, with this kind of 2 peak/1 peak ondulation. Honestly, I have no idea how the QRS detector implemented works, if you want to dig in, it’s define here.

Also, there is definitely weird lines and filter definition.

  • The ECG events are found with find_ecg_events which defaults to l_freq=5, h_freq=35.
  • The ECG epochs are created with create_ecg_epochs which defaults to l_freq=8, h_freq=16 and calls find_ecg_events with those different filter settings.
  • find_ecg_events calls the qrs_detector function with l_freq=None, h_freq=None despite this function having also l_freq=5, h_freq=35 as defaults.

This last point makes sense because at this point the channel is already filtered, but then why do we have those 2 filter parameters at the qrs_detector level since they are not even used :wink:


Regardless of this weirdness, let’s just test on an raw (unfiltered) ECG channel. I took one of my files recorded on an ANT Neuro ampifier with an ECG channel on the AUX8 channel:

from matplotlib import pyplot as plt
from mne.io import read_raw_fif
from mne.preprocessing import find_ecg_events


raw = read_raw_fif(
    "my-raw-file-with-an-ECG-channel-raw.fif", preload=False
)
raw.pick_channels(["AUX8"])
raw.set_channel_types({"AUX8": "ecg"})
raw.rename_channels({"AUX8": "ECG"})
raw.crop(0, 30)
raw.load_data()

# default for find_ecg_events (5, 35) Hz bandpass
ecg_events1, _, _ = find_ecg_events(
    raw, ch_name="ECG", l_freq=5, h_freq=35
)
# default for create_ecg_epochs (8, 16) Hz bandpass
ecg_events2, _, _ = find_ecg_events(
    raw, ch_name="ECG", l_freq=8, h_freq=16
)

# plot
f, ax = plt.subplots(2, 1, sharex=True, sharey=True)
ax[0].plot(raw.get_data()[0, :])
ax[1].plot(raw.get_data()[0, :])

for event in ecg_events1:
    ax[0].axvline(event[0], color="teal", linestyle="--")
for event in ecg_events2:
    ax[1].axvline(event[0], color="teal", linestyle="--")
    
# format
ax[0].set_title("BP (5, 35) Hz")
ax[1].set_title("BP (8, 16) Hz")
f.tight_layout()

And here is the figure:

Looks like both filter yield a very accurate QRS detection. Again, I did not dig in on how the qrs_detector function actually works, but it works.

1 Like