Skip to content

Commit

Permalink
#11608, buggfix and docstring update (#12066)
Browse files Browse the repository at this point in the history
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Eric Larson <larson.eric.d@gmail.com>
Co-authored-by: Daniel McCloy <dan@mccloy.info>
  • Loading branch information
4 people authored Oct 5, 2023
1 parent 5a83eae commit 27d1c59
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 19 deletions.
1 change: 1 addition & 0 deletions doc/changes/devel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Bugs
- Fix bugs with :func:`mne.preprocessing.realign_raw` where the start of ``other`` was incorrectly cropped; and onsets and durations in ``other.annotations`` were left unsynced with the resampled data (:gh:`11950` by :newcontrib:`Qian Chu`)
- Fix bug where ``encoding`` argument was ignored when reading annotations from an EDF file (:gh:`11958` by :newcontrib:`Andrew Gilbert`)
- Mark tests ``test_adjacency_matches_ft`` and ``test_fetch_uncompressed_file`` as network tests (:gh:`12041` by :newcontrib:`Maksym Balatsko`)
- Fix bug with :func:`mne.channels.read_ch_adjacency` (:gh:`11608` by :newcontrib:`Ivan Zubarev`)
- Fix bugs with saving splits for :class:`~mne.Epochs` (:gh:`11876` by `Dmitrii Altukhov`_)
- Fix bug with multi-plot 3D rendering where only one plot was updated (:gh:`11896` by `Eric Larson`_)
- Fix bug where subject birthdays were not correctly read by :func:`mne.io.read_raw_snirf` (:gh:`11912` by `Eric Larson`_)
Expand Down
12 changes: 3 additions & 9 deletions mne/channels/channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -1340,8 +1340,7 @@ def read_ch_adjacency(fname, picks=None):
You can retrieve the names of all
built-in channel adjacencies via
:func:`mne.channels.get_builtin_ch_adjacencies`.
%(picks_all)s
Picks must match the template.
%(picks_all_notypes)s
Returns
-------
Expand Down Expand Up @@ -1401,20 +1400,15 @@ def read_ch_adjacency(fname, picks=None):

nb = loadmat(fname)["neighbours"]
ch_names = _recursive_flatten(nb["label"], str)
picks = _picks_to_idx(len(ch_names), picks)
temp_info = create_info(ch_names, 1.0)
picks = _picks_to_idx(temp_info, picks, none="all")
neighbors = [_recursive_flatten(c, str) for c in nb["neighblabel"].flatten()]
assert len(ch_names) == len(neighbors)
adjacency = _ch_neighbor_adjacency(ch_names, neighbors)
# picking before constructing matrix is buggy
adjacency = adjacency[picks][:, picks]
ch_names = [ch_names[p] for p in picks]

# make sure MEG channel names contain space after "MEG"
for idx, ch_name in enumerate(ch_names):
if ch_name.startswith("MEG") and not ch_name[3] == " ":
ch_name = ch_name.replace("MEG", "MEG ")
ch_names[idx] = ch_name

return adjacency, ch_names


Expand Down
25 changes: 20 additions & 5 deletions mne/channels/tests/test_channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,25 @@ def test_get_builtin_ch_adjacencies():
assert len(name_and_description) == 2


@pytest.mark.parametrize("name", get_builtin_ch_adjacencies())
@pytest.mark.parametrize("picks", ["pick-slice", "pick-arange", "pick-names"])
def test_read_builtin_ch_adjacency_picks(name, picks):
"""Test picking channel subsets when reading builtin adjacency matrices."""
ch_adjacency, ch_names = read_ch_adjacency(name)
assert_equal(ch_adjacency.shape[0], len(ch_names))
subset_names = ch_names[::2]
if picks == "pick-slice":
subset = slice(None, None, 2)
elif picks == "pick-arange":
subset = np.arange(0, len(ch_names), 2)
else:
assert picks == "pick-names"
subset = subset_names

ch_subset_adjacency, ch_subset_names = read_ch_adjacency(name, subset)
assert_array_equal(ch_subset_names, subset_names)


def test_read_ch_adjacency(tmp_path):
"""Test reading channel adjacency templates."""
a = partial(np.array, dtype="<U7")
Expand All @@ -262,6 +281,7 @@ def test_read_ch_adjacency(tmp_path):
savemat(mat_fname, mat, oned_as="row")

ch_adjacency, ch_names = read_ch_adjacency(mat_fname)

x = ch_adjacency
assert_equal(x.shape[0], len(ch_names))
assert_equal(x.shape, (3, 3))
Expand Down Expand Up @@ -328,11 +348,6 @@ def test_read_ch_adjacency(tmp_path):
savemat(mat_fname, mat, oned_as="row")
pytest.raises(ValueError, read_ch_adjacency, mat_fname)

# Try reading all built-in FieldTrip neighbors
for name in get_builtin_ch_adjacencies():
ch_adjacency, ch_names = read_ch_adjacency(name)
assert_equal(ch_adjacency.shape[0], len(ch_names))


def _download_ft_neighbors(target_dir):
"""Download the known neighbors from FieldTrip."""
Expand Down
20 changes: 15 additions & 5 deletions mne/utils/docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3358,11 +3358,16 @@ def _reflow_param_docstring(docstring, has_first_line=True, width=75):
_picks_header = f"picks : {_picks_types}"
_picks_desc = "Channels to include."
_picks_int = "Slices and lists of integers will be interpreted as channel " "indices."
_picks_str = """In lists, channel *type* strings
(e.g., ``['meg', 'eeg']``) will pick channels of those
types, channel *name* strings (e.g., ``['MEG0111', 'MEG2623']``
will pick the given channels. Can also be the string values
"all" to pick all channels, or "data" to pick :term:`data channels`.
_picks_str_types = """channel *type* strings (e.g., ``['meg', 'eeg']``) will
pick channels of those types,"""
_picks_str_names = """channel *name* strings (e.g., ``['MEG0111', 'MEG2623']``
will pick the given channels."""
_picks_str_values = """Can also be the string values "all" to pick
all channels, or "data" to pick :term:`data channels`."""
_picks_str = f"""In lists, {_picks_str_types} {_picks_str_names}
{_picks_str_values}
None (default) will pick"""
_picks_str_notypes = f"""In lists, {_picks_str_names}
None (default) will pick"""
_reminder = (
"Note that channels in ``info['bads']`` *will be included* if "
Expand All @@ -3373,13 +3378,18 @@ def _reflow_param_docstring(docstring, has_first_line=True, width=75):
noref = f"(excluding reference MEG channels). {reminder}"
picks_base = f"""{_picks_header}
{_picks_desc} {_picks_int} {_picks_str}"""
picks_base_notypes = f"""picks : list of int | list of str | slice | None
{_picks_desc} {_picks_int} {_picks_str_notypes}"""
docdict["picks_all"] = _reflow_param_docstring(f"{picks_base} all channels. {reminder}")
docdict["picks_all_data"] = _reflow_param_docstring(
f"{picks_base} all data channels. {reminder}"
)
docdict["picks_all_data_noref"] = _reflow_param_docstring(
f"{picks_base} all data channels {noref}"
)
docdict["picks_all_notypes"] = _reflow_param_docstring(
f"{picks_base_notypes} all channels. {reminder}"
)
docdict["picks_base"] = _reflow_param_docstring(picks_base)
docdict["picks_good_data"] = _reflow_param_docstring(
f"{picks_base} good data channels. {reminder}"
Expand Down

0 comments on commit 27d1c59

Please sign in to comment.