-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Replace inst.pick_channels() with inst.pick() #11907
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
|
There are also some docstrings that need to be adapted, but I'm not sure I even understood that change. Why were Also, Finally, I'm not sure how |
Have you done some investigation on your own looking at blame, GitHub PRs, linked issues, and maybe also dev discussion notes on Discord? I suspect this was discussed at some point previously |
The behavior is equivalent to
Is this a problem for you in practice? This was also discussed at some point a long time ago (I think when we implemented generic string-based picking) and we decided this was going to be a very rare corner case. There might even be a test or two for it, not sure. Feel free to look into past comments and code blame etc. if you're still interested because I think there's stuff in our history about this somewhere as well |
Yes. The PR with the changes is #11665, and the main discussion is in #11531. As far as I understood (I wasn't part of the original discussion), the main issue was inconsistent behavior between Re the Re channel names equalling channel types, I think this is definitely a rare case, but probably not rare enough to ignore. We even have a test, which uses channel types as names: https://github.com/mne-tools/mne-python/blob/main/mne/io/fiff/tests/test_raw_fiff.py#L1150 IMO, a nice API would have two independent parameters inst.pick(types="meg", names=["C3", "Cz", "C4"])I would also remove the inst.pick(types="eeg").drop(names=["C3", "Cz", "C4"])I think this would cover most (all?) use cases, but of course I might be missing something. |
And possibly silent buggy behavior, and the usual considerations of having one-right-way to do things, and trying not to break people's code, etc.
No, I consider this issue closed/resolved by
Yes you found the test I was talking about! Did you look into the history and discussion, though? It looks like this was a concern that was brought up and addressed explicitly in #4511 (comment) (with other API discussion in #4502). Given this extensive prior discussion, I'd rather not continue to discuss this unless we see in practice that it is making things difficult for people. We have had this code in
We spent a decent amount of time years ago deciding an API and implementing it. I don't think we've met the burden for adding new params and breaking our existing API. I don't think we should strive to make all our APIs ideal when it breaks backward compatibility, or strive to cover every corner case. I think we need to be practical and focus on stuff people need, and avoid breaking stuff that already works, even if the API is a bit ugly. |
... these functions we could think about at some point, though, because we decided to focus on instance methods to start and did not make a decision about the: But we should have a separate issue for that since it's going to be another non-trivial discussion separate from replacing instance method usage (this PR). |
We just introduced a new API, namely the
But the workaround will stop working, because there won't be a separate
I think the addition of a new method, which is going to replace two legacy methods, would have been an opportunity to make the API less ugly. It is arguably worse than before IMO. But I won't argue for it anymore if no one else thinks it worth doing. Re |
I think you might be misreading the history -- assuming you're talking about Docs seem to confirm this back to at least 0.21 (older ones are archived and I don't want to unzip them). Discussion of its functionality appears to have been pretty extensive based on the linked discussions in #4511 and #4502 (and possibly elsewhere). The (only?) new-ish picking API change is to change how
We have no plans to remove it.
This part is weird -- I don't think |
You're right, I thought this was added recently. However, it's a pity that what @agramfort suggested way back then (which is exactly what I suggested in this PR again) didn't get enough traction (although many people in the original thread liked it a lot).
OK, this clears up the confusion. I thought they were going to be removed. Still, it is not ideal that disambiguating channel names and types can only be done with these legacy functions. I don't think adding
It's not a warning, but this message after calling This is because a private function still uses |
well, that is definitely something we can/should change now, without further discussion. |
drammock
left a comment
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.
Thanks for tackling this... I had meant to work on this immediately after the addition of @legacy to these methods, but clearly it slipped off my plate. Lots of CI failures, probably all down to repeat examples of the one comment I've left below
dcbfd93 to
18d7109
Compare
|
@drammock would you like to take over? I thought this would be much quicker, and now I need to focus on other things. If there's no hurry, I can of course continue to work on it later (probably in a couple of weeks). I think I've fixed all (simple) issues except for some real bugs that need a little more work. |
I think I can tackle this tomorrow or Monday (but if I fail to, feel free to pick it back up when you have time) |
|
This is a bit of a never-ending story. Is it really too late to discuss/revert/modify this change? I still think replacing
If the idea of replacing |
This is (1) assumed to be rare, and (2) can be easily addressed by renaming the problematic channels
I proposed to remedy this in my summary of the dev mtg discussion. Specifically these: It seems that wasn't part of #11665, but it can/should still happen, either here or in a separate PR.
why is this a problem? We have lots of redundant function/method pairs; personally I don't think we should but that is a larger discussion / not specific to the picking functions/methods, and should get its own issue.
this is an assertion, not an argument. I'll just note that several folks participated in the discussions about the API, both at the live dev meeting and in #11531, and that #11531 was open for nearly two months before it was closed by #11665. There was ample time for API discussion.
There is nothing wrong with testing legacy functionality to make sure we don't break it. It's also OK because end users shouldn't ever need to interact with our tests in their roles as users. If they're contributing new features or bugfixes, they have their contributor hat on and should expect to see some cobwebs when they pull back the curtain. Now, if we're using legacy methods in tests other than tests specifically of those methods then we should change/update the tests that use legacy methods incidentally. I've just done that (hopefully I've caught all of them now). |
|
Thanks @drammock for your thoughts. I know the decision has been made, I just wanted to understand it better. I still don't know why this change was made and why it is supposed to be better than the previous separate methods. It's OK though, no need to discuss this further.
Yes, this would certainly improve consistency! I would add it in a separate PR.
It's not a big deal, but again, consistency. The question could also be: why didn't we keep
Yes, unfortunately I missed it. And several people, including @agramfort were in favor of I guess it's not too late to add that as an enhancement to the API, or is it? It can be completely optional, and maybe at some later time we can make it the primary way to pick channels and types. |
I understand it's probably annoying and disappointing to have missed the discussion, but if we come to a decision as a group everyone in the end has to be willing to live with it to some extent. If there is some bug or something objectively wrong that we need to fix that's one thing. But continuing to push discussion of redesigning the API and discussing its pain points -- most or all of which rehash issues that were already discussed and weighed and deliberated originally -- seems a bit unfair to the people who participated in terms of taking up their (our) time discussing them again. So yes I think in instances like this it's too late unfortunately, and ideally we wouldn't have spent as long as we have already discussing it over the last two weeks. To the point about splitting into
Specifically regarding these I consider them a (very) low priority as I think they get used mostly by experts. Most of the time as a user the correct channels for cov and forward are picked for you when computing inverses, etc. Or to put it in terms of how often we describe these to people by use in examples and tutorials: I think we have very few uses of these things in our docs. This is consistent with my experience helping people use MNE as well -- end-users don't use these. And experts can live with doing a little bit more work. As a side point, So for this PR I think we should change as many user-facing examples as is reasonable, merge, and move on to something else more pressing! |
|
I'm sorry, I just wanted to understand the decision/motivation for the change, which is not clear to me from the discussion on GitHub. |
@dengemann's initial comment in #11531 said:
He goes on to describe how this can lead to silent bugs when data from MNE is processed with NumPy / sklearn / etc. That was the main motivation for changing the Now consider @larsoner's comment later in that thread:
We've now (nearly?) done that in this PR, and it's worth assessing whether the gymnastics necessary to switch over to |
My comment above has to do with what I (errantly?) perceived as a motivation to redesign the API and revise previous decisions built by consensus after deliberation. As a few examples, here, here, or here:
I read these comments as suggestions to "reopen" a decision-making process that we already "closed" by consensus, as opposed to merely an effort to understand the "why" behind those decisions. Apologies if I misread your intent from these statements! But hopefully you can also perhaps see how someone could misread your intentions from them? In any case, hopefully @drammock's explanations above help clarify things further. Looks like CircleCI just needs to be fixed so we can merge. |
|
Thanks for clarifying @drammock. I don't have any energy left to continue this discussion, so although I very much appreciate your suggestion to review this PR again, I'm just going to accept whatever you decide. There are more important things than discussing our pick API. |
|
argh I thought this was still in draft mode. Wasn't finished. I'll do a follow-up PR |
Co-authored-by: Daniel McCloy <dan@mccloy.info>
This fixes deprecation warnings by replacing
inst.pick_channels()withinst.pick()(whereinstis one ofRaw,Epochs, TFR classes, and possibly more). The same replacement is necessary forinst.pick_types().