Unexpected behaviour Raw.pick

I found 2 strange behaviours surrounding Raw and Pick.

The first is that Raw.plot() does not support a picks argument, even though both Epochs.plot() and Evoked.plot() do support it. This is not really a problem, but it makes using MNE a little bit harder than it needs to be.

The second is that Raw.pick() returns the modified instance with the picked channels (as according to documentation), but also modifies the original.

  • MNE version: 1.6.0
  • operating system: macOS 14
from mne.channels import make_standard_montage
from mne.datasets import eegbci
from mne.io import concatenate_raws, read_raw_edf

subject = 1
runs = [6, 10, 14] 

# Fetch some arbitrary EEG data
raw_fnames = eegbci.load_data(subject, runs)
raw = concatenate_raws([read_raw_edf(f, preload=True) for f in raw_fnames])
eegbci.standardize(raw)  # set channel names
raw.set_montage(montage)

print(raw.ch_names) # Raw will have 64 channels
picked_channels = raw.pick(["C3", "C4"]) # picked_channels has 2 channels
print(picked_channels.ch_names)
print(raw.ch_names) # But now raw also only has C3 and C4

This is not clear in the documentation, and can cause bugs. It’s probably better if the original is not modified. If the goal is in-place operations, I think it’d be clearer to not return the modified instance.

Is there a reason they work like this? If not, I’d be happy to fix these things and write a PR.

MNE always modifies objects in place, and for convenience it also returns the modified object so that you can use it in a pipeline: Design philosophy — MNE 1.6.1 documentation

1 Like

I’m not a fan of returning as convenience, but we can agree to disagree.

How about the other behaviour that Raw.plot() doesn’t support a picks argument, even though Evoked and Epochs do?

https://mne.tools/stable/generated/mne.io.Raw.html#mne.io.Raw.plot

https://mne.tools/stable/generated/mne.Epochs.html#mne.Epochs.plot

https://mne.tools/stable/generated/mne.Evoked.html#mne.Evoked.plot

I think adding a picks= argument to Raw.plot might help with the mostly-unified API goal (Design philosophy — MNE 1.6.1 documentation).

This was not meant as an argument, but simply to point out how it is implemented.

Yes, sure, please open an issue in our repo.

2 Likes

This is unexpected, mostly because many other methods in the Raw documentation explicitly mention being performed in-place, whereas the pick method doesn’t.
How would one “pick” a subset of their raw object without overwriting the original object?

Raw.pick() does work in-place. If this is not the case, please file a bug report. If you’re asking how would you pick a subset of channels without modifying the original object, you would use Raw.copy().pick().

1 Like