diff --git a/python/plugins/processing/algs/saga/SagaAlgorithm.py b/python/plugins/processing/algs/saga/SagaAlgorithm.py index bd8fc78c408..deff6c13699 100644 --- a/python/plugins/processing/algs/saga/SagaAlgorithm.py +++ b/python/plugins/processing/algs/saga/SagaAlgorithm.py @@ -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 @@ class SagaAlgorithm(GeoAlgorithm): 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 @@ class SagaAlgorithm(GeoAlgorithm): 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 @@ class SagaAlgorithm(GeoAlgorithm): # 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 @@ class SagaAlgorithm(GeoAlgorithm): 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 @@ class SagaAlgorithm(GeoAlgorithm): 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 @@ class SagaAlgorithm(GeoAlgorithm): 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 @@ class SagaAlgorithm(GeoAlgorithm): html = '
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
' - html += 'Click here to know more about how to install and configure SAGA to be used with QGIS
' + html += '\ + Click here to know more about how to install and configure SAGA to be used with QGIS
' 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() diff --git a/python/plugins/processing/algs/saga/SagaAlgorithmProvider.py b/python/plugins/processing/algs/saga/SagaAlgorithmProvider.py index 469ba189507..35811b2094b 100644 --- a/python/plugins/processing/algs/saga/SagaAlgorithmProvider.py +++ b/python/plugins/processing/algs/saga/SagaAlgorithmProvider.py @@ -51,48 +51,23 @@ class SagaAlgorithmProvider(AlgorithmProvider): 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) diff --git a/python/plugins/processing/algs/saga/SagaUtils.py b/python/plugins/processing/algs/saga/SagaUtils.py index 14d4ee7799a..e8f2b9f2b3b 100644 --- a/python/plugins/processing/algs/saga/SagaUtils.py +++ b/python/plugins/processing/algs/saga/SagaUtils.py @@ -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' diff --git a/python/plugins/processing/algs/saga/description/GridCalculator.txt b/python/plugins/processing/algs/saga/description/GridCalculator.txt index 495f21b24d6..9cb976cb8ce 100644 --- a/python/plugins/processing/algs/saga/description/GridCalculator.txt +++ b/python/plugins/processing/algs/saga/description/GridCalculator.txt @@ -1,5 +1,6 @@ Raster calculator|Grid Calculator grid_calculus +AllowUnmatching ParameterMultipleInput|GRIDS|Raster layers|3|False ParameterString|FORMULA|Formula| OutputRaster|RESULT|Result diff --git a/python/plugins/processing/algs/saga/description/Merging.txt b/python/plugins/processing/algs/saga/description/Merging.txt index 31be8e7c2f9..cb112b28ea8 100644 --- a/python/plugins/processing/algs/saga/description/Merging.txt +++ b/python/plugins/processing/algs/saga/description/Merging.txt @@ -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