Description of the problem
I am working with snirf files produced from a NirX Sport 2 system. I have validated the files against the official specification using (pysnirf2)[https://github.com/BUNPC/pysnirf2]. It shows that these are valid snirf files according to the official protocol. When attempting to read these files into mne using read_raw_snirf, an assertion is failed that causes the parsers to fail early. I haven't found any additional documentation to explain why this file isn't capable of being read. Regardless, the parser shouldn't fail to read a file that meets the official specification without explanation as to why (ie missing features). I include below the validator result. Additionally, the snirf file is following version 1.1 of the spec.
from snirf import validateSnirf
target = '2024-01-19_007.snirf'
result = validateSnirf(target)
>>> Found 564 OK (hidden)
>>> Found 704 INFO (hidden)
>>> Found 0 WARNING
>>> Found 0 FATAL
>>> File is VALID
Looking into this problem myself, it seems that the assertion of the number of detector positions and number of detectors in the channel data does not always hold true. Looking at my data, the number of detector positions is 15, while the number of detectors found in the channel data is 14, where D8 is missing. An explanation of why this is the case follows.
In our optode layout, we have bundles of sources and detectors, 8 each. In this layout, we are using 16 sources and 15 detectors. However, because the sources and detectors are in these bundles, there is one remaining detector that would otherwise hang off the cap. To make this less of an obstruction, that detector is placed on the side of the cap, but is not used to capture any signal information. For that reason, it exists in the detector position array, but not in the channels.
Steps to reproduce
from mne.io import read_raw_snirf
target = '2024-01-19_007.snirf'
raw_intensity = read_raw_snirf(target, optode_frame='mri')
Link to data
2024-01-19_007.snirf.zip
Expected results
A parsed snirf file as a RawSNIRF object.
Actual results
Traceback (most recent call last):
File "/home/alexk101/Documents/Research/Bertenthal/fnirs/fnirs-nirx/src/process.py", line 83, in <module>
process_all()
File "/home/alexk101/Documents/Research/Bertenthal/fnirs/fnirs-nirx/src/process.py", line 78, in process_all
sub_data[int(sub.stem)] = process_sub(snirf_file)
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/alexk101/Documents/Research/Bertenthal/fnirs/fnirs-nirx/src/process.py", line 35, in process_sub
raw_intensity = read_raw_snirf(target, optode_frame='mri')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/alexk101/.mambaforge/envs/fnirs/lib/python3.11/site-packages/mne/io/snirf/_snirf.py", line 56, in read_raw_snirf
return RawSNIRF(fname, optode_frame, preload, verbose)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<decorator-gen-340>", line 12, in __init__
File "/home/alexk101/.mambaforge/envs/fnirs/lib/python3.11/site-packages/mne/io/snirf/_snirf.py", line 226, in __init__
assert len(detectors) == detPos3D.shape[0]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError
Additional information
This issue was originally filed under the mne-fnirs repo, but it seems that io is the responsibility of the main mne package. The old issue can be found here. I have discussed a correction for this with @larsoner and will attach the pull request shortly.
Platform Linux-6.7.2-arch1-1-x86_64-with-glibc2.38
Python 3.11.6 | packaged by conda-forge | (main, Oct 3 2023, 10:40:35) [GCC 12.3.0]
Executable /home/alexk101/.mambaforge/envs/fnirs/bin/python
CPU (16 cores)
Memory 30.5 GB
Core
├☒ mne 1.6.0 (outdated, release 1.6.1 is available!)
├☑ numpy 1.26.2 (OpenBLAS 0.3.25 with 16 threads)
├☑ scipy 1.11.4
├☑ matplotlib 3.8.2 (backend=QtAgg)
├☑ pooch 1.8.0
└☑ jinja2 3.1.2
Numerical (optional)
├☑ sklearn 1.3.2
├☑ numba 0.58.1
├☑ nibabel 5.1.0
├☑ nilearn 0.10.2
├☑ dipy 1.7.0
├☑ openmeeg 2.5.7
├☑ cupy 12.2.0
└☑ pandas 2.1.3
Visualization (optional)
├☑ pyvista 0.42.3 (OpenGL 4.5.0 NVIDIA 545.29.06 via NVIDIA GeForce RTX 3070 Ti Laptop GPU/PCIe/SSE2)
├☑ pyvistaqt 0.11.0
├☑ vtk 9.2.6
qt.qpa.plugin: Could not find the Qt platform plugin "wayland" in ""
├☑ qtpy 2.4.1 (PyQt5=5.15.8)
├☑ pyqtgraph 0.13.3
├☑ mne-qt-browser 0.6.1
├☑ ipywidgets 8.1.1
├☑ trame_client 2.13.0
├☑ trame_server 2.12.1
├☑ trame_vtk 2.6.2
├☑ trame_vuetify 2.3.1
└☐ unavailable ipympl
Ecosystem (optional)
├☑ mne-nirs 0.6.0
└☐ unavailable mne-bids, mne-features, mne-connectivity, mne-icalabel, mne-bids-pipeline
Description of the problem
I am working with snirf files produced from a NirX Sport 2 system. I have validated the files against the official specification using (pysnirf2)[https://github.com/BUNPC/pysnirf2]. It shows that these are valid snirf files according to the official protocol. When attempting to read these files into mne using
read_raw_snirf, an assertion is failed that causes the parsers to fail early. I haven't found any additional documentation to explain why this file isn't capable of being read. Regardless, the parser shouldn't fail to read a file that meets the official specification without explanation as to why (ie missing features). I include below the validator result. Additionally, the snirf file is following version 1.1 of the spec.Looking into this problem myself, it seems that the assertion of the number of detector positions and number of detectors in the channel data does not always hold true. Looking at my data, the number of detector positions is 15, while the number of detectors found in the channel data is 14, where D8 is missing. An explanation of why this is the case follows.
In our optode layout, we have bundles of sources and detectors, 8 each. In this layout, we are using 16 sources and 15 detectors. However, because the sources and detectors are in these bundles, there is one remaining detector that would otherwise hang off the cap. To make this less of an obstruction, that detector is placed on the side of the cap, but is not used to capture any signal information. For that reason, it exists in the detector position array, but not in the channels.
Steps to reproduce
Link to data
2024-01-19_007.snirf.zip
Expected results
A parsed snirf file as a RawSNIRF object.
Actual results
Additional information
This issue was originally filed under the mne-fnirs repo, but it seems that io is the responsibility of the main mne package. The old issue can be found here. I have discussed a correction for this with @larsoner and will attach the pull request shortly.