Skip to content
Permalink
Browse files
[processing] simplified saga algorithms
Now it assumes matching grid extents and does not perform resampling
  • Loading branch information
volaya committed May 21, 2014
1 parent c1a2ac8 commit 202d331abbf7b3af56e168ab587367655519fb07
@@ -63,34 +63,18 @@ class SagaAlgorithm(GeoAlgorithm):
OUTPUT_EXTENT = 'OUTPUT_EXTENT'

def __init__(self, descriptionfile):
# True if it should resample
self.resample = True
self.allowUnmatchingGridExtents = False

# In case several non-matching raster layers are used as input
GeoAlgorithm.__init__(self)
self.descriptionFile = descriptionfile
self.defineCharacteristicsFromFile()
if self.resample:
# Reconsider resampling policy now that we know the input
# parameters
self.resample = self.setResamplingPolicy()

def getCopy(self):
newone = SagaAlgorithm(self.descriptionFile)
newone.provider = self.provider
return newone

def setResamplingPolicy(self):
count = 0
for param in self.parameters:
if isinstance(param, ParameterRaster):
count += 1
if isinstance(param, ParameterMultipleInput):
if param.datatype == ParameterMultipleInput.TYPE_RASTER:
return True

return count > 1

def getIcon(self):
return QIcon(os.path.dirname(__file__) + '/../../images/saga.png')

@@ -116,8 +100,8 @@ def defineCharacteristicsFromFile(self):
self.hardcodedStrings.append(line[len('Harcoded|') + 1:])
elif line.startswith('Parameter'):
self.addParameter(ParameterFactory.getFromString(line))
elif line.startswith('DontResample'):
self.resample = False
elif line.startswith('AllowUnmatching'):
self.allowUnmatchingGridExtents = True
elif line.startswith('Extent'):
# An extent parameter that wraps 4 SAGA numerical parameters
self.extentParamNames = line[6:].strip().split(' ')
@@ -128,71 +112,6 @@ def defineCharacteristicsFromFile(self):
line = lines.readline().strip('\n').strip()
lines.close()

def calculateResamplingExtent(self):
"""This method calculates the resampling extent, but it might
set self.resample to False if, with the current layers, there
is no need to resample.
"""

auto = ProcessingConfig.getSetting(SagaUtils.SAGA_AUTO_RESAMPLING)
if auto:
first = True
self.inputExtentsCount = 0
for param in self.parameters:
if param.value:
if isinstance(param, ParameterRaster):
if isinstance(param.value, QgsRasterLayer):
layer = param.value
else:
layer = dataobjects.getObjectFromUri(param.value)
self.addToResamplingExtent(layer, first)
first = False
if isinstance(param, ParameterMultipleInput):
if param.datatype \
== ParameterMultipleInput.TYPE_RASTER:
layers = param.value.split(';')
for layername in layers:
layer = dataobjects.getObjectFromUri(layername)
self.addToResamplingExtent(layer, first)
first = False
if self.inputExtentsCount < 2:
self.resample = False
else:
self.xmin = ProcessingConfig.getSetting(
SagaUtils.SAGA_RESAMPLING_REGION_XMIN)
self.xmax = ProcessingConfig.getSetting(
SagaUtils.SAGA_RESAMPLING_REGION_XMAX)
self.ymin = ProcessingConfig.getSetting(
SagaUtils.SAGA_RESAMPLING_REGION_YMIN)
self.ymax = ProcessingConfig.getSetting(
SagaUtils.SAGA_RESAMPLING_REGION_YMAX)
self.cellsize = ProcessingConfig.getSetting(
SagaUtils.SAGA_RESAMPLING_REGION_CELLSIZE)

def addToResamplingExtent(self, layer, first):
if layer is None:
return
if first:
self.inputExtentsCount = 1
self.xmin = layer.extent().xMinimum()
self.xmax = layer.extent().xMaximum()
self.ymin = layer.extent().yMinimum()
self.ymax = layer.extent().yMaximum()
self.cellsize = (layer.extent().xMaximum()
- layer.extent().xMinimum()) / layer.width()
else:
cellsize = (layer.extent().xMaximum() -
layer.extent().xMinimum()) / layer.width()
if self.xmin != layer.extent().xMinimum() or self.xmax \
!= layer.extent().xMaximum() or self.ymin \
!= layer.extent().yMinimum() or self.ymax \
!= layer.extent().yMaximum() or self.cellsize != cellsize:
self.xmin = min(self.xmin, layer.extent().xMinimum())
self.xmax = max(self.xmax, layer.extent().xMaximum())
self.ymin = min(self.ymin, layer.extent().yMinimum())
self.ymax = max(self.ymax, layer.extent().yMaximum())
self.cellsize = min(self.cellsize, cellsize)
self.inputExtentsCount += 1

