Easiest way to combine channels while retaining other existing channels?

,
  • MNE-Python version: 0.22

Hello, I’m looking for a way to easily

  • combine two channels into a new, virtual channel,
  • add the virtual channel to the existing data, and
  • drop the two combined channels from the data.

Concrete application: I have EEG data with two HEOG and two VEOG electrodes. I’d like to combine the two electrodes into a bipolar channel (i.e., calculate the differences) for HEOG and VEOG, respectively, for use in further processing.

Is there any convenient way to do this?

I do know about mne.channels.combine_channels(), but it will only return the combined channels and none of the other existing channels. I could take the combined channels and add them back to my original data using Raw.add_channels(), and eventually drop the source channels via Raw.drop_channels(). But this feels very cumbersome and hacky. :exploding_head:

Does anybody have a better idea how to achieve the same result more easily?

Thanks,

–Richard

I don’t know a better way, but it’s the first time I’ve heard of mne.channels.combine_channels. How would you use it to compute a bipolar channel? Like this (assuming that HEOG and VEOG have indices 64 and 65, respectively)?

mne.channels.combine_channels(raw,
                              {"eog": [64, 65]},
                              method=lambda x: np.diff(x, 0))

Yes that’s how I thought I could do it…

Note, however, that I have two channels for each EOG, i.e. I’d like to have VEOG = VEOG1 – VEOG2, and the equivalent for HEOG. But yes you got the principle right.

… But I can tell you’re not really convinced either! :slight_smile:

I think what I want is what set_bipolar_reference() does, just for VEOG and HEOG.

import mne
path = mne.datasets.sample.data_path()

raw = mne.io.read_raw_fif(f'{path}/MEG/sample/sample_audvis_raw.fif', preload=True)

# Copy the EOG channel for demonstration purposes
single_eog_channel = raw.copy().pick_channels(['EOG 061'])
single_eog_channel.rename_channels({'EOG 061': 'EOG 062'})
raw.add_channels([single_eog_channel])

# Create a bipolar EOG channel.
# The resulting signal should be EOG 061 - EOG 062, so all zeros, because in
# this example we just copied the channel.
raw = mne.set_bipolar_reference(raw, 'EOG 061', 'EOG 062', ch_name='HEOG')

# There should now be an all zeros HEOG channel
raw.plot()
1 Like

By default, the original EOG 061 and EOG 062 channels are dropped.

Hello @wmvanvliet, thank you for your example!

But wouldn’t this reference all my signals to the new, virtual channel? (I haven’t tried it yet, will do later)

No. Unlike functions such as set_eeg_reference, set_bipolar_reference just takes the channels you give it, subtracts them from each-other and writes the result to a new channel. Then (optionally) removes the original channels. It was designed with exactly your use case in mind.

1 Like

Interesting! Then I wonder if the name isn’t a bit misleading? Because … you know, set_*_reference(), I expect it to set a reference :slight_smile: I will try it out, thank you so much!!

Reading the doctoring again, yes, it all makes sense the way you explained it!!

Re-reference selected channels using a bipolar referencing scheme.

A bipolar reference takes the difference between two channels (the anode
minus the cathode) and adds it as a new virtual channel. The original
channels will be dropped.

I think the function name is kind of ill-chosen, though… Anyway, I’ll give it a shot and report back! Thank you so much for your suggestion, @wmvanvliet

Thanks @wmvanvliet, it’s doing what I want! Awesome!

1 Like