Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
added support for all gdal/ogr formats in all providers
added support for pre and post execution hooks
  • Loading branch information
volaya committed Jan 21, 2013
1 parent c58c9da commit 995ede3
Show file tree
Hide file tree
Showing 13 changed files with 188 additions and 40 deletions.
80 changes: 72 additions & 8 deletions python/plugins/sextante/core/GeoAlgorithm.py
Expand Up @@ -17,6 +17,9 @@
from sextante.outputs.OutputTable import OutputTable
from sextante.outputs.OutputHTML import OutputHTML
import copy
from sextante.core.SextanteVectorWriter import SextanteVectorWriter
from sextante.core.SextanteConfig import SextanteConfig
from sextante.gdal.GdalUtils import GdalUtils

class GeoAlgorithm:

Expand Down Expand Up @@ -103,18 +106,23 @@ def checkParameterValuesBeforeExecuting(self):
This check is called from the parameters dialog, and also when calling from the console'''
return None
#=========================================================



def execute(self, progress):
'''The method to use to call a SEXTANTE algorithm.
Although the body of the algorithm is in processAlgorithm(),
it should be called using this method, since it performs
some additional operations.
Raises a GeoAlgorithmExecutionException in case anything goes wrong.'''
self.setOutputCRSFromInputLayers()
self.resolveTemporaryOutputs()
self.checkOutputFileExtensions()

try:
self.processAlgorithm(progress)
self.setOutputCRSFromInputLayers()
self.resolveTemporaryOutputs()
self.checkOutputFileExtensions()
self.runPreExecutionScript(progress)
self.processAlgorithm(progress)
self.convertUnsupportedFormats(progress)
self.runPostExecutionScript(progress)
except GeoAlgorithmExecutionException, gaee:
SextanteLog.addToLog(SextanteLog.LOG_ERROR, gaee.msg)
raise gaee
Expand All @@ -132,6 +140,62 @@ def execute(self, progress):
SextanteLog.addToLog(SextanteLog.LOG_ERROR, lines)
raise GeoAlgorithmExecutionException(errstring)


def runPostExecutionScript(self, progress):
scriptFile = SextanteConfig.getSetting(SextanteConfig.POST_EXECUTION_SCRIPT)
self.runHookScript(scriptFile, progress);

def runPreExecutionScript(self, progress):
scriptFile = SextanteConfig.getSetting(SextanteConfig.PRE_EXECUTION_SCRIPT)
self.runHookScript(scriptFile, progress);

def runHookScript(self, filename, progress):
if not os.path.exists(filename):
return
try:
script = "import sextante\n"
ns = {}
ns['progress'] = progress
ns['alg'] = self
f = open(filename)
lines = f.readlines()
for line in lines:
script+=line
exec(script) in ns
except: # a wrong script should not cause problems, so we swallow all exceptions
pass

def convertUnsupportedFormats(self, progress):
i = 0
progress.setText("Converting outputs")
for out in self.outputs:
if isinstance(out, OutputVector):
if out.compatible is not None:
layer = QGisLayers.getObjectFromUri(out.compatible)
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):
if out.compatible is not None:
layer = QGisLayers.getObjectFromUri(out.compatible)
provider = layer.dataProvider()
writer = QgsRasterFileWriter(out.value)
format = self.getFormatShortNameFromFilename(out.value)
writer.setOutputFormat(format);
writer.writeRaster(layer.pipe(), layer.width(), layer.height(), layer.extent(), layer.crs())
progress.setPercentage(100 * i / float(len(self.outputs)))

def getFormatShortNameFromFilename(self, filename):
ext = filename[filename.rfind(".")+1:]
supported = GdalUtils.getSupportedRasters()
for name in supported.keys():
exts = supported[name]
if ext in exts:
return name
return "GTiff"

def checkOutputFileExtensions(self):
'''Checks if the values of outputs are correct and have one of the supported output extensions.
If not, it adds the first one of the supported extensions, which is assumed to be the default one'''
Expand All @@ -140,11 +204,11 @@ def checkOutputFileExtensions(self):
if not os.path.isabs(out.value):
continue
if isinstance(out, OutputRaster):
exts = self.provider.getSupportedOutputRasterLayerExtensions()
exts = QGisLayers.getSupportedOutputRasterLayerExtensions()
elif isinstance(out, OutputVector):
exts = self.provider.getSupportedOutputVectorLayerExtensions()
exts = QGisLayers.getSupportedOutputVectorLayerExtensions()
elif isinstance(out, OutputTable):
exts = self.provider.getSupportedOutputTableExtensions()
exts = QGisLayers.getSupportedOutputTableExtensions()
elif isinstance(out, OutputHTML):
exts =["html", "htm"]
else:
Expand Down
27 changes: 27 additions & 0 deletions python/plugins/sextante/core/QGisLayers.py
Expand Up @@ -16,6 +16,7 @@
* *
***************************************************************************
"""
from sextante.gdal.GdalUtils import GdalUtils

__author__ = 'Victor Olaya'
__date__ = 'August 2012'
Expand All @@ -37,6 +38,32 @@ class QGisLayers:
ALL_TYPES = -1
iface = None;

@staticmethod
def getSupportedOutputVectorLayerExtensions():
formats = QgsVectorFileWriter.supportedFiltersAndFormats()
exts = ["shp"]#shp is the default, should be the first
for extension in formats.keys():
extension = unicode(extension)
extension = extension[extension.find('*.') + 2:]
extension = extension[:extension.find(" ")]
if extension.lower() != "shp":
exts.append(extension)
return exts

@staticmethod
def getSupportedOutputRasterLayerExtensions():
allexts = ["tif"]
for exts in GdalUtils.getSupportedRasters().values():
for ext in exts:
if ext not in allexts:
allexts.append(ext)
return allexts

@staticmethod
def getSupportedOutputTableExtensions():
exts = ["dbf, csv"]
return exts

@staticmethod
def getRasterLayers():
layers = QGisLayers.iface.legendInterface().layers()
Expand Down
9 changes: 5 additions & 4 deletions python/plugins/sextante/core/Sextante.py
Expand Up @@ -257,7 +257,7 @@ def runAlgorithm(algOrName, onFinish, *args):
alghelp(algOrName)
return

alg = alg.getCopy()#copy.deepcopy(alg)
alg = alg.getCopy()
if isinstance(args, dict):
# set params by name
for name, value in args.items():
Expand Down Expand Up @@ -306,7 +306,7 @@ def runAlgorithm(algOrName, onFinish, *args):
def finish():
QApplication.restoreOverrideCursor()
if onFinish is not None:
onFinish(alg)
onFinish(alg, SilentProgress())
progress.close()
def error(msg):
QApplication.restoreOverrideCursor()
Expand All @@ -325,9 +325,10 @@ def cancel():
algEx.start()
algEx.wait()
else:
ret = UnthreadedAlgorithmExecutor.runalg(alg, SilentProgress())
progress = SilentProgress()
ret = UnthreadedAlgorithmExecutor.runalg(alg, progress)
if onFinish is not None and ret:
onFinish(alg)
onFinish(alg, progress)
QApplication.restoreOverrideCursor()
return alg

Expand Down
6 changes: 6 additions & 0 deletions python/plugins/sextante/core/SextanteConfig.py
Expand Up @@ -43,6 +43,8 @@ class SextanteConfig():
USE_THREADS = "USE_THREADS"
SHOW_DEBUG_IN_DIALOG = "SHOW_DEBUG_IN_DIALOG"
RECENT_ALGORITHMS = "RECENT_ALGORITHMS"
PRE_EXECUTION_SCRIPT = "PRE_EXECUTION_SCRIPT"
POST_EXECUTION_SCRIPT = "POST_EXECUTION_SCRIPT"

settings = {}
settingIcons= {}
Expand All @@ -65,7 +67,11 @@ def initialize():
SextanteConfig.addSetting(Setting("General", SextanteConfig.VECTOR_POINT_STYLE,"Style for point layers",""))
SextanteConfig.addSetting(Setting("General", SextanteConfig.VECTOR_LINE_STYLE,"Style for line layers",""))
SextanteConfig.addSetting(Setting("General", SextanteConfig.VECTOR_POLYGON_STYLE,"Style for polygon layers",""))
SextanteConfig.addSetting(Setting("General", SextanteConfig.VECTOR_POLYGON_STYLE,"Style for polygon layers",""))
SextanteConfig.addSetting(Setting("General", SextanteConfig.PRE_EXECUTION_SCRIPT,"Pre-execution script",""))
SextanteConfig.addSetting(Setting("General", SextanteConfig.POST_EXECUTION_SCRIPT,"Post-execution script",""))
SextanteConfig.addSetting(Setting("General", SextanteConfig.RECENT_ALGORITHMS,"Recent algs","", hidden=True))


@staticmethod
def setGroupIcon(group, icon):
Expand Down
6 changes: 4 additions & 2 deletions python/plugins/sextante/gdal/GdalOgrAlgorithmProvider.py
Expand Up @@ -100,5 +100,7 @@ def createAlgsList(self):
def getSupportedOutputRasterLayerExtensions(self):
return GdalUtils.getSupportedRasterExtensions()

def getSupportedOutputVectorLayerExtensions(self):
return ["shp", "sqlite"]
#===========================================================================
# def getSupportedOutputVectorLayerExtensions(self):
# return ["shp", "sqlite"]
#===========================================================================
6 changes: 4 additions & 2 deletions python/plugins/sextante/gdal/GdalUtils.py
Expand Up @@ -73,8 +73,10 @@ def getSupportedRasters():

shortName = str(QString(driver.ShortName).remove( QRegExp( '\(.*$' ) ).trimmed())
metadata = driver.GetMetadata()
if not metadata.has_key(gdal.DCAP_CREATE) or metadata[gdal.DCAP_CREATE] != 'YES':
continue
if metadata.has_key(gdal.DMD_EXTENSION):
extensions = metadata[gdal.DMD_EXTENSION].split("/")
extensions = metadata[gdal.DMD_EXTENSION].split("/")
if extensions:
GdalUtils.supportedRasters[shortName] = extensions

Expand All @@ -85,7 +87,7 @@ def getSupportedRasterExtensions():
allexts = ["tif"]
for exts in GdalUtils.getSupportedRasters().values():
for ext in exts:
if ext not in allexts:
if ext not in allexts and ext != "":
allexts.append(ext)
return allexts

Expand Down
4 changes: 2 additions & 2 deletions python/plugins/sextante/gui/AlgorithmExecutionDialog.py
Expand Up @@ -286,8 +286,8 @@ def accept(self):

@pyqtSlot()
def finish(self):
keepOpen = SextanteConfig.getSetting(SextanteConfig.KEEP_DIALOG_OPEN)
SextantePostprocessing.handleAlgorithmResults(self.alg, not keepOpen)
keepOpen = SextanteConfig.getSetting(SextanteConfig.KEEP_DIALOG_OPEN)
SextantePostprocessing.handleAlgorithmResults(self.alg, self, not keepOpen)
self.executed = True
self.setInfo("Algorithm %s finished" % self.alg.name)
QApplication.restoreOverrideCursor()
Expand Down
6 changes: 5 additions & 1 deletion python/plugins/sextante/gui/SextantePostprocessing.py
Expand Up @@ -38,9 +38,12 @@
class SextantePostprocessing:

@staticmethod
def handleAlgorithmResults(alg, showResults = True):
def handleAlgorithmResults(alg, progress, showResults = True):
htmlResults = False;
progress.setText("Loading resulting layers")
i = 0
for out in alg.outputs:
progress.setPercentage(100 * i / float(len(alg.outputs)))
if out.hidden or not out.open:
continue
if isinstance(out, (OutputRaster, OutputVector, OutputTable)):
Expand All @@ -59,6 +62,7 @@ def handleAlgorithmResults(alg, showResults = True):
elif isinstance(out, OutputHTML):
SextanteResults.addResult(out.description, out.value)
htmlResults = True
i += 1
if showResults and htmlResults:
QApplication.restoreOverrideCursor()
dlg = ResultsDialog()
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/sextante/gui/UnthreadedAlgorithmExecutor.py
Expand Up @@ -84,7 +84,7 @@ def runalgIterating(alg,paramToIter,progress):
progress.setText("Executing iteration " + str(i) + "/" + str(len(filelist)) + "...")
progress.setPercentage((i * 100) / len(filelist))
if UnthreadedAlgorithmExecutor.runalg(alg, SilentProgress()):
SextantePostprocessing.handleAlgorithmResults(alg, False)
SextantePostprocessing.handleAlgorithmResults(alg, progress, False)
i+=1
else:
return False;
Expand Down
19 changes: 17 additions & 2 deletions python/plugins/sextante/outputs/OutputRaster.py
Expand Up @@ -16,6 +16,7 @@
* *
***************************************************************************
"""
from sextante.core.QGisLayers import QGisLayers

__author__ = 'Victor Olaya'
__date__ = 'August 2012'
Expand All @@ -24,14 +25,28 @@
__revision__ = '$Format:%H$'

from sextante.outputs.Output import Output
from sextante.core.SextanteUtils import SextanteUtils

class OutputRaster(Output):


compatible = None

def getFileFilter(self, alg):
exts = alg.provider.getSupportedOutputRasterLayerExtensions()
exts = QGisLayers.getSupportedOutputRasterLayerExtensions()
for i in range(len(exts)):
exts[i] = exts[i].upper() + " files(*." + exts[i].lower() + ")"
return ";;".join(exts)

def getDefaultFileExtension(self, alg):
return alg.provider.getSupportedOutputRasterLayerExtensions()[0]

def getCompatibleFileName(self, alg):
'''Returns a filename that is compatible with the algorithm that is going to generate this output.
If the algorithm supports the file format of the current output value, it returns that value. If not,
it returns a temporary file with a supported file format, to be used to generate the output result.'''
if self.value.endswith(self.getDefaultFileExtension(alg)):
return self.value
else:
if self.compatible is None:
self.compatible = SextanteUtils.getTempFilename(self.getDefaultFileExtension(alg))
return self.compatible;
6 changes: 5 additions & 1 deletion python/plugins/sextante/outputs/OutputTable.py
Expand Up @@ -31,14 +31,18 @@
class OutputTable(Output):

def getFileFilter(self,alg):
exts = alg.provider.getSupportedOutputTableExtensions()
exts = ['csv']
for i in range(len(exts)):
exts[i] = exts[i].upper() + " files(*." + exts[i].lower() + ")"
return ";;".join(exts)

def getDefaultFileExtension(self, alg):
return alg.provider.getSupportedOutputTableExtensions()[0]

def getCompatibleFileName(self, alg):
#TODO!!!
return self.value

def getTableWriter(self, fields):
'''Returns a suitable writer to which records can be added as a
result of the algorithm. Use this to transparently handle output
Expand Down
25 changes: 21 additions & 4 deletions python/plugins/sextante/outputs/OutputVector.py
Expand Up @@ -16,6 +16,7 @@
* *
***************************************************************************
"""
from sextante.core.QGisLayers import QGisLayers

__author__ = 'Victor Olaya'
__date__ = 'August 2012'
Expand All @@ -24,23 +25,39 @@
__revision__ = '$Format:%H$'

from PyQt4.QtCore import *

from qgis.core import *
from sextante.outputs.Output import Output
from sextante.core.SextanteVectorWriter import SextanteVectorWriter
from sextante.core.SextanteUtils import SextanteUtils


class OutputVector(Output):

encoding = None
compatible = None

def getFileFilter(self,alg):
exts = alg.provider.getSupportedOutputVectorLayerExtensions()
def getFileFilter(self,alg):
exts = QGisLayers.getSupportedOutputRasterLayerExtensions()
for i in range(len(exts)):
exts[i] = exts[i].upper() + " files(*." + exts[i].lower() + ")"
return ";;".join(exts)


def getDefaultFileExtension(self, alg):
return alg.provider.getSupportedOutputVectorLayerExtensions()[0]


def getCompatibleFileName(self, alg):
'''Returns a filename that is compatible with the algorithm that is going to generate this output.
If the algorithm supports the file format of the current output value, it returns that value. If not,
it returns a temporary file with a supported file format, to be used to generate the output result.'''
if self.value.endswith(self.getDefaultFileExtension(alg)):
return self.value
else:
if self.compatible is None:
self.compatible = SextanteUtils.getTempFilename(self.getDefaultFileExtension(alg))
return self.compatible;


def getVectorWriter(self, fields, geomType, crs, options=None):
'''Returns a suitable writer to which features can be added as a
result of the algorithm. Use this to transparently handle output
Expand Down

0 comments on commit 995ede3

Please sign in to comment.