def plot_to_docks(self, video_path_to_plots_dict, area): if not video_path_to_plots_dict: return roi_names = list(list(video_path_to_plots_dict.values())[0].keys()) video_paths = list(video_path_to_plots_dict.keys()) # regroup ROIs of same type together and add to Docks dynamically plot_docks = range(len([i for i in self.area.docks.keys()])) plot_docs_cycle = cycle(plot_docks) for roi_name in roi_names: warning_issued = False plots_for_roi = [] source_names = [] for video_path in video_path_to_plots_dict.keys(): root, ext = os.path.splitext(video_path) source_name = os.path.basename(root) source_names = source_names + [source_name] plots_for_roi = plots_for_roi + [video_path_to_plots_dict[video_path][roi_name]] # put all plots from one ROI on a single plot and place on one of the 4 docs next_dock = next(plot_docs_cycle) d = Dock(roi_name, size=(500, 200), closable=True) area.addDock(d, 'above', area.docks['d' + str(next_dock + 1)]) doc_window = pg.GraphicsWindow(title="Dock plot") plot = doc_window.addPlot(title=roi_name) plot.setLabel('bottom', "Image Frames") plot.setLabel('left', "Activity") plot.addLegend() assert (len(plots_for_roi) == len(source_names)) for i, (p, source_name) in enumerate(zip(plots_for_roi, source_names)): if i < len(brewer_colors): color = brewer_colors[i].rgb else: if not warning_issued: qtutil.warning('Perceptual distinctiveness limit (12) reached. Resorting to Kelly colours. ' 'Please be careful with how you interpret your data') warning_issued = True if i < len(brewer_colors) + len(kelly_colors): color = kelly_colors[i - len(brewer_colors)].rgb else: qtutil.critical( 'Colour limit reached. Please plot your data over multiple plots or output solely to csv') return doc_window plot.plot(p, pen=color, name=source_name) d.addWidget(doc_window) # Save plot to file (backup) ps = [list(p) for p in plots_for_roi] ps_rows = list(zip(*ps)) plot_out = os.path.join(os.path.dirname(video_paths[0]), roi_name + '_plots_backup.csv') with open(plot_out, 'w', newline='') as csvfile: writer = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL) writer.writerow(source_names) for i, row in enumerate(ps_rows): writer.writerow([str(p) for p in row]) # close placeholder docks for plot_dock in plot_docks: area.docks['d' + str(plot_dock + 1)].close()
def load_file(filename, progress_callback=None, segment=None): file_size = os.path.getsize(filename) available = list(psutil.virtual_memory())[1] percent = list(psutil.virtual_memory())[2] # [total, available, percent, used, free, active, inactive, buffers, cached, shared] = list(psutil.virtual_memory()) if file_size > available: qtutil.critical('Not enough memory. File is of size ' + str(file_size) + ' and available memory is: ' + str(available)) raise MemoryError('Not enough memory. File is of size ' + str(file_size) + ' and available memory is: ' + str(available)) if percent > 95: qtutil.warning('Your memory appears to be getting low.') if filename.endswith('.npy'): frames = load_npy(filename, progress_callback, segment) # if frames.dtype == 'float64': # qtutil.critical("FLOAT64") # raise MemoryError("FLOAT64") else: raise UnknownFileFormatError() return frames
def new_json(self): self.video_list.model().clear() fd = FileDialog() fd.exec_() fd.show() dirnames = fd.selectedFiles() if not dirnames or os.path.normpath(dirnames[0]) == os.path.normpath( fd.directory().absolutePath()): return for project_dir in dirnames: only_files = [ join(project_dir, f) for f in listdir(project_dir) if isfile(join(project_dir, f)) ] json_paths = [f for f in only_files if f[-5:] == '.json'] if not json_paths: qtutil.critical( "Not a project directory. No JSON file found in " + project_dir + ". Skipping.") continue self.project_list = self.project_list + [Project(project_dir)] for project in self.project_list: for f in project.files: if f['type'] != 'video': continue self.video_list.model().appendRow(QStandardItem(f['name'])) self.project_at_ind = self.project_at_ind + [project] self.video_list.setCurrentIndex(self.video_list.model().index( 0, 0))
def load_state(self): filenames = QFileDialog.getOpenFileNames( self, 'Load images', QSettings().value('last_vis_path'), 'visualization window pickle (*.pkl)')[0] if not filenames: return QSettings().setValue('last_vis_path', os.path.dirname(filenames[0])) for filename in filenames: try: with open(filename, 'rb') as input: [video_path_to_plots_dict, state] = pickle.load(input) new_dw = DockWindowPlot(video_path_to_plots_dict, parent=self.parent, state=state, title=os.path.basename(filename)) self.parent.open_dialogs.append(new_dw) new_dw.show() new_dw.saving_state[str].connect( functools.partial(pfs.save_dock_window_to_project, self.parent, self.parent.Labels.window_type)) except: qtutil.critical(filename + " failed to open. Aborting.") return
def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setWindowTitle(APPNAME) self.setWindowFlags(Qt.Window | Qt.WindowContextHelpButtonHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) self.project = None self.current_plugin = None self.project_manager = ProjectManager(self) self.plugins = self.load_plugins() self.sidebar = Sidebar() self.setup_ui() self.setup_signals() self.enable(False) self.pipeline_model = PipelineModel() self.sidebar.pl_list.setModel(self.pipeline_model) self.pipeconf.pipeline_list.setModel(self.pipeline_model) last = str(QSettings().value('path_of_last_project')) if last: quit_msg = "Load last project " + last + " ?" reply = QMessageBox.question(self, 'Project Setup', quit_msg, QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: if last: try: self.open_project(last) except: qtutil.critical('Previous project appears to have been corrupted.\n \n' + traceback.format_exc(), self) #qtutil.critical("Previous project appears to have been corrupted. Please move or delete it.") self.sidebar.setup_sidebar_values(self.project)
def connectivity_triggered(self): cm_type = self.cm_comboBox.currentText() progress = QProgressDialog('Generating Correlation Matrix...', 'Abort', 0, 100, self) progress.setAutoClose(True) progress.setMinimumDuration(0) def callback(x): progress.setValue(x * 100) QApplication.processEvents() indexes = self.roi_list.selectionModel().selectedIndexes() roinames = [index.data(Qt.DisplayRole) for index in indexes] rois = [self.view.vb.getRoi(roiname) for roiname in roinames] if not self.view.vb.img: qtutil.critical('Select video.') elif not rois: qtutil.critical('Select Roi(s).') else: win = ConnectivityDialog(self, roinames, cm_type, progress_callback=callback) win.resize(900, 900) callback(1) # self.open_dialogs.append(win) # todo: add matrices to docks dock_window = DockWindowMat(win, parent=self) self.open_dialogs.append(dock_window) dock_window.show() self.save_open_dialogs_to_csv()
def sub_clicked(self): summed_filesize = 0 for path in self.selected_videos: summed_filesize = summed_filesize + os.path.getsize(path) available = list(psutil.virtual_memory())[1] if summed_filesize > available: qtutil.critical("Not enough memory. Total is of size "+str(summed_filesize) +\ " and available memory is: " + str(available)) raise MemoryError("Not enough memory. Total is of size "+str(summed_filesize) +\ " and available memory is: " + str(available)) paths = self.selected_videos if len(paths) != 2: qtutil.warning('Select two files to subtract.') return frames = [file_io.load_file(f) for f in paths] min_len = min([len(f) for f in frames]) frames = np.subtract(np.array(frames[0][0:min_len], dtype=np.float32), np.array(frames[1][0:min_len], dtype=np.float32)) frames = np.array(frames, dtype=np.float32) # First one has to take the name otherwise pfs.save_projects doesn't work manip = 'channel_sub' pfs.save_project(paths[0], self.project, frames, manip, 'video') 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 __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setWindowTitle(APPNAME) self.setWindowFlags(Qt.Window | Qt.WindowContextHelpButtonHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) self.project = None self.current_plugin = None self.project_manager = ProjectManager(self) self.plugins = self.load_plugins() self.sidebar = Sidebar() self.setup_ui() self.setup_signals() self.enable(False) self.pipeline_model = PipelineModel() self.sidebar.pl_list.setModel(self.pipeline_model) self.pipeconf.pipeline_list.setModel(self.pipeline_model) last = str(QSettings().value('path_of_last_project')) if last: quit_msg = "Load last project " + last + " ?" reply = QMessageBox.question(self, 'Project Setup', quit_msg, QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: if last: try: self.open_project(last) except: qtutil.critical('Previous project appears to have been corrupted.\n \n' + traceback.format_exc(), self) #qtutil.critical("Previous project appears to have been corrupted. Please move or delete it.") self.sidebar.setup_sidebar_values(self.project)
def remove_clicked(self): rows = self.table.selectionModel().selectedRows() if not rows: return fileinfos = [self.table.model().get_entry(row) for row in rows] for fileinfo in fileinfos: #fileinfo = self.table.model().get_entry(row) dialog = RemoveDialog(fileinfo, self) dialog.exec_() if not dialog.action: return if dialog.action == 'remove': try: os.remove(fileinfo['path']) except: qtutil.critical('Could not delete file.') return # detach self.project.files[:] = [ f for f in self.project.files if f['path'] != fileinfo['path'] ] self.project.save() self.reload_plugins.emit() self.update(self.project)
def export_raw(self, filepath, filename, export_dtype): frames = file_io.load_file(filepath) frames = frames.astype(export_dtype) try: frames.tofile(filename) except: qtutil.critical(filename + ' could not be written. Ensure that export dtype is properly set. ' 'This fixes this issue in most cases.', self)
def save_state(self): save_loc = super().save_state() with open(save_loc, 'rb') as input: state = pickle.load(input) try: with open(save_loc, 'wb') as output: pickle.dump([self.video_path_to_plots_dict, state], output, -1) except: qtutil.critical(save_loc + " failed to save.") return
def convert_tif(self, filename): rescale_value = float(self.scale_factor.value()) channel = int(self.channel.value()) new_filename = os.path.basename(filename)[:-4] new_filename = os.path.join(self.project.path, new_filename) + '.npy' if os.path.isfile(new_filename): i = 1 path_after = new_filename while os.path.isfile(path_after): name_after = new_filename[:-4] + '(' + str(i) + ')' + '.npy' path_after = os.path.join(self.project.path, name_after) i = i + 1 path = path_after else: path = os.path.splitext(os.path.basename(filename))[0] + '.npy' path = os.path.join(self.project.path, path) progress = QProgressDialog('Converting tif to npy...', 'Abort', 0, 100, self) progress.setAutoClose(True) progress.setMinimumDuration(0) progress.setValue(0) def callback(value): progress.setValue(int(value * 100)) QApplication.processEvents() try: fileconverter.tif2npy(filename, path, callback) except: qtutil.critical('Converting tiff to npy failed.') progress.close() else: ret_filename = path with tiff.TiffFile(filename) as tif: if rescale_value != 1.00: w, h = tif[0].shape rescale_width = int(w * rescale_value) rescale_height = int(h * rescale_value) no_frames = len(tif) unscaled = np.load(path) try: scaled = self.bin_ndarray( unscaled, (no_frames, rescale_height, rescale_width), callback, operation='mean') np.save(path, scaled) except: qtutil.critical( 'Rebinning tiff failed. We can only scale down from larger sized files to preserve data' ) progress.close() return ret_filename
def convert_coord_to_numpy_reference(self, coord, dim): assert (dim == 'x' or dim == 'y') if not self.project['origin']: qtutil.critical("No origin set for project") return pix_per_mm = 1 / self.project['unit_per_pixel'] coord_pix = coord * pix_per_mm if dim == 'x': return self.project['origin'][0] + coord_pix else: return self.project['origin'][1] + coord_pix
def setData(self, index, value, role): if role == Qt.EditRole: value = str(value) if value in self.rois[index.row()]: pass elif value in self.rois: qtutil.critical('Roi name taken.') else: self.textChanged.emit(self.rois[index.row()], value) self.rois[index.row()] = value return True return super(RoiItemModel, self).setData(index, value, role)
def save_state(self): save_loc = super().save_state() with open(save_loc, 'rb') as input: state = pickle.load(input) try: with open(save_loc, 'wb') as output: pickle.dump([self.connectivity_dialog.model._data, self.connectivity_dialog.model.roinames, self.connectivity_dialog.selected_image_stacks, state], output, -1) except: qtutil.critical(save_loc + " failed to save.") return
def set_shifts(self): [reference_frame, not_reference_frames] = self.get_alignment_inputs() if len(not_reference_frames) != 1: qtutil.critical("Please select only one file to align to the reference frame to set the shift. Only one " "file for setting shifts is supported for now") return frame_to_shift = file_io.load_file(not_reference_frames[0], segment=[self.ref_no.value(), self.ref_no.value()+1]) shift = self.compute_shift(reference_frame, frame_to_shift[0]) self.tvec_x_sb.setValue(shift['tvec'][1]) # [Y,X] not [X,Y] self.tvec_y_sb.setValue(shift['tvec'][0]) self.rotation_sb.setValue(shift['angle']) self.scale_sb.setValue(shift['scale'])
def remove_clicked(self): for path in self.selected_videos: norm_path = os.path.normpath(path) self.project.files[:] = [f for f in self.project.files if os.path.normpath(f['path']) != norm_path] self.project.save() for path in self.selected_videos: try: os.remove(path) except: qtutil.critical('Could not delete file ' + path) return pfs.refresh_list(self.project, self.video_list, self.video_list_indices, self.Defaults.list_display_type, self.toolbutton_values)
def import_files(self, filenames): for filename in filenames: if filename in [f['path'] for f in self.project.files]: continue try: filename = self.import_file(filename) except NotConvertedError: qtutil.warning('Skipping file \'{}\' since not converted.'.format(filename)) except FileAlreadyInProjectError as e: qtutil.warning('Skipping file \'{}\' since already in project.'.format(e.filename)) except: qtutil.critical('Import of \'{}\' failed:\n'.format(filename) +\ traceback.format_exc()) else: self.listview.model().appendRow(QStandardItem(filename))
def import_files(self, filenames): imported_paths = [] for filename in filenames: if filename in [f['path'] for f in self.project.files]: continue try: imported_path = self.import_file(filename) except NotConvertedError: qtutil.warning('Skipping file \'{}\' since not converted.'.format(filename)) except: qtutil.critical('Import of \'{}\' failed:\n'.format(filename) +\ traceback.format_exc()) else: self.listview.model().appendRow(QStandardItem(imported_path)) imported_paths = imported_paths + [imported_path] return imported_paths
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 load_state(self): filenames = QFileDialog.getOpenFileNames( self, 'Load images', QSettings().value('last_vis_path'), 'visualization window pickle (*.pkl)') if not filenames: return QSettings().setValue('last_vis_path', os.path.dirname(filenames[0])) for filename in filenames: try: with open(filename, 'rb') as input: state = pickle.load(input) new_dw = DockWindow(state, os.path.basename(filename)) new_dw.show() except: qtutil.critical(filename + " failed to open. Aborting.") return return filenames
def export_avi(self, filepath, filename, export_dtype, export_framerate): progress = MyProgressDialog('File Exporter', 'Writing to avi...', self) try: frames = file_io.load_file(filepath) frames = frames.astype(export_dtype) video = cv2.VideoWriter( filename, cv2.VideoWriter_fourcc(*'DIVX'), export_framerate, (frames.shape[1], frames.shape[2]), False ) for i, frame in enumerate(frames): progress.setValue(100 * i / float(len(frames)-1)) video.write(frame) cv2.destroyAllWindows() video.release() except: progress.close() qtutil.critical(filename + ' could not be written. Ensure that dtype and framerate are properly set above. ' 'This fixes this issue in most cases.', self)
def export_avi(self, filepath, filename): progress = MyProgressDialog('File Exporter', 'Writing to avi...', self) try: frames = fileloader.load_file(filepath) if frames.dtype != np.uint8: frames = frames.astype(np.uint8) # todo: 30 = export framerate needs to be user-decided video = cv2.VideoWriter( filename, cv2.VideoWriter_fourcc(*'DIVX'), 30, (frames.shape[1], frames.shape[2]), False ) for i, frame in enumerate(frames): progress.setValue(100 * i / float(len(frames)-1)) video.write(frame) cv2.destroyAllWindows() video.release() except: progress.close() qtutil.critical('Video file could not be written.', self)
def open_project(self, path=''): if not path: dialog = QFileDialog(self.mainwindow, 'Select project location', str(QSettings().value('projects_path'))) dialog.setFileMode(QFileDialog.Directory) dialog.setOption(QFileDialog.DontUseNativeDialog) dialog.setOption(QFileDialog.ShowDirsOnly, True) if dialog.exec_(): path = str(dialog.selectedFiles()[0]) if path: if not os.path.isfile(os.path.join(path, 'mbeproject.json')): qtutil.critical('Directory is not a project.') return None parent = os.path.abspath(os.path.join(path, os.pardir)) QSettings().setValue('projects_path', parent) if os.path.isdir(path) and os.path.isfile(os.path.join(path, 'mbeproject.json')): return self.redefine_paths(Project(path)) else: return None
def import_files(self, filenames): for filename in filenames: if filename in [f['path'] for f in self.project.files]: continue try: filename = self.import_file(filename) except NotConvertedError: qtutil.warning( 'Skipping file \'{}\' since not converted.'.format( filename)) except FileAlreadyInProjectError as e: qtutil.warning( 'Skipping file \'{}\' since already in project.'.format( e.filename)) except: qtutil.critical('Import of \'{}\' failed:\n'.format(filename) + \ traceback.format_exc()) else: self.listview.model().appendRow(QStandardItem(filename))
def load_state(self): filenames = QFileDialog.getOpenFileNames( self, 'Load images', QSettings().value('last_vis_path'), 'visualization window pickle (*.pkl)') if not filenames: return QSettings().setValue('last_vis_path', os.path.dirname(filenames[0])) for filename in filenames: try: with open(filename, 'rb') as input: [video_path_to_plots_dict, state] = pickle.load(input) new_dw = DockWindowPlot(video_path_to_plots_dict, parent=self.parent, state=state, title=os.path.basename(filename)) self.parent.open_dialogs.append(new_dw) new_dw.show() new_dw.saving_state[str].connect(functools.partial(pfs.save_dock_window_to_project, self.parent, self.parent.Labels.window_type)) except: qtutil.critical(filename + " failed to open. Aborting.") return
def execute_primary_function(self, input_paths=None): if not input_paths: if not self.selected_videos: return else: selected_videos = self.selected_videos else: selected_videos = input_paths summed_filesize = 0 for path in self.selected_videos: summed_filesize = summed_filesize + os.path.getsize(path) available = list(psutil.virtual_memory())[1] if summed_filesize > available: qtutil.critical("Not enough memory. Concatenated file is of size ~"+str(summed_filesize) +\ " and available memory is: " + str(available)) raise MemoryError("Not enough memory. Concatenated file is of size ~"+str(summed_filesize) +\ " and available memory is: " + str(available)) paths = selected_videos if len(paths) < 2: qtutil.warning('Select multiple files to concatenate.') return frames = [file_io.load_file(f) for f in paths] progress = MyProgressDialog('Concatenation', 'Concatenating files...', self) progress.show() progress.setValue(1) frames = np.concatenate(frames) progress.setValue(99) # First one has to take the name otherwise pfs.save_projects doesn't work filenames = [os.path.basename(path) for path in paths] manip = 'concat-' + str(len(filenames)) output_path = pfs.save_project(paths[0], self.project, frames, manip, 'video') 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]) progress.close() return [output_path]
def load_state(self): filenames = QFileDialog.getOpenFileNames( self, 'Load matrix', QSettings().value('last_vis_path'), 'visualization window pickle (*.pkl)')[0] if not filenames: return QSettings().setValue('last_vis_path', os.path.dirname(filenames[0])) for filename in filenames: try: with open(filename, 'rb') as input: [mat_data, roinames, selected_image_stacks, state] = pickle.load(input) cm_type = self.parent.cm_comboBox.currentText() win = ConnectivityDialog(self.parent, roinames, cm_type, mat_data) new_dw = DockWindowMat(win, parent=self.parent, state=state, title=os.path.basename(filename)) self.parent.open_dialogs.append(new_dw) new_dw.show() new_dw.saving_state[str].connect(functools.partial(pfs.save_dock_window_to_project, self.parent, self.parent.Defaults.window_type)) except: qtutil.critical(filename + " failed to open. Aborting.") return
def load_state(self): filenames = QFileDialog.getOpenFileNames( self, 'Load matrix', QSettings().value('last_vis_path'), 'visualization window pickle (*.pkl)') if not filenames: return QSettings().setValue('last_vis_path', os.path.dirname(filenames[0])) for filename in filenames: try: with open(filename, 'rb') as input: [mat_data, roinames, selected_image_stacks, state] = pickle.load(input) cm_type = self.parent.cm_comboBox.currentText() win = ConnectivityDialog(self.parent, roinames, cm_type, mat_data) new_dw = DockWindowMat(win, parent=self.parent, state=state, title=os.path.basename(filename)) self.parent.open_dialogs.append(new_dw) new_dw.show() new_dw.saving_state[str].connect(functools.partial(pfs.save_dock_window_to_project, self.parent, self.parent.Defaults.window_type)) except: qtutil.critical(filename + " failed to open. Aborting.") return
def convert_raw(self, filename): rescale_value = float(self.scale_factor.value()) dtype = str(self.cb_dtype.currentText()) width = int(self.sb_width.value()) height = int(self.sb_height.value()) rescale_width = int(width * rescale_value) rescale_height = int(height * rescale_value) channels = int(self.sb_channel.value()) channel = int(self.channel.value()) path = os.path.splitext(os.path.basename(filename))[0] + '_channel_' + str(channel) + '.npy' path = os.path.join(self.project.path, path) progress = QProgressDialog('Converting raw to npy...', 'Abort', 0, 100, self) progress.setAutoClose(True) progress.setMinimumDuration(0) progress.setValue(0) def callback(value): progress.setValue(int(value * 100)) QApplication.processEvents() try: fileconverter.raw2npy(filename, path, dtype, width, height, channels, channel, callback) except: qtutil.critical('Converting raw to npy failed.') progress.close() else: ret_filename = path if rescale_value != 1.00: unscaled = np.load(path) no_frames = len(unscaled) try: scaled = self.bin_ndarray(unscaled, (no_frames, rescale_height, rescale_width), callback, operation='mean') np.save(path, scaled) except: qtutil.critical('Rebinning raw failed. We can only scale down from larger sized files to preserve data') progress.close() return ret_filename
def compute_ref_frame(self): if not self.selected_videos: qtutil.critical("No files selected") return if len(self.selected_videos) > 1: qtutil.critical( "Select only one file to compute the reference frame from") return if 'ref_frame' in self.selected_videos[0]: qtutil.critical( "Cannot compute reference frame of reference frame") return # find size, assuming all files in project have the same size ref_no_min = self.ref_no_min.value() ref_no_max = self.ref_no_max.value() frames_mmap = np.load(self.shown_video_path, mmap_mode='c') reference_frame_range = np.array(frames_mmap[ref_no_min:ref_no_max]) ref_frames = self.spatial_filter(reference_frame_range) ref_frames = self.crop_border(ref_frames) if not ref_frames.any(): return self.reference_frame = np.mean(ref_frames, axis=0, dtype=np.float32) frames_mmap = np.load(self.shown_video_path, mmap_mode='c') frame_no, h, w = frames_mmap.shape self.reference_frame = np.reshape(self.reference_frame, (1, h, w)) pfs.save_project(self.selected_videos[0], self.project, self.reference_frame, 'ref_frame', 'ref_frame') 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 div_clicked(self): summed_filesize = 0 for path in self.selected_videos: summed_filesize = summed_filesize + os.path.getsize(path) available = list(psutil.virtual_memory())[1] if summed_filesize > available: qtutil.critical("Not enough memory. Total is of size "+str(summed_filesize) +\ " and available memory is: " + str(available)) raise MemoryError("Not enough memory. Total is of size "+str(summed_filesize) +\ " and available memory is: " + str(available)) paths = self.selected_videos if len(paths) != 2: qtutil.warning('Select 2 files to divide.') return frames = [file_io.load_file(f) for f in paths] min_len = min([len(f) for f in frames]) frames = np.divide(np.array(frames[0][0:min_len], dtype=np.float32), np.array(frames[1][0:min_len], dtype=np.float32)) if np.isinf(frames).any(): qtutil.critical("Infinite values detected. Are you sure you are dividing appropriate image stacks?") qtutil.critical('Output will appear blank. Output is too small when scaled against infinite') frames[np.isnan(frames)] = 0 # todo: is this okay? frames = np.array(frames, dtype=np.float32) # First one has to take the name otherwise pfs.save_projects doesn't work manip = 'channel_div' pfs.save_project(paths[0], self.project, frames, manip, 'video') 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 get_alignment_inputs(self, input_files=None): if not input_files: filenames = self.selected_videos reference_frame_file = [path for path in filenames if self.Defaults.secondary_manip in path] else: filenames = input_files reference_frame_file = self.selected_videos if len(reference_frame_file) != 1: qtutil.critical("Please only select a single reference frame for each alignment plugin used." " Automation will now close.") raise ValueError("Please only select a single reference frame for each alignment plugin used") if len(reference_frame_file) == 0: qtutil.critical("No reference frame selected") raise ValueError("No reference frame selected") if len(reference_frame_file) > 1: qtutil.critical("Multiple reference frames selected. Please only pick one") raise ValueError("Multiple reference frames selected. Please only pick one") assert(len(reference_frame_file) == 1) reference_frame_file = reference_frame_file[0] assert ('ref_frame' in reference_frame_file) reference_frame = np.load(reference_frame_file)[0] not_reference_frames = [path for path in filenames if self.Defaults.secondary_manip not in path] return [reference_frame, not_reference_frames]
def compute_ref_frame(self): if not self.selected_videos: qtutil.critical("No files selected") return if len(self.selected_videos) > 1: qtutil.critical("Select only one file to compute the reference frame from") return if 'ref_frame' in self.selected_videos[0]: qtutil.critical("Cannot compute reference frame of reference frame") return # find size, assuming all files in project have the same size ref_no_min = self.ref_no_min.value() ref_no_max = self.ref_no_max.value() frames_mmap = np.load(self.shown_video_path, mmap_mode='c') reference_frame_range = np.array(frames_mmap[ref_no_min:ref_no_max]) ref_frames = self.spatial_filter(reference_frame_range) ref_frames = self.crop_border(ref_frames) if not ref_frames.any(): return self.reference_frame = np.mean(ref_frames, axis=0, dtype=np.float32) frames_mmap = np.load(self.shown_video_path, mmap_mode='c') frame_no, h, w = frames_mmap.shape self.reference_frame = np.reshape(self.reference_frame, (1, h, w)) pfs.save_project(self.selected_videos[0], self.project, self.reference_frame, 'ref_frame', 'ref_frame') 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 open_project(self, path=''): if not path: dialog = QFileDialog(self.mainwindow, 'Select project location', str(QSettings().value('projects_path'))) dialog.setFileMode(QFileDialog.Directory) dialog.setOption(QFileDialog.DontUseNativeDialog) dialog.setOption(QFileDialog.ShowDirsOnly, True) if dialog.exec_(): path = str(dialog.selectedFiles()[0]) if path: if not os.path.isfile(os.path.join(path, 'mbeproject.json')): qtutil.critical('Directory is not a project.') return None parent = os.path.abspath(os.path.join(path, os.pardir)) QSettings().setValue('projects_path', parent) if os.path.isdir(path) and os.path.isfile( os.path.join(path, 'mbeproject.json')): return self.redefine_paths(Project(path)) else: return None
def connectivity_triggered(self): progress = QProgressDialog('Generating Connectivity Matrix...', 'Abort', 0, 100, self) progress.setAutoClose(True) progress.setMinimumDuration(0) def callback(x): progress.setValue(x * 100) QApplication.processEvents() indexes = self.roi_list.selectionModel().selectedIndexes() roinames = [index.data(Qt.DisplayRole) for index in indexes] rois = [self.view.vb.getRoi(roiname) for roiname in roinames] if not self.view.vb.img: qtutil.critical('Select video.') elif not rois: qtutil.critical('Select Roi(s).') else: win = ConnectivityDialog(self.selected_videos, self.view.vb.img, rois, self.cm_type, self, callback) callback(1) win.show() self.open_dialogs.append(win)
def convert_tif(self, filename): rescale_value = float(self.scale_factor.value()) #channel = int(self.channel.value()) path = os.path.splitext(os.path.basename(filename))[0] + '.npy' path = os.path.join(self.project.path, path) progress = QProgressDialog('Converting tif to npy...', 'Abort', 0, 100, self) progress.setAutoClose(True) progress.setMinimumDuration(0) progress.setValue(0) def callback(value): progress.setValue(int(value * 100)) QApplication.processEvents() try: fileconverter.tif2npy(filename, path, callback) except: qtutil.critical('Converting tiff to npy failed.') progress.close() else: ret_filename = path with tiff.TiffFile(filename) as tif: if rescale_value != 1.00: w, h = tif[0].shape rescale_width = int(w * rescale_value) rescale_height = int(h * rescale_value) no_frames = len(tif) unscaled = np.load(path) try: scaled = self.bin_ndarray(unscaled, (no_frames, rescale_height, rescale_width), callback, operation='mean') np.save(path, scaled) except: qtutil.critical('Rebinning tiff failed. We can only scale down from larger sized files to preserve data') progress.close() return ret_filename
def save_file(path, data): file_size = data.nbytes available = list(psutil.virtual_memory())[1] percent = list(psutil.virtual_memory())[2] # [total, available, percent, used, free, active, inactive, buffers, cached, shared] = list(psutil.virtual_memory()) if file_size > available: qtutil.critical('Memory warning. File is of size ' + str(file_size) + ' and available memory is: ' + str(available)) # del_msg = path + " might not be saved due to insufficient memory. " \ # "If you attempt to save it, it may cause system instability. If you do abort then this file" \ # "will be lost. Note that only this one file will be lost. Proceed?" # reply = QMessageBox.question(widget, 'File Save Error', # del_msg, QMessageBox.Yes, QMessageBox.No) # if reply == QMessageBox.No: # raise MemoryError('Not enough memory. File is of size ' + str(file_size) + # ' and available memory is: ' + str(available)) if percent > 95: qtutil.warning('Your memory appears to be getting low.') # total, used, free = psutil.disk_usage(os.path.dirname(path)) # if data.nbytes > free: # qtutil.critical('Not enough space on drive. File is of size ' + str(data.nbytes) + # ' and available space is: ' + str(free)) # raise IOError('Not enough space on drive. File is of size ' + str(data.nbytes) + # ' and available space is: ' + str(free)) if os.path.isfile(path): os.remove(path) try: # if data.dtype == 'float64': # qtutil.critical("FLOAT64") # raise MemoryError("FLOAT64") np.save(path, data) except: qtutil.critical( 'Could not save ' + path + '. This is likely due to running out of space on the drive')
def get_video_path_to_plots_dict(self): '''Collect ROI activities for each selected vid''' indexes = self.roi_list.selectionModel().selectedIndexes() roinames = [index.data(Qt.DisplayRole) for index in indexes] rois = [self.view.vb.getRoi(roiname) for roiname in roinames] video_paths = self.selected_videos image = self.view.vb.img if not rois: qtutil.critical("No ROI selected.") return if not video_paths: qtutil.critical("No image stack selected") return progress_load = QProgressDialog( 'Loading files and collecting ROI data. This may take a while ' 'for large files.', 'Abort', 0, 100) progress_load.setAutoClose(True) progress_load.setMinimumDuration(0) def callback_load(x): progress_load.setValue(x * 100) QApplication.processEvents() video_path_to_plots_dict = {} for i, video_path in enumerate(video_paths): callback_load(i / len(video_paths)) if progress_load.wasCanceled(): return frames = file_io.load_file(video_path) roi_activity_dict = {} for j, roi in enumerate(rois): mask = roi.getROIMask(frames, image, axes=(1, 2)) size = np.count_nonzero(mask) if size <= 0: qtutil.critical( "No ROI selected. If you do have ROIs selected then the most likely cause is that " "you have modified the unit per pixel and not updated the size of the ROIs which " "don't adjust automatically. So for example any ROI with length 1 might now be less " "than 1 pixel after you changed the unit per pixel. To update the ROIs against your " "new unit per pixel, go to the import ROI plugin and press the 'Update Table' button" ) return roi_frames = frames * mask[np.newaxis, :, :] roi_frames = np.ndarray.sum(np.ndarray.sum(roi_frames, axis=1), axis=1) p = roi_frames / size roi_activity_dict[roi.name] = p video_path_to_plots_dict[video_path] = roi_activity_dict callback_load(1) return video_path_to_plots_dict
def get_video_path_to_spc_dict(self): # retrieve ROIs in view and their coordinates if 'roi_table' not in [self.project.files[x]['type'] for x in range(len(self.project.files))]: qtutil.critical("There's no ROI table associated with this project. " "ROIs coordinates are used as seeds to create seed pixel correlation maps") return text_file_path = [self.project.files[x]['path'] for x in range(len(self.project.files)) if self.project.files[x]['type'] == 'roi_table'] assert (len(text_file_path) == 1) text_file_path = text_file_path[0] roi_table = [] with open(text_file_path, 'rt', encoding='ascii') as csvfile: roi_table_it = csv.reader(csvfile, delimiter=',') for row in roi_table_it: roi_table = roi_table + [row] roi_table = np.array(roi_table) roi_table_range = range(len(roi_table))[1:] roi_names = [roi_table[x, 0] for x in roi_table_range] roi_coord_x = [float(roi_table[x, 2]) for x in roi_table_range] roi_coord_y = [float(roi_table[x, 3]) for x in roi_table_range] roi_coord_x = [self.convert_coord_to_numpy_reference(x, 'x') for x in roi_coord_x] roi_coord_y = [self.convert_coord_to_numpy_reference(y, 'y') for y in roi_coord_y] rois_in_view = [self.view.vb.rois[x].name for x in range(len(self.view.vb.rois))] selected_videos = self.selected_videos if not rois_in_view: qtutil.critical("No ROI(s) selected as seed(s)") return if not selected_videos: qtutil.critical("No image stack selected") return progress_load = MyProgressDialog('Processing...', 'Loading files and processing Seed Pixel Correlation maps. ' 'This may take a while for large files.', parent=self) video_path_to_plots_dict = {} progress = MyProgressDialog('SPC Map', 'Generating correlation map...', self) for selected_vid_no, video_path in enumerate(selected_videos): frames = file_io.load_file(video_path) roi_activity_dict = {} for i, roi_name in enumerate(roi_names): if progress_load.wasCanceled(): return progress_load.setValue((selected_vid_no * i) / (len(selected_videos) * len(roi_names)) * 100) if roi_name in rois_in_view: x = roi_coord_x[i] y = roi_coord_y[i] spc = calc_spc(frames, x, y, progress) roi_activity_dict[roi_name] = spc video_path_to_plots_dict[video_path] = roi_activity_dict progress.close() progress_load.close() return video_path_to_plots_dict
def get_video_path_to_plots_dict(self): '''Collect ROI activities for each selected vid''' indexes = self.roi_list.selectionModel().selectedIndexes() roinames = [index.data(Qt.DisplayRole) for index in indexes] rois = [self.view.vb.getRoi(roiname) for roiname in roinames] video_paths = self.selected_videos image = self.view.vb.img if not rois: qtutil.critical("No ROI selected.") return if not video_paths: qtutil.critical("No image stack selected") return progress_load = QProgressDialog('Loading files and collecting ROI data. This may take a while ' 'for large files.', 'Abort', 0, 100) progress_load.setAutoClose(True) progress_load.setMinimumDuration(0) def callback_load(x): progress_load.setValue(x * 100) QApplication.processEvents() video_path_to_plots_dict = {} for i, video_path in enumerate(video_paths): callback_load(i / len(video_paths)) if progress_load.wasCanceled(): return frames = file_io.load_file(video_path) roi_activity_dict = {} for j, roi in enumerate(rois): mask = roi.getROIMask(frames, image, axes=(1, 2)) size = np.count_nonzero(mask) if size <= 0: qtutil.critical("No ROI selected. If you do have ROIs selected then the most likely cause is that " "you have modified the unit per pixel and not updated the size of the ROIs which " "don't adjust automatically. So for example any ROI with length 1 might now be less " "than 1 pixel after you changed the unit per pixel. To update the ROIs against your " "new unit per pixel, go to the import ROI plugin and press the 'Update Table' button") return roi_frames = frames * mask[np.newaxis, :, :] roi_frames = np.ndarray.sum(np.ndarray.sum(roi_frames, axis=1), axis=1) p = roi_frames / size roi_activity_dict[roi.name] = p video_path_to_plots_dict[video_path] = roi_activity_dict callback_load(1) return video_path_to_plots_dict
def go(self): path = str(self.final_path_edit.text()) if not path: qtutil.critical('Choose project location.') elif os.path.isdir(path): qtutil.critical('Directory already exists.') else: try: os.makedirs(path) except Exception: qtutil.critical(traceback.format_exc()) else: self.path = path self.name = str(self.project_name_edit.text()) self.close() return self.path = None self.name = None
def div_clicked(self): summed_filesize = 0 for path in self.selected_videos: summed_filesize = summed_filesize + os.path.getsize(path) available = list(psutil.virtual_memory())[1] if summed_filesize > available: qtutil.critical("Not enough memory. Total is of size "+str(summed_filesize) +\ " and available memory is: " + str(available)) raise MemoryError("Not enough memory. Total is of size "+str(summed_filesize) +\ " and available memory is: " + str(available)) paths = self.selected_videos if len(paths) != 2: qtutil.warning('Select 2 files to divide.') return frames = [file_io.load_file(f) for f in paths] min_len = min([len(f) for f in frames]) frames = np.divide(np.array(frames[0][0:min_len], dtype=np.float32), np.array(frames[1][0:min_len], dtype=np.float32)) if np.isinf(frames).any(): qtutil.critical( "Infinite values detected. Are you sure you are dividing appropriate image stacks?" ) qtutil.critical( 'Output will appear blank. Output is too small when scaled against infinite' ) frames[np.isnan(frames)] = 0 # todo: is this okay? frames = np.array(frames, dtype=np.float32) # First one has to take the name otherwise pfs.save_projects doesn't work manip = 'channel_div' pfs.save_project(paths[0], self.project, frames, manip, 'video') 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 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 load_ROI_table(self, text_file_path=None): if not self.isActiveWindow(): return if not text_file_path: text_file_path = QFileDialog.getOpenFileName( self, 'Load images', QSettings().value('last_load_text_path'), 'Video files (*.csv *.txt)') if not text_file_path: return QSettings().setValue('last_load_text_path', os.path.dirname(text_file_path)) self.text_file_path = text_file_path # Remove all ROI's from list rois = [r for r in self.roi_list.model().rois] for roi in rois: self.roi_list.model().removeRow(roi) # Delete all auto_ROIs from file for auto_roi in [fileinfo for fileinfo in self.project.files if fileinfo['type'] == 'auto_roi']: try: os.remove(auto_roi['path']) except: qtutil.critical('Could not delete previous ROI ' + auto_roi['path'] + '. Please delete manually before continuing') return # detach self.project.files[:] = [ f for f in self.project.files if f['path'] != auto_roi['path'] ] self.project.save() roi_table = [] # numpy way: np.empty(shape=(4, )) with open(text_file_path, 'rt', encoding='ascii') as csvfile: roi_table_it = csv.reader(csvfile, delimiter=',') for row in roi_table_it: roi_table = roi_table + [row] roi_table = np.array(roi_table) self.headers = [str.strip(x) for x in roi_table[0, ]] roi_table_range = range(len(roi_table))[1:] roi_names = [str(roi_table[x, 0]) for x in roi_table_range] roi_sizes = [int(roi_table[x, 1]) for x in roi_table_range] roi_coord_x = [float(roi_table[x, 2]) for x in roi_table_range] roi_coord_y = [float(roi_table[x, 3]) for x in roi_table_range] self.data = {self.headers[0]: roi_names, self.headers[1]: roi_sizes, self.headers[2]: roi_coord_x, self.headers[3]: roi_coord_y} text_file_path_for_project = os.path.join(self.project.path, os.path.basename(text_file_path)) # for now only support having one roi_table associated per project if 'roi_table' not in [self.project.files[x]['type'] for x in range(len(self.project.files))]: # if text_file_path not in [self.project.files[x]['path'] for x in range(len(self.project.files))]: try: copyfile(text_file_path, text_file_path_for_project) except: qtutil.critical('Could not copy ' + text_file_path + ' to ' + text_file_path_for_project + '. Please do this manually and try again') self.project.files.append({ 'path': text_file_path_for_project, 'type': 'roi_table', 'name': os.path.basename(text_file_path) }) else: # Replace old table with new one if not (os.path.normpath(text_file_path) == os.path.normpath(text_file_path_for_project)): try: copyfile(text_file_path, text_file_path_for_project) except: qtutil.critical('Could not copy ' + text_file_path + ' to ' + text_file_path_for_project + '. Please do this manually and try again') for i, item in enumerate(self.project.files): if item['type'] == 'roi_table': self.project.files[i] = { 'path': text_file_path_for_project, 'type': 'roi_table', 'name': os.path.basename(text_file_path) } self.table_widget.clear() self.table_widget.setRowCount(len(self.data[self.headers[0]])) self.table_widget.update(self.data) self.auto_ROI()
def plot_triggered(self): # main_window = QMainWindow() # area = self.setup_docks() # main_window.setCentralWidget(area) # main_window.resize(2000, 900) # main_window.setWindowTitle("Window ID - " + str(uuid.uuid4()) + # ". Click Shift+F1 for help") # main_window.setWhatsThis("Use View All to reset a view\n" # "\n" # "The blue tabs have the name of the ROI for a particular plot. These tabs can be dragged " # "around to highlighted regions to the side of other tabs to split the dock or on top of " # "other plots to place the tab in that dock. \n" # "\n" # "right click any plot to see more options. One important one is mouse mode. In Mouse " # "mode 3 you can hold the left mouse button to pan and " # "In mouse mode 1 you can zoom in on a particular region by creating cropping it with the " # "left mouse button. In either mode the right mouse button can be used to adjust the shape " # "of the plot and the mouse wheel for zoom \n" # "\n" # "Use Export to save a particular plot's data to csv or save as an image after you are " # "satisfied with how graphical elements (see 'plot options') are arranged. " # "Note that backups csv's of all plots are made automatically and can be found in your " # "project directory") video_path_to_plots_dict = self.get_video_path_to_plots_dict() if len(video_path_to_plots_dict.keys()) == 1: # area = DockArea() # d1 = Dock("d1", size=(500, 200), closable=True) # area.addDock(d1) video_path = list(video_path_to_plots_dict.keys())[0] plot_title, ext = os.path.splitext(video_path) # d = Dock(video_path, size=(500, 200), closable=True) # area.addDock(d, 'above', area.docks['d1']) win = pg.GraphicsWindow(title="Single Image Stack Plot") plot = win.addPlot(title=plot_title) plot.setLabel('bottom', "Image Frames") plot.setLabel('left', "Activity") plot.addLegend() roi_names = list(video_path_to_plots_dict[video_path].keys()) warning_issued = False for i, roi_name in enumerate(roi_names): p = video_path_to_plots_dict[video_path][roi_name] if i < len(brewer_colors): color = brewer_colors[i].rgb else: if not warning_issued: qtutil.warning('Perceptual distinctiveness limit (12) reached. Resorting to Kelly colours. ' 'Please be careful with how you interpret your data') warning_issued = True if i < len(brewer_colors) + len(kelly_colors): color = kelly_colors[i - len(brewer_colors)].rgb else: qtutil.critical( 'Colour limit reached. Outputting to csv instead.') # Save plot to file (backup) ps = [list(p) for p in list(video_path_to_plots_dict[video_path].values())] ps_rows = list(zip(*ps)) plot_out = os.path.join(os.path.dirname(video_path), roi_name + '_plots.csv') with open(plot_out, 'w', newline='') as csvfile: writer = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL) writer.writerow(roi_names) for i, row in enumerate(ps_rows): writer.writerow([str(p) for p in row]) plot.plot(p, pen=color, name=roi_name) self.open_dialogs.append(win) # d.addWidget(doc_window) else: # self.plot_to_docks(video_path_to_plots_dict, area) dock_window = DockWindowPlot(video_path_to_plots_dict, parent=self) dock_window.show() self.open_dialogs.append(dock_window)