Skip to content

Conversation

@larsoner
Copy link
Member

@larsoner larsoner commented Feb 3, 2016

One possible solution to the projection issue. @agramfort can you take a look and see if you think this is a good approach? You can see that for e.g. our LCMV tests we had a lot of violations due to subselections. I'll need to make a lot of other cleanups to get rid of all the warnings in tests, but I wanted to make sure that's the right approach before doing it.

Related to #2760.

@larsoner larsoner added this to the 0.12 milestone Feb 3, 2016
@wmvanvliet
Copy link
Contributor

what's with the stacklevel parameter? Is that a temporary thing?

@agramfort
Copy link
Member

for the beamformer test can't you just apply the projections before subselection? and raise a warning if proj have not been applied?

I don't like this new stacklevel parameter either ;)

@larsoner
Copy link
Member Author

larsoner commented Feb 4, 2016 via email

@larsoner
Copy link
Member Author

larsoner commented Feb 4, 2016

FYI the stacklevel changes outputs from things like this (for the io module):

/home/larsoner/custombuilds/mne-python/mne/io/fiff/raw.py:186: UserWarning: This file contains raw Internal Active Shielding data. It may be distorted. Elekta recommends it be run through MaxFilter to produce reliable results. Consider closing the file and running MaxFilter on the data.
  warnings.warn(msg)  # , stacklevel=7)

i.e., not informative about user's line caused the warning, to:

/home/larsoner/Desktop/untitled3.py:3: UserWarning: This file contains raw Internal Active Shielding data. It may be distorted. Elekta recommends it be run through MaxFilter to produce reliable results. Consider closing the file and running MaxFilter on the data.
  allow_maxshield=True)

numpy does this with their warnings about slicing and the like. I think we should start doing it everywhere. It makes debugging warnings a lot easier.

@larsoner
Copy link
Member Author

larsoner commented Feb 4, 2016

@agramfort if I do raw.apply_proj() and remove all the warning catches that I put in for the one test test_lcmv, I end up with 7 lines in the test that elicit warnings about too few channels during projection.

I think it's an interaction with the covariance code, where even if you apply proj, after doing a selection with epochs, you need to subselect the channels from the covariance that actually need to be used in beamforming. During that process, projectors get applied with a limited subset of channels. I suspect it's a bug -- it seems like we'd want to apply the projectors to the covariance matrix and then subselect -- but it looks like someone went through a lot of effort to let it work the other way (subselect, then apply re-normalized partial projection vectors). It might be related to needing to know the degrees of freedom. If you apply N vectors then subselect channels I don't think you can guarantee how many DOF you've lost, whereas if you subselect then apply N vectors, you know you've dropped your DOF by N.

@agramfort
Copy link
Member

agramfort commented Feb 5, 2016 via email

@larsoner
Copy link
Member Author

larsoner commented Feb 5, 2016

Once the stacklevel stuff is merged, this will be rebased and more or less ready to go. You can find the bugs by looking at where I had to add warning-catchers.

@larsoner larsoner changed the title WIP: Protect against bad projections ENH: Protect against bad projections Feb 9, 2016
@larsoner
Copy link
Member Author

larsoner commented Feb 9, 2016

@agramfort now you can see where all the proj options are problematic in our tests by the added warnings.catch_warnings calls. I'm fine to merge this as is, or have you take over, up to you.


# Handle whitening + data covariance
whitener, _ = compute_whitener(noise_cov, info, picks, rank=rank)
whitener = compute_whitener(noise_cov, info, picks, rank=rank)[0]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer the older way. I find it less error prone as it makes the code break when the number of output args changes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reverted

@larsoner
Copy link
Member Author

@agramfort feel free to push directly to this branch if you want

