You could use something like the following:
import processing
lddLrs = qgis.utils.iface.legendInterface().layers()
path = "path/to/results//"
for lyr in lddLrs:
processing.runalg("saga:rastercalculator", lyr, None, "(a/a)*a", True, 7, path + lyr.name() + "_suffix.tif")
EDIT :
If you want to use the QgsRasterCalculator, you could try using the following (based on this post):
from qgis.analysis import QgsRasterCalculatorEntry, QgsRasterCalculator
lddLrs = qgis.utils.iface.legendInterface().layers()
path = "path/to/results"
for lyr in lddLrs:
entries = []
ras = QgsRasterCalculatorEntry()
ras.ref = 'ras@1'
ras.raster = lyr
ras.bandNumber = 1
entries.append( ras )
calc = QgsRasterCalculator( '(ras@1 / ras@1) * ras@1', path + lyr.name() + "_suffix.tif", 'GTiff', lyr.extent(), lyr.width(), lyr.height(), entries )
calc.processCalculation()
UPDATE:
You can use the following code in a script which allows you to select individual rasters and run the calculator on them. I've changed the output to a folder so that multiple (or single) rasters can be output to the same directory but you can change this:
##NoDATA Background=name
##Raster=multiple raster
##OUT=folder
import glob, qgis
from PyQt4.QtCore import QFileInfo
from qgis.analysis import QgsRasterCalculatorEntry, QgsRasterCalculator
from qgis.core import QgsMapLayerRegistry, QgsRasterLayer
# Split rasters
layers = Raster.split(';')
output_path = OUT + "/"
suffix = "_suffix.tif"
for ras in layers:
# Get layer object
lyr = processing.getObjectFromUri(ras)
entries = []
ras = QgsRasterCalculatorEntry()
ras.ref = 'lyr@1'
ras.raster = lyr
ras.bandNumber = 1
entries.append( ras )
calc = QgsRasterCalculator( '(lyr@1 / lyr@1) * lyr@1', output_path + lyr.name() + suffix, 'GTiff', lyr.extent(), lyr.width(), lyr.height(), entries )
calc.processCalculation()
for results in glob.glob(output_path + "*" + suffix):
fileInfo = QFileInfo(results)
path = fileInfo.filePath()
baseName = fileInfo.baseName()
layer = QgsRasterLayer(path, baseName)
QgsMapLayerRegistry.instance().addMapLayer(layer)
In addition to not setting is_child_algorithm=True
, you are not retrieving your buffer distance parameter correctly. I have also added a few other improvements and simplifications- you do not need to manually add output features to feature sink, you can just use a QgsProcessingParameterVectorDestination
and set it as the 'OUTPUT'
for your final algorithm. You can also use QgsProcessingMultiStepFeedback
so you get a nicely updating progress bar for the overall algorithm.
Try this modified script:
from PyQt5.QtCore import QCoreApplication, QVariant
from qgis.core import (QgsProcessing,
QgsProcessingException,
QgsProcessingAlgorithm,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterVectorDestination,
QgsProcessingParameterNumber,
QgsProcessingParameterRasterLayer,
QgsProcessingMultiStepFeedback)
import processing
class ExampleProcessingAlgorithm(QgsProcessingAlgorithm):
CENTROIDS = 'CENTROIDS'
INPUT_RASTER_LAND_COVER = 'INPUT_RASTER_LAND_COVER'
VEG_BUFFER_DIST = 'VEG_BUFFER_DIST'
VUN_OUTPUT = 'VUN_OUTPUT'
def tr(self, string):
return QCoreApplication.translate('Processing', string)
def createInstance(self):
return ExampleProcessingAlgorithm()
def name(self):
return 'myscript'
def displayName(self):
return self.tr('My Script')
def group(self):
return self.tr('Example scripts')
def groupId(self):
return 'examplescripts'
def shortHelpString(self):
return self.tr("Example algorithm short description")
def initAlgorithm(self, config=None):
self.addParameter(
QgsProcessingParameterRasterLayer(
self.INPUT_RASTER_LAND_COVER,
self.tr("Input a raster with land cover as distinct bands"),
[QgsProcessing.TypeRaster]
)
)
self.addParameter(
QgsProcessingParameterFeatureSource(
self.CENTROIDS,
self.tr('Building centroids'),
[QgsProcessing.TypeVectorPoint]
)
)
self.addParameter(
QgsProcessingParameterNumber(
self.VEG_BUFFER_DIST,
self.tr('Buffer distance around each property to assess vegetation cover (meters)')
)
)
self.addParameter(
QgsProcessingParameterVectorDestination(
self.VUN_OUTPUT,
self.tr('Vulnerability Output')
)
)
def processAlgorithm(self, parameters, context, model_feedback):
#each source layer is named, it is a two step process
landcover = self.parameterAsRasterLayer(
parameters,
self.INPUT_RASTER_LAND_COVER,
context
)
#if the input is invalid an error is raised
if landcover is None:
raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT_RASTER_LAND_COVER))
#same as above, but with a vector not raster
centroids = self.parameterAsVectorLayer(
parameters,
self.CENTROIDS,
context
)
if centroids is None:
raise QgsProcessingException(self.invalidSourceError(parameters, self.BUILDING_CENTROIDS))
buffer_distance = self.parameterAsInt(parameters,
self.VEG_BUFFER_DIST,
context)
steps = 5
feedback = QgsProcessingMultiStepFeedback(steps, model_feedback)
step = 1
results = {}
outputs = {}
feedback.setCurrentStep(step)
step+=1
outputs['buffer_result'] = processing.run("native:buffer", {
'INPUT': centroids,
'DISTANCE': buffer_distance,
'SEGMENTS': 5,
'END_CAP_STYLE': 0,
'JOIN_STYLE': 0,
'MITER_LIMIT': 2,
'DISSOLVE': False,
'OUTPUT': 'TEMPORARY_OUTPUT'
}, context=context, feedback=feedback, is_child_algorithm=True)
results['buffer_result'] = outputs['buffer_result']['OUTPUT']
feedback.setCurrentStep(step)
step+=1
outputs['zonal_statistics_result'] = processing.run("native:zonalstatisticsfb", {
'INPUT': results['buffer_result'],
'INPUT_RASTER': landcover,
'RASTER_BAND':1,
'COLUMN_PREFIX':'_',
'STATISTICS':[0,1,2],
'OUTPUT':'TEMPORARY_OUTPUT'
},
context=context, feedback=feedback, is_child_algorithm=True)
results['zonal_statistics_result'] = outputs['zonal_statistics_result']['OUTPUT']
feedback.setCurrentStep(step)
step+=1
outputs['join_1'] = processing.run("native:joinattributestable", {
'INPUT':results['buffer_result'],
'FIELD':'OBJECTID',
'INPUT_2': results['zonal_statistics_result'],
'FIELD_2':'OBJECTID',
'FIELDS_TO_COPY':[],
'METHOD':1,
'DISCARD_NONMATCHING':False,
'PREFIX':'',
'OUTPUT':'TEMPORARY_OUTPUT'
}, context=context, feedback=feedback, is_child_algorithm=True)
results['join_1'] = outputs['join_1']['OUTPUT']
feedback.setCurrentStep(step)
step+=1
#drop geometry of the multipolygons, so fields can be attached to point layer
outputs['dropped_geoms'] = processing.run("native:dropgeometries", {
'INPUT': results['join_1'],
'OUTPUT':'TEMPORARY_OUTPUT'
},
context=context, feedback=feedback, is_child_algorithm=True)
results['dropped_geoms'] = outputs['dropped_geoms']['OUTPUT']
feedback.setCurrentStep(step)
step+=1
#attach fields without geometry to point layer
outputs['join_2'] = processing.run("native:joinattributestable", {
'INPUT':centroids,
'FIELD':'OBJECTID',
'INPUT_2': results['dropped_geoms'],
'FIELD_2':'OBJECTID',
'FIELDS_TO_COPY':['_count'],
'METHOD':1,
'DISCARD_NONMATCHING':False,
'PREFIX':'',
'OUTPUT':parameters[self.VUN_OUTPUT]
}, context=context, feedback=feedback, is_child_algorithm=True)
results['join_2'] = outputs['join_2']['OUTPUT']
return results
Best Answer
Just pass the QgsProcessing.SourceType to the
QgsProcessingParameterMultipleLayers
class constructor: