mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
git-svn-id: http://sextante.googlecode.com/svn/trunk/soft/bindings/qgis-plugin@43 881b9c09-3ef8-f3c2-ec3d-21d735c97f4d
376 lines
18 KiB
Python
376 lines
18 KiB
Python
import os
|
|
from qgis.core import *
|
|
from PyQt4.QtCore import *
|
|
from PyQt4.QtGui import *
|
|
from sextante.core.GeoAlgorithm import GeoAlgorithm
|
|
from sextante.saga.SagaBlackList import SagaBlackList
|
|
from sextante.saga.UnwrappableSagaAlgorithmException import UnwrappableSagaAlgorithmException
|
|
from sextante.parameters.ParameterTable import ParameterTable
|
|
from sextante.parameters.ParameterFixedTable import ParameterFixedTable
|
|
from sextante.parameters.ParameterTableField import ParameterTableField
|
|
from sextante.outputs.OutputTable import OutputTable
|
|
from sextante.parameters.ParameterMultipleInput import ParameterMultipleInput
|
|
from sextante.parameters.ParameterRaster import ParameterRaster
|
|
from sextante.outputs.OutputRaster import OutputRaster
|
|
from sextante.parameters.ParameterVector import ParameterVector
|
|
from sextante.parameters.ParameterNumber import ParameterNumber
|
|
from sextante.parameters.ParameterBoolean import ParameterBoolean
|
|
from sextante.parameters.ParameterString import ParameterString
|
|
from sextante.parameters.ParameterSelection import ParameterSelection
|
|
from sextante.core.SextanteUtils import SextanteUtils
|
|
|
|
from sextante.outputs.OutputVector import OutputVector
|
|
from sextante.saga.SagaUtils import SagaUtils
|
|
import time
|
|
from sextante.saga.SagaGroupNameDecorator import SagaGroupNameDecorator
|
|
from sextante.parameters.ParameterRange import ParameterRange
|
|
from sextante.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
|
from sextante.core.SextanteLog import SextanteLog
|
|
from sextante.parameters.ParameterFactory import ParameterFactory
|
|
from sextante.outputs.OutputFactory import OutputFactory
|
|
from sextante.core.SextanteConfig import SextanteConfig
|
|
|
|
class SagaAlgorithm(GeoAlgorithm):
|
|
|
|
def __init__(self, descriptionfile):
|
|
GeoAlgorithm.__init__(self)
|
|
self._descriptionFile = descriptionfile
|
|
self.defineCharacteristicsFromFile()
|
|
self.numExportedLayers = 0
|
|
self.resample = False #True if the user should define a grid system in
|
|
#case several non-matching raster layers are used as input
|
|
|
|
def getIcon(self):
|
|
return QIcon(os.path.dirname(__file__) + "/../images/saga.png")
|
|
|
|
def defineCharacteristicsFromFile(self):
|
|
lines = open(self._descriptionFile)
|
|
line = lines.readline().strip("\n").strip()
|
|
self.name = line
|
|
line = lines.readline().strip("\n").strip()
|
|
self.undecoratedGroup = line
|
|
self.group = SagaGroupNameDecorator.getDecoratedName(self.undecoratedGroup)
|
|
while line != "":
|
|
line = line.strip("\n").strip()
|
|
if line.startswith("Parameter"):
|
|
self.addParameter(ParameterFactory.getFromString(line))
|
|
elif line.startswith("Resample"):
|
|
self.resample = True
|
|
else:
|
|
self.addOutput(OutputFactory.getFromString(line))
|
|
line = lines.readline().strip("\n").strip()
|
|
lines.close()
|
|
|
|
|
|
def defineCharacteristicsFromFileSagaFormat(self):
|
|
|
|
lines = open(self._descriptionFile)
|
|
line = lines.readline()
|
|
while line != "":
|
|
line = line.strip("\n").strip()
|
|
readLine = True;
|
|
if line.startswith("library name"):
|
|
self.undecoratedGroup = line.split("\t")[1]
|
|
self.group = SagaGroupNameDecorator.getDecoratedName(self.undecoratedGroup)
|
|
if line.startswith("module name"):
|
|
self.name = line.split("\t")[1]
|
|
if line.startswith("-"):
|
|
try:
|
|
paramName = line[1:line.index(":")]
|
|
paramDescription = line[line.index(">") + 1:].strip()
|
|
except Exception: #boolean params have a different syntax
|
|
paramName = line[1:line.index("\t")]
|
|
paramDescription = line[line.index("\t") + 1:].strip()
|
|
if SagaBlackList.isBlackListed(self.name, self.undecoratedGroup):
|
|
raise UnwrappableSagaAlgorithmException()
|
|
line = lines.readline().lower()
|
|
if "data object" in line:
|
|
output = OutputRaster()
|
|
output.name = paramName
|
|
output.description = paramDescription
|
|
self.addOutput(output)
|
|
elif "file" in line:
|
|
param = ParameterString(paramName, paramDescription)
|
|
self.addParameter(param)
|
|
elif "table" in line:
|
|
#print(line)
|
|
if "input" in line:
|
|
param = ParameterTable(paramName, paramDescription, ("optional" in line))
|
|
lastParentParameterName = paramName;
|
|
self.addParameter(param)
|
|
elif "static" in line:
|
|
print (self.name)
|
|
line = lines.readline().strip("\n").strip()
|
|
numCols = int(line.split(" ")[0])
|
|
colNames = [];
|
|
for i in range(numCols):
|
|
line = lines.readline().strip("\n").strip()
|
|
colNames.append(line.split("]")[1])
|
|
param = ParameterFixedTable(paramName, paramDescription, colNames, 3, False)
|
|
self.addParameter(param)
|
|
elif "field" in line:
|
|
if lastParentParameterName == None:
|
|
raise UnwrappableSagaAlgorithmException();
|
|
param = ParameterTableField(paramName, paramDescription, lastParentParameterName)
|
|
self.addParameter(param)
|
|
else:
|
|
output = OutputTable()
|
|
output.name = paramName
|
|
output.description = paramDescription
|
|
self.addOutput(output)
|
|
elif "grid" in line:
|
|
if "input" in line:
|
|
if "list" in line:
|
|
param = ParameterMultipleInput(paramName, paramDescription, ParameterMultipleInput.TYPE_RASTER,("optional" in line))
|
|
self.addParameter(param)
|
|
else:
|
|
param = ParameterRaster(paramName, paramDescription,("optional" in line))
|
|
self.addParameter(param)
|
|
else:
|
|
output = OutputRaster()
|
|
output.name = paramName
|
|
output.description = paramDescription
|
|
self.addOutput(output)
|
|
elif "shapes" in line:
|
|
if "input" in line:
|
|
if "list" in line:
|
|
param = ParameterMultipleInput(paramName, paramDescription, ParameterMultipleInput.TYPE_VECTOR_ANY,("optional" in line))
|
|
self.addParameter(param)
|
|
else:
|
|
param = ParameterVector(paramName, paramDescription,ParameterVector.VECTOR_TYPE_ANY,("optional" in line))
|
|
lastParentParameterName = paramName;
|
|
self.addParameter(param)
|
|
else:
|
|
output = OutputVector()
|
|
output.name = paramName
|
|
output.description = paramDescription
|
|
self.addOutput(output)
|
|
elif "floating" in line or "integer" in line or "degree" in line:
|
|
param = ParameterNumber(paramName, paramDescription,)
|
|
self.addParameter(param)
|
|
elif "boolean" in line:
|
|
param = ParameterBoolean(paramName,paramDescription)
|
|
self.addParameter(param)
|
|
elif "text" in line:
|
|
param = ParameterString(paramName, paramDescription)
|
|
self.addParameter(param)
|
|
elif "range" in line:
|
|
param = ParameterRange(paramName, paramDescription)
|
|
self.addParameter(param)
|
|
elif "choice" in line:
|
|
line = lines.readline()
|
|
line = lines.readline().strip("\n").strip()
|
|
options = list()
|
|
while line != "" and not (line.startswith("-")):
|
|
options.append(line);
|
|
line = lines.readline().strip("\n").strip()
|
|
param = ParameterSelection(paramName, paramDescription, options)
|
|
self.addParameter(param)
|
|
if line == "":
|
|
break
|
|
else:
|
|
readLine = False
|
|
if readLine:
|
|
line = lines.readline()
|
|
lines.close()
|
|
|
|
|
|
def calculateResamplingExtent(self):
|
|
auto = SextanteConfig.getSetting(SagaUtils.SAGA_AUTO_RESAMPLING)
|
|
if auto:
|
|
first = True;
|
|
for param in self.parameters:
|
|
if isinstance(param, ParameterRaster):
|
|
if isinstance(param.value, QgsRasterLayer):
|
|
value = param.value
|
|
else:
|
|
value = QGisLayers.getObjectFromUri(param.value)
|
|
if first:
|
|
self.xmin = value.extent().xMinimum()
|
|
self.xmax = value.extent().xMaximum()
|
|
self.ymin = value.extent().yMinimum()
|
|
self.ymax = value.extent().yMaximum()
|
|
self.cellsize = (value.extent().xMaximum() - value.extent().xMinimum())/value.getRasterXDim()
|
|
first = False
|
|
else:
|
|
self.xmin = min(self.xmin, value.extent().xMinimum())
|
|
self.xmax = max(self.xmax, value.extent().xMaximum())
|
|
self.ymin = min(self.ymin, value.extent().yMinimum())
|
|
self.ymax = max(self.ymax, value.extent().yMaximum())
|
|
self.cellsize = max(self.cellsize, (value.extent().xMaximum() - value.extent().xMinimum())/value.getRasterXDim())
|
|
else:
|
|
self.xmin = SextanteConfig.getSetting(SagaUtils.SAGA_RESAMPLING_REGION_XMIN)
|
|
self.xmax = SextanteConfig.getSetting(SagaUtils.SAGA_RESAMPLING_REGION_XMAX)
|
|
self.ymin = SextanteConfig.getSetting(SagaUtils.SAGA_RESAMPLING_REGION_YMIN)
|
|
self.ymax = SextanteConfig.getSetting(SagaUtils.SAGA_RESAMPLING_REGION_YMAX)
|
|
self.cellsize = SextanteConfig.getSetting(SagaUtils.SAGA_RESAMPLING_REGION_CELLSIZE)
|
|
|
|
|
|
|
|
def processAlgorithm(self, progress):
|
|
|
|
path = SagaUtils.sagaPath()
|
|
if path == "":
|
|
raise GeoAlgorithmExecutionException("SAGA folder is not configured.\nPlease configure it before running SAGA algorithms.")
|
|
commands = list()
|
|
self.exportedLayers = {}
|
|
self.numExportedLayers = 0;
|
|
|
|
#1: Export rasters to sgrd. only ASC and TIF are supported.
|
|
# Vector layers must be in shapefile format and tables in dbf format. We check that.
|
|
if self.resample:
|
|
self.calculateResamplingExtent()
|
|
for param in self.parameters:
|
|
if isinstance(param, ParameterRaster):
|
|
if param.value == None:
|
|
continue
|
|
if isinstance(param.value, QgsRasterLayer):
|
|
value = str(param.value.dataProvider().dataSourceUri())
|
|
else:
|
|
value = param.value
|
|
if not value.endswith("sgrd"):
|
|
commands.append(self.exportRasterLayer(value))
|
|
if self.resample:
|
|
commands.append(self.resampleRasterLayer(value));
|
|
if isinstance(param, ParameterVector):
|
|
if param.value == None:
|
|
continue
|
|
if isinstance(param.value, QgsVectorLayer):
|
|
value = str(param.value.dataProvider().dataSourceUri())
|
|
else:
|
|
value = param.value
|
|
if not value.endswith("shp"):
|
|
raise GeoAlgorithmExecutionException("Unsupported file format")
|
|
if isinstance(param, ParameterTable):
|
|
if param.value == None:
|
|
continue
|
|
if isinstance(param.value, QgsVectorLayer):
|
|
value = str(param.value.dataProvider().dataSourceUri())
|
|
else:
|
|
value = param.value
|
|
if value.endswith("shp"):
|
|
value = value[:-3] + "dbf"
|
|
if not value.endswith("dbf"):
|
|
raise GeoAlgorithmExecutionException("Unsupported file format")
|
|
if isinstance(param, ParameterMultipleInput):
|
|
if param.value == None:
|
|
continue
|
|
layers = param.value.split(";")
|
|
if layers == None or len(layers) == 0:
|
|
continue
|
|
if param.datatype == ParameterMultipleInput.TYPE_RASTER:
|
|
for layer in layers:
|
|
if not layer.endswith("sgrd"):
|
|
commands.append(self.exportRasterLayer(layer))
|
|
if self.resample:
|
|
commands.append(self.resampleRasterLayer(layer));
|
|
elif param.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY:
|
|
for layer in layers:
|
|
if not layer.endswith("shp"):
|
|
raise GeoAlgorithmExecutionException("Unsupported file format")
|
|
|
|
#2: set parameters and outputs
|
|
command = self.undecoratedGroup + " \"" + self.name + "\""
|
|
for param in self.parameters:
|
|
if param.value == None:
|
|
continue
|
|
if isinstance(param, ParameterRaster):
|
|
value = param.value
|
|
if value in self.exportedLayers.keys():
|
|
command+=(" -" + param.name + " " + self.exportedLayers[value])
|
|
else:
|
|
command+=(" -" + param.name + " " + value)
|
|
elif isinstance(param, ParameterMultipleInput):
|
|
s = param.value
|
|
for layer in self.exportedLayers.keys():
|
|
if layer in self.exportedLayers.keys():
|
|
s = s.replace(layer, self.exportedLayers[layer])
|
|
command+=(" -" + param.name + " " + s);
|
|
elif isinstance(param, ParameterBoolean):
|
|
if param.value:
|
|
command+=(" -" + param.name);
|
|
else:
|
|
command+=(" -" + param.name + " " + str(param.value));
|
|
|
|
|
|
for out in self.outputs:
|
|
if isinstance(out, OutputRaster):
|
|
filename = out.value
|
|
if not filename.endswith(".asc") and not filename.endswith(".tif"):
|
|
filename += ".tif"
|
|
out.value = filename
|
|
filename = SextanteUtils.tempFolder() + os.sep + os.path.basename(filename) + ".sgrd"
|
|
command+=(" -" + out.name + " " + filename);
|
|
if isinstance(out, OutputVector):
|
|
filename = out.value
|
|
if not filename.endswith(".shp"):
|
|
filename += ".shp"
|
|
out.value = filename
|
|
command+=(" -" + out.name + " " + filename);
|
|
if isinstance(out, OutputTable):
|
|
filename = out.value
|
|
if not filename.endswith(".dbf"):
|
|
filename += ".dbf"
|
|
out.value = filename
|
|
command+=(" -" + out.name + " " + filename);
|
|
|
|
commands.append(command)
|
|
|
|
#3:Export resulting raster layers
|
|
for out in self.outputs:
|
|
if isinstance(out, OutputRaster):
|
|
filename = out.value
|
|
filename2 = SextanteUtils.tempFolder() + os.sep + os.path.basename(filename) + ".sgrd"
|
|
if filename.endswith("asc"):
|
|
commands.append("io_grid 0 -GRID " + filename2 + " -FORMAT 1 -FILE " + filename);
|
|
else:
|
|
commands.append("io_gdal 1 -GRIDS " + filename2 + " -FORMAT 1 -TYPE 0 -FILE " + filename);
|
|
|
|
#4 Run SAGA
|
|
SagaUtils.createSagaBatchJobFileFromSagaCommands(commands)
|
|
loglines = []
|
|
loglines.append("SAGA execution commands")
|
|
for line in commands:
|
|
loglines.append(line)
|
|
SextanteLog.addToLog(SextanteLog.LOG_INFO, loglines)
|
|
SagaUtils.executeSaga(progress);
|
|
|
|
|
|
def resampleRasterLayer(self,layer):
|
|
if layer in self.exportedLayers.keys:
|
|
inputFilename = self.exportedLayers[layer]
|
|
else:
|
|
inputFilename = layer
|
|
destFilename = self.getTempFilename()
|
|
self.exportedLayers[layer]= destFilename
|
|
s = "grid_tools \"Resampling\" -INPUT " + inputFilename + "-TARGET 0 -SCALE_UP_METHOD 4 -SCALE_DOWN_METHOD 4 -USER_XMIN " +\
|
|
self.xmin + " -USER_XMAX " + self.xmax + " -USER_YMIN " + self.ymin + " -USER_YMAX " + self.ymax +\
|
|
" -USER_SIZE " + str(self.cellsize) + " -USER_GRID " + destFilename
|
|
return s
|
|
|
|
def exportRasterLayer(self,layer):
|
|
#=======================================================================
|
|
# if not layer.lower().endswith("tif") and not layer.lower().endswith("asc"):
|
|
# raise GeoAlgorithmExecutionException("Unsupported input file format: " + layer)
|
|
#=======================================================================
|
|
#ext = os.path.splitext(layer)[1][1:].strip()
|
|
destFilename = self.getTempFilename()
|
|
self.exportedLayers[layer]= destFilename
|
|
#=======================================================================
|
|
# if ext.lower() == "tif":
|
|
# return "io_grid_image 1 -OUT_GRID " + destFilename + " -FILE " + layer + " -METHOD 0"
|
|
# else:
|
|
#=======================================================================
|
|
return "io_gdal 0 -GRIDS " + destFilename + " -FILES " + layer
|
|
|
|
|
|
def getTempFilename(self):
|
|
self.numExportedLayers+=1
|
|
path = SextanteUtils.tempFolder()
|
|
filename = path + os.sep + str(time.time()) + str(SextanteUtils.NUM_EXPORTED) + ".sgrd"
|
|
SextanteUtils.NUM_EXPORTED +=1
|
|
|
|
return filename
|
|
|
|
|