def processAlgorithm(self, progress):
if isWindows():
@@ -208,8 +127,6 @@ def processAlgorithm(self, progress):

# 1: Export rasters to sgrd and vectors to shp
# Tables must be in dbf format. We check that.
if self.resample:
self.calculateResamplingExtent()
for param in self.parameters:
if isinstance(param, ParameterRaster):
if param.value is None:
@@ -219,8 +136,6 @@ def processAlgorithm(self, progress):
exportCommand = self.exportRasterLayer(value)
if exportCommand is not None:
commands.append(exportCommand)
if self.resample:
commands.append(self.resampleRasterLayer(value))
if isinstance(param, ParameterVector):
if param.value is None:
continue
@@ -253,9 +168,6 @@ def processAlgorithm(self, progress):
exportCommand = self.exportRasterLayer(layerfile)
if exportCommand is not None:
commands.append(exportCommand)
if self.resample:
commands.append(
self.resampleRasterLayer(layerfile))
elif param.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY:
for layerfile in layers:
layer = dataobjects.getObjectFromUri(layerfile, False)
@@ -421,34 +333,7 @@ def getOutputCellsize(self):
cellsize = float(param.value)
break
return cellsize

def resampleRasterLayer(self, layer):
"""This is supposed to be run after having exported all raster
layers.
"""

if layer in self.exportedLayers.keys():
inputFilename = self.exportedLayers[layer]
else:
inputFilename = layer
destFilename = getTempFilename('sgrd')
self.exportedLayers[layer] = destFilename
saga208 = ProcessingConfig.getSetting(SagaUtils.SAGA_208)
if isWindows() or isMac() or not saga208:
s = 'grid_tools "Resampling" -INPUT "' + inputFilename \
+ '" -TARGET 0 -SCALE_UP_METHOD 0 -SCALE_DOWN_METHOD 0 -USER_XMIN ' \
+ str(self.xmin) + ' -USER_XMAX ' + str(self.xmax) \
+ ' -USER_YMIN ' + str(self.ymin) + ' -USER_YMAX ' \
+ str(self.ymax) + ' -USER_SIZE ' + str(self.cellsize) \
+ ' -USER_GRID "' + destFilename + '"'
else:
s = 'libgrid_tools "Resampling" -INPUT "' + inputFilename \
+ '" -TARGET 0 -SCALE_UP_METHOD 0 -SCALE_DOWN_METHOD 0 -USER_XMIN ' \
+ str(self.xmin) + ' -USER_XMAX ' + str(self.xmax) \
+ ' -USER_YMIN ' + str(self.ymin) + ' -USER_YMAX ' \
+ str(self.ymax) + ' -USER_SIZE ' + str(self.cellsize) \
+ ' -USER_GRID "' + destFilename + '"'
return s


def exportRasterLayer(self, source):
if source in sessionExportedLayers:
@@ -485,22 +370,33 @@ def checkBeforeOpeningParametersDialog(self):
html = '<p>This algorithm requires SAGA to be run.Unfortunately, \
it seems that SAGA is not installed in your system, or it \
is not correctly configured to be used from QGIS</p>'
html += '<p><a href= "http://docs.qgis.org/2.0/en/docs/user_manual/processing/3rdParty.html">Click here</a> to know more about how to install and configure SAGA to be used with QGIS</p>'
html += '<p><a href= "http://docs.qgis.org/2.0/en/docs/user_manual/processing/3rdParty.html">\
Click here</a> to know more about how to install and configure SAGA to be used with QGIS</p>'
return html

def checkParameterValuesBeforeExecuting(self):
"""We check that there are no multiband layers, which are not
supported by SAGA.
"""

We check that there are no multiband layers, which are not
supported by SAGA, and that raster layers have the same grid extent
"""
extent = None
for param in self.parameters:
if isinstance(param, ParameterRaster):
value = param.value
layer = dataobjects.getObjectFromUri(value)
if layer is not None and layer.bandCount() > 1:
if isinstance(param, ParameterRaster):
layer = dataobjects.getObjectFromUri(param.value)
if layer is None:
continue
if layer.bandCount() > 1:
return 'Input layer ' + str(layer.name()) \
+ ' has more than one band.\n' \
+ 'Multiband layers are not supported by SAGA'
if extent is None:
extent = (layer.extent(), layer.height(), layer.width())
else:
extent2 = (layer.extent(), layer.height(), layer.width())
if extent != extent2:
return "Input layers do not have the same grid extent."



def help(self):
name = self.cmdname.lower()
@@ -51,48 +51,23 @@ def initializeSettings(self):
SagaUtils.sagaPath()))
ProcessingConfig.addSetting(Setting(self.getDescription(),
SagaUtils.SAGA_208,
'Enable SAGA 2.0.8 compatibility', True))
'Use SAGA 2.0.8 syntax', True))
ProcessingConfig.addSetting(Setting(self.getDescription(),
SagaUtils.SAGA_IMPORT_EXPORT_OPTIMIZATION,
'Enable SAGA Import/Export optimizations',
False))
ProcessingConfig.addSetting(Setting(self.getDescription(),
SagaUtils.SAGA_AUTO_RESAMPLING,
'Use min covering grid system for resampling', True))
ProcessingConfig.addSetting(Setting(self.getDescription(),
SagaUtils.SAGA_LOG_COMMANDS,
'Log execution commands', True))
ProcessingConfig.addSetting(Setting(self.getDescription(),
SagaUtils.SAGA_LOG_CONSOLE,
'Log console output', True))
ProcessingConfig.addSetting(Setting(self.getDescription(),
SagaUtils.SAGA_RESAMPLING_REGION_XMIN,
'Resampling region min x', 0))
ProcessingConfig.addSetting(Setting(self.getDescription(),
SagaUtils.SAGA_RESAMPLING_REGION_YMIN,
'Resampling region min y', 0))
ProcessingConfig.addSetting(Setting(self.getDescription(),
SagaUtils.SAGA_RESAMPLING_REGION_XMAX,
'Resampling region max x', 1000))
ProcessingConfig.addSetting(Setting(self.getDescription(),
SagaUtils.SAGA_RESAMPLING_REGION_YMAX,
'Resampling region max y', 1000))
ProcessingConfig.addSetting(Setting(self.getDescription(),
SagaUtils.SAGA_RESAMPLING_REGION_CELLSIZE,
'Resampling region cellsize', 1))

def unload(self):
AlgorithmProvider.unload(self)
if isWindows():
ProcessingConfig.removeSetting(SagaUtils.SAGA_FOLDER)

ProcessingConfig.removeSetting(SagaUtils.SAGA_AUTO_RESAMPLING)
ProcessingConfig.removeSetting(SagaUtils.SAGA_RESAMPLING_REGION_XMIN)
ProcessingConfig.removeSetting(SagaUtils.SAGA_RESAMPLING_REGION_YMIN)
ProcessingConfig.removeSetting(SagaUtils.SAGA_RESAMPLING_REGION_XMAX)
ProcessingConfig.removeSetting(SagaUtils.SAGA_RESAMPLING_REGION_YMAX)
ProcessingConfig.removeSetting(
SagaUtils.SAGA_RESAMPLING_REGION_CELLSIZE)

ProcessingConfig.removeSetting(SagaUtils.SAGA_LOG_CONSOLE)
ProcessingConfig.removeSetting(SagaUtils.SAGA_LOG_COMMANDS)

@@ -42,12 +42,6 @@ class SagaUtils:
SAGA_208 = 'SAGA_208'
SAGA_LOG_COMMANDS = 'SAGA_LOG_COMMANDS'
SAGA_LOG_CONSOLE = 'SAGA_LOG_CONSOLE'
SAGA_AUTO_RESAMPLING = 'SAGA_AUTO_RESAMPLING'
SAGA_RESAMPLING_REGION_XMIN = 'SAGA_RESAMPLING_REGION_XMIN'
SAGA_RESAMPLING_REGION_YMIN = 'SAGA_RESAMPLING_REGION_YMIN'
SAGA_RESAMPLING_REGION_XMAX = 'SAGA_RESAMPLING_REGION_XMAX'
SAGA_RESAMPLING_REGION_YMAX = 'SAGA_RESAMPLING_REGION_YMAX'
SAGA_RESAMPLING_REGION_CELLSIZE = 'SAGA_RESAMPLING_REGION_CELLSIZE'
SAGA_FOLDER = 'SAGA_FOLDER'
SAGA_IMPORT_EXPORT_OPTIMIZATION = 'SAGA_IMPORT_EXPORT_OPTIMIZATION'

@@ -1,5 +1,6 @@
Raster calculator|Grid Calculator
grid_calculus
AllowUnmatching
ParameterMultipleInput|GRIDS|Raster layers|3|False
ParameterString|FORMULA|Formula|
OutputRaster|RESULT|Result
@@ -1,6 +1,6 @@
Merge raster layers|Merging
grid_tools
DontResample
AllowUnmatching
ParameterMultipleInput|GRIDS|Grids to Merge|3|False
ParameterSelection|TYPE|Preferred data storage type|[0] 1 bit;[1] 1 byte unsigned integer;[2] 1 byte signed integer;[3] 2 byte unsigned integer;[4] 2 byte signed integer;[5] 4 byte unsigned integer;[6] 4 byte signed integer;[7] 4 byte floating point;[8] 8 byte floating point
ParameterSelection|INTERPOL|Interpolation|[0] Nearest Neighbor;[1] Bilinear Interpolation;[2] Inverse Distance Interpolation;[3] Bicubic Spline Interpolation;[4] B-Spline Interpolation

0 comments on commit 202d331

Please sign in to comment.