The documentation for raw.filter() specifies that the raw.info["highpass"] and raw.info["lowpass"] fields only update when calling filter with picks=None. Indeed, attempting to set these values manually (e.g. raw.info["lowpass"] = 7) raises an error: RuntimeError: highpass cannot be set directly. Please use method inst.filter() instead.
I would like to challenge this behavior.
I’m interested in filtering both eeg and eog channels. The former are data channels whereas the latter are not (why?). If I used picks=None I would only filter eeg channels, so I have to usepicks=['eeg', 'eog'] when calling filter(). However, I also want the Info object to store the high/lowpass filters I’m using (for example, when I later call ica.fit(raw), it prints a warning because it thinks my raw object isn’t filtered).
I’m fairly new to MNE, so not sure if you prefer this type of discussions here or as a new “issue” on your github. If so, I can just post it there instead. But I am interested in hearing your opinion
MNE is a package for neurophysiological data analysis, so this might explain why it treats only neurophysiological signals as data channels. While filtering both EEG and EOG channels is a perfectly valid use case, MNE stores only a single raw.info["highpass"] and raw.info["lowpass"] value for all channels. Therefore, the assumption seems to be that all data channels share the same filter settings.
I’m curious what others think about this.
And yes, I think posting questions like this in the forum is the preferred approach.
the current behavior will not set a value for raw.info["lowpass"] even when you specify picks="all", according to the documentation. Only if picks=None will this value be set, which now makes me wonder if the equivalent picks="data" also sets this value (I can’t check now, but will update).
I believe a preferred solution would be to add a keyword argument that controls whether this field is set or not. But lets wait for others to weigh in.
picks="data" includes bad channels unlike picks="all" or picks=None, therefore the behavior shouldn’t be the same.
If picks=None is equivalent to picks="all" (as stated in the documentation) then either the part of the documentation you are referring to is incomplete on this point and needs to be changed, or there is a bug in the evaluation logic of picks.
I think the question pertaining to your use case is whether when you have a “superset” of data and non-data channels the measurement info is/should be updated or not. From the warning you are mentioning I take it that it doesn’t, right? Looking at how picks are selected I would expected it work (picks=["eeg", "eog"] are a superset of picks=None). However, it seems you are falling into the case of not updating a subset of channels, not sure why… Possibly something to do with some excluded channels?
I have other non-data (stim/misc) channels, but none of the eeg and eog are excluded at that point of the pipeline. I do have “bad data” annotations, but this shouldn’t have an effect, should it?
Is there a specific reason why you want to process different channel types simultaneously? Otherwise, I suggest that you create separate objects for EEG and EOG channels and process them separately. Alternatively, it sounds as if you want to treat EOG channels as “EEG-like” (e.g., for ICA), so you could set their type to EEG.
Setting EOG channels to have EEG type is a workaround, but it “feels” wrong…
And why wouldn’t I process different channel types simultaneously? specifically filtering - I would expect that one applies the same high-pass/notch filter to all “electrical” channels (EOG, EEG, etc.), no?
In any case, this has become a thread on user story for a specific edge case and so I leave it to MNE’s product/engineering to discuss… My specific case has multiple workarounds as @cbrnr mentioned.
Thanks!