Skip to content

Commit

Permalink
improvements in SEXTANTE modeler
Browse files Browse the repository at this point in the history
  • Loading branch information
volaya committed Feb 3, 2013
1 parent 158dadb commit 9a70fe0
Show file tree
Hide file tree
Showing 16 changed files with 293 additions and 87 deletions.
4 changes: 2 additions & 2 deletions python/plugins/sextante/algs/AutoincrementalField.py
Expand Up @@ -29,8 +29,6 @@
from sextante.parameters.ParameterVector import ParameterVector
from sextante.core.QGisLayers import QGisLayers
from sextante.outputs.OutputVector import OutputVector
import os
from PyQt4 import QtGui

class AutoincrementalField(GeoAlgorithm):

Expand Down Expand Up @@ -73,3 +71,5 @@ def defineCharacteristics(self):
self.addParameter(ParameterVector(self.INPUT, "Input layer", ParameterVector.VECTOR_TYPE_ANY))
self.addOutput(OutputVector(self.OUTPUT, "Output layer"))



8 changes: 5 additions & 3 deletions python/plugins/sextante/algs/QGISAlgorithmProvider.py
Expand Up @@ -16,7 +16,7 @@
* *
***************************************************************************
"""
from sextante.algs.JoinAttributes import JoinAttributes
from sextante.algs.CreateConstantRaster import CreateConstantRaster

__author__ = 'Victor Olaya'
__date__ = 'August 2012'
Expand Down Expand Up @@ -68,7 +68,6 @@
mmqgisx_label_point_algorithm, mmqgisx_merge_algorithm,
mmqgisx_select_algorithm, mmqgisx_sort_algorithm,
mmqgisx_text_to_float_algorithm)

from sextante.algs.EquivalentNumField import EquivalentNumField
from sextante.core.AlgorithmProvider import AlgorithmProvider
from sextante.algs.AddTableField import AddTableField
Expand All @@ -79,6 +78,7 @@
from sextante.algs.Explode import Explode
from sextante.algs.AutoincrementalField import AutoincrementalField
from sextante.algs.FieldPyculator import FieldsPyculator
from sextante.algs.JoinAttributes import JoinAttributes

class QGISAlgorithmProvider(AlgorithmProvider):

Expand Down Expand Up @@ -120,7 +120,9 @@ def __init__(self):
mmqgisx_merge_algorithm(),
mmqgisx_select_algorithm(),
mmqgisx_sort_algorithm(),
mmqgisx_text_to_float_algorithm()]
mmqgisx_text_to_float_algorithm(),
#raster
CreateConstantRaster()]

def initializeSettings(self):
AlgorithmProvider.initializeSettings(self)
Expand Down
16 changes: 6 additions & 10 deletions python/plugins/sextante/algs/ftools/SelectByLocation.py
Expand Up @@ -24,15 +24,12 @@
__revision__ = '$Format:%H$'

from PyQt4.QtCore import *

from qgis.core import *

from sextante.core.GeoAlgorithm import GeoAlgorithm
from sextante.core.QGisLayers import QGisLayers

from sextante.parameters.ParameterSelection import ParameterSelection
from sextante.parameters.ParameterVector import ParameterVector
from sextante.parameters.ParameterBoolean import ParameterBoolean


from sextante.outputs.OutputVector import OutputVector

Expand Down Expand Up @@ -67,16 +64,15 @@ def processAlgorithm(self, progress):
filename = self.getParameterValue(self.INTERSECT)
selectLayer = QGisLayers.getObjectFromUri(filename)
inputProvider = inputLayer.dataProvider()
selectProvider = selectLayer.dataProvider()


oldSelection = set(inputLayer.selectedFeaturesIds())
index = QgsSpatialIndex()
inputProvider.rewind()
inputProvider.select()
feat = QgsFeature()
while inputProvider.nextFeature(feat):
index.insertFeature(feat)

selectProvider.select()

infeat = QgsFeature()
geom = QgsGeometry()
selectedSet = []
Expand All @@ -95,9 +91,9 @@ def processAlgorithm(self, progress):
progress.setPercentage(int(current * total))

if method == 1:
selectedSet = list(set(inputLayer.selectedFeaturesIds()).union(selectedSet))
selectedSet = list(oldSelection.union(selectedSet))
elif method == 2:
selectedSet = list(set(inputLayer.selectedFeaturesIds()).difference(selectedSet))
selectedSet = list(oldSelection.difference(selectedSet))

inputLayer.setSelectedFeatures(selectedSet)
self.setOutputValue(self.OUTPUT, filename)
8 changes: 3 additions & 5 deletions python/plugins/sextante/algs/mmqgisx/mmqgisx_library.py
Expand Up @@ -1704,21 +1704,19 @@ def mmqgisx_select(progress, layer, selectattributename, comparisonvalue, compar
return "No comparison value given"

readcount = 0
writecount = 0
feature = QgsFeature()
layer.dataProvider().select(layer.dataProvider().attributeIndexes())
layer.dataProvider().rewind()

selected = []
totalcount = layer.featureCount()
features = QGisLayers.features(layer)
for feature in features:
while layer.dataProvider().nextFeature(feature):
if (comparisonname == 'begins with') or (comparisonname == 'contains') or \
(feature.attributeMap()[selectindex].type() == QVariant.String):
(feature.attributeMap()[selectindex].type() == QVariant.String) or \
isinstance(comparisonvalue, basestring):
x = unicode(feature.attributeMap()[selectindex].toString())
y = unicode(comparisonvalue)
else:
# print feature.attributeMap()[selectindex].typeName()
x = float(feature.attributeMap()[selectindex].toString())
y = float(comparisonvalue)

Expand Down
5 changes: 3 additions & 2 deletions python/plugins/sextante/core/GeoAlgorithm.py
Expand Up @@ -194,13 +194,14 @@ def convertUnsupportedFormats(self, progress):
if isinstance(out, OutputVector):
if out.compatible is not None:
layer = QGisLayers.getObjectFromUri(out.compatible)
if layer is None: # for the case of memory layer, if the getCompatible method has been called
continue
provider = layer.dataProvider()
writer = out.getVectorWriter( provider.fields(), provider.geometryType(), provider.crs())
features = QGisLayers.features(layer)
for feature in features:
writer.addFeature(feature)
elif isinstance(out, OutputRaster):
out.close()
elif isinstance(out, OutputRaster):
if out.compatible is not None:
layer = QGisLayers.getObjectFromUri(out.compatible)
provider = layer.dataProvider()
Expand Down
26 changes: 14 additions & 12 deletions python/plugins/sextante/gui/MultipleInputPanel.py
Expand Up @@ -59,18 +59,20 @@ def setSelectedItems(self, selected):
self.label.setText(str(len(self.selectedoptions)) + " elements selected")

def showSelectionDialog(self):
#If there is a datatype, we use it to create the list of options
if self.datatype is not None:
if self.datatype == ParameterMultipleInput.TYPE_RASTER:
options = QGisLayers.getRasterLayers()
elif self.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY:
options = QGisLayers.getVectorLayers()
else:
options = QGisLayers.getVectorLayers(self.datatype)
opts = []
for opt in options:
opts.append(opt.name())
self.options = opts
#=======================================================================
# #If there is a datatype, we use it to create the list of options
# if self.datatype is not None:
# if self.datatype == ParameterMultipleInput.TYPE_RASTER:
# options = QGisLayers.getRasterLayers()
# elif self.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY:
# options = QGisLayers.getVectorLayers()
# else:
# options = QGisLayers.getVectorLayers(self.datatype)
# opts = []
# for opt in options:
# opts.append(opt.name())
# self.options = opts
#=======================================================================
dlg = MultipleInputDialog(self.options, self.selectedoptions)
dlg.exec_()
if dlg.selectedoptions != None:
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/sextante/gui/ParametersPanel.py
Expand Up @@ -275,7 +275,7 @@ def getWidgetFromParameter(self, param):
opts = []
for opt in options:
opts.append(opt.name())
item = MultipleInputPanel(opts, param.datatype)
item = MultipleInputPanel(opts)
elif isinstance(param, ParameterNumber):
item = NumberInputPanel(param.default, param.isInteger)
elif isinstance(param, ParameterExtent):
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/sextante/gui/UnthreadedAlgorithmExecutor.py
Expand Up @@ -45,7 +45,7 @@ def runalg(alg, progress):
QMessageBox.critical(None, "Error", e.msg)
return False
except Exception:
QMessageBox.critical(None, "Error", traceback.format_exc())
QMessageBox.critical(None, "Uncaught error", traceback.format_exc())
return False

@staticmethod
Expand Down
90 changes: 71 additions & 19 deletions python/plugins/sextante/modeler/ModelerAlgorithm.py
Expand Up @@ -72,6 +72,13 @@ def __init__(self):
#Each entry is a map with (paramname, paramvalue) values for algs[i].
#paramvalues are instances of AlgorithmAndParameter
self.algParameters = []

#algorithms that each algorithm depends on.
#This is just a list of dependencies not set by outputs and inputs
#but explicitely entered instead, meaning that an algorithm must ''wait''
#for another to finish
#Each entry is a list with algorithm indexes
self.dependencies = []

#outputs of Geoalgorithms in self.algs.
#Each entry is a map with (output, outputvalue) values for algs[i].
Expand Down Expand Up @@ -100,6 +107,7 @@ def openModel(self, filename):
self.algParameters = []
self.algOutputs = []
self.paramValues = {}
self.dependencies = []

self.descriptionFile = filename
lines = codecs.open(filename, "r", encoding='utf-8')
Expand Down Expand Up @@ -136,6 +144,11 @@ def openModel(self, filename):
tokens = posline.split(",")
self.algPos.append(QtCore.QPointF(float(tokens[0]), float(tokens[1])))
self.algs.append(alg)
dependenceline = lines.readline().strip("\n")
dependencies = [];
if dependenceline != str(None):
for index in dependenceline.split(","):
dependencies.append(int(index))
for param in alg.parameters:
line = lines.readline().strip("\n")
if line==str(None):
Expand All @@ -157,12 +170,13 @@ def openModel(self, filename):
algOutputs[out.name] = None
self.algOutputs.append(algOutputs)
self.algParameters.append(algParams)
self.dependencies.append(dependencies)
iAlg += 1
else:
raise WrongModelException("Error in line: " + line)
line = lines.readline().strip("\n")
except WrongModelException:
raise WrongModelException(line)
except:
raise WrongModelException("Error in line: " + line)

def addParameter(self, param):
self.parameters.append(param)
Expand All @@ -172,17 +186,19 @@ def updateParameter(self, paramIndex, param):
self.parameters[paramIndex] = param
#self.updateModelerView()

def addAlgorithm(self, alg, parametersMap, valuesMap, outputsMap):
def addAlgorithm(self, alg, parametersMap, valuesMap, outputsMap, dependencies):
self.algs.append(alg)
self.algParameters.append(parametersMap)
self.algOutputs.append(outputsMap)
self.dependencies.append(dependencies)
for value in valuesMap.keys():
self.paramValues[value] = valuesMap[value]
self.algPos.append(self.getPositionForAlgorithmItem())

def updateAlgorithm(self, algIndex, parametersMap, valuesMap, outputsMap):
def updateAlgorithm(self, algIndex, parametersMap, valuesMap, outputsMap, dependencies):
self.algParameters[algIndex] = parametersMap
self.algOutputs[algIndex] = outputsMap
self.dependencies[algIndex] = dependencies
for value in valuesMap.keys():
self.paramValues[value] = valuesMap[value]
self.updateModelerView()
Expand All @@ -200,6 +216,20 @@ def removeAlgorithm(self, index):
del self.algParameters[index]
del self.algOutputs[index]
del self.algPos[index]

index = -1
for paramValues in self.algParameters:
index += 1
newValues = []
for name, value in paramValues:
if value:
if value.alg > index:
newValues[name] = AlgorithmAndParameter(value.alg - 1, value.param, value.algName, value.paramName)
else:
newValues[name] = value
else:
newValues[name] = value

self.updateModelerView()
return True

Expand Down Expand Up @@ -239,49 +269,67 @@ def hasDependencies(self, element, elementIndex):
return False

def deactivateAlgorithm(self, algIndex, update = False):
if algIndex not in self.deactivated:
self.deactivated.append(algIndex)
dependent = self.getDependentAlgorithms(algIndex)
for alg in dependent:
self.deactivateAlgorithm(alg)
if algIndex not in self.deactivated:
dependent = self.getDependentAlgorithms(algIndex)
self.deactivated.extend(dependent)
if update:
self.updateModelerView()

def activateAlgorithm(self, algIndex, update = False):
if algIndex in self.deactivated:
dependsOn = self.getDependsOnAlgorithms(algIndex)
for alg in dependsOn:
if alg in self.deactivated:
if alg in self.deactivated and alg != algIndex:
return False
self.deactivated.remove(algIndex)
dependent = self.getDependentAlgorithms(algIndex)
for alg in dependent:
self.activateAlgorithm(alg)
self.deactivated.remove(alg)
if update:
self.updateModelerView()
return True

def getDependsOnAlgorithms(self, algIndex):
'''This method returns a list with the indexes of algorithm a given one depends on'''
'''This method returns a list with the indexes of algorithms a given one depends on'''
algs = []
algs.extend(self.dependencies[algIndex])
index = -1
for aap in self.algParameters[algIndex].values():
index += 1
if aap is not None:
if aap.alg != AlgorithmAndParameter.PARENT_MODEL_ALGORITHM and aap.alg not in algs:
algs.append(aap.alg)
if aap.alg != AlgorithmAndParameter.PARENT_MODEL_ALGORITHM and aap.alg not in algs:
algs.append(index)
dep = self.getDependsOnAlgorithms(index)
for alg in dep:
if alg not in algs:
algs.append(alg)
return algs

def getDependentAlgorithms(self, algIndex):
'''This method returns a list with the indexes of algorithm depending on a given one'''
dependent = []
'''This method returns a list with the indexes of algorithms depending on a given one'''
dependent = [algIndex]
index = -1
for alg in self.algParameters:
index += 1
if index in dependent:
continue
for aap in alg.values():
if aap is not None:
if aap.alg == algIndex:
dependent.append(index)
if aap.alg == algIndex:
dep = self.getDependentAlgorithms(index)
for alg in dep:
if alg not in dependent:
dependent.append(alg)
break

index = -1
for dep in self.dependencies:
index += 1
if algIndex in dep:
dep = self.getDependentAlgorithms(index)
for alg in dep:
if alg not in dependent:
dependent.append(alg)

return dependent

def getPositionForAlgorithmItem(self):
Expand Down Expand Up @@ -326,6 +374,10 @@ def serialize(self):
s+="ALGORITHM:" + alg.commandLineName()+"\n"
pt = self.algPos[i]
s += str(pt.x()) + "," + str(pt.y()) + "\n"
if len(self.dependencies[i]) != 0:
s += ",".join([str(index) for index in self.dependencies[i]]) + "\n"
else:
s += str(None) + "\n"
for param in alg.parameters:
value = self.algParameters[i][param.name]
if value:
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/sextante/modeler/ModelerDialog.py
Expand Up @@ -367,7 +367,7 @@ def addAlgorithm(self):
dlg.exec_()
if dlg.params != None:
self.alg.setPositions(self.scene.getParameterPositions(), self.scene.getAlgorithmPositions())
self.alg.addAlgorithm(alg, dlg.params, dlg.values, dlg.outputs)
self.alg.addAlgorithm(alg, dlg.params, dlg.values, dlg.outputs, dlg.dependencies)
self.repaintModel()
self.view.ensureVisible(self.scene.getLastAlgorithmItem())

Expand Down
2 changes: 1 addition & 1 deletion python/plugins/sextante/modeler/ModelerGraphicItem.py
Expand Up @@ -103,7 +103,7 @@ def editElement(self):
dlg = ModelerParametersDialog(self.element, self.model, self.elementIndex)
dlg.exec_()
if dlg.params != None:
self.model.updateAlgorithm(self.elementIndex, dlg.params, dlg.values, dlg.outputs)
self.model.updateAlgorithm(self.elementIndex, dlg.params, dlg.values, dlg.outputs, dlg.dependencies)

def removeElement(self):
if isinstance(self.element, Parameter):
Expand Down

0 comments on commit 9a70fe0

Please sign in to comment.