Skip to content

Commit

Permalink
MAINT: Updates for latest MNE (#1312)
Browse files Browse the repository at this point in the history
* MAINT: Updates for latest MNE

* FIX: Unify

* FIX: Comment

* TST: Ping

* FIX: What

* FIX: More

* FIX: Suffix
  • Loading branch information
larsoner authored Oct 1, 2024
1 parent 9575eab commit c18e45f
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 23 deletions.
60 changes: 47 additions & 13 deletions mne_bids/read.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import os
import os.path as op
import re
from datetime import datetime, timezone
from datetime import datetime, timedelta, timezone
from difflib import get_close_matches
from pathlib import Path

Expand Down Expand Up @@ -260,38 +260,72 @@ def _handle_participants_reading(participants_fname, raw, subject):
raw.info["subject_info"] = dict() # start from scratch

# set data from participants tsv into subject_info
# TODO: Could potentially use "comment" someday to store other options e.g. in JSON
# https://github.com/mne-tools/fiff-constants/blob/e27f68cbf74dbfc5193ad429cc77900a59475181/DictionaryTags.txt#L369
allowed_keys = set(
"""
id his_id last_name first_name middle_name birthday sex hand weight height
""".strip().split()
)
bad_key_vals = list()
for col_name, value in participants_tsv.items():
orig_value = value = value[row_ind]
if col_name in ("sex", "hand"):
value = _map_options(
what=col_name, key=value[row_ind], fro="bids", to="mne"
)
value = _map_options(what=col_name, key=value, fro="bids", to="mne")
# We don't know how to translate to MNE, so skip.
if value is None:
if col_name == "sex":
info_str = "subject sex"
else:
info_str = "subject handedness"
warn(
f'Unable to map "{col_name}" value "{value}" to MNE. '
f"Not setting {info_str}."
)
bad_key_vals.append((col_name, orig_value, info_str))
elif col_name in ("height", "weight"):
try:
value = float(value[row_ind])
value = float(value)
except ValueError:
value = None
elif col_name == "age":
if raw.info["meas_date"] is None:
value = None
elif value is not None:
try:
value = float(value)
except Exception:
value = None
else:
value = (
raw.info["meas_date"]
- timedelta(days=int(np.ceil(365.25 * value)))
).date()
else:
if value[row_ind] == "n/a":
if value == "n/a":
value = None
else:
value = value[row_ind]

# adjust keys to match MNE nomenclature
key = col_name
if col_name == "participant_id":
key = "his_id"
elif col_name == "age":
key = "birthday"

if key not in allowed_keys:
bad_key_vals.append((col_name, orig_value, None))
continue

# add data into raw.Info
key = "his_id" if col_name == "participant_id" else col_name
if value is not None:
assert key not in raw.info["subject_info"]
raw.info["subject_info"][key] = value

if bad_key_vals:
warn_str = "Unable to map the following column(s) to to MNE:"
for col_name, orig_value, info_str in bad_key_vals:
warn_str += f"\n{col_name}"
if info_str is not None:
warn_str += f" ({info_str})"
warn_str += f": {orig_value}"
warn(warn_str)

return raw


Expand Down
2 changes: 1 addition & 1 deletion mne_bids/tests/test_copyfiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def test_copyfile_brainvision(tmp_path):

# Try to read with MNE - if this works, the links are correct
raw = mne.io.read_raw_brainvision(new_name)
assert raw.filenames[0] == (op.join(head, "tested_conversion.eeg"))
assert Path(raw.filenames[0]) == Path(head) / "tested_conversion.eeg"

# Test with anonymization
raw = mne.io.read_raw_brainvision(raw_fname)
Expand Down
5 changes: 4 additions & 1 deletion mne_bids/tests/test_read.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,10 @@ def test_read_participants_data(tmp_path):
participants_tsv_fpath = tmp_path / "participants.tsv"
participants_tsv = _from_tsv(participants_tsv_fpath)
participants_tsv["hand"][0] = "n/a"
participants_tsv["outcome"] = ["good"] # e.g. clinical tutorial from MNE-Python
_to_tsv(participants_tsv, participants_tsv_fpath)
raw = read_raw_bids(bids_path=bids_path)
with pytest.warns(RuntimeWarning, match="Unable to map"):
raw = read_raw_bids(bids_path=bids_path)
assert raw.info["subject_info"]["hand"] == 0
assert raw.info["subject_info"]["sex"] == 2
assert raw.info["subject_info"]["weight"] == 70.5
Expand All @@ -163,6 +165,7 @@ def test_read_participants_data(tmp_path):
# 'n/a' values should get omitted
participants_tsv["weight"] = ["n/a"]
participants_tsv["height"] = ["tall"]
del participants_tsv["outcome"]

_to_tsv(participants_tsv, participants_tsv_fpath)
with pytest.warns(RuntimeWarning, match="Unable to map"):
Expand Down
16 changes: 8 additions & 8 deletions mne_bids/tests/test_write.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,15 @@
cnt_warning2="ignore:.*Could not define the number of bytes automatically."
" Defaulting to 2.",
cnt_warning3="ignore:.*Coordinate frame could not be inferred.*",
no_hand="ignore:.*Not setting subject handedness.:RuntimeWarning:mne",
no_hand=r"ignore:Unable to map.*\n.*subject handedness.*:RuntimeWarning:mne",
no_montage=r"ignore:Not setting position of.*channel found in "
r"montage.*:RuntimeWarning:mne",
)


