mne-tools / mne-python

MNE: Magnetoencephalography (MEG) and Electroencephalography (EEG) in Python
https://mne.tools
BSD 3-Clause "New" or "Revised" License
2.7k stars 1.31k forks source link

[Question / Bug?]: warnings when interpolating channels #3430

Closed jasmainak closed 7 years ago

jasmainak commented 8 years ago

I get these warnings when I try to interpolate bad channels:

Computing interpolation matrix from 60 sensor positions
Interpolating 0 sensors
    Computing dot products for 291 coils...
    Computing cross products for coils 291 x 15 coils...
    Preparing the mapping matrix...
reproduce_proj.py:10: RuntimeWarning: Projection vector "PCA-v1" has magnitude 0.99 (should be unity), applying projector with 87/102 of the original channels available may be dangerous, consider recomputing and adding projection vectors for channels that are eventually used. If this is intentional, consider using info.normalize_proj()

Projection vector "PCA-v1" has magnitude 0.99 (should be unity), applying projector with 87/102 of the original channels available may be dangerous, consider recomputing and adding projection vectors for channels that are eventually used. If this is intentional, consider using info.normalize_proj()
reproduce_proj.py:10: RuntimeWarning: Projection vector "PCA-v2" has magnitude 0.96 (should be unity), applying projector with 87/102 of the original channels available may be dangerous, consider recomputing and adding projection vectors for channels that are eventually used. If this is intentional, consider using info.normalize_proj()

Projection vector "PCA-v2" has magnitude 0.96 (should be unity), applying projector with 87/102 of the original channels available may be dangerous, consider recomputing and adding projection vectors for channels that are eventually used. If this is intentional, consider using info.normalize_proj()
reproduce_proj.py:10: RuntimeWarning: Projection vector "PCA-v3" has magnitude 0.86 (should be unity), applying projector with 87/102 of the original channels available may be dangerous, consider recomputing and adding projection vectors for channels that are eventually used. If this is intentional, consider using info.normalize_proj()

Projection vector "PCA-v3" has magnitude 0.86 (should be unity), applying projector with 87/102 of the original channels available may be dangerous, consider recomputing and adding projection vectors for channels that are eventually used. If this is intentional, consider using info.normalize_proj()
    [Truncate at 79 missing 0.0001]

The code to reproduce is here:

from mne import io
from mne.datasets import sample

data_path = sample.data_path()
raw_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw.fif'
raw = io.read_raw_fif(raw_fname, preload=True)

raw.info['bads'] = raw.info['ch_names'][2:306:3][:15]

raw.interpolate_bads()

It appears to be somehow related to this: https://github.com/mne-tools/mne-python/blob/master/mne/forward/_field_interpolation.py#L64-L65 but I'm not super sure what's going on. Any clues @Eric89GXL or @agramfort ?

larsoner commented 8 years ago

A protection operator is being applied using fewer channels than were originally used to compute the projection vectors, which can be dangerous in some circumstances, thus the warning. Can we make the message clearer somehow?

In this case they are empty room / acquisition machine projection vectors, so it is probably okay.

jasmainak commented 8 years ago

okay, but why do we need to apply the projection vectors here? this is not something we do with EEG interpolation. To me, the user should apply it before in the pipeline.

larsoner commented 8 years ago

One reason is that we are creating a minimum norm solution, so we apply proj when doing it just like we do in standard inversion. There could be good mathematical reasons for always doing that but we'll have to ask Matti if we're really curious. But I think the idea is that if the projectors are there, we assume they should be applied during inversion.

jasmainak commented 8 years ago

okay, I see. I am really curious :) The reason I ask is that when you compute a mapping matrix for 306 x 306 channels vs 305 x 1, it seems intuitive that they should be exactly the same if you drop the diagonal elements. That is, the quantity printed in the last two lines of this code:

from mne import io, pick_info
from mne.datasets import sample
from mne.forward import _map_meg_channels

data_path = sample.data_path()
raw_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw.fif'
raw = io.read_raw_fif(raw_fname, preload=True)

raw.pick_types(meg=True, stim=False, exclude=[])

info_from = raw.info.copy()
info_to = raw.info.copy()

mapping = _map_meg_channels(info_from, info_to, 'accurate')

info_from = pick_info(info_from, range(1, 306))
info_to = pick_info(info_to, [0])

mapping_slice = _map_meg_channels(info_from, info_to, 'accurate')

print(mapping_slice[0, :5])
print(mapping[0, 1:6])

mapping_slice[0, :5] and mapping[0, 1:6] should exactly be the same. However, this is the case only when I disable the proj in the MNE code.

agramfort commented 8 years ago

what do you suggest? improving the doc? better warning?

jasmainak commented 8 years ago

I suggest getting rid of the warning since it's not clear what the warning means in the context of channel interpolation. Further, if I try to do epoch-wise interpolation, I'm being flooded by these warnings.

Maybe something like this would work? I don't seem to see any qualitative difference in the interpolation if I remove the proj ...

larsoner commented 8 years ago

If you want to go that route you'll have to ask Matti why the projections are used (maybe just for denoising?)

It's probably okay to silence the warnings with verbose='error', but it seems a bit risky

agramfort commented 8 years ago

@jasmainak try removing the projs from the info and see if it affects your results.

you can silence for you the warnings with verbose='error' indeed.

jasmainak commented 8 years ago

okay, sounds like doing verbose='error' could be a "fix". But it's not exposed for raw.interpolate_bads(). I want to suppress the warnings only for this method, not everywhere.

larsoner commented 8 years ago

Pass verbose='error' param only within some call inside interpolate_bads, probably make_projector or so

larsoner commented 8 years ago

Actually a better fix is to call info.normalize_proj before passing it along

jasmainak commented 8 years ago

okay, so there is something to fix in MNE master? should I make a PR?

larsoner commented 8 years ago

You could do it in your own code before calling the interpolation function for now. Not sure if we want it in master or not. Maybe?

larsoner commented 8 years ago

Up for a PR @jasmainak?

jasmainak commented 8 years ago

@Eric89GXL did you change your mind whether this needs to be in master? I also see the problem if I pick channels after making epochs and then do epochs.plot()

larsoner commented 8 years ago

Were you able to fix it in your own code by calling the normalization function? If so I guess we don't need a PR.

jasmainak commented 8 years ago

I haven't looked into yet because I've been working with data without proj. If you keep it open, I might get around to it when I'm hacking on MNE code. No strong feelings either way.

larsoner commented 7 years ago

I'll go ahead and close this one, feel free to reopen if it comes up again/often @jasmainak