Skip to content

Commit

Permalink
Restore more saga functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson authored and alexbruy committed Nov 9, 2017
1 parent 9ba4143 commit 8d91f1f
Show file tree
Hide file tree
Showing 12 changed files with 80 additions and 54 deletions.
102 changes: 64 additions & 38 deletions python/plugins/processing/algs/saga/SagaAlgorithm.py
Expand Up @@ -41,14 +41,13 @@
QgsProcessingParameterMultipleLayers,
QgsProcessingParameterMatrix,
QgsProcessingParameterString,
QgsProcessingParameterField)
QgsProcessingParameterField,
QgsProcessingParameterFile,
QgsProcessingParameterExtent,
QgsProcessingParameterRasterDestination,
QgsProcessingParameterVectorDestination)
from processing.core.ProcessingConfig import ProcessingConfig
from processing.core.parameters import (getParameterFromString,
ParameterExtent)
from processing.core.outputs import (getOutputFromString,
OutputVector,
OutputRaster)
from processing.tools import dataobjects
from processing.core.parameters import getParameterFromString
from processing.algs.help import shortHelp
from processing.tools.system import getTempFilename
from processing.algs.saga.SagaNameDecorator import decoratedAlgorithmName, decoratedGroupName
Expand Down Expand Up @@ -131,8 +130,8 @@ def defineCharacteristicsFromFile(self):
elif line.startswith('Extent'):
# An extent parameter that wraps 4 SAGA numerical parameters
self.extentParamNames = line[6:].strip().split(' ')
self.params.append(ParameterExtent(self.OUTPUT_EXTENT,
'Output extent'))
self.params.append(QgsProcessingParameterExtent(self.OUTPUT_EXTENT,
'Output extent'))
else:
pass # TODO
#self.addOutput(getOutputFromString(line))
Expand Down Expand Up @@ -160,9 +159,14 @@ def processAlgorithm(self, parameters, context, feedback):
elif isinstance(param, QgsProcessingParameterFeatureSource):
if param.name() not in parameters or parameters[param.name()] is None:
continue
layer_path = self.parameterAsCompatibleSourceLayerPath(parameters, param.name(), context, 'shp', feedback=feedback)

if not crs:
source = self.parameterAsSource(parameters, param.name(), context)
crs = source.sourceCrs()

layer_path = self.parameterAsCompatibleSourceLayerPath(parameters, param.name(), context, ['shp'], 'shp', feedback=feedback)
if layer_path:
self.exportedLayers[parameters[param.name()]] = layer_path
self.exportedLayers[param.name()] = layer_path
else:
raise QgsProcessingException(
self.tr('Unsupported file format'))
Expand All @@ -186,6 +190,11 @@ def processAlgorithm(self, parameters, context, feedback):
temp_params = deepcopy(parameters)
for layer in layers:
temp_params[param.name()] = layer

if not crs:
source = self.parameterAsSource(temp_params, param.name(), context)
crs = source.sourceCrs()

layer_path = self.parameterAsCompatibleSourceLayerPath(temp_params, param.name(), context, 'shp',
feedback=feedback)
if layer_path:
Expand All @@ -197,31 +206,26 @@ def processAlgorithm(self, parameters, context, feedback):
raise QgsProcessingException(
self.tr('Unsupported file format'))

# TODO - set minimum extent
if not extent:
extent = QgsProcessingUtils.combineLayerExtents([layer])

# 2: Set parameters and outputs
command = self.undecorated_group + ' "' + self.cmdname + '"'
command += ' ' + ' '.join(self.hardcoded_strings)

for param in self.parameterDefinitions():
if not param.name() in parameters or parameters[param.name()] is None:
continue
if param.isDestination():
continue

