Skip to content

Reading 3D coordinates from snirf produces different result than read_custom_montage() #545

Description

@kdarti

Describe the bug

I'm not completely sure that this is a bug, and I'm not sure it's even expected that you'd get the same results when automatically reading coordinates from a snirf file as when reading the same coordinates using read_custom_montage().

Steps to reproduce

20240327-snirf3d-mne.zip

import mne
mne.io.read_raw_snirf(r"2x12_nz-to-nasion.snirf").get_montage().plot()
mne.channels.read_custom_montage(r"digitisation_2x12.elc").plot()
mne.io.read_raw_snirf(r"2x12_nz-to-nasion.snirf").get_montage().get_positions()
mne.channels.read_custom_montage(r"digitisation_2x12.elc").get_positions()

Expected results

I'd expect the resulting coordinates to be the same, given the coordinates in the .snirf and the .elc files are identical.

The difference seems to lie here:

https://github.com/mne-tools/mne-python/blob/eee8e6fe580034f4a3a4fb13bdca3bfc99240708/mne/channels/_standard_montage_utils.py#L274

If I comment out that line I get identical results.

Actual results

image
image

I should say that the digitisation is bad and not realistic, but the result that I expect is what I get from read_custom_montage()

mne.io.read_raw_snirf(r"2x12_nz-to-nasion.snirf").get_montage().get_positions()
Loading ...\2x12_nz-to-nasion.snirf
Out[221]: 
{'ch_pos': OrderedDict([('S1', array([0.05263, 0.04361, 0.10604])),
              ('S2', array([-0.0598 ,  0.03692,  0.10477])),
              ('S3', array([-0.00454,  0.09951,  0.07741])),
              ('S4', array([0.05279, 0.11416, 0.00981])),
              ('S5', array([-0.06111,  0.11034,  0.00243])),
              ('S6', array([ 0.06122, -0.1047 ,  0.0347 ])),
              ('S7', array([-0.0399 , -0.10976,  0.04771])),
              ('S8', array([ 0.01618, -0.07903,  0.09699])),
              ('S9', array([ 0.07706, -0.03319,  0.09421])),
              ('S10', array([-0.04648, -0.03294,  0.11256])),
              ('D1', array([-0.00076,  0.04186,  0.119  ])),
              ('D2', array([0.05333, 0.08289, 0.07874])),
              ('D3', array([-0.06278,  0.08358,  0.07064])),
              ('D4', array([-0.0044 ,  0.12561,  0.01085])),
              ('D5', array([ 0.01436, -0.11273,  0.05478])),
              ('D6', array([ 0.07158, -0.08069,  0.06542])),
              ('D7', array([-0.03738, -0.07695,  0.09272])),
              ('D8', array([ 0.01718, -0.03431,  0.12018]))]),
 'coord_frame': 'unknown',
 'nasion': array([-0.001,  0.084, -0.043]),
 'lpa': array([-0.0825, -0.018 , -0.048 ]),
 'rpa': array([ 0.081, -0.019, -0.048]),
 'hsp': None,
 'hpi': None}

mne.channels.read_custom_montage(r"digitisation_2x12.elc").get_positions()
Out[222]: 
{'ch_pos': OrderedDict([('D1', array([-0.00057231,  0.03152226,  0.08961177])),
              ('D2', array([0.04015963, 0.06241949, 0.05929438])),
              ('D3', array([-0.04727586,  0.06293909,  0.05319475])),
              ('D4', array([-0.00331338,  0.09458937,  0.00817049])),
              ('D5', array([ 0.01081366, -0.08489021,  0.04125154])),
              ('D6', array([ 0.05390261, -0.06076281,  0.04926388])),
              ('D7', array([-0.02814864, -0.05794644,  0.06982188])),
              ('D8', array([ 0.01293723, -0.02583681,  0.09050036])),
              ('S1', array([0.0396325 , 0.03284008, 0.07985237])),
              ('S2', array([-0.0450318 ,  0.02780224,  0.07889601])),
              ('S3', array([-0.0034188 ,  0.07493502,  0.05829283])),
              ('S4', array([0.03975299, 0.08596706, 0.00738732])),
              ('S5', array([-0.04601828,  0.08309044,  0.00182989])),
              ('S6', array([ 0.04610111, -0.0788433 ,  0.02613049])),
              ('S7', array([-0.0300463 , -0.08265368,  0.03592754])),
              ('S8', array([ 0.01218419, -0.05951276,  0.07303736])),
              ('S9', array([ 0.05802927, -0.0249934 ,  0.07094391])),
              ('S10', array([-0.0350013 , -0.02480514,  0.08476219]))]),
 'coord_frame': 'unknown',
 'nasion': array([-0.00075304,  0.06325537, -0.03238072]),
 'lpa': array([-0.06212581, -0.01355472, -0.03614592]),
 'rpa': array([ 0.06099625, -0.01430776, -0.03614592]),
 'hsp': None,
 'hpi': None}

Additional information

Platform Windows-10-10.0.19045-SP0
Python 3.12.2 | packaged by conda-forge | (main, Feb 16 2024, 20:42:31) [MSC v.1937 64 bit (AMD64)]
Executable C:\Users\kdahlslatt\Anaconda3\envs\mne\python.exe
CPU Intel64 Family 6 Model 158 Stepping 10, GenuineIntel (12 cores)
Memory 15.7 GB

Core
├☑ mne 1.6.1 (latest release)
├☑ numpy 1.26.4 (OpenBLAS 0.3.26 with 12 threads)
├☑ scipy 1.12.0
├☑ matplotlib 3.8.3 (backend=Qt5Agg)
├☑ pooch 1.8.1
└☑ jinja2 3.1.3

Numerical (optional)
├☑ sklearn 1.4.1.post1
├☑ numba 0.59.1
├☑ nibabel 5.2.1
├☑ nilearn 0.10.3
├☑ dipy 1.9.0
├☑ openmeeg 2.5.7
├☑ pandas 2.2.1
└☐ unavailable cupy

Visualization (optional)
├☑ pyvista 0.43.4 (OpenGL 4.5.0 - Build 30.0.101.1404 via Intel(R) UHD Graphics 630)
├☑ pyvistaqt 0.11.0
├☑ vtk 9.2.6
├☑ qtpy 2.4.1 (PyQt5=5.15.8)
├☑ pyqtgraph 0.13.4
├☑ mne-qt-browser 0.6.2
├☑ ipywidgets 8.1.2
├☑ trame_client 2.16.5
├☑ trame_server 2.17.2
├☑ trame_vtk 2.8.5
├☑ trame_vuetify 2.4.3
└☐ unavailable ipympl

Ecosystem (optional)
├☑ mne-nirs 0.6.0
└☐ unavailable mne-bids, mne-features, mne-connectivity, mne-icalabel, mne-bids-pipeline

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions