mne-python icon indicating copy to clipboard operation
mne-python copied to clipboard

Snirf files not readable

Open Carlafrenzel opened this issue 1 year ago • 6 comments

Hi,

I am creating snirf files with pysnirf2 based on data collected with LSL in xdf format. I then want to preprocess the data in the snirf files with MNE. If I create the snirf files, the nirs group is an indexed group. So the key will be 'nirs1' as indexing starts with 1 in h5py, I believe. In the snirf documentation (https://github.com/fNIRS/snirf/blob/master/snirf_specification.md#nirsiprobesourcepos2d) the nirs group should also be an indexed group. In Homer3 the created snirf files are readable.

However, with MNE I get an error that the file does not have the nirs element. This is expected as it searches for 'nirs' as a key but the key is actually 'nirs1'.

KeyError: "Unable to open object (object 'nirs' doesn't exist)"

And opening with h5py:

<KeysViewHDF5 ['nirs1']>

My question is, if anyone has any suggestions how to fix this or if there is an quick fix for my problem so that I can actually use my files in MNE?

Another question is, how to generally handle the nirs group. As far as I understand the snirf format is based on hdf5 format and indexing generally starts at 1? Snirf files created with the aurora directly use 'nirs' as a key. Is there any standard which way it should be?

I also attached the file. subj3_mt_loc.snirf.zip

Thanks, Carla

Carlafrenzel avatar Sep 21 '22 16:09 Carlafrenzel

Hello! 👋 Thanks for opening your first issue here! ❤️ We will try to get back to you soon. 🚴🏽‍♂️

welcome[bot] avatar Sep 21 '22 16:09 welcome[bot]

@rob-luke any ideas?

larsoner avatar Sep 21 '22 16:09 larsoner

Hi @Carlafrenzel, thanks for reporting (and thanks for including the problematic file!)

As for a quick fix, you could try this:

import h5py
import mne
with h5py.File('subj3_mt_loc.snirf', 'r+') as dat:
    dat.move('nirs1', 'nirs')

raw = mne.io.read_raw_snirf('subj3_mt_loc.snirf')

but for me at least, that just yields a different error about the MeasurmentTime being None.

drammock avatar Sep 21 '22 17:09 drammock

Hi,

thanks for the quick reply and fix. Your suggestion does work:)

The file I attached does indeed lack the measurementTime data. I didn't notice before. After fixing my mistake the suggested solution does work and I am now able to open the modified snirf file in MNE.

Thanks again:)

Carlafrenzel avatar Sep 22 '22 07:09 Carlafrenzel

Hi @Carlafrenzel, thanks for taking the time to raise this issue.

I just took a read of the SNIRF spec, and as you say, it supports /nirs# as valid naming. See...

All SNIRF data elements are associated with a unique HDF5 location path in the form of /root/parent/.../name. All paths must use /nirs or /nirs# (indexed group array). Note that the root /nirs can be either indexed or a non-indexed single entry.

MNE does not yet support all features of the SNIRF specification. For example, multiple measurements in one file, DCS data types etc. And the edge case you report is also not yet supported.

Further, I do not believe any manufacturers use the indexing /nirs#, every manufacturer file I have got my hands on uses /nirs.

As you are writing your own files, I suggest you use /nirs rather than /nirs1 unless you have a great reason to. But, as you seem technically capable, I think the best solution would be for you to open a small PR to MNE-Python to enable reading either naming with our SNIRF reader. Can you contribute a PR?

rob-luke avatar Sep 23 '22 10:09 rob-luke

Hi @rob-luke,

just to clarify, I do not use /nirs1 or /nirs# on purpose. This rather is an issue with creating own snirf files as pysnirf2 creates nirs as an indexed group. Similarly, if I create an .h5 file and define nirs as an indexed group I end up with /nirs1 again. The one thing I could try, which I haven't yet, is to create an .h5 file and do not create an indexed nirs group. With all other ways related to writing own snirf files with pysnirf2 and/or h5py I end up with the nirs1 problem. But now thanks to @drammock I have a solution. At least for now this works for my files and in the future I can still come up with a more elegant solution:)

Further, I do not believe any manufacturers use the indexing /nirs#, every manufacturer file I have got my hands on uses /nirs.

I really think this will be more of an issue for people who want to use data that is not coming straight from the device. In our case, for example, we used LSL as we have multiple data streams that need to be synchronized.

But, as you seem technically capable, I think the best solution would be for you to open a small PR to MNE-Python to enable reading either naming with our SNIRF reader. Can you contribute a PR?

Yes, I can definitely attempt to contribute but it's probably going to take a couple of days or so.

Carlafrenzel avatar Sep 24 '22 16:09 Carlafrenzel

This rather is an issue with creating own snirf files as pysnirf2

Thanks for clarifying! This is great to know. We should definitely make sure we include support for this in MNE then.

Yes, I can definitely attempt to contribute but it's probably going to take a couple of days or so.

Great! We can guide you through the process if you need help at any point. Just yell out 😄

rob-luke avatar Sep 25 '22 22:09 rob-luke

Great! We can guide you through the process if you need help at any point. Just yell out 😄

That would definitely be great and appreciated:)

Carlafrenzel avatar Sep 26 '22 16:09 Carlafrenzel

Relevant info here: https://github.com/BUNPC/pysnirf2/issues/35

rob-luke avatar Sep 29 '22 23:09 rob-luke