Skip to content

Commit 4d242c5

Browse files
committed
Partial port of raster calculator to new API
TODO: modeler handling
1 parent 338ee36 commit 4d242c5

File tree

3 files changed

+86
-76
lines changed

3 files changed

+86
-76
lines changed

python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@
124124
from .RandomSelection import RandomSelection
125125
from .RandomSelectionWithinSubsets import RandomSelectionWithinSubsets
126126
from .Rasterize import RasterizeAlgorithm
127+
from .RasterCalculator import RasterCalculator
127128
from .RasterLayerStatistics import RasterLayerStatistics
128129
from .RectanglesOvalsDiamondsFixed import RectanglesOvalsDiamondsFixed
129130
from .RectanglesOvalsDiamondsVariable import RectanglesOvalsDiamondsVariable
@@ -172,7 +173,6 @@
172173
# from .SpatialJoin import SpatialJoin
173174
# from .GeometryConvert import GeometryConvert
174175
# from .SelectByAttributeSum import SelectByAttributeSum
175-
# from .RasterCalculator import RasterCalculator
176176

177177
pluginPath = os.path.normpath(os.path.join(
178178
os.path.split(os.path.dirname(__file__))[0], os.pardir))
@@ -192,8 +192,6 @@ def getAlgs(self):
192192
# SpatialJoin(),
193193
# GeometryConvert(),
194194
# SelectByAttributeSum()
195-
# RasterCalculator(),
196-
#
197195
# ]
198196
algs = [AddTableField(),
199197
Aggregate(),
@@ -278,6 +276,7 @@ def getAlgs(self):
278276
RandomPointsPolygons(),
279277
RandomSelection(),
280278
RandomSelectionWithinSubsets(),
279+
RasterCalculator(),
281280
RasterizeAlgorithm(),
282281
RasterLayerStatistics(),
283282
RectanglesOvalsDiamondsFixed(),

python/plugins/processing/algs/qgis/RasterCalculator.py

+55-44
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
* *
1717
***************************************************************************
1818
"""
19-
from processing.modeler.ModelerAlgorithm import ValueFromInput, ValueFromOutput
19+
2020
import os
2121

2222
__author__ = 'Victor Olaya'
@@ -29,17 +29,18 @@
2929

3030
import math
3131
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
32-
from processing.core.parameters import ParameterMultipleInput, ParameterExtent, ParameterString, ParameterRaster, ParameterNumber
33-
from processing.core.outputs import OutputRaster
34-
from processing.tools import dataobjects
3532
from processing.algs.gdal.GdalUtils import GdalUtils
36-
from qgis.core import (QgsApplication,
37-
QgsRectangle,
33+
from qgis.core import (QgsProcessing,
34+
QgsProcessingException,
3835
QgsProcessingUtils,
39-
QgsProject)
36+
QgsProcessingParameterMultipleLayers,
37+
QgsProcessingParameterNumber,
38+
QgsProcessingParameterExtent,
39+
QgsProcessingParameterRasterDestination,
40+
QgsProcessingParameterRasterLayer,
41+
QgsProcessingOutputRasterLayer,
42+
QgsProcessingParameterString)
4043
from qgis.analysis import QgsRasterCalculator, QgsRasterCalculatorEntry
41-
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
42-
from processing.algs.qgis.ui.RasterCalculatorWidgets import LayersListWidgetWrapper, ExpressionWidgetWrapper
4344

4445

4546
class RasterCalculator(QgisAlgorithm):
@@ -57,41 +58,54 @@ def __init__(self):
5758
super().__init__()
5859

5960
def initAlgorithm(self, config=None):
60-
self.addParameter(ParameterMultipleInput(self.LAYERS,
61-
self.tr('Input layers'),
62-
datatype=dataobjects.TYPE_RASTER,
63-
optional=True,
64-
metadata={'widget_wrapper': LayersListWidgetWrapper}))
61+
layer_param = QgsProcessingParameterMultipleLayers(self.LAYERS,
62+
self.tr('Input layers'),
63+
layerType=QgsProcessing.TypeRaster,
64+
optional=True)
65+
layer_param.setMetadata({'widget_wrapper': 'processing.algs.qgis.ui.RasterCalculatorWidgets.LayersListWidgetWrapper'})
66+
self.addParameter(layer_param)
67+
68+
class ParameterRasterCalculatorExpression(QgsProcessingParameterString):
69+
70+
def __init__(self, name='', description='', multiLine=False):
71+
super().__init__(name, description, multiLine=multiLine)
72+
self.setMetadata({
73+
'widget_wrapper': 'processing.algs.qgis.ui.RasterCalculatorWidgets.ExpressionWidgetWrapper'
74+
})
6575

66-
class ParameterRasterCalculatorExpression(ParameterString):
76+
def type(self):
77+
return 'raster_calc_expression'
78+
79+
def clone(self):
80+
return ParameterRasterCalculatorExpression(self.name(), self.description(), self.multiLine())
6781

6882
def evaluateForModeler(self, value, model):
6983
for i in list(model.inputs.values()):
7084
param = i.param
71-
if isinstance(param, ParameterRaster):
85+
if isinstance(param, QgsProcessingParameterRasterLayer):
7286
new = "{}@".format(os.path.basename(param.value))
7387
old = "{}@".format(param.name())
7488
value = value.replace(old, new)
7589

7690
for alg in list(model.algs.values()):
7791
for out in alg.algorithm.outputs:
78-
if isinstance(out, OutputRaster):
92+
if isinstance(out, QgsProcessingOutputRasterLayer):
7993
if out.value:
8094
new = "{}@".format(os.path.basename(out.value))
8195
old = "{}:{}@".format(alg.modeler_name, out.name)
8296
value = value.replace(old, new)
8397
return value
8498

8599
self.addParameter(ParameterRasterCalculatorExpression(self.EXPRESSION, self.tr('Expression'),
86-
multiline=True,
87-
metadata={'widget_wrapper': ExpressionWidgetWrapper}))
88-
self.addParameter(ParameterNumber(self.CELLSIZE,
89-
self.tr('Cell size (use 0 or empty to set it automatically)'),
90-
minValue=0.0, default=0.0, optional=True))
91-
self.addParameter(ParameterExtent(self.EXTENT,
92-
self.tr('Output extent'),
93-
optional=True))
94-
self.addOutput(OutputRaster(self.OUTPUT, self.tr('Output')))
100+
multiLine=True))
101+
self.addParameter(QgsProcessingParameterNumber(self.CELLSIZE,
102+
self.tr('Cell size (use 0 or empty to set it automatically)'),
103+
type=QgsProcessingParameterNumber.Double,
104+
minValue=0.0, defaultValue=0.0, optional=True))
105+
self.addParameter(QgsProcessingParameterExtent(self.EXTENT,
106+
self.tr('Output extent'),
107+
optional=True))
108+
self.addParameter(QgsProcessingParameterRasterDestination(self.OUTPUT, self.tr('Output')))
95109

96110
def name(self):
97111
return 'rastercalculator'
@@ -100,11 +114,10 @@ def displayName(self):
100114
return self.tr('Raster calculator')
101115

102116
def processAlgorithm(self, parameters, context, feedback):
103-
expression = self.getParameterValue(self.EXPRESSION)
104-
layersValue = self.getParameterValue(self.LAYERS)
117+
expression = self.parameterAsString(parameters, self.EXPRESSION, context)
118+
layers = self.parameterAsLayerList(parameters, self.LAYERS, context)
105119
layersDict = {}
106-
if layersValue:
107-
layers = [QgsProcessingUtils.mapLayerFromString(f, context) for f in layersValue.split(";")]
120+
if layers:
108121
layersDict = {os.path.basename(lyr.source().split(".")[0]): lyr for lyr in layers}
109122

110123
for lyr in QgsProcessingUtils.compatibleRasterLayers(context.project()):
@@ -121,26 +134,22 @@ def processAlgorithm(self, parameters, context, feedback):
121134
entry.bandNumber = n + 1
122135
entries.append(entry)
123136

124-
output = self.getOutputValue(self.OUTPUT)
125-
extentValue = self.getParameterValue(self.EXTENT)
126-
if not extentValue:
127-
extentValue = QgsProcessingUtils.combineLayerExtents(layersValue)
137+
output = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
138+
bbox = self.parameterAsExtent(parameters, self.EXTENT, context)
139+
if bbox.isNull():
140+
bbox = QgsProcessingUtils.combineLayerExtents(layers)
128141

129-
if extentValue:
130-
extent = extentValue.split(',')
131-
bbox = QgsRectangle(float(extent[0]), float(extent[2]),
132-
float(extent[1]), float(extent[3]))
133-
else:
142+
if bbox.isNull():
134143
if layersDict:
135144
bbox = list(layersDict.values())[0].extent()
136145
for lyr in layersDict.values():
137146
bbox.combineExtentWith(lyr.extent())
138147
else:
139-
raise GeoAlgorithmExecutionException(self.tr("No layers selected"))
148+
raise QgsProcessingException(self.tr("No layers selected"))
140149

141150
def _cellsize(layer):
142151
return (layer.extent().xMaximum() - layer.extent().xMinimum()) / layer.width()
143-
cellsize = self.getParameterValue(self.CELLSIZE) or min([_cellsize(lyr) for lyr in layersDict.values()])
152+
cellsize = self.parameterAsDouble(parameters, self.CELLSIZE, context) or min([_cellsize(lyr) for lyr in layersDict.values()])
144153
width = math.floor((bbox.xMaximum() - bbox.xMinimum()) / cellsize)
145154
height = math.floor((bbox.yMaximum() - bbox.yMinimum()) / cellsize)
146155
driverName = GdalUtils.getFormatShortNameFromFilename(output)
@@ -154,14 +163,16 @@ def _cellsize(layer):
154163

155164
res = calc.processCalculation()
156165
if res == QgsRasterCalculator.ParserError:
157-
raise GeoAlgorithmExecutionException(self.tr("Error parsing formula"))
166+
raise QgsProcessingException(self.tr("Error parsing formula"))
167+
168+
return {self.OUTPUT: output}
158169

159170
def processBeforeAddingToModeler(self, algorithm, model):
160171
values = []
161172
expression = algorithm.params[self.EXPRESSION]
162173
for i in list(model.inputs.values()):
163174
param = i.param
164-
if isinstance(param, ParameterRaster) and "{}@".format(param.name) in expression:
175+
if isinstance(param, QgsProcessingParameterRasterLayer) and "{}@".format(param.name) in expression:
165176
values.append(ValueFromInput(param.name()))
166177

167178
if algorithm.name:
@@ -171,7 +182,7 @@ def processBeforeAddingToModeler(self, algorithm, model):
171182
for alg in list(model.algs.values()):
172183
if alg.modeler_name not in dependent:
173184
for out in alg.algorithm.outputs:
174-
if (isinstance(out, OutputRaster) and
185+
if (isinstance(out, QgsProcessingOutputRasterLayer) and
175186
"{}:{}@".format(alg.modeler_name, out.name) in expression):
176187
values.append(ValueFromOutput(alg.modeler_name, out.name))
177188

python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml

+29-29
Original file line numberDiff line numberDiff line change
@@ -2210,35 +2210,35 @@ tests:
22102210
- 'Maximum value: 15:29:22'
22112211
- 'NULL \(missing\) values: 1'
22122212

2213-
# - algorithm: qgis:rastercalculator
2214-
# name: Raster Calculator with cellsize
2215-
# params:
2216-
# LAYERS:
2217-
# params:
2218-
# - name: dem.tif
2219-
# type: raster
2220-
# type: multi
2221-
# CELLSIZE: 0.001
2222-
# EXPRESSION: dem@1
2223-
# results:
2224-
# OUTPUT:
2225-
# hash: ef97a22ee16e0e28bbdc0341449777b1527e37febc3c4339b2c057c9
2226-
# type: rasterhash
2227-
#
2228-
# - algorithm: qgis:rastercalculator
2229-
# name: Raster Calculator
2230-
# params:
2231-
# LAYERS:
2232-
# params:
2233-
# - name: dem.tif
2234-
# type: raster
2235-
# type: multi
2236-
# CELLSIZE: 0.0
2237-
# EXPRESSION: dem@1 * 2
2238-
# results:
2239-
# OUTPUT:
2240-
# hash: fe6e018be13c5a3c17f3f4d0f0dc7686c628cb440b74c4642aa0c939
2241-
# type: rasterhash
2213+
- algorithm: qgis:rastercalculator
2214+
name: Raster Calculator with cellsize
2215+
params:
2216+
LAYERS:
2217+
params:
2218+
- name: dem.tif
2219+
type: raster
2220+
type: multi
2221+
CELLSIZE: 0.001
2222+
EXPRESSION: dem@1
2223+
results:
2224+
OUTPUT:
2225+
hash: ef97a22ee16e0e28bbdc0341449777b1527e37febc3c4339b2c057c9
2226+
type: rasterhash
2227+
2228+
- algorithm: qgis:rastercalculator
2229+
name: Raster Calculator
2230+
params:
2231+
LAYERS:
2232+
params:
2233+
- name: dem.tif
2234+
type: raster
2235+
type: multi
2236+
CELLSIZE: 0.0
2237+
EXPRESSION: dem@1 * 2
2238+
results:
2239+
OUTPUT:
2240+
hash: fe6e018be13c5a3c17f3f4d0f0dc7686c628cb440b74c4642aa0c939
2241+
type: rasterhash
22422242

22432243
- algorithm: qgis:orientedminimumboundingbox
22442244
name: Oriented minimum bounding box polys

0 commit comments

Comments
 (0)