def execute_in_place(alg, parameters, context=None, feedback=None): """Executes an algorithm modifying features in-place, if the INPUT parameter is not defined, the current active layer will be used as INPUT. :param alg: algorithm to run :type alg: QgsProcessingAlgorithm :param parameters: parameters of the algorithm :type parameters: dict :param context: context, defaults to None :param context: QgsProcessingContext, optional :param feedback: feedback, defaults to None :param feedback: QgsProcessingFeedback, optional :raises QgsProcessingException: raised when the layer is not editable or the layer cannot be found in the current project :return: a tuple with true if success and results :rtype: tuple """ if feedback is None: feedback = QgsProcessingFeedback() if context is None: context = dataobjects.createContext(feedback) if not 'INPUT' in parameters or not parameters['INPUT']: parameters['INPUT'] = iface.activeLayer() ok, results = execute_in_place_run(alg, parameters, context=context, feedback=feedback) if ok: if isinstance(parameters['INPUT'], QgsProcessingFeatureSourceDefinition): layer = alg.parameterAsVectorLayer({'INPUT': parameters['INPUT'].source}, 'INPUT', context) elif isinstance(parameters['INPUT'], QgsVectorLayer): layer = parameters['INPUT'] if layer: layer.triggerRepaint() return ok, results
def getParamValues(self): if self.mUpdateExistingGroupBox.isChecked(): fieldName = self.mExistingFieldComboBox.currentText() else: fieldName = self.mOutputFieldNameLineEdit.text() layer = self.cmbInputLayer.currentLayer() context = dataobjects.createContext() parameters = {} parameters['INPUT'] = layer parameters['FIELD_NAME'] = fieldName parameters['FIELD_TYPE'] = self.mOutputFieldTypeComboBox.currentIndex() parameters['FIELD_LENGTH'] = self.mOutputFieldWidthSpinBox.value() parameters['FIELD_PRECISION'] = self.mOutputFieldPrecisionSpinBox.value() parameters['NEW_FIELD'] = self.mNewFieldGroupBox.isChecked() parameters['FORMULA'] = self.builder.expressionText() output = QgsProcessingOutputLayerDefinition() if self.leOutputFile.text().strip(): output.sink = QgsProperty.fromValue(self.leOutputFile.text().strip()) else: output.sink = QgsProperty.fromValue('memory:') output.destinationProject = context.project() parameters['OUTPUT'] = output ok, msg = self.alg.checkParameterValues(parameters, context) if not ok: QMessageBox.warning( self, self.tr('Unable to execute algorithm'), msg) return {} return parameters
def _executeAlgorithm(alg): ok, message = alg.canExecute() if not ok: dlg = MessageDialog() dlg.setTitle(Processing.tr('Missing dependency')) dlg.setMessage( Processing.tr('<h3>Missing dependency. This algorithm cannot ' 'be run :-( </h3>\n{0}').format(message)) dlg.exec_() return if (alg.countVisibleParameters()) > 0: dlg = alg.createCustomParametersWidget(None) if not dlg: dlg = AlgorithmDialog(alg) canvas = iface.mapCanvas() prevMapTool = canvas.mapTool() dlg.show() dlg.exec_() if canvas.mapTool() != prevMapTool: try: canvas.mapTool().reset() except: pass canvas.setMapTool(prevMapTool) else: feedback = MessageBarProgress() context = dataobjects.createContext(feedback) parameters = {} ret, results = execute(alg, parameters, context, feedback) handleAlgorithmResults(alg, context, feedback) feedback.close()
def getSafeExportedLayer(self): """Returns not the value entered by the user, but a string with a filename which contains the data of this layer, but saved in a standard format (currently always a shapefile) so that it can be opened by most external applications. If there is a selection and QGIS is configured to use just the selection, if exports the layer even if it is already in a suitable format. Works only if the layer represented by the parameter value is currently loaded in QGIS. Otherwise, it will not perform any export and return the current value string. If the current value represents a layer in a suitable format, it does not export at all and returns that value. The layer is exported just the first time the method is called. The method can be called several times and it will always return the same file, performing the export only the first time. """ context = dataobjects.createContext() if self.exported: return self.exported layer = QgsProcessingUtils.mapLayerFromString(self.value, context, False) if layer: self.exported = dataobjects.exportVectorLayer(layer) else: self.exported = self.value return self.exported
def checkExtentCRS(self): unmatchingCRS = False hasExtent = False context = dataobjects.createContext() projectCRS = iface.mapCanvas().mapSettings().destinationCrs() layers = QgsProcessingUtils.compatibleLayers(QgsProject.instance()) for param in self.algorithm().parameterDefinitions(): if isinstance(param, (ParameterRaster, ParameterVector, ParameterMultipleInput)): if param.value: if isinstance(param, ParameterMultipleInput): inputlayers = param.value.split(';') else: inputlayers = [param.value] for inputlayer in inputlayers: for layer in layers: if layer.source() == inputlayer: if layer.crs() != projectCRS: unmatchingCRS = True p = QgsProcessingUtils.mapLayerFromString(inputlayer, context) if p is not None: if p.crs() != projectCRS: unmatchingCRS = True if isinstance(param, ParameterExtent): if param.skip_crs_check: continue value = self.mainWidget().wrappers[param.name()].widget.leText.text().strip() if value: hasExtent = True return hasExtent and unmatchingCRS
def __init__(self, name='', description='', options=[], default=None, isSource=False, multiple=False, optional=False): Parameter.__init__(self, name, description, default, optional) self.multiple = multiple isSource = parseBool(isSource) self.options = options if isSource: self.options = [] layer = QgsVectorLayer(options[0], "layer", "ogr") if layer.isValid(): try: index = resolveFieldIndex(layer, options[1]) feats = QgsProcessingUtils.getFeatures(layer, dataobjects.createContext()) for feature in feats: self.options.append(str(feature.attributes()[index])) except ValueError: pass elif isinstance(self.options, str): self.options = self.options.split(";") # compute options as (value, text) options = [] for i, option in enumerate(self.options): if option is None or isinstance(option, basestring): options.append((i, option)) else: options.append((option[0], option[1])) self.options = options self.values = [option[0] for option in options] self.value = None
def getSafeExportedTable(self): """Returns not the value entered by the user, but a string with a filename which contains the data of this table, but saved in a standard format (currently always a DBF file) so that it can be opened by most external applications. Works only if the table represented by the parameter value is currently loaded in QGIS. Otherwise, it will not perform any export and return the current value string. If the current value represents a table in a suitable format, it does not export at all and returns that value. The table is exported just the first time the method is called. The method can be called several times and it will always return the same file, performing the export only the first time. """ context = dataobjects.createContext() if self.exported: return self.exported table = QgsProcessingUtils.mapLayerFromString(self.value, context, False) if table: self.exported = dataobjects.exportTable(table) else: self.exported = self.value return self.exported
def __init__(self, alg, model, algName=None, configuration=None): QDialog.__init__(self) self.setModal(True) self._alg = alg # The algorithm to define in this dialog. It is an instance of QgsProcessingAlgorithm self.model = model # The model this algorithm is going to be added to. It is an instance of QgsProcessingModelAlgorithm self.childId = algName # The name of the algorithm in the model, in case we are editing it and not defining it for the first time self.configuration = configuration self.context = createContext() self.widget_labels = {} class ContextGenerator(QgsProcessingContextGenerator): def __init__(self, context): super().__init__() self.processing_context = context def processingContext(self): return self.processing_context self.context_generator = ContextGenerator(self.context) self.setupUi() self.params = None settings = QgsSettings() self.restoreGeometry(settings.value("/Processing/modelParametersDialogGeometry", QByteArray()))
def executeAlgorithm(self): alg = self.algorithmTree.selectedAlgorithm() if alg is not None: ok, message = alg.canExecute() if not ok: dlg = MessageDialog() dlg.setTitle(self.tr('Error executing algorithm')) dlg.setMessage( self.tr('<h3>This algorithm cannot ' 'be run :-( </h3>\n{0}').format(message)) dlg.exec_() return if alg.countVisibleParameters() > 0: dlg = alg.createCustomParametersWidget(self) if not dlg: dlg = AlgorithmDialog(alg) canvas = iface.mapCanvas() prevMapTool = canvas.mapTool() dlg.show() dlg.exec_() if canvas.mapTool() != prevMapTool: try: canvas.mapTool().reset() except: pass canvas.setMapTool(prevMapTool) else: feedback = MessageBarProgress() context = dataobjects.createContext(feedback) parameters = {} ret, results = execute(alg, parameters, context, feedback) handleAlgorithmResults(alg, context, feedback) feedback.close()
def setOutputCRS(self): context = dataobjects.createContext() layers = QgsProcessingUtils.compatibleLayers(QgsProject.instance()) for param in self.parameterDefinitions(): if isinstance(param, (ParameterRaster, ParameterVector, ParameterMultipleInput)): if param.value: if isinstance(param, ParameterMultipleInput): inputlayers = param.value.split(';') else: inputlayers = [param.value] for inputlayer in inputlayers: for layer in layers: if layer.source() == inputlayer: self.crs = layer.crs() return p = QgsProcessingUtils.mapLayerFromString(inputlayer, context) if p is not None: self.crs = p.crs() p = None return try: from qgis.utils import iface if iface is not None: self.crs = iface.mapCanvas().mapSettings().destinationCrs() except: pass
def getLayerFromValue(self, value): context = createContext() if isinstance(value, QgsProcessingFeatureSourceDefinition): value, ok = value.source.valueAsString(context.expressionContext()) if isinstance(value, str): value = QgsProcessingUtils.mapLayerFromString(value, context) return value
def __init__(self, dialog, param): super(ExtentSelectionPanel, self).__init__(None) self.setupUi(self) self.dialog = dialog self.param = param if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional: if hasattr(self.leText, 'setPlaceholderText'): self.leText.setPlaceholderText( self.tr('[Leave blank to use min covering extent]')) self.btnSelect.clicked.connect(self.selectExtent) canvas = iface.mapCanvas() self.prevMapTool = canvas.mapTool() self.tool = RectangleMapTool(canvas) self.tool.rectangleCreated.connect(self.updateExtent) if param.defaultValue() is not None: context = createContext() rect = QgsProcessingParameters.parameterAsExtent(param, {param.name(): param.defaultValue()}, context) if not rect.isNull(): try: s = '{},{},{},{}'.format( rect.xMinimum(), rect.xMaximum(), rect.yMinimum(), rect.yMaximum()) self.leText.setText(s) except: pass
def __init__(self, parent, alg): super(ParametersPanel, self).__init__(None) self.setupUi(self) self.grpAdvanced.hide() self.scrollAreaWidgetContents.setContentsMargins(4, 4, 4, 4) self.layoutMain = self.scrollAreaWidgetContents.layout() self.layoutAdvanced = self.grpAdvanced.layout() self.parent = parent self.alg = alg self.wrappers = {} self.outputWidgets = {} self.checkBoxes = {} self.dependentItems = {} self.iterateButtons = {} self.processing_context = createContext() class ContextGenerator(QgsProcessingContextGenerator): def __init__(self, context): super().__init__() self.processing_context = context def processingContext(self): return self.processing_context self.context_generator = ContextGenerator(self.processing_context) self.initWidgets() QgsProject.instance().layerWasAdded.connect(self.layerRegistryChanged) QgsProject.instance().layersWillBeRemoved.connect(self.layerRegistryChanged)
def executeAlgorithm(alg, parameters, context=None, feedback=None, model=None): """The method to use to call a processing algorithm. Although the body of the algorithm is in processAlgorithm(), it should be called using this method, since it performs some additional operations. Raises a QgsProcessingException in case anything goes wrong. :param parameters: """ if feedback is None: feedback = QgsProcessingFeedback() if context is None: context = dataobjects.createContext(feedback) #self.model = model #self.setOutputCRS() #self.resolveOutputs() #self.evaluateParameterValues() #self.runPreExecutionScript(feedback) result, ok = alg.run(parameters, context, feedback) #self.processAlgorithm(parameters, context, feedback) feedback.setProgress(100) return result, ok
def exportVectorLayer(self, orgFilename): context = dataobjects.createContext() # TODO: improve this. We are now exporting if it is not a shapefile, # but the functionality of v.in.ogr could be used for this. # We also export if there is a selection if not os.path.exists(orgFilename) or not orgFilename.endswith('shp'): layer = QgsProcessingUtils.mapLayerFromString(orgFilename, context, False) if layer: filename = dataobjects.exportVectorLayer(layer) else: layer = QgsProcessingUtils.mapLayerFromString(orgFilename, context, False) if layer: #TODO #useSelection = \ # ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED) if useSelection and layer.selectedFeatureCount() != 0: filename = dataobjects.exportVectorLayer(layer) else: filename = orgFilename else: filename = orgFilename destFilename = 'a' + os.path.basename(self.getTempFilename()) self.exportedLayers[orgFilename] = destFilename command = 'v.in.ogr' min_area = self.getParameterValue(self.GRASS_MIN_AREA_PARAMETER) command += ' min_area=' + str(min_area) snap = self.getParameterValue(self.GRASS_SNAP_TOLERANCE_PARAMETER) command += ' snap=' + str(snap) command += ' input="' + os.path.dirname(filename) + '"' command += ' layer=' + os.path.basename(filename)[:-4] command += ' output=' + destFilename command += ' --overwrite -o' return command
def showExpressionsBuilder(self): context = self.alg.createExpressionContext({}, createContext()) dlg = QgsExpressionBuilderDialog(None, self.leText.text(), self, 'generic', context) dlg.setWindowTitle(self.tr('Expression based output')) if dlg.exec_() == QDialog.Accepted: expression = QgsExpression(dlg.expressionText()) self.leText.setText(expression.evaluate(context))
def getConsoleCommands(self, parameters): out = self.getOutputValue(self.OUTPUT) mask = self.getParameterValue(self.MASK) context = dataobjects.createContext() maskLayer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.MASK), context) ogrMask = ogrConnectionString(mask)[1:-1] noData = self.getParameterValue(self.NO_DATA) opts = self.getParameterValue(self.OPTIONS) if noData is not None: noData = str(noData) addAlphaBand = self.getParameterValue(self.ALPHA_BAND) cropToCutline = self.getParameterValue(self.CROP_TO_CUTLINE) keepResolution = self.getParameterValue(self.KEEP_RESOLUTION) arguments = [] arguments.append('-ot') arguments.append(self.TYPE[self.getParameterValue(self.RTYPE)]) arguments.append('-q') arguments.append('-of') arguments.append(GdalUtils.getFormatShortNameFromFilename(out)) if noData and len(noData) > 0: arguments.append('-dstnodata') arguments.append(noData) if keepResolution: r = gdal.Open(self.getParameterValue(self.INPUT)) geoTransform = r.GetGeoTransform() r = None arguments.append('-tr') arguments.append(str(geoTransform[1])) arguments.append(str(geoTransform[5])) arguments.append('-tap') arguments.append('-cutline') arguments.append(ogrMask) if maskLayer and maskLayer.subsetString() != '': arguments.append('-cwhere') arguments.append(maskLayer.subsetString()) if cropToCutline: arguments.append('-crop_to_cutline') if addAlphaBand: arguments.append('-dstalpha') if opts: arguments.append('-co') arguments.append(opts) if GdalUtils.version() in [2010000, 2010100]: arguments.append("--config GDALWARP_IGNORE_BAD_CUTLINE YES") arguments.append(self.getParameterValue(self.INPUT)) arguments.append(out) return ['gdalwarp', GdalUtils.escapeAndJoin(arguments)]
def populateByExpression(self, adding=False): """ Populates the panel using an expression """ context = dataobjects.createContext() expression_context = context.expressionContext() # use the first row parameter values as a preview during expression creation params = self.panel.parametersForRow(0, warnOnInvalid=False) alg_scope = QgsExpressionContextUtils.processingAlgorithmScope(self.panel.alg, params, context) # create explicit variables corresponding to every parameter for k, v in params.items(): alg_scope.setVariable(k, v, True) expression_context.appendScope(alg_scope) # mark the parameter variables as highlighted for discoverability highlighted_vars = expression_context.highlightedVariables() highlighted_vars.extend(list(params.keys())) expression_context.setHighlightedVariables(highlighted_vars) dlg = QgsExpressionBuilderDialog(layer=None, context=context.expressionContext()) if adding: dlg.setExpectedOutputFormat(self.tr('An array of values corresponding to each new row to add')) if not dlg.exec_(): return if adding: exp = QgsExpression(dlg.expressionText()) res = exp.evaluate(expression_context) if type(res) is not list: res = [res] first_row = self.panel.batchRowCount() if self.panel.batchRowCount() > 1 else 0 for row, value in enumerate(res): self.setRowValue(row + first_row, value, context) else: for row in range(self.panel.batchRowCount()): params = self.panel.parametersForRow(row, warnOnInvalid=False) # remove previous algorithm scope -- we need to rebuild this completely, using the # other parameter values from the current row expression_context.popScope() alg_scope = QgsExpressionContextUtils.processingAlgorithmScope(self.panel.alg, params, context) for k, v in params.items(): alg_scope.setVariable(k, v, True) expression_context.appendScope(alg_scope) # rebuild a new expression every time -- we don't want the expression compiler to replace # variables with precompiled values exp = QgsExpression(dlg.expressionText()) value = exp.evaluate(expression_context) self.setRowValue(row, value, context)
def testProcessingException(self): """ Test that Python exception is caught when running an alg """ alg = TestAlg() context = createContext() feedback = QgsProcessingFeedback() results, ok = alg.run({}, context, feedback) self.assertFalse(ok)
def fillParameterValues(self, column): context = dataobjects.createContext() wrapper = self.wrappers[0][column] if wrapper is None: # e.g. double clicking on a destination header return for row in range(1, self.tblParameters.rowCount()): self.wrappers[row][column].setParameterValue(wrapper.parameterValue(), context)
def setDynamicLayer(self, layer): context = createContext() try: if isinstance(layer, QgsProcessingFeatureSourceDefinition): layer, ok = layer.source.valueAsString(context.expressionContext()) if isinstance(layer, str): layer = QgsProcessingUtils.mapLayerFromString(layer, context) self.btnDataDefined.setVectorLayer(layer) except: pass
def _test_difference_on_invalid_geometries(self, geom_option): polygon_layer = self._make_layer('Polygon') self.assertTrue(polygon_layer.startEditing()) f = QgsFeature(polygon_layer.fields()) f.setAttributes([1]) # Flake! f.setGeometry(QgsGeometry.fromWkt('Polygon ((0 0, 2 2, 0 2, 2 0, 0 0))')) self.assertTrue(f.isValid()) self.assertTrue(polygon_layer.addFeatures([f])) polygon_layer.commitChanges() polygon_layer.rollBack() self.assertEqual(polygon_layer.featureCount(), 1) overlay_layer = self._make_layer('Polygon') self.assertTrue(overlay_layer.startEditing()) f = QgsFeature(overlay_layer.fields()) f.setAttributes([1]) f.setGeometry(QgsGeometry.fromWkt('Polygon ((0 0, 2 0, 2 2, 0 2, 0 0))')) self.assertTrue(f.isValid()) self.assertTrue(overlay_layer.addFeatures([f])) overlay_layer.commitChanges() overlay_layer.rollBack() self.assertEqual(overlay_layer.featureCount(), 1) QgsProject.instance().addMapLayers([polygon_layer, overlay_layer]) old_features = [f for f in polygon_layer.getFeatures()] # 'Ignore features with invalid geometries' = 1 ProcessingConfig.setSettingValue(ProcessingConfig.FILTER_INVALID_GEOMETRIES, geom_option) feedback = ConsoleFeedBack() context = dataobjects.createContext(feedback) context.setProject(QgsProject.instance()) alg = self.registry.createAlgorithmById('native:difference') self.assertIsNotNone(alg) parameters = { 'OVERLAY': overlay_layer, 'INPUT': polygon_layer, 'OUTPUT': ':memory', } old_features = [f for f in polygon_layer.getFeatures()] self.assertTrue(polygon_layer.startEditing()) polygon_layer.selectAll() ok, _ = execute_in_place_run( alg, parameters, context=context, feedback=feedback, raise_exceptions=True) new_features = [f for f in polygon_layer.getFeatures()] return old_features, new_features
def setSessionProjectionFromLayer(self, layer, commands): context = dataobjects.createContext() if not Grass7Utils.projectionSet: qGisLayer = QgsProcessingUtils.mapLayerFromString(layer, context) if qGisLayer: proj4 = str(qGisLayer.crs().toProj4()) command = 'g.proj' command += ' -c' command += ' proj4="' + proj4 + '"' self.commands.append(command) Grass7Utils.projectionSet = True
def setLayer(self, layer): context = dataobjects.createContext() if layer == self._layer: return if isinstance(layer, QgsProcessingFeatureSourceDefinition): layer, ok = layer.source.valueAsString(context.expressionContext()) if isinstance(layer, str): layer = QgsProcessingUtils.mapLayerFromString(layer, context) if not isinstance(layer, QgsVectorLayer): layer = None self._layer = layer self.panel.setLayer(self._layer)
def addFilesByPattern(self): """ Populates the dialog using a file pattern match """ dlg = QgsFindFilesByPatternDialog() dlg.setWindowTitle(self.tr("Add Files by Pattern")) if dlg.exec_(): files = dlg.files() context = dataobjects.createContext() first_row = self.panel.batchRowCount() if self.panel.batchRowCount() > 1 else 0 for row, file in enumerate(files): self.setRowValue(first_row + row, file, context)
def executeAlgorithm(self): item = self.algorithmTree.currentItem() if isinstance(item, TreeAlgorithmItem): alg = QgsApplication.processingRegistry().createAlgorithmById(item.alg.id()) if not alg: return ok, message = alg.canExecute() if not ok: dlg = MessageDialog() dlg.setTitle(self.tr('Error executing algorithm')) dlg.setMessage( self.tr('<h3>This algorithm cannot ' 'be run :-( </h3>\n{0}').format(message)) dlg.exec_() return if alg.countVisibleParameters() > 0: dlg = alg.createCustomParametersWidget(self) if not dlg: dlg = AlgorithmDialog(alg) canvas = iface.mapCanvas() prevMapTool = canvas.mapTool() dlg.show() dlg.exec_() if canvas.mapTool() != prevMapTool: try: canvas.mapTool().reset() except: pass canvas.setMapTool(prevMapTool) if dlg.executed: showRecent = ProcessingConfig.getSetting( ProcessingConfig.SHOW_RECENT_ALGORITHMS) if showRecent: self.addRecentAlgorithms(True) # have to manually delete the dialog - otherwise it's owned by the # iface mainWindow and never deleted dlg.deleteLater() else: feedback = MessageBarProgress() context = dataobjects.createContext(feedback) parameters = {} ret, results = execute(alg, parameters, context, feedback) handleAlgorithmResults(alg, context, feedback) feedback.close() if isinstance(item, TreeActionItem): action = item.action action.setData(self) action.execute()
def getSafeExportedLayers(self): """ Returns not the value entered by the user, but a string with semicolon-separated filenames which contains the data of the selected layers, but saved in a standard format (currently shapefiles for vector layers and GeoTiff for raster) so that they can be opened by most external applications. If there is a selection and QGIS is configured to use just the selection, it exports the layer even if it is already in a suitable format. Works only if the layer represented by the parameter value is currently loaded in QGIS. Otherwise, it will not perform any export and return the current value string. If the current value represents a layer in a suitable format, it does no export at all and returns that value. Currently, it works just for vector layer. In the case of raster layers, it returns the parameter value. The layers are exported just the first time the method is called. The method can be called several times and it will always return the same string, performing the export only the first time. """ context = dataobjects.createContext() if self.exported: return self.exported self.exported = self.value layers = self.value.split(';') if layers is None or len(layers) == 0: return self.value if self.datatype == dataobjects.TYPE_RASTER: for layerfile in layers: layer = QgsProcessingUtils.mapLayerFromString(layerfile, context, False) if layer: filename = dataobjects.exportRasterLayer(layer) self.exported = self.exported.replace(layerfile, filename) return self.exported elif self.datatype == dataobjects.TYPE_FILE: return self.value else: for layerfile in layers: layer = QgsProcessingUtils.mapLayerFromString(layerfile, context, False) if layer: filename = dataobjects.exportVectorLayer(layer) self.exported = self.exported.replace(layerfile, filename) return self.exported
def getLayerFromValue(self, value): context = createContext() if isinstance(value, QgsProcessingFeatureSourceDefinition): value, ok = value.source.valueAsString(context.expressionContext()) if isinstance(value, str): value = QgsProcessingUtils.mapLayerFromString(value, context) if value is None or not isinstance(value, QgsMapLayer): return None # need to return layer with ownership - otherwise layer may be deleted when context # goes out of scope new_layer = context.takeResultLayer(value.id()) # if we got ownership, return that - otherwise just return the layer (which may be owned by the project) return new_layer if new_layer is not None else value
def save(self): toSave = [] context = dataobjects.createContext() for row in range(self.tblParameters.rowCount()): algParams = {} algOutputs = {} col = 0 alg = self.alg for param in alg.parameterDefinitions(): if param.flags() & QgsProcessingParameterDefinition.FlagHidden: continue if param.isDestination(): continue wrapper = self.wrappers[row][col] if not param.checkValueIsAcceptable(wrapper.value(), context): self.parent.messageBar().pushMessage("", self.tr('Wrong or missing parameter value: {0} (row {1})').format( param.description(), row + 1), level=Qgis.Warning, duration=5) return algParams[param.name()] = param.valueAsPythonString(wrapper.value(), context) col += 1 for out in alg.destinationParameterDefinitions(): if out.flags() & QgsProcessingParameterDefinition.FlagHidden: continue widget = self.tblParameters.cellWidget(row, col) text = widget.getValue() if text.strip() != '': algOutputs[out.name()] = text.strip() col += 1 else: self.parent.messageBar().pushMessage("", self.tr('Wrong or missing output value: {0} (row {1})').format( out.description(), row + 1), level=Qgis.Warning, duration=5) return toSave.append({self.PARAMETERS: algParams, self.OUTPUTS: algOutputs}) settings = QgsSettings() last_path = settings.value("/Processing/LastBatchPath", QDir.homePath()) filename, __ = QFileDialog.getSaveFileName(self, self.tr('Save Batch'), last_path, self.tr('JSON files (*.json)')) if filename: if not filename.endswith('.json'): filename += '.json' last_path = QFileInfo(filename).path() settings.setValue('/Processing/LastBatchPath', last_path) with open(filename, 'w') as f: json.dump(toSave, f)
def executeAlgorithm(alg, parameters, context=None, feedback=None, model=None): """The method to use to call a processing algorithm. Although the body of the algorithm is in processAlgorithm(), it should be called using this method, since it performs some additional operations. Raises a GeoAlgorithmExecutionException in case anything goes wrong. :param parameters: """ if feedback is None: feedback = QgsProcessingFeedback() if context is None: context = dataobjects.createContext() #self.model = model try: #self.setOutputCRS() #self.resolveOutputs() #self.evaluateParameterValues() #self.runPreExecutionScript(feedback) result = alg.run(parameters, context, feedback) #self.processAlgorithm(parameters, context, feedback) feedback.setProgress(100) return result #self.convertUnsupportedFormats(context, feedback) #self.runPostExecutionScript(feedback) except GeoAlgorithmExecutionException as gaee: lines = [self.tr('Error while executing algorithm')] lines = [] lines.append(traceback.format_exc()) feedback.reportError(gaee.msg) QgsMessageLog.logMessage(gaee.msg, self.tr('Processing'), QgsMessageLog.CRITICAL) raise GeoAlgorithmExecutionException(gaee.msg, lines, gaee) #except Exception as e: # If something goes wrong and is not caught in the # algorithm, we catch it here and wrap it #lines = [self.tr('Uncaught error while executing algorithm')] # lines = [] # lines.append(traceback.format_exc()) #QgsMessageLog.logMessage('\n'.join(lines), self.tr('Processing'), QgsMessageLog.CRITICAL) #raise GeoAlgorithmExecutionException(str(e) + self.tr('\nSee log for more details'), lines, e) def helpUrl(self): return QgsHelp.helpUrl("processing_algs/{}/{}".format( self.provider().id(), self.id())).toString()
def accept(self): alg_parameters = [] load = [] feedback = self.createFeedback() context = dataobjects.createContext(feedback) for row in range(self.mainWidget.tblParameters.rowCount()): col = 0 parameters = {} for param in self.alg.parameterDefinitions(): if param.flags( ) & QgsProcessingParameterDefinition.FlagHidden or param.isDestination( ): continue wrapper = self.mainWidget.wrappers[row][col] parameters[param.name()] = wrapper.value() if not param.checkValueIsAcceptable(wrapper.value(), context): self.bar.pushMessage( "", self.tr( 'Wrong or missing parameter value: {0} (row {1})'). format(param.description(), row + 1), level=QgsMessageBar.WARNING, duration=5) return col += 1 count_visible_outputs = 0 for out in self.alg.destinationParameterDefinitions(): if out.flags() & QgsProcessingParameterDefinition.FlagHidden: continue count_visible_outputs += 1 widget = self.mainWidget.tblParameters.cellWidget(row, col) text = widget.getValue() if param.checkValueIsAcceptable(text, context): if isinstance(out, (QgsProcessingParameterRasterDestination, QgsProcessingParameterFeatureSink)): # load rasters and sinks on completion parameters[ out.name()] = QgsProcessingOutputLayerDefinition( text, context.project()) else: parameters[out.name()] = text col += 1 else: self.bar.pushMessage( "", self.tr('Wrong or missing output value: {0} (row {1})' ).format(out.description(), row + 1), level=QgsMessageBar.WARNING, duration=5) return alg_parameters.append(parameters) QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.mainWidget.setEnabled(False) self.buttonCancel.setEnabled(True) # Make sure the Log tab is visible before executing the algorithm try: self.tabWidget.setCurrentIndex(1) self.repaint() except: pass start_time = time.time() algorithm_results = [] for count, parameters in enumerate(alg_parameters): if feedback.isCanceled(): break self.setText( self.tr('\nProcessing algorithm {0}/{1}...').format( count + 1, len(alg_parameters))) self.setInfo(self.tr('<b>Algorithm {0} starting...</b>').format( self.alg.displayName()), escape_html=False) feedback.pushInfo(self.tr('Input parameters:')) feedback.pushCommandInfo(pformat(parameters)) feedback.pushInfo('') alg_start_time = time.time() ret, results = execute(self.alg, parameters, context, feedback) if ret: self.setInfo( self.tr('Algorithm {0} correctly executed...').format( self.alg.displayName()), escape_html=False) feedback.setProgress(100) feedback.pushInfo( self.tr('Execution completed in {0:0.2f} seconds'.format( time.time() - alg_start_time))) feedback.pushInfo(self.tr('Results:')) feedback.pushCommandInfo(pformat(results)) feedback.pushInfo('') algorithm_results.append(results) else: break feedback.pushInfo( self.tr('Batch execution completed in {0:0.2f} seconds'.format( time.time() - start_time))) handleAlgorithmResults(self.alg, context, feedback, False) self.finish(algorithm_results) self.buttonCancel.setEnabled(False)
def paintModel(self, model, controls=True): self.model = model context = createContext() # Inputs for inp in list(model.parameterComponents().values()): item = ModelerGraphicItem(inp, model, controls, scene=self) item.setFlag(QGraphicsItem.ItemIsMovable, True) item.setFlag(QGraphicsItem.ItemIsSelectable, True) self.addItem(item) item.setPos(inp.position().x(), inp.position().y()) self.paramItems[inp.parameterName()] = item # Input dependency arrows for input_name in list(model.parameterComponents().keys()): idx = 0 parameter_def = model.parameterDefinition(input_name) if hasattr(parameter_def, 'parentLayerParameterName' ) and parameter_def.parentLayerParameterName(): parent_name = parameter_def.parentLayerParameterName() if input_name in self.paramItems and parent_name in self.paramItems: input_item = self.paramItems[input_name] parent_item = self.paramItems[parent_name] arrow = ModelerArrowItem(parent_item, -1, input_item, -1) input_item.addArrow(arrow) parent_item.addArrow(arrow) arrow.setPenStyle(Qt.DotLine) arrow.updatePath() self.addItem(arrow) # We add the algs for alg in list(model.childAlgorithms().values()): item = ModelerGraphicItem(alg, model, controls, scene=self) item.setFlag(QGraphicsItem.ItemIsMovable, True) item.setFlag(QGraphicsItem.ItemIsSelectable, True) self.addItem(item) item.setPos(alg.position().x(), alg.position().y()) self.algItems[alg.childId()] = item # And then the arrows for alg in list(model.childAlgorithms().values()): idx = 0 for parameter in alg.algorithm().parameterDefinitions(): if not parameter.isDestination() and not parameter.flags( ) & QgsProcessingParameterDefinition.FlagHidden: if parameter.name() in alg.parameterSources(): sources = alg.parameterSources()[parameter.name()] else: sources = [] for source in sources: sourceItems = self.getItemsFromParamValue( source, alg.childId(), context) for sourceItem, sourceIdx in sourceItems: arrow = ModelerArrowItem( sourceItem, sourceIdx, self.algItems[alg.childId()], idx) sourceItem.addArrow(arrow) self.algItems[alg.childId()].addArrow(arrow) arrow.updatePath() self.addItem(arrow) idx += 1 for depend in alg.dependencies(): arrow = ModelerArrowItem(self.algItems[depend], -1, self.algItems[alg.childId()], -1) self.algItems[depend].addArrow(arrow) self.algItems[alg.childId()].addArrow(arrow) arrow.updatePath() self.addItem(arrow) # And finally the outputs for alg in list(model.childAlgorithms().values()): outputs = alg.modelOutputs() outputItems = {} idx = 0 for key, out in outputs.items(): if out is not None: item = ModelerGraphicItem(out, model, controls, scene=self) item.setFlag(QGraphicsItem.ItemIsMovable, True) item.setFlag(QGraphicsItem.ItemIsSelectable, True) self.addItem(item) pos = out.position() if pos is None: pos = (alg.position() + QPointF(ModelerGraphicItem.BOX_WIDTH, 0) + self.algItems[ alg.childId()].getLinkPointForOutput(idx)) item.setPos(pos) outputItems[key] = item arrow = ModelerArrowItem(self.algItems[alg.childId()], idx, item, -1) self.algItems[alg.childId()].addArrow(arrow) item.addArrow(arrow) arrow.updatePath() self.addItem(arrow) idx += 1 else: outputItems[key] = None self.outputItems[alg.childId()] = outputItems
def ogrConnectionString(uri): """Generates OGR connection sting from layer source """ ogrstr = None context = dataobjects.createContext() layer = QgsProcessingUtils.mapLayerFromString(uri, context, False) if layer is None: return '"' + uri + '"' provider = layer.dataProvider().name() if provider == 'spatialite': # dbname='/geodata/osm_ch.sqlite' table="places" (Geometry) sql= regex = re.compile("dbname='(.+)'") r = regex.search(str(layer.source())) ogrstr = r.groups()[0] elif provider == 'postgres': # dbname='ktryjh_iuuqef' host=spacialdb.com port=9999 # user='******' password='******' sslmode=disable # key='gid' estimatedmetadata=true srid=4326 type=MULTIPOLYGON # table="t4" (geom) sql= dsUri = QgsDataSourceUri(layer.dataProvider().dataSourceUri()) conninfo = dsUri.connectionInfo() conn = None ok = False while not conn: try: conn = psycopg2.connect(dsUri.connectionInfo()) except psycopg2.OperationalError: (ok, user, passwd) = QgsCredentials.instance().get(conninfo, dsUri.username(), dsUri.password()) if not ok: break dsUri.setUsername(user) dsUri.setPassword(passwd) if not conn: raise RuntimeError('Could not connect to PostgreSQL database - check connection info') if ok: QgsCredentials.instance().put(conninfo, user, passwd) ogrstr = "PG:%s" % dsUri.connectionInfo() elif provider == "oracle": # OCI:user/password@host:port/service:table dsUri = QgsDataSourceUri(layer.dataProvider().dataSourceUri()) ogrstr = "OCI:" if dsUri.username() != "": ogrstr += dsUri.username() if dsUri.password() != "": ogrstr += "/" + dsUri.password() delim = "@" if dsUri.host() != "": ogrstr += delim + dsUri.host() delim = "" if dsUri.port() != "" and dsUri.port() != '1521': ogrstr += ":" + dsUri.port() ogrstr += "/" if dsUri.database() != "": ogrstr += dsUri.database() elif dsUri.database() != "": ogrstr += delim + dsUri.database() if ogrstr == "OCI:": raise RuntimeError('Invalid oracle data source - check connection info') ogrstr += ":" if dsUri.schema() != "": ogrstr += dsUri.schema() + "." ogrstr += dsUri.table() else: ogrstr = str(layer.source()).split("|")[0] return '"' + ogrstr + '"'
def runAlgorithm(algOrName, onFinish, *args, **kwargs): if isinstance(algOrName, GeoAlgorithm): alg = algOrName else: alg = QgsApplication.processingRegistry().algorithmById(algOrName) if alg is None: # fix_print_with_import print('Error: Algorithm not found\n') QgsMessageLog.logMessage( Processing.tr('Error: Algorithm {0} not found\n').format( algOrName), Processing.tr("Processing")) return parameters = {} if len(args) == 1 and isinstance(args[0], dict): # Set params by name and try to run the alg even if not all parameter values are provided, # by using the default values instead. for (name, value) in list(args[0].items()): param = alg.parameterDefinition(name) if param: parameters[param.name()] = value continue # fix_print_with_import print('Error: Wrong parameter value %s for parameter %s.' % (value, name)) QgsMessageLog.logMessage( Processing.tr( 'Error: Wrong parameter value {0} for parameter {1}.'). format(value, name), Processing.tr("Processing")) QgsMessageLog.logMessage( Processing. tr('Error in {0}. Wrong parameter value {1} for parameter {2}.' ).format(alg.name(), value, name), Processing.tr("Processing"), QgsMessageLog.CRITICAL) return # check for any manadatory parameters which were not specified for param in alg.parameterDefinitions(): if param.name() not in parameters: if not param.flags( ) & QgsProcessingParameterDefinition.FlagOptional: # fix_print_with_import print( 'Error: Missing parameter value for parameter %s.' % param.name()) QgsMessageLog.logMessage( Processing. tr('Error: Missing parameter value for parameter {0}.' ).format(param.name()), Processing.tr("Processing")) return else: if len(args) != alg.countVisibleParameters(): # fix_print_with_import print('Error: Wrong number of parameters') QgsMessageLog.logMessage( Processing.tr('Error: Wrong number of parameters'), Processing.tr("Processing")) processing.algorithmHelp(algOrName) return i = 0 for param in alg.parameterDefinitions(): if not param.flags( ) & QgsProcessingParameterDefinition.FlagHidden: if not True: # TODO param.setValue(args[i]): # fix_print_with_import print('Error: Wrong parameter value: ' + str(args[i])) QgsMessageLog.logMessage( Processing.tr('Error: Wrong parameter value: ') + str(args[i]), Processing.tr("Processing")) return else: parameters[param.name()] = args[i] i = i + 1 for output in alg.outputs: if not output.flags( ) & QgsProcessingParameterDefinition.FlagHidden: if not output.setValue(args[i]): # fix_print_with_import print('Error: Wrong output value: ' + str(args[i])) QgsMessageLog.logMessage( Processing.tr('Error: Wrong output value: ') + str(args[i]), Processing.tr("Processing")) return i = i + 1 context = None if kwargs is not None and 'context' in list(kwargs.keys()): context = kwargs["context"] else: context = dataobjects.createContext() ok, msg = alg.checkParameterValues(parameters, context) if not ok: # fix_print_with_import print('Unable to execute algorithm\n' + str(msg)) QgsMessageLog.logMessage( Processing.tr('Unable to execute algorithm\n{0}').format(msg), Processing.tr("Processing")) return if not alg.validateInputCrs(parameters, context): print('Warning: Not all input layers use the same CRS.\n' + 'This can cause unexpected results.') QgsMessageLog.logMessage( Processing. tr('Warning: Not all input layers use the same CRS.\nThis can cause unexpected results.' ), Processing.tr("Processing")) # Don't set the wait cursor twice, because then when you # restore it, it will still be a wait cursor. overrideCursor = False if iface is not None: cursor = QApplication.overrideCursor() if cursor is None or cursor == 0: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) overrideCursor = True elif cursor.shape() != Qt.WaitCursor: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) overrideCursor = True feedback = None if kwargs is not None and "feedback" in list(kwargs.keys()): feedback = kwargs["feedback"] elif iface is not None: feedback = MessageBarProgress(alg.displayName()) ret, results = execute(alg, parameters, context, feedback) if ret: if onFinish is not None: onFinish(alg, context, feedback) else: QgsMessageLog.logMessage( Processing.tr("There were errors executing the algorithm."), Processing.tr("Processing")) if overrideCursor: QApplication.restoreOverrideCursor() if isinstance(feedback, MessageBarProgress): feedback.close() return results
def runAlgorithm(self): alg_parameters = [] feedback = self.createFeedback() load_layers = self.mainWidget().checkLoadLayersOnCompletion.isChecked() project = QgsProject.instance() if load_layers else None for row in range(self.mainWidget().batchRowCount()): parameters = self.mainWidget().parametersForRow(row, destinationProject=project, warnOnInvalid=True) alg_parameters.append(parameters) task = QgsScopedProxyProgressTask(self.tr('Batch Processing - {0}').format(self.algorithm().displayName())) multi_feedback = BatchFeedback(len(alg_parameters), feedback) feedback.progressChanged.connect(task.setProgress) algorithm_results = [] errors = [] with OverrideCursor(Qt.WaitCursor): self.mainWidget().setEnabled(False) self.cancelButton().setEnabled(True) # Make sure the Log tab is visible before executing the algorithm try: self.showLog() self.repaint() except Exception: # FIXME which one? pass start_time = time.time() for count, parameters in enumerate(alg_parameters): if feedback.isCanceled(): break self.setProgressText( QCoreApplication.translate('BatchAlgorithmDialog', '\nProcessing algorithm {0}/{1}…').format( count + 1, len(alg_parameters))) self.setInfo(self.tr('<b>Algorithm {0} starting…</b>').format(self.algorithm().displayName()), escapeHtml=False) multi_feedback.setCurrentStep(count) parameters = self.algorithm().preprocessParameters(parameters) feedback.pushInfo(self.tr('Input parameters:')) feedback.pushCommandInfo(pformat(parameters)) feedback.pushInfo('') # important - we create a new context for each iteration # this avoids holding onto resources and layers from earlier iterations, # and allows batch processing of many more items then is possible # if we hold on to these layers context = dataobjects.createContext(feedback) alg_start_time = time.time() multi_feedback.errors = [] results, ok = self.algorithm().run(parameters, context, multi_feedback) if ok: self.setInfo( QCoreApplication.translate('BatchAlgorithmDialog', 'Algorithm {0} correctly executed…').format( self.algorithm().displayName()), escapeHtml=False) feedback.pushInfo( self.tr('Execution completed in {0:0.2f} seconds'.format(time.time() - alg_start_time))) feedback.pushInfo(self.tr('Results:')) feedback.pushCommandInfo(pformat(results)) feedback.pushInfo('') algorithm_results.append({'parameters': parameters, 'results': results}) handleAlgorithmResults(self.algorithm(), context, multi_feedback, False, parameters) else: err = [e for e in multi_feedback.errors] self.setInfo( QCoreApplication.translate('BatchAlgorithmDialog', 'Algorithm {0} failed…').format( self.algorithm().displayName()), escapeHtml=False) feedback.reportError( self.tr('Execution failed after {0:0.2f} seconds'.format(time.time() - alg_start_time)), fatalError=False) errors.append({'parameters': parameters, 'errors': err}) feedback.pushInfo(self.tr('Batch execution completed in {0:0.2f} seconds'.format(time.time() - start_time))) if errors: feedback.reportError(self.tr('{} executions failed. See log for further details.').format(len(errors)), fatalError=True) task = None self.finish(algorithm_results, errors) self.cancelButton().setEnabled(False)
def accept(self): alg_parameters = [] feedback = self.createFeedback() load_layers = self.mainWidget().checkLoadLayersOnCompletion.isChecked() project = QgsProject.instance() if load_layers else None for row in range(self.mainWidget().tblParameters.rowCount()): col = 0 parameters = {} for param in self.algorithm().parameterDefinitions(): if param.flags( ) & QgsProcessingParameterDefinition.FlagHidden or param.isDestination( ): continue wrapper = self.mainWidget().wrappers[row][col] parameters[param.name()] = wrapper.value() if not param.checkValueIsAcceptable(wrapper.value()): self.messageBar().pushMessage( "", self.tr( 'Wrong or missing parameter value: {0} (row {1})'). format(param.description(), row + 1), level=Qgis.Warning, duration=5) return col += 1 count_visible_outputs = 0 for out in self.algorithm().destinationParameterDefinitions(): if out.flags() & QgsProcessingParameterDefinition.FlagHidden: continue count_visible_outputs += 1 widget = self.mainWidget().tblParameters.cellWidget(row, col) text = widget.getValue() if out.checkValueIsAcceptable(text): if isinstance(out, (QgsProcessingParameterRasterDestination, QgsProcessingParameterFeatureSink)): # load rasters and sinks on completion parameters[ out.name()] = QgsProcessingOutputLayerDefinition( text, project) else: parameters[out.name()] = text col += 1 else: self.messageBar().pushMessage( "", self.tr('Wrong or missing output value: {0} (row {1})' ).format(out.description(), row + 1), level=Qgis.Warning, duration=5) return alg_parameters.append(parameters) with OverrideCursor(Qt.WaitCursor): self.mainWidget().setEnabled(False) self.cancelButton().setEnabled(True) # Make sure the Log tab is visible before executing the algorithm try: self.showLog() self.repaint() except: pass start_time = time.time() algorithm_results = [] for count, parameters in enumerate(alg_parameters): if feedback.isCanceled(): break self.setProgressText( QCoreApplication.translate( 'BatchAlgorithmDialog', '\nProcessing algorithm {0}/{1}…').format( count + 1, len(alg_parameters))) self.setInfo( self.tr('<b>Algorithm {0} starting…</b>').format( self.algorithm().displayName()), escapeHtml=False) feedback.pushInfo(self.tr('Input parameters:')) feedback.pushCommandInfo(pformat(parameters)) feedback.pushInfo('') # important - we create a new context for each iteration # this avoids holding onto resources and layers from earlier iterations, # and allows batch processing of many more items then is possible # if we hold on to these layers context = dataobjects.createContext(feedback) alg_start_time = time.time() ret, results = execute(self.algorithm(), parameters, context, feedback) if ret: self.setInfo(QCoreApplication.translate( 'BatchAlgorithmDialog', 'Algorithm {0} correctly executed…').format( self.algorithm().displayName()), escapeHtml=False) feedback.setProgress(100) feedback.pushInfo( self.tr( 'Execution completed in {0:0.2f} seconds'.format( time.time() - alg_start_time))) feedback.pushInfo(self.tr('Results:')) feedback.pushCommandInfo(pformat(results)) feedback.pushInfo('') algorithm_results.append(results) else: break handleAlgorithmResults(self.algorithm(), context, feedback, False) feedback.pushInfo( self.tr('Batch execution completed in {0:0.2f} seconds'.format( time.time() - start_time))) self.finish(algorithm_results) self.cancelButton().setEnabled(False)
def runAlgorithm(algOrName, parameters, onFinish=None, feedback=None, context=None): if isinstance(algOrName, QgsProcessingAlgorithm): alg = algOrName else: alg = QgsApplication.processingRegistry().createAlgorithmById( algOrName) if feedback is None: feedback = QgsProcessingFeedback() if alg is None: msg = Processing.tr('Error: Algorithm {0} not found\n').format( algOrName) feedback.reportError(msg) raise QgsProcessingException(msg) if context is None: context = dataobjects.createContext(feedback) if context.feedback() is None: context.setFeedback(feedback) ok, msg = alg.checkParameterValues(parameters, context) if not ok: msg = Processing.tr('Unable to execute algorithm\n{0}').format(msg) feedback.reportError(msg) raise QgsProcessingException(msg) if not alg.validateInputCrs(parameters, context): feedback.pushInfo( Processing. tr('Warning: Not all input layers use the same CRS.\nThis can cause unexpected results.' )) ret, results = execute(alg, parameters, context, feedback) if ret: feedback.pushInfo(Processing.tr('Results: {}').format(results)) if onFinish is not None: onFinish(alg, context, feedback) else: # auto convert layer references in results to map layers for out in alg.outputDefinitions(): if out.name() not in results: continue if isinstance(out, (QgsProcessingOutputVectorLayer, QgsProcessingOutputRasterLayer, QgsProcessingOutputMapLayer)): result = results[out.name()] if not isinstance(result, QgsMapLayer): layer = context.takeResultLayer( result ) # transfer layer ownership out of context if layer: results[out.name( )] = layer # replace layer string ref with actual layer (+ownership) elif isinstance(out, QgsProcessingOutputMultipleLayers): result = results[out.name()] if result: layers_result = [] for l in result: if not isinstance(result, QgsMapLayer): layer = context.takeResultLayer( l ) # transfer layer ownership out of context if layer: layers_result.append(layer) else: layers_result.append(l) else: layers_result.append(l) results[out.name( )] = layers_result # replace layers strings ref with actual layers (+ownership) else: msg = Processing.tr("There were errors executing the algorithm.") feedback.reportError(msg) raise QgsProcessingException(msg) if isinstance(feedback, MessageBarProgress): feedback.close() return results
def save(self): toSave = [] context = dataobjects.createContext() for row in range(self.batchRowCount()): algParams = {} algOutputs = {} col = 0 alg = self.alg for param in alg.parameterDefinitions(): if param.flags() & QgsProcessingParameterDefinition.FlagHidden: continue if param.isDestination(): continue wrapper = self.wrappers[row][col] # For compatibility with 3.x API, we need to check whether the wrapper is # the deprecated WidgetWrapper class. If not, it's the newer # QgsAbstractProcessingParameterWidgetWrapper class # TODO QGIS 4.0 - remove if issubclass(wrapper.__class__, WidgetWrapper): widget = wrapper.widget else: widget = wrapper.wrappedWidget() value = wrapper.parameterValue() if not param.checkValueIsAcceptable(value, context): self.parent.messageBar().pushMessage("", self.tr( 'Wrong or missing parameter value: {0} (row {1})').format( param.description(), row + 1), level=Qgis.Warning, duration=5) return algParams[param.name()] = param.valueAsPythonString(value, context) col += 1 for out in alg.destinationParameterDefinitions(): if out.flags() & QgsProcessingParameterDefinition.FlagHidden: continue widget = self.tblParameters.cellWidget(row + 1, col) text = widget.getValue() if text.strip() != '': algOutputs[out.name()] = text.strip() col += 1 else: self.parent.messageBar().pushMessage("", self.tr('Wrong or missing output value: {0} (row {1})').format( out.description(), row + 1), level=Qgis.Warning, duration=5) return toSave.append({self.PARAMETERS: algParams, self.OUTPUTS: algOutputs}) settings = QgsSettings() last_path = settings.value("/Processing/LastBatchPath", QDir.homePath()) filename, __ = QFileDialog.getSaveFileName(self, self.tr('Save Batch'), last_path, self.tr('JSON files (*.json)')) if filename: if not filename.endswith('.json'): filename += '.json' last_path = QFileInfo(filename).path() settings.setValue('/Processing/LastBatchPath', last_path) with open(filename, 'w') as f: json.dump(toSave, f)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.context = dataobjects.createContext()
def execute_in_place_run(alg, parameters, context=None, feedback=None, raise_exceptions=False): """Executes an algorithm modifying features in-place in the input layer. :param alg: algorithm to run :type alg: QgsProcessingAlgorithm :param parameters: parameters of the algorithm :type parameters: dict :param context: context, defaults to None :type context: QgsProcessingContext, optional :param feedback: feedback, defaults to None :type feedback: QgsProcessingFeedback, optional :param raise_exceptions: useful for testing, if True exceptions are raised, normally exceptions will be forwarded to the feedback :type raise_exceptions: boo, default to False :raises QgsProcessingException: raised when there is no active layer, or it cannot be made editable :return: a tuple with true if success and results :rtype: tuple """ if feedback is None: feedback = QgsProcessingFeedback() if context is None: context = dataobjects.createContext(feedback) active_layer = parameters['INPUT'] # Run some checks and prepare the layer for in-place execution by: # - getting the active layer and checking that it is a vector # - making the layer editable if it was not already # - selecting all features if none was selected # - checking in-place support for the active layer/alg/parameters # If one of the check fails and raise_exceptions is True an exception # is raised, else the execution is aborted and the error reported in # the feedback try: if active_layer is None: raise QgsProcessingException(tr("There is not active layer.")) if not isinstance(active_layer, QgsVectorLayer): raise QgsProcessingException( tr("Active layer is not a vector layer.")) if not active_layer.isEditable(): if not active_layer.startEditing(): raise QgsProcessingException( tr("Active layer is not editable (and editing could not be turned on)." )) if not alg.supportInPlaceEdit(active_layer): raise QgsProcessingException( tr("Selected algorithm and parameter configuration are not compatible with in-place modifications." )) except QgsProcessingException as e: if raise_exceptions: raise e QgsMessageLog.logMessage(str(sys.exc_info()[0]), 'Processing', Qgis.Critical) if feedback is not None: feedback.reportError(getattr(e, 'msg', str(e)), fatalError=True) return False, {} if not active_layer.selectedFeatureIds(): active_layer.selectAll() parameters['OUTPUT'] = 'memory:' # Start the execution # If anything goes wrong and raise_exceptions is True an exception # is raised, else the execution is aborted and the error reported in # the feedback try: new_feature_ids = [] active_layer.beginEditCommand(alg.displayName()) req = QgsFeatureRequest(QgsExpression(r"$id < 0")) req.setFlags(QgsFeatureRequest.NoGeometry) req.setSubsetOfAttributes([]) # Checks whether the algorithm has a processFeature method if hasattr(alg, 'processFeature'): # in-place feature editing # Make a clone or it will crash the second time the dialog # is opened and run alg = alg.create() if not alg.prepare(parameters, context, feedback): raise QgsProcessingException( tr("Could not prepare selected algorithm.")) # Check again for compatibility after prepare if not alg.supportInPlaceEdit(active_layer): raise QgsProcessingException( tr("Selected algorithm and parameter configuration are not compatible with in-place modifications." )) field_idxs = range(len(active_layer.fields())) feature_iterator = active_layer.getFeatures( QgsFeatureRequest(active_layer.selectedFeatureIds())) step = 100 / len(active_layer.selectedFeatureIds() ) if active_layer.selectedFeatureIds() else 1 for current, f in enumerate(feature_iterator): feedback.setProgress(current * step) if feedback.isCanceled(): break # need a deep copy, because python processFeature implementations may return # a shallow copy from processFeature input_feature = QgsFeature(f) new_features = alg.processFeature(input_feature, context, feedback) new_features = QgsVectorLayerUtils.makeFeaturesCompatible( new_features, active_layer) if len(new_features) == 0: active_layer.deleteFeature(f.id()) elif len(new_features) == 1: new_f = new_features[0] if not f.geometry().equals(new_f.geometry()): active_layer.changeGeometry(f.id(), new_f.geometry()) if f.attributes() != new_f.attributes(): active_layer.changeAttributeValues( f.id(), dict(zip(field_idxs, new_f.attributes())), dict(zip(field_idxs, f.attributes()))) new_feature_ids.append(f.id()) else: active_layer.deleteFeature(f.id()) # Get the new ids old_ids = set( [f.id() for f in active_layer.getFeatures(req)]) if not active_layer.addFeatures(new_features): raise QgsProcessingException( tr("Error adding processed features back into the layer." )) new_ids = set( [f.id() for f in active_layer.getFeatures(req)]) new_feature_ids += list(new_ids - old_ids) results, ok = {}, True else: # Traditional 'run' with delete and add features cycle results, ok = alg.run(parameters, context, feedback) if ok: result_layer = QgsProcessingUtils.mapLayerFromString( results['OUTPUT'], context) # TODO: check if features have changed before delete/add cycle active_layer.deleteFeatures(active_layer.selectedFeatureIds()) new_features = [] for f in result_layer.getFeatures(): new_features.extend( QgsVectorLayerUtils.makeFeaturesCompatible( [f], active_layer)) # Get the new ids old_ids = set([f.id() for f in active_layer.getFeatures(req)]) if not active_layer.addFeatures(new_features): raise QgsProcessingException( tr("Error adding processed features back into the layer." )) new_ids = set([f.id() for f in active_layer.getFeatures(req)]) new_feature_ids += list(new_ids - old_ids) active_layer.endEditCommand() if ok and new_feature_ids: active_layer.selectByIds(new_feature_ids) elif not ok: active_layer.rollBack() return ok, results except QgsProcessingException as e: active_layer.endEditCommand() active_layer.rollBack() if raise_exceptions: raise e QgsMessageLog.logMessage(str(sys.exc_info()[0]), 'Processing', Qgis.Critical) if feedback is not None: feedback.reportError(getattr(e, 'msg', str(e)), fatalError=True) return False, {}
def accept(self): super(AlgorithmDialog, self)._saveGeometry() context = dataobjects.createContext() checkCRS = ProcessingConfig.getSetting( ProcessingConfig.WARN_UNMATCHING_CRS) try: parameters = self.getParamValues() QgsMessageLog.logMessage(str(parameters), 'Processing', QgsMessageLog.CRITICAL) # TODO if False and checkCRS and not self.alg.checkInputCRS(): reply = QMessageBox.question( self, self.tr("Unmatching CRS's"), self.tr('Layers do not all use the same CRS. This can ' 'cause unexpected results.\nDo you want to ' 'continue?'), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.No: return checkExtentCRS = ProcessingConfig.getSetting( ProcessingConfig.WARN_UNMATCHING_EXTENT_CRS) #TODO if False and checkExtentCRS and self.checkExtentCRS(): reply = QMessageBox.question( self, self.tr("Extent CRS"), self. tr('Extent parameters must use the same CRS as the input layers.\n' 'Your input layers do not have the same extent as the project, ' 'so the extent might be in a wrong CRS if you have selected it from the canvas.\n' 'Do you want to continue?'), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.No: return ok, msg = self.alg.checkParameterValues(parameters, context) if msg: QMessageBox.warning(self, self.tr('Unable to execute algorithm'), msg) return self.btnRun.setEnabled(False) self.btnClose.setEnabled(False) buttons = self.mainWidget.iterateButtons self.iterateParam = None for i in range(len(list(buttons.values()))): button = list(buttons.values())[i] if button.isChecked(): self.iterateParam = list(buttons.keys())[i] break self.progressBar.setMaximum(0) self.lblProgress.setText(self.tr('Processing algorithm...')) # Make sure the Log tab is visible before executing the algorithm try: self.tabWidget.setCurrentIndex(1) self.repaint() except: pass QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.setInfo( self.tr('<b>Algorithm {0} starting...</b>').format( self.alg.displayName())) if self.iterateParam: if executeIterating(self.alg, parameters, self.iterateParam, context, self.feedback): self.finish(parameters, context) else: QApplication.restoreOverrideCursor() self.resetGUI() else: # TODO #command = self.alg.getAsCommand() #if command: # ProcessingLog.addToLog(command) self.buttonCancel.setEnabled( self.alg.flags() & QgsProcessingAlgorithm.FlagCanCancel) result = executeAlgorithm(self.alg, parameters, context, self.feedback) self.buttonCancel.setEnabled(False) self.finish(result, context) #TODO #else: # QApplication.restoreOverrideCursor() # self.resetGUI() except AlgorithmDialogBase.InvalidParameterValue as e: try: self.buttonBox.accepted.connect( lambda e=e: e.widget.setPalette(QPalette())) palette = e.widget.palette() palette.setColor(QPalette.Base, QColor(255, 255, 0)) e.widget.setPalette(palette) except: pass self.bar.clearWidgets() self.bar.pushMessage( "", self.tr("Wrong or missing parameter value: {0}").format( e.parameter.description()), level=QgsMessageBar.WARNING, duration=5)
def execute_in_place_run(alg, parameters, context=None, feedback=None, raise_exceptions=False): """Executes an algorithm modifying features in-place in the input layer. :param alg: algorithm to run :type alg: QgsProcessingAlgorithm :param parameters: parameters of the algorithm :type parameters: dict :param context: context, defaults to None :type context: QgsProcessingContext, optional :param feedback: feedback, defaults to None :type feedback: QgsProcessingFeedback, optional :param raise_exceptions: useful for testing, if True exceptions are raised, normally exceptions will be forwarded to the feedback :type raise_exceptions: boo, default to False :raises QgsProcessingException: raised when there is no active layer, or it cannot be made editable :return: a tuple with true if success and results :rtype: tuple """ if feedback is None: feedback = QgsProcessingFeedback() if context is None: context = dataobjects.createContext(feedback) # Only feature based algs have sourceFlags try: if alg.sourceFlags() & QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks: context.setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck) except AttributeError: pass in_place_input_parameter_name = 'INPUT' if hasattr(alg, 'inputParameterName'): in_place_input_parameter_name = alg.inputParameterName() active_layer = parameters[in_place_input_parameter_name] # prepare expression context for feature iteration alg_context = context.expressionContext() alg_context.appendScope(active_layer.createExpressionContextScope()) context.setExpressionContext(alg_context) # Run some checks and prepare the layer for in-place execution by: # - getting the active layer and checking that it is a vector # - making the layer editable if it was not already # - selecting all features if none was selected # - checking in-place support for the active layer/alg/parameters # If one of the check fails and raise_exceptions is True an exception # is raised, else the execution is aborted and the error reported in # the feedback try: if active_layer is None: raise QgsProcessingException(tr("There is no active layer.")) if not isinstance(active_layer, QgsVectorLayer): raise QgsProcessingException(tr("Active layer is not a vector layer.")) if not active_layer.isEditable(): if not active_layer.startEditing(): raise QgsProcessingException(tr("Active layer is not editable (and editing could not be turned on).")) if not alg.supportInPlaceEdit(active_layer): raise QgsProcessingException(tr("Selected algorithm and parameter configuration are not compatible with in-place modifications.")) except QgsProcessingException as e: if raise_exceptions: raise e QgsMessageLog.logMessage(str(sys.exc_info()[0]), 'Processing', Qgis.Critical) if feedback is not None: feedback.reportError(getattr(e, 'msg', str(e)), fatalError=True) return False, {} if not active_layer.selectedFeatureIds(): active_layer.selectAll() # Make sure we are working on selected features only parameters[in_place_input_parameter_name] = QgsProcessingFeatureSourceDefinition(active_layer.id(), True) parameters['OUTPUT'] = 'memory:' req = QgsFeatureRequest(QgsExpression(r"$id < 0")) req.setFlags(QgsFeatureRequest.NoGeometry) req.setSubsetOfAttributes([]) # Start the execution # If anything goes wrong and raise_exceptions is True an exception # is raised, else the execution is aborted and the error reported in # the feedback try: new_feature_ids = [] active_layer.beginEditCommand(alg.displayName()) # Checks whether the algorithm has a processFeature method if hasattr(alg, 'processFeature'): # in-place feature editing # Make a clone or it will crash the second time the dialog # is opened and run alg = alg.create({'IN_PLACE': True}) if not alg.prepare(parameters, context, feedback): raise QgsProcessingException(tr("Could not prepare selected algorithm.")) # Check again for compatibility after prepare if not alg.supportInPlaceEdit(active_layer): raise QgsProcessingException(tr("Selected algorithm and parameter configuration are not compatible with in-place modifications.")) # some algorithms have logic in outputFields/outputCrs/outputWkbType which they require to execute before # they can start processing features _ = alg.outputFields(active_layer.fields()) _ = alg.outputWkbType(active_layer.wkbType()) _ = alg.outputCrs(active_layer.crs()) field_idxs = range(len(active_layer.fields())) iterator_req = QgsFeatureRequest(active_layer.selectedFeatureIds()) iterator_req.setInvalidGeometryCheck(context.invalidGeometryCheck()) feature_iterator = active_layer.getFeatures(iterator_req) step = 100 / len(active_layer.selectedFeatureIds()) if active_layer.selectedFeatureIds() else 1 current = 0 for current, f in enumerate(feature_iterator): if feedback.isCanceled(): break # need a deep copy, because python processFeature implementations may return # a shallow copy from processFeature input_feature = QgsFeature(f) context.expressionContext().setFeature(input_feature) new_features = alg.processFeature(input_feature, context, feedback) new_features = QgsVectorLayerUtils.makeFeaturesCompatible(new_features, active_layer) if len(new_features) == 0: active_layer.deleteFeature(f.id()) elif len(new_features) == 1: new_f = new_features[0] if not f.geometry().equals(new_f.geometry()): active_layer.changeGeometry(f.id(), new_f.geometry()) if f.attributes() != new_f.attributes(): active_layer.changeAttributeValues(f.id(), dict(zip(field_idxs, new_f.attributes())), dict(zip(field_idxs, f.attributes()))) new_feature_ids.append(f.id()) else: active_layer.deleteFeature(f.id()) # Get the new ids old_ids = set([f.id() for f in active_layer.getFeatures(req)]) # If multiple new features were created, we need to pass # them to createFeatures to manage constraints correctly features_data = [] for f in new_features: features_data.append(QgsVectorLayerUtils.QgsFeatureData(f.geometry(), dict(enumerate(f.attributes())))) new_features = QgsVectorLayerUtils.createFeatures(active_layer, features_data, context.expressionContext()) if not active_layer.addFeatures(new_features): raise QgsProcessingException(tr("Error adding processed features back into the layer.")) new_ids = set([f.id() for f in active_layer.getFeatures(req)]) new_feature_ids += list(new_ids - old_ids) feedback.setProgress(int((current + 1) * step)) results, ok = {'__count': current + 1}, True else: # Traditional 'run' with delete and add features cycle # There is no way to know if some features have been skipped # due to invalid geometries if context.invalidGeometryCheck() == QgsFeatureRequest.GeometrySkipInvalid: selected_ids = active_layer.selectedFeatureIds() else: selected_ids = [] results, ok = alg.run(parameters, context, feedback, configuration={'IN_PLACE': True}) if ok: result_layer = QgsProcessingUtils.mapLayerFromString(results['OUTPUT'], context) # TODO: check if features have changed before delete/add cycle new_features = [] # Check if there are any skipped features if context.invalidGeometryCheck() == QgsFeatureRequest.GeometrySkipInvalid: missing_ids = list(set(selected_ids) - set(result_layer.allFeatureIds())) if missing_ids: for f in active_layer.getFeatures(QgsFeatureRequest(missing_ids)): if not f.geometry().isGeosValid(): new_features.append(f) active_layer.deleteFeatures(active_layer.selectedFeatureIds()) regenerate_primary_key = result_layer.customProperty('OnConvertFormatRegeneratePrimaryKey', False) sink_flags = QgsFeatureSink.SinkFlags(QgsFeatureSink.RegeneratePrimaryKey) if regenerate_primary_key \ else QgsFeatureSink.SinkFlags() for f in result_layer.getFeatures(): new_features.extend(QgsVectorLayerUtils. makeFeaturesCompatible([f], active_layer, sink_flags)) # Get the new ids old_ids = set([f.id() for f in active_layer.getFeatures(req)]) if not active_layer.addFeatures(new_features): raise QgsProcessingException(tr("Error adding processed features back into the layer.")) new_ids = set([f.id() for f in active_layer.getFeatures(req)]) new_feature_ids += list(new_ids - old_ids) results['__count'] = len(new_feature_ids) active_layer.endEditCommand() if ok and new_feature_ids: active_layer.selectByIds(new_feature_ids) elif not ok: active_layer.rollBack() return ok, results except QgsProcessingException as e: active_layer.endEditCommand() active_layer.rollBack() if raise_exceptions: raise e QgsMessageLog.logMessage(str(sys.exc_info()[0]), 'Processing', Qgis.Critical) if feedback is not None: feedback.reportError(getattr(e, 'msg', str(e)), fatalError=True) return False, {}
def accept(self): super(AlgorithmDialog, self)._saveGeometry() feedback = self.createFeedback() context = dataobjects.createContext(feedback) checkCRS = ProcessingConfig.getSetting( ProcessingConfig.WARN_UNMATCHING_CRS) try: parameters = self.getParamValues() if checkCRS and not self.alg.validateInputCrs(parameters, context): reply = QMessageBox.question( self, self.tr("Unmatching CRS's"), self.tr('Layers do not all use the same CRS. This can ' 'cause unexpected results.\nDo you want to ' 'continue?'), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.No: return checkExtentCRS = ProcessingConfig.getSetting( ProcessingConfig.WARN_UNMATCHING_EXTENT_CRS) # TODO if False and checkExtentCRS and self.checkExtentCRS(): reply = QMessageBox.question( self, self.tr("Extent CRS"), self. tr('Extent parameters must use the same CRS as the input layers.\n' 'Your input layers do not have the same extent as the project, ' 'so the extent might be in a wrong CRS if you have selected it from the canvas.\n' 'Do you want to continue?'), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.No: return ok, msg = self.alg.checkParameterValues(parameters, context) if msg: QMessageBox.warning(self, self.tr('Unable to execute algorithm'), msg) return self.btnRun.setEnabled(False) self.btnClose.setEnabled(False) buttons = self.mainWidget.iterateButtons self.iterateParam = None for i in range(len(list(buttons.values()))): button = list(buttons.values())[i] if button.isChecked(): self.iterateParam = list(buttons.keys())[i] break self.progressBar.setMaximum(0) self.lblProgress.setText(self.tr('Processing algorithm...')) # Make sure the Log tab is visible before executing the algorithm try: self.tabWidget.setCurrentIndex(1) self.repaint() except: pass self.setInfo( self.tr('<b>Algorithm \'{0}\' starting...</b>').format( self.alg.displayName()), escape_html=False) feedback.pushInfo(self.tr('Input parameters:')) display_params = [] for k, v in parameters.items(): display_params.append("'" + k + "' : " + self.alg.parameterDefinition( k).valueAsPythonString(v, context)) feedback.pushCommandInfo('{ ' + ', '.join(display_params) + ' }') feedback.pushInfo('') start_time = time.time() if self.iterateParam: self.buttonCancel.setEnabled( self.alg.flags() & QgsProcessingAlgorithm.FlagCanCancel) if executeIterating(self.alg, parameters, self.iterateParam, context, feedback): feedback.pushInfo( self.tr( 'Execution completed in {0:0.2f} seconds'.format( time.time() - start_time))) self.buttonCancel.setEnabled(False) self.finish(True, parameters, context, feedback) else: self.buttonCancel.setEnabled(False) self.resetGUI() else: command = self.alg.asPythonCommand(parameters, context) if command: ProcessingLog.addToLog(command) self.buttonCancel.setEnabled( self.alg.flags() & QgsProcessingAlgorithm.FlagCanCancel) def on_complete(ok, results): if ok: feedback.pushInfo( self.tr('Execution completed in {0:0.2f} seconds'. format(time.time() - start_time))) feedback.pushInfo(self.tr('Results:')) feedback.pushCommandInfo(pformat(results)) else: feedback.reportError( self.tr('Execution failed after {0:0.2f} seconds'. format(time.time() - start_time))) feedback.pushInfo('') self.buttonCancel.setEnabled(False) self.finish(ok, results, context, feedback) task = QgsProcessingAlgRunnerTask(self.alg, parameters, context, feedback) task.executed.connect(on_complete) QgsApplication.taskManager().addTask(task) except AlgorithmDialogBase.InvalidParameterValue as e: try: self.buttonBox.accepted.connect( lambda e=e: e.widget.setPalette(QPalette())) palette = e.widget.palette() palette.setColor(QPalette.Base, QColor(255, 255, 0)) e.widget.setPalette(palette) except: pass self.bar.clearWidgets() self.bar.pushMessage( "", self.tr("Wrong or missing parameter value: {0}").format( e.parameter.description()), level=QgsMessageBar.WARNING, duration=5)
def getParameterValues(self): parameters = {} if self.mainWidget() is None: return parameters for param in self.algorithm().parameterDefinitions(): if param.flags() & QgsProcessingParameterDefinition.FlagHidden: continue if not param.isDestination(): if self.in_place and param.name() == 'INPUT': parameters[param.name()] = self.active_layer continue try: wrapper = self.mainWidget().wrappers[param.name()] except KeyError: continue # For compatibility with 3.x API, we need to check whether the wrapper is # the deprecated WidgetWrapper class. If not, it's the newer # QgsAbstractProcessingParameterWidgetWrapper class # TODO QGIS 4.0 - remove if issubclass(wrapper.__class__, WidgetWrapper): widget = wrapper.widget else: widget = wrapper.wrappedWidget() if widget is None: continue value = wrapper.parameterValue() parameters[param.name()] = value if not param.checkValueIsAcceptable(value): raise AlgorithmDialogBase.InvalidParameterValue( param, widget) else: if self.in_place and param.name() == 'OUTPUT': parameters[param.name()] = 'memory:' continue dest_project = None if not param.flags() & QgsProcessingParameterDefinition.FlagHidden and \ isinstance(param, (QgsProcessingParameterRasterDestination, QgsProcessingParameterFeatureSink, QgsProcessingParameterVectorDestination)): if self.mainWidget().checkBoxes[param.name()].isChecked(): dest_project = QgsProject.instance() widget = self.mainWidget().outputWidgets[param.name()] value = widget.getValue() if value and isinstance(value, QgsProcessingOutputLayerDefinition): value.destinationProject = dest_project if value: parameters[param.name()] = value if param.isDestination(): context = dataobjects.createContext() ok, error = self.algorithm().provider( ).isSupportedOutputValue(value, param, context) if not ok: raise AlgorithmDialogBase.InvalidOutputExtension( widget, error) return self.algorithm().preprocessParameters(parameters)
def rasterize_vectors_and_load_to_db( grassdb, grass_location, qgis_prefix_path, mask, vector_path, attribue_name, raster_name, ): QgsApplication.setPrefixPath(qgis_prefix_path, True) Qgs = QgsApplication([], False) Qgs.initQgis() from processing.core.Processing import Processing from processing.tools import dataobjects from qgis import processing feedback = QgsProcessingFeedback() Processing.initialize() QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms()) context = dataobjects.createContext() context.setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck) mask_layer = qgis_raster_read_raster( processing, os.path.join(grassdb, mask + ".tif") ) ### load DEM raster as a QGIS raster object to obtain attribute cellSize, SpRef_in = qgis_raster_return_raster_properties( processing, mask_layer) ### Get Raster cell size # load grass working location import grass.script as grass import grass.script.setup as gsetup from grass.pygrass.modules import Module from grass.pygrass.modules.shortcuts import general as g from grass.pygrass.modules.shortcuts import raster as r from grass.script import array as garray from grass.script import core as gcore from grass_session import Session os.environ.update( dict(GRASS_COMPRESS_NULLS="1", GRASS_COMPRESSOR="ZSTD", GRASS_VERBOSE="1")) PERMANENT = Session() PERMANENT.open(gisdb=grassdb, location=grass_location, create_opts="") # get dem array and get nrows and ncols of the domain strtemp_array = Return_Raster_As_Array_With_garray(garray, mask) ncols = int(strtemp_array.shape[1]) nrows = int(strtemp_array.shape[0]) grsregion = gcore.region() qgis_raster_gdal_rasterize( processing, context, INPUT=vector_path, Column_nm=attribue_name, cellsize=cellSize, w=grsregion["w"], s=grsregion["s"], e=grsregion["e"], n=grsregion["n"], OUTPUT=os.path.join(grassdb, raster_name + ".tif"), ) grass_raster_r_in_gdal( grass, raster_path=os.path.join(grassdb, raster_name + ".tif"), output_nm=raster_name, ) grass_raster_setnull(grass, raster_nm=raster_name, null_values=[-9999], create_new_raster=False) grass_raster_v_import(grass, input_path=vector_path, output_vector_nm=raster_name) Qgs.exit() PERMANENT.close()
def __init__(self, param, dialog, row=0, col=0, **kwargs): super().__init__(param, dialog, row, col, **kwargs) self.context = dataobjects.createContext()
def runAlgorithm(self): self.feedback = self.createFeedback() self.context = dataobjects.createContext(self.feedback) checkCRS = ProcessingConfig.getSetting( ProcessingConfig.WARN_UNMATCHING_CRS) try: parameters = self.createProcessingParameters() if checkCRS and not self.algorithm().validateInputCrs( parameters, self.context): reply = QMessageBox.question( self, self.tr("Unmatching CRS's"), self.tr('Parameters do not all use the same CRS. This can ' 'cause unexpected results.\nDo you want to ' 'continue?'), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.No: return ok, msg = self.algorithm().checkParameterValues( parameters, self.context) if not ok: QMessageBox.warning(self, self.tr('Unable to execute algorithm'), msg) return self.blockControlsWhileRunning() self.setExecutedAnyResult(True) self.cancelButton().setEnabled(False) self.iterateParam = None for param in self.algorithm().parameterDefinitions(): if isinstance( parameters.get(param.name(), None), QgsProcessingFeatureSourceDefinition ) and parameters[param.name( )].flags & QgsProcessingFeatureSourceDefinition.FlagCreateIndividualOutputPerInputFeature: self.iterateParam = param.name() break self.clearProgress() self.feedback.pushVersionInfo(self.algorithm().provider()) if self.algorithm().provider().warningMessage(): self.feedback.reportError( self.algorithm().provider().warningMessage()) self.setProgressText( QCoreApplication.translate('AlgorithmDialog', 'Processing algorithm…')) self.setInfo(QCoreApplication.translate( 'AlgorithmDialog', '<b>Algorithm \'{0}\' starting…</b>').format( self.algorithm().displayName()), escapeHtml=False) self.feedback.pushInfo(self.tr('Input parameters:')) display_params = [] for k, v in parameters.items(): display_params.append("'" + k + "' : " + self.algorithm( ).parameterDefinition(k).valueAsPythonString(v, self.context)) self.feedback.pushCommandInfo('{ ' + ', '.join(display_params) + ' }') self.feedback.pushInfo('') start_time = time.time() if self.iterateParam: # Make sure the Log tab is visible before executing the algorithm try: self.showLog() self.repaint() except: pass self.cancelButton().setEnabled( self.algorithm().flags() & QgsProcessingAlgorithm.FlagCanCancel) if executeIterating(self.algorithm(), parameters, self.iterateParam, self.context, self.feedback): self.feedback.pushInfo( self.tr('Execution completed in {0:0.2f} seconds'). format(time.time() - start_time)) self.cancelButton().setEnabled(False) self.finish(True, parameters, self.context, self.feedback) else: self.cancelButton().setEnabled(False) self.resetGui() else: command = self.algorithm().asPythonCommand( parameters, self.context) if command: ProcessingLog.addToLog(command) QgsGui.instance().processingRecentAlgorithmLog().push( self.algorithm().id()) self.cancelButton().setEnabled( self.algorithm().flags() & QgsProcessingAlgorithm.FlagCanCancel) def on_complete(ok, results): if ok: self.feedback.pushInfo( self.tr('Execution completed in {0:0.2f} seconds'). format(time.time() - start_time)) self.feedback.pushInfo(self.tr('Results:')) r = { k: v for k, v in results.items() if k not in ('CHILD_RESULTS', 'CHILD_INPUTS') } self.feedback.pushCommandInfo(pformat(r)) else: self.feedback.reportError( self.tr('Execution failed after {0:0.2f} seconds'). format(time.time() - start_time)) self.feedback.pushInfo('') if self.feedback_dialog is not None: self.feedback_dialog.close() self.feedback_dialog.deleteLater() self.feedback_dialog = None self.cancelButton().setEnabled(False) self.finish(ok, results, self.context, self.feedback, in_place=self.in_place) self.feedback = None self.context = None if not self.in_place and not ( self.algorithm().flags() & QgsProcessingAlgorithm.FlagNoThreading): # Make sure the Log tab is visible before executing the algorithm self.showLog() task = QgsProcessingAlgRunnerTask(self.algorithm(), parameters, self.context, self.feedback) if task.isCanceled(): on_complete(False, {}) else: task.executed.connect(on_complete) self.setCurrentTask(task) else: self.proxy_progress = QgsProxyProgressTask( QCoreApplication.translate( "AlgorithmDialog", "Executing “{}”").format( self.algorithm().displayName())) QgsApplication.taskManager().addTask(self.proxy_progress) self.feedback.progressChanged.connect( self.proxy_progress.setProxyProgress) self.feedback_dialog = self.createProgressDialog() self.feedback_dialog.show() if self.in_place: ok, results = execute_in_place(self.algorithm(), parameters, self.context, self.feedback) else: ok, results = execute(self.algorithm(), parameters, self.context, self.feedback) self.feedback.progressChanged.disconnect() self.proxy_progress.finalize(ok) on_complete(ok, results) except AlgorithmDialogBase.InvalidParameterValue as e: try: self.buttonBox().accepted.connect( lambda e=e: e.widget.setPalette(QPalette())) palette = e.widget.palette() palette.setColor(QPalette.Base, QColor(255, 255, 0)) e.widget.setPalette(palette) except: pass self.messageBar().clearWidgets() self.messageBar().pushMessage( "", self.tr("Wrong or missing parameter value: {0}").format( e.parameter.description()), level=Qgis.Warning, duration=5) except AlgorithmDialogBase.InvalidOutputExtension as e: try: self.buttonBox().accepted.connect( lambda e=e: e.widget.setPalette(QPalette())) palette = e.widget.palette() palette.setColor(QPalette.Base, QColor(255, 255, 0)) e.widget.setPalette(palette) except: pass self.messageBar().clearWidgets() self.messageBar().pushMessage("", e.message, level=Qgis.Warning, duration=5)
def runAlgorithm(algOrName, onFinish, *args, **kwargs): if isinstance(algOrName, GeoAlgorithm): alg = algOrName else: alg = QgsApplication.processingRegistry().algorithmById(algOrName) if alg is None: # fix_print_with_import print('Error: Algorithm not found\n') QgsMessageLog.logMessage( Processing.tr('Error: Algorithm {0} not found\n').format( algOrName), Processing.tr("Processing")) return # hack - remove when getCopy is removed provider = alg.provider() alg = alg.getCopy() #hack pt2 alg.setProvider(provider) if len(args) == 1 and isinstance(args[0], dict): # Set params by name and try to run the alg even if not all parameter values are provided, # by using the default values instead. setParams = [] for (name, value) in list(args[0].items()): param = alg.getParameterFromName(name) if param and param.setValue(value): setParams.append(name) continue output = alg.getOutputFromName(name) if output and output.setValue(value): continue # fix_print_with_import print('Error: Wrong parameter value %s for parameter %s.' % (value, name)) QgsMessageLog.logMessage( Processing.tr( 'Error: Wrong parameter value {0} for parameter {1}.'). format(value, name), Processing.tr("Processing")) QgsMessageLog.logMessage( Processing. tr('Error in {0}. Wrong parameter value {1} for parameter {2}.' ).format(alg.name(), value, name), Processing.tr("Processing"), QgsMessageLog.CRITICAL) return # fill any missing parameters with default values if allowed for param in alg.parameters: if param.name not in setParams: if not param.setDefaultValue(): # fix_print_with_import print( 'Error: Missing parameter value for parameter %s.' % param.name) QgsMessageLog.logMessage( Processing. tr('Error: Missing parameter value for parameter {0}.' ).format(param.name), Processing.tr("Processing")) return else: if len(args) != alg.getVisibleParametersCount( ) + alg.getVisibleOutputsCount(): # fix_print_with_import print('Error: Wrong number of parameters') QgsMessageLog.logMessage( Processing.tr('Error: Wrong number of parameters'), Processing.tr("Processing")) processing.algorithmHelp(algOrName) return i = 0 for param in alg.parameters: if not param.hidden: if not param.setValue(args[i]): # fix_print_with_import print('Error: Wrong parameter value: ' + str(args[i])) QgsMessageLog.logMessage( Processing.tr('Error: Wrong parameter value: ') + str(args[i]), Processing.tr("Processing")) return i = i + 1 for output in alg.outputs: if not output.hidden: if not output.setValue(args[i]): # fix_print_with_import print('Error: Wrong output value: ' + str(args[i])) QgsMessageLog.logMessage( Processing.tr('Error: Wrong output value: ') + str(args[i]), Processing.tr("Processing")) return i = i + 1 context = None if kwargs is not None and 'context' in list(kwargs.keys()): context = kwargs["context"] else: context = dataobjects.createContext() msg = alg._checkParameterValuesBeforeExecuting(context) if msg: # fix_print_with_import print('Unable to execute algorithm\n' + str(msg)) QgsMessageLog.logMessage( Processing.tr('Unable to execute algorithm\n{0}').format(msg), Processing.tr("Processing")) return if not alg.checkInputCRS(context): print('Warning: Not all input layers use the same CRS.\n' + 'This can cause unexpected results.') QgsMessageLog.logMessage( Processing. tr('Warning: Not all input layers use the same CRS.\nThis can cause unexpected results.' ), Processing.tr("Processing")) # Don't set the wait cursor twice, because then when you # restore it, it will still be a wait cursor. overrideCursor = False if iface is not None: cursor = QApplication.overrideCursor() if cursor is None or cursor == 0: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) overrideCursor = True elif cursor.shape() != Qt.WaitCursor: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) overrideCursor = True feedback = None if kwargs is not None and "feedback" in list(kwargs.keys()): feedback = kwargs["feedback"] elif iface is not None: feedback = MessageBarProgress(alg.displayName()) ret = execute(alg, context, feedback) if ret: if onFinish is not None: onFinish(alg, context, feedback) else: QgsMessageLog.logMessage( Processing.tr("There were errors executing the algorithm."), Processing.tr("Processing")) if overrideCursor: QApplication.restoreOverrideCursor() if isinstance(feedback, MessageBarProgress): feedback.close() return alg
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ feedback.pushInfo("\nDébut du processus\n") # unité de sondage path_us = self.parameterAsVectorLayer(parameters, self.UniteSondage, context) # numéro de l'unité de sondage us = self.parameterAsString(parameters, self.uniteSondage, context) # Parametres Dossier Intrants wd_intrants = self.parameterAsString(parameters, self.DossierIntrants, context) feedback.pushInfo( "\nVous traité l'unité de sondage : {0}\n".format(us)) # Permet d'ignorer les erreurs de geometries noCheckGeom = dataobjects.createContext() noCheckGeom.setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck) # Construction de l'environnement d'exécution d'ArcGIS # Nécessaire car l'environnement de QGIS engendre des conflits arcgis_env = {} arcgis_env['SYSTEMROOT'] = os.environ['SYSTEMROOT'] arcgis_env['AGSDESKTOPJAVA'] = os.path.join( os.environ['AGSDESKTOPJAVA'], 'bin') arcgis_env['USERPROFILE'] = os.environ['USERPROFILE'] # Liste des intrants sur le réseau (DDE et autres) # path_PeupForestiers_reseau = path_PentesNum_reseau = r"\\vulcain\raigeop\Depot_Dde\Catalogue_du_systeme_DDE\Couches_de_donnees\ Classe_de_pente_numerique\CLASSES_DE_PENTE_NUMERIQUE_S\FGDB_GEO\CPN_PROV\CPN_PROV.gdb|layername=CPN_PROV" path_HydroLin_reseau = r"\\vulcain\raigeop\Depot_Dde\Catalogue_du_systeme_DDE\Couches_de_donnees\Reference_geographique_Quebec\ BDTQ_20K_a_jour\HYDROGRAPHIE_LINEAIRE_BDTQ_20K_L\FGDB_GEO\HL20_PROV\HL20_PROV.gdb|layername=BDTQ_20K_HYDRO_LO" path_VoieFerree_reseau = r"\\vulcain\raigeop\Depot_Dde\Catalogue_du_systeme_DDE\Couches_de_donnees\Reference_geographique_Quebec\ BDTQ_20K_a_jour\VOIE_COMM_LINEAIRE_BDTQ_20K_L\FGDB_GEO\VCL_BDTQ_20K\VCL_BDTQ_20K.gdb|layername=BDTQ_20K_VOIE_COMMU_LO" path_PEP_reseau = r"\\vulcain\raigeop\Depot_Dde\Produits_IEQM\Placettes_echantillons\PEP.gpkg|layername=df_placettes_metadata_PeupForestiers_US" path_ponc_reseau = r"\\vulcain\raigeop\Depot_Dde\Catalogue_du_systeme_DDE\Couches_de_donnees\Reference_geographique_Quebec\ BDTQ_20K_a_jour\BATIMENT_PONCTUEL_BDTQ_20K_P\FGDB_GEO\BATP_PROV\BATP_PROV.gdb|layername=BDTQ_20K_BATIM_PO" path_BatiLin_reseau = r"\\vulcain\raigeop\Depot_Dde\Catalogue_du_systeme_DDE\Couches_de_donnees\Reference_geographique_Quebec\ BDTQ_20K_a_jour\BATIMENT_LINEAIRE_BDTQ_20K_L\FGDB_GEO\BATL_PROV\BATL_PROV.gdb|layername=BDTQ_20K_BATIM_LO" path_BatiSur_reseau = r"\\vulcain\raigeop\Depot_Dde\Catalogue_du_systeme_DDE\Couches_de_donnees\Reference_geographique_Quebec\ BDTQ_20K_a_jour\BATIMENT_SURFACIQUE_BDTQ_20K_S\FGDB_GEO\BATS_PROV\BATS_PROV.gdb|layername=BDTQ_20K_BATIM_SO" path_EquipPonc_reseau = r"\\vulcain\raigeop\Depot_Dde\Catalogue_du_systeme_DDE\Couches_de_donnees\Reference_geographique_Quebec\ BDTQ_20K_a_jour\EQUIPEMENT_PONCTUEL_BDTQ_20K_P\FGDB_GEO\EQP_PROV\EQP_PROV.gdb|layername=BDTQ_20K_EQUIP_PO" path_EquipLin_reseau = r"\\vulcain\raigeop\Depot_Dde\Catalogue_du_systeme_DDE\Couches_de_donnees\Reference_geographique_Quebec\ BDTQ_20K_a_jour\EQUIPEMENT_LINEAIRE_BDTQ_20K_L\FGDB_GEO\EQL_PROV\EQL_PROV.gdb|layername=BDTQ_20K_EQUIP_LO" path_EquipSur_reseau = r"\\vulcain\raigeop\Depot_Dde\Catalogue_du_systeme_DDE\Couches_de_donnees\Reference_geographique_Quebec\ BDTQ_20K_a_jour\EQUIPEMENT_SURFACIQUE_BDTQ_20K_S\FGDB_GEO\EQS_PROV\EQS_PROV.gdb|layername=BDTQ_20K_EQUIP_SO" path_AffecPonc_reseau = r"\\vulcain\raigeop\Depot_Dde\Catalogue_du_systeme_DDE\Couches_de_donnees\Utilisation_du_territoire\ Usage_forestier\USAGE_FORESTIER_PONCTUEL_P\FGDB_CCL\UFP_PROV\UFP_PROV.gdb|layername=DDE_UFZ_USAGE_FORES_VUE_P" path_AffecLin_reseau = r"\\vulcain\raigeop\Depot_Dde\Catalogue_du_systeme_DDE\Couches_de_donnees\Utilisation_du_territoire\ Usage_forestier\USAGE_FORESTIER_LINEAIRE_L\FGDB_CCL\UFL_PROV\UFL_PROV.gdb|layername=DDE_UFZ_USAGE_FORES_VUE_L" # path_Feux_reseau= # path_PertMaj_reseau= # path_Interv_reseau= # path_Planif_reseau= # #Ce sont des intrants préparés hors de l'outil # path_us = os.path.join(wd_intrants, "US_{0}.shp".format(us)) #Robin # path_ParamBuffers = os.path.join(wd_intrants, "Parametres", "BUFFER_template.csv")# SONDAGE # path_chemins = os.path.join(wd_intrants, "CHEMIN_SONAR_{0}.shp".format(us)) # SONDAGE # path_geocodes = os.path.join(wd_intrants, "LIST_GEOC_{0}.shp".format(us)) # PHILIPPE MORIN # path_masque = os.path.join(wd_intrants, "MASQUE_{0}.shp".format(us))# SONDAGE # path_SIP = os.path.join(wd_intrants, "CFETBFEC_08664_SIP.shp")# Pour l'intant on laisse desactivé # Liste des intrant local (gpkg) # gpkg des intrants gpkg = os.path.join(wd_intrants, "SONAR2_Intrants.gpkg") path_PeupForestiers = 'ogr:dbname=\'{0}\' table=\"DDE_20K_PEU_FOR_ORI_TRV_VUE_SE_{1}\" (geom) sql='.format( gpkg, us) #OUTIL path_PentesNum = 'ogr:dbname=\'{0}\' table=\"DDE_20K_CLA_PEN_VUE_SE_{1}\" (geom) sql='.format( gpkg, us) #OUTIL path_HydroLin = 'ogr:dbname=\'{0}\' table=\"BDTQ_20K_HYDRO_LO_{1}\" (geom) sql='.format( gpkg, us) #OUTIL path_VoieFerree = 'ogr:dbname=\'{0}\' table=\"BDTQ_20K_VOIE_COMMU_LO_{1}\" (geom) sql='.format( gpkg, us) #OUTIL path_PEP = 'ogr:dbname=\'{0}\' table=\"DDE_20K_PEP_VUE_PE_{1}\" (geom) sql='.format( gpkg, us) #OUTIL path_ponc = 'ogr:dbname=\'{0}\' table=\"BDTQ_20K_BATIM_PO_{1}\" (geom) sql='.format( gpkg, us) #OUTIL path_BatiLin = 'ogr:dbname=\'{0}\' table=\"BDTQ_20K_BATIM_LO_{1}\" (geom) sql='.format( gpkg, us) #OUTIL path_BatiSur = 'ogr:dbname=\'{0}\' table=\"BDTQ_20K_BATIM_SO_{1}\" (geom) sql='.format( gpkg, us) #OUTIL path_EquipPonc = 'ogr:dbname=\'{0}\' table=\"BDTQ_20K_EQUIP_PO_{1}\" (geom) sql='.format( gpkg, us) #OUTIL path_EquipLin = 'ogr:dbname=\'{0}\' table=\"BDTQ_20K_EQUIP_LO_{1}\" (geom) sql='.format( gpkg, us) #OUTIL path_EquipSur = 'ogr:dbname=\'{0}\' table=\"BDTQ_20K_EQUIP_SO_{1}\" (geom) sql='.format( gpkg, us) #OUTIL path_AffecPonc = 'ogr:dbname=\'{0}\' table=\"DDE_UFZ_20K_USAGE_FOR_VUE_PE_{1}\" (geom) sql='.format( gpkg, us) #OUTIL path_AffecLin = 'ogr:dbname=\'{0}\' table=\"DDE_UFZ_20K_USAGE_FOR_VUE_LE_{1}\" (geom) sql='.format( gpkg, us) #OUTIL path_Feux = 'ogr:dbname=\'{0}\' table=\"DDE_20K_FEUX_MAJ_TRV_{1}\" (geom) sql='.format( gpkg, us) #OUTIL path_PertMaj = 'ogr:dbname=\'{0}\' table=\"DDE_20K_AUTRE_PERTU_MAJ_TRV_{1}\" (geom) sql='.format( gpkg, us) #OUTIL path_Interv = 'ogr:dbname=\'{0}\' table=\"INTERVENTION_{1}\" (geom) sql='.format( gpkg, us) #YVAN path_Planif = 'ogr:dbname=\'{0}\' table=\"PLAN_{1}\" (geom) sql='.format( gpkg, us) #YVAN path_BufferIn = 'ogr:dbname=\'{0}\' table=\"us_bufin_{1}_2025m\" (geom) sql='.format( gpkg, us) #OUTIL # couches intermediaires path_us_dissolve = '{0}|layername=us_dissolve'.format(gpkg) path_us_buf_2km = 'ogr:dbname=\'{0}\' table=\"us_buf_2km_{1}\" (geom) sql='.format( gpkg, us) # copie l'us dans le geopackage # Copie des peuplement dans le GPKG us_gpkg = 'us' copyCeToGpkg(path_us, gpkg, us_gpkg) # faire un dissolve de l'US dissolvedGeopandasGPKG(gpkg, us_gpkg, 'us_dissolve', fields=None) # faire un dissolve arcpy # si je fais le dissolve avec arpy path_us ser le suivant: # path_us = '{0}'.format(gpkg)+"/"+'us' # path_us = r"E:\ADG\SONAR\1415CE\Intrants\US_1415CE.shp" # basepath = os.path.dirname(os.path.realpath(__file__)) # path_arpyPy = os.path.join(basepath, 'Arcpy_Dissolve_SONAR2.py {}'.format(path_us)) # # # # Paramètres pour éviter que les appels subprocess.run() # # n'ouvrent une fenêtre dérangeant l'utilisateur # startupinfo = subprocess.STARTUPINFO() # startupinfo.dwFlags = subprocess.STARTF_USESHOWWINDOW # startupinfo.wShowWindow = 7 # # subprocess.run(r"C:\Mrnmicro\Applic\python27\ArcGIS10.3\python.exe"+" "+ path_arpyPy, env=arcgis_env, startupinfo=startupinfo) # # dissolve_us = r"C:\MrnMicro\temp\dissolve.shp" # supprimer les trous # je fais cette étape si je fais le dissolve avec GEOPANDAS # clean_us = processing.run("native:deleteholes", {'INPUT':path_us_dissolve,'MIN_AREA':0, # 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT})["OUTPUT"] # faire la couche path_BufferIn buff_25 = processing.run( "native:buffer", { 'INPUT': dissolve_us, 'DISTANCE': -25, 'SEGMENTS': 5, 'END_CAP_STYLE': 0, 'JOIN_STYLE': 0, 'MITER_LIMIT': 2, 'DISSOLVE': False, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT })["OUTPUT"] # faire la différence avec l'us et lbuffer interne de 25 m processing.run("native:difference", { 'INPUT': dissolve_us, 'OVERLAY': buff_25, 'OUTPUT': path_BufferIn }) # faire un buffer de 2000m de l'US # Si GEOPANADS # processing.run("native:buffer", {'INPUT':clean_us,'DISTANCE':2000,'SEGMENTS':5,'END_CAP_STYLE':0,'JOIN_STYLE':0,'MITER_LIMIT':2, # 'DISSOLVE':False,'OUTPUT':path_us_buf_2km}) processing.run( "native:buffer", { 'INPUT': dissolve_us, 'DISTANCE': 2000, 'SEGMENTS': 5, 'END_CAP_STYLE': 0, 'JOIN_STYLE': 0, 'MITER_LIMIT': 2, 'DISSOLVE': False, 'OUTPUT': path_us_buf_2km }) # Faire les différents clip return {self.uniteSondage: us}
def runAlgorithm(algOrName, parameters, onFinish=None, feedback=None, context=None): if isinstance(algOrName, QgsProcessingAlgorithm): alg = algOrName else: alg = QgsApplication.processingRegistry().createAlgorithmById( algOrName) if feedback is None: feedback = MessageBarProgress( alg.displayName() if alg else Processing.tr('Processing')) if alg is None: # fix_print_with_import print('Error: Algorithm not found\n') msg = Processing.tr('Error: Algorithm {0} not found\n').format( algOrName) feedback.reportError(msg) raise QgsProcessingException(msg) # check for any mandatory parameters which were not specified for param in alg.parameterDefinitions(): if param.name() not in parameters: if not param.flags( ) & QgsProcessingParameterDefinition.FlagOptional: # fix_print_with_import msg = Processing.tr( 'Error: Missing parameter value for parameter {0}.' ).format(param.name()) print('Error: Missing parameter value for parameter %s.' % param.name()) feedback.reportError(msg) raise QgsProcessingException(msg) if context is None: context = dataobjects.createContext(feedback) ok, msg = alg.checkParameterValues(parameters, context) if not ok: # fix_print_with_import print('Unable to execute algorithm\n' + str(msg)) msg = Processing.tr('Unable to execute algorithm\n{0}').format(msg) feedback.reportError(msg) raise QgsProcessingException(msg) if not alg.validateInputCrs(parameters, context): print('Warning: Not all input layers use the same CRS.\n' + 'This can cause unexpected results.') feedback.pushInfo( Processing. tr('Warning: Not all input layers use the same CRS.\nThis can cause unexpected results.' )) ret, results = execute(alg, parameters, context, feedback) if ret: feedback.pushInfo(Processing.tr('Results: {}').format(results)) if onFinish is not None: onFinish(alg, context, feedback) else: # auto convert layer references in results to map layers for out in alg.outputDefinitions(): if isinstance(out, (QgsProcessingOutputVectorLayer, QgsProcessingOutputRasterLayer)): result = results[out.name()] if not isinstance(result, QgsMapLayer): layer = context.takeResultLayer( result ) # transfer layer ownership out of context if layer: results[out.name( )] = layer # replace layer string ref with actual layer (+ownership) else: msg = Processing.tr("There were errors executing the algorithm.") feedback.reportError(msg) raise QgsProcessingException(msg) if isinstance(feedback, MessageBarProgress): feedback.close() return results
def accept(self): self.algs = [] self.load = [] self.canceled = False for row in range(self.mainWidget.tblParameters.rowCount()): alg = self.alg.getCopy() # hack - remove when getCopy is removed alg.setProvider(self.alg.provider()) col = 0 for param in alg.parameters: if param.hidden: continue wrapper = self.mainWidget.wrappers[row][col] if not self.mainWidget.setParamValue(param, wrapper, alg): self.bar.pushMessage( "", self.tr( 'Wrong or missing parameter value: {0} (row {1})'). format(param.description, row + 1), level=QgsMessageBar.WARNING, duration=5) self.algs = None return col += 1 for out in alg.outputs: if out.hidden: continue widget = self.mainWidget.tblParameters.cellWidget(row, col) text = widget.getValue() if text.strip() != '': out.value = text col += 1 else: self.bar.pushMessage( "", self.tr('Wrong or missing output value: {0} (row {1})' ).format(out.description, row + 1), level=QgsMessageBar.WARNING, duration=5) self.algs = None return self.algs.append(alg) if self.alg.getVisibleOutputsCount(): widget = self.mainWidget.tblParameters.cellWidget(row, col) self.load.append(widget.currentIndex() == 0) else: self.load.append(False) QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.mainWidget.setEnabled(False) self.progressBar.setMaximum(len(self.algs)) # Make sure the Log tab is visible before executing the algorithm try: self.tabWidget.setCurrentIndex(1) self.repaint() except: pass context = dataobjects.createContext() for count, alg in enumerate(self.algs): self.setText( self.tr('\nProcessing algorithm {0}/{1}...').format( count + 1, len(self.algs))) self.setInfo( self.tr('<b>Algorithm {0} starting...</b>').format( alg.displayName())) if execute(alg, context, self.feedback) and not self.canceled: if self.load[count]: handleAlgorithmResults(alg, context, self.feedback, False) self.setInfo( self.tr('Algorithm {0} correctly executed...').format( alg.displayName())) else: QApplication.restoreOverrideCursor() return self.finish()
def createProcessingParameters(self, flags=QgsProcessingParametersGenerator.Flags()): include_default = not (flags & QgsProcessingParametersGenerator.Flag.SkipDefaultValueParameters) parameters = {} for p, v in self.extra_parameters.items(): parameters[p] = v for param in self.algorithm().parameterDefinitions(): if param.flags() & QgsProcessingParameterDefinition.FlagHidden: continue if not param.isDestination(): try: wrapper = self.wrappers[param.name()] except KeyError: continue # For compatibility with 3.x API, we need to check whether the wrapper is # the deprecated WidgetWrapper class. If not, it's the newer # QgsAbstractProcessingParameterWidgetWrapper class # TODO QGIS 4.0 - remove if issubclass(wrapper.__class__, WidgetWrapper): widget = wrapper.widget else: widget = wrapper.wrappedWidget() if not isinstance(wrapper, QgsProcessingHiddenWidgetWrapper) and widget is None: continue value = wrapper.parameterValue() if param.defaultValue() != value or include_default: parameters[param.name()] = value if not param.checkValueIsAcceptable(value): raise AlgorithmDialogBase.InvalidParameterValue(param, widget) else: if self.in_place and param.name() == 'OUTPUT': parameters[param.name()] = 'memory:' continue try: wrapper = self.wrappers[param.name()] except KeyError: continue widget = wrapper.wrappedWidget() value = wrapper.parameterValue() dest_project = None if wrapper.customProperties().get('OPEN_AFTER_RUNNING'): dest_project = QgsProject.instance() if value and isinstance(value, QgsProcessingOutputLayerDefinition): value.destinationProject = dest_project if value and (param.defaultValue() != value or include_default): parameters[param.name()] = value context = createContext() ok, error = param.isSupportedOutputValue(value, context) if not ok: raise AlgorithmDialogBase.InvalidOutputExtension(widget, error) return self.algorithm().preprocessParameters(parameters)
def setLayer(self, layer): context = dataobjects.createContext() if isinstance(layer, str): layer = QgsProcessingUtils.mapLayerFromString(_resolveLayers(layer), context) self.widget.setLayer(layer)
if args.value5 and args.value5.startswith("["): args.value5 = args.value5[1:-1].split(',') if args.value6 and args.value6.startswith("["): args.value6 = args.value6[1:-1].split(',') if args.value7 and args.value7.startswith("["): args.value7 = args.value7[1:-1].split(',') if args.value8 and args.value8.startswith("["): args.value8 = args.value8[1:-1].split(',') if args.value9 and args.value9.startswith("["): args.value9 = args.value9[1:-1].split(',') if args.value10 and args.value10.startswith("["): args.value10 = args.value10[1:-1].split(',') params = { args.param1: args.value1, args.param2: args.value2, args.param3: args.value3, args.param4: args.value4, args.param5: args.value5, args.param6: args.value6, args.param7: args.value7, args.param8: args.value8, args.param9: args.value9, args.param10: args.value10 } # print(args.value1) # print(params) context = dataobjects.createContext() context.setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck) res = processing.run(args.alg, params, context=context)
def Locate_subid_needsbyuser_qgis(Path_Points="#", Gauge_NMS="#", Path_products="#", qgis_prefix_path="#"): """Get Subbasin Ids Function that used to obtain subbasin ID of certain gauge. or subbasin ID of the polygon that includes the given point shapefile. Parameters ---------- Path_Points : string (Optional) It is the path of the point shapefile. If the point shapefile is provided. The function will return subids of those catchment polygons that includes these point in the point shapefile Gauge_NMS : list Name of the streamflow gauges, such as ['09PC019'], if the gauge name is provided, the subbasin ID that contain this gauge will be returned Path_products : string The path of the subbasin polygon shapefile. The shapefile should at least contains following columns ##############Subbasin related attributes########################### SubID - integer, The subbasin Id DowSubId - integer, The downstream subbasin ID of this subbasin Obs_NM - The streamflow obervation gauge name. Notes ------- Path_Points or Gauge_NMS should only provide one each time to use this function Returns: ------- SubId_Selected : list It is a list contains the selected subid based on provided streamflow gauge name or provided point shapefile Examples ------- """ tempfolder = os.path.join( tempfile.gettempdir(), "basinmaker_locsubid" + str(np.random.randint(1, 10000 + 1)), ) if not os.path.exists(tempfolder): os.makedirs(tempfolder) # obtain subbasin ID based on either points or guage names QgsApplication.setPrefixPath(qgis_prefix_path, True) Qgs = QgsApplication([], False) Qgs.initQgis() from processing.core.Processing import Processing from processing.tools import dataobjects from qgis import processing feedback = QgsProcessingFeedback() Processing.initialize() QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms()) context = dataobjects.createContext() context.setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck) SubId_Selected = -1 if Gauge_NMS[0] != "#": hyinfocsv = Path_products[:-3] + "dbf" tempinfo = Dbf5(hyinfocsv) hyshdinfo2 = tempinfo.to_dataframe().drop_duplicates("SubId", keep="first") hyshdinfo2 = hyshdinfo2.loc[hyshdinfo2["Obs_NM"] != "-9999.0"] hyshdinfo2 = hyshdinfo2.loc[hyshdinfo2["Obs_NM"].isin(Gauge_NMS)] hyshdinfo2 = hyshdinfo2[["Obs_NM", "SubId"]] # hyshdinfo2.to_csv(os.path.join(self.OutputFolder,'SubIds_Selected.csv'),sep=',', index = None) SubId_Selected = hyshdinfo2["SubId"].values if Path_Points != "#": vector_layer = qgis_vector_read_vector(processing, context, Path_products) SpRef_in = qgis_vector_return_crs_id(processing, context, vector_layer) qgis_vector_reproject_layers( processing, context, INPUT=Path_Points, TARGET_CRS=SpRef_in, OUTPUT=os.path.join(tempfolder, "Obspoint_project2.shp"), ) qgis_vector_add_polygon_attribute_to_points( processing, context, INPUT_Layer=os.path.join(tempfolder, "Obspoint_project2.shp"), POLYGONS=Path_products, FIELDS="SubId", OUTPUT=os.path.join(tempfolder, "Sub_Selected_by_Points.shp"), ) hyshdinfo2 = Dbf_To_Dataframe( os.path.join(tempfolder, "Sub_Selected_by_Points.shp")) SubId_Selected = hyshdinfo2["SubId"].values SubId_Selected = SubId_Selected[SubId_Selected > 0] Qgs.exit() return SubId_Selected
def executeAlgorithm(self): config = {} if self.in_place_mode: config['IN_PLACE'] = True alg = self.algorithmTree.selectedAlgorithm().create( config) if self.algorithmTree.selectedAlgorithm( ) is not None else None if alg is not None: ok, message = alg.canExecute() if not ok: dlg = MessageDialog() dlg.setTitle(self.tr('Error executing algorithm')) dlg.setMessage( self.tr('<h3>This algorithm cannot ' 'be run :-( </h3>\n{0}').format(message)) dlg.exec_() return if self.in_place_mode and not [ d for d in alg.parameterDefinitions() if d.name() not in ('INPUT', 'OUTPUT') ]: parameters = {} feedback = MessageBarProgress(algname=alg.displayName()) ok, results = execute_in_place(alg, parameters, feedback=feedback) if ok: iface.messageBar().pushSuccess( '', self.tr( '{algname} completed. %n feature(s) processed.', n=results['__count']).format( algname=alg.displayName())) feedback.close() # MessageBarProgress handles errors return if alg.countVisibleParameters() > 0: dlg = alg.createCustomParametersWidget(self) if not dlg: dlg = AlgorithmDialog(alg, self.in_place_mode, iface.mainWindow()) canvas = iface.mapCanvas() prevMapTool = canvas.mapTool() dlg.show() dlg.exec_() if canvas.mapTool() != prevMapTool: try: canvas.mapTool().reset() except: pass canvas.setMapTool(prevMapTool) else: feedback = MessageBarProgress(algname=alg.displayName()) context = dataobjects.createContext(feedback) parameters = {} ret, results = execute(alg, parameters, context, feedback) handleAlgorithmResults(alg, context, feedback) feedback.close()
def accept(self): feedback = self.createFeedback() context = dataobjects.createContext(feedback) checkCRS = ProcessingConfig.getSetting( ProcessingConfig.WARN_UNMATCHING_CRS) try: parameters = self.getParameterValues() if checkCRS and not self.algorithm().validateInputCrs( parameters, context): reply = QMessageBox.question( self, self.tr("Unmatching CRS's"), self.tr('Parameters do not all use the same CRS. This can ' 'cause unexpected results.\nDo you want to ' 'continue?'), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.No: return ok, msg = self.algorithm().checkParameterValues( parameters, context) if not ok: QMessageBox.warning(self, self.tr('Unable to execute algorithm'), msg) return self.runButton().setEnabled(False) self.cancelButton().setEnabled(False) buttons = self.mainWidget().iterateButtons self.iterateParam = None for i in range(len(list(buttons.values()))): button = list(buttons.values())[i] if button.isChecked(): self.iterateParam = list(buttons.keys())[i] break self.clearProgress() self.setProgressText( QCoreApplication.translate('AlgorithmDialog', 'Processing algorithm…')) self.setInfo(QCoreApplication.translate( 'AlgorithmDialog', '<b>Algorithm \'{0}\' starting…</b>').format( self.algorithm().displayName()), escapeHtml=False) feedback.pushInfo(self.tr('Input parameters:')) display_params = [] for k, v in parameters.items(): display_params.append("'" + k + "' : " + self.algorithm().parameterDefinition( k).valueAsPythonString(v, context)) feedback.pushCommandInfo('{ ' + ', '.join(display_params) + ' }') feedback.pushInfo('') start_time = time.time() if self.iterateParam: # Make sure the Log tab is visible before executing the algorithm try: self.showLog() self.repaint() except: pass self.cancelButton().setEnabled( self.algorithm().flags() & QgsProcessingAlgorithm.FlagCanCancel) if executeIterating(self.algorithm(), parameters, self.iterateParam, context, feedback): feedback.pushInfo( self.tr('Execution completed in {0:0.2f} seconds'). format(time.time() - start_time)) self.cancelButton().setEnabled(False) self.finish(True, parameters, context, feedback) else: self.cancelButton().setEnabled(False) self.resetGui() else: command = self.algorithm().asPythonCommand(parameters, context) if command: ProcessingLog.addToLog(command) QgsGui.instance().processingRecentAlgorithmLog().push( self.algorithm().id()) self.cancelButton().setEnabled( self.algorithm().flags() & QgsProcessingAlgorithm.FlagCanCancel) def on_complete(ok, results): if ok: feedback.pushInfo( self.tr('Execution completed in {0:0.2f} seconds'). format(time.time() - start_time)) feedback.pushInfo(self.tr('Results:')) feedback.pushCommandInfo(pformat(results)) else: feedback.reportError( self.tr('Execution failed after {0:0.2f} seconds'). format(time.time() - start_time)) feedback.pushInfo('') if self.feedback_dialog is not None: self.feedback_dialog.close() self.feedback_dialog.deleteLater() self.feedback_dialog = None self.cancelButton().setEnabled(False) self.finish(ok, results, context, feedback) if not (self.algorithm().flags() & QgsProcessingAlgorithm.FlagNoThreading): # Make sure the Log tab is visible before executing the algorithm self.showLog() task = QgsProcessingAlgRunnerTask(self.algorithm(), parameters, context, feedback) task.executed.connect(on_complete) self.setCurrentTask(task) else: self.feedback_dialog = self.createProgressDialog() self.feedback_dialog.show() ok, results = execute(self.algorithm(), parameters, context, feedback) on_complete(ok, results) except AlgorithmDialogBase.InvalidParameterValue as e: try: self.buttonBox().accepted.connect( lambda e=e: e.widget.setPalette(QPalette())) palette = e.widget.palette() palette.setColor(QPalette.Base, QColor(255, 255, 0)) e.widget.setPalette(palette) except: pass self.messageBar().clearWidgets() self.messageBar().pushMessage( "", self.tr("Wrong or missing parameter value: {0}").format( e.parameter.description()), level=Qgis.Warning, duration=5)
def calculate_basic_attributes( grassdb, grass_location, qgis_prefix_path, input_geo_names, projection, catinfo, cat_ply_info, cat_riv_info, outlet_pt_info, ): catchments = input_geo_names["catchment_without_merging_lakes"] river_r = input_geo_names["river_without_merging_lakes"] river_v = input_geo_names["str_v"] dem = input_geo_names["dem"] fdr = input_geo_names["nfdr_grass"] acc = input_geo_names["acc"] cat_use_default_acc = input_geo_names["cat_use_default_acc"] problem_seg = input_geo_names["problem_seg"] nfdr_arcgis = input_geo_names["nfdr_arcgis"] import grass.script as grass import grass.script.setup as gsetup from grass.pygrass.modules import Module from grass.pygrass.modules.shortcuts import general as g from grass.pygrass.modules.shortcuts import raster as r from grass.script import array as garray from grass.script import core as gcore from grass_session import Session QgsApplication.setPrefixPath(qgis_prefix_path, True) Qgs = QgsApplication([], False) Qgs.initQgis() from processing.core.Processing import Processing from processing.tools import dataobjects from qgis import processing feedback = QgsProcessingFeedback() Processing.initialize() QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms()) context = dataobjects.createContext() context.setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck) os.environ.update( dict(GRASS_COMPRESS_NULLS="1", GRASS_COMPRESSOR="ZSTD", GRASS_VERBOSE="1")) PERMANENT = Session() PERMANENT.open(gisdb=grassdb, location=grass_location, create_opts="") con = sqlite3.connect( os.path.join(grassdb, grass_location, "PERMANENT", "sqlite", "sqlite.db")) # create a catchment vector and overlay with str v exp = "%s = int(%s)" % (catchments, catchments) grass.run_command("r.mapcalc", expression=exp, overwrite=True) grass.run_command( "r.to.vect", input=catchments, output=cat_ply_info + "t1", type="area", overwrite=True, ) grass.run_command("v.db.addcolumn", map=cat_ply_info + "t1", columns="GC_str VARCHAR(40)") grass.run_command("v.db.addcolumn", map=cat_ply_info + "t1", columns="Area_m double") grass.run_command("v.db.update", map=cat_ply_info + "t1", column="GC_str", qcol="value") # dissolve based on gridcode grass.run_command( "v.dissolve", input=cat_ply_info + "t1", column="GC_str", output=cat_ply_info, overwrite=True, ) grass.run_command("v.db.addcolumn", map=cat_ply_info, columns="Gridcode INT") grass.run_command("v.db.update", map=cat_ply_info, column="Gridcode", qcol="GC_str") ## obtain a stream vector, segmentation based on new catchment polygon grass.run_command( "v.overlay", ainput=river_v, alayer=2, atype="line", binput=cat_ply_info, operator="and", output=cat_riv_info + "t1", overwrite=True, ) grass.run_command( "v.out.ogr", input=cat_riv_info + "t1", output=os.path.join(grassdb, cat_riv_info + "t1" + ".shp"), format="ESRI_Shapefile", overwrite=True, ) processing.run( "gdal:dissolve", { "INPUT": os.path.join(grassdb, cat_riv_info + "t1" + ".shp"), "FIELD": "b_GC_str", "OUTPUT": os.path.join(grassdb, cat_riv_info + ".shp"), }, ) grass.run_command( "v.import", input=os.path.join(grassdb, cat_riv_info + ".shp"), output=cat_riv_info, overwrite=True, ) grass.run_command("v.db.addcolumn", map=cat_riv_info, columns="Gridcode INT") grass.run_command("v.db.addcolumn", map=cat_riv_info, columns="Length_m double") grass.run_command("v.db.update", map=cat_riv_info, column="Gridcode", qcol="b_GC_str") grass.run_command("v.db.dropcolumn", map=cat_riv_info, columns=["b_GC_str"]) grass.run_command( "r.out.gdal", input=dem, output=os.path.join(grassdb, "dem_par.tif"), format="GTiff", overwrite=True, ) PERMANENT.close() os.system("gdalwarp " + '"' + os.path.join(grassdb, "dem_par.tif") + '"' + " " + '"' + os.path.join(grassdb, "dem_proj.tif") + '"' + " -t_srs " + '"' + projection + '"') project = Session() project.open(gisdb=grassdb, location=grass_location + "_proj", create_opts=projection) grass.run_command( "r.import", input=os.path.join(grassdb, "dem_proj.tif"), output="dem_proj", overwrite=True, ) grass.run_command("g.region", raster="dem_proj") grass.run_command( "v.proj", location=grass_location, mapset="PERMANENT", input=cat_riv_info, overwrite=True, ) grass.run_command( "v.proj", location=grass_location, mapset="PERMANENT", input=cat_ply_info, overwrite=True, ) grass.run_command( "v.to.db", map=cat_ply_info, option="area", columns="Area_m", units="meters", overwrite=True, ) grass.run_command( "v.to.db", map=cat_riv_info, option="length", columns="Length_m", units="meters", overwrite=True, ) grass.run_command( "r.slope.aspect", elevation="dem_proj", slope="slope", aspect="aspect", precision="DCELL", overwrite=True, ) ### calcuate averaged slope and aspect of each subbasin grass.run_command( "v.rast.stats", map=cat_ply_info, raster="slope", column_prefix="s", method="average", ) grass.run_command( "v.rast.stats", map=cat_ply_info, raster="aspect", column_prefix="a", method="average", ) grass.run_command( "v.rast.stats", map=cat_ply_info, raster="dem_proj", column_prefix="d", method="average", ) ### calcuate minimum and maximum dem along the channel grass.run_command( "v.rast.stats", map=cat_riv_info, raster="dem_proj", column_prefix="d", method=["minimum", "maximum"], ) project.close() PERMANENT = Session() PERMANENT.open(gisdb=grassdb, location=grass_location, create_opts="") grass.run_command("g.region", raster="dem") grass.run_command( "v.proj", location=grass_location + "_proj", mapset="PERMANENT", input=cat_riv_info, overwrite=True, ) grass.run_command( "v.proj", location=grass_location + "_proj", mapset="PERMANENT", input=cat_ply_info, overwrite=True, ) ### calcuate averaged DEM in each subbasin # grass.run_command( # "v.rast.stats", # map=cat_ply_info, # raster="dem", # column_prefix="d", # method="average", # ) # # ### calcuate minimum and maximum dem along the channel # grass.run_command( # "v.rast.stats", # map=cat_riv_info, # raster="dem", # column_prefix="d", # method=["minimum", "maximum"], # ) ## get routing structure exp = "%s = int(%s)" % (fdr, fdr) grass.run_command( "r.mapcalc", expression=exp, overwrite=True, ) grass.run_command( "r.accumulate", direction=fdr, accumulation="acc_grass_CatOL", overwrite=True, ) ##### obtain catment id overlaied with problem seg prom_seg_id, cat_pro_id = generate_stats_list_from_grass_raster( grass, mode=2, input_a=problem_seg, input_b=catchments) cat_pro_id = np.unique(cat_pro_id) grass.run_command("g.copy", rast=(catchments, cat_use_default_acc), overwrite=True) if len(cat_pro_id) > 0: grass.run_command("r.null", map=cat_use_default_acc, setnull=cat_pro_id, overwrite=True) else: cat_pro_id = [] exp = "acc_grass_CatOL2 = if(isnull(%s),%s,%s)" % ( cat_use_default_acc, "acc_grass_CatOL", acc, ) grass.run_command( "r.mapcalc", expression=exp, overwrite=True, ) routing_temp = generate_routing_info_of_catchments( grass, con, cat=catchments, acc="acc_grass_CatOL2", Name="Final", str=river_r, garray=garray, ) routing_temp = generate_routing_info_of_catchments( grass, con, cat=river_r, acc="acc_grass_CatOL2", Name="Friv", str=river_r, garray=garray, ) cat_array = garray.array(mapname=catchments) nfdr_arcgis_array = garray.array(mapname=nfdr_arcgis) cat_outlet_array = garray.array(mapname="Final_OL") ncols = int(cat_array.shape[1]) nrows = int(cat_array.shape[0]) grass.run_command("g.copy", vector=("Final_OL_v", outlet_pt_info), overwrite=True) PERMANENT.close() ## add coordinates to outlet point in wgs84 system project_wgs84 = Session() project_wgs84.open(gisdb=grassdb, location=grass_location + "_wgs84", create_opts='EPSG:4326') grass.run_command( "v.proj", location=grass_location, mapset="PERMANENT", input=outlet_pt_info, overwrite=True, ) grass.run_command( "v.to.db", map=outlet_pt_info, type='point', option='coor', columns=['outletLng', 'outletLat'], overwrite=True, ) project_wgs84.close() ## import updated outlet points after add coordinates in wgs84 system PERMANENT = Session() PERMANENT.open(gisdb=grassdb, location=grass_location, create_opts="") grass.run_command("g.region", raster="dem") grass.run_command( "v.proj", location=grass_location + "_wgs84", mapset="PERMANENT", input=outlet_pt_info, overwrite=True, ) ### update dataframe ### sqlstat = "SELECT Gridcode, Length_m, d_minimum, d_maximum FROM %s" % ( cat_riv_info) leninfo = pd.read_sql_query(sqlstat, con) ### read catchment sqlstat = "SELECT Gridcode, Area_m,d_average,s_average,a_average FROM %s" % ( cat_ply_info) areainfo = pd.read_sql_query(sqlstat, con) ### read catchment sqlstat = "SELECT SubId, DowSubId,ILSubIdmax,ILSubIdmin,outletLat, outletLng FROM %s" % ( outlet_pt_info) outletinfo = pd.read_sql_query(sqlstat, con) outletinfo = outletinfo.fillna(-9999) outletinfo = outletinfo.loc[outletinfo['SubId'] >= 0] ### read catchment sqlstat = "SELECT SubId, DSubId_str FROM %s" % ('Friv_OL_v') outlet_riv_info = pd.read_sql_query(sqlstat, con) outlet_riv_info = outlet_riv_info.fillna(-9999) leninfo = leninfo.astype(float).fillna(-9999) areainfo = areainfo.astype(float).fillna(-9999) for i in range(0, len(outletinfo)): catid = outletinfo["SubId"].values[i] DownSubID_cat = outletinfo["DowSubId"].values[i] outlet_lat = outletinfo["outletLat"].values[i] outlet_lon = outletinfo["outletLng"].values[i] catinfo.loc[i, "SubId"] = catid catinfo.loc[i, "outletLat"] = outlet_lat catinfo.loc[i, "outletLng"] = outlet_lon # load routing info based on str outlet_riv_info_i = outlet_riv_info.loc[outlet_riv_info['SubId'] == catid] # check if riv outlet exist if len(outlet_riv_info_i) < 1: DownSubID = DownSubID_cat DownSubID_riv = -9999 else: # get down sub id based in river network DownSubID_riv = outlet_riv_info_i['DSubId_str'].values[0] # may need to modify if downsub id from river != down subid from cat if DownSubID_riv != DownSubID_cat: # check if DownSubID_cat drainage to DSubId_str Down_id_of_downriv_info = outletinfo.loc[outletinfo['SubId'] == DownSubID_riv] if len(Down_id_of_downriv_info) > 0: # get down subid of down subid of river DSubId_DSubId_str = Down_id_of_downriv_info[ 'DowSubId'].values[0] # if down subid of down sub id of river = down sub id from cat if catid == 10762: print(DSubId_DSubId_str, DownSubID_cat) if DSubId_DSubId_str == DownSubID_cat: DownSubID = DownSubID_riv else: DownSubID = DownSubID_cat else: DownSubID = DownSubID_cat else: DownSubID = DownSubID_cat if catid in cat_pro_id or DownSubID == catid or DownSubID == -9999: downsubid_array = return_subid_of_next_down_stream_grids( cat_array, catid, nfdr_arcgis_array, cat_outlet_array, ncols, nrows) # print(catid,DownSubID,downsubid_array) if downsubid_array > 0: DownSubID = downsubid_array ### change the downsub id to -1 for watershed outlet if len(outletinfo.loc[outletinfo["SubId"] == DownSubID]) < 1: catinfo.loc[i, "DowSubId"] = -1 elif catid == DownSubID: catinfo.loc[i, "DowSubId"] = -1 else: catinfo.loc[i, "DowSubId"] = DownSubID catarea = np.unique(areainfo.loc[areainfo["Gridcode"] == catid] ["Area_m"].values) #'Area_m' catslope = np.unique( areainfo.loc[areainfo["Gridcode"] == catid]["s_average"].values) catelev = np.unique( areainfo.loc[areainfo["Gridcode"] == catid]["d_average"].values) cataspect = np.unique( areainfo.loc[areainfo["Gridcode"] == catid]["a_average"].values) if len(catarea) == 1: catinfo.loc[i, "BasArea"] = catarea catinfo.loc[i, "BasSlope"] = catslope catinfo.loc[i, "BasAspect"] = cataspect catinfo.loc[i, "MeanElev"] = catelev else: print( "Warning basin area of stream ", catid, " need check ", len(catarea), ) catinfo.loc[i, "BasArea"] = -9999 catinfo.loc[i, "BasSlope"] = -9999 catinfo.loc[i, "BasAspect"] = -9999 catinfo.loc[i, "MeanElev"] = -9999 ### add river parameters rivlen = np.unique(leninfo.loc[leninfo["Gridcode"] == catid] ["Length_m"].values) #'Area_m' dmaxelev = np.unique( leninfo.loc[leninfo["Gridcode"] == catid]["d_maximum"].values) dminelev = np.unique( leninfo.loc[leninfo["Gridcode"] == catid]["d_minimum"].values) if len(rivlen) > 0: catinfo.loc[i, "RivLength"] = rivlen[0] maxdem = dmaxelev[0] mindem = dminelev[0] catinfo.loc[i, "Min_DEM"] = mindem catinfo.loc[i, "Max_DEM"] = maxdem if rivlen[0] >= 0: if max(0, float((maxdem - mindem)) / float(rivlen[0])) == 0: slope_rch = -9999 else: slope_rch = max( 0, float((maxdem - mindem)) / float(rivlen[0])) slope_rch = max(slope_rch, min_riv_slope) slope_rch = min(slope_rch, max_riv_slope) catinfo.loc[i, "RivSlope"] = slope_rch else: catinfo.loc[i, "RivSlope"] = -9999 else: catinfo.loc[i, "RivLength"] = -9999 catinfo.loc[i, "RivSlope"] = -9999 catinfo.loc[i, "FloodP_n"] = -9999 catinfo.loc[i, "Min_DEM"] = -9999 catinfo.loc[i, "Max_DEM"] = -9999 PERMANENT.close() return catinfo
def populateByExpression(self, adding=False): """ Populates the panel using an expression """ context = dataobjects.createContext() expression_context = context.expressionContext() # use the first row parameter values as a preview during expression creation params, ok = self.panel.parametersForRow(0, warnOnInvalid=False) alg_scope = QgsExpressionContextUtils.processingAlgorithmScope(self.panel.alg, params, context) # create explicit variables corresponding to every parameter for k, v in params.items(): alg_scope.setVariable(k, v, True) # add batchCount in the alg scope to be used in the expressions. 0 is only an example value alg_scope.setVariable('row_number', 0, False) expression_context.appendScope(alg_scope) # mark the parameter variables as highlighted for discoverability highlighted_vars = expression_context.highlightedVariables() highlighted_vars.extend(list(params.keys())) highlighted_vars.append('row_number') expression_context.setHighlightedVariables(highlighted_vars) dlg = QgsExpressionBuilderDialog(layer=None, context=context.expressionContext()) if adding: dlg.setExpectedOutputFormat(self.tr('An array of values corresponding to each new row to add')) if not dlg.exec_(): return if adding: exp = QgsExpression(dlg.expressionText()) res = exp.evaluate(expression_context) if type(res) is not list: res = [res] first_row = self.panel.batchRowCount() if self.panel.batchRowCount() > 1 else 0 for row, value in enumerate(res): self.setRowValue(row + first_row, value, context) else: for row in range(self.panel.batchRowCount()): params, ok = self.panel.parametersForRow(row, warnOnInvalid=False) # remove previous algorithm scope -- we need to rebuild this completely, using the # other parameter values from the current row expression_context.popScope() alg_scope = QgsExpressionContextUtils.processingAlgorithmScope(self.panel.alg, params, context) for k, v in params.items(): alg_scope.setVariable(k, v, True) # add batch row number as evaluable variable in algorithm scope alg_scope.setVariable('row_number', row, False) expression_context.appendScope(alg_scope) # rebuild a new expression every time -- we don't want the expression compiler to replace # variables with precompiled values exp = QgsExpression(dlg.expressionText()) value = exp.evaluate(expression_context) self.setRowValue(row, value, context)
def runAlgorithm(self): self.feedback = self.createFeedback() self.context = dataobjects.createContext(self.feedback) self.context.setLogLevel(self.logLevel()) checkCRS = ProcessingConfig.getSetting( ProcessingConfig.WARN_UNMATCHING_CRS) try: # messy as all heck, but we don't want to call the dialog's implementation of # createProcessingParameters as we want to catch the exceptions raised by the # parameter panel instead... parameters = {} if self.mainWidget() is None else self.mainWidget( ).createProcessingParameters() if checkCRS and not self.algorithm().validateInputCrs( parameters, self.context): reply = QMessageBox.question( self, self.tr("Unmatching CRS's"), self.tr('Parameters do not all use the same CRS. This can ' 'cause unexpected results.\nDo you want to ' 'continue?'), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.No: return ok, msg = self.algorithm().checkParameterValues( parameters, self.context) if not ok: QMessageBox.warning(self, self.tr('Unable to execute algorithm'), msg) return self.blockControlsWhileRunning() self.setExecutedAnyResult(True) self.cancelButton().setEnabled(False) self.iterateParam = None for param in self.algorithm().parameterDefinitions(): if isinstance( parameters.get(param.name(), None), QgsProcessingFeatureSourceDefinition ) and parameters[param.name( )].flags & QgsProcessingFeatureSourceDefinition.FlagCreateIndividualOutputPerInputFeature: self.iterateParam = param.name() break self.clearProgress() self.feedback.pushVersionInfo(self.algorithm().provider()) if self.algorithm().provider().warningMessage(): self.feedback.reportError( self.algorithm().provider().warningMessage()) self.feedback.pushInfo( QCoreApplication.translate('AlgorithmDialog', 'Algorithm started at: {}').format( datetime.datetime.now().replace( microsecond=0).isoformat())) self.setInfo(QCoreApplication.translate( 'AlgorithmDialog', '<b>Algorithm \'{0}\' starting…</b>').format( self.algorithm().displayName()), escapeHtml=False) self.feedback.pushInfo(self.tr('Input parameters:')) display_params = [] for k, v in parameters.items(): display_params.append("'" + k + "' : " + self.algorithm( ).parameterDefinition(k).valueAsPythonString(v, self.context)) self.feedback.pushCommandInfo('{ ' + ', '.join(display_params) + ' }') self.feedback.pushInfo('') start_time = time.time() def elapsed_time(start_time, result): delta_t = time.time() - start_time hours = int(delta_t / 3600) minutes = int((delta_t % 3600) / 60) seconds = delta_t - hours * 3600 - minutes * 60 str_hours = [self.tr("hour"), self.tr("hours")][hours > 1] str_minutes = [self.tr("minute"), self.tr("minutes")][minutes > 1] str_seconds = [self.tr("second"), self.tr("seconds")][seconds != 1] if hours > 0: elapsed = '{0} {1:0.2f} {2} ({3} {4} {5} {6} {7:0.0f} {2})'.format( result, delta_t, str_seconds, hours, str_hours, minutes, str_minutes, seconds) elif minutes > 0: elapsed = '{0} {1:0.2f} {2} ({3} {4} {5:0.0f} {2})'.format( result, delta_t, str_seconds, minutes, str_minutes, seconds) else: elapsed = '{0} {1:0.2f} {2}'.format( result, delta_t, str_seconds) return elapsed if self.iterateParam: # Make sure the Log tab is visible before executing the algorithm try: self.showLog() self.repaint() except: pass self.cancelButton().setEnabled( self.algorithm().flags() & QgsProcessingAlgorithm.FlagCanCancel) if executeIterating(self.algorithm(), parameters, self.iterateParam, self.context, self.feedback): self.feedback.pushInfo( self.tr( elapsed_time(start_time, 'Execution completed in'))) self.cancelButton().setEnabled(False) self.finish(True, parameters, self.context, self.feedback) else: self.cancelButton().setEnabled(False) self.resetGui() else: self.history_details = { 'python_command': self.algorithm().asPythonCommand(parameters, self.context), 'algorithm_id': self.algorithm().id(), 'parameters': self.algorithm().asMap(parameters, self.context) } process_command, command_ok = self.algorithm( ).asQgisProcessCommand(parameters, self.context) if command_ok: self.history_details['process_command'] = process_command self.history_log_id, _ = QgsGui.historyProviderRegistry( ).addEntry('processing', self.history_details) QgsGui.instance().processingRecentAlgorithmLog().push( self.algorithm().id()) self.cancelButton().setEnabled( self.algorithm().flags() & QgsProcessingAlgorithm.FlagCanCancel) def on_complete(ok, results): if ok: self.feedback.pushInfo( self.tr( elapsed_time(start_time, 'Execution completed in'))) self.feedback.pushInfo(self.tr('Results:')) r = { k: v for k, v in results.items() if k not in ('CHILD_RESULTS', 'CHILD_INPUTS') } self.feedback.pushCommandInfo(pformat(r)) else: self.feedback.reportError( self.tr( elapsed_time(start_time, 'Execution failed after'))) self.feedback.pushInfo('') if self.history_log_id is not None: # can't deepcopy this! self.history_details['results'] = { k: v for k, v in results.items() if k != 'CHILD_INPUTS' } QgsGui.historyProviderRegistry().updateEntry( self.history_log_id, self.history_details) if self.feedback_dialog is not None: self.feedback_dialog.close() self.feedback_dialog.deleteLater() self.feedback_dialog = None self.cancelButton().setEnabled(False) self.finish(ok, results, self.context, self.feedback, in_place=self.in_place) self.feedback = None self.context = None if not self.in_place and not ( self.algorithm().flags() & QgsProcessingAlgorithm.FlagNoThreading): # Make sure the Log tab is visible before executing the algorithm self.showLog() task = QgsProcessingAlgRunnerTask(self.algorithm(), parameters, self.context, self.feedback) if task.isCanceled(): on_complete(False, {}) else: task.executed.connect(on_complete) self.setCurrentTask(task) else: self.proxy_progress = QgsProxyProgressTask( QCoreApplication.translate( "AlgorithmDialog", "Executing “{}”").format( self.algorithm().displayName())) QgsApplication.taskManager().addTask(self.proxy_progress) self.feedback.progressChanged.connect( self.proxy_progress.setProxyProgress) self.feedback_dialog = self.createProgressDialog() self.feedback_dialog.show() if self.in_place: ok, results = execute_in_place(self.algorithm(), parameters, self.context, self.feedback) else: ok, results = execute(self.algorithm(), parameters, self.context, self.feedback) self.feedback.progressChanged.disconnect() self.proxy_progress.finalize(ok) on_complete(ok, results) except AlgorithmDialogBase.InvalidParameterValue as e: self.flag_invalid_parameter_value(e.parameter.description(), e.widget) except AlgorithmDialogBase.InvalidOutputExtension as e: self.flag_invalid_output_extension(e.message, e.widget)