Seal Sleep Analysis- ICA, heart rate calculations, and custom Topography

Hello all,

Thank you very much for providing this forum for folks to ask their MNE questions! I am a PhD student using MNE and EEGLAB (and proprietary LabChart software) to process and score sleep data for seals (EEG, EOG, EMG, and ECG). I am trying to switch all of my analyses to Python to ensure reproducibility with open-source software.

Heart beat detection and heart rate calculation
I would like to detect heart beats and create an additional instantaneous heart rate channel to visualize the success of peak detection. In the past, I have used LabChart (proprietary electrophysiological analysis software) to generate “cyclic measurements” of heart rate in a separate channel. I have found HeartPy in python but would need to get the ECG channel out of and back into MNE to use this.
I have tried mne.preprocessing.find_ecg_events() to locate ECG events. However, I need to customize the qrs_threshold given that the seals’ heart rate can go down to 2bpm and up to ~120bpm. What do the numbers 0-1 mean for this variable?

I have not yet found an easy way to add a heart rate channel in MNE to visualize the success of find_ecg_events() at peak detection. Would you recommend using MNE for heart rate processing or switching to another software or package and then appending a separate channel to the EDF?

Here are the settings I have been using in LabChart:

ICA pre-processing
I’m wondering if there is a way to apply ICA to remove heartbeats from EOG, EEG, and EMG, but maintain the ECG channel intact, and construct two additional channels: one “reconstructed ECG” (append the ECG component(s) which was subtracted from the other channels - similar to ica.find_ecg_events) and one “reconstructed brain” (append the component(s) which seemed to have most of the brain signal). I have used EEGLAB in the past and it has a function to append those components, but I do not know the relevant names in MNE. I would like to append ICA001 or similar from ica.plot_sources.

Custom Topography
I need to create a custom topography map for the location of sensors on the animal, should I only generate this map for sensors on the head or should I include EMG and ECG sensor locations further down on the body? How would you recommend constructing this map from scratch (with distances in centimeters between each electrode)? The ultimate goal would be to use this topomap to demonstrate that ICA successfully isolates artifacts from the ECG channel.

Thank you very much for any help or guidance that you can provide.

  • MNE-Python version: 0.23.00 (just updated- thanks!)
  • operating system: Windows 10
1 Like

Although MNE does come with some ECG detection functions, it is probably a good idea to use a more specialized package for that. I have just started to work on ECG-based sleep detection myself, but I cannot recommend any specific package yet.

If you want to use HeartPy, you need to export the ECG channel to CSV as follows:

  1. Load the data (I assume you have EDF files) with raw = mne.io.read_raw_edf(...)
  2. Convert the ECG channel to a Pandas dataframe df = raw.to_data_frame(picks=...)
  3. Save dataframe to CSV df.to_csv()

You will need to play around with the various arguments in all three function/method calls to create the CSV that HeartPy can read.

Once you have the continuous HR (preferably with the same sampling frequency as the other signals) stored in a CSV file, you can import it into MNE (using pandas.read_csv and mne.io.RawArray) and add the channel to the original raw object using raw.add_channels.

Of course this is just a rough sketch of how I’d try to do it, and there might be many details that need to be discussed. I’d be very interested in your project, so feel free to share more details as you progress here.

Regarding appending ICs, I think this can also be achieved by the add_channels method.

For creating a topography map, I’d only include EEG sensor locations since everything outside the head circumference will be plotted outside the circle. We’re also using either a spherical or a realistic head model that doesn’t include the rest of the body, so we can’t make use of locations that are not on the head. Also, I guess seals look different enough from humans that even if we had whole-body models this wouldn’t really work.

Let me know if you need help for any of these steps outlined above!

Also, if anyone else has alternative suggestions on how to tackle this problem (these problems) I’d be very much interested!

1 Like

It just occurred to me that maybe you don’t need to jump through saving to and loading from CSV hoops. HeartPy works with NumPy arrays, so you can directly extract the ECG time series with raw.get_data(picks=ECG_CHANNEL).