Skip to content

Commit

Permalink
ENH: Add option to not orthogonalize power envelopes
Browse files Browse the repository at this point in the history
  • Loading branch information
dengemann authored and larsoner committed Jul 22, 2019
1 parent 40f1f5e commit 6a65caa
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 13 deletions.
37 changes: 24 additions & 13 deletions mne/connectivity/envelope.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@


@verbose
def envelope_correlation(data, combine='mean', verbose=None):
def envelope_correlation(data, combine='mean', orthogonalize="pairwise",
verbose=None):
"""Compute the envelope correlation.
Parameters
----------
data : array-like, shape=(n_epochs, n_signals, n_times) | generator
Expand All @@ -24,15 +24,19 @@ def envelope_correlation(data, combine='mean', verbose=None):
object (and ``stc.data`` will be used). If it's float data,
the Hilbert transform will be applied; if it's complex data,
it's assumed the Hilbert has already been applied.
combine : 'mean' | callable | None
combine : 'mean' | callable | None
How to combine correlation estimates across epochs.
Default is 'mean'. Can be None to return without combining.
If callable, it must accept one positional input.
For example::
combine = lambda data: np.median(data, axis=0)
%(verbose)s
orthogonalize : 'pairwise' | False
Whether to orthogonalize with the pairwise method or not.
Defaults to 'pairwise'. Note that when False,
the correlation matrix will not be returned with
absolute values.
%(verbose)s
Returns
-------
corr : ndarray, shape ([n_epochs, ]n_nodes, n_nodes)
Expand Down Expand Up @@ -82,6 +86,7 @@ def envelope_correlation(data, combine='mean', verbose=None):
if epoch_data.dtype in (np.float32, np.float64):
n_fft = next_fast_len(n_times)
epoch_data = hilbert(epoch_data, N=n_fft, axis=-1)[..., :n_times]

if epoch_data.dtype not in (np.complex64, np.complex128):
raise ValueError('data.dtype must be float or complex, got %s'
% (epoch_data.dtype,))
Expand All @@ -95,18 +100,24 @@ def envelope_correlation(data, combine='mean', verbose=None):
data_mag_std[data_mag_std == 0] = 1
corr = np.empty((n_nodes, n_nodes))
for li, label_data in enumerate(epoch_data):
label_data_orth = (label_data * data_conj_scaled).imag
label_data_orth -= np.mean(label_data_orth, axis=-1, keepdims=True)
label_data_orth_std = np.linalg.norm(label_data_orth, axis=-1)
label_data_orth_std[label_data_orth_std == 0] = 1
if orthogonalize is False: # the new code
label_data_orth = label_data
label_data_orth_std = data_mag_std[li]
else:
label_data_orth = (label_data * data_conj_scaled).imag
label_data_orth -= np.mean(label_data_orth, axis=-1,
keepdims=True)
label_data_orth_std = np.linalg.norm(label_data_orth, axis=-1)
label_data_orth_std[label_data_orth_std == 0] = 1
# correlation is dot product divided by variances
corr[li] = np.dot(label_data_orth, data_mag_nomean[li])
corr[li] /= data_mag_std[li]
corr[li] /= label_data_orth_std
# Make it symmetric (it isn't at this point)
corr = np.abs(corr)
corrs.append((corr.T + corr) / 2.)
del corr
if orthogonalize is not False:
# Make it symmetric (it isn't at this point)
corr = np.abs(corr)
corrs.append((corr.T + corr) / 2.)
del corr

corr = fun(corrs)
return corr
5 changes: 5 additions & 0 deletions mne/connectivity/tests/test_envelope.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,8 @@ def test_envelope_correlation():
envelope_correlation(data, 1.)
with pytest.raises(ValueError, match='Combine option'):
envelope_correlation(data, 'foo')

corr_plain = envelope_correlation(data, combine=None, orthogonalize=False)
assert np.min(corr_plain) < 0
assert len(np.unique(np.diag(corr_plain))) == 1
assert np.unique(np.diag(corr_plain))[0] == 1.

0 comments on commit 6a65caa

Please sign in to comment.