def save_open_dialogs_to_csv(self): if not self.open_dialogs: qtutil.info('No correlation matrix windows are open. ') return for i, dialog in enumerate(self.open_dialogs): rois_names = [dialog.connectivity_dialog.model.rois[x].name for x in range( len(dialog.connectivity_dialog.model.rois))] file_name_avg = os.path.splitext(os.path.basename(dialog.windowTitle()))[0] + \ '_averaged_correlation_matrix.csv' file_name_stdev = os.path.splitext(os.path.basename(dialog.windowTitle()))[0] + \ '_stdev_correlation_matrix.csv' with open(os.path.join(self.project.path, file_name_avg), 'w', newline='') as csvfile: writer = csv.writer(csvfile, delimiter=',') writer.writerow(rois_names) for row_ind in range(len(dialog.connectivity_dialog.model._data)): row = dialog.connectivity_dialog.model._data[row_ind] row = [row[x][0] for x in range(len(row))] writer.writerow(row) writer.writerow(['Selected videos:']+self.selected_videos) # Do the standard deviation with open(os.path.join(self.project.path, file_name_stdev), 'w', newline='') as csvfile: writer = csv.writer(csvfile, delimiter=',') writer.writerow(rois_names) for row_ind in range(len(dialog.connectivity_dialog.model._data)): row = dialog.connectivity_dialog.model._data[row_ind] row = [row[x][1] for x in range(len(row))] writer.writerow(row) writer.writerow(['Selected videos:'] + self.selected_videos)
def import_file(self, filename): if not filename.endswith('.npy'): new_filename = self.to_npy(filename) if not new_filename: raise NotConvertedError() else: filename = new_filename else: new_filename = os.path.basename(filename) new_filename = os.path.join(self.project.path, new_filename) if os.path.normpath(filename) != os.path.normpath(new_filename): qtutil.info('Copying .npy from '+ filename + ' to ' + new_filename + '. You can do this manually for large files to see a progress bar') copyfile(filename, new_filename) filename = new_filename if filename in [f['path'] for f in self.project.files]: raise FileAlreadyInProjectError(filename) name, ext = os.path.splitext(os.path.basename(filename)) self.project.files.append({ 'name': name, 'path': filename, 'type': 'video', 'manipulations': [] }) self.project.save() return filename
def execute_primary_function(self, input_paths=None): '''Primary function of plugin''' if not input_paths: if not self.selected_videos: return else: selected_videos = self.selected_videos else: selected_videos = input_paths # use selected_videos which are the paths to stacks the user has selected or have been input from automation # todo: insert functionality here if not len(self.add_list.selectedIndexes()) == len(selected_videos): qtutil.info('Select the same number of image stacks and additions to apply') return output_paths = [] for add_num_item, video_path in zip(self.add_list.selectedIndexes(), selected_videos): frames = file_io.load_file(video_path) frames = frames + int(add_num_item.data()) # note that memory mapping is recommended for large files. path = pfs.save_project(video_path, self.project, frames, 'custom-addition-'+add_num_item.data(), 'video') output_paths = output_paths + [path] # refresh_list can be used to refresh an input list that will have particular indices selected, # specified content type shown as well as only showing content after a particular plugin manipulation pfs.refresh_list(self.project, self.video_list, self.params[self.Labels.video_list_indices_label], self.Defaults.list_display_type, self.params[self.Labels.last_manips_to_display_label]) # return the output path(s) of this function for automation return output_paths
def execute_primary_function(self, input_paths=None): '''Primary function of plugin''' if not input_paths: if not self.selected_videos: return else: selected_videos = self.selected_videos else: selected_videos = input_paths # use selected_videos which are the paths to stacks the user has selected or have been input from automation # todo: insert functionality here if not len(self.add_list.selectedIndexes()) == len(selected_videos): qtutil.info( 'Select the same number of image stacks and additions to apply' ) return output_paths = [] for add_num_item, video_path in zip(self.add_list.selectedIndexes(), selected_videos): frames = file_io.load_file(video_path) frames = frames + int(add_num_item.data( )) # note that memory mapping is recommended for large files. path = pfs.save_project(video_path, self.project, frames, 'custom-addition-' + add_num_item.data(), 'video') output_paths = output_paths + [path] # refresh_list can be used to refresh an input list that will have particular indices selected, # specified content type shown as well as only showing content after a particular plugin manipulation pfs.refresh_list(self.project, self.video_list, self.params[self.Labels.video_list_indices_label], self.Defaults.list_display_type, self.params[self.Labels.last_manips_to_display_label]) # return the output path(s) of this function for automation return output_paths
def export_bulk_clicked(self): filetype = self.export_filetype_cb.currentText() export_dir = str(QFileDialog.getExistingDirectory(self, "Select Directory")) progress = MyProgressDialog('Export Progress', 'Exporting files...', self) progress.show() for i, selected_video in enumerate(self.selected_videos): export_path = os.path.join(export_dir, os.path.basename(os.path.splitext(selected_video)[0]) + filetype) progress.setValue((i / len(self.selected_videos)) * 100) self.export_video(selected_video, export_path) progress.close() qtutil.info("Export to " + export_dir + " complete")
def avg_mat_triggered(self): qtutil.info("Please select all the matrices to be averaged. Matrices must have the same ROIs in the same " "locations. You might find it easier to move all the matrix pkl files to the same folder before " "performing this action.") paths = QFileDialog.getOpenFileNames( self, 'Load matrices', QSettings().value('last_vis_path'), 'visualization window pickle (*.pkl)') dat = [] roinames_previous = [] path_previous = '' for path in paths: try: with open(path, 'rb') as input: [mat_data, roinames, selected_image_stacks, state] = \ pickle.load(input) dat = dat + [[mat_data, roinames, selected_image_stacks, state]] if roinames != roinames_previous and roinames_previous: qtutil.critical(path + 'does not have the same ROI names as ' + path_previous) return roinames_previous = roinames path_previous = path except: qtutil.critical(path + " failed to open. Aborting. Make sure this file is a MATRIX pkl file") mat_datas = [[len(d[2]), d[0]] for d in dat] ns_and_means_and_stdevs = [[[] for j in range(len(mat_datas[0][1][0]))] for i in range(len(mat_datas[0][1]))] for row_no, row in enumerate(mat_datas[0][1]): for col_no, col in enumerate(mat_datas[0][1][0]): for mat_data in mat_datas: ns_and_means_and_stdevs[row_no][col_no] = ns_and_means_and_stdevs[row_no][col_no] + \ [[mat_data[0]] + list(mat_data[1][row_no][col_no])] result = [[[] for j in range(len(mat_datas[0][1][0]))] for i in range(len(mat_datas[0][1]))] for row_no, row in enumerate(result): for col_no, col in enumerate(result[0]): result[row_no][col_no] = (combined_mean([x[:-1] for x in ns_and_means_and_stdevs[row_no][col_no]]), combined_st_dev(ns_and_means_and_stdevs[row_no][col_no])) cm_type = self.cm_comboBox.currentText() win = ConnectivityDialog(self, roinames, cm_type, loaded_data=result) new_dw = DockWindowMat(win, parent=self, state=state, title=os.path.basename(paths[0]) + ' ' + str(len(paths)) + ' other matrices averaged') self.open_dialogs.append(new_dw) new_dw.show() new_dw.saving_state[str].connect(functools.partial(pfs.save_dock_window_to_project, self, self.Defaults.window_type))
def import_file(self, filename): if not filename.endswith('.npy'): new_filename = self.to_npy(filename) if not new_filename: raise NotConvertedError() else: filename = new_filename else: new_filename = os.path.basename(filename) new_filename = os.path.join(self.project.path, new_filename) if os.path.normpath(filename) != os.path.normpath(new_filename): qtutil.info( 'Copying .npy from ' + filename + ' to ' + new_filename + '. We recommend doing this manually for large files') copyfile_progress = QProgressDialog( 'Progress Copying ' + filename + ' to ' + new_filename, 'Abort', 0, 100, self) copyfile_progress.setAutoClose(True) copyfile_progress.setMinimumDuration(0) def callback(x): copyfile_progress.setValue(x * 100) QApplication.processEvents() callback(0.0) if copyfile_progress.wasCanceled(): return copyfile(filename, new_filename) if copyfile_progress.wasCanceled(): return callback(1.0) filename = new_filename if filename in [f['path'] for f in self.project.files]: return filename # raise FileAlreadyInProjectError(filename) name, ext = os.path.splitext(os.path.basename(filename)) self.project.files.append({ 'name': name, 'path': filename, 'type': 'video', 'manipulations': [] }) self.project.save() return filename
def execute_primary_function(self, input_paths=None): '''Primary function of plugin''' if not input_paths: if not self.selected_videos: return else: selected_videos = self.selected_videos else: selected_videos = input_paths # use selected_videos which are the paths to stacks the user has selected or have been input from automation qtutil.info('This is only a template. Use it to code from. \n' 'Value of spinbox is: ' + str(self.example_sb.value())) # todo: insert functionality here # refresh_list can be used to refresh an input list that will have particular indices selected, # specified content type shown as well as only showing content after a particular plugin manipulation pfs.refresh_list(self.project, self.video_list, self.params[self.Labels.video_list_indices_label], self.Defaults.list_display_type, self.params[self.Labels.last_manips_to_display_label])
def export_clicked(self): """Retrieve fileinfo and call export""" progress = MyProgressDialog('Export Progress', 'Exporting files...', self) progress.show() for i, selected_video in enumerate(self.selected_videos): progress.setValue((i/len(self.selected_videos)) * 100) filters = { # '.mp4': 'MP4 file (*.mp4)', '.avi': 'AVI file (*.avi)', '.tif': 'TIF file (*.tif)', '.raw': 'RAW file (*.raw)' } default = os.path.basename(selected_video) or 'untitled' # default = 'name' in fileinfo and fileinfo['name'] or 'untitled' filename = self.filedialog(default, filters) if not filename: return self.export_video(selected_video, filename) progress.close() qtutil.info("File export for selected files complete")
def load_triggered(self): paths = [p['path'] for p in self.project.files if p['type'] == self.Defaults.window_type] if not paths: qtutil.info("Your project has no correlation matrices. Make and save some!") return for pickle_path in paths: try: with open(pickle_path, 'rb') as input: (title, roinames, dat) = pickle.load(input) except: del_msg = pickle_path + " could not be loaded. If this file exists, " \ "ensure MBE has read access to this " \ "location and that another program isn't using this file " \ "" \ "\n \nOtherwise, would you like to detatch this file from your project? " reply = QMessageBox.question(self, 'File Load Error', del_msg, QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: norm_path = os.path.normpath(pickle_path) self.project.files[:] = [f for f in self.project.files if os.path.normpath(f['path']) != norm_path] self.project.save() load_msg = pickle_path + " detatched from your project." \ "" \ "\n \n Would you like to continue loading the " \ "remaining project matrices?" reply = QMessageBox.question(self, 'Continue?', load_msg, QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.No: return continue main_window = ConnectivityDialog(self, roinames, self.cm_comboBox.currentText(), dat) main_window.setWindowTitle(title) main_window.resize(900, 900) main_window.show() self.open_dialogs.append(main_window)
def load_triggered(self): paths = [p['path'] for p in self.project.files if p['type'] == self.Defaults.window_type] if not paths: qtutil.info("Your project has no correlation matrices. Make and save some!") return for pickle_path in paths: try: with open(pickle_path, 'rb') as input: (title, roinames, dat) = pickle.load(input) except: del_msg = pickle_path + " could not be loaded. If this file exists, " \ "ensure MBE has read access to this " \ "location and that another program isn't using this file " \ "" \ "\n \nOtherwise, would you like to detatch this file from your project? " reply = QMessageBox.question(self, 'File Load Error', del_msg, QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: norm_path = os.path.normpath(pickle_path) self.project.files[:] = [f for f in self.project.files if os.path.normpath(f['path']) != norm_path] self.project.save() load_msg = pickle_path + " detatched from your project." \ "" \ "\n \n Would you like to continue loading the " \ "remaining project matrices?" reply = QMessageBox.question(self, 'Continue?', load_msg, QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.No: return continue main_window = ConnectivityDialog(self, roinames, self.cm_comboBox.currentText(), dat) main_window.setWindowTitle(title) main_window.resize(900, 900) main_window.show() self.open_dialogs.append(main_window)
def save_open_dialogs_to_csv(self): progress = QProgressDialog('Generating csv files...', 'Abort', 0, 100, self) progress.setAutoClose(True) progress.setMinimumDuration(0) def callback(x): progress.setValue(x * 100) QApplication.processEvents() for i, dialog in enumerate(self.open_dialogs): callback(i / len(self.open_dialogs)) rois_names = [dialog.model.rois[x].name for x in range(len(dialog.model.rois))] unique_id = str(uuid.uuid4()) file_name_avg = self.project.name + '_averaged_connectivity_matrix_' + unique_id + '.csv' file_name_stdev = self.project.name + '_stdev_connectivity_matrix_' + unique_id + '.csv' with open(os.path.join(self.project.path, file_name_avg), 'w', newline='') as csvfile: writer = csv.writer(csvfile, delimiter=',') writer.writerow(rois_names) for row_ind in range(len(dialog.model._data)): row = dialog.model._data[row_ind] row = [row[x][0] for x in range(len(row))] writer.writerow(row) writer.writerow(['Selected videos:']+self.selected_videos) # Do the standard deviation with open(os.path.join(self.project.path, file_name_stdev), 'w', newline='') as csvfile: writer = csv.writer(csvfile, delimiter=',') writer.writerow(rois_names) for row_ind in range(len(dialog.model._data)): row = dialog.model._data[row_ind] row = [row[x][1] for x in range(len(row))] writer.writerow(row) writer.writerow(['Selected videos:'] + self.selected_videos) callback(1) qtutil.info("All matrices saved to project directory")
def sub_mat_triggered(self): qtutil.info("Please select the matrix that will act as the minuend") minuend_path = QFileDialog.getOpenFileName( self, 'Load matrix', QSettings().value('last_vis_path'), 'visualization window pickle (*.pkl)') if not minuend_path: return qtutil.info("Please select the matrix that will act as the subtrahend. This second matrix must have the " "same dimensions and ROIs in the same locations as the minuend matrix") subtrahand_path = QFileDialog.getOpenFileName( self, 'Load matrix', QSettings().value('last_vis_path'), 'visualization window pickle (*.pkl)') if not subtrahand_path: return QSettings().setValue('last_vis_path', os.path.dirname(subtrahand_path)) try: with open(minuend_path, 'rb') as input: [minuend_mat_data, minuend_roinames, minuend_selected_image_stacks, minuend_state] = pickle.load(input) except: qtutil.critical(minuend_path + " failed to open. Aborting. Make sure this file is a MATRIX pkl file") try: with open(subtrahand_path, 'rb') as input: [subtrahand_mat_data, subtrahand_roinames, subtrahand_selected_image_stacks, subtrahand_state] = pickle.load(input) except: qtutil.critical(subtrahand_path + " failed to open. Aborting. Make sure this file is a MATRIX pkl file") if subtrahand_roinames != minuend_roinames: qtutil.critical('roi names do not match. The same roi names and same order is required. Aborting.') return minuend_number = len(minuend_selected_image_stacks) subtrahand_number = len(subtrahand_selected_image_stacks) altogether = minuend_number + subtrahand_number # minus one = Bessel correction. # See https://stats.stackexchange.com/questions/55999/is-it-possible-to-find-the-combined-standard-deviation ns_and_means_and_stdevs = [[[] for j in range(len(subtrahand_mat_data))] for i in range(len(subtrahand_mat_data[0]))] for row_no, row in enumerate(ns_and_means_and_stdevs): for col_no, col in enumerate(ns_and_means_and_stdevs[0]): ns_and_means_and_stdevs[row_no][col_no] = [[minuend_number] + list(minuend_mat_data[row_no][col_no]), [subtrahand_number] + list(subtrahand_mat_data[row_no][col_no])] sub_mat = [[[] for j in range(len(subtrahand_mat_data[0]))] for i in range(len(subtrahand_mat_data))] for row_no, row in enumerate(sub_mat): for col_no, col in enumerate(sub_mat[0]): sub_mat[row_no][col_no] = (minuend_mat_data[row_no][col_no][0]-subtrahand_mat_data[row_no][col_no][0], combined_st_dev(ns_and_means_and_stdevs[row_no][col_no])) cm_type = self.cm_comboBox.currentText() win = ConnectivityDialog(self, minuend_roinames, cm_type, sub_mat) new_dw = DockWindowMat(win, parent=self, state=minuend_state, title=os.path.basename(minuend_path) + ' - ' + os.path.basename(subtrahand_path)) self.open_dialogs.append(new_dw) new_dw.show() new_dw.saving_state[str].connect(functools.partial(pfs.save_dock_window_to_project, self, self.Defaults.window_type))
def save_triggered(self): if not self.open_dialogs: qtutil.info('No correlation matrix windows are open. ') return self.save_open_dialogs_to_csv() qtutil.info('csvs saved to project directory') return #todo: improve general user experience (saving,loading etc). Look at below continue_msg = "All Correlation Matrices will be closed after saving, *including* ones you have not saved. \n" \ "\n" \ "Continue?" reply = QMessageBox.question(self, 'Save All', continue_msg, QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.No: return qtutil.info( 'There are ' + str(len(self.open_dialogs)) + ' correlation matrices in memory. We will now choose a path ' 'to save each one to. Simply don\'t save ones you have ' 'purposefully closed. Though, good news, you now have ' 'one last chance to save and recover any matrices you ' 'accidentally closed') for dialog in self.open_dialogs: win_title = dialog.windowTitle() filters = { '.pkl': 'Python pickle file (*.pkl)' } default = win_title pickle_path = self.filedialog(default, filters) if pickle_path: self.project.files.append({ 'path': pickle_path, 'type': self.Defaults.window_type, 'name': os.path.basename(pickle_path) }) self.project.save() # for row in dialog.model._data: # for cell in row: # if math.isnan(cell[0]) or math.isnan(cell[0]): # qtutil.warning("File might not save properly since it has nan values. Make sure all your " # "ROIs are inside your mask.") # break # Now save the actual file title = os.path.basename(pickle_path) matrix_output_data = (title, dialog.connectivity_dialog.model.roinames, dialog.connectivity_dialog.model._data) try: with open(pickle_path, 'wb') as output: pickle.dump(matrix_output_data, output, -1) except: qtutil.critical( pickle_path + " could not be saved. Ensure MBE has write access to this location and " "that another program isn't using this file.") qtutil.info("All files have been saved") csv_msg = "Save csv files of all open Correlation Matrix windows as well?" reply = QMessageBox.question(self, 'Save All', csv_msg, QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: self.save_open_dialogs_to_csv() for dialog in self.open_dialogs: dialog.close() self.open_dialogs = []
def save_triggered(self): if not self.open_dialogs: qtutil.info('No correlation matrix windows are open. ') return self.save_open_dialogs_to_csv() qtutil.info('csvs saved to project directory') return #todo: improve general user experience (saving,loading etc). Look at below continue_msg = "All Correlation Matrices will be closed after saving, *including* ones you have not saved. \n" \ "\n" \ "Continue?" reply = QMessageBox.question(self, 'Save All', continue_msg, QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.No: return qtutil.info( 'There are ' + str(len(self.open_dialogs)) + ' correlation matrices in memory. We will now choose a path ' 'to save each one to. Simply don\'t save ones you have ' 'purposefully closed. Though, good news, you now have ' 'one last chance to save and recover any matrices you ' 'accidentally closed') for dialog in self.open_dialogs: win_title = dialog.windowTitle() filters = { '.pkl': 'Python pickle file (*.pkl)' } default = win_title pickle_path = self.filedialog(default, filters) if pickle_path: self.project.files.append({ 'path': pickle_path, 'type': self.Defaults.window_type, 'name': os.path.basename(pickle_path) }) self.project.save() # for row in dialog.model._data: # for cell in row: # if math.isnan(cell[0]) or math.isnan(cell[0]): # qtutil.warning("File might not save properly since it has nan values. Make sure all your " # "ROIs are inside your mask.") # break # Now save the actual file title = os.path.basename(pickle_path) matrix_output_data = (title, dialog.connectivity_dialog.model.roinames, dialog.connectivity_dialog.model._data) try: with open(pickle_path, 'wb') as output: pickle.dump(matrix_output_data, output, -1) except: qtutil.critical( pickle_path + " could not be saved. Ensure MBE has write access to this location and " "that another program isn't using this file.") qtutil.info("All files have been saved") csv_msg = "Save csv files of all open Correlation Matrix windows as well?" reply = QMessageBox.question(self, 'Save All', csv_msg, QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: self.save_open_dialogs_to_csv() for dialog in self.open_dialogs: dialog.close() self.open_dialogs = []
def automate_pipeline(self): # order by index ordered_q_model_indexes = sorted(self.sidebar.pl_list.selectedIndexes(), key=lambda x: x.row(), reverse=False) if not ordered_q_model_indexes: qtutil.info("Select all the plugins you want to process through. Use shift or ctrl to select multiple") import_plugin_indexes = [ind for ind in range(len(ordered_q_model_indexes)) if self.plugins[ordered_q_model_indexes[ind].data(Qt.UserRole)].name in constants.IMPORT_PLUGINS] if not import_plugin_indexes: p = self.plugins[ordered_q_model_indexes[0].data(Qt.UserRole)] if p.name not in constants.IMPORT_PLUGINS: number_of_outputs = p.output_number_expected() # find the number of files outputted by the first plugin for q_model_index in ordered_q_model_indexes: p = self.plugins[q_model_index.data(Qt.UserRole)] if p.name not in constants.IMPORT_PLUGINS: number_of_outputs = p.output_number_expected() if not p.check_ready_for_automation(number_of_outputs): qtutil.critical(p.automation_error_message()) return number_of_outputs = p.output_number_expected(number_of_outputs) # find the number of outputs p = self.plugins[ordered_q_model_indexes[0].data(Qt.UserRole)] input_paths = p.get_input_paths() if not input_paths: qtutil.critical("The first plugin in the pipeline does not have a set of input files selected") return for q_model_index in ordered_q_model_indexes: p = self.plugins[q_model_index.data(Qt.UserRole)] output_paths = p.run(input_paths) input_paths = output_paths ordered_q_model_indexes_segments = [] for i, import_ind in enumerate(import_plugin_indexes): if i < len(import_plugin_indexes)-1: # ordered_q_model_indexes are the indices in the GUI. # retrieve the indices from where this import plugin is (import_ind) to # the index right before the next import plugin ordered_q_model_indexes_segment = ordered_q_model_indexes[import_ind:(import_plugin_indexes[i+1])] else: ordered_q_model_indexes_segment = ordered_q_model_indexes[import_ind:] ordered_q_model_indexes_segments = ordered_q_model_indexes_segments + [ordered_q_model_indexes_segment] import_paths = [] for i, ordered_q_model_indexes_segment in enumerate(ordered_q_model_indexes_segments): import_plugin = self.plugins[ordered_q_model_indexes_segment[0].data(Qt.UserRole)] qtutil.info("Please select all your files for the pipeline starting from import plugin " + str(i)) input_paths = import_plugin.get_input_paths() import_paths = import_paths + [input_paths] if not input_paths: qtutil.critical("import plugin " + str(i) + " in the pipeline does not have a set of input files selected") return # ensure all selected plugins are ready for automation for i, ordered_q_model_indexes_segment in enumerate(ordered_q_model_indexes_segments): not_import_plugins = [self.plugins[ordered_q_model_indexes_segment[j].data(Qt.UserRole)] for j in range(1, len(ordered_q_model_indexes_segment))] number_of_outputs = len(import_paths[i]) for not_import_plugin in not_import_plugins: if not not_import_plugin.check_ready_for_automation(number_of_outputs): qtutil.critical(not_import_plugin.automation_error_message()) return number_of_outputs = not_import_plugin.output_number_expected(number_of_outputs) for i, ordered_q_model_indexes_segment in enumerate(ordered_q_model_indexes_segments): input_paths = import_paths[i] for q_model_index in ordered_q_model_indexes_segment: p = self.plugins[q_model_index.data(Qt.UserRole)] output_paths = p.run(input_paths) input_paths = output_paths
def automate_pipeline(self): # order by index ordered_q_model_indexes = sorted( self.sidebar.pl_list.selectedIndexes(), key=lambda x: x.row(), reverse=False) if not ordered_q_model_indexes: qtutil.info( "Select all the plugins you want to process through. Use shift or ctrl to select multiple" ) import_plugin_indexes = [ ind for ind in range(len(ordered_q_model_indexes)) if self.plugins[ordered_q_model_indexes[ind].data( Qt.UserRole)].name in constants.IMPORT_PLUGINS ] if not import_plugin_indexes: p = self.plugins[ordered_q_model_indexes[0].data(Qt.UserRole)] if p.name not in constants.IMPORT_PLUGINS: number_of_outputs = p.output_number_expected( ) # find the number of files outputted by the first plugin for q_model_index in ordered_q_model_indexes: p = self.plugins[q_model_index.data(Qt.UserRole)] if p.name not in constants.IMPORT_PLUGINS: number_of_outputs = p.output_number_expected() if not p.check_ready_for_automation(number_of_outputs): qtutil.critical(p.automation_error_message()) return number_of_outputs = p.output_number_expected( number_of_outputs) # find the number of outputs p = self.plugins[ordered_q_model_indexes[0].data(Qt.UserRole)] input_paths = p.get_input_paths() if not input_paths: qtutil.critical( "The first plugin in the pipeline does not have a set of input files selected" ) return for q_model_index in ordered_q_model_indexes: p = self.plugins[q_model_index.data(Qt.UserRole)] output_paths = p.run(input_paths) input_paths = output_paths ordered_q_model_indexes_segments = [] for i, import_ind in enumerate(import_plugin_indexes): if i < len(import_plugin_indexes) - 1: # ordered_q_model_indexes are the indices in the GUI. # retrieve the indices from where this import plugin is (import_ind) to # the index right before the next import plugin ordered_q_model_indexes_segment = ordered_q_model_indexes[ import_ind:(import_plugin_indexes[i + 1])] else: ordered_q_model_indexes_segment = ordered_q_model_indexes[ import_ind:] ordered_q_model_indexes_segments = ordered_q_model_indexes_segments + [ ordered_q_model_indexes_segment ] import_paths = [] for i, ordered_q_model_indexes_segment in enumerate( ordered_q_model_indexes_segments): import_plugin = self.plugins[ ordered_q_model_indexes_segment[0].data(Qt.UserRole)] qtutil.info( "Please select all your files for the pipeline starting from import plugin " + str(i)) input_paths = import_plugin.get_input_paths() import_paths = import_paths + [input_paths] if not input_paths: qtutil.critical( "import plugin " + str(i) + " in the pipeline does not have a set of input files selected" ) return # ensure all selected plugins are ready for automation for i, ordered_q_model_indexes_segment in enumerate( ordered_q_model_indexes_segments): not_import_plugins = [ self.plugins[ordered_q_model_indexes_segment[j].data( Qt.UserRole)] for j in range(1, len(ordered_q_model_indexes_segment)) ] number_of_outputs = len(import_paths[i]) for not_import_plugin in not_import_plugins: if not not_import_plugin.check_ready_for_automation( number_of_outputs): qtutil.critical( not_import_plugin.automation_error_message()) return number_of_outputs = not_import_plugin.output_number_expected( number_of_outputs) for i, ordered_q_model_indexes_segment in enumerate( ordered_q_model_indexes_segments): input_paths = import_paths[i] for q_model_index in ordered_q_model_indexes_segment: p = self.plugins[q_model_index.data(Qt.UserRole)] output_paths = p.run(input_paths) input_paths = output_paths
def sub_mat_triggered(self): qtutil.info("Please select the matrix that will act as the minuend") minuend_path = QFileDialog.getOpenFileName( self, 'Load matrix', QSettings().value('last_vis_path'), 'visualization window pickle (*.pkl)')[0] if not minuend_path: return qtutil.info("Please select the matrix that will act as the subtrahend. This second matrix must have the " "same dimensions and ROIs in the same locations as the minuend matrix") subtrahand_path = QFileDialog.getOpenFileName( self, 'Load matrix', QSettings().value('last_vis_path'), 'visualization window pickle (*.pkl)') if not subtrahand_path: return QSettings().setValue('last_vis_path', os.path.dirname(subtrahand_path)) try: with open(minuend_path, 'rb') as input: [minuend_mat_data, minuend_roinames, minuend_selected_image_stacks, minuend_state] = pickle.load(input) except: qtutil.critical(minuend_path + " failed to open. Aborting. Make sure this file is a MATRIX pkl file") try: with open(subtrahand_path, 'rb') as input: [subtrahand_mat_data, subtrahand_roinames, subtrahand_selected_image_stacks, subtrahand_state] = pickle.load(input) except: qtutil.critical(subtrahand_path + " failed to open. Aborting. Make sure this file is a MATRIX pkl file") if subtrahand_roinames != minuend_roinames: qtutil.critical('roi names do not match. The same roi names and same order is required. Aborting.') return minuend_number = len(minuend_selected_image_stacks) subtrahand_number = len(subtrahand_selected_image_stacks) altogether = minuend_number + subtrahand_number # minus one = Bessel correction. # See https://stats.stackexchange.com/questions/55999/is-it-possible-to-find-the-combined-standard-deviation ns_and_means_and_stdevs = [[[] for j in range(len(subtrahand_mat_data))] for i in range(len(subtrahand_mat_data[0]))] for row_no, row in enumerate(ns_and_means_and_stdevs): for col_no, col in enumerate(ns_and_means_and_stdevs[0]): ns_and_means_and_stdevs[row_no][col_no] = [[minuend_number] + list(minuend_mat_data[row_no][col_no]), [subtrahand_number] + list(subtrahand_mat_data[row_no][col_no])] sub_mat = [[[] for j in range(len(subtrahand_mat_data[0]))] for i in range(len(subtrahand_mat_data))] for row_no, row in enumerate(sub_mat): for col_no, col in enumerate(sub_mat[0]): sub_mat[row_no][col_no] = (minuend_mat_data[row_no][col_no][0]-subtrahand_mat_data[row_no][col_no][0], combined_st_dev(ns_and_means_and_stdevs[row_no][col_no])) cm_type = self.cm_comboBox.currentText() win = ConnectivityDialog(self, minuend_roinames, cm_type, sub_mat) new_dw = DockWindowMat(win, parent=self, state=minuend_state, title=os.path.basename(minuend_path) + ' - ' + os.path.basename(subtrahand_path)) self.open_dialogs.append(new_dw) new_dw.show() new_dw.saving_state[str].connect(functools.partial(pfs.save_dock_window_to_project, self, self.Defaults.window_type))