-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
MRG, DOC: Make "rank" options in docs more accessible #8707
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Basically, I just moved the explanation of the different "rank" settings from the Notes section up to the `rank` parameter, where I think they belong. I also added an info box, suggesting to use `rank='info'` on Maxwell-filtered data. I had discussed this with @SophieHerbst, but would appreciate feedback from @agramfort and / or @larsoner
mne/utils/docs.py
Outdated
| .. note:: For Maxwell-filtered data, you will typically want set this to | ||
| ``'info'``. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say this is actually not true if you use movement compensation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any suggestion on how to phrase this better?
Background is that empirical rank determination doesn't work properly for @SophieHerbst with the default settings: rank is always equal to number of channels. Only with rank='info' do we get what looks like a more "trustworthy" rank. We figured that we somehow should inform users about this. Maybe we can take an entirely different approach in communication here? I know too little about this stuff to come up with really useful proposals, I'm afraid! (as just demonstrated!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might depend on whether Python or Elekta MaxFilter was used (?) but in general what I do is do everything in Python, compute rank on epochs, then pass this as the rank param in all functions (like cov and inverse computation, etc.). I don't usually have trouble with rank when doing this, so we should figure out what the problem is.
For now I would just remove this extra bit of wording (it's an orthogonal issue) and discuss in #4676 what the right thing is to do, probably by sharing files and figuring out what the problems actually are.
|
rendered docs of compute_rank: https://24383-1301584-gh.circle-artifacts.com/0/dev/generated/mne.compute_rank.html#mne.compute_rank rendered docs of make_inverse_operator: https://24383-1301584-gh.circle-artifacts.com/0/dev/generated/mne.minimum_norm.make_inverse_operator.html#mne.minimum_norm.make_inverse_operator |
mne/utils/docs.py
Outdated
| number of good channels. If a `~mne.Covariance` is passed, this can | ||
| make sense if it has been (possibly improperly) regularized without | ||
| taking into account the true data rank. | ||
| """ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing explanation of rank = dict(...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes so what does this actually do? What is the use case? Looking at the code, it seems it simply skips the rank estimation for the channel types that are present in the dict? Why do we need that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the use case? Looking at the code, it seems it simply skips the rank estimation for the channel types that are present in the dict? Why do we need that?
Precisely the one I mentioned that I use above: compute rank once on epochs to obtain a rank dict, then pass this rank dict to compute_covariance, make_inverse_operator, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok this does make sense for those functions, but clearly not for compute_rank – but we do have support there, part of the public API. I think what should be done is refactor compute_rank such that we move the implementation into a private function, which gets called by compute_rank, make_inverse_operator etc; and compute_rank wouldn't accept a dict anymore, while make_inverse_operator and friends would.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a bit of overkill / overengineering to deal with a use case that isn't really causing people problems
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(and it's even possible someone knows their EEG rank but not MEG, but wants the result to have both because they have both, so doing out = compute_rank(epochs, rank=dict(eeg=59)) might even be a valid use case for example)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(and it's even possible someone knows their EEG rank but not MEG, but wants the result to have both because they have both, so doing
out = compute_rank(epochs, rank=dict(eeg=59))might even be a valid use case for example)
Honestly I think that this is over-engineered. Because my naive approach would have been:
out = compute_rank(epochs.copy().pick_types(meg=True))Anyway, I've added a doctoring now :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly I think that this is over-engineered.
Indeed, but the important difference is that this is (perhaps) over-engineered at the user's end, I'm trying to avoid unnecessary code churn and complications at our (MNE maintenance) end. Plus if it's a valid use case (even if over-engineered) then we don't want to break it just to simplify our docstrings a bit.
|
|
||
| Notes | ||
| ----- | ||
| The ``rank`` parameter can be: | ||
|
|
||
| :data:`python:None` (default) | ||
| Rank will be estimated from the data after proper scaling of | ||
| different channel types. | ||
| ``'info'`` | ||
| Rank is inferred from ``info``. If data have been processed | ||
| with Maxwell filtering, the Maxwell filtering header is used. | ||
| Otherwise, the channel counts themselves are used. | ||
| In both cases, the number of projectors is subtracted from | ||
| the (effective) number of channels in the data. | ||
| For example, if Maxwell filtering reduces the rank to 68, with | ||
| two projectors the returned value will be 68. | ||
| ``'full'`` | ||
| Rank is assumed to be full, i.e. equal to the | ||
| number of good channels. If a `Covariance` is passed, this can make | ||
| sense if it has been (possibly improperly) regularized without taking | ||
| into account the true data rank. | ||
|
|
||
| .. versionadded:: 0.18 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| Notes | |
| ----- | |
| The ``rank`` parameter can be: | |
| :data:`python:None` (default) | |
| Rank will be estimated from the data after proper scaling of | |
| different channel types. | |
| ``'info'`` | |
| Rank is inferred from ``info``. If data have been processed | |
| with Maxwell filtering, the Maxwell filtering header is used. | |
| Otherwise, the channel counts themselves are used. | |
| In both cases, the number of projectors is subtracted from | |
| the (effective) number of channels in the data. | |
| For example, if Maxwell filtering reduces the rank to 68, with | |
| two projectors the returned value will be 68. | |
| ``'full'`` | |
| Rank is assumed to be full, i.e. equal to the | |
| number of good channels. If a `Covariance` is passed, this can make | |
| sense if it has been (possibly improperly) regularized without taking | |
| into account the true data rank. | |
| .. versionadded:: 0.18 | |
| Notes | |
| ----- | |
| .. versionadded:: 0.18 |
|
Thanks @hoechenberger |
… [skip github][skip azure]
…thub][skip azure] (#8721)
* upstream/master: (66 commits) MRG, ENH: Add infant template downloader (mne-tools#8738) ENH: add reader for NeuroElectrics .nedf files (mne-tools#8734) DOC: improve glossary entry about fiducials (mne-tools#8763) MRG, ENH: Add Report.add_custom_css (mne-tools#8762) BUG, DOC: read_raw_egi didn't support pathlib.Path; update read_raw() docstring (mne-tools#8759) Add "dbs" as new channel type (mne-tools#8739) MRG, VIZ: Fix title position in plot_sensors (mne-tools#8752) MRG: Support for non-FIFF files in Report.parse_folder (mne-tools#8744) MRG, VIZ, FIX: sEEG picking in _prepare_topomap_plot() (mne-tools#8736) DOC: don't use single letter variable name in _compute_forward (mne-tools#8727) WIP: Fix search [skip github] [skip azp] (mne-tools#8742) WIP: Compare Beer-lambert to HOMER (mne-tools#8711) MRG: bump spyder version (mne-tools#8020) FIX anon with IO round trip (mne-tools#8731) fix set_bipolar_reference for Epochs (mne-tools#8728) WIP: Add width argument, reduce default (mne-tools#8725) ENH: Add toggle-all button to Report (mne-tools#8723) fix int/float conversion in nicolet header (mne-tools#8712) MRG, BUG: Fix Report.add_bem_to_section n_jobs != 1 (mne-tools#8713) MRG, DOC: Make "rank" options in docs more accessible (mne-tools#8707) ...
Basically, I just moved the explanation of the different "rank" settings from the Notes section up to the
rankparameter, where I think they belong. I also added an info box, suggesting to userank='info'on Maxwell-filtered data. I had discussed this with @SophieHerbst, but would appreciate feedback from @agramfort and / or @larsoner