def update_the_status_of_classification(self, sampling_layer=None): if sampling_layer is None: sampling_layer = self.QCBox_SamplingFile.currentLayer() if sampling_layer: # classification status if sampling_layer in Classification.instances: classification = Classification.instances[sampling_layer] self.QPBar_ClassificationStatus.setMaximum( classification.num_points) self.QPBar_ClassificationStatus.setValue( classification.total_classified) else: count_samples = len(list(sampling_layer.getFeatures())) self.QPBar_ClassificationStatus.setMaximum(count_samples) self.QPBar_ClassificationStatus.setValue(0) self.QPBar_ClassificationStatus.setTextVisible(True) # check if the classification is completed and update in dockwidget status if sampling_layer in Classification.instances and Classification.instances[ sampling_layer].is_completed: self.QLabel_ClassificationStatus.setText( "Classification completed") self.QLabel_ClassificationStatus.setStyleSheet( "QLabel {color: green;}") else: self.QLabel_ClassificationStatus.setText( "Classification not completed") self.QLabel_ClassificationStatus.setStyleSheet( "QLabel {color: orange;}") # grid settings if sampling_layer in Classification.instances: classification = Classification.instances[sampling_layer] with block_signals_to(self.QGBox_GridSettings): self.grid_columns.setValue(classification.grid_columns) self.grid_rows.setValue(classification.grid_rows) else: with block_signals_to(self.QGBox_GridSettings): self.grid_columns.setValue(2) self.grid_rows.setValue(1) if not ClassificationDialog.is_opened: # enable group box that depends of sampling file self.QGBox_SamplingClassification.setEnabled(True) self.QGBox_saveSamplingClassified.setEnabled(True) else: # return to default values self.QPBar_ClassificationStatus.setTextVisible(False) self.QPBar_ClassificationStatus.setValue(0) self.QLabel_ClassificationStatus.setText( "No sampling file selected") self.QLabel_ClassificationStatus.setStyleSheet( "QLabel {color: gray;}") self.grid_columns.setValue(2) self.grid_rows.setValue(1) # disable group box that depends of sampling file self.QGBox_SamplingClassification.setDisabled(True) self.QGBox_saveSamplingClassified.setDisabled(True) # updated state of sampling file selected for accuracy assessment tab self.set_sampling_file_accuracy_assessment()
def render_layer(self, layer): with block_signals_to(self): # set the CRS of the canvas view based on sampling layer sampling_crs = self.parent_view.sampling_layer.crs() self.canvas.setDestinationCrs(sampling_crs) # set the sampling over the layer to view self.canvas.setLayers([self.parent_view.sampling_layer, layer]) # set init extent from other view if any is activated else set layer extent from AcATaMa.gui.classification_dialog import ClassificationDialog others_view = [ (view_widget.render_widget.canvas.extent(), view_widget.current_scale_factor) for view_widget in ClassificationDialog.view_widgets if not view_widget.render_widget.canvas.extent().isEmpty() ] if others_view: extent, scale = others_view[0] extent.scale(1 / scale) self.set_extents_and_scalefactor(extent) elif ClassificationDialog.current_sample: ClassificationDialog.current_sample.fit_to( self.parent_view, ClassificationDialog.instance.radiusFitToSample.value()) self.canvas.refresh() self.layer = layer # show marker if ClassificationDialog.current_sample: self.marker.show(ClassificationDialog.current_sample)
def fit_to(self, view_widget, radius): # fit to current sample with min radius of extent fit_extent = QgsRectangle(self.QgsPnt.x() - radius, self.QgsPnt.y() - radius, self.QgsPnt.x() + radius, self.QgsPnt.y() + radius) with block_signals_to(view_widget.render_widget.canvas): view_widget.render_widget.set_extents_and_scalefactor(fit_extent)
def enable(self): with block_signals_to(self.render_widget): # activate some parts of this view self.QLabel_ViewName.setEnabled(True) self.render_widget.setEnabled(True) self.scaleFactorLabel.setEnabled(True) self.scaleFactor.setEnabled(True) self.layerStyleEditor.setEnabled(True) self.render_widget.canvas.setCanvasColor(QColor(255, 255, 255)) # set status for view widget self.is_active = True
def disable(self): with block_signals_to(self.render_widget): self.render_widget.canvas.setLayers([]) self.render_widget.marker.remove() self.render_widget.canvas.clearCache() self.render_widget.canvas.refresh() self.render_widget.layer = None # deactivate some parts of this view self.QLabel_ViewName.setDisabled(True) self.render_widget.setDisabled(True) self.scaleFactorLabel.setDisabled(True) self.scaleFactor.setDisabled(True) self.layerStyleEditor.setDisabled(True) self.render_widget.canvas.setCanvasColor(QColor(245, 245, 245)) # set status for view widget self.is_active = False
def clear_and_unset_the_thematic_raster(): with block_signals_to(self.QCBox_ThematicRaster): self.QCBox_ThematicRaster.setCurrentIndex(-1) self.QCBox_band_ThematicRaster.clear() self.nodata_ThematicRaster.setValue(-1) # SimpRS self.minDistance_SimpRS.setSuffix("") self.minDistance_SimpRS.setToolTip("") self.minDistance_SimpRS.setValue(0) # StraRS self.minDistance_StraRS.setSuffix("") self.minDistance_StraRS.setToolTip("") self.minDistance_StraRS.setValue(0) # disable sampling tab self.scrollAreaWidgetContents_S.setDisabled(True) # unset the thematic classes in classification instance sampling_layer = self.QCBox_SamplingFile.currentLayer() if sampling_layer and sampling_layer in Classification.instances: Classification.instances[sampling_layer].with_thematic_classes = False # updated state of sampling file selected for accuracy assessment tab self.set_sampling_file_accuracy_assessment()
def update_srs_table_content(dockwidget, srs_table): with block_signals_to(dockwidget.QTableW_StraRS): # init table dockwidget.QTableW_StraRS.setRowCount(srs_table["row_count"]) dockwidget.QTableW_StraRS.setColumnCount(srs_table["column_count"]) # enter data onto Table for n, key in enumerate(srs_table["header"]): if key == "Pix Val": for m, item in enumerate( srs_table["color_table"]["Pixel Value"]): item_table = QTableWidgetItem(str(item)) item_table.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) item_table.setTextAlignment(Qt.AlignCenter | Qt.AlignVCenter) dockwidget.QTableW_StraRS.setItem(m, n, item_table) if key == "Color": for m in range(srs_table["row_count"]): item_table = QTableWidgetItem() item_table.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) item_table.setBackground( QColor(srs_table["color_table"]["Red"][m], srs_table["color_table"]["Green"][m], srs_table["color_table"]["Blue"][m], srs_table["color_table"]["Alpha"][m])) dockwidget.QTableW_StraRS.setItem(m, n, item_table) if key == "Num Samples": for m in range(srs_table["row_count"]): item_table = QTableWidgetItem(srs_table["num_samples"][m]) item_table.setTextAlignment(Qt.AlignCenter | Qt.AlignVCenter) if not srs_table["On"][m]: item_table.setForeground(QColor("lightGrey")) item_table.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) dockwidget.QTableW_StraRS.setItem(m, n, item_table) if key == "Std Error": for m in range(srs_table["row_count"]): item_table = QTableWidgetItem(srs_table["std_error"][m]) item_table.setTextAlignment(Qt.AlignCenter | Qt.AlignVCenter) if not srs_table["On"][m]: item_table.setForeground(QColor("lightGrey")) item_table.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) dockwidget.QTableW_StraRS.setItem(m, n, item_table) if key == "On": for m in range(srs_table["row_count"]): item_table = QTableWidgetItem() item_table.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) item_table.setTextAlignment(Qt.AlignCenter | Qt.AlignVCenter) if srs_table["On"][m]: item_table.setCheckState(Qt.Checked) else: item_table.setCheckState(Qt.Unchecked) dockwidget.QTableW_StraRS.setItem(m, n, item_table) # hidden row labels dockwidget.QTableW_StraRS.verticalHeader().setVisible(False) # add Header dockwidget.QTableW_StraRS.setHorizontalHeaderLabels( srs_table["header"]) # adjust size of Table dockwidget.QTableW_StraRS.resizeColumnsToContents() dockwidget.QTableW_StraRS.resizeRowsToContents() # set label total samples total_num_samples = sum( [int(x) for x in mask(srs_table["num_samples"], srs_table["On"])]) dockwidget.TotalNumSamples.setText(str(total_num_samples)) # set maximum and reset the value in progress bar status dockwidget.widget_generate_StraRS.QPBar_GenerateSampling.setValue(0) dockwidget.widget_generate_StraRS.QPBar_GenerateSampling.setMaximum( total_num_samples)
def set_extents_and_scalefactor(self, extent): with block_signals_to(self.canvas): self.canvas.setExtent(extent) self.canvas.zoomByFactor(self.parent_view.scaleFactor.value()) if self.marker.marker: self.marker.marker.updatePosition()
def __init__(self, sampling_layer, columns, rows): QDialog.__init__(self) self.sampling_layer = sampling_layer self.setupUi(self) ClassificationDialog.instance = self # flags self.setWindowFlags(self.windowFlags() | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint) # get classification or init new instance if sampling_layer in Classification.instances: self.classification = Classification.instances[sampling_layer] else: self.classification = Classification(sampling_layer) self.classification.grid_columns = columns self.classification.grid_rows = rows #### settings the classification dialog # set dialog title self.setWindowTitle("Classification of samples for " + sampling_layer.name()) # resize the classification dialog if self.classification.dialog_size: self.resize(*self.classification.dialog_size) # disable enter action self.QPBtn_SetClassification.setAutoDefault(False) self.QPBtn_unclassifySampleButton.setAutoDefault(False) # go to sample ID action self.GoTo_ID_Button.clicked.connect(self.go_to_sample_id) self.GoTo_ID.returnPressed.connect(self.go_to_sample_id) self.GoTo_ID.textChanged.connect( lambda: self.GoTo_ID.setStyleSheet("")) # open in Google Earth self.QPBtn_OpenInGE.clicked.connect( self.open_current_point_in_google_engine) # set properties and default value for the fit to sample spinBox based on sampling file layer_dist_unit = self.sampling_layer.crs().mapUnits() str_unit = QgsUnitTypes.toString(layer_dist_unit) abbr_unit = QgsUnitTypes.toAbbreviatedString(layer_dist_unit) self.radiusFitToSample.setSuffix(" {}".format(abbr_unit)) self.radiusFitToSample.setToolTip( "Units in {} for set the zoom radius to the current sample\n" "(units based on sampling file selected)".format(str_unit)) self.radiusFitToSample.setRange( 0, 360 if layer_dist_unit == QgsUnitTypes.DistanceDegrees else 10e6) self.radiusFitToSample.setDecimals(4 if layer_dist_unit in [ QgsUnitTypes.DistanceKilometers, QgsUnitTypes. DistanceNauticalMiles, QgsUnitTypes.DistanceMiles, QgsUnitTypes. DistanceDegrees ] else 1) self.radiusFitToSample.setSingleStep(0.0001 if layer_dist_unit in [ QgsUnitTypes.DistanceKilometers, QgsUnitTypes. DistanceNauticalMiles, QgsUnitTypes.DistanceMiles, QgsUnitTypes. DistanceDegrees ] else 1) self.radiusFitToSample.setValue(self.classification.fit_to_sample) # set total samples self.QPBar_SamplesNavigation.setMaximum(len( self.classification.points)) # actions for fit and go to current sample self.radiusFitToSample.valueChanged.connect( lambda: self.show_and_go_to_current_sample(highlight=False)) self.currentSample.clicked.connect( lambda: self.show_and_go_to_current_sample(highlight=True)) # move through samples self.nextSample.clicked.connect(self.next_sample) self.nextSampleNotClassified.clicked.connect( self.next_sample_not_classified) self.previousSample.clicked.connect(self.previous_sample) self.previousSampleNotClassified.clicked.connect( self.previous_sample_not_classified) # dialog buttons box self.closeButton.rejected.connect(self.closing) # disable enter action self.closeButton.button(QDialogButtonBox.Close).setAutoDefault(False) # init current point self.current_sample_idx = self.classification.current_sample_idx self.current_sample = None self.set_current_sample() # set classification buttons self.classification_btns_config = ClassificationButtonsConfig( self.classification.buttons_config) self.create_classification_buttons( buttons_config=self.classification.buttons_config) self.QPBtn_SetClassification.clicked.connect( self.open_set_classification_dialog) self.QPBtn_unclassifySampleButton.clicked.connect( self.unclassify_sample) # create dynamic size of the view render widgets windows # inside the grid with columns x rows divide by splitters h_splitters = [] view_widgets = [] for row in range(self.classification.grid_rows): splitter = QSplitter(Qt.Horizontal) for column in range(self.classification.grid_columns): new_view_widget = ClassificationViewWidget() splitter.addWidget(new_view_widget) h_splitters.append(splitter) view_widgets.append(new_view_widget) v_splitter = QSplitter(Qt.Vertical) for splitter in h_splitters: v_splitter.addWidget(splitter) # add to classification dialog self.widget_view_windows.layout().addWidget(v_splitter) # save instances ClassificationDialog.view_widgets = view_widgets # setup view widget [ view_widget.setup_view_widget(sampling_layer) for view_widget in ClassificationDialog.view_widgets ] for idx, view_widget in enumerate(ClassificationDialog.view_widgets): view_widget.id = idx # set the label names for each view for num_view, view_widget in enumerate( ClassificationDialog.view_widgets): view_widget.QLabel_ViewID.setText("View {}:".format(num_view + 1)) # restore view widgets status for config_id, view_config in self.classification.view_widgets_config.items( ): for view_widget in ClassificationDialog.view_widgets: if config_id == view_widget.id: view_widget = ClassificationDialog.view_widgets[config_id] # select the file for this view widget if exists and is loaded in Qgis layer_name = view_config["layer_name"] if not layer_name and view_config["render_file_path"]: layer_name = os.path.splitext( os.path.basename( view_config["render_file_path"]))[0] file_index = view_widget.QCBox_RenderFile.findText( layer_name, Qt.MatchFixedString) if file_index != -1: # select layer if exists in Qgis with block_signals_to(view_widget.QCBox_RenderFile): view_widget.QCBox_RenderFile.setCurrentIndex( file_index) elif view_config["render_file_path"] and os.path.isfile( view_config["render_file_path"]): # load file and select in view if this exists and not load in Qgis load_and_select_filepath_in( view_widget.QCBox_RenderFile, view_config["render_file_path"], layer_name=layer_name) elif view_config["render_file_path"] and not os.path.isfile( view_config["render_file_path"]): self.MsgBar.pushMessage( "Could not to load the layer '{}' in the view {}: no such file {}" .format( layer_name, "'{}'".format(view_config["view_name"]) if view_config["view_name"] else view_widget.id + 1, view_config["render_file_path"]), level=Qgis.Warning, duration=-1) else: self.MsgBar.pushMessage( "Could not to load the layer '{}' in the view {} (for network layers use save/load a Qgis project)" .format( layer_name, "'{}'".format(view_config["view_name"]) if view_config["view_name"] else view_widget.id + 1), level=Qgis.Warning, duration=-1) # TODO: restore size by view widget # view_widget.resize(*view_config["view_size"]) view_widget.QLabel_ViewName.setText( view_config["view_name"]) view_widget.scaleFactor.setValue( view_config["scale_factor"]) # active render layer in canvas view_widget.set_render_layer( view_widget.QCBox_RenderFile.currentLayer())