if isinstance(param, (QgsProcessingParameterRasterLayer, QgsProcessingParameterFeatureSource)):
value = parameters[param.name()]
if value in list(self.exportedLayers.keys()):
command += ' -' + param.name() + ' "' \
+ self.exportedLayers[value] + '"'
else:
command += ' -' + param.name() + ' "' + value + '"'
command += ' -' + param.name() + ' "' \
+ self.exportedLayers[param.name()] + '"'
elif isinstance(param, QgsProcessingParameterMultipleLayers):
s = parameters[param.name()]
for layer in list(self.exportedLayers.keys()):
s = s.replace(layer, self.exportedLayers[layer])
command += ' -' + ';'.join(self.exportedLayers[param.name()]) + ' "' + s + '"'
elif isinstance(param, QgsProcessingParameterBoolean):
if parameters[param.name()]:
if self.parameterAsBool(parameters, param.name(), context):
command += ' -' + param.name().strip() + " true"
else:
command += ' -' + param.name().strip() + " false"
Expand All @@ -234,31 +238,48 @@ def processAlgorithm(self, parameters, context, feedback):
s = values[i] + '\t' + values[i + 1] + '\t' + values[i + 2] + '\n'
f.write(s)
command += ' -' + param.name() + ' "' + tempTableFile + '"'
elif isinstance(param, ParameterExtent):
elif isinstance(param, QgsProcessingParameterExtent):
# 'We have to substract/add half cell size, since SAGA is
# center based, not corner based
halfcell = self.getOutputCellsize(parameters) / 2
halfcell = self.getOutputCellsize(parameters, context) / 2
offset = [halfcell, -halfcell, halfcell, -halfcell]
values = parameters[param.name()].split(',')
rect = self.parameterAsExtent(parameters, param.name(), context)

values = []
values.append(rect.xMinimum())
values.append(rect.yMinimum())
values.append(rect.xMaximum())
values.append(rect.yMaximum())

for i in range(4):
command += ' -' + self.extentParamNames[i] + ' ' \
+ str(float(values[i]) + offset[i])
elif isinstance(param, QgsProcessingParameterNumber):
command += ' -' + param.name() + ' ' + str(self.parameterAsDouble(parameters, param.name(), context))
elif isinstance(param, QgsProcessingParameterEnum):
command += ' -' + param.name() + ' ' + str(self.parameterAsEnum(parameters, param.name(), context))
elif isinstance(param, QgsProcessingParameterString, QgsProcessingParameterField):
elif isinstance(param, (QgsProcessingParameterString, QgsProcessingParameterFile)):
command += ' -' + param.name() + ' "' + self.parameterAsFile(parameters, param.name(), context) + '"'
elif isinstance(param, (QgsProcessingParameterString, QgsProcessingParameterField)):
command += ' -' + param.name() + ' "' + self.parameterAsString(parameters, param.name(), context) + '"'

for out in self.outputs:
command += ' -' + out.name + ' "' + out.getCompatibleFileName(self) + '"'
output_layers = []
output_files = {}
for out in self.destinationParameterDefinitions():
# TODO
# command += ' -' + out.name() + ' "' + out.getCompatibleFileName(self) + '"'
file = self.parameterAsOutputLayer(parameters, out.name(), context)
if isinstance(out, (QgsProcessingParameterRasterDestination, QgsProcessingParameterVectorDestination)):
output_layers.append(file)
output_files[out.name()] = file
command += ' -' + out.name() + ' "' + file + '"'

commands.append(command)

# special treatment for RGB algorithm
# TODO: improve this and put this code somewhere else
for out in self.outputs:
if isinstance(out, OutputRaster):
for out in self.destinationParameterDefinitions():
if isinstance(out, QgsProcessingParameterRasterDestination):
filename = out.getCompatibleFileName(self)
filename2 = filename + '.sgrd'
if self.cmdname == 'RGB Composite':
Expand All @@ -277,12 +298,17 @@ def processAlgorithm(self, parameters, context, feedback):
QgsMessageLog.logMessage('\n'.join(loglines), self.tr('Processing'), QgsMessageLog.INFO)
SagaUtils.executeSaga(feedback)

if self.crs is not None:
for out in self.outputs:
if isinstance(out, (OutputVector, OutputRaster)):
prjFile = os.path.splitext(out.getCompatibleFileName(self))[0] + ".prj"
with open(prjFile, "w") as f:
f.write(self.crs.toWkt())
if crs is not None:
for out in output_layers:
prjFile = os.path.splitext(out)[0] + ".prj"
with open(prjFile, "w") as f:
f.write(crs.toWkt())

result = {}
for o in self.outputDefinitions():
if o.name() in output_files:
result[o.name()] = output_files[o.name()]
return result

def preProcessInputs(self):
name = self.name().replace('.', '_')
Expand All @@ -305,7 +331,7 @@ def editCommands(self, commands):
else:
return commands

def getOutputCellsize(self, parameters):
def getOutputCellsize(self, parameters, context):
"""Tries to guess the cell size of the output, searching for
a parameter with an appropriate name for it.
:param parameters:
Expand All @@ -314,7 +340,7 @@ def getOutputCellsize(self, parameters):
cellsize = 0
for param in self.parameterDefinitions():
if param.name() in parameters and param.name() == 'USER_SIZE':
cellsize = float(parameters[param.name()])
cellsize = self.parameterAsDouble(parameters, param.name(), context)
break
return cellsize

Expand Down
Expand Up @@ -3,5 +3,5 @@ shapes_polygons
QgsProcessingParameterFeatureSource|INPUT|Polygons|2|None|False
QgsProcessingParameterFeatureSource|POINTS|Points|0|None|False
QgsProcessingParameterField|FIELDS|Attributes|None|POINTS|-1|False|False
QgsProcessingParameterBoolean|ADD_LOCATION_INFO|Add location info|False
QgsProcessingParameterBoolean|ADD_LOCATION_INFO|Add locPation info|False
QgsProcessingParameterVectorDestination|OUTPUT|Result
@@ -1,6 +1,6 @@
K-Means Clustering for Grids
imagery_classification
QgsProcessingParameterMultipleLayers|GRIDS|Grids|3.0|None|False
QgsProcessingParameterMultipleLayers|GRIDS|Grids|3|None|False
QgsProcessingParameterEnum|METHOD|Method|[0] Iterative Minimum Distance (Forgy 1965);[1] Hill-Climbing (Rubin 1967);[2] Combined Minimum Distance / Hillclimbing
QgsProcessingParameterNumber|NCLUSTER|Clusters|QgsProcessingParameterNumber.Integer|10|False|2|None
QgsProcessingParameterNumber|MAXITER|Maximum Iterations|QgsProcessingParameterNumber.Integer|0|False|0|None
Expand Down
@@ -1,6 +1,6 @@
GWR for Multiple Predictor Grids
statistics_regression
QgsProcessingParameterMultipleLayers|PREDICTORS|Predictors|3.0|None|False
QgsProcessingParameterMultipleLayers|PREDICTORS|Predictors|3|None|False
QgsProcessingParameterFeatureSource|POINTS|Points|0|None|False
QgsProcessingParameterField|DEPENDENT|Dependent Variable|None|POINTS|-1|False|False
QgsProcessingParameterEnum|RESOLUTION|Model Resolution|[0] same as predictors;[1] user defined|False|1
Expand Down
@@ -1,7 +1,7 @@
GridCombination
sim_rivflow
QgsProcessingParameterRasterLayer|INPUT|Gelaendemodell (DTM)|None|False
ParameterFile|Folder1|Pfad WaterGap Raster|False|False
QgsProcessingParameterFile|Folder1|Pfad WaterGap Raster|False|None|False
QgsProcessingParameterNumber|sY|Start-Jahr|QgsProcessingParameterNumber.Integer|1990|False| 1906| 2000
QgsProcessingParameterNumber|eY|End-Jahr|QgsProcessingParameterNumber.Integer|1990|False| 1906| 2000
QgsProcessingParameterBoolean|DomW|Domestic Water|True
Expand Down
Expand Up @@ -7,8 +7,8 @@ QgsProcessingParameterRasterDestination|PREDICTION|Presence Prediction
QgsProcessingParameterRasterDestination|PROBABILITY|Presence Probability
QgsProcessingParameterNumber|BACKGROUND|Background Sample Density [Percent]|QgsProcessingParameterNumber.Double|1.000000|False| 0.000000| 100.000000
QgsProcessingParameterEnum|METHOD|Method|[0] Yoshimasa Tsuruoka;[1] Dekang Lin|False|0
ParameterFile|YT_FILE_LOAD|Load from File...|False|False
ParameterFile|YT_FILE_SAVE|Save to File...|False|False
QgsProcessingParameterFile|YT_FILE_LOAD|Load from File...|False|None|False
QgsProcessingParameterFile|YT_FILE_SAVE|Save to File...|False|None|False
QgsProcessingParameterEnum|YT_REGUL|Regularization|[0] none;[1] L1;[2] L2|False|1
QgsProcessingParameterNumber|YT_REGUL_VAL|Regularization Factor|QgsProcessingParameterNumber.Double|1.000000|False| 0.000000|None
QgsProcessingParameterBoolean|YT_NUMASREAL|Real-valued Numerical Features|True
Expand Down
Expand Up @@ -10,8 +10,8 @@ QgsProcessingParameterNumber|mRMR_NFEATURES|Number of Features|QgsProcessingPara
QgsProcessingParameterBoolean|mRMR_DISCRETIZE|Discretization|True
QgsProcessingParameterNumber|mRMR_THRESHOLD|Discretization Threshold|QgsProcessingParameterNumber.Double|1.000000|False| 0.000000|None
QgsProcessingParameterEnum|mRMR_METHOD|Selection Method|[0] Mutual Information Difference (MID);[1] Mutual Information Quotient (MIQ)|False|0
ParameterFile|RF_IMPORT|Import from File|False|False
ParameterFile|RF_EXPORT|Export to File|False|False
QgsProcessingParameterFile|RF_IMPORT|Import from File|False|None|False
QgsProcessingParameterFile|RF_EXPORT|Export to File|False|None|False
QgsProcessingParameterNumber|RF_TREE_COUNT|Tree Count|QgsProcessingParameterNumber.Integer|32|False| 1|None
QgsProcessingParameterNumber|RF_TREE_SAMPLES|Samples per Tree|QgsProcessingParameterNumber.Double|1.000000|False| 0.000000| 1.000000
QgsProcessingParameterBoolean|RF_REPLACE|Sample with Replacement|True
Expand Down
Expand Up @@ -5,10 +5,10 @@ QgsProcessingParameterRasterDestination|CLASSES|Classification
QgsProcessingParameterEnum|SCALING|Scaling|[0] none;[1] normalize (0-1);[2] standardize|False|2
QgsProcessingParameterBoolean|MESSAGE|Verbose Messages|False
QgsProcessingParameterEnum|MODEL_SRC|Model Source|[0] create from training areas;[1] restore from file|False|0
ParameterFile|MODEL_LOAD|Restore Model from File|False|False
QgsProcessingParameterFile|MODEL_LOAD|Restore Model from File|False|None|False
QgsProcessingParameterFeatureSource|ROI|Training Areas|-1|None|False
QgsProcessingParameterFeatureSource|ROI_ID|Class Identifier|5|None|False
ParameterFile|MODEL_SAVE|Store Model to File|False|False
QgsProcessingParameterFile|MODEL_SAVE|Store Model to File|False|None|False
QgsProcessingParameterEnum|SVM_TYPE|SVM Type|[0] C-SVC;[1] nu-SVC;[2] one-class SVM;[3] epsilon-SVR;[4] nu-SVR|False|0
QgsProcessingParameterEnum|KERNEL_TYPE|Kernel Type|[0] linear;[1] polynomial;[2] radial basis function;[3] sigmoid|False|2
QgsProcessingParameterNumber|DEGREE|Degree|QgsProcessingParameterNumber.Integer|3|False|None|None
Expand Down
@@ -1,6 +1,6 @@
Supervised Classification
imagery_classification
QgsProcessingParameterMultipleLayers|GRIDS|Grids|3.0|None|False
QgsProcessingParameterMultipleLayers|GRIDS|Grids|3|None|False
QgsProcessingParameterFeatureSource|ROI|Training Areas|2|None|False
QgsProcessingParameterField|ROI_ID|Class Identifier|None|ROI|-1|False|False
QgsProcessingParameterFeatureSource|STATS|Class Statistics|5|None|False
Expand Down
Expand Up @@ -6,8 +6,8 @@ QgsProcessingParameterRasterDestination|CLASSES|Classification
QgsProcessingParameterRasterDestination|QUALITY|Quality
QgsProcessingParameterFeatureSource|TRAINING|Training Areas|-1|None|True
QgsProcessingParameterFeatureSource|TRAINING_CLASS|Class Identifier|5|None|False
ParameterFile|FILE_LOAD|Load Statistics from File...|False|False
ParameterFile|FILE_SAVE|Save Statistics to File...|False|False
QgsProcessingParameterFile|FILE_LOAD|Load Statistics from File...|False|None|False
QgsProcessingParameterFile|FILE_SAVE|Save Statistics to File...|False|None|False
QgsProcessingParameterEnum|METHOD|Method|[0] Binary Encoding;[1] Parallelepiped;[2] Minimum Distance;[3] Mahalanobis Distance;[4] Maximum Likelihood;[5] Spectral Angle Mapping;[6] Winner Takes All|False|2
QgsProcessingParameterNumber|THRESHOLD_DIST|Distance Threshold|QgsProcessingParameterNumber.Double|0.000000|False| 0.000000|None
QgsProcessingParameterNumber|THRESHOLD_ANGLE|Spectral Angle Threshold (Degree)|QgsProcessingParameterNumber.Double|0.000000|False| 0.000000| 90.000000
Expand Down
Expand Up @@ -5,8 +5,8 @@ QgsProcessingParameterVectorDestination|CLASSES|Classification
QgsProcessingParameterFeatureSource|FEATURES|Features|5|None|False
QgsProcessingParameterBoolean|NORMALISE|Normalise|False
QgsProcessingParameterFeatureSource|TRAINING|Training Classes|5|None|False
ParameterFile|FILE_LOAD|Load Statistics from File...|False|False
ParameterFile|FILE_SAVE|Save Statistics to File...|False|False
QgsProcessingParameterFile|FILE_LOAD|Load Statistics from File...|False|None|False
QgsProcessingParameterFile|FILE_SAVE|Save Statistics to File...|False|None|False
QgsProcessingParameterEnum|METHOD|Method|[0] Binary Encoding;[1] Parallelepiped;[2] Minimum Distance;[3] Mahalanobis Distance;[4] Maximum Likelihood;[5] Spectral Angle Mapping;[6] Winner Takes All|False|2
QgsProcessingParameterNumber|THRESHOLD_DIST|Distance Threshold|QgsProcessingParameterNumber.Double|0.000000|False| 0.000000|None
QgsProcessingParameterNumber|THRESHOLD_ANGLE|Spectral Angle Threshold (Degree)|QgsProcessingParameterNumber.Double|0.000000|False| 0.000000| 90.000000
Expand Down
Expand Up @@ -48,7 +48,7 @@ QgsProcessingParameterRasterDestination|RF_OLI10|Reflectance Band 10
QgsProcessingParameterRasterDestination|RF_OLI11|Reflectance Band 11
QgsProcessingParameterRasterLayer|DN_PAN08|DN Band 8|None|True
QgsProcessingParameterRasterDestination|RF_PAN08|Reflectance Band 8
ParameterFile|METAFILE|Metadata File|False|False
QgsProcessingParameterFile|METAFILE|Metadata File|False|None|False
QgsProcessingParameterEnum|SENSOR|Spacecraft Sensor|[0] Landsat-1 MSS;[1] Landsat-2 MSS;[2] Landsat-3 MSS;[3] Landsat-4 MSS;[4] Landsat-5 MSS;[5] Landsat-4 TM;[6] Landsat-5 TM;[7] Landsat-7 ETM+;[8] Landsat-8 OLI/TIRS|False|7
QgsProcessingParameterString|DATE_ACQU|Image Acquisition Date
QgsProcessingParameterString|DATE_PROD|Image Creation Date
Expand Down

0 comments on commit 8d91f1f

Please sign in to comment.