mne-tools / mne-bids

MNE-BIDS is a Python package that allows you to read and write BIDS-compatible datasets with the help of MNE-Python.
https://mne.tools/mne-bids/
BSD 3-Clause "New" or "Revised" License
131 stars 86 forks source link

store digitization for (non-existing) reference channel(s) #1012

Open dominikwelke opened 2 years ago

dominikwelke commented 2 years ago

Describe the problem

hi all,

I noticed that it is not straight forward to store the digitization for an EEG reference channel if this channel is not present in the raw recorded data (as is the case for my raw data recorded with brainvision recorder).

while it makes sense to only store digitization points for channels that are present, it still feels like a minor bug to me. in the end, the digitization for the ref channel(s) was recorded and would be lost when sharing the raw BIDS formatted data.

Describe your solution

it is possible to acchieve storage of the ref channel location(s) by first adding an empty ref channel to the raw data, and then attaching the montage:

raw = mne.io.read_raw_Brainvision('path/to/file', preload=True)
raw.add_reference_channels('myEEGRef')

montage = mne.channels.make_dig_montage(digiargs)  
raw.set_montage(montage)

write_raw_bids(
        raw,
        bids_path='bids/path',
        allow_preload=True, format='BrainVision')

however, this requires preloading, changes the data and is hence not optimal. also, in my case of brainvision-recorder-files, the comments in the header (including impedance measures etc) are lost this way.

Describe possible alternatives

what do you think, is there an easy way to support this?

adam2392 commented 2 years ago

I haven't dealt much with needing to store reference chs, can you educate us a bit on what the purpose of storing an empty reference channel is in *channels.tsv BIDS files?

sappelhoff commented 2 years ago

Is the reference channel listed in the VHDR file? To my knowledge it might show up under "impedances", but not otherwise 🤔 Do you have a [Coordinates] section in your VHDR file? Or is the montage from elsewhere (e.g., a CapTrak file)?

re: impedances: These are parsed and saved to electrodes.tsv via BIDS, but I understand that it's undesirable to not have them in the VHDR anymore (albeit not really bad)

apart from this: I think there was a discussion once whether tracking EEG reference channels in mne-python might be possible. It'd be quite nice also to fill the EEGReference metadata in BIDS

hoechenberger commented 2 years ago

It'd be quite nice also to fill the EEGReference metadata in BIDS

👍

dominikwelke commented 2 years ago

I haven't dealt much with needing to store reference chs, can you educate us a bit on what the purpose of storing an empty reference channel is in *channels.tsv BIDS files?

Do you have a [Coordinates] section in your VHDR file? Or is the montage from elsewhere (e.g., a CapTrak file)?

@sappelhoff : yes, I recorded channel positions (with a polhemus fasttrack device, in this case). sorry if this didnt come through! @adam2392 : this mainly becomes relevant if you apply e.g. common average reference down the line, as this will "restore" the data of the empty reference channel to the average of all other channels. in my case, i would then have one channel (the restored ref channel) without coordinates, even though these have been recorded.

Is the reference channel listed in the VHDR file? To my knowledge it might show up under "impedances", but not otherwise 🤔

It'd be quite nice also to fill the EEGReference metadata in BIDS

well, in my case the ref is listed in the "Amplifier Setup" section, but not otherwise (brainvision recorder V. 1.23.0003). the impedance list only holds the name of the ref channel (not marked as ref) and Gnd without location/position name.

A m p l i f i e r  S e t u p
============================
Number of channels: 65
Sampling Rate [Hz]: 1000
Sampling Interval [µS]: 1000

Channels
--------
#     Name      Phys. Chn.    Resolution / Unit   Low Cutoff [s]   High Cutoff [Hz]   Notch [Hz]    Gradient         Offset
1     Fp1         1          0.0488281 µV             DC              280              Off
2     Fp2         2          0.0488281 µV             DC              280              Off
(...)

Reference Channel Name = FCz
Reference Phys. Chn.   = 28
Use active/dry Electrodes = Yes 
Good Level [kOhms]     = 10
Bad Level [kOhms]      = 50
(...)

here is a full example header file (masked as .txt for upload): sub-00_task-aeAHA_eeg.vhdr

i found this curious, because if I read the header correctly i'd also expect the Ref to be listed in the Channel info for each channel

[Channel Infos]
; Each entry: Ch<Channel number>=<Name>,<Reference channel name>,
; <Resolution in "Unit">,<Unit>, Future extensions..
; Fields are delimited by commas, some fields might be omitted (empty).
; Commas in channel names are coded as "\1".
Ch1=Fp1,,0.0488281,µV
Ch2=Fp2,,0.0488281,µV
(...)

above, you see the reference channel value is empty (same for all my channels), even though the recorder obviously had this information..

by the way, i just noticed that the procedure i described above (preloading data, adding ref and montage, writing BIDS from MNE object) does change another thing besides omitting the additional info from the header: the "Resolution" entries of the channels are changed (in my case to 0.1 across the bench). the above section in the .vhdr file now reads:

[Channel Infos]
; Each entry: Ch<Channel number>=<Name>,<Reference channel name>,
; <Resolution in "Unit">,<Unit>, Future extensions..
; Fields are delimited by commas, some fields might be omitted (empty).
; Commas in channel names are coded as "\1".
Ch1=Fp1,,0.1,µV
Ch2=Fp2,,0.1,µV
(...)

re: impedances: These are parsed and saved to electrodes.tsv via BIDS, but I understand that it's undesirable to not have them in the VHDR anymore (albeit not really bad)

good to know, thanks! it even takes the correct impedance for the recently added ref channel!

apart from this: I think there was a discussion once whether tracking EEG reference channels in mne-python might be possible.

yes, i also saw this: https://github.com/mne-tools/mne-python/issues/8962

sappelhoff commented 2 years ago

yes, I recorded channel positions (with a polhemus fasttrack device, in this case). sorry if this didnt come through!

It did come through - thanks for the info on the used device -- I was most interested whether you also got the coordinates to show up in the VHDR file itself ... as opposed to having a separate polhemus file with the coordinates.

in my case the ref is listed in the "Amplifier Setup" section, but not otherwise (brainvision recorder V. 1.23.0003)

damn these headers really differ a lot in terms of included information by used software, hardware, and their versions

here is a full example header file (masked as .txt for upload):

I think you (accidentally?) posted the pybv converted header :)

the "Resolution" entries of the channels are changed

yes, that's to be expected based on our code, it's a precaution against loss of precision:


overall I am not sure what we could practically do right now.

dominikwelke commented 2 years ago

I think you (accidentally?) posted the pybv converted header :)

urgs, sorry! sub-00_task-aeAHA_eeg.vhdr

no coordinates in the vhdr file