def run_fast_ica(samples, params): print("Beginning Fast ICA") if not params['NUM_COMPONENTS'] == None: params['NUM_COMPONENTS'] = nChans samples = np.rot90(samples) print(samples.shape) ica = FastICA(n_components=params['NUM_COMPONENTS'], max_iter=params['MAX_ITER'], tol=params['TOLERANCE']) print("ica.get_params(): ", ica.get_params()) print("type(ica): ", type(ica)) S_ = ica.fit_transform(samples) # Reconstruct signals print("S_", S_.shape) A_ = ica.mixing_ # Get estimated mixing matrix print("A_", A_.shape) combinedSignals = np.dot(S_, A_.T) print("Combined signals shape: ", combinedSignals.shape) print("ica.mean_ ", ica.mean_.shape) combinedSignalsICAmean = combinedSignals + ica.mean_ print("combined + mean: ", combinedSignalsICAmean) return np.rot90(S_)
class ICA(object): """ Wrapper for sklearn package. Performs fast ICA (Independent Component Analysis) ICA has 4 methods: - fit(waveforms) update class instance with ICA fit - fit_transform() do what fit() does, but additionally return the projection onto ICA space - inverse_transform(A) inverses the decomposition, returns waveforms for an input A, using Z - get_params() returns metadata used for fits. """ def __init__(self, num_components=10, catalog_name='unknown', whiten=True, fun = 'logcosh', fun_args = None, max_iter = 600, tol = .00001, w_init = None, random_state = None, algorithm = 'parallel'): self._decomposition = 'Fast ICA' self._num_components = num_components self._catalog_name = catalog_name self._whiten = whiten self._fun = fun self._fun_args = fun_args self._max_iter = max_iter self._tol = tol self._w_init = w_init self._random_state = random_state self._algorithm = algorithm self._ICA = FastICA(n_components=self._num_components, whiten = self._whiten, fun = self._fun, fun_args = self._fun_args, max_iter = self._max_iter, tol = self._tol, w_init = self._w_init, random_state = self._random_state, algorithm = self._algorithm) def fit(self,waveforms): # TODO make sure there are more columns than rows (transpose if not) # normalize waveforms self._waveforms = waveforms self._ICA.fit(self._waveforms) def fit_transform(self,waveforms): # TODO make sure there are more columns than rows (transpose if not) # normalize waveforms self._waveforms = waveforms self._A = self._ICA.fit_transform(self._waveforms) return self._A def inverse_transform(self,A): # convert basis back to waveforms using fit new_waveforms = self._ICA.inverse_transform(A) return new_waveforms def get_params(self): # TODO know what catalog was used! (include waveform metadata) params = self._ICA.get_params() params['num_components'] = params.pop('n_components') params['Decompositon'] = self._decomposition return params def get_basis(self): """ Return the ICA basis vectors (Z^\dagger)""" return self._ICA.get_mixing_matrix()
def btnConvert_click(self): msgBox = QMessageBox() Alg = ui.cbAlg.currentText() # Tol try: Tol = np.float(ui.txtTole.text()) except: msgBox.setText("Tolerance is wrong!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False # MaxIte try: MaxIter = np.int32(ui.txtMaxIter.text()) except: msgBox.setText("Maximum number of iterations is wrong!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False if MaxIter < 1: msgBox.setText("Maximum number of iterations is wrong!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False # OutFile OutFile = ui.txtOutFile.text() if not len(OutFile): msgBox.setText("Please enter out file!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False # InFile InFile = ui.txtInFile.text() if not len(InFile): msgBox.setText("Please enter input file!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False if not os.path.isfile(InFile): msgBox.setText("Input file not found!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False if ui.rbScale.isChecked() == True and ui.rbALScale.isChecked( ) == False: msgBox.setText( "Subject Level Normalization is just available for Subject Level Analysis!" ) msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False InData = io.loadmat(InFile) OutData = dict() OutData["imgShape"] = InData["imgShape"] if not len(ui.txtData.currentText()): msgBox.setText("Please enter Data variable name!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False try: X = InData[ui.txtData.currentText()] if ui.cbScale.isChecked() and (not ui.rbScale.isChecked()): X = preprocessing.scale(X) print("Whole of data is scaled X~N(0,1).") except: print("Cannot load data") return try: NumFea = np.int32(ui.txtNumFea.text()) except: msgBox.setText("Number of features is wrong!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False if NumFea < 1: msgBox.setText("Number of features must be greater than zero!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False if NumFea > np.shape(X)[1]: msgBox.setText("Number of features is wrong!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False # Subject if not len(ui.txtSubject.currentText()): msgBox.setText("Please enter Subject variable name!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False try: Subject = InData[ui.txtSubject.currentText()] OutData[ui.txtOSubject.text()] = Subject except: print("Cannot load Subject ID") return # Label if not len(ui.txtLabel.currentText()): msgBox.setText("Please enter Label variable name!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False OutData[ui.txtOLabel.text()] = InData[ui.txtLabel.currentText()] # Task if ui.cbTask.isChecked(): if not len(ui.txtTask.currentText()): msgBox.setText("Please enter Task variable name!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False OutData[ui.txtOTask.text()] = InData[ui.txtTask.currentText()] # Run if ui.cbRun.isChecked(): if not len(ui.txtRun.currentText()): msgBox.setText("Please enter Run variable name!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False OutData[ui.txtORun.text()] = InData[ui.txtRun.currentText()] # Counter if ui.cbCounter.isChecked(): if not len(ui.txtCounter.currentText()): msgBox.setText("Please enter Counter variable name!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False OutData[ui.txtOCounter.text()] = InData[ ui.txtCounter.currentText()] # Matrix Label if ui.cbmLabel.isChecked(): if not len(ui.txtmLabel.currentText()): msgBox.setText("Please enter Matrix Label variable name!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False OutData[ui.txtOmLabel.text()] = InData[ui.txtmLabel.currentText()] # Design if ui.cbDM.isChecked(): if not len(ui.txtDM.currentText()): msgBox.setText("Please enter Design Matrix variable name!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False OutData[ui.txtODM.text()] = InData[ui.txtDM.currentText()] # Coordinate if ui.cbCol.isChecked(): if not len(ui.txtCol.currentText()): msgBox.setText("Please enter Coordinator variable name!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False OutData[ui.txtOCol.text()] = InData[ui.txtCol.currentText()] # Condition if ui.cbCond.isChecked(): if not len(ui.txtCond.currentText()): msgBox.setText("Please enter Condition variable name!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False OutData[ui.txtOCond.text()] = InData[ui.txtCond.currentText()] # Number of Scan if ui.cbNScan.isChecked(): if not len(ui.txtScan.currentText()): msgBox.setText("Please enter Number of Scan variable name!") msgBox.setIcon(QMessageBox.Critical) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return False OutData[ui.txtOScan.text()] = InData[ui.txtScan.currentText()] Models = dict() Models["Name"] = "FastICA" if ui.rbALScale.isChecked(): print("Partition data to subject level ...") SubjectUniq = np.unique(Subject) X_Sub = list() for subj in SubjectUniq: if ui.cbScale.isChecked() and ui.rbScale.isChecked(): X_Sub.append( preprocessing.scale( X[np.where(Subject == subj)[1], :])) print("Data in subject level is scaled, X_" + str(subj) + "~N(0,1).") else: X_Sub.append(X[np.where(Subject == subj)[1], :]) print("Subject ", subj, " is extracted from data.") print("Running FICA in subject level ...") X_Sub_PCA = list() lenPCA = len(X_Sub) for xsubindx, xsub in enumerate(X_Sub): model = FastICA(n_components=NumFea, algorithm=Alg, max_iter=MaxIter, tol=Tol) X_Sub_PCA.append(model.fit_transform(xsub)) Models["Model" + str(xsubindx + 1)] = str( model.get_params(deep=True)) print("FICA: ", xsubindx + 1, " of ", lenPCA, " is done.") print("Data integration ... ") X_new = None for xsubindx, xsub in enumerate(X_Sub_PCA): X_new = np.concatenate( (X_new, xsub)) if X_new is not None else xsub print("Integration: ", xsubindx + 1, " of ", lenPCA, " is done.") OutData[ui.txtOData.text()] = X_new else: print("Running FastICA ...") model = FastICA(n_components=NumFea, algorithm=Alg, max_iter=MaxIter, tol=Tol) OutData[ui.txtOData.text()] = model.fit_transform(X) Models["Model"] = str(model.get_params(deep=True)) OutData["ModelParameter"] = Models print("Saving ...") io.savemat(ui.txtOutFile.text(), mdict=OutData) print("DONE.") msgBox.setText("FastICA is done.") msgBox.setIcon(QMessageBox.Information) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_()
class ICA(object): """ Wrapper for sklearn package. Performs fast ICA (Independent Component Analysis) ICA has 4 methods: - fit(waveforms) update class instance with ICA fit - fit_transform() do what fit() does, but additionally return the projection onto ICA space - inverse_transform(A) inverses the decomposition, returns waveforms for an input A, using Z - get_params() returns metadata used for fits. """ def __init__(self, num_components=10, catalog_name='unknown', whiten=True, fun='logcosh', fun_args=None, max_iter=600, tol=.00001, w_init=None, random_state=None, algorithm='parallel'): self._decomposition = 'Fast ICA' self._num_components = num_components self._catalog_name = catalog_name self._whiten = whiten self._fun = fun self._fun_args = fun_args self._max_iter = max_iter self._tol = tol self._w_init = w_init self._random_state = random_state self._algorithm = algorithm self._ICA = FastICA(n_components=self._num_components, whiten=self._whiten, fun=self._fun, fun_args=self._fun_args, max_iter=self._max_iter, tol=self._tol, w_init=self._w_init, random_state=self._random_state, algorithm=self._algorithm) def fit(self, waveforms): # TODO make sure there are more columns than rows (transpose if not) # normalize waveforms self._waveforms = waveforms self._ICA.fit(self._waveforms) def fit_transform(self, waveforms): # TODO make sure there are more columns than rows (transpose if not) # normalize waveforms self._waveforms = waveforms self._A = self._ICA.fit_transform(self._waveforms) return self._A def inverse_transform(self, A): # convert basis back to waveforms using fit new_waveforms = self._ICA.inverse_transform(A) return new_waveforms def get_params(self): # TODO know what catalog was used! (include waveform metadata) params = self._ICA.get_params() params['num_components'] = params.pop('n_components') params['Decompositon'] = self._decomposition return params def get_basis(self): """ Return the ICA basis vectors (Z^\dagger)""" return self._ICA.get_mixing_matrix()