diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f6421a4f..1caa22a7 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -9,7 +9,7 @@ trigger: jobs: - job: Windows pool: - vmIMage: 'VS2017-Win2016' + vmIMage: 'windows-latest' variables: MNE_LOGGING_LEVEL: 'warning' MNE_FORCE_SERIAL: 'true' @@ -34,16 +34,19 @@ jobs: $PSDefaultParameterValues['*:ErrorAction']='Stop' pip install --upgrade --pre numpy scipy matplotlib pip install https://api.github.com/repos/mne-tools/mne-python/zipball/main - pip install --upgrade -r requirements.txt - pip install codecov pylsl + pip install --upgrade -r requirements.txt -r requirements_testing.txt codecov displayName: 'Install dependencies with pip' - script: python setup.py develop - displayName: 'Install MNE-Realtime' + displayName: 'Install MNE-Connectivity' + - bash: | + set -e + git clone --depth 1 git://github.com/pyvista/gl-ci-helpers.git + powershell gl-ci-helpers/appveyor/install_opengl.ps1 - script: python -c "import mne; print(mne.sys_info())" displayName: 'Print config' - script: python -c "import mne; mne.datasets.testing.data_path(verbose=True)" displayName: 'Get test data' - - script: pytest mne_realtime + - script: pytest mne_connectivity displayName: 'Run tests' - script: codecov --root %BUILD_REPOSITORY_LOCALPATH% -t %CODECOV_TOKEN% displayName: 'Codecov' diff --git a/mne_connectivity/conftest.py b/mne_connectivity/conftest.py index 2dd5e3d5..b575c387 100644 --- a/mne_connectivity/conftest.py +++ b/mne_connectivity/conftest.py @@ -24,6 +24,7 @@ def pytest_configure(config): ignore:.*SelectableGroups dict interface is deprecated.*:DeprecationWarning ignore:.*Converting `np.character` to a dtype is deprecated.*:DeprecationWarning ignore:.*distutils Version classes are deprecated.*:DeprecationWarning + ignore:.*`np.MachAr` is deprecated.*:DeprecationWarning # for the persistence of metadata and Raw Annotations within mne-python # Epochs class ignore:.*There were no Annotations stored in.*:RuntimeWarning diff --git a/mne_connectivity/spectral/smooth.py b/mne_connectivity/spectral/smooth.py index cb13f3b2..fac5121b 100644 --- a/mne_connectivity/spectral/smooth.py +++ b/mne_connectivity/spectral/smooth.py @@ -90,8 +90,9 @@ def _smooth_spectra(spectra, kernel, scale=False, decim=1): Smoothed spectra of shape (..., n_freqs, n_times) """ # fill potentially missing dimensions - while kernel.ndim != spectra.ndim: - kernel = kernel[np.newaxis, ...] + kernel = kernel[ + tuple([np.newaxis] * (spectra.ndim - kernel.ndim)) + (Ellipsis,)] + # smooth the spectra if not scale: axes = (-2, -1) diff --git a/mne_connectivity/spectral/time.py b/mne_connectivity/spectral/time.py index 33dc4b37..4e90976a 100644 --- a/mne_connectivity/spectral/time.py +++ b/mne_connectivity/spectral/time.py @@ -53,14 +53,14 @@ def spectral_connectivity_time(data, names=None, method='coh', indices=None, Extract frequencies of interest. This parameters should be an array of shapes (n_foi, 2) defining where each band of interest start and finish. - sm_times : float | .5 - Number of points to consider for the temporal smoothing in seconds. By - default, a 500ms smoothing is used. - sm_freqs : int | 1 + sm_times : float + Amount of time to consider for the temporal smoothing in seconds. By + default, 0.5 sec smoothing is used. + sm_freqs : int Number of points for frequency smoothing. By default, 1 is used which - is equivalent to no smoothing - kernel : {'square', 'hanning'} - Kernel type to use. Choose either 'square' or 'hanning' + is equivalent to no smoothing. + sm_kernel : {'square', 'hanning'} + Kernel type to use. Choose either 'square' or 'hanning' (default). mode : str, optional Spectrum estimation mode can be either: 'multitaper', or 'cwt_morlet'. @@ -239,6 +239,7 @@ def _spectral_connectivity(data, method, kernel, foi_idx, n_pairs = len(source_idx) # first compute time-frequency decomposition + collapse = None if mode == 'cwt_morlet': out = tfr_array_morlet( data, sfreq, freqs, n_cycles=n_cycles, output='complex', @@ -261,13 +262,24 @@ def _spectral_connectivity(data, method, kernel, foi_idx, data, sfreq, freqs, n_cycles=n_cycles, time_bandwidth=mt_bandwidth, output='complex', decim=decim, n_jobs=n_jobs, **kw_mt) + collapse = True + if out.ndim == 5: # newest MNE-Python + collapse = -3 # get the supported connectivity function conn_func = {'coh': _coh, 'plv': _plv, 'sxy': _cs}[method] # computes conn across trials + # TODO: This is wrong -- it averages in the complex domain (over tapers). + # What it *should* do is compute the conn for each taper, then average + # (see below). + if collapse is not None: + out = np.mean(out, axis=collapse) this_conn = conn_func(out, kernel, foi_idx, source_idx, target_idx, n_jobs=n_jobs, verbose=verbose, total=n_pairs) + # This is where it should go, but the regression test fails... + # if collapse is not None: + # this_conn = [c.mean(axis=collapse) for c in this_conn] return this_conn @@ -288,10 +300,10 @@ def _coh(w, kernel, foi_idx, source_idx, target_idx, n_jobs, verbose, total): # define the pairwise coherence def pairwise_coh(w_x, w_y): # computes the coherence - s_xy = w[:, w_y, :, :] * np.conj(w[:, w_x, :, :]) + s_xy = w[:, w_y] * np.conj(w[:, w_x]) s_xy = _smooth_spectra(s_xy, kernel) - s_xx = s_auto[:, w_x, :, :] - s_yy = s_auto[:, w_y, :, :] + s_xx = s_auto[:, w_x] + s_yy = s_auto[:, w_y] out = np.abs(s_xy) ** 2 / (s_xx * s_yy) # mean inside frequency sliding window (if needed) if isinstance(foi_idx, np.ndarray): @@ -312,7 +324,7 @@ def _plv(w, kernel, foi_idx, source_idx, target_idx, n_jobs, verbose, total): # define the pairwise plv def pairwise_plv(w_x, w_y): # computes the plv - s_xy = w[:, w_y, :, :] * np.conj(w[:, w_x, :, :]) + s_xy = w[:, w_y] * np.conj(w[:, w_x]) # complex exponential of phase differences exp_dphi = s_xy / np.abs(s_xy) # smooth e^(-i*\delta\phi) @@ -338,7 +350,7 @@ def _cs(w, kernel, foi_idx, source_idx, target_idx, n_jobs, verbose, total): # define the pairwise cross-spectra def pairwise_cs(w_x, w_y): # computes the cross-spectra - out = w[:, w_x, :, :] * np.conj(w[:, w_y, :, :]) + out = w[:, w_x] * np.conj(w[:, w_y]) out = _smooth_spectra(out, kernel) if foi_idx is not None: return _foi_average(out, foi_idx)