def refresh(self): layers = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance()) options = {} for lyr in layers: for n in range(lyr.bandCount()): options[lyr.name()] = '{:s}@{:d}'.format(lyr.name(), n + 1) self.widget.setList(options)
def showLayerSelectionDialog(self): if (isinstance(self.param, ParameterRaster) or (isinstance(self.param, ParameterMultipleInput) and self.param.datatype == dataobjects.TYPE_RASTER)): layers = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance()) elif isinstance(self.param, ParameterTable): layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance()) else: if isinstance(self.param, ParameterVector): datatype = self.param.datatype else: datatype = [self.param.datatype] if datatype != dataobjects.TYPE_VECTOR_ANY: layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [datatype]) else: layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance()) dlg = MultipleInputDialog([layer.name() for layer in layers]) dlg.exec_() if dlg.selectedoptions is not None: selected = dlg.selectedoptions if len(selected) == 1: self.setValue(layers[selected[0]]) else: if isinstance(self.param, ParameterMultipleInput): self.text.setText(';'.join(layers[idx].name() for idx in selected)) else: rowdif = len(selected) - (self._table().rowCount() - self.row) for i in range(rowdif): self._panel().addRow() for i, layeridx in enumerate(selected): self._table().cellWidget(i + self.row, self.col).setValue(layers[layeridx])
def getAsString(self, value): if self.datatype == dataobjects.TYPE_RASTER: if isinstance(value, QgsRasterLayer): return str(value.dataProvider().dataSourceUri()) else: s = str(value) layers = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance()) for layer in layers: if layer.name() == s: return str(layer.dataProvider().dataSourceUri()) return s if self.datatype == dataobjects.TYPE_FILE: return str(value) else: if isinstance(value, QgsVectorLayer): return str(value.source()) else: s = str(value) if self.datatype != dataobjects.TYPE_VECTOR_ANY: layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [self.datatype], False) else: layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False) for layer in layers: if layer.name() == s: return str(layer.source()) return s
def refresh(self): # TODO: check if avoid code duplication with self.createWidget layers = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance()) options = {} for lyr in layers: for n in range(lyr.bandCount()): options[lyr.name()] = '{:s}@{:d}'.format(lyr.name(), n + 1) self.widget.setList(options)
def processAlgorithm(self, parameters, context, feedback): expression = self.getParameterValue(self.EXPRESSION) layersValue = self.getParameterValue(self.LAYERS) layersDict = {} if layersValue: layers = [QgsProcessingUtils.mapLayerFromString(f, context) for f in layersValue.split(";")] layersDict = {os.path.basename(lyr.source().split(".")[0]): lyr for lyr in layers} for lyr in QgsProcessingUtils.compatibleRasterLayers(context.project()): name = lyr.name() if (name + "@") in expression: layersDict[name] = lyr entries = [] for name, lyr in layersDict.items(): for n in range(lyr.bandCount()): entry = QgsRasterCalculatorEntry() entry.ref = '{:s}@{:d}'.format(name, n + 1) entry.raster = lyr entry.bandNumber = n + 1 entries.append(entry) output = self.getOutputValue(self.OUTPUT) extentValue = self.getParameterValue(self.EXTENT) if not extentValue: extentValue = QgsProcessingUtils.combineLayerExtents(layersValue) if extentValue: extent = extentValue.split(',') bbox = QgsRectangle(float(extent[0]), float(extent[2]), float(extent[1]), float(extent[3])) else: if layersDict: bbox = list(layersDict.values())[0].extent() for lyr in layersDict.values(): bbox.combineExtentWith(lyr.extent()) else: raise GeoAlgorithmExecutionException(self.tr("No layers selected")) def _cellsize(layer): return (layer.extent().xMaximum() - layer.extent().xMinimum()) / layer.width() cellsize = self.getParameterValue(self.CELLSIZE) or min([_cellsize(lyr) for lyr in layersDict.values()]) width = math.floor((bbox.xMaximum() - bbox.xMinimum()) / cellsize) height = math.floor((bbox.yMaximum() - bbox.yMinimum()) / cellsize) driverName = GdalUtils.getFormatShortNameFromFilename(output) calc = QgsRasterCalculator(expression, output, driverName, bbox, width, height, entries) res = calc.processCalculation() if res == QgsRasterCalculator.ParserError: raise GeoAlgorithmExecutionException(self.tr("Error parsing formula"))
def processAlgorithm(self, parameters, context, feedback): expression = self.parameterAsString(parameters, self.EXPRESSION, context) layers = self.parameterAsLayerList(parameters, self.LAYERS, context) layersDict = {} if layers: layersDict = {os.path.basename(lyr.source().split(".")[0]): lyr for lyr in layers} for lyr in QgsProcessingUtils.compatibleRasterLayers(context.project()): name = lyr.name() if (name + "@") in expression: layersDict[name] = lyr entries = [] for name, lyr in layersDict.items(): for n in range(lyr.bandCount()): entry = QgsRasterCalculatorEntry() entry.ref = '{:s}@{:d}'.format(name, n + 1) entry.raster = lyr entry.bandNumber = n + 1 entries.append(entry) output = self.parameterAsOutputLayer(parameters, self.OUTPUT, context) bbox = self.parameterAsExtent(parameters, self.EXTENT, context) if bbox.isNull(): bbox = QgsProcessingUtils.combineLayerExtents(layers) if bbox.isNull(): if layersDict: bbox = list(layersDict.values())[0].extent() for lyr in layersDict.values(): bbox.combineExtentWith(lyr.extent()) else: raise QgsProcessingException(self.tr("No layers selected")) def _cellsize(layer): return (layer.extent().xMaximum() - layer.extent().xMinimum()) / layer.width() cellsize = self.parameterAsDouble(parameters, self.CELLSIZE, context) or min([_cellsize(lyr) for lyr in layersDict.values()]) width = math.floor((bbox.xMaximum() - bbox.xMinimum()) / cellsize) height = math.floor((bbox.yMaximum() - bbox.yMinimum()) / cellsize) driverName = GdalUtils.getFormatShortNameFromFilename(output) calc = QgsRasterCalculator(expression, output, driverName, bbox, width, height, entries) res = calc.processCalculation() if res == QgsRasterCalculator.ParserError: raise QgsProcessingException(self.tr("Error parsing formula")) return {self.OUTPUT: output}
def showLayerSelectionDialog(self): layers = [] if (isinstance(self.param, QgsProcessingParameterRasterLayer) or (isinstance(self.param, QgsProcessingParameterMultipleLayers) and self.param.layerType() == QgsProcessing.TypeRaster)): layers = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance()) elif isinstance(self.param, QgsProcessingParameterVectorLayer): layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance()) elif (isinstance(self.param, QgsProcessingParameterMeshLayer) or (isinstance(self.param, QgsProcessingParameterMultipleLayers) and self.param.layerType() == QgsProcessing.TypeMesh)): layers = QgsProcessingUtils.compatibleMeshLayers(QgsProject.instance()) else: datatypes = [QgsProcessing.TypeVectorAnyGeometry] if isinstance(self.param, QgsProcessingParameterFeatureSource): datatypes = self.param.dataTypes() elif isinstance(self.param, QgsProcessingParameterMultipleLayers): datatypes = [self.param.layerType()] if QgsProcessing.TypeVectorAnyGeometry not in datatypes: layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), datatypes) else: layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance()) dlg = MultipleInputDialog([layer.name() for layer in layers]) dlg.exec_() def generate_layer_id(layer): # prefer layer name if unique if len([l for l in layers if l.name().lower() == layer.name().lower()]) == 1: return layer.name() else: # otherwise fall back to layer id return layer.id() if dlg.selectedoptions is not None: selected = dlg.selectedoptions if len(selected) == 1: self.setValue(generate_layer_id(layers[selected[0]])) else: if isinstance(self.param, QgsProcessingParameterMultipleLayers): self.text.setText(';'.join(layers[idx].id() for idx in selected)) else: rowdif = len(selected) - (self._table().rowCount() - self.row) for i in range(rowdif): self._panel().addRow() for i, layeridx in enumerate(selected): self._table().cellWidget(i + self.row, self.col).setValue(generate_layer_id(layers[layeridx]))
def createWidget(self): if self.dialogType == DIALOG_STANDARD: layers = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance(), False) options = {} for lyr in layers: for n in range(lyr.bandCount()): name = '{:s}@{:d}'.format(lyr.name(), n + 1) options[name] = name return self._panel(options) elif self.dialogType == DIALOG_BATCH: return QLineEdit() else: layers = self.dialog.getAvailableValuesOfType([QgsProcessingParameterRasterLayer], [QgsProcessingOutputRasterLayer]) options = {self.dialog.resolveValueDescription(lyr): "{}@1".format(lyr) for lyr in layers} return self._panel(options)
def value(self): if self.dialogType == DIALOG_STANDARD: if self.param.datatype == dataobjects.TYPE_FILE: return self.param.setValue(self.widget.selectedoptions) else: if self.param.datatype == dataobjects.TYPE_RASTER: options = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance(), False) elif self.param.datatype == dataobjects.TYPE_VECTOR_ANY: options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False) else: options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [self.param.datatype], False) return [options[i] for i in self.widget.selectedoptions] elif self.dialogType == DIALOG_BATCH: return self.widget.getText() else: options = self._getOptions() values = [options[i] for i in self.widget.selectedoptions] if len(values) == 0 and not self.param.flags() & QgsProcessingParameterDefinition.FlagOptional: raise InvalidParameterValue() return values
def createWidget(self): if self.dialogType == DIALOG_STANDARD: layers = QgsProcessingUtils.compatibleRasterLayers( QgsProject.instance(), False) options = {} for lyr in layers: for n in range(lyr.bandCount()): name = '{:s}@{:d}'.format(lyr.name(), n + 1) options[name] = name return self._panel(options) elif self.dialogType == DIALOG_BATCH: return QLineEdit() else: layers = self.dialog.getAvailableValuesOfType( [QgsProcessingParameterRasterLayer], [QgsProcessingOutputRasterLayer]) options = { self.dialog.resolveValueDescription(lyr): "{}@1".format(lyr) for lyr in layers } return self._panel(options)
def showLayerSelectionDialog(self): if (isinstance(self.param, ParameterRaster) or (isinstance(self.param, ParameterMultipleInput) and self.param.datatype == dataobjects.TYPE_RASTER)): layers = QgsProcessingUtils.compatibleRasterLayers( QgsProject.instance()) elif isinstance(self.param, ParameterTable): layers = QgsProcessingUtils.compatibleVectorLayers( QgsProject.instance()) else: if isinstance(self.param, ParameterVector): datatype = self.param.datatype else: datatype = [self.param.datatype] if datatype != dataobjects.TYPE_VECTOR_ANY: layers = QgsProcessingUtils.compatibleVectorLayers( QgsProject.instance(), [datatype]) else: layers = QgsProcessingUtils.compatibleVectorLayers( QgsProject.instance()) dlg = MultipleInputDialog([layer.name() for layer in layers]) dlg.exec_() if dlg.selectedoptions is not None: selected = dlg.selectedoptions if len(selected) == 1: self.setValue(layers[selected[0]]) else: if isinstance(self.param, ParameterMultipleInput): self.text.setText(';'.join(layers[idx].name() for idx in selected)) else: rowdif = len(selected) - (self._table().rowCount() - self.row) for i in range(rowdif): self._panel().addRow() for i, layeridx in enumerate(selected): self._table().cellWidget( i + self.row, self.col).setValue(layers[layeridx])
def value(self): if self.dialogType == DIALOG_STANDARD: if self.param.datatype == dataobjects.TYPE_FILE: return self.param.setValue(self.widget.selectedoptions) else: if self.param.datatype == dataobjects.TYPE_RASTER: options = QgsProcessingUtils.compatibleRasterLayers( QgsProject.instance(), False) elif self.param.datatype == dataobjects.TYPE_VECTOR_ANY: options = QgsProcessingUtils.compatibleVectorLayers( QgsProject.instance(), [], False) else: options = QgsProcessingUtils.compatibleVectorLayers( QgsProject.instance(), [self.param.datatype], False) return [options[i] for i in self.widget.selectedoptions] elif self.dialogType == DIALOG_BATCH: return self.widget.getText() else: options = self._getOptions() values = [options[i] for i in self.widget.selectedoptions] if len(values) == 0 and not self.param.optional: raise InvalidParameterValue() return values
def showLayerSelectionDialog(self): layers = [] if (isinstance(self.param, QgsProcessingParameterRasterLayer) or (isinstance(self.param, QgsProcessingParameterMultipleLayers) and self.param.layerType() == QgsProcessing.TypeRaster)): layers = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance()) elif isinstance(self.param, QgsProcessingParameterVectorLayer): layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance()) else: datatypes = [QgsProcessing.TypeVectorAny] if isinstance(self.param, QgsProcessingParameterFeatureSource): datatypes = self.param.dataTypes() elif isinstance(self.param, QgsProcessingParameterMultipleLayers): datatypes = [self.param.layerType()] if QgsProcessing.TypeVectorAny not in datatypes: layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), datatypes) else: layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance()) dlg = MultipleInputDialog([layer.name() for layer in layers]) dlg.exec_() if dlg.selectedoptions is not None: selected = dlg.selectedoptions if len(selected) == 1: self.setValue(layers[selected[0]].id()) else: if isinstance(self.param, QgsProcessingParameterMultipleLayers): self.text.setText(';'.join(layers[idx].id() for idx in selected)) else: rowdif = len(selected) - (self._table().rowCount() - self.row) for i in range(rowdif): self._panel().addRow() for i, layeridx in enumerate(selected): self._table().cellWidget(i + self.row, self.col).setValue(layers[layeridx].id())
def showLayerSelectionDialog(self): layers = [] if (isinstance(self.param, QgsProcessingParameterRasterLayer) or (isinstance(self.param, QgsProcessingParameterMultipleLayers) and self.param.layerType() == QgsProcessingParameterDefinition.TypeRaster)): layers = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance()) elif isinstance(self.param, QgsProcessingParameterVectorLayer): layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance()) else: datatypes = [QgsProcessingParameterDefinition.TypeVectorAny] if isinstance(self.param, QgsProcessingParameterFeatureSource): datatypes = self.param.dataTypes() elif isinstance(self.param, QgsProcessingParameterMultipleLayers): datatypes = [self.param.layerType()] if QgsProcessingParameterDefinition.TypeVectorAny not in datatypes: layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), datatypes) else: layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance()) dlg = MultipleInputDialog([layer.name() for layer in layers]) dlg.exec_() if dlg.selectedoptions is not None: selected = dlg.selectedoptions if len(selected) == 1: self.setValue(layers[selected[0]].id()) else: if isinstance(self.param, QgsProcessingParameterMultipleLayers): self.text.setText(';'.join(layers[idx].id() for idx in selected)) else: rowdif = len(selected) - (self._table().rowCount() - self.row) for i in range(rowdif): self._panel().addRow() for i, layeridx in enumerate(selected): self._table().cellWidget(i + self.row, self.col).setValue(layers[layeridx].id())
def processAlgorithm(self, parameters, context, feedback): expression = self.parameterAsString(parameters, self.EXPRESSION, context) layers = self.parameterAsLayerList(parameters, self.LAYERS, context) layersDict = {} if layers: layersDict = { os.path.basename(lyr.source().split(".")[0]): lyr for lyr in layers } crs = self.parameterAsCrs(parameters, self.CRS, context) if not layers and not crs.isValid(): raise QgsProcessingException( self.tr("No reference layer selected nor CRS provided")) if not crs.isValid() and layers: crs = list(layersDict.values())[0].crs() bbox = self.parameterAsExtent(parameters, self.EXTENT, context) if not layers and bbox.isNull(): raise QgsProcessingException( self.tr("No reference layer selected nor extent box provided")) if not bbox.isNull(): bboxCrs = self.parameterAsExtentCrs(parameters, self.EXTENT, context) if bboxCrs != crs: transform = QgsCoordinateTransform(bboxCrs, crs, context.project()) bbox = transform.transformBoundingBox(bbox) if bbox.isNull() and layers: bbox = QgsProcessingUtils.combineLayerExtents(layers, crs) cellsize = self.parameterAsDouble(parameters, self.CELLSIZE, context) if not layers and cellsize == 0: raise QgsProcessingException( self.tr( "No reference layer selected nor cellsize value provided")) def _cellsize(layer): ext = layer.extent() if layer.crs() != crs: transform = QgsCoordinateTransform(layer.crs(), crs, context.project()) ext = transform.transformBoundingBox(ext) return (ext.xMaximum() - ext.xMinimum()) / layer.width() if cellsize == 0: cellsize = min([_cellsize(lyr) for lyr in layersDict.values()]) for lyr in QgsProcessingUtils.compatibleRasterLayers( context.project()): name = lyr.name() if (name + "@") in expression: layersDict[name] = lyr entries = [] for name, lyr in layersDict.items(): for n in range(lyr.bandCount()): ref = '{:s}@{:d}'.format(name, n + 1) if ref in expression: entry = QgsRasterCalculatorEntry() entry.ref = ref entry.raster = lyr entry.bandNumber = n + 1 entries.append(entry) output = self.parameterAsOutputLayer(parameters, self.OUTPUT, context) width = math.floor((bbox.xMaximum() - bbox.xMinimum()) / cellsize) height = math.floor((bbox.yMaximum() - bbox.yMinimum()) / cellsize) driverName = GdalUtils.getFormatShortNameFromFilename(output) calc = QgsRasterCalculator(expression, output, driverName, bbox, crs, width, height, entries) res = calc.processCalculation(feedback) if res == QgsRasterCalculator.ParserError: raise QgsProcessingException(self.tr("Error parsing formula")) return {self.OUTPUT: output}
def processAlgorithm(self, parameters, context, feedback): expression = self.parameterAsString(parameters, self.EXPRESSION, context) layers = self.parameterAsLayerList(parameters, self.LAYERS, context) layersDict = {} if layers: layersDict = {lyr.source(): lyr for lyr in layers} crs = self.parameterAsCrs(parameters, self.CRS, context) if crs is None or not crs.isValid(): if not layers: raise QgsProcessingException( self.tr("No reference layer selected nor CRS provided")) else: crs = list(layersDict.values())[0].crs() bbox = self.parameterAsExtent(parameters, self.EXTENT, context) if bbox.isNull() and not layers: raise QgsProcessingException( self.tr("No reference layer selected nor extent box provided")) if not bbox.isNull(): bboxCrs = self.parameterAsExtentCrs(parameters, self.EXTENT, context) if bboxCrs != crs: transform = QgsCoordinateTransform(bboxCrs, crs, context.project()) bbox = transform.transformBoundingBox(bbox) if bbox.isNull() and layers: bbox = QgsProcessingUtils.combineLayerExtents(layers, crs) cellsize = self.parameterAsDouble(parameters, self.CELLSIZE, context) if cellsize == 0 and not layers: raise QgsProcessingException( self.tr( "No reference layer selected nor cellsize value provided")) def _cellsize(layer): ext = layer.extent() if layer.crs() != crs: transform = QgsCoordinateTransform(layer.crs(), crs, context.project()) ext = transform.transformBoundingBox(ext) return (ext.xMaximum() - ext.xMinimum()) / layer.width() if cellsize == 0: cellsize = min([_cellsize(lyr) for lyr in layersDict.values()]) # check for layers available in the model layersDictCopy = layersDict.copy( ) # need a shallow copy because next calls invalidate iterator for lyr in layersDictCopy.values(): expression = self.mappedNameToLayer(lyr, expression, layersDict, context) # check for layers available in the project for lyr in QgsProcessingUtils.compatibleRasterLayers( context.project()): expression = self.mappedNameToLayer(lyr, expression, layersDict, context) # create the list of layers to be passed as inputs to RasterCalculaltor # at this phase expression has been modified to match available layers # in the current scope entries = [] for name, lyr in layersDict.items(): for n in range(lyr.bandCount()): ref = '{:s}@{:d}'.format(name, n + 1) if ref in expression: entry = QgsRasterCalculatorEntry() entry.ref = ref entry.raster = lyr entry.bandNumber = n + 1 entries.append(entry) # Append any missing entry from the current project for entry in QgsRasterCalculatorEntry.rasterEntries(): if not [e for e in entries if e.ref == entry.ref]: entries.append(entry) output = self.parameterAsOutputLayer(parameters, self.OUTPUT, context) width = round((bbox.xMaximum() - bbox.xMinimum()) / cellsize) height = round((bbox.yMaximum() - bbox.yMinimum()) / cellsize) driverName = GdalUtils.getFormatShortNameFromFilename(output) calc = QgsRasterCalculator(expression, output, driverName, bbox, crs, width, height, entries) res = calc.processCalculation(feedback) if res == QgsRasterCalculator.ParserError: raise QgsProcessingException(self.tr("Error parsing formula")) return {self.OUTPUT: output}
def processAlgorithm(self, parameters, context, feedback): expression = self.parameterAsString(parameters, self.EXPRESSION, context) layers = self.parameterAsLayerList(parameters, self.LAYERS, context) layersDict = {} if layers: layersDict = {lyr.source(): lyr for lyr in layers} crs = self.parameterAsCrs(parameters, self.CRS, context) if crs is None or not crs.isValid(): if not layers: raise QgsProcessingException(self.tr("No reference layer selected nor CRS provided")) else: crs = list(layersDict.values())[0].crs() bbox = self.parameterAsExtent(parameters, self.EXTENT, context) if bbox.isNull() and not layers: raise QgsProcessingException(self.tr("No reference layer selected nor extent box provided")) if not bbox.isNull(): bboxCrs = self.parameterAsExtentCrs(parameters, self.EXTENT, context) if bboxCrs != crs: transform = QgsCoordinateTransform(bboxCrs, crs, context.project()) bbox = transform.transformBoundingBox(bbox) if bbox.isNull() and layers: bbox = QgsProcessingUtils.combineLayerExtents(layers, crs, context) cellsize = self.parameterAsDouble(parameters, self.CELLSIZE, context) if cellsize == 0 and not layers: raise QgsProcessingException(self.tr("No reference layer selected nor cellsize value provided")) def _cellsize(layer): ext = layer.extent() if layer.crs() != crs: transform = QgsCoordinateTransform(layer.crs(), crs, context.project()) ext = transform.transformBoundingBox(ext) return (ext.xMaximum() - ext.xMinimum()) / layer.width() if cellsize == 0: cellsize = min([_cellsize(lyr) for lyr in layersDict.values()]) # check for layers available in the model layersDictCopy = layersDict.copy() # need a shallow copy because next calls invalidate iterator for lyr in layersDictCopy.values(): expression = self.mappedNameToLayer(lyr, expression, layersDict, context) # check for layers available in the project for lyr in QgsProcessingUtils.compatibleRasterLayers(context.project()): expression = self.mappedNameToLayer(lyr, expression, layersDict, context) # create the list of layers to be passed as inputs to RasterCalculaltor # at this phase expression has been modified to match available layers # in the current scope entries = [] for name, lyr in layersDict.items(): for n in range(lyr.bandCount()): ref = '{:s}@{:d}'.format(name, n + 1) if ref in expression: entry = QgsRasterCalculatorEntry() entry.ref = ref entry.raster = lyr entry.bandNumber = n + 1 entries.append(entry) # Append any missing entry from the current project for entry in QgsRasterCalculatorEntry.rasterEntries(): if not [e for e in entries if e.ref == entry.ref]: entries.append(entry) output = self.parameterAsOutputLayer(parameters, self.OUTPUT, context) width = round((bbox.xMaximum() - bbox.xMinimum()) / cellsize) height = round((bbox.yMaximum() - bbox.yMinimum()) / cellsize) driverName = GdalUtils.getFormatShortNameFromFilename(output) calc = QgsRasterCalculator(expression, output, driverName, bbox, crs, width, height, entries, context.transformContext()) res = calc.processCalculation(feedback) if res == QgsRasterCalculator.ParserError: raise QgsProcessingException(self.tr("Error parsing formula")) return {self.OUTPUT: output}
def processAlgorithm(self, parameters, context, feedback): expression = self.getParameterValue(self.EXPRESSION) layersValue = self.getParameterValue(self.LAYERS) layersDict = {} if layersValue: layers = [ QgsProcessingUtils.mapLayerFromString(f, context) for f in layersValue.split(";") ] layersDict = { os.path.basename(lyr.source().split(".")[0]): lyr for lyr in layers } for lyr in QgsProcessingUtils.compatibleRasterLayers( context.project()): name = lyr.name() if (name + "@") in expression: layersDict[name] = lyr entries = [] for name, lyr in layersDict.items(): for n in range(lyr.bandCount()): entry = QgsRasterCalculatorEntry() entry.ref = '{:s}@{:d}'.format(name, n + 1) entry.raster = lyr entry.bandNumber = n + 1 entries.append(entry) output = self.getOutputValue(self.OUTPUT) extentValue = self.getParameterValue(self.EXTENT) if not extentValue: extentValue = QgsProcessingUtils.combineLayerExtents(layersValue) if extentValue: extent = extentValue.split(',') bbox = QgsRectangle(float(extent[0]), float(extent[2]), float(extent[1]), float(extent[3])) else: if layersDict: bbox = list(layersDict.values())[0].extent() for lyr in layersDict.values(): bbox.combineExtentWith(lyr.extent()) else: raise GeoAlgorithmExecutionException( self.tr("No layers selected")) def _cellsize(layer): return (layer.extent().xMaximum() - layer.extent().xMinimum()) / layer.width() cellsize = self.getParameterValue(self.CELLSIZE) or min( [_cellsize(lyr) for lyr in layersDict.values()]) width = math.floor((bbox.xMaximum() - bbox.xMinimum()) / cellsize) height = math.floor((bbox.yMaximum() - bbox.yMinimum()) / cellsize) driverName = GdalUtils.getFormatShortNameFromFilename(output) calc = QgsRasterCalculator(expression, output, driverName, bbox, width, height, entries) res = calc.processCalculation() if res == QgsRasterCalculator.ParserError: raise GeoAlgorithmExecutionException( self.tr("Error parsing formula"))
def processAlgorithm(self, parameters, context, feedback): expression = self.parameterAsString(parameters, self.EXPRESSION, context) layers = self.parameterAsLayerList(parameters, self.LAYERS, context) layersDict = {} if layers: layersDict = {os.path.basename(lyr.source().split(".")[0]): lyr for lyr in layers} crs = self.parameterAsCrs(parameters, self.CRS, context) if not layers and not crs.isValid(): raise QgsProcessingException(self.tr("No reference layer selected nor CRS provided")) if not crs.isValid() and layers: crs = list(layersDict.values())[0].crs() bbox = self.parameterAsExtent(parameters, self.EXTENT, context) if not layers and bbox.isNull(): raise QgsProcessingException(self.tr("No reference layer selected nor extent box provided")) if not bbox.isNull(): bboxCrs = self.parameterAsExtentCrs(parameters, self.EXTENT, context) if bboxCrs != crs: transform = QgsCoordinateTransform(bboxCrs, crs, context.project()) bbox = transform.transformBoundingBox(bbox) if bbox.isNull() and layers: bbox = QgsProcessingUtils.combineLayerExtents(layers, crs) cellsize = self.parameterAsDouble(parameters, self.CELLSIZE, context) if not layers and cellsize == 0: raise QgsProcessingException(self.tr("No reference layer selected nor cellsize value provided")) def _cellsize(layer): ext = layer.extent() if layer.crs() != crs: transform = QgsCoordinateTransform(layer.crs(), crs, context.project()) ext = transform.transformBoundingBox(ext) return (ext.xMaximum() - ext.xMinimum()) / layer.width() if cellsize == 0: cellsize = min([_cellsize(lyr) for lyr in layersDict.values()]) for lyr in QgsProcessingUtils.compatibleRasterLayers(context.project()): name = lyr.name() if (name + "@") in expression: layersDict[name] = lyr entries = [] for name, lyr in layersDict.items(): for n in range(lyr.bandCount()): ref = '{:s}@{:d}'.format(name, n + 1) if ref in expression: entry = QgsRasterCalculatorEntry() entry.ref = ref entry.raster = lyr entry.bandNumber = n + 1 entries.append(entry) output = self.parameterAsOutputLayer(parameters, self.OUTPUT, context) width = math.floor((bbox.xMaximum() - bbox.xMinimum()) / cellsize) height = math.floor((bbox.yMaximum() - bbox.yMinimum()) / cellsize) driverName = GdalUtils.getFormatShortNameFromFilename(output) calc = QgsRasterCalculator(expression, output, driverName, bbox, crs, width, height, entries) res = calc.processCalculation(feedback) if res == QgsRasterCalculator.ParserError: raise QgsProcessingException(self.tr("Error parsing formula")) return {self.OUTPUT: output}
def showLayerSelectionDialog(self): layers = [] if isinstance(self.parameterDefinition, QgsProcessingParameterRasterLayer): layers = QgsProcessingUtils.compatibleRasterLayers( QgsProject.instance()) elif isinstance( self.parameterDefinition, QgsProcessingParameterMultipleLayers ) and self.parameterDefinition.layerType() == QgsProcessing.TypeRaster: layers = QgsProcessingUtils.compatibleRasterLayers( QgsProject.instance()) elif isinstance(self.parameterDefinition, QgsProcessingParameterVectorLayer): layers = QgsProcessingUtils.compatibleVectorLayers( QgsProject.instance()) elif isinstance(self.parameterDefinition, QgsProcessingParameterMapLayer): layers = QgsProcessingUtils.compatibleLayers(QgsProject.instance()) elif isinstance(self.parameterDefinition, QgsProcessingParameterMeshLayer): layers = QgsProcessingUtils.compatibleMeshLayers( QgsProject.instance()) elif isinstance( self.parameterDefinition, QgsProcessingParameterMultipleLayers ) and self.parameterDefinition.layerType() == QgsProcessing.TypeMesh: layers = QgsProcessingUtils.compatibleMeshLayers( QgsProject.instance()) else: datatypes = [QgsProcessing.TypeVectorAnyGeometry] if isinstance(self.parameterDefinition, QgsProcessingParameterFeatureSource): datatypes = self.parameterDefinition.dataTypes() elif isinstance(self.parameterDefinition, QgsProcessingParameterMultipleLayers): datatypes = [self.parameterDefinition.layerType()] if QgsProcessing.TypeVectorAnyGeometry not in datatypes: layers = QgsProcessingUtils.compatibleVectorLayers( QgsProject.instance(), datatypes) else: layers = QgsProcessingUtils.compatibleVectorLayers( QgsProject.instance()) dlg = MultipleInputDialog([layer.name() for layer in layers]) dlg.exec_() def generate_layer_id(layer): # prefer layer name if unique if len([ l for l in layers if l.name().lower() == layer.name().lower() ]) == 1: return layer.name() else: # otherwise fall back to layer id return layer.id() if not dlg.selectedoptions: return selected = dlg.selectedoptions context = dataobjects.createContext() first_row = self.panel.batchRowCount( ) if self.panel.batchRowCount() > 1 else 0 for row, selected_idx in enumerate(selected): layer = layers[selected_idx] value = generate_layer_id(layer) self.setRowValue(first_row + row, value, context)