Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions mne/stats/_adjacency.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,37 @@ def combine_adjacency(*structure):
-------
adjacency : scipy.sparse.coo_matrix, shape (n_features, n_features)
The adjacency matrix.

Notes
-----
For 4-dimensional data with shape ``(n_obs, n_times, n_freqs, n_chans)``,
you can specify **no** connections among elements in a particular
dimension by passing a matrix of zeros. For example:

>>> import numpy as np
>>> from scipy.sparse import diags
>>> from mne.stats import combine_adjacency
>>> n_times, n_freqs, n_chans = (50, 7, 16)
>>> chan_adj = diags([1., 1.], offsets=(-1, 1), shape=(n_chans, n_chans))
>>> combine_adjacency(
... n_times, # regular lattice adjacency for times
... np.zeros((n_freqs, n_freqs)), # no adjacency between freq. bins
... chan_adj, # custom matrix, or use mne.channels.find_ch_adjacency
... ) # doctest: +NORMALIZE_WHITESPACE
<5600x5600 sparse matrix of type '<class 'numpy.float64'>'
with 27076 stored elements in COOrdinate format>
"""
from scipy import sparse
structure = list(structure)
for di, dim in enumerate(structure):
name = f'structure[{di}]'
_validate_type(dim, ('int-like', np.ndarray, sparse.spmatrix), name)
if isinstance(dim, int_like):
dim = int(dim)
# Don't add the diagonal, because we explicitly remove it later:
# dim = sparse.eye(dim, format='coo')
# dim += sparse.eye(dim.shape[0], k=1, format='coo')
# dim += sparse.eye(dim.shape[0], k=-1, format='coo')
ii, jj = np.arange(0, dim - 1), np.arange(1, dim)
edges = np.vstack([np.hstack([ii, jj]), np.hstack([jj, ii])])
dim = sparse.coo_matrix(
(np.ones(edges.shape[1]), edges), (dim, dim), float)
# Don't add the diagonal, because we explicitly remove it later
dim = sparse.diags([1, 1],
offsets=(-1, 1),
shape=(int(dim), int(dim)),
dtype=float).tocoo()
else:
_check_option(f'{name}.ndim', dim.ndim, [2])
if dim.shape[0] != dim.shape[1]:
Expand Down
5 changes: 3 additions & 2 deletions mne/utils/docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -1782,7 +1782,7 @@
stat_fun : callable | None
Function called to calculate the test statistic. Must accept 1D-array as
input and return a 1D array. If ``None`` (the default), uses
:func:`mne.stats.{}`.
`mne.stats.{}`.
"""
docdict['clust_stat_f'] = docdict['clust_stat'].format('f_oneway')
docdict['clust_stat_t'] = docdict['clust_stat'].format('ttest_1samp_no_p')
Expand All @@ -1803,10 +1803,11 @@
'a square matrix with dimension ``{x}.shape[-1]`` (n_vertices) to save '
'memory and computation, and to use ``max_step`` to define the extent '
'of temporal adjacency to consider when clustering.')
comb = ' The function `mne.stats.combine_adjacency` may be useful for 4D data.'
st = dict(sp='spatial', lastdim='', parone='(n_vertices)',
partwo='(n_times * n_vertices)', memory=mem)
tf = dict(sp='', lastdim=' (or the last two dimensions if ``{x}`` is 2D)',
parone='', partwo='', memory='')
parone='(for 3D data)', partwo='(for 4D data)', memory=comb)
nogroups = dict(eachgrp='', x='X')
groups = dict(eachgrp='each group ', x='X[k]')
docdict['clust_adj_st1'] = docdict['clust_adj'].format(**st).format(**nogroups)
Expand Down