def __init__(self, model, main_controller): super().__init__() self._model = model self._main_controller = main_controller self._ui = Ui_MainWindow() self._ui.setupUi(self) # connect ui-widget to controller # if ui changes, it sends a signal to an slot on which we connect a controller class. # therefore we can recive the signal in the controller self._ui.spinBox_amount.valueChanged.connect( self._main_controller.change_amount) # Lambda to execute function with value self._ui.pushButton_reset.clicked.connect( lambda: self._main_controller.change_amount(0)) self._ui.pushButton_add.clicked.connect( lambda: self._main_controller.add_user(self._ui.lineEdit_name.text( ))) self._ui.pushButton_delete.clicked.connect( lambda: self._main_controller.delete_user(self._ui.listWidget_names .currentRow())) # listen for model event signals # connect the method to update the ui to the slots of the model # if model sends/emits a signal the ui gets notified self._model.amount_changed.connect(self.on_amount_changed) self._model.even_odd_changed.connect(self.on_even_odd_changed) self._model.enable_reset_changed.connect(self.on_enable_reset_changed) self._model.users_changed.connect(self.on_list_changed) # set a default value self._main_controller.change_amount(42)
class MainView(QMainWindow): def __init__(self, model, main_controller): super().__init__() self._model = model self._main_controller = main_controller self._ui = Ui_MainWindow() self._ui.setupUi(self) # connect widgets to controller self._ui.spinBox_amount.valueChanged.connect( self._main_controller.change_amount) self._ui.pushButton_reset.clicked.connect( lambda: self._main_controller.change_amount(0)) # listen for model event signals self._model.amount_changed.connect(self.on_amount_changed) self._model.even_odd_changed.connect(self.on_even_odd_changed) self._model.enable_reset_changed.connect(self.on_enable_reset_changed) # set a default value self._main_controller.change_amount(42) @pyqtSlot(int) def on_amount_changed(self, value): self._ui.spinBox_amount.setValue(value) @pyqtSlot(str) def on_even_odd_changed(self, value): self._ui.label_even_odd.setText(value) @pyqtSlot(bool) def on_enable_reset_changed(self, value): self._ui.pushButton_reset.setEnabled(value)
def __init__(self, model, conroller): super().__init__() self._model = model self._controller = conroller self._ui = Ui_MainWindow() self._ui.setupUi(self)
class MainView(QtWidgets.QMainWindow): def __init__(self, model, conroller): super().__init__() self._model = model self._controller = conroller self._ui = Ui_MainWindow() self._ui.setupUi(self)
def __init__(self, model, main_controller): super().__init__() self._model = model self._main_controller = main_controller self._ui = Ui_MainWindow() self._ui.setupUi(self) # connect widgets to controller self._ui.spinBox_amount.valueChanged.connect(self._main_controller.change_amount) self._ui.pushButton_reset.clicked.connect(lambda: self._main_controller.change_amount(0)) # listen for model event signals self._model.amount_changed.connect(self.on_amount_changed) self._model.even_odd_changed.connect(self.on_even_odd_changed) self._model.enable_reset_changed.connect(self.on_enable_reset_changed) # set a default value self._main_controller.change_amount(42)
def __init__(self, model, main_controller): super().__init__() self._model = model self._main_controller = main_controller self._ui = Ui_MainWindow() self._ui.setupUi(self) # init dialog self._input_dialog = InputDialog(self._model, self._main_controller) # connect widgets to controller # show input dialog self._ui.openButton.clicked.connect(self._input_dialog.show) # show output dialog self._ui.saveButton.clicked.connect(self.open_save_dialog) # listen for model event signals self._model.geo_dataframe_changed.connect( self.on_geo_dataframe_changed)
class MainView(QMainWindow): def __init__(self, model, main_controller): super().__init__() self._model = model self._main_controller = main_controller self._ui = Ui_MainWindow() self._ui.setupUi(self) # init dialog self._input_dialog = InputDialog(self._model, self._main_controller) # connect widgets to controller # show input dialog self._ui.openButton.clicked.connect(self._input_dialog.show) # show output dialog self._ui.saveButton.clicked.connect(self.open_save_dialog) # listen for model event signals self._model.geo_dataframe_changed.connect( self.on_geo_dataframe_changed) @pyqtSlot(object) def on_geo_dataframe_changed(self, value): # show 100rows gdf_100_nogeom = value.head(100).drop(['geometry'], axis=1) model = PandasModel(gdf_100_nogeom) self._ui.tableView.setModel(model) # show save dialog def open_save_dialog(self): if self._model.geo_dataframe.empty: error_msg(self, 'no file to output') else: self._output_dialog = OutputDialog(self._model, self._main_controller) self._output_dialog.show()
def __init__(self, model, file_table_model, filter_table_model, main_controller, image_manager_controller, filter_controller): super().__init__() self.all_models = model self._model = model.current_image_model self._file_table_model = file_table_model self._seg_class_model = model.current_seg_model self._filter_table_model = filter_table_model self._main_controller = main_controller self._image_manager_controller = image_manager_controller self._filter_controller = filter_controller self._ui = Ui_MainWindow() self._ui.setupUi(self) self.current_image = pg.ImageItem() self.current_image.setImage(self._model.image) self._ui.graphicsView.view.addItem(self.current_image) # Default segmentation mask turned off self.segmentation_image = pg.ImageItem() self._ui.graphicsView.view.addItem(self.segmentation_image) self.segmentation_opacity = 0.0 # Default cluster mask turned off self.cluster_image = pg.ImageItem() self._ui.graphicsView.view.addItem(self.cluster_image) self.cluster_opacity = 0.0 # Settings for segmentation class table self._ui.segmentationClassList.setModel(self._seg_class_model) self._ui.segmentationClassList.setSelectionMode( QAbstractItemView.SingleSelection) self._ui.segmentationClassList.verticalHeader().setVisible(False) self._ui.segmentationClassList.horizontalHeader( ).setStretchLastSection(True) self._ui.segmentationClassList.horizontalHeader().setVisible(False) self._ui.segmentationClassList.doubleClicked.connect( self.seg_class_data_change_request) # Turns off default pyqtgraph visualization settings #self._ui.graphicsView.ui.histogram.hide() self._ui.graphicsView.ui.roiBtn.hide() self._ui.graphicsView.ui.menuBtn.hide() self._ui.graphicsView.view.setAspectLocked(True) #self._ui.graphicsView.getImageItem().mouseDragEvent = self.mouseDragEvent #self.current_image.mouseDragEvent = self.mouseDragEvent #self.segmentation_image.mouseDragEvent = self.mouseDragEvent # I heard you like connections self._model.image_changed.connect(self.on_image_change) self._model.segmentation_image_changed.connect( self.on_seg_image_change) self._ui.toggleSegmentationMaskButton.clicked.connect( self.mask_button_press) self._ui.actionImage_Manager.triggered.connect( self.launch_image_manager) self._ui.imageFileNavigatorView.currentIndexChanged.connect( self.current_image_changed) self._ui.loadAnalysisFileButton.clicked.connect( self.load_analysis_file_clicked) self._ui.filterButton.clicked.connect(self.launch_filter_manager) self._ui.AddRegionOfInterestButton.clicked.connect(self.add_roi) self._ui.RemoveRegionOfInterestButton.clicked.connect(self.delete_roi) self._ui.clusterButton.clicked.connect(self.cluster_button_press) self._ui.ToggleClusterButton.clicked.connect( self.toggle_cluster_clicked) self._image_manager_controller.change_current_image.connect( self.current_image_changed) self._image_manager_controller.image_manager_window_closed.connect( self.update_file_list) self._seg_class_model.class_table_update.connect( self._filter_table_model.class_list_changed) self._filter_controller.filters_changed.connect( self.filter_objects_from_seg_image) self._ui.ROIListView.currentRowChanged.connect(self.roi_selected) self._ui.SaveAsFilterResultsButton.clicked.connect( self.save_as_filtered_results_button_clicked) self._ui.saveMaskButton.clicked.connect(self.save_current_mask) self._current_image_index = -1
class MainView(QMainWindow): def __init__(self, model, file_table_model, filter_table_model, main_controller, image_manager_controller, filter_controller): super().__init__() self.all_models = model self._model = model.current_image_model self._file_table_model = file_table_model self._seg_class_model = model.current_seg_model self._filter_table_model = filter_table_model self._main_controller = main_controller self._image_manager_controller = image_manager_controller self._filter_controller = filter_controller self._ui = Ui_MainWindow() self._ui.setupUi(self) self.current_image = pg.ImageItem() self.current_image.setImage(self._model.image) self._ui.graphicsView.view.addItem(self.current_image) # Default segmentation mask turned off self.segmentation_image = pg.ImageItem() self._ui.graphicsView.view.addItem(self.segmentation_image) self.segmentation_opacity = 0.0 # Default cluster mask turned off self.cluster_image = pg.ImageItem() self._ui.graphicsView.view.addItem(self.cluster_image) self.cluster_opacity = 0.0 # Settings for segmentation class table self._ui.segmentationClassList.setModel(self._seg_class_model) self._ui.segmentationClassList.setSelectionMode( QAbstractItemView.SingleSelection) self._ui.segmentationClassList.verticalHeader().setVisible(False) self._ui.segmentationClassList.horizontalHeader( ).setStretchLastSection(True) self._ui.segmentationClassList.horizontalHeader().setVisible(False) self._ui.segmentationClassList.doubleClicked.connect( self.seg_class_data_change_request) # Turns off default pyqtgraph visualization settings #self._ui.graphicsView.ui.histogram.hide() self._ui.graphicsView.ui.roiBtn.hide() self._ui.graphicsView.ui.menuBtn.hide() self._ui.graphicsView.view.setAspectLocked(True) #self._ui.graphicsView.getImageItem().mouseDragEvent = self.mouseDragEvent #self.current_image.mouseDragEvent = self.mouseDragEvent #self.segmentation_image.mouseDragEvent = self.mouseDragEvent # I heard you like connections self._model.image_changed.connect(self.on_image_change) self._model.segmentation_image_changed.connect( self.on_seg_image_change) self._ui.toggleSegmentationMaskButton.clicked.connect( self.mask_button_press) self._ui.actionImage_Manager.triggered.connect( self.launch_image_manager) self._ui.imageFileNavigatorView.currentIndexChanged.connect( self.current_image_changed) self._ui.loadAnalysisFileButton.clicked.connect( self.load_analysis_file_clicked) self._ui.filterButton.clicked.connect(self.launch_filter_manager) self._ui.AddRegionOfInterestButton.clicked.connect(self.add_roi) self._ui.RemoveRegionOfInterestButton.clicked.connect(self.delete_roi) self._ui.clusterButton.clicked.connect(self.cluster_button_press) self._ui.ToggleClusterButton.clicked.connect( self.toggle_cluster_clicked) self._image_manager_controller.change_current_image.connect( self.current_image_changed) self._image_manager_controller.image_manager_window_closed.connect( self.update_file_list) self._seg_class_model.class_table_update.connect( self._filter_table_model.class_list_changed) self._filter_controller.filters_changed.connect( self.filter_objects_from_seg_image) self._ui.ROIListView.currentRowChanged.connect(self.roi_selected) self._ui.SaveAsFilterResultsButton.clicked.connect( self.save_as_filtered_results_button_clicked) self._ui.saveMaskButton.clicked.connect(self.save_current_mask) self._current_image_index = -1 def launch_image_manager(self): """ Launches ImageManagerView GUI when the "Image Manager" is selected from the File menu """ self._image_manager_view = ImageManagerView( self._file_table_model, self._image_manager_controller) self._image_manager_view.show() def launch_filter_manager(self): """ Launches FilterManagerView GUI when the "Manage Filters" button is pressed """ if self.all_models.object_data is not None: self._filter_manager_view = FilterManagerView( self._filter_table_model, self._main_controller, self._filter_controller) self._filter_manager_view.show() @pyqtSlot(list) def update_file_list(self, value): """ Detects when the image list has changed in the file table model and updates the image models accordingly. """ self._current_image_index = -1 for i in range(self._ui.imageFileNavigatorView.count(), 0, -1): self._ui.imageFileNavigatorView.removeItem(i - 1) for entry in value: filename = entry.split("/")[-1] self._ui.imageFileNavigatorView.addItem(filename) self.all_models.add_image_model(filename) self.all_models.add_seg_model(filename) @pyqtSlot(int) def current_image_changed(self, value): """ Detects when the user has selected a new image to view and updates the models accordingly """ if (self._current_image_index != self._ui.imageFileNavigatorView.currentIndex()): self.all_models.current_id = self._file_table_model._filelist[ self._ui.imageFileNavigatorView.currentIndex()] self._current_image_index = self._ui.imageFileNavigatorView.currentIndex( ) self._main_controller.update_models_from_file_table( self._file_table_model._data[self._current_image_index]) self._model.image_scale = float( self._file_table_model._data[self._current_image_index][3]) self._ui.segmentationMaskFileDisplay.setText( self._model.segmentation_label) @pyqtSlot(int) def on_image_change(self, value): """ Sets a new image to the ImageItem """ self.current_image.setImage(self._model.image) @pyqtSlot(int) def on_seg_image_change(self, value): """ Sets a new segmentation image to the ImageItem """ if self._model.has_segmentation_image: self.segmentation_image.setImage(self._model.segmentation_image, opacity=self.segmentation_opacity) def mask_button_press(self): """ Toggles the segmentation mask by changing the opacity of the segmentation image """ self.segmentation_opacity = 1 - self.segmentation_opacity self.segmentation_image.setImage(self._model.segmentation_image, opacity=self.segmentation_opacity) def seg_class_data_change_request(self): """ Detects when user wants to change the segmentation class color and notifies the main controller """ idx = self._ui.segmentationClassList.selectionModel().selectedIndexes( )[0] if idx.column() == 0: self._main_controller.change_class_color(idx.row()) def load_analysis_file_clicked(self): """ Detects when the "Load Analysis File" button is clicked and notifies the main controller to load it. Then tells the filter controller to index all of the objects in the image. """ if len(self._file_table_model._filelist) == 0: no_image_loaded_error_msg = QMessageBox(self) no_image_loaded_error_msg.setText("Can't load analysis file") no_image_loaded_error_msg.setDetailedText( "Please load image file before loading analysis file.") no_image_loaded_error_msg.show() else: [tf, filename] = self._main_controller.load_analysis_file() if (self._model.has_segmentation_image) and tf: self._filter_controller.index_objects() self._ui.analysisFileDisplay.setText(filename) def filter_objects_from_seg_image(self): self.segmentation_opacity = 0.0 self.segmentation_image.setImage(self._model.segmentation_image, opacity=self.segmentation_opacity) self.cluster_opacity = 0.0 self.cluster_image.setImage(self._model.cluster_image, opacity=self.cluster_opacity) results_index = self._filter_table_model.query_results try: results = results_index['object_id'].values except TypeError: results = self.all_models.object_data['object_id'].values self.all_models.filter_results = results_index self._main_controller.construct_seg_image_from_objectids(results) def add_roi(self): if self._model.has_segmentation_image: defaultx = self._model.segmentation_image.shape[0] / 2 defaulty = self._model.segmentation_image.shape[1] / 2 w = np.floor( np.min([ self._model.segmentation_image.shape[0] / 10, self._model.segmentation_image.shape[1] / 10 ])) roi = pg.PolyLineROI( [[defaulty - w, defaultx - w], [defaulty - w, defaultx + w], [defaulty + w, defaultx + w], [defaulty + w, defaultx - w]], closed=True, movable=True) roi.sigRegionChanged.connect(self.update_roi_list) label = "ROI_" + str(len(self.all_models.rois.keys()) + 1) self.all_models.rois[label] = [roi, self.map_roi_to_image(roi)] self._ui.ROIListView.addItem(label) self._ui.graphicsView.view.addItem(roi) self._filter_table_model.non_class_filterable_object_list.append( label) self._filter_table_model.class_list_changed([ row.label for row in self._seg_class_model._color_table.values() ]) @pyqtSlot(int) def roi_selected(self, value): if value != -1: for row in range(self._ui.ROIListView.count()): if row == self._ui.ROIListView.currentRow(): label = self._ui.ROIListView.currentItem().text() self.all_models.rois[label][0].setMouseHover(True) self.all_models.rois[label][0].sigHoverEvent.emit( self.all_models.rois[label][0]) else: label = self._ui.ROIListView.item(row).text() self.all_models.rois[label][0].setMouseHover(False) self.all_models.rois[label][0].sigHoverEvent.emit( self.all_models.rois[label][0]) def delete_roi(self): label = str( self._ui.ROIListView.takeItem( self._ui.ROIListView.currentRow()).text()) self._ui.graphicsView.view.removeItem(self.all_models.rois[label][0]) del self.all_models.rois[label][0] def map_roi_to_image(self, roi): pts = roi.getSceneHandlePositions() return [[ roi.mapSceneToParent(pt[1]).x(), roi.mapSceneToParent(pt[1]).y() ] for pt in pts] def update_roi_list(self): for key in self.all_models.rois.keys(): self.all_models.rois[key][1] = self.map_roi_to_image( self.all_models.rois[key][0]) def cluster_button_press(self): self.all_models.cluster_ids = [] if self.all_models.filter_results is not None: try: min_dist = float(self._ui.ClusterMinDist.text()) min_neighbors = int(self._ui.ClusterMinNeighbors.text()) self.all_models.filter_results = self._main_controller.cluster_objects( self.all_models.filter_results, min_dist, min_neighbors) except ValueError: print("Enter parameters for clustering") self.segmentation_opacity = 0.0 self.segmentation_image.setImage(self._model.segmentation_image, opacity=self.segmentation_opacity) self.cluster_opacity = 1.0 self.cluster_image.setImage(self._model.cluster_image, opacity=self.cluster_opacity) def toggle_cluster_clicked(self): self.cluster_opacity = 1 - self.cluster_opacity self.cluster_image.setImage(self._model.cluster_image, opacity=self.cluster_opacity) def save_as_filtered_results_button_clicked(self): filepath = self._main_controller.select_path_to_save_filter_results( self._filter_table_model.query_results, save_filter_metadata=self._ui.saveFilterMetadataCheckbox.isChecked( )) def save_current_mask(self): self._main_controller.save_current_mask()