Skip to content

[MRG] Add function that returns all defined channel types#4842

Merged
larsoner merged 5 commits intomne-tools:masterfrom
cbrnr:get_channel_types
Dec 21, 2017
Merged

[MRG] Add function that returns all defined channel types#4842
larsoner merged 5 commits intomne-tools:masterfrom
cbrnr:get_channel_types

Conversation

@cbrnr
Copy link
Copy Markdown
Contributor

@cbrnr cbrnr commented Dec 19, 2017

The function get_channel_types returns a dict with known channel types as keys and their definitions in the info dict as values. This PR has two benefits:

  1. It is now possible to ask for a list of known channel types
  2. The function channel_type is now more generic and much shorter (because the logic is now in the dict defined in get_channel_types

WDYT? I can't believe I had to use the else clause of a for loop.

@cbrnr
Copy link
Copy Markdown
Contributor Author

cbrnr commented Dec 19, 2017

A use case for this functionality is described in cbrnr/mnelab#5

@larsoner
Copy link
Copy Markdown
Member

Looks reasonable to me, but not travis.

Can you check for relative speed improvements or regressions? I know the function overhead will be small but it might be used a lot of places in the code. Using OrderedDict with channels ordered roughly by how often they get picked (EEG, MEG, STIM, ECG, EOG?) entered first might make things faster in most use cases, for example.

Did you look at channel_indices_by_type to see if it would suit your use case already?

If you have time, can you look to see if there is a way to (finally!) deduplicate the logic here with that of pick_types now that you've done some standardization?

@codecov
Copy link
Copy Markdown

codecov bot commented Dec 19, 2017

Codecov Report

Merging #4842 into master will increase coverage by 0.02%.
The diff coverage is 90%.

@@            Coverage Diff             @@
##           master    #4842      +/-   ##
==========================================
+ Coverage   83.66%   83.68%   +0.02%     
==========================================
  Files         348      348              
  Lines       62435    62401      -34     
  Branches    10738    10719      -19     
==========================================
- Hits        52237    52222      -15     
+ Misses       7442     7434       -8     
+ Partials     2756     2745      -11

@cbrnr
Copy link
Copy Markdown
Contributor Author

cbrnr commented Dec 19, 2017

Looks reasonable to me, but not travis.

Should be fixed. I assumed that the keys always existed.

Can you check for relative speed improvements or regressions? I know the function overhead will be small but it might be used a lot of places in the code. Using OrderedDict with channels ordered roughly by how often they get picked (EEG, MEG, STIM, ECG, EOG?) entered first might make things faster in most use cases, for example.

Let's check how often this function is called before prematurely optimizing.

Did you look at channel_indices_by_type to see if it would suit your use case already?

No, I really need to know all supported channel types, not just the ones in the current data set.

If you have time, can you look to see if there is a way to (finally!) deduplicate the logic here with that of pick_types now that you've done some standardization?

OMG, I thought this would be a nice and quick PR 😝 . Yes, I'll take a look, but let's first assert that my change is usable in the first place before deduplicating this.

@larsoner
Copy link
Copy Markdown
Member

Let's check how often this function is called before prematurely optimizing.

Right now git grep "channel_type(" gives 27 direct results. Functions that call those could multiply the effect. But it's not currently used by pick_* functions which will help limit its impact.

A quick check would be to try something like pytest mne/io before and after the PR to make sure nothing big changes.

When combined with the deduplication idea (something we should do eventually), it would be used any time a pick_* function would be used, though. So we'd need to look at speed then.

OMG, I thought this would be a nice and quick PR

Yes that's why I added the "if you have time" -- it's not essential for this PR, but if you're in the mode to do it, it would be appreciated :)

@cbrnr
Copy link
Copy Markdown
Contributor Author

cbrnr commented Dec 19, 2017

All tests (except the OSX ones) pass. Now on to the timing question.

@cbrnr
Copy link
Copy Markdown
Contributor Author

cbrnr commented Dec 19, 2017

Master branch:

%timeit [mne.io.pick.channel_type(raw.info, idx) for idx in range(raw.info["nchan"])]
86.8 µs ± 1.51 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

This PR:

%timeit [mne.io.pick.channel_type(raw.info, idx) for idx in range(raw.info["nchan"])]
88.5 µs ± 2.11 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

pytest mne/io seems to be too variable to use as a reliable estimate of speed changes of this PR.

@cbrnr cbrnr changed the title Add get_channel_types that returns all defined channel types [MRG] Add function that returns all defined channel types Dec 19, 2017
mne/io/pick.py Outdated

for t, rules in get_channel_types().items():
for key, vals in rules.items():
if isinstance(vals, int) and ch.get(key, None) != vals:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I find the logic hard to parse. Can you simplify the testing?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

for instance changing this to if ch.get(key, None) not in np.array(vals) might avoid the need for the conditional (depending on how well separated the logic currently is)

Copy link
Copy Markdown
Contributor Author

@cbrnr cbrnr Dec 21, 2017

Choose a reason for hiding this comment

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

Yes, this gets rid of the condition. @larsoner I was wondering if this is possible with simple lists, but apparently there is no list constructor that does something similar to np.array, or is there?
@agramfort I've also added comments. Is the logic clearer now?

@cbrnr
Copy link
Copy Markdown
Contributor Author

cbrnr commented Dec 21, 2017

And yes, as @larsoner mentioned deduplicating this is important! I just saw that this is also used in meas_info.py in create_info. Let's not forget to to that after this PR.

@agramfort
Copy link
Copy Markdown
Member

+1 for MRG when CIs are happy

@larsoner larsoner merged commit df7e00e into mne-tools:master Dec 21, 2017
@cbrnr cbrnr deleted the get_channel_types branch December 21, 2017 15:03
@cbrnr cbrnr mentioned this pull request Jan 1, 2018
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.

3 participants