def _wrap_read_raw(read_raw):
def fn(fname, *args, **kwargs):
if str(fname).endswith(".mff") and check_version("mne", "1.8"):
if Path(fname).suffix == ".mff" and check_version("mne", "1.8"):
kwargs["events_as_annotations"] = True
raw = read_raw(fname, *args, **kwargs)
raw.info["line_freq"] = 60
Expand Down Expand Up @@ -3414,10 +3414,10 @@ def test_convert_eeg_formats(dir_name, fmt, fname, reader, tmp_path):
assert channels_tsv["units"][0] == "V"

if fmt == "BrainVision":
assert raw2.filenames[0].endswith(".eeg")
assert Path(raw2.filenames[0]).suffix == ".eeg"
assert bids_output_path.extension == ".vhdr"
elif fmt == "EDF":
assert raw2.filenames[0].endswith(".edf")
assert Path(raw2.filenames[0]).suffix == ".edf"
assert bids_output_path.extension == ".edf"

orig_len = len(raw)
Expand Down Expand Up @@ -3513,7 +3513,7 @@ def test_convert_meg_formats(dir_name, fmt, fname, reader, tmp_path):
raw2 = read_raw_bids(bids_output_path)

if fmt == "FIF":
assert raw2.filenames[0].endswith(".fif")
assert Path(raw2.filenames[0]).suffix == ".fif"
assert bids_output_path.extension == ".fif"

orig_len = len(raw)
Expand Down Expand Up @@ -4086,16 +4086,16 @@ def test_unknown_extension(_bids_validate, tmp_path):
raw_fname = data_path / "MEG" / "sample" / "sample_audvis_trunc_raw.fif"

raw = _read_raw_fif(raw_fname)
raw._filenames = (raw.filenames[0].replace(".fif", ".foo"),)
raw._filenames = (Path(raw.filenames[0]).with_suffix(".foo"),)

# When data is not preloaded, we should raise an exception.
with pytest.raises(ValueError, match="file format not supported by BIDS"):
write_raw_bids(raw, bids_path)

# With preloaded data, writing should work.
raw._filenames = (raw.filenames[0].replace(".foo", ".fif"),)
raw._filenames = (Path(raw.filenames[0]).with_suffix(".fif"),)
raw.load_data()
raw._filenames = (raw.filenames[0].replace(".fif", ".foo"),)
raw._filenames = (Path(raw.filenames[0]).with_suffix(".foo"),)

write_raw_bids(raw, bids_path, allow_preload=True, format="FIF")
_bids_validate(bids_root)
Expand Down

0 comments on commit c18e45f

Please sign in to comment.