-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
WIP: Add NIRSport support #7936
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
|
Wow, that's a lot of errors for such a small patch. Regarding Don't know about the code coverage though.
|
474ec68 to
965f2e3
Compare
|
It's actually not that bad: Style errors: Typos: (should be |
The third option may be to return the saturated data and an index/mask to which data is invalid. Not sure how this would actually be implemented. But just throwing all the options out there. |
|
Oh very interesting! I didn't know about this. But yeah sounds like lots of work. And I guess we can't expand But I think its worth having these API discussions now before @swy7ch puts too much work in. We need to decide which approach to take (return NaNs, return invalid data, or return data+mask), then what the defaults should be. @larsoner any suggestions here?
Once we get your test sets in this should fix itself. |
| read_raw_nirx(fname, preload=True) | ||
|
|
||
| @requires_testing_data | ||
| def test_nirx_nosatflags_v1_warn(tmpdir): |
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.
Great. Lets update with your real data once collected.
|
mne-python/mne/io/nirx/nirx.py Lines 133 to 136 in 965f2e3
You can also add NIRSport1 to this somehow (depends how encoded in header file, hopefully the headers for NIRSport1 are similar format). |
Looks like the general header structure is the same, only some variables differ. For instance, in [GeneralInfo], 'APD' (for a NIRScout dataset) are replaced with 'Dual-Tip' (for a NIRSport one). Don't know if they are the same thing with a differnt name, but they're booth booleans.
@drammock Fixed it, except for Not quite used to write Python (C dev here), and PEP8 recommends to break before a binary operator, for readability purpose. Since the choice to break before or after binary operator is a project convention, which path did you chose to follow ? Force-pushing in the meantime to review other changes |
|
We still abide by the old standard (we had a lot of code before they changed it in 2016), see our custom config here https://github.com/mne-tools/mne-python/blob/master/setup.cfg#L19 I'd be okay with removing this requirement altogether. We can't just switch easily -- |
|
No problem, just wanted to stick with PEP8 recommendations before knowing what your were :). I've fixed it. By the way @larsoner, I assume you already now about it but the ci/circleci job is broken: |
mne/io/nirx/nirx.py
Outdated
| ---------- | ||
| fname : str | ||
| Path to the NIRX data folder or header file. | ||
| nosatflags : bool |
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.
Can we try to find a better parameter name? Something without any abbreviations, such as saturated=False or flag_saturated=False would be much better IMO.
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 figured I could use the name of the file, but your request does make sense. Maybe use_saturated ? To be more specific than just saturated. @rob-luke, any idea ?
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 think we need to establish the preferred behaviour of the function first, then answer these detail questions. But my vote is for return_saturated or use_saturated.
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.
IMO flag_saturated is clearer, because it implies that saturated values are flagged somehow (with NaNs in this case). Even if we don't flag/mask saturated values, we will always return saturated values (either masked/flagged or not), so use_saturated or return_saturated does not tell me what they do. So I'd vote for either flag_saturated or mask_saturated, both of which return NaNs for saturated values if True and the raw values if False.
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.
Lets go with mask_saturated then.
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.
My bad, I actually always agreed with @larsoner but I wrote 'annotate' instead of 'nan'. So yes, I think we now all agree on the solution:
saturated='ignore'(the default) returns the original values (contained in .nosatflags_wl* files)saturated='nan'replaces saturated values with NaNs (contained in .wl* files)saturated='annotate'will return the original values (just like'ignore') and in addition will create annotations at the locations of saturated values - however, this option is for another PR
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 we are all on the same page now. Thanks for clarifying cbrnr.
however, this option is for another PR
Can we do this all in this PR? There is no rush to get this merged as we don't even have a test set committed to the repo yet. I don't want to have incomplete support for NIRSport merged, then we are just going to have triage more issues. Let's add complete support in one hit. If annotate is too much work for one person, then multiple people can commit to this branch.
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.
Also thanks for bearing with us Swy7ch. Let us know if there are any other decisions to be made that are blocking your progress.
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.
Don't worry, I actually think the process is quite active, which is a good think as far as I'm concerned :)
Can we do this all in this PR?
Definitely ! You already suggested it in #7926, so I didn't ask again. I'll see what I can do concerning the annotation. A few questions in this regard:
- the data should be used as is (i.e. with NaN values), but the channels must be marked(like the 'bad' channels markin the tutorial), right ? I don't fully understand @drammock's solution
- any idea of the name of the marking ? 'saturated', I assume ?
- do you know if marking an object twice could lead to troubles ? I'll try to find a dataset with channels that are both of bad quality and containing NaN anyway, it's just to have a heads-up.
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.
the data should be used as is (i.e. with NaN values), but the channels must be marked (like the 'bad' channels markin the tutorial), right ? I don't fully understand @drammock's solution
TL;DR: you don't need to understand my solution, because it looks like we're not going to do that anyway (which is fine).
Full explanation: My suggestion of using numpy.ma.masked_array was an alternative to doing separate masked / non-masked options in the reader function. In a masked array approach, the data includes all the saturated values, but the nan-masked values are also read from disk and used to create a numpy mask over the data array. This is nice because it gives users the option to change their mind about using/not using the saturated values later on (without having to reload from disk) because masked arrays make it easy to ignore the mask and see the underlying data if you want to. But the downside is that most of the downstream code (analysis and plotting functions that operate on Raw objects) is not tested to work with masked arrays and I expect several things will break. The good news is, by having string options like ignore and nan and annotate, it leaves open the possibility to add a masked option later if we find that we need/want Raw objects to support masked arrays for other reasons.
e99491d to
c274112
Compare
d7b0ee8 to
a5d5751
Compare
|
Just finished the PR with the three NIRSport (v1) datasets: mne-tools/mne-testing-data#78. Thanks @rob-luke for the example you linked above, it helped me a lot in the process ! I made some slight changes for this second acquisition:
Let me know if anything is missing or can be improved, or if any other testing data is needed. |
|
Looks great @rderollepot. I cut a new release at https://github.com/mne-tools/mne-testing-data/releases/tag/0.111 So you will need to update this line to point to 0.111, then it will give you a hash error, so you will need to update the hash a few lines below. Let us know if you get stuck. mne-python/mne/datasets/utils.py Line 248 in fe8eb45
|
|
Sorry @rob-luke but there is something I am not sure to understand : at which point will I have the hash error ? Is it when I will push the new commit with the updated release number ? |
When the probes get saturated (i.e. when the value they return is "too high"), NIRStar replaces the value with 'NaN' in the standard .wlX file. The true value is kept in a .nosatflags_wlX file, which is a copy of a .wlX file with the true probed values. It is unclear how NIRstar decides that a probe got satured, so we added a flag to `read_raw_nirx()` and `RawNIRX.__init__` to let the user chose which file to use. Providing two *.wl1 or two *.wl2 files still raises an error, as we check for the existence and unicity of the corresponding *.nosatflags_wlX file. Note that the directory structure check doesn't yet discriminate between *.wlX and *.nosatflags_wlX (as it checks for any file ending with 'wlX'). Changing the check could be done in another PR to make sure the user did not provide only *.nosatflags_wlX files and maybe warn them.
Some devices register 'NaN' values when the probes saturate. Since 'NaN' values can cause unexpected behaviour, we added the ability to annotate them so that they can be filtered out during the process.
Yes but also I just downloaded the .tar.gz and the hash I got was this if you want to try to avoid the error: Put this hash in when you update the release number and you should be good |
…port v1 testing data
6414183 to
aa773c2
Compare
|
Ok thank you @larsoner ! |
|
Where are we on this one? We're going to try to release 0.23 soon and it would be nice to get this in! |
|
@rderollepot if you don't currently have the resources to complete this I can assist by pushing a few commits. But only if you wish, no pressure. |
|
@larsoner I just reviewed this code. Its great, but a decent way off finished. The docs don't reflect the code (I think later code modifications just weren't reflected in the docs) and the tests don't really test anything. The authors kindly contributed data to the testing repo, but it is not used here. I am going to put some effort in to tidying up the great work started by @rderollepot and @swy7ch . I cant figure out how to do the right git magic, so I have continued the PR over at #9348. But we must ensure that the original authors are credited appropriately. |
|
Sounds good! |
|
Oh, sorry for being late here, I'll catch up here and on the new PR.
I'll gladly accept your help on this @rob-luke. Since the end of @swy7ch's internship I've indeed been lacking some resources and I wasn't able to consistently spend some time on MNE myself. He also was much more used to the collaborative quality development process than I am, and I must confess I didn't even realize the job on this PR was not finished, sorry for that. So thanks a lot for helping here ! I'll jump to #9348 |
|
@rob-luke want to make a push in the next week or so to get this in, or do we bump the milestone again? |
|
Geez, I'd actually thought this was merged @larsoner. I will take a look at the code this week and evaluate the effort required and if its possible with my schedule in the next two weeks. After changing the ppf, this is my next top priority. |
|
Great ! |
Reference issue
#7926, in this comment.
What does this implement/fix?
Add NIRSport (v1) systems data processing in MNE:
NaNvalues annotationAdditional information
The two versions of NIRSport (1 & 2) do not provide data the same way, so v2 support will be handled later.
As said here by @cbrnr, NIRSport v1 and NIRScout data seem similar enough to use the same reader. We can of course debate this, and I'd make another one if needed.