def test_covariances(estimator, rndstate): """Test covariance for multiple estimators""" n_matrices, n_channels, n_times = 2, 3, 100 x = rndstate.randn(n_matrices, n_channels, n_times) if estimator is None: cov = covariances(x) assert cov.shape == (n_matrices, n_channels, n_channels) elif estimator == 'truc': with pytest.raises(ValueError): covariances(x, estimator=estimator) else: cov = covariances(x, estimator=estimator) assert cov.shape == (n_matrices, n_channels, n_channels)
def transform(self, X): """Estimate the hankel covariance matrices. Parameters ---------- X : ndarray, shape (n_trials, n_channels, n_samples) ndarray of trials. Returns ------- covmats : ndarray, shape (n_trials, n_channels, n_channels) ndarray of covariance matrices for each trials. """ if isinstance(self.delays, int): delays = range(1, self.delays) else: delays = self.delays X2 = [] for x in X: tmp = x for d in delays: tmp = numpy.r_[tmp, numpy.roll(x, d, axis=-1)] X2.append(tmp) X2 = numpy.array(X2) covmats = covariances(X2, estimator=self.estimator) return covmats
def test_covariances(): """Test covariance for multiple estimator""" x = np.random.randn(2, 3, 100) cov = covariances(x) cov = covariances(x, estimator='oas') cov = covariances(x, estimator='lwf') cov = covariances(x, estimator='scm') cov = covariances(x, estimator='corr') cov = covariances(x, estimator='mcd') cov = covariances(x, estimator=np.cov) with pytest.raises(ValueError): covariances(x, estimator='truc')
def find_soulmate_iter(population_signals, stranger_signals): dist_dict = {} stranger_covariance = covariances(X=stranger_signals) stranger_reference = mean_covariance(covmats=stranger_covariance, metric='riemann') for subject, subject_signal in population_signals.iteritems(): subject_covariance = covariances(X=subject_signal) subject_reference = mean_covariance(covmats=subject_covariance, metric='riemann') dist_dict[subject] = distance(stranger_reference, subject_reference) sorted_dist_dict = sorted(dist_dict.items(), key=operator.itemgetter(1)) return dict(sorted_dist_dict)
def test_block_covariances(rndstate): """Test block covariance""" n_matrices, n_channels, n_times = 2, 12, 100 x = rndstate.randn(n_matrices, n_channels, n_times) cov = block_covariances(x, [12], estimator='cov') assert_array_almost_equal(cov, covariances(x, estimator='cov')) cov = block_covariances(x, [6, 6], estimator='cov') cov2 = covariances(x, estimator='cov') covcomp = block_diag(*(cov2[0, :6, :6], cov2[0, 6:12, 6:12])) assert_array_almost_equal(cov[0], covcomp) cov = block_covariances(x, [3, 5, 4], estimator='cov') cov2 = covariances(x, estimator='cov') covcomp = block_diag(*(cov2[0, :3, :3], cov2[0, 3:8, 3:8], cov2[0, 8:12, 8:12])) assert_array_almost_equal(cov[0], covcomp)
def transform(self, X): """Clean signal Parameters ---------- X : ndarray, shape (n_trials, n_samples, n_channels) Data to clean, already filtered Returns ------- Xclean : ndarray, shape (n_trials, n_samples, n_channels) Cleaned data """ check_is_fitted(self, ['Ne_', 'mixing_', 'threshold_']) X = check_array(X, allow_nd=True) shapeX = X.shape if len(shapeX) == 3: Nt, Ns, Ne = shapeX else: raise ValueError( "X.shape should be (n_trials, n_samples, n_electrodes).") Xclean = np.zeros((Nt, Ns, Ne)) assert Ne < Ns, "number of samples should be higher than number of electrodes, check than \n" \ + "X.shape is (n_trials, n_samples, n_channels)." covmats = covariances( np.swapaxes(X, 1, 2), estimator=self.estimator) # (n_trials, n_channels, n_times) # TODO: parallelizing the loop for efficiency for k in range(Nt): # TODO: HAVE BOTH euclidian PCA and Riemannian PCA (PGA) using pymanopt evals, evecs = eigh(covmats[k, :]) # compute PCA indx = np.argsort(evals) # sort in ascending evecs = evecs[:, indx] keep = (evals[indx] < np.sum(self.threshold_.dot(evecs) ** 2, axis = 0)) | \ (np.arange(Ne) < (Ne * (1 - self.max_dimension))) keep = np.expand_dims( keep, 0) # for element wise multiplication that follows spatialfilter = np.linalg.pinv(keep.transpose() * evecs.transpose().dot(self.mixing_)) R = self.mixing_.dot(spatialfilter).dot(evecs.transpose()) Xclean[k, :] = X[k, :].dot(R.transpose( )) # suboptimal in term of memory but great for debug return Xclean
def test_covariances(): """Test covariance for multiple estimator""" x = np.random.randn(2, 3, 100) cov = covariances(x) cov = covariances(x, estimator='oas') cov = covariances(x, estimator='lwf') cov = covariances(x, estimator='scm') cov = covariances(x, estimator='corr') cov = covariances(x, estimator='mcd') cov = covariances(x, estimator=np.cov) assert_raises(ValueError,covariances, x, estimator='truc')
def transform(self, X): """Estimate covariance matrices. Parameters ---------- X : ndarray, shape (n_trials, n_channels, n_samples) ndarray of trials. Returns ------- covmats : ndarray, shape (n_trials, n_channels, n_channels) ndarray of covariance matrices for each trials. """ covmats = covariances(X, estimator=self.estimator) return covmats
def transform(self, X: np.array) -> np.array: """Estimate covariance matrices. Parameters ---------- X : ndarray, shape (n_trials, n_channels, n_samples) ndarray of trials. Returns ------- covmats : ndarray, shape (n_trials, n_channels * n_frequencies, n_channels * n_frequencies) SSVEP covariance matrices for each trials. """ filtered = [] for filter in self.filters: filtered_X = filter(X, axis=-1) filtered.append(filtered_X) mega_X = np.concatenate(filtered, axis=1) out = covariances(mega_X, estimator=self._estimator) return out
def fit(self, X, y=None): """ Parameters ---------- X : ndarray, shape (n_trials, n_samples, n_channels) Training data, already filtered. y : ndarray, shape (n_trials,) | None, optional labels corresponding to each trial, not used (mentioned for sklearn comp) Returns ------- self : RASR instance. the fitted RASR estimator. """ X = check_array(X, allow_nd=True) shapeX = X.shape if len(shapeX) == 3: # concatenate all epochs Nt, Ns, Ne = shapeX # 3D array (not fully sklearn-compatible). First dim should always be trials. else: raise ValueError( "X.shape should be (n_trials, n_samples, n_electrodes).") assert Ne < Ns, "number of samples should be higher than number of electrodes, check than \n" \ + "X.shape is (n_trials, n_samples, n_channels)." if shapeX[0] < 100: raise ValueError( "Training requires at least 100 of trials to fit.") self.Ne_ = Ne # save attribute for testing epochs = X.copy() epochs = check_array(epochs, allow_nd=True) # estimate covariances matrices covmats = covariances( np.swapaxes(epochs, 1, 2), estimator=self.estimator) # (n_trials, n_channels, n_times) covmats = check_array(covmats, allow_nd=True) # geometric median # NOTE: while the term geometric median is used, it is NOT riemannian median but euclidian median, i.e. # it might be suboptimal for Symmetric Positive Definite matrices. logger.debug("geometric median") # covmean = mean_covariance(covmats, metric=self.metric_mean) covmean = np.reshape( geometric_median( np.reshape( covmats, (covmats.shape[0], covmats.shape[1] * covmats.shape[2]))), (covmats.shape[1], covmats.shape[2])) self.mixing_ = sqrtm(covmean) # estimate matrix matrix # TODO: implement both manifold-aware PCA (rASR) and standard PCA (ASR) evals, evecs = eigh(self.mixing_) # compute PCA indx = np.argsort(evals) # sort in ascending evecs = evecs[:, indx] epochs = np.tensordot(epochs, evecs, axes=(2, 0)) # apply PCA to epochs # RMS on sliding window rms_sliding = _rms(epochs) dist_params = np.zeros( (Ne, 4)) # mu, sig, alpha, beta parameters of estimated distribution #TODO: use joblib to parrallelize this loop (code bottleneck) for c in range(Ne): dist_params[c, :] = _fit_eeg_distribution( rms_sliding[:, c], **self.args_eeg_distribution) self.threshold_ = np.diag(dist_params[:, 0] + self.rejection_cutoff * dist_params[:, 1]).dot(np.transpose(evecs)) logger.debug("rASR calibrated") return self