mne/io/proj.py Outdated
orig_n = p['data']['data'].shape[1]
if len(vecsel) < 0.9 * orig_n:
warn('Projection vector "%s" magnitude %0.2f, '
'applying projector with %s/%s of the original '
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get this sentence. Words are missing or something.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"vector %s has magnitude %f (should be unity)" make more sense?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it does

@agramfort
Copy link
Member

about the "lot of efforts" are you talking about the _prepare_beamformer_input function?

@larsoner
Copy link
Member Author

Not quite. The problem is that I'm not sure how you properly deal with using projections, but then later only subselecting a set of channels like is done in that example. Fortunately we don't do it in many places in the codebase (maybe only in tests to primarily save time?) but I suspect what we're doing isn't quite right. If you eliminate, say, half the channels than your previously-orthogonal vectors very will might not be orthogonal anymore. So things like rank estimates can get screwed up. But I suppose in that case we'd be conservative by saying that 2 projectors always decreases rank by 2, even with channel removal.

@larsoner
Copy link
Member Author

Also see from above:

I think it's an interaction with the covariance code, where even if you apply proj, after doing a selection with epochs, you need to subselect the channels from the covariance that actually need to be used in beamforming. During that process, projectors get applied with a limited subset of channels. I suspect it's a bug -- it seems like we'd want to apply the projectors to the covariance matrix and then subselect -- but it looks like someone went through a lot of effort to let it work the other way (subselect, then apply re-normalized partial projection vectors). It might be related to needing to know the degrees of freedom. If you apply N vectors then subselect channels I don't think you can guarantee how many DOF you've lost, whereas if you subselect then apply N vectors, you know you've dropped your DOF by N.

@larsoner
Copy link
Member Author

Changed warning text and rebased

@agramfort
Copy link
Member

does this help:

agramfort@9bf4111

?

@larsoner
Copy link
Member Author

The way to check would be to remove all the with warnings.catch_warnings(record=True) that I inserted in the tests. I'll try it.

picks=picks, baseline=(None, 0),
preload=epochs_preload,
reject=dict(grad=4000e-13, mag=4e-12, eog=150e-6))
with warnings.catch_warnings(record=True):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this one still needs to stay

@larsoner
Copy link
Member Author

I stopped after the first three checks, but it looks like no, it didn't help

@larsoner
Copy link
Member Author

I think it's because a lot of the warnings come from the guts of the covariance code, not the beamforming code

@agramfort
Copy link
Member

agramfort commented Feb 28, 2016 via email

@larsoner
Copy link
Member Author

Cool, thanks for looking. Feel free to push to my branch if you find a solution, I probably won't work on it in the meantime.

@larsoner
Copy link
Member Author

@agramfort comments addressed, see what you think

vals = np.abs(vals) # avoid negative values (numerical errors)
# avoid negative (numerical errors) or zero (semi-definite matrix) values
tol = vals.max() * vals.size * np.finfo(np.float64).eps
vals = np.where(vals > tol, vals, tol)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were getting some values that actually equalled zero, which threw a warning. This prevents that from happening hopefully by setting a hopefully reasonable minimum, but please double-check my logic @agramfort

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@larsoner
Copy link
Member Author

ping @agramfort

mne/io/proj.py Outdated
'%s/%s of the original channels available may '
'be dangerous, consider recomputing and adding '
'projection vectors for channels that are '
'eventually used'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please update the warning to recommend to use normalize_proj method

@larsoner
Copy link
Member Author

@agramfort warning updated. Anything else?

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.04%) to 90.731% when pulling 0628608 on Eric89GXL:proj-protect into 923bdc3 on mne-tools:master.

@agramfort
Copy link
Member

@Eric89GXL I pushed a commit here. I think we're almost there...

@coveralls
Copy link

Coverage Status

Coverage increased (+0.08%) to 90.844% when pulling 29021d8 on Eric89GXL:proj-protect into 923bdc3 on mne-tools:master.

@larsoner
Copy link
Member Author

@agramfort anything left to do that you can see?

@agramfort
Copy link
Member

I think we're good. Hopefully we did not break anything...

please rebase and add a clear message on what's new.

thanks heaps @Eric89GXL !

@larsoner
Copy link
Member Author

Done and merged by rebase, thanks @agramfort

@larsoner larsoner closed this Mar 28, 2016
@larsoner larsoner deleted the proj-protect branch March 28, 2016 11:57
@agramfort
Copy link
Member

agramfort commented Mar 28, 2016 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants