mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-08 00:06:51 -05:00
[processing] simplified saga algorithms
Now it assumes matching grid extents and does not perform resampling
This commit is contained in:
parent
c1a2ac8678
commit
202d331abb
@ -63,34 +63,18 @@ class SagaAlgorithm(GeoAlgorithm):
|
|||||||
OUTPUT_EXTENT = 'OUTPUT_EXTENT'
|
OUTPUT_EXTENT = 'OUTPUT_EXTENT'
|
||||||
|
|
||||||
def __init__(self, descriptionfile):
|
def __init__(self, descriptionfile):
|
||||||
# True if it should resample
|
self.allowUnmatchingGridExtents = False
|
||||||
self.resample = True
|
|
||||||
|
|
||||||
# In case several non-matching raster layers are used as input
|
# In case several non-matching raster layers are used as input
|
||||||
GeoAlgorithm.__init__(self)
|
GeoAlgorithm.__init__(self)
|
||||||
self.descriptionFile = descriptionfile
|
self.descriptionFile = descriptionfile
|
||||||
self.defineCharacteristicsFromFile()
|
self.defineCharacteristicsFromFile()
|
||||||
if self.resample:
|
|
||||||
# Reconsider resampling policy now that we know the input
|
|
||||||
# parameters
|
|
||||||
self.resample = self.setResamplingPolicy()
|
|
||||||
|
|
||||||
def getCopy(self):
|
def getCopy(self):
|
||||||
newone = SagaAlgorithm(self.descriptionFile)
|
newone = SagaAlgorithm(self.descriptionFile)
|
||||||
newone.provider = self.provider
|
newone.provider = self.provider
|
||||||
return newone
|
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):
|
def getIcon(self):
|
||||||
return QIcon(os.path.dirname(__file__) + '/../../images/saga.png')
|
return QIcon(os.path.dirname(__file__) + '/../../images/saga.png')
|
||||||
|
|
||||||
@ -116,8 +100,8 @@ class SagaAlgorithm(GeoAlgorithm):
|
|||||||
self.hardcodedStrings.append(line[len('Harcoded|') + 1:])
|
self.hardcodedStrings.append(line[len('Harcoded|') + 1:])
|
||||||
elif line.startswith('Parameter'):
|
elif line.startswith('Parameter'):
|
||||||
self.addParameter(ParameterFactory.getFromString(line))
|
self.addParameter(ParameterFactory.getFromString(line))
|
||||||
elif line.startswith('DontResample'):
|
elif line.startswith('AllowUnmatching'):
|
||||||
self.resample = False
|
self.allowUnmatchingGridExtents = True
|
||||||
elif line.startswith('Extent'):
|
elif line.startswith('Extent'):
|
||||||
# An extent parameter that wraps 4 SAGA numerical parameters
|
# An extent parameter that wraps 4 SAGA numerical parameters
|
||||||
self.extentParamNames = line[6:].strip().split(' ')
|
self.extentParamNames = line[6:].strip().split(' ')
|
||||||
@ -128,71 +112,6 @@ class SagaAlgorithm(GeoAlgorithm):
|
|||||||
line = lines.readline().strip('\n').strip()
|
line = lines.readline().strip('\n').strip()
|
||||||
lines.close()
|
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):
|
def processAlgorithm(self, progress):
|
||||||
if isWindows():
|
if isWindows():
|
||||||
@ -208,8 +127,6 @@ class SagaAlgorithm(GeoAlgorithm):
|
|||||||
|
|
||||||
# 1: Export rasters to sgrd and vectors to shp
|
# 1: Export rasters to sgrd and vectors to shp
|
||||||
# Tables must be in dbf format. We check that.
|
# Tables must be in dbf format. We check that.
|
||||||
if self.resample:
|
|
||||||
self.calculateResamplingExtent()
|
|
||||||
for param in self.parameters:
|
for param in self.parameters:
|
||||||
if isinstance(param, ParameterRaster):
|
if isinstance(param, ParameterRaster):
|
||||||
if param.value is None:
|
if param.value is None:
|
||||||
@ -219,8 +136,6 @@ class SagaAlgorithm(GeoAlgorithm):
|
|||||||
exportCommand = self.exportRasterLayer(value)
|
exportCommand = self.exportRasterLayer(value)
|
||||||
if exportCommand is not None:
|
if exportCommand is not None:
|
||||||
commands.append(exportCommand)
|
commands.append(exportCommand)
|
||||||
if self.resample:
|
|
||||||
commands.append(self.resampleRasterLayer(value))
|
|
||||||
if isinstance(param, ParameterVector):
|
if isinstance(param, ParameterVector):
|
||||||
if param.value is None:
|
if param.value is None:
|
||||||
continue
|
continue
|
||||||
@ -253,9 +168,6 @@ class SagaAlgorithm(GeoAlgorithm):
|
|||||||
exportCommand = self.exportRasterLayer(layerfile)
|
exportCommand = self.exportRasterLayer(layerfile)
|
||||||
if exportCommand is not None:
|
if exportCommand is not None:
|
||||||
commands.append(exportCommand)
|
commands.append(exportCommand)
|
||||||
if self.resample:
|
|
||||||
commands.append(
|
|
||||||
self.resampleRasterLayer(layerfile))
|
|
||||||
elif param.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY:
|
elif param.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY:
|
||||||
for layerfile in layers:
|
for layerfile in layers:
|
||||||
layer = dataobjects.getObjectFromUri(layerfile, False)
|
layer = dataobjects.getObjectFromUri(layerfile, False)
|
||||||
@ -421,34 +333,7 @@ class SagaAlgorithm(GeoAlgorithm):
|
|||||||
cellsize = float(param.value)
|
cellsize = float(param.value)
|
||||||
break
|
break
|
||||||
return cellsize
|
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):
|
def exportRasterLayer(self, source):
|
||||||
if source in sessionExportedLayers:
|
if source in sessionExportedLayers:
|
||||||
@ -485,22 +370,33 @@ class SagaAlgorithm(GeoAlgorithm):
|
|||||||
html = '<p>This algorithm requires SAGA to be run.Unfortunately, \
|
html = '<p>This algorithm requires SAGA to be run.Unfortunately, \
|
||||||
it seems that SAGA is not installed in your system, or it \
|
it seems that SAGA is not installed in your system, or it \
|
||||||
is not correctly configured to be used from QGIS</p>'
|
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
|
return html
|
||||||
|
|
||||||
def checkParameterValuesBeforeExecuting(self):
|
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:
|
for param in self.parameters:
|
||||||
if isinstance(param, ParameterRaster):
|
if isinstance(param, ParameterRaster):
|
||||||
value = param.value
|
layer = dataobjects.getObjectFromUri(param.value)
|
||||||
layer = dataobjects.getObjectFromUri(value)
|
if layer is None:
|
||||||
if layer is not None and layer.bandCount() > 1:
|
continue
|
||||||
|
if layer.bandCount() > 1:
|
||||||
return 'Input layer ' + str(layer.name()) \
|
return 'Input layer ' + str(layer.name()) \
|
||||||
+ ' has more than one band.\n' \
|
+ ' has more than one band.\n' \
|
||||||
+ 'Multiband layers are not supported by SAGA'
|
+ '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):
|
def help(self):
|
||||||
name = self.cmdname.lower()
|
name = self.cmdname.lower()
|
||||||
|
|||||||
@ -51,48 +51,23 @@ class SagaAlgorithmProvider(AlgorithmProvider):
|
|||||||
SagaUtils.sagaPath()))
|
SagaUtils.sagaPath()))
|
||||||
ProcessingConfig.addSetting(Setting(self.getDescription(),
|
ProcessingConfig.addSetting(Setting(self.getDescription(),
|
||||||
SagaUtils.SAGA_208,
|
SagaUtils.SAGA_208,
|
||||||
'Enable SAGA 2.0.8 compatibility', True))
|
'Use SAGA 2.0.8 syntax', True))
|
||||||
ProcessingConfig.addSetting(Setting(self.getDescription(),
|
ProcessingConfig.addSetting(Setting(self.getDescription(),
|
||||||
SagaUtils.SAGA_IMPORT_EXPORT_OPTIMIZATION,
|
SagaUtils.SAGA_IMPORT_EXPORT_OPTIMIZATION,
|
||||||
'Enable SAGA Import/Export optimizations',
|
'Enable SAGA Import/Export optimizations',
|
||||||
False))
|
False))
|
||||||
ProcessingConfig.addSetting(Setting(self.getDescription(),
|
|
||||||
SagaUtils.SAGA_AUTO_RESAMPLING,
|
|
||||||
'Use min covering grid system for resampling', True))
|
|
||||||
ProcessingConfig.addSetting(Setting(self.getDescription(),
|
ProcessingConfig.addSetting(Setting(self.getDescription(),
|
||||||
SagaUtils.SAGA_LOG_COMMANDS,
|
SagaUtils.SAGA_LOG_COMMANDS,
|
||||||
'Log execution commands', True))
|
'Log execution commands', True))
|
||||||
ProcessingConfig.addSetting(Setting(self.getDescription(),
|
ProcessingConfig.addSetting(Setting(self.getDescription(),
|
||||||
SagaUtils.SAGA_LOG_CONSOLE,
|
SagaUtils.SAGA_LOG_CONSOLE,
|
||||||
'Log console output', True))
|
'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):
|
def unload(self):
|
||||||
AlgorithmProvider.unload(self)
|
AlgorithmProvider.unload(self)
|
||||||
if isWindows():
|
if isWindows():
|
||||||
ProcessingConfig.removeSetting(SagaUtils.SAGA_FOLDER)
|
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_CONSOLE)
|
||||||
ProcessingConfig.removeSetting(SagaUtils.SAGA_LOG_COMMANDS)
|
ProcessingConfig.removeSetting(SagaUtils.SAGA_LOG_COMMANDS)
|
||||||
|
|
||||||
|
|||||||
@ -42,12 +42,6 @@ class SagaUtils:
|
|||||||
SAGA_208 = 'SAGA_208'
|
SAGA_208 = 'SAGA_208'
|
||||||
SAGA_LOG_COMMANDS = 'SAGA_LOG_COMMANDS'
|
SAGA_LOG_COMMANDS = 'SAGA_LOG_COMMANDS'
|
||||||
SAGA_LOG_CONSOLE = 'SAGA_LOG_CONSOLE'
|
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_FOLDER = 'SAGA_FOLDER'
|
||||||
SAGA_IMPORT_EXPORT_OPTIMIZATION = 'SAGA_IMPORT_EXPORT_OPTIMIZATION'
|
SAGA_IMPORT_EXPORT_OPTIMIZATION = 'SAGA_IMPORT_EXPORT_OPTIMIZATION'
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
Raster calculator|Grid Calculator
|
Raster calculator|Grid Calculator
|
||||||
grid_calculus
|
grid_calculus
|
||||||
|
AllowUnmatching
|
||||||
ParameterMultipleInput|GRIDS|Raster layers|3|False
|
ParameterMultipleInput|GRIDS|Raster layers|3|False
|
||||||
ParameterString|FORMULA|Formula|
|
ParameterString|FORMULA|Formula|
|
||||||
OutputRaster|RESULT|Result
|
OutputRaster|RESULT|Result
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
Merge raster layers|Merging
|
Merge raster layers|Merging
|
||||||
grid_tools
|
grid_tools
|
||||||
DontResample
|
AllowUnmatching
|
||||||
ParameterMultipleInput|GRIDS|Grids to Merge|3|False
|
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|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
|
ParameterSelection|INTERPOL|Interpolation|[0] Nearest Neighbor;[1] Bilinear Interpolation;[2] Inverse Distance Interpolation;[3] Bicubic Spline Interpolation;[4] B-Spline Interpolation
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user