Skip to content
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

[ENH, MRG] Simplify reading dig #979

Merged
merged 3 commits into from
Mar 7, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/whats_new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ Enhancements

- :func:`mne_bids.update_anat_landmarks` can now directly work with fiducials saved from the MNE-Python coregistration GUI or :func:`mne.io.write_fiducials`, by Richard Höchenberger`_ (:gh:`977`)

- Add message about non-MNE-Python supported coordinate frames being set to 'unknown' when being read in, by `Alex Rockhill`_ (:gh:`979`)
hoechenberger marked this conversation as resolved.
Show resolved Hide resolved

API and behavior changes
^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
41 changes: 19 additions & 22 deletions mne_bids/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,18 +205,27 @@
'UNCInfant2V23',
]

coordsys_meg = ['CTF', 'ElektaNeuromag', '4DBti', 'KitYokogawa', 'ChietiItab']
coordsys_eeg = ['CapTrak']
coordsys_ieeg = ['Pixels', 'ACPC']
# accepted BIDS formats, which may be subject to change
# depending on the specification
BIDS_IEEG_COORDINATE_FRAMES = ['ACPC', 'Pixels']
BIDS_MEG_COORDINATE_FRAMES = ['CTF', 'ElektaNeuromag',
'4DBti', 'KitYokogawa',
'ChietiItab']
BIDS_EEG_COORDINATE_FRAMES = ['CapTrak']

# accepted coordinate SI units
BIDS_COORDINATE_UNITS = ['m', 'cm', 'mm']
coordsys_wildcard = ['Other']
coordsys_shared = (coordsys_standard_template +
coordsys_standard_template_deprecated +
coordsys_wildcard)
BIDS_SHARED_COORDINATE_FRAMES = (coordsys_standard_template +
coordsys_standard_template_deprecated +
coordsys_wildcard)

ALLOWED_SPACES = dict()
ALLOWED_SPACES['meg'] = coordsys_shared + coordsys_meg + coordsys_eeg
ALLOWED_SPACES['eeg'] = coordsys_shared + coordsys_meg + coordsys_eeg
ALLOWED_SPACES['ieeg'] = coordsys_shared + coordsys_ieeg
ALLOWED_SPACES['meg'] = ALLOWED_SPACES['eeg'] = \
BIDS_SHARED_COORDINATE_FRAMES + BIDS_MEG_COORDINATE_FRAMES + \
BIDS_EEG_COORDINATE_FRAMES
ALLOWED_SPACES['ieeg'] = \
BIDS_SHARED_COORDINATE_FRAMES + BIDS_IEEG_COORDINATE_FRAMES
ALLOWED_SPACES['anat'] = None
ALLOWED_SPACES['beh'] = None

Expand All @@ -235,17 +244,6 @@
'extension': 'label'
}

# accepted BIDS formats, which may be subject to change
# depending on the specification
BIDS_IEEG_COORDINATE_FRAMES = ['ACPC', 'Pixels', 'Other']
BIDS_MEG_COORDINATE_FRAMES = ['CTF', 'ElektaNeuromag',
'4DBti', 'KitYokogawa',
'ChietiItab', 'Other']
BIDS_EEG_COORDINATE_FRAMES = ['CapTrak']

# accepted coordinate SI units
BIDS_COORDINATE_UNITS = ['m', 'cm', 'mm']

# mapping from supported BIDs coordinate frames -> MNE
BIDS_TO_MNE_FRAMES = {
'CTF': 'ctf_head',
Expand All @@ -256,8 +254,7 @@
'CapTrak': 'head',
'ACPC': 'mri', # assumes T1 is ACPC-aligned, if not the coordinates are lost # noqa
'fsaverage': 'mni_tal', # XXX: note fsaverage and MNI305 are the same # noqa
'MNI305': 'mni_tal',
'Other': 'unknown'
'MNI305': 'mni_tal'
}

# mapping from supported MNE coordinate frames -> BIDS
Expand Down
66 changes: 12 additions & 54 deletions mne_bids/dig.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
from mne.utils import logger, warn
from mne.io.pick import _picks_to_idx

from mne_bids.config import (BIDS_IEEG_COORDINATE_FRAMES,
BIDS_MEG_COORDINATE_FRAMES,
BIDS_EEG_COORDINATE_FRAMES,
from mne_bids.config import (ALLOWED_SPACES,
BIDS_COORDINATE_UNITS,
MNE_TO_BIDS_FRAMES, BIDS_TO_MNE_FRAMES,
MNE_FRAME_TO_STR, BIDS_COORD_FRAME_DESCRIPTIONS)
Expand Down Expand Up @@ -535,57 +533,17 @@ def _read_dig_bids(electrodes_fpath, coordsystem_fpath,
bids_coord_frame, bids_coord_unit = _handle_coordsystem_reading(
coordsystem_fpath, datatype)

if datatype == 'meg':
if bids_coord_frame not in BIDS_MEG_COORDINATE_FRAMES:
warn(f'MEG coordinate frame "{bids_coord_frame}" is not '
f'supported. The supported coordinate frames are: '
f'{BIDS_MEG_COORDINATE_FRAMES}')
coord_frame = None
elif bids_coord_frame == 'Other':
warn("Coordinate frame of MEG data can't be determined "
"when 'other'. The currently accepted keywords are: "
"{}".format(BIDS_MEG_COORDINATE_FRAMES))
coord_frame = None
else:
coord_frame = BIDS_TO_MNE_FRAMES.get(bids_coord_frame, None)
elif datatype == 'ieeg':
# iEEG datatype for BIDS only supports
# acpc, pixels and then standard templates
# iEEG datatype for mne-python only supports
# mni_tal == fsaverage == MNI305
if bids_coord_frame == 'Pixels':
warn("Coordinate frame of iEEG data in pixels is not "
"recognized by mne-python, the coordinate frame "
"of the montage will be set to 'unknown'")
coord_frame = 'unknown'
elif bids_coord_frame == 'ACPC':
coord_frame = BIDS_TO_MNE_FRAMES.get(bids_coord_frame, None)
elif bids_coord_frame == 'Other':
# default coordinate frames to available ones in mne-python
# noqa: see https://bids-specification.readthedocs.io/en/stable/99-appendices/08-coordinate-systems.html
warn(f"Defaulting coordinate frame to unknown "
f"from coordinate system input {bids_coord_frame}")
coord_frame = BIDS_TO_MNE_FRAMES.get(bids_coord_frame, None)
else:
coord_frame = BIDS_TO_MNE_FRAMES.get(bids_coord_frame, None)

# XXX: if the coordinate frame is not recognized, then
# coordinates are stored in a system that we cannot
# recognize yet.
if coord_frame is None:
warn(f"iEEG Coordinate frame {bids_coord_frame} is not a "
f"readable BIDS keyword by mne-bids yet. The allowed "
f"keywords are: {BIDS_IEEG_COORDINATE_FRAMES}")
coord_frame = 'unknown'
elif datatype == 'eeg':
# only accept captrak
if bids_coord_frame not in BIDS_EEG_COORDINATE_FRAMES:
warn("EEG Coordinate frame is not accepted "
"BIDS keyword. The allowed keywords are: "
"{}".format(BIDS_IEEG_COORDINATE_FRAMES))
coord_frame = None
else:
coord_frame = BIDS_TO_MNE_FRAMES.get(bids_coord_frame, None)
if bids_coord_frame not in ALLOWED_SPACES[datatype]:
warn(f'"{bids_coord_frame}" is not a BIDS-acceptable coordinate frame '
f'for {datatype.upper()}. The supported coordinate frames are: '
'{}'.format(ALLOWED_SPACES[datatype]))
coord_frame = None
elif bids_coord_frame in BIDS_TO_MNE_FRAMES:
coord_frame = BIDS_TO_MNE_FRAMES.get(bids_coord_frame, None)
else:
warn(f"{bids_coord_frame} is not an MNE-Python coordinate frame "
f"for {datatype.upper()} data and so will be set to 'unknown'")
coord_frame = 'unknown'

# check coordinate units
if bids_coord_unit not in BIDS_COORDINATE_UNITS:
Expand Down
25 changes: 13 additions & 12 deletions mne_bids/tests/test_read.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
from mne.datasets import testing, somato

from mne_bids import BIDSPath
from mne_bids.config import MNE_STR_TO_FRAME
from mne_bids.config import (MNE_STR_TO_FRAME, BIDS_SHARED_COORDINATE_FRAMES,
BIDS_TO_MNE_FRAMES)
from mne_bids.read import (read_raw_bids,
_read_raw, get_head_mri_trans,
_handle_events_reading)
Expand Down Expand Up @@ -733,8 +734,8 @@ def test_handle_eeg_coords_reading(tmp_path):
suffix='coordsystem',
extension='.json')
_update_sidecar(coordsystem_fname, 'EEGCoordinateSystem', 'besa')
with pytest.warns(RuntimeWarning, match='EEG Coordinate frame is not '
'accepted BIDS keyword'):
with pytest.warns(RuntimeWarning, match='is not a BIDS-acceptable '
'coordinate frame for EEG'):
raw_test = read_raw_bids(bids_path)
assert raw_test.info['dig'] is None

Expand Down Expand Up @@ -842,25 +843,25 @@ def test_handle_ieeg_coords_reading(bids_path, tmp_path):
_update_sidecar(coordsystem_fname, 'iEEGCoordinateSystem', coord_frame)
# read in raw file w/ updated coordinate frame
# and make sure all digpoints are MRI coordinate frame
with pytest.warns(RuntimeWarning, match="Defaulting coordinate "
"frame to unknown"):
with pytest.warns(RuntimeWarning, match="not an MNE-Python "
"coordinate frame"):
raw_test = read_raw_bids(bids_path=bids_fname, verbose=False)
assert raw_test.info['dig'] is not None

# check that standard template identifiers that are unsupported in
# mne-python coordinate frames, still get read in, but produce a warning
coordinate_frames = ['individual', 'fsnative', 'scanner',
'ICBM452AirSpace', 'NIHPD']
for coord_frame in coordinate_frames:
for coord_frame in BIDS_SHARED_COORDINATE_FRAMES:
# update coordinate units
_update_sidecar(coordsystem_fname, 'iEEGCoordinateSystem', coord_frame)
# read in raw file w/ updated coordinate frame
# and make sure all digpoints are MRI coordinate frame
with pytest.warns(
RuntimeWarning, match=f"iEEG Coordinate frame {coord_frame} "
f"is not a readable BIDS keyword "):
if coord_frame in BIDS_TO_MNE_FRAMES:
raw_test = read_raw_bids(bids_path=bids_fname, verbose=False)
assert raw_test.info['dig'] is not None
else:
with pytest.warns(RuntimeWarning, match="not an MNE-Python "
"coordinate frame"):
raw_test = read_raw_bids(bids_path=bids_fname, verbose=False)
assert raw_test.info['dig'] is not None

# ACPC should be read in as RAS for iEEG
_update_sidecar(coordsystem_fname, 'iEEGCoordinateSystem', 'ACPC')
Expand Down
2 changes: 1 addition & 1 deletion mne_bids/tests/test_write.py
Original file line number Diff line number Diff line change
Expand Up @@ -3642,7 +3642,7 @@ def test_write_dig(tmpdir):
coordsystem_path = bids_path.copy().update(
task=None, run=None, suffix='coordsystem', extension='.json')
with pytest.warns(RuntimeWarning,
match='recognized by mne-python'):
match='not an MNE-Python coordinate frame'):
_read_dig_bids(electrodes_path, coordsystem_path,
bids_path.datatype, raw)
montage2 = raw.get_montage()
Expand Down