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 . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
"""
2015-09-30 08:39:39 +02:00
from operator import attrgetter
2013-10-24 15:26:39 +02:00
2012-10-04 19:33:47 +02:00
__author__ = ' Victor Olaya '
__date__ = ' August 2012 '
__copyright__ = ' (C) 2012, Victor Olaya '
2013-10-01 20:52:22 +03:00
2012-10-04 19:33:47 +02:00
# This will get replaced with a git SHA1 when you do a git archive
2013-10-01 20:52:22 +03:00
2012-10-04 19:33:47 +02:00
__revision__ = ' $Format: % H$ '
2012-12-20 00:16:05 +01:00
import os . path
2014-06-08 00:21:12 +02:00
import sys
import copy
2012-12-20 00:16:05 +01:00
import time
2014-06-08 00:21:12 +02:00
import json
2014-08-22 11:27:57 +02:00
import codecs
import traceback
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
from PyQt4 . QtCore import QCoreApplication , QPointF
from PyQt4 . QtGui import QIcon
from qgis . core import QgsRasterLayer , QgsVectorLayer
2015-03-25 17:46:30 +01:00
from qgis . gui import QgsMessageBar
from qgis . utils import iface
2013-08-12 20:44:27 +02:00
from processing . core . GeoAlgorithm import GeoAlgorithm
2014-06-08 00:21:12 +02:00
from processing . modeler . WrongModelException import WrongModelException
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
from processing . core . GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
2013-08-12 20:44:27 +02:00
from processing . modeler . ModelerUtils import ModelerUtils
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
from processing . core . parameters import getParameterFromString , ParameterRaster , ParameterVector , ParameterTable , ParameterTableField , ParameterBoolean , ParameterString , ParameterNumber , ParameterExtent , ParameterDataObject , ParameterMultipleInput
2013-10-01 20:52:22 +03:00
from processing . tools import dataobjects
2014-09-23 10:13:21 +02:00
from processing . gui . Help2Html import getHtmlFromDescriptionsDict
2012-09-15 18:25:25 +03:00
2015-05-18 19:51:26 +03:00
pluginPath = os . path . split ( os . path . dirname ( __file__ ) ) [ 0 ]
2014-08-14 10:56:08 +02:00
class ModelerParameter ( ) :
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
def __init__ ( self , param = None , pos = None ) :
self . param = param
self . pos = pos
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
def todict ( self ) :
return self . __dict__
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
@staticmethod
2014-07-02 07:46:03 +02:00
def fromdict ( d ) :
2014-08-14 10:56:08 +02:00
return ModelerParameter ( d [ " param " ] , d [ " pos " ] )
2014-07-02 07:46:03 +02:00
2014-08-14 10:56:08 +02:00
class ModelerOutput ( ) :
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
def __init__ ( self , description = " " ) :
self . description = description
self . pos = None
def todict ( self ) :
2014-07-02 07:46:03 +02:00
return self . __dict__
2014-06-08 00:21:12 +02:00
class Algorithm ( ) :
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
def __init__ ( self , consoleName = " " ) :
2014-07-02 07:46:03 +02:00
self . name = None
2014-06-08 00:21:12 +02:00
self . description = " "
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
#The type of the algorithm, indicated as a string, which corresponds
#to the string used to refer to it in the python console
self . consoleName = consoleName
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
self . _algInstance = None
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
#A dict of Input object. keys are param names
2014-07-02 07:46:03 +02:00
self . params = { }
#A dict of Output with final output descriptions. Keys are output names.
2014-06-08 00:21:12 +02:00
#Outputs not final are not stored in this dict
2014-07-02 07:46:03 +02:00
self . outputs = { }
2014-06-08 00:21:12 +02:00
self . pos = None
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
self . dependencies = [ ]
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
self . paramsFolded = True
self . outputsFolded = True
self . active = True
2014-07-02 07:46:03 +02:00
def todict ( self ) :
2015-08-22 14:29:41 +02:00
return { k : v for k , v in self . __dict__ . iteritems ( ) if not k . startswith ( " _ " ) }
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
@property
def algorithm ( self ) :
if self . _algInstance is None :
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
self . _algInstance = ModelerUtils . getAlgorithm ( self . consoleName ) . getCopy ( )
2014-06-08 00:21:12 +02:00
return self . _algInstance
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
def setName ( self , model ) :
if self . name is None :
i = 1
2015-08-16 20:57:24 +02:00
name = self . consoleName + " _ " + unicode ( i )
2014-06-08 00:21:12 +02:00
while name in model . algs :
i + = 1
2015-08-16 20:57:24 +02:00
name = self . consoleName + " _ " + unicode ( i )
2014-06-08 00:21:12 +02:00
self . name = name
2014-07-02 07:46:03 +02:00
2014-10-03 14:44:01 +03:00
2014-06-08 00:21:12 +02:00
class ValueFromInput ( ) :
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
def __init__ ( self , name = " " ) :
self . name = name
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
def todict ( self ) :
2014-07-02 07:46:03 +02:00
return self . __dict__
2014-06-08 00:21:12 +02:00
def __str__ ( self ) :
2014-07-02 07:46:03 +02:00
return self . name
2014-06-08 00:21:12 +02:00
def __eq__ ( self , other ) :
try :
return self . name == other . name
except :
2014-07-02 07:46:03 +02:00
return False
2014-10-03 14:44:01 +03:00
2014-06-08 00:21:12 +02:00
class ValueFromOutput ( ) :
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
def __init__ ( self , alg = " " , output = " " ) :
self . alg = alg
self . output = output
def todict ( self ) :
return self . __dict__
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
def __eq__ ( self , other ) :
try :
return self . alg == other . alg and self . output == other . output
except :
2014-07-02 07:46:03 +02:00
return False
2014-06-08 00:21:12 +02:00
def __str__ ( self ) :
2014-07-02 07:46:03 +02:00
return self . alg + " , " + self . output
2014-10-03 14:44:01 +03:00
2012-09-15 18:25:25 +03:00
class ModelerAlgorithm ( GeoAlgorithm ) :
CANVAS_SIZE = 4000
def getCopy ( self ) :
newone = ModelerAlgorithm ( )
newone . provider = self . provider
2014-06-08 00:21:12 +02:00
newone . algs = copy . deepcopy ( self . algs )
newone . inputs = copy . deepcopy ( self . inputs )
newone . defineCharacteristics ( )
newone . name = self . name
newone . group = self . group
newone . descriptionFile = self . descriptionFile
2014-11-23 14:03:32 +01:00
newone . helpContent = copy . deepcopy ( self . helpContent )
2012-09-15 18:25:25 +03:00
return newone
def __init__ ( self ) :
2014-10-03 21:56:24 +03:00
self . name = self . tr ( ' Model ' , ' ModelerAlgorithm ' )
2013-10-01 20:52:22 +03:00
# The dialog where this model is being edited
2012-09-15 18:25:25 +03:00
self . modelerdialog = None
self . descriptionFile = None
2014-06-08 00:21:12 +02:00
self . helpContent = { }
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
# Geoalgorithms in this model. A dict of Algorithm objects, with names as keys
self . algs = { }
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
#Input parameters. A dict of Input objects, with names as keys
self . inputs = { }
GeoAlgorithm . __init__ ( self )
2012-09-15 18:25:25 +03:00
def getIcon ( self ) :
2015-05-18 19:51:26 +03:00
return QIcon ( os . path . join ( pluginPath , ' images ' , ' model.png ' ) )
2012-09-15 18:25:25 +03:00
2014-07-02 07:46:03 +02:00
def defineCharacteristics ( self ) :
2014-11-21 07:20:48 +01:00
classes = [ ParameterRaster , ParameterVector , ParameterTable , ParameterTableField ,
ParameterBoolean , ParameterString , ParameterNumber ]
self . parameters = [ ]
for c in classes :
for inp in self . inputs . values ( ) :
if isinstance ( inp . param , c ) :
self . parameters . append ( inp . param )
for inp in self . inputs . values ( ) :
if inp . param not in self . parameters :
self . parameters . append ( inp . param )
2014-06-08 00:21:12 +02:00
self . outputs = [ ]
for alg in self . algs . values ( ) :
if alg . active :
for out in alg . outputs :
modelOutput = copy . deepcopy ( alg . algorithm . getOutputFromName ( out ) )
modelOutput . name = self . getSafeNameForOutput ( alg . name , out )
modelOutput . description = alg . outputs [ out ] . description
self . outputs . append ( modelOutput )
2015-09-30 08:39:39 +02:00
self . outputs . sort ( key = attrgetter ( " description " ) )
2014-07-02 07:46:03 +02:00
2012-09-15 18:25:25 +03:00
def addParameter ( self , param ) :
2014-06-08 00:21:12 +02:00
self . inputs [ param . param . name ] = param
def updateParameter ( self , param ) :
self . inputs [ param . name ] . param = param
2014-07-02 07:46:03 +02:00
def addAlgorithm ( self , alg ) :
name = self . getNameForAlgorithm ( alg )
alg . name = name
self . algs [ name ] = alg
2014-06-08 00:21:12 +02:00
def getNameForAlgorithm ( self , alg ) :
i = 1
2015-08-16 20:57:24 +02:00
while alg . consoleName . upper ( ) . replace ( " : " , " " ) + " _ " + unicode ( i ) in self . algs . keys ( ) :
2013-10-01 20:52:22 +03:00
i + = 1
2015-08-16 20:57:24 +02:00
return alg . consoleName . upper ( ) . replace ( " : " , " " ) + " _ " + unicode ( i )
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
def updateAlgorithm ( self , alg ) :
2014-07-02 07:46:03 +02:00
alg . pos = self . algs [ alg . name ] . pos
2015-10-06 16:06:37 +02:00
alg . paramsFolded = self . algs [ alg . name ] . paramsFolded
alg . outputsFolded = self . algs [ alg . name ] . outputsFolded
2014-07-02 07:46:03 +02:00
self . algs [ alg . name ] = alg
2013-08-12 20:44:27 +02:00
from processing . modeler . ModelerGraphicItem import ModelerGraphicItem
2014-07-02 07:46:03 +02:00
for i , out in enumerate ( alg . outputs ) :
alg . outputs [ out ] . pos = ( alg . outputs [ out ] . pos or
2015-08-22 14:29:41 +02:00
alg . pos + QPointF (
ModelerGraphicItem . BOX_WIDTH ,
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
( i + 1.5 ) * ModelerGraphicItem . BOX_HEIGHT ) )
2012-09-15 18:25:25 +03:00
2014-06-08 00:21:12 +02:00
def removeAlgorithm ( self , name ) :
2013-10-01 20:52:22 +03:00
""" Returns True if the algorithm could be removed, False if
others depend on it and could not be removed .
"""
2014-06-08 00:21:12 +02:00
if self . hasDependencies ( name ) :
2012-09-15 18:25:25 +03:00
return False
2014-06-08 00:21:12 +02:00
del self . algs [ name ]
self . modelerdialog . hasChanged = True
2012-09-15 18:25:25 +03:00
return True
2014-06-08 00:21:12 +02:00
def removeParameter ( self , name ) :
2013-10-01 20:52:22 +03:00
""" Returns True if the parameter could be removed, False if
others depend on it and could not be removed .
"""
2014-06-08 00:21:12 +02:00
if self . hasDependencies ( name ) :
2012-09-15 18:25:25 +03:00
return False
2014-07-02 07:46:03 +02:00
del self . inputs [ name ]
self . modelerdialog . hasChanged = True
2012-09-15 18:25:25 +03:00
return True
2014-06-08 00:21:12 +02:00
def hasDependencies ( self , name ) :
2013-10-01 20:52:22 +03:00
""" This method returns True if some other element depends on
the passed one .
2014-07-02 07:46:03 +02:00
"""
2014-06-08 00:21:12 +02:00
for alg in self . algs . values ( ) :
2014-07-02 07:46:03 +02:00
for value in alg . params . values ( ) :
2014-06-08 00:21:12 +02:00
if value is None :
2014-07-02 07:46:03 +02:00
continue
if isinstance ( value , list ) :
2014-06-08 00:21:12 +02:00
for v in value :
if isinstance ( v , ValueFromInput ) :
if v . name == name :
2012-09-15 18:25:25 +03:00
return True
2014-06-08 00:21:12 +02:00
elif isinstance ( v , ValueFromOutput ) :
if v . alg == name :
return True
if isinstance ( value , ValueFromInput ) :
if value . name == name :
return True
elif isinstance ( value , ValueFromOutput ) :
if value . alg == name :
2014-07-02 07:46:03 +02:00
return True
2012-09-15 18:25:25 +03:00
return False
2014-06-08 00:21:12 +02:00
def getDependsOnAlgorithms ( self , name ) :
""" This method returns a list with names of algorithms
2013-10-01 20:52:22 +03:00
a given one depends on .
"""
2014-06-08 00:21:12 +02:00
alg = self . algs [ name ]
algs = set ( )
algs . update ( set ( alg . dependencies ) )
for value in alg . params . values ( ) :
if value is None :
2013-02-03 10:26:43 +01:00
continue
2014-07-02 07:46:03 +02:00
if isinstance ( value , list ) :
2014-06-08 00:21:12 +02:00
for v in value :
if isinstance ( v , ValueFromOutput ) :
algs . add ( v . alg )
2014-07-02 07:46:03 +02:00
algs . update ( self . getDependsOnAlgorithms ( v . alg ) )
2014-06-08 00:21:12 +02:00
elif isinstance ( value , ValueFromOutput ) :
algs . add ( value . alg )
algs . update ( self . getDependsOnAlgorithms ( value . alg ) )
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
return algs
2012-09-15 18:25:25 +03:00
2014-06-08 00:21:12 +02:00
def getDependentAlgorithms ( self , name ) :
""" This method returns a list with the names of algorithms
depending on a given one . It includes the algorithm itself
2014-07-02 07:46:03 +02:00
"""
2014-06-08 00:21:12 +02:00
algs = set ( )
algs . add ( name )
for alg in self . algs . values ( ) :
2014-07-02 07:46:03 +02:00
for value in alg . params . values ( ) :
2014-06-08 00:21:12 +02:00
if value is None :
2014-07-02 07:46:03 +02:00
continue
2014-06-08 00:21:12 +02:00
if isinstance ( value , list ) :
2014-07-02 07:46:03 +02:00
for v in value :
2014-06-08 00:21:12 +02:00
if isinstance ( v , ValueFromOutput ) and v . alg == name :
algs . update ( self . getDependentAlgorithms ( alg . name ) )
elif isinstance ( value , ValueFromOutput ) and value . alg == name :
algs . update ( self . getDependentAlgorithms ( alg . name ) )
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
return algs
2012-09-15 18:25:25 +03:00
2014-07-02 07:46:03 +02:00
def setPositions ( self , paramPos , algPos , outputsPos ) :
2014-06-08 00:21:12 +02:00
for param , pos in paramPos . iteritems ( ) :
self . inputs [ param ] . pos = pos
for alg , pos in algPos . iteritems ( ) :
self . algs [ alg ] . pos = pos
for alg , positions in outputsPos . iteritems ( ) :
for output , pos in positions . iteritems ( ) :
self . algs [ alg ] . outputs [ output ] . pos = pos
def prepareAlgorithm ( self , alg ) :
algInstance = alg . algorithm
for param in algInstance . parameters :
2014-05-21 16:33:20 +02:00
if not param . hidden :
2015-03-25 17:46:30 +01:00
if param . name in alg . params :
value = self . resolveValue ( alg . params [ param . name ] )
else :
iface . messageBar ( ) . pushMessage ( self . tr ( " Warning " ) ,
2015-05-18 19:51:26 +03:00
self . tr ( " Parameter %s in algorithm %s in the model is run with default value! Edit the model to make sure that this is correct. " % ( param . name , alg . name ) ) ,
2015-03-25 17:46:30 +01:00
QgsMessageBar . WARNING , 4 )
value = None
2014-06-08 00:21:12 +02:00
if value is None and isinstance ( param , ParameterExtent ) :
2014-07-02 07:46:03 +02:00
value = self . getMinCoveringExtent ( )
2014-05-21 17:31:12 +02:00
# We allow unexistent filepaths, since that allows
# algorithms to skip some conversion routines
if not param . setValue ( value ) and not isinstance ( param ,
2015-08-22 14:29:41 +02:00
ParameterDataObject ) :
2014-10-03 21:56:24 +03:00
raise GeoAlgorithmExecutionException (
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
self . tr ( ' Wrong value: %s ' , ' ModelerAlgorithm ' ) % value )
2014-06-08 00:21:12 +02:00
for out in algInstance . outputs :
2014-07-02 07:46:03 +02:00
if not out . hidden :
2014-06-08 00:21:12 +02:00
if out . name in alg . outputs :
name = self . getSafeNameForOutput ( alg . name , out . name )
modelOut = self . getOutputFromName ( name )
if modelOut :
out . value = modelOut . value
2014-05-21 16:33:20 +02:00
else :
out . value = None
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
return algInstance
2014-07-02 07:46:03 +02:00
def deactivateAlgorithm ( self , algName ) :
2014-06-08 00:21:12 +02:00
dependent = self . getDependentAlgorithms ( algName )
for alg in dependent :
self . algs [ alg ] . active = False
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
def activateAlgorithm ( self , algName ) :
parents = self . getDependsOnAlgorithms ( algName )
for alg in parents :
if not self . algs [ alg ] . active :
return False
self . algs [ algName ] . active = True
return True
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
def getSafeNameForOutput ( self , algName , outName ) :
return outName + ' _ALG ' + algName
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
def resolveValue ( self , value ) :
if value is None :
return None
if isinstance ( value , list ) :
return " ; " . join ( [ self . resolveValue ( v ) for v in value ] )
if isinstance ( value , ValueFromInput ) :
return self . getParameterFromName ( value . name ) . value
elif isinstance ( value , ValueFromOutput ) :
return self . algs [ value . alg ] . algorithm . getOutputFromName ( value . output ) . value
else :
return value
2014-07-02 07:46:03 +02:00
2012-12-20 00:16:05 +01:00
def getMinCoveringExtent ( self ) :
first = True
found = False
for param in self . parameters :
if param . value :
if isinstance ( param , ( ParameterRaster , ParameterVector ) ) :
found = True
2014-06-08 00:21:12 +02:00
if isinstance ( param . value , ( QgsRasterLayer , QgsVectorLayer ) ) :
2012-12-20 00:16:05 +01:00
layer = param . value
else :
2013-09-12 13:19:00 +02:00
layer = dataobjects . getObjectFromUri ( param . value )
2012-12-20 00:16:05 +01:00
self . addToRegion ( layer , first )
first = False
elif isinstance ( param , ParameterMultipleInput ) :
found = True
2013-10-01 20:52:22 +03:00
layers = param . value . split ( ' ; ' )
2012-12-20 00:16:05 +01:00
for layername in layers :
2013-09-12 13:19:00 +02:00
layer = dataobjects . getObjectFromUri ( layername )
2012-12-20 00:16:05 +01:00
self . addToRegion ( layer , first )
first = False
if found :
2015-08-16 20:57:24 +02:00
return ' , ' . join ( [ unicode ( v ) for v in [ self . xmin , self . xmax , self . ymin , self . ymax ] ] )
2012-12-20 00:16:05 +01:00
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 ( ) )
2014-07-02 07:46:03 +02:00
def processAlgorithm ( self , progress ) :
2012-09-15 18:25:25 +03:00
executed = [ ]
2014-06-08 00:21:12 +02:00
toExecute = [ alg for alg in self . algs . values ( ) if alg . active ]
2014-07-02 07:46:03 +02:00
while len ( executed ) < len ( toExecute ) :
2014-06-08 00:21:12 +02:00
for alg in toExecute :
if alg . name not in executed :
2012-09-15 18:25:25 +03:00
canExecute = True
2014-06-08 00:21:12 +02:00
required = self . getDependsOnAlgorithms ( alg . name )
2012-09-15 18:25:25 +03:00
for requiredAlg in required :
2014-06-08 00:21:12 +02:00
if requiredAlg != alg . name and requiredAlg not in executed :
2012-09-15 18:25:25 +03:00
canExecute = False
break
if canExecute :
try :
2014-10-03 21:56:24 +03:00
progress . setDebugInfo (
self . tr ( ' Prepare algorithm: %s ' , ' ModelerAlgorithm ' ) % alg . name )
2014-06-08 00:21:12 +02:00
self . prepareAlgorithm ( alg )
2014-10-03 21:56:24 +03:00
progress . setText (
2015-08-22 14:29:41 +02:00
self . tr ( ' Running %s [ %i / %i ] ' , ' ModelerAlgorithm ' ) % ( alg . description , len ( executed ) + 1 , len ( toExecute ) ) )
2014-07-02 07:46:03 +02:00
progress . setDebugInfo ( ' Parameters: ' + ' , ' . join ( [ unicode ( p ) . strip ( )
2015-08-22 14:29:41 +02:00
+ ' = ' + unicode ( p . value ) for p in alg . algorithm . parameters ] ) )
2012-09-15 18:25:25 +03:00
t0 = time . time ( )
2014-06-08 00:21:12 +02:00
alg . algorithm . execute ( progress , self )
2014-07-02 07:46:03 +02:00
dt = time . time ( ) - t0
2014-06-08 00:21:12 +02:00
executed . append ( alg . name )
2013-10-01 20:52:22 +03:00
progress . setDebugInfo (
2014-10-03 21:56:24 +03:00
self . tr ( ' OK. Execution took %0.3f ms ( %i outputs). ' , ' ModelerAlgorithm ' ) % ( dt , len ( alg . algorithm . outputs ) ) )
2015-08-22 14:29:41 +02:00
except GeoAlgorithmExecutionException as e :
2014-10-03 21:56:24 +03:00
progress . setDebugInfo ( self . tr ( ' Failed ' , ' ModelerAlgorithm ' ) )
2013-10-01 20:52:22 +03:00
raise GeoAlgorithmExecutionException (
2014-10-03 21:56:24 +03:00
self . tr ( ' Error executing algorithm %s \n %s ' , ' ModelerAlgorithm ' ) % ( alg . description , e . msg ) )
2014-07-02 07:46:03 +02:00
2013-10-01 20:52:22 +03:00
progress . setDebugInfo (
2014-10-03 21:56:24 +03:00
self . tr ( ' Model processed ok. Executed %i algorithms total ' , ' ModelerAlgorithm ' ) % len ( executed ) )
2014-06-08 00:21:12 +02:00
2012-09-15 18:25:25 +03:00
def getAsCommand ( self ) :
if self . descriptionFile :
return GeoAlgorithm . getAsCommand ( self )
else :
return None
def commandLineName ( self ) :
2014-06-08 00:21:12 +02:00
if self . descriptionFile is None :
return ' '
else :
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 ( )
2014-04-19 00:48:56 +02:00
def help ( self ) :
2014-06-08 00:21:12 +02:00
try :
2014-11-23 14:03:32 +01:00
return True , getHtmlFromDescriptionsDict ( self , self . helpContent )
2014-06-08 00:21:12 +02:00
except :
2014-04-24 17:25:36 +02:00
return False , None
2014-07-02 07:46:03 +02:00
def todict ( self ) :
2014-11-23 14:03:32 +01:00
keys = [ " inputs " , " group " , " name " , " algs " , " helpContent " ]
2015-08-22 14:29:41 +02:00
return { k : v for k , v in self . __dict__ . iteritems ( ) if k in keys }
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
def toJson ( self ) :
def todict ( o ) :
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
if isinstance ( o , QPointF ) :
2014-07-02 07:46:03 +02:00
return { " class " : " point " , " values " : { " x " : o . x ( ) , " y " : o . y ( ) } }
2014-06-08 00:21:12 +02:00
try :
d = o . todict ( )
return { " class " : o . __class__ . __module__ + " . " + o . __class__ . __name__ , " values " : d }
2015-08-22 14:29:41 +02:00
except Exception as e :
2014-06-08 00:21:12 +02:00
pass
2014-07-02 07:46:03 +02:00
return json . dumps ( self , default = todict , indent = 4 )
2014-06-08 00:21:12 +02:00
@staticmethod
def fromJson ( s ) :
2014-07-02 07:46:03 +02:00
def fromdict ( d ) :
2014-06-08 00:21:12 +02:00
try :
fullClassName = d [ " class " ]
tokens = fullClassName . split ( " . " )
className = tokens [ - 1 ]
moduleName = " . " . join ( tokens [ : - 1 ] )
values = d [ " values " ]
if className == " point " :
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
return QPointF ( values [ " x " ] , values [ " y " ] )
2014-06-08 00:21:12 +02:00
def _import ( name ) :
__import__ ( name )
return sys . modules [ name ]
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
2014-07-14 14:19:09 +02:00
if moduleName . startswith ( " processing.parameters " ) :
moduleName = " processing.core.parameters "
2014-06-08 00:21:12 +02:00
module = _import ( moduleName )
clazz = getattr ( module , className )
instance = clazz ( )
2015-08-22 14:29:41 +02:00
for k , v in values . iteritems ( ) :
2014-06-08 00:21:12 +02:00
instance . __dict__ [ k ] = v
return instance
except KeyError :
return d
2015-08-22 14:29:41 +02:00
except Exception as e :
2014-07-02 07:46:03 +02:00
raise e
2014-06-08 00:21:12 +02:00
try :
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
model = json . loads ( s , object_hook = fromdict )
2015-08-22 14:29:41 +02:00
except Exception as e :
2014-06-08 00:21:12 +02:00
raise WrongModelException ( e . args [ 0 ] )
return model
2014-07-02 07:46:03 +02:00
2014-06-08 00:21:12 +02:00
@staticmethod
2014-07-02 07:46:03 +02:00
def fromJsonFile ( filename ) :
2014-06-08 00:21:12 +02:00
with open ( filename ) as f :
2014-07-02 07:46:03 +02:00
s = f . read ( )
2014-06-08 00:21:12 +02:00
alg = ModelerAlgorithm . fromJson ( s )
alg . descriptionFile = filename
return alg
2014-07-02 07:46:03 +02:00
2014-08-22 11:27:57 +02:00
############LEGACY METHOD TO SUPPORT OLD FORMAT###########
LINE_BREAK_STRING = ' %% % '
@staticmethod
def fromFile ( filename ) :
try :
alg = ModelerAlgorithm . fromJsonFile ( filename )
return alg
2015-08-22 14:29:41 +02:00
except WrongModelException as e :
2014-08-22 11:27:57 +02:00
alg = ModelerAlgorithm . fromOldFormatFile ( filename )
return alg
@staticmethod
def fromOldFormatFile ( filename ) :
2014-10-07 11:58:17 +02:00
def _tr ( s ) :
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
return QCoreApplication . translate ( ' ModelerAlgorithm ' , s )
2014-08-22 11:27:57 +02:00
hardcodedValues = { }
modelParameters = [ ]
modelAlgs = [ ]
model = ModelerAlgorithm ( )
model . descriptionFile = filename
lines = codecs . open ( filename , ' r ' , encoding = ' utf-8 ' )
line = lines . readline ( ) . strip ( ' \n ' ) . strip ( ' \r ' )
try :
while line != ' ' :
if line . startswith ( ' PARAMETER: ' ) :
paramLine = line [ len ( ' PARAMETER: ' ) : ]
param = getParameterFromString ( paramLine )
if param :
pass
else :
2014-10-03 21:56:24 +03:00
raise WrongModelException (
2014-10-07 11:58:17 +02:00
_tr ( ' Error in parameter line: %s ' , ' ModelerAlgorithm ' ) % line )
2014-08-22 11:27:57 +02:00
line = lines . readline ( ) . strip ( ' \n ' )
tokens = line . split ( ' , ' )
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
model . addParameter ( ModelerParameter ( param ,
2015-08-22 14:29:41 +02:00
QPointF ( float ( tokens [ 0 ] ) , float ( tokens [ 1 ] ) ) ) )
2014-08-22 11:27:57 +02:00
modelParameters . append ( param . name )
elif line . startswith ( ' VALUE: ' ) :
valueLine = line [ len ( ' VALUE: ' ) : ]
tokens = valueLine . split ( ' === ' )
name = tokens [ 0 ]
value = tokens [ 1 ] . replace ( ModelerAlgorithm . LINE_BREAK_STRING , ' \n ' )
hardcodedValues [ name ] = value
elif line . startswith ( ' NAME: ' ) :
model . name = line [ len ( ' NAME: ' ) : ]
elif line . startswith ( ' GROUP: ' ) :
model . group = line [ len ( ' GROUP: ' ) : ]
elif line . startswith ( ' ALGORITHM: ' ) :
algLine = line [ len ( ' ALGORITHM: ' ) : ]
alg = ModelerUtils . getAlgorithm ( algLine )
if alg is not None :
modelAlg = Algorithm ( alg . commandLineName ( ) )
modelAlg . description = alg . name
posline = lines . readline ( ) . strip ( ' \n ' ) . strip ( ' \r ' )
tokens = posline . split ( ' , ' )
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
modelAlg . pos = QPointF ( float ( tokens [ 0 ] ) , float ( tokens [ 1 ] ) )
# dependenceline = lines.readline().strip('\n').strip('\r')
2014-08-22 11:27:57 +02:00
for param in alg . parameters :
if not param . hidden :
line = lines . readline ( ) . strip ( ' \n ' ) . strip ( ' \r ' )
2015-08-16 20:57:24 +02:00
if line == unicode ( None ) :
2015-08-22 14:29:41 +02:00
modelAlg . params [ param . name ] = None
2014-08-22 11:27:57 +02:00
else :
tokens = line . split ( ' | ' )
algIdx = int ( tokens [ 0 ] )
if algIdx == - 1 :
if tokens [ 1 ] in modelParameters :
modelAlg . params [ param . name ] = ValueFromInput ( tokens [ 1 ] )
else :
modelAlg . params [ param . name ] = hardcodedValues [ tokens [ 1 ] ]
else :
modelAlg . params [ param . name ] = ValueFromOutput ( algIdx , tokens [ 1 ] )
for out in alg . outputs :
if not out . hidden :
line = lines . readline ( ) . strip ( ' \n ' ) . strip ( ' \r ' )
2015-08-16 20:57:24 +02:00
if unicode ( None ) != line :
2014-08-22 11:27:57 +02:00
if ' | ' in line :
tokens = line . split ( ' | ' )
name = tokens [ 0 ]
tokens = tokens [ 1 ] . split ( ' , ' )
2015-08-22 14:29:41 +02:00
pos = QPointF ( float ( tokens [ 0 ] ) , float ( tokens [ 1 ] ) )
2014-08-22 11:27:57 +02:00
else :
name = line
pos = None
modelerOutput = ModelerOutput ( name )
modelerOutput . pos = pos
modelAlg . outputs [ out . name ] = modelerOutput
model . addAlgorithm ( modelAlg )
modelAlgs . append ( modelAlg . name )
else :
2014-10-03 21:56:24 +03:00
raise WrongModelException (
2014-10-07 11:58:17 +02:00
_tr ( ' Error in algorithm name: %s ' , ) % algLine )
2014-08-22 11:27:57 +02:00
line = lines . readline ( ) . strip ( ' \n ' ) . strip ( ' \r ' )
for modelAlg in model . algs . values ( ) :
for name , value in modelAlg . params . iteritems ( ) :
if isinstance ( value , ValueFromOutput ) :
value . alg = modelAlgs [ value . alg ]
return model
2015-08-22 14:29:41 +02:00
except Exception as e :
2014-08-22 11:27:57 +02:00
if isinstance ( e , WrongModelException ) :
raise e
else :
2014-10-07 11:58:17 +02:00
raise WrongModelException ( _tr ( ' Error in model definition line: ' ) + ' %s \n %s ' % ( line . strip ( ) , traceback . format_exc ( ) ) )