-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
[MRG, BUG] Fixed bug with EDF channel types and minor bug where other types of channels were not written and bug where annotations were not written to correct scale #9694
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
|
The test doesn't cover the |
Oh apologies, forgot to push up the updated test. Upon further inspection, I realized that EDF cannot write the type of channels in the header, as there is nowhere to store that. I also realized that What we might need to do though is "specify" that you lose channel type information in the doc string. However, with packages like mne-bids, this issue is circumvented since one would just leverage the |
agramfort
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.
no objection to merge
|
Okay now I think this is good to go from me. I put the hidden runtime bug that's user dependent into a new issue. |
There is: The header field 'label' offers 16 ASCII characters. The standard structure consists of three components, from left to right: |
|
Sorry @agramfort there were some updates pertaining to how EDF should be read/written. This is good to go again on my end, and I have added in all the thoughts from #9704 |
agramfort
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.
what does eeglab do when reading files with ch types like this?
I assume that readers that do not parse the label field will just display the complete text as a channel label, e.g. "EEG Fz" instead of just "Fz". For this reason, I would like to have an option to turn channel type parsing off. |
|
|
Co-authored-by: Clemens Brunner <clemens.brunner@gmail.com>
|
I'm sorry if you have already mentioned it in this long thread, but how does EDF only support voltage data? The specs just mention that the physical dimension for each channel are 8 ASCII characters, so any unit should be supported. |
Idk actually. I think possibly we could export any channel type, but I would prefer not implementing the ability to export MEG -> EDF. My impression was that EDF should only be used for EEG-like data. I don't see why anyone would export MEG/non-voltage data to EDF and not FIF unless it was by accident, so we have some catches in export to handle that. |
|
I disagree. The table on the specs page even lists MEG as a signal type. I think we should not artificially restrict our export functionality by allowing only voltage data, which is not backed up by the EDF specs. |
|
Re exporting to EDF vs. FIFF, I think EDF is much more widely adopted/used than FIFF, but even if FIFF is the de facto standard for MEG signals the EDF format allows signals of any unit to be stored. |
| phys_dims = 'uV' | ||
|
|
||
| # get EEG-related data in uV | ||
| units = dict(eeg='uV', ecog='uV', seeg='uV', eog='uV', ecg='uV', emg='uV', |
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.
@cbrnr can you lmk which data channels you would like included here? I'm not a MEG user, so I've only ever used MNE for EEG/iEEG.
Would it be:
mag='fT', grad='fT/cm'
Anything else?
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 include everything. Why not?
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.
Actually the challenge is more-so on reading in MEG/fnirs data correctly using read_raw_edf. I'm not sure how to read in this data correctly. Sure I can easily append "MEG M1" to indicate M1 is a MEG channel, or "FNIRS M2" to indicate M2 is a FNIRS channel, but reading the data back in to do a unit test on the round trip is non-trivial for me.
Is it possible to leave this PR as is and then table it for a future improvement from someone who wants to export MEG/Fnirs to EDF and is familiar with the reader of MEG/Fnirs enough to add that functionality in?
Reference LOC:
Lines 388 to 417 in b579d32
| for idx, ch_name in enumerate(ch_names): | |
| chan_info = {} | |
| chan_info['cal'] = 1. | |
| chan_info['logno'] = idx + 1 | |
| chan_info['scanno'] = idx + 1 | |
| chan_info['range'] = 1. | |
| chan_info['unit_mul'] = FIFF.FIFF_UNITM_NONE | |
| chan_info['ch_name'] = ch_name | |
| chan_info['unit'] = FIFF.FIFF_UNIT_V | |
| chan_info['coord_frame'] = FIFF.FIFFV_COORD_HEAD | |
| chan_info['coil_type'] = FIFF.FIFFV_COIL_EEG | |
| chan_info['kind'] = FIFF.FIFFV_EEG_CH | |
| chan_info['loc'] = np.zeros(12) | |
| if ch_name in eog or idx in eog or idx - nchan in eog: | |
| chan_info['coil_type'] = FIFF.FIFFV_COIL_NONE | |
| chan_info['kind'] = FIFF.FIFFV_EOG_CH | |
| pick_mask[idx] = False | |
| elif ch_name in misc or idx in misc or idx - nchan in misc: | |
| chan_info['coil_type'] = FIFF.FIFFV_COIL_NONE | |
| chan_info['kind'] = FIFF.FIFFV_MISC_CH | |
| pick_mask[idx] = False | |
| elif idx in stim_channel_idxs: | |
| chan_info['coil_type'] = FIFF.FIFFV_COIL_NONE | |
| chan_info['unit'] = FIFF.FIFF_UNIT_NONE | |
| chan_info['kind'] = FIFF.FIFFV_STIM_CH | |
| pick_mask[idx] = False | |
| chan_info['ch_name'] = ch_name | |
| ch_names[idx] = chan_info['ch_name'] | |
| edf_info['units'][idx] = 1 | |
| chs.append(chan_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.
+1 for doing it later. I assume YAGNI, and for MEG important information will be lost anyway (at the very least, the head<->device transform, sensor orientations, sensor coil types)
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 same could be said for EEG as well because EDF doesn't store custom sensor locations. But let's stick to exporting EEG for now, the warning message and code comment are now clear that this is not a restriction imposed by EDF.
Okay sure I can add in then MEG support. Can you lmk which channels and their corresponding default units I should add in to this comment? I'm not too familiar with non-EEG data types in MNE. |
|
This lgtm to go if we are okay w/ the future PR. |
|
Don't want to lose track of this PR since it had a lot of discussion. Is this good to merge now? |
|
thx @adam2392 |
| chan_info['coil_type'] = FIFF.FIFFV_COIL_EEG | ||
| chan_info['kind'] = FIFF.FIFFV_EEG_CH | ||
| chan_info['loc'] = np.zeros(12) | ||
| chan_info['loc'] = nan_arr |
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 needed to be nan_arr.copy() (as found with @drammock working together), after this PR all info['chs'][ii]['loc'] point to the same array in memory, so setting values in one of them sets all of them. We need a unit test that would have caught this...
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 @drammock is working on a fix for this)
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.
Ah my bad. I changed to nan to better match roundtrip.
Lmk if you need me to 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.
see #9743
… types of channels were not written and bug where annotations were not written to correct scale (mne-tools#9694) * Fixing bug * Update doc. * Update docstring * Add diff * Add diff * Add diff * Add warning * Fix flake * Adding test at data level. * Dont mess with global random state * Adding note to edf export * Adding note to edf export * Adding updated unit tests and io reading for edf * Adding unit test for channel type * Adding change log * Add warning * Add additional parameter * Fix docstring * Fixing other test * Fix flake * Apply suggestions from code review Co-authored-by: Alexandre Gramfort <alexandre.gramfort@m4x.org> * Update mne/export/tests/test_export.py Co-authored-by: Alexandre Gramfort <alexandre.gramfort@m4x.org> * Fixing flake * Apply suggestions from code review Co-authored-by: Daniel McCloy <dan@mccloy.info> * Update mne/export/_edf.py Co-authored-by: Daniel McCloy <dan@mccloy.info> * Update mne/export/_edf.py Co-authored-by: Daniel McCloy <dan@mccloy.info> * Update mne/export/_edf.py Co-authored-by: Daniel McCloy <dan@mccloy.info> * Merge * Address comments * Check double export * Fix flake * Remove scruff * Fix codespell * Apply suggestions from code review Co-authored-by: Daniel McCloy <dan@mccloy.info> * update docstring * Commeent on stim * Fix annotations * Adding docstring * Fix number of annotations * Add check for duration * Fix issues * Fix docstring * Apply suggestions from code review Co-authored-by: Clemens Brunner <clemens.brunner@gmail.com> * Clarify warning and inline comment * Fix docstring * Fix doc warning and len(annotations). Co-authored-by: Alexandre Gramfort <alexandre.gramfort@m4x.org> Co-authored-by: Daniel McCloy <dan@mccloy.info> Co-authored-by: Clemens Brunner <clemens.brunner@gmail.com>
* Pull in changes from old PR * [MRG, BUG] Fixed bug with EDF channel types and minor bug where other types of channels were not written and bug where annotations were not written to correct scale (#9694) * Fixing bug * Update doc. * Update docstring * Add diff * Add diff * Add diff * Add warning * Fix flake * Adding test at data level. * Dont mess with global random state * Adding note to edf export * Adding note to edf export * Adding updated unit tests and io reading for edf * Adding unit test for channel type * Adding change log * Add warning * Add additional parameter * Fix docstring * Fixing other test * Fix flake * Apply suggestions from code review Co-authored-by: Alexandre Gramfort <alexandre.gramfort@m4x.org> * Update mne/export/tests/test_export.py Co-authored-by: Alexandre Gramfort <alexandre.gramfort@m4x.org> * Fixing flake * Apply suggestions from code review Co-authored-by: Daniel McCloy <dan@mccloy.info> * Update mne/export/_edf.py Co-authored-by: Daniel McCloy <dan@mccloy.info> * Update mne/export/_edf.py Co-authored-by: Daniel McCloy <dan@mccloy.info> * Update mne/export/_edf.py Co-authored-by: Daniel McCloy <dan@mccloy.info> * Merge * Address comments * Check double export * Fix flake * Remove scruff * Fix codespell * Apply suggestions from code review Co-authored-by: Daniel McCloy <dan@mccloy.info> * update docstring * Commeent on stim * Fix annotations * Adding docstring * Fix number of annotations * Add check for duration * Fix issues * Fix docstring * Apply suggestions from code review Co-authored-by: Clemens Brunner <clemens.brunner@gmail.com> * Clarify warning and inline comment * Fix docstring * Fix doc warning and len(annotations). Co-authored-by: Alexandre Gramfort <alexandre.gramfort@m4x.org> Co-authored-by: Daniel McCloy <dan@mccloy.info> Co-authored-by: Clemens Brunner <clemens.brunner@gmail.com> * Remove _BEM_VIEWS from __init__.py * Add back cropped MNE logo * Change default of raw_psd back to False again * Remove old JS libraries * FIX _repr_html_ of Info add all channel types (#9725) * update info html template * add all channel types to the html repr * update html repr test * Update mne/io/meas_info.py Co-authored-by: Eric Larson <larson.eric.d@gmail.com> * Update mne/io/meas_info.py Co-authored-by: Eric Larson <larson.eric.d@gmail.com> * add repr_html smoke test * ENH: Titles * update changelog * fix name in the change log * FIX: Move down Co-authored-by: Alexandre Gramfort <alexandre.gramfort@m4x.org> Co-authored-by: Eric Larson <larson.eric.d@gmail.com> * Don't call tight_layout() on figs passed to _fig_to_img() * Reduce verbosity related to prjector handling * Don't produce empty drop figure if no epochs were dropped * Don't add legend to GFP plots * use viz.utils.tight_layout() * More tight_layout() * Fix warnings * Finally tight_layout() issues 🙈 * Add back time zone test * Deprecation handling * Better deprecation testing * ALMOST finish work on tutorial * Disable carousel buttons * Finalize tutorial * Maximize main content column width * Allow more than 1 BEM sliders in a row * Apply changes discussed with Alex * flake * Add options to decimate time points in STC and Evoked plots * Add time decimation params to parse_folder() * Try to speed up tutorial rendering * Allow further decimation, render STCs in parse_folder() * Style and further speedups * Even more speeeedd 🚗💨💨 * flake * Apply suggestions from code review [ci skip] Co-authored-by: Alexandre Gramfort <alexandre.gramfort@m4x.org> * Fix reference * Reduce processing time * Further reduce tutorial runtime [skip azp][skip actions] * Explain butterfly param * Avoid "deprecated" decorator * Re-enable add_sys_info test * Don't show STC traces, fix layout * Remove some cruft * Add changelog entries * Remove duplicate line in changelog [ci skip] * A few tiny layout tweaks * Hack around issue between deprecated decorator and numpydoc * Better Note for add_code * Revert "Hack around issue between deprecated decorator and numpydoc" This reverts commit 6d8f9ac. * ENH: Better decorator * BUG: Dont force tight_layout * DOC: Better linking * FIX: Ori labels * STY: Flake * FIX: Missed one * TST: "Fix" doctest * FIX: One more * Use docdict for some more subject and subjects_dir params * Explain slices=None and reformat code for readability * Correct STC subject docstrings * Fix: plot_bem() requires subject param * Remove whitespace * Properly encode titles and TOC entries * Center SVGs, fix horizontal scrolling issue * Add fill_doc decorator to plot_bem() * Fix tests * ENH: Speed up test * Speed up evoked rendering in test * MAINT: Speed up tests * FIX: Also mayavi Co-authored-by: Adam Li <adam2392@gmail.com> Co-authored-by: Alexandre Gramfort <alexandre.gramfort@m4x.org> Co-authored-by: Daniel McCloy <dan@mccloy.info> Co-authored-by: Clemens Brunner <clemens.brunner@gmail.com> Co-authored-by: Valerii <42982039+vagechirkov@users.noreply.github.com> Co-authored-by: Eric Larson <larson.eric.d@gmail.com>
Reference issue
Follow up fix from #9643 where not all the relevant "Voltage/uVoltage" channels were added.
In addition, it will allow channel types to be written to EDF files, in accordance with: #9694 (comment)
Closes: #9704
Closes: #9730
What does this implement/fix?