QGIS/python/plugins/processing/modeler/ModelerAlgorithm.py

777 lines
32 KiB
Python
Raw Normal View History

2012-10-04 19:33:47 +02:00
# -*- coding: utf-8 -*-
"""
***************************************************************************
ModelerAlgorithm.py
---------------------
Date : August 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
2012-10-04 19:33:47 +02:00
__author__ = 'Victor Olaya'
__date__ = 'August 2012'
__copyright__ = '(C) 2012, Victor Olaya'
2012-10-04 19:33:47 +02:00
# This will get replaced with a git SHA1 when you do a git archive
2012-10-04 19:33:47 +02:00
__revision__ = '$Format:%H$'
import traceback
import copy
import os.path
import codecs
import time
from PyQt4 import QtCore, QtGui
from qgis.core import *
2013-08-12 20:44:27 +02:00
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.GeoAlgorithmExecutionException import \
GeoAlgorithmExecutionException
from processing.gui.Help2Html import Help2Html
2013-08-12 20:44:27 +02:00
from processing.modeler.WrongModelException import WrongModelException
from processing.modeler.ModelerUtils import ModelerUtils
from processing.parameters.ParameterFactory import ParameterFactory
2013-08-12 20:44:27 +02:00
from processing.parameters.ParameterRaster import ParameterRaster
from processing.parameters.ParameterDataObject import ParameterDataObject
2013-08-12 20:44:27 +02:00
from processing.parameters.ParameterExtent import ParameterExtent
from processing.parameters.ParameterMultipleInput import ParameterMultipleInput
from processing.parameters.Parameter import Parameter
from processing.parameters.ParameterVector import ParameterVector
from processing.parameters.ParameterTableField import ParameterTableField
2013-08-12 20:44:27 +02:00
from processing.outputs.OutputRaster import OutputRaster
from processing.outputs.OutputHTML import OutputHTML
from processing.outputs.OutputTable import OutputTable
from processing.outputs.OutputVector import OutputVector
from processing.outputs.OutputNumber import OutputNumber
from processing.outputs.OutputString import OutputString
from processing.tools import dataobjects
2012-09-15 18:25:25 +03:00
class ModelerAlgorithm(GeoAlgorithm):
CANVAS_SIZE = 4000
LINE_BREAK_STRING = '%%%'
2012-09-15 18:25:25 +03:00
def getCopy(self):
newone = ModelerAlgorithm()
newone.openModel(self.descriptionFile)
newone.provider = self.provider
newone.deactivated = self.deactivated
2012-09-15 18:25:25 +03:00
return newone
def __init__(self):
GeoAlgorithm.__init__(self)
# The dialog where this model is being edited
2012-09-15 18:25:25 +03:00
self.modelerdialog = None
self.descriptionFile = None
# Geoalgorithms in this model
2012-09-15 18:25:25 +03:00
self.algs = []
# Parameters of Geoalgorithms in self.algs. Each entry is a
# map with (paramname, paramvalue) values for algs[i].
# paramvalues are instances of AlgorithmAndParameter.
2012-09-15 18:25:25 +03:00
self.algParameters = []
2013-02-07 01:09:39 +01:00
# Algorithms that each algorithm depends on. This is just a
# list of dependencies not set by outputs and inputs but
# explicitly entered instead, meaning that an algorithm must
# 'wait' for another to finish. Each entry is a list with
# algorithm indexes
2013-02-03 10:26:43 +01:00
self.dependencies = []
2012-09-15 18:25:25 +03:00
# Outputs of Geoalgorithms in self.algs. Each entry is a map
# with (output, outputvalue) values for algs[i]. outputvalue
# is the name of the output if final. None if is an
# intermediate output
2012-09-15 18:25:25 +03:00
self.algOutputs = []
# Hardcoded parameter values entered by the user when defining
# the model. Keys are value names.
2012-09-15 18:25:25 +03:00
self.paramValues = {}
# Position of items in canvas
2012-09-15 18:25:25 +03:00
self.algPos = []
2013-05-15 20:42:04 +02:00
self.paramPos = []
self.outputPos = [] # same structure as algOutputs
2012-09-15 18:25:25 +03:00
# Deactivated algorithms that should not be executed
2012-09-15 18:25:25 +03:00
self.deactivated = []
def getIcon(self):
return QtGui.QIcon(os.path.dirname(__file__) + '/../images/model.png')
2012-09-15 18:25:25 +03:00
def openModel(self, filename):
self.algPos = []
self.paramPos = []
self.outputOutputs = []
2012-09-15 18:25:25 +03:00
self.algs = []
self.algParameters = []
self.algOutputs = []
self.paramValues = {}
self.dependencies = []
2012-09-15 18:25:25 +03:00
self.descriptionFile = filename
lines = codecs.open(filename, 'r', encoding='utf-8')
line = lines.readline().strip('\n').strip('\r')
2012-09-15 18:25:25 +03:00
iAlg = 0
try:
while line != '':
if line.startswith('PARAMETER:'):
paramLine = line[len('PARAMETER:'):]
2012-09-15 18:25:25 +03:00
param = ParameterFactory.getFromString(paramLine)
if param:
self.parameters.append(param)
else:
raise WrongModelException('Error in parameter line: '
+ line)
line = lines.readline().strip('\n')
tokens = line.split(',')
self.paramPos.append(QtCore.QPointF(float(tokens[0]),
float(tokens[1])))
elif line.startswith('VALUE:'):
valueLine = line[len('VALUE:'):]
tokens = valueLine.split('===')
self.paramValues[tokens[0]] = \
tokens[1].replace(ModelerAlgorithm.LINE_BREAK_STRING,
'\n')
elif line.startswith('NAME:'):
self.name = line[len('NAME:'):]
elif line.startswith('GROUP:'):
self.group = line[len('GROUP:'):]
if self.group == '[Test models]':
2013-09-21 12:44:51 +02:00
self.showInModeler = False
self.showInToolbox = False
elif line.startswith('ALGORITHM:'):
algParams = {}
algOutputs = {}
algLine = line[len('ALGORITHM:'):]
2012-09-15 18:25:25 +03:00
alg = ModelerUtils.getAlgorithm(algLine)
if alg is not None:
posline = lines.readline().strip('\n').strip('\r')
tokens = posline.split(',')
self.algPos.append(QtCore.QPointF(float(tokens[0]),
float(tokens[1])))
2012-09-15 18:25:25 +03:00
self.algs.append(alg)
dependenceline = lines.readline().strip('\n'
).strip('\r')
dependencies = []
2013-02-07 01:09:39 +01:00
if dependenceline != str(None):
for index in dependenceline.split(','):
try:
dependencies.append(int(index))
except:
# A quick fix while I figure out
# how to solve problems when
# parsing this
pass
2012-09-15 18:25:25 +03:00
for param in alg.parameters:
line = lines.readline().strip('\n').strip('\r')
if line == str(None):
2012-09-15 18:25:25 +03:00
algParams[param.name] = None
else:
tokens = line.split('|')
algParams[param.name] = \
AlgorithmAndParameter(int(tokens[0]),
tokens[1])
2013-05-15 20:42:04 +02:00
outputPos = {}
2012-09-15 18:25:25 +03:00
for out in alg.outputs:
line = lines.readline().strip('\n').strip('\r')
if str(None) != line:
if '|' in line:
tokens = line.split('|')
name = tokens[0]
tokens = tokens[1].split(',')
outputPos[out.name] = QtCore.QPointF(
float(tokens[0]), float(tokens[1]))
else:
name = line
outputPos[out.name] = None
algOutputs[out.name] = name
# We add the output to the algorithm,
# with a name indicating where it comes
# from that guarantees that the name is
# unique
2012-09-15 18:25:25 +03:00
output = copy.deepcopy(out)
output.description = name
output.name = self.getSafeNameForOutput(iAlg,
output)
2012-09-15 18:25:25 +03:00
self.addOutput(output)
else:
algOutputs[out.name] = None
2013-05-15 20:42:04 +02:00
self.outputPos.append(outputPos)
2012-09-15 18:25:25 +03:00
self.algOutputs.append(algOutputs)
self.algParameters.append(algParams)
2013-02-03 10:26:43 +01:00
self.dependencies.append(dependencies)
2012-09-15 18:25:25 +03:00
iAlg += 1
else:
raise WrongModelException('Error in algorithm name: '
+ algLine)
line = lines.readline().strip('\n').strip('\r')
except Exception, e:
if isinstance(e, WrongModelException):
raise e
else:
raise WrongModelException('Error in model definition line:'
+ line.strip() + ' : ' + traceback.format_exc())
2012-09-15 18:25:25 +03:00
def addParameter(self, param):
self.parameters.append(param)
self.paramPos.append(self.getPositionForParameterItem())
def updateParameter(self, paramIndex, param):
self.parameters[paramIndex] = param
def addAlgorithm(self, alg, parametersMap, valuesMap, outputsMap,
dependencies):
2012-09-15 18:25:25 +03:00
self.algs.append(alg)
self.algParameters.append(parametersMap)
self.algOutputs.append(outputsMap)
2013-02-03 10:26:43 +01:00
self.dependencies.append(dependencies)
2012-09-15 18:25:25 +03:00
for value in valuesMap.keys():
self.paramValues[value] = valuesMap[value]
algPos = self.getPositionForAlgorithmItem()
self.algPos.append(algPos)
pos = {}
i = 0
2013-08-12 20:44:27 +02:00
from processing.modeler.ModelerGraphicItem import ModelerGraphicItem
2013-05-15 20:42:04 +02:00
for out in outputsMap:
pos[out] = algPos + QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH, i
* ModelerGraphicItem.BOX_HEIGHT)
i += 1
self.outputPos.append(pos)
2012-09-15 18:25:25 +03:00
def updateAlgorithm(self, algIndex, parametersMap, valuesMap, outputsMap,
dependencies):
2012-09-15 18:25:25 +03:00
self.algParameters[algIndex] = parametersMap
self.algOutputs[algIndex] = outputsMap
self.dependencies[algIndex] = dependencies
2012-09-15 18:25:25 +03:00
for value in valuesMap.keys():
self.paramValues[value] = valuesMap[value]
self.updateModelerView()
2013-05-15 20:42:04 +02:00
algPos = self.algPos[algIndex]
pos = {}
i = 0
2013-08-12 20:44:27 +02:00
from processing.modeler.ModelerGraphicItem import ModelerGraphicItem
for out in outputsMap:
pos[out] = algPos + QtCore.QPointF(ModelerGraphicItem.BOX_WIDTH, i
* ModelerGraphicItem.BOX_HEIGHT)
i += 1
self.outputPos[algIndex] = pos
2012-09-15 18:25:25 +03:00
def removeAlgorithm(self, index):
"""Returns True if the algorithm could be removed, False if
others depend on it and could not be removed.
"""
2012-09-15 18:25:25 +03:00
if self.hasDependencies(self.algs[index], index):
return False
for out in self.algs[index].outputs:
val = self.algOutputs[index][out.name]
if val:
name = self.getSafeNameForOutput(index, out)
self.removeOutputFromName(name)
del self.algs[index]
del self.algParameters[index]
del self.algOutputs[index]
del self.algPos[index]
2013-05-15 20:42:04 +02:00
del self.outputPos[index]
2013-02-07 01:09:39 +01:00
2013-03-10 17:13:24 +01:00
i = -1
2013-02-03 10:26:43 +01:00
for paramValues in self.algParameters:
2013-03-10 17:13:24 +01:00
i += 1
newValues = {}
for (name, value) in paramValues.iteritems():
2013-02-03 10:26:43 +01:00
if value:
if value.alg > index:
newValues[name] = AlgorithmAndParameter(value.alg - 1,
value.param, value.algName, value.paramName)
2013-02-03 10:26:43 +01:00
else:
newValues[name] = value
else:
newValues[name] = value
2013-03-10 17:13:24 +01:00
self.algParameters[i] = newValues
2012-09-15 18:25:25 +03:00
self.updateModelerView()
return True
def removeParameter(self, index):
"""Returns True if the parameter could be removed, False if
others depend on it and could not be removed.
"""
2012-09-15 18:25:25 +03:00
if self.hasDependencies(self.parameters[index], index):
return False
del self.parameters[index]
del self.paramPos[index]
self.updateModelerView()
return True
def hasDependencies(self, element, elementIndex):
"""This method returns True if some other element depends on
the passed one.
"""
2012-09-15 18:25:25 +03:00
if isinstance(element, Parameter):
for alg in self.algParameters:
for aap in alg.values():
if aap:
if aap.alg == \
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM:
2012-09-15 18:25:25 +03:00
if aap.param == element.name:
return True
elif aap.param in self.paramValues:
# Check for multiple inputs
2012-09-15 18:25:25 +03:00
aap2 = self.paramValues[aap.param]
if element.name in aap2:
return True
if isinstance(element, ParameterVector):
for param in self.parameters:
if isinstance(param, ParameterTableField):
if param.parent == element.name:
return True
else:
for alg in self.algParameters:
for aap in alg.values():
if aap:
if aap.alg == elementIndex:
return True
return False
def deactivateAlgorithm(self, algIndex, update=False):
2013-02-07 01:09:39 +01:00
if algIndex not in self.deactivated:
dependent = self.getDependentAlgorithms(algIndex)
2013-02-03 10:26:43 +01:00
self.deactivated.extend(dependent)
2012-09-15 18:25:25 +03:00
if update:
self.updateModelerView()
def activateAlgorithm(self, algIndex, update=False):
2012-09-15 18:25:25 +03:00
if algIndex in self.deactivated:
dependsOn = self.getDependsOnAlgorithms(algIndex)
for alg in dependsOn:
2013-02-03 10:26:43 +01:00
if alg in self.deactivated and alg != algIndex:
2012-09-15 18:25:25 +03:00
return False
self.deactivated.remove(algIndex)
dependent = self.getDependentAlgorithms(algIndex)
for alg in dependent:
2013-04-17 13:16:34 +02:00
if alg in self.deactivated:
self.deactivated.remove(alg)
2012-09-15 18:25:25 +03:00
if update:
self.updateModelerView()
return True
def getDependsOnAlgorithms(self, algIndex):
"""This method returns a list with the indexes of algorithms
a given one depends on.
"""
2012-09-15 18:25:25 +03:00
algs = []
2013-02-03 10:26:43 +01:00
algs.extend(self.dependencies[algIndex])
2013-03-31 21:18:27 +02:00
index = -1
2012-09-15 18:25:25 +03:00
for aap in self.algParameters[algIndex].values():
2013-02-03 10:26:43 +01:00
index += 1
2012-09-15 18:25:25 +03:00
if aap is not None:
if aap.alg != AlgorithmAndParameter.PARENT_MODEL_ALGORITHM \
and aap.alg not in algs:
algs.append(aap.alg)
dep = self.getDependsOnAlgorithms(aap.alg)
2013-02-03 10:26:43 +01:00
for alg in dep:
if alg not in algs:
algs.append(alg)
2012-09-15 18:25:25 +03:00
return algs
def getDependentAlgorithms(self, algIndex):
"""This method returns a list with the indexes of algorithms
depending on a given one.
"""
2013-02-03 10:26:43 +01:00
dependent = [algIndex]
2012-09-15 18:25:25 +03:00
index = -1
for alg in self.algParameters:
index += 1
2013-02-03 10:26:43 +01:00
if index in dependent:
continue
2012-09-15 18:25:25 +03:00
for aap in alg.values():
if aap is not None:
2013-02-07 01:09:39 +01:00
if aap.alg == algIndex:
2013-02-03 10:26:43 +01:00
dep = self.getDependentAlgorithms(index)
for alg in dep:
if alg not in dependent:
dependent.append(alg)
2012-09-15 18:25:25 +03:00
break
2013-02-03 10:26:43 +01:00
index = -1
for dep in self.dependencies:
index += 1
2013-02-07 01:09:39 +01:00
if algIndex in dep:
2013-02-03 10:26:43 +01:00
dep = self.getDependentAlgorithms(index)
for alg in dep:
if alg not in dependent:
dependent.append(alg)
2013-02-07 01:09:39 +01:00
2012-09-15 18:25:25 +03:00
return dependent
def getPositionForAlgorithmItem(self):
MARGIN = 20
BOX_WIDTH = 200
BOX_HEIGHT = 80
if len(self.algPos) != 0:
maxX = max([pos.x() for pos in self.algPos])
maxY = max([pos.y() for pos in self.algPos])
newX = min(MARGIN + BOX_WIDTH + maxX, self.CANVAS_SIZE - BOX_WIDTH)
newY = min(MARGIN + BOX_HEIGHT + maxY, self.CANVAS_SIZE
- BOX_HEIGHT)
2012-09-15 18:25:25 +03:00
else:
newX = MARGIN + BOX_WIDTH / 2
newY = MARGIN * 2 + BOX_HEIGHT + BOX_HEIGHT / 2
return QtCore.QPointF(newX, newY)
def getPositionForParameterItem(self):
MARGIN = 20
BOX_WIDTH = 200
BOX_HEIGHT = 80
if len(self.paramPos) != 0:
maxX = max([pos.x() for pos in self.paramPos])
newX = min(MARGIN + BOX_WIDTH + maxX, self.CANVAS_SIZE - BOX_WIDTH)
else:
newX = MARGIN + BOX_WIDTH / 2
return QtCore.QPointF(newX, MARGIN + BOX_HEIGHT / 2)
def serialize(self):
s = 'NAME:' + unicode(self.name) + '\n'
s += 'GROUP:' + unicode(self.group) + '\n'
2012-09-15 18:25:25 +03:00
i = 0
for param in self.parameters:
s += 'PARAMETER:' + param.serialize() + '\n'
2012-09-15 18:25:25 +03:00
pt = self.paramPos[i]
s += str(pt.x()) + ',' + str(pt.y()) + '\n'
i += 1
2012-09-15 18:25:25 +03:00
for key in self.paramValues.keys():
s += 'VALUE:' + key + '===' \
+ str(self.paramValues[key]).replace('\n',
ModelerAlgorithm.LINE_BREAK_STRING) + '\n'
2012-09-15 18:25:25 +03:00
for i in range(len(self.algs)):
alg = self.algs[i]
s += 'ALGORITHM:' + alg.commandLineName() + '\n'
2012-09-15 18:25:25 +03:00
pt = self.algPos[i]
s += str(pt.x()) + ',' + str(pt.y()) + '\n'
2013-02-03 10:26:43 +01:00
if len(self.dependencies[i]) != 0:
s += ','.join([str(index) for index in self.dependencies[i]]) \
+ '\n'
2013-02-03 10:26:43 +01:00
else:
s += str(None) + '\n'
2012-09-15 18:25:25 +03:00
for param in alg.parameters:
value = self.algParameters[i][param.name]
if value:
s += value.serialize() + '\n'
2012-09-15 18:25:25 +03:00
else:
s += str(None) + '\n'
2013-05-15 20:42:04 +02:00
for out in alg.outputs:
value = self.algOutputs[i][out.name]
s += unicode(value)
if value is not None:
pt = self.outputPos[i][out.name]
s += '|' + str(pt.x()) + ',' + str(pt.y())
s += '\n'
2013-05-15 20:42:04 +02:00
2012-09-15 18:25:25 +03:00
return s
def setPositions(self, paramPos, algPos, outputPos):
2012-09-15 18:25:25 +03:00
self.paramPos = paramPos
self.algPos = algPos
self.outputPos = outputPos
2012-09-15 18:25:25 +03:00
def prepareAlgorithm(self, alg, iAlg):
for param in alg.parameters:
aap = self.algParameters[iAlg][param.name]
if aap is None:
if isinstance(param, ParameterExtent):
value = self.getMinCoveringExtent()
if not param.setValue(value):
raise GeoAlgorithmExecutionException('Wrong value: '
+ str(value))
else:
param.setValue(None)
2012-09-15 18:25:25 +03:00
continue
if isinstance(param, ParameterMultipleInput):
value = self.getValueFromAlgorithmAndParameter(aap)
tokens = value.split(';')
2012-09-15 18:25:25 +03:00
layerslist = []
for token in tokens:
(i, paramname) = token.split('|')
2012-09-15 18:25:25 +03:00
aap = AlgorithmAndParameter(int(i), paramname)
value = self.getValueFromAlgorithmAndParameter(aap)
layerslist.append(str(value))
value = ';'.join(layerslist)
2012-09-15 18:25:25 +03:00
else:
value = self.getValueFromAlgorithmAndParameter(aap)
# We allow unexistent filepaths, since that allows
# algorithms to skip some conversion routines
if not param.setValue(value) and not isinstance(param,
ParameterDataObject):
raise GeoAlgorithmExecutionException('Wrong value: '
+ str(value))
2012-09-15 18:25:25 +03:00
for out in alg.outputs:
val = self.algOutputs[iAlg][out.name]
if val:
name = self.getSafeNameForOutput(iAlg, out)
out.value = self.getOutputFromName(name).value
else:
out.value = None
def getMinCoveringExtent(self):
first = True
found = False
for param in self.parameters:
if param.value:
if isinstance(param, (ParameterRaster, ParameterVector)):
found = True
if isinstance(param.value, (QgsRasterLayer,
QgsVectorLayer)):
layer = param.value
else:
layer = dataobjects.getObjectFromUri(param.value)
self.addToRegion(layer, first)
first = False
elif isinstance(param, ParameterMultipleInput):
found = True
layers = param.value.split(';')
for layername in layers:
layer = dataobjects.getObjectFromUri(layername)
self.addToRegion(layer, first)
first = False
if found:
return str(self.xmin) + ',' + str(self.xmax) + ',' \
+ str(self.ymin) + ',' + str(self.ymax)
else:
return None
def addToRegion(self, layer, first):
if first:
self.xmin = layer.extent().xMinimum()
self.xmax = layer.extent().xMaximum()
self.ymin = layer.extent().yMinimum()
self.ymax = layer.extent().yMaximum()
else:
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())
2012-09-15 18:25:25 +03:00
def getSafeNameForOutput(self, ialg, out):
return out.name + '_ALG' + str(ialg)
2012-09-15 18:25:25 +03:00
def getValueFromAlgorithmAndParameter(self, aap):
if aap is None:
return None
if float(aap.alg) \
== float(AlgorithmAndParameter.PARENT_MODEL_ALGORITHM):
for key in self.paramValues.keys():
if aap.param == key:
return self.paramValues[key]
for param in self.parameters:
if aap.param == param.name:
return param.value
2012-12-10 00:12:07 +01:00
else:
2012-09-15 18:25:25 +03:00
return self.producedOutputs[int(aap.alg)][aap.param]
def processAlgorithm(self, progress):
self.producedOutputs = {}
executed = []
while len(executed) < len(self.algs) - len(self.deactivated):
iAlg = 0
for alg in self.algs:
if iAlg not in self.deactivated and iAlg not in executed:
canExecute = True
required = self.getDependsOnAlgorithms(iAlg)
for requiredAlg in required:
if requiredAlg != iAlg and requiredAlg not in executed:
2012-09-15 18:25:25 +03:00
canExecute = False
break
if canExecute:
try:
alg = alg.getCopy()
progress.setDebugInfo('Prepare algorithm %i: %s'
% (iAlg, alg.name))
2012-09-15 18:25:25 +03:00
self.prepareAlgorithm(alg, iAlg)
progress.setText('Running ' + alg.name + ' ['
+ str(iAlg + 1) + '/' + str(len(self.algs)
- len(self.deactivated)) + ']')
2012-09-15 18:25:25 +03:00
outputs = {}
progress.setDebugInfo('Parameters: '
+ ', '.join([unicode(p).strip() + '='
+ unicode(p.value) for p in
alg.parameters]))
2012-09-15 18:25:25 +03:00
t0 = time.time()
alg.execute(progress, self)
2012-09-15 18:25:25 +03:00
dt = time.time() - t0
2012-12-10 00:12:07 +01:00
for out in alg.outputs:
2012-09-15 18:25:25 +03:00
outputs[out.name] = out.value
progress.setDebugInfo('Outputs: '
+ ', '.join([unicode(out).strip() + '='
+ unicode(outputs[out.name]) for out in
alg.outputs]))
2012-09-15 18:25:25 +03:00
self.producedOutputs[iAlg] = outputs
executed.append(iAlg)
progress.setDebugInfo(
'OK. Execution took %0.3f ms (%i outputs).'
% (dt, len(outputs)))
except GeoAlgorithmExecutionException, e:
progress.setDebugInfo('Failed')
raise GeoAlgorithmExecutionException(
'Error executing algorithm ' + str(iAlg)
+ '\n' + e.msg)
2012-09-15 18:25:25 +03:00
else:
pass
2012-09-15 18:25:25 +03:00
iAlg += 1
progress.setDebugInfo(
'Model processed ok. Executed %i algorithms total' % iAlg)
2012-09-15 18:25:25 +03:00
def getOutputType(self, i, outname):
for out in self.algs[i].outputs:
if out.name == outname:
if isinstance(out, OutputRaster):
return 'output raster'
2012-09-15 18:25:25 +03:00
elif isinstance(out, OutputVector):
return 'output vector'
2012-09-15 18:25:25 +03:00
elif isinstance(out, OutputTable):
return 'output table'
2012-09-15 18:25:25 +03:00
elif isinstance(out, OutputHTML):
return 'output html'
2012-09-15 18:25:25 +03:00
elif isinstance(out, OutputNumber):
return 'output number'
elif isinstance(out, OutputString):
return 'output string'
2012-09-15 18:25:25 +03:00
def getAsPythonCode(self):
s = []
for param in self.parameters:
s.append(str(param.getAsScriptCode().lower()))
i = 0
for outs in self.algOutputs:
for out in outs.keys():
if outs[out]:
s.append('##' + out.lower() + '_alg' + str(i) + '='
+ self.getOutputType(i, out))
2012-09-15 18:25:25 +03:00
i += 1
i = 0
iMultiple = 0
for alg in self.algs:
multiple = []
runline = 'outputs_' + str(i) + '=Processing.runalg("' \
+ alg.commandLineName() + '"'
2012-09-15 18:25:25 +03:00
for param in alg.parameters:
aap = self.algParameters[i][param.name]
if aap is None:
runline += ', None'
2012-09-15 18:25:25 +03:00
elif isinstance(param, ParameterMultipleInput):
value = self.paramValues[aap.param]
tokens = value.split(';')
2012-09-15 18:25:25 +03:00
layerslist = []
for token in tokens:
(iAlg, paramname) = token.split('|')
if float(iAlg) == float(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM):
2012-09-15 18:25:25 +03:00
if self.ismodelparam(paramname):
value = paramname.lower()
else:
value = self.paramValues[paramname]
else:
value = 'outputs_' + str(iAlg) + "['" + paramname \
+ "']"
2012-09-15 18:25:25 +03:00
layerslist.append(str(value))
multiple.append('multiple_' + str(iMultiple) + '=['
+ ','.join(layerslist) + ']')
runline += ', ";".join(multiple_' + str(iMultiple) + ') '
2012-09-15 18:25:25 +03:00
else:
if float(aap.alg) == float(
AlgorithmAndParameter.PARENT_MODEL_ALGORITHM):
2012-09-15 18:25:25 +03:00
if self.ismodelparam(aap.param):
runline += ', ' + aap.param.lower()
2012-09-15 18:25:25 +03:00
else:
runline += ', ' + str(self.paramValues[aap.param])
2012-09-15 18:25:25 +03:00
else:
runline += ', outputs_' + str(aap.alg) + "['" \
+ aap.param + "']"
2012-09-15 18:25:25 +03:00
for out in alg.outputs:
value = self.algOutputs[i][out.name]
if value:
name = out.name.lower() + '_alg' + str(i)
2012-09-15 18:25:25 +03:00
else:
name = str(None)
runline += ', ' + name
2012-09-15 18:25:25 +03:00
i += 1
s += multiple
s.append(str(runline + ')'))
return '\n'.join(s)
2012-09-15 18:25:25 +03:00
def ismodelparam(self, paramname):
for modelparam in self.parameters:
if modelparam.name == paramname:
return True
return False
def getAsCommand(self):
if self.descriptionFile:
return GeoAlgorithm.getAsCommand(self)
else:
return None
def commandLineName(self):
return 'modeler:' + os.path.basename(self.descriptionFile)[:-6].lower()
2012-09-15 18:25:25 +03:00
def setModelerView(self, dialog):
self.modelerdialog = dialog
def updateModelerView(self):
if self.modelerdialog:
self.modelerdialog.repaintModel()
def helpFile(self):
helpfile = self.descriptionFile + '.help'
2012-09-15 18:25:25 +03:00
if os.path.exists(helpfile):
h2h = Help2Html()
return h2h.getHtmlFile(self, helpfile)
else:
return None
class AlgorithmAndParameter:
2012-09-15 18:25:25 +03:00
PARENT_MODEL_ALGORITHM = -1
# alg is the index of the algorithm in the list in
# ModelerAlgorithm.algs.
# -1 if the value is not taken from the output of an algorithm,
# but from an input of the model or a hardcoded value.
# Names are just used for decoration, and are not needed to
# create a hardcoded value.
def __init__(self, alg, param, algName='', paramName=''):
2012-09-15 18:25:25 +03:00
self.alg = alg
self.param = param
self.algName = algName
self.paramName = paramName
def serialize(self):
return str(self.alg) + '|' + str(self.param)
2012-09-15 18:25:25 +03:00
def name(self):
if self.alg != AlgorithmAndParameter.PARENT_MODEL_ALGORITHM:
return self.paramName + ' from algorithm ' + str(self.alg) + '(' \
+ self.algName + ')'
2012-09-15 18:25:25 +03:00
else:
return self.paramName
def __str__(self):
return str(self.alg) + '|' + str(self.param)