def __init__(self, data, samplerate, pure_range=None): """ """ # process the pure range if pure_range is None: pure_range = (None, None) self._pure_range = pure_range # run pca sys.stdout.write("Running PCA...") Wpca, pca_data = pca( data[:, pure_range[0]:pure_range[1]]) #, ncomps, eigratio) # Run iwasobi sys.stdout.write("Running IWASOBI ICA...") sys.stdout.flush() #(W,Winit,ISR,signals) = iwasobi(data[:,pure_range[0]:pure_range[1]]) (W, Winit, ISR, signals) = iwasobi(pca_data) # combine the iwasobi weights with the pca weights W = np.dot(W, Wpca) A = np.linalg.pinv(W) # reorder the signals by loading (reordered from high to low) ind = np.argsort(np.abs(A).sum(0))[::-1] A = A[:, ind] W = W[ind, :] signals = signals[ind, :] self._ICA_weights = A #A = np.linalg.inv(W) sys.stdout.write("DONE!\n") sys.stdout.flush() # expand signals to span the entire dataset if necessary if (not pure_range[0] is None) or (not pure_range[1] is None): #Xmean=data[:,pure_range[0]:pure_range[1]].mean(1) #signals = np.add(np.dot(W,data).T,np.dot(W,Xmean)).T signals = np.dot(W, data) self._components = signals self._samplerate = samplerate self._data = data
def __init__(self, data, samplerate, pure_range=None): """ """ # process the pure range if pure_range is None: pure_range = (None,None) self._pure_range = pure_range # run pca sys.stdout.write("Running PCA...") Wpca,pca_data = pca(data[:,pure_range[0]:pure_range[1]]) #, ncomps, eigratio) # Run iwasobi sys.stdout.write("Running IWASOBI ICA...") sys.stdout.flush() #(W,Winit,ISR,signals) = iwasobi(data[:,pure_range[0]:pure_range[1]]) (W,Winit,ISR,signals) = iwasobi(pca_data) # combine the iwasobi weights with the pca weights W = np.dot(W,Wpca) A = np.linalg.pinv(W) # reorder the signals by loading (reordered from high to low) ind = np.argsort(np.abs(A).sum(0))[::-1] A = A[:,ind] W = W[ind,:] signals = signals[ind,:] self._ICA_weights = A #A = np.linalg.inv(W) sys.stdout.write("DONE!\n") sys.stdout.flush() # expand signals to span the entire dataset if necessary if (not pure_range[0] is None) or (not pure_range[1] is None): #Xmean=data[:,pure_range[0]:pure_range[1]].mean(1) #signals = np.add(np.dot(W,data).T,np.dot(W,Xmean)).T signals = np.dot(W,data) self._components = signals self._samplerate = samplerate self._data = data
def wica_clean(data, samplerate=None, pure_range=(None, None), EOG_elecs=[0, 1], std_fact=1.5, Kthr=2.5, num_mp_procs=0): """ Clean data with the Wavelet-ICA method described here: N.P. Castellanos, and V.A. Makarov (2006). 'Recovering EEG brain signals: Artifact suppression with wavelet enhanced independent component analysis' J. Neurosci. Methods, 158, 300--312. Instead of using the Infomax ICA algorithm, we use the (much much faster) IWASOBI algorithm. We also pick components to clean by only cleaning components that weigh heavily on the EOG electrodes. This ICA algorithm works better if you pass in data that have been high-pass filtered to remove big non-neural fluctuations and drifts. You do not have to run the ICA step on your entire dataset. Instead, it is possible to provide the start and end indicies for a continguous chunk of data that is 'clean' except for having lots of eyeblink examples. This range will also be used inside the wavelet-based artifact correction code to determine the best threshold for identifying artifacts. You do, however, want to try and make sure you provide enough samples for a good ICA decomposition. A good rule of thumb is 3*(N^2) where N is the number of channels/sources. """ # run pca sys.stdout.write("Running PCA...") Wpca, pca_data = pca( data[:, pure_range[0]:pure_range[1]]) #, ncomps, eigratio) # Run iwasobi sys.stdout.write("Running IWASOBI ICA...") sys.stdout.flush() #(W,Winit,ISR,signals) = iwasobi(data[:,pure_range[0]:pure_range[1]]) (W, Winit, ISR, signals) = iwasobi(pca_data) W = np.dot(W, Wpca) A = np.linalg.pinv(W) #A = np.linalg.inv(W) sys.stdout.write("DONE!\n") sys.stdout.flush() # expand signals to span the entire dataset if necessary if (not pure_range[0] is None) or (not pure_range[1] is None): #Xmean=data[:,pure_range[0]:pure_range[1]].mean(1) #signals = np.add(np.dot(W,data).T,np.dot(W,Xmean)).T signals = np.dot(W, data) # pick which signals to clean (ones that weigh on EOG elecs) # vals = np.sum(np.abs(A[EOG_elecs,:]),0) # std_thresh = std_fact*np.std(vals) # comp_ind = np.nonzero(vals>=std_thresh)[0] comp_ind = [] # loop over EOG elecs for e in EOG_elecs: # get the weights of each component onto that electrode vals = np.abs(A[e, :]) # calculate the threshold that the std must exceed for that # component to be considered std_thresh = std_fact * np.std(vals) #comp_ind.extend(np.nonzero(vals>=std_thresh)[0].tolist()) # loop over potential components for s in np.nonzero(vals >= std_thresh)[0].tolist(): # calculate the weights of all electrodes into that component sweights = np.abs(A[:, s]) # get threshold based on the std across those weights sthresh2 = std_fact * sweights.std() # see if that component crosses this second threshold if np.abs(A[e, s]) >= sthresh2: # yes, so append to the list to clean comp_ind.append(s) # Instead, try and make sure the weights are above the STD thresh # AND bigger for EOG elecs than for an elec like Pz comp_ind = np.unique(comp_ind) sys.stdout.write("Cleaning these components: " + str(comp_ind) + '\n') sys.stdout.flush() # remove strong artifacts if (not pure_range[0] is None) or (not pure_range[1] is None): # figure out the thresh for the range Cthr = remove_strong_artifacts(signals[:, pure_range[0]:pure_range[1]], comp_ind, Kthr, samplerate, num_mp_procs=num_mp_procs) else: Cthr = None Cthr = remove_strong_artifacts(signals, comp_ind, Kthr, samplerate, Cthr, num_mp_procs=num_mp_procs) # return cleaned data back in EEG space return np.dot(A, signals).astype(data.dtype)
def wica_clean(data, samplerate=None, pure_range=(None,None), EOG_elecs=[0,1], std_fact=1.5, Kthr=2.5,num_mp_procs=0): """ Clean data with the Wavelet-ICA method described here: N.P. Castellanos, and V.A. Makarov (2006). 'Recovering EEG brain signals: Artifact suppression with wavelet enhanced independent component analysis' J. Neurosci. Methods, 158, 300--312. Instead of using the Infomax ICA algorithm, we use the (much much faster) IWASOBI algorithm. We also pick components to clean by only cleaning components that weigh heavily on the EOG electrodes. This ICA algorithm works better if you pass in data that have been high-pass filtered to remove big non-neural fluctuations and drifts. You do not have to run the ICA step on your entire dataset. Instead, it is possible to provide the start and end indicies for a continguous chunk of data that is 'clean' except for having lots of eyeblink examples. This range will also be used inside the wavelet-based artifact correction code to determine the best threshold for identifying artifacts. You do, however, want to try and make sure you provide enough samples for a good ICA decomposition. A good rule of thumb is 3*(N^2) where N is the number of channels/sources. """ # run pca sys.stdout.write("Running PCA...") Wpca,pca_data = pca(data[:,pure_range[0]:pure_range[1]]) #, ncomps, eigratio) # Run iwasobi sys.stdout.write("Running IWASOBI ICA...") sys.stdout.flush() #(W,Winit,ISR,signals) = iwasobi(data[:,pure_range[0]:pure_range[1]]) (W,Winit,ISR,signals) = iwasobi(pca_data) W = np.dot(W,Wpca) A = np.linalg.pinv(W) #A = np.linalg.inv(W) sys.stdout.write("DONE!\n") sys.stdout.flush() # expand signals to span the entire dataset if necessary if (not pure_range[0] is None) or (not pure_range[1] is None): #Xmean=data[:,pure_range[0]:pure_range[1]].mean(1) #signals = np.add(np.dot(W,data).T,np.dot(W,Xmean)).T signals = np.dot(W,data) # pick which signals to clean (ones that weigh on EOG elecs) # vals = np.sum(np.abs(A[EOG_elecs,:]),0) # std_thresh = std_fact*np.std(vals) # comp_ind = np.nonzero(vals>=std_thresh)[0] comp_ind = [] # loop over EOG elecs for e in EOG_elecs: # get the weights of each component onto that electrode vals = np.abs(A[e,:]) # calculate the threshold that the std must exceed for that # component to be considered std_thresh = std_fact*np.std(vals) #comp_ind.extend(np.nonzero(vals>=std_thresh)[0].tolist()) # loop over potential components for s in np.nonzero(vals>=std_thresh)[0].tolist(): # calculate the weights of all electrodes into that component sweights = np.abs(A[:,s]) # get threshold based on the std across those weights sthresh2 = std_fact*sweights.std() # see if that component crosses this second threshold if np.abs(A[e,s]) >= sthresh2: # yes, so append to the list to clean comp_ind.append(s) # Instead, try and make sure the weights are above the STD thresh # AND bigger for EOG elecs than for an elec like Pz comp_ind = np.unique(comp_ind) sys.stdout.write("Cleaning these components: " + str(comp_ind) + '\n') sys.stdout.flush() # remove strong artifacts if (not pure_range[0] is None) or (not pure_range[1] is None): # figure out the thresh for the range Cthr = remove_strong_artifacts(signals[:,pure_range[0]:pure_range[1]], comp_ind,Kthr, samplerate, num_mp_procs=num_mp_procs) else: Cthr = None Cthr = remove_strong_artifacts(signals,comp_ind,Kthr, samplerate,Cthr, num_mp_procs=num_mp_procs) # return cleaned data back in EEG space return np.dot(A,signals).astype(data.dtype)