mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
350 lines
15 KiB
Python
350 lines
15 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
***************************************************************************
|
|
OTBAlgorithm.py
|
|
---------------------
|
|
Date : August 2012
|
|
Copyright : (C) 2012 by Victor Olaya
|
|
(C) 2013 by CS Systemes d'information (CS SI)
|
|
Email : volayaf at gmail dot com
|
|
otb at c-s dot fr (CS SI)
|
|
Contributors : Victor Olaya
|
|
Julien Malik (CS SI) - Changing the way to load algorithms first version
|
|
Oscar Picas (CS SI) - Changing the way to load algorithms
|
|
Alexia Mondot (CS SI) - Add hdf5 support
|
|
***************************************************************************
|
|
* *
|
|
* 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. *
|
|
* *
|
|
***************************************************************************
|
|
"""
|
|
|
|
__author__ = 'Victor Olaya'
|
|
__date__ = 'August 2012'
|
|
__copyright__ = '(C) 2012, Victor Olaya'
|
|
# This will get replaced with a git SHA1 when you do a git archive
|
|
__revision__ = '$Format:%H$'
|
|
|
|
import os
|
|
import re
|
|
import PyQt4.QtGui
|
|
from processing.core.GeoAlgorithm import GeoAlgorithm
|
|
from processing.parameters.ParameterMultipleInput import ParameterMultipleInput
|
|
from processing.parameters.ParameterRaster import ParameterRaster
|
|
from processing.parameters.ParameterVector import ParameterVector
|
|
from processing.parameters.ParameterBoolean import ParameterBoolean
|
|
from processing.parameters.ParameterSelection import ParameterSelection
|
|
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
|
from processing.core.ProcessingLog import ProcessingLog
|
|
from processing.core.WrongHelpFileException import WrongHelpFileException
|
|
from processing.parameters.ParameterFactory import ParameterFactory
|
|
from processing.outputs.OutputFactory import OutputFactory
|
|
from OTBUtils import OTBUtils
|
|
from processing.parameters.ParameterExtent import ParameterExtent
|
|
from processing.tools.system import *
|
|
import xml.etree.ElementTree as ET
|
|
import traceback
|
|
import inspect
|
|
|
|
class OTBAlgorithm(GeoAlgorithm):
|
|
|
|
REGION_OF_INTEREST = "ROI"
|
|
|
|
def __init__(self, descriptionfile):
|
|
GeoAlgorithm.__init__(self)
|
|
self.roiFile = None
|
|
self.descriptionFile = descriptionfile
|
|
self.defineCharacteristicsFromFile()
|
|
self.numExportedLayers = 0
|
|
self.hasROI = None;
|
|
|
|
|
|
def __str__(self):
|
|
return( "Algo : " + self.name + " from app : " + self.cliName + " in : " + self.group )
|
|
|
|
def getCopy(self):
|
|
newone = OTBAlgorithm(self.descriptionFile)
|
|
newone.provider = self.provider
|
|
return newone
|
|
|
|
def getIcon(self):
|
|
return PyQt4.QtGui.QIcon(os.path.dirname(__file__) + "/../../images/otb.png")
|
|
|
|
def help(self):
|
|
folder = os.path.join( OTBUtils.otbDescriptionPath(), 'doc' )
|
|
helpfile = os.path.join( str(folder), self.appkey + ".html")
|
|
if os.path.exists(helpfile):
|
|
return False, helpfile
|
|
else:
|
|
raise WrongHelpFileException("Could not find help file for this algorithm. \nIf you have it put it in: \n"+str(folder))
|
|
|
|
|
|
def adapt_list_to_string(self, c_list):
|
|
a_list = c_list[1:]
|
|
if a_list[0] in ["ParameterVector", "ParameterMultipleInput"]:
|
|
if c_list[0] == "ParameterType_InputImageList":
|
|
a_list[3] = 3
|
|
elif c_list[0] == "ParameterType_InputFilenameList":
|
|
a_list[3] = 4
|
|
else:
|
|
a_list[3] = -1
|
|
|
|
a_list[1] = "-%s" % a_list[1]
|
|
def mystr(par):
|
|
if type(par) == type([]):
|
|
return ";".join(par)
|
|
return str(par)
|
|
b_list = map(mystr, a_list)
|
|
res = "|".join(b_list)
|
|
return res
|
|
|
|
def get_list_from_node(self, myet):
|
|
all_params = []
|
|
for parameter in myet.iter('parameter'):
|
|
rebuild = []
|
|
par_type = parameter.find('parameter_type').text
|
|
key = parameter.find('key').text
|
|
name = parameter.find('name').text
|
|
source_par_type = parameter.find('parameter_type').attrib['source_parameter_type']
|
|
rebuild.append(source_par_type)
|
|
rebuild.append(par_type)
|
|
rebuild.append(key)
|
|
rebuild.append(name)
|
|
for each in parameter[4:]:
|
|
if not each.tag in ["hidden"]:
|
|
if len(list(each)) == 0:
|
|
rebuild.append(each.text)
|
|
else:
|
|
rebuild.append([item.text for item in each.iter('choice')])
|
|
all_params.append(rebuild)
|
|
return all_params
|
|
|
|
|
|
def defineCharacteristicsFromFile(self):
|
|
content = open(self.descriptionFile).read()
|
|
dom_model = ET.fromstring(content)
|
|
|
|
self.appkey = dom_model.find('key').text
|
|
self.cliName = dom_model.find('exec').text
|
|
self.name = dom_model.find('longname').text
|
|
self.group = dom_model.find('group').text
|
|
|
|
#ProcessingLog.addToLog(ProcessingLog.LOG_INFO, "Reading parameters for %s" % self.appkey)
|
|
|
|
rebu = None
|
|
the_result = None
|
|
|
|
try:
|
|
rebu = self.get_list_from_node(dom_model)
|
|
the_result = map(self.adapt_list_to_string,rebu)
|
|
except Exception, e:
|
|
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, "Could not open OTB algorithm: " + self.descriptionFile + "\n" + traceback.format_exc())
|
|
raise e
|
|
|
|
for line in the_result:
|
|
try:
|
|
if line.startswith("Parameter"):
|
|
param = ParameterFactory.getFromString(line)
|
|
# Hack for initializing the elevation parameters from Processing configuration
|
|
if param.name == "-elev.dem.path" or param.name == "-elev.dem" or "elev.dem" in param.name:
|
|
param.default = OTBUtils.otbSRTMPath()
|
|
elif param.name == "-elev.dem.geoid" or param.name == "-elev.geoid" or "elev.geoid" in param.name:
|
|
param.default = OTBUtils.otbGeoidPath()
|
|
self.addParameter(param)
|
|
elif line.startswith("*Parameter"):
|
|
param = ParameterFactory.getFromString(line[1:])
|
|
param.isAdvanced = True
|
|
self.addParameter(param)
|
|
elif line.startswith("Extent"):
|
|
self.addParameter(ParameterExtent(self.REGION_OF_INTEREST, "Region of interest", "0,1,0,1"))
|
|
self.hasROI = True
|
|
else:
|
|
self.addOutput(OutputFactory.getFromString(line))
|
|
except Exception,e:
|
|
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, "Could not open OTB algorithm: " + self.descriptionFile + "\n" + line)
|
|
raise e
|
|
|
|
|
|
|
|
def processAlgorithm(self, progress):
|
|
currentOs = os.name
|
|
|
|
path = OTBUtils.otbPath()
|
|
libpath = OTBUtils.otbLibPath()
|
|
if path == "" or libpath == "":
|
|
raise GeoAlgorithmExecutionException("OTB folder is not configured.\nPlease configure it before running OTB algorithms.")
|
|
|
|
commands = []
|
|
commands.append(path + os.sep + self.cliName)
|
|
|
|
self.roiVectors = {}
|
|
self.roiRasters = {}
|
|
for param in self.parameters:
|
|
# get the given input(s)
|
|
if param.name in ["-il", "-in"] :
|
|
newparams = ""
|
|
listeParameters = param.value.split(";")
|
|
for inputParameter in listeParameters :
|
|
# if HDF5 file
|
|
if "HDF5" in inputParameter :
|
|
if currentOs == "posix" :
|
|
data = inputParameter[6:]
|
|
else :
|
|
data = inputParameter[5:]
|
|
dataset = data
|
|
|
|
#on windows, there isn't "
|
|
#if data[-1] == '"':
|
|
if currentOs == "posix" :
|
|
data = data[:data.index('"')]
|
|
else :
|
|
data = data[:data.index('://')]
|
|
#try :
|
|
if currentOs == "posix" :
|
|
dataset.index('"')
|
|
dataset = os.path.basename( data ) + dataset[dataset.index('"'):]
|
|
#except ValueError :
|
|
else :
|
|
#dataset = os.path.basename( data ) + '"' + dataset[dataset.index('://'):]
|
|
dataset = dataset[dataset.index('://'):]
|
|
|
|
#get index of the subdataset with gdal
|
|
if currentOs == "posix" :
|
|
commandgdal = "gdalinfo " + data + " | grep '" + dataset + "$'"
|
|
else :
|
|
commandgdal = "gdalinfo " + data + " | findstr \"" + dataset + "$\""
|
|
resultGDAL = os.popen( commandgdal ).readlines()
|
|
indexSubdataset = -1
|
|
if resultGDAL :
|
|
indexSubdatasetString = re.search("SUBDATASET_(\d+)_", resultGDAL[0])
|
|
if indexSubdatasetString :
|
|
#match between ()
|
|
indexSubdataset = indexSubdatasetString.group(1)
|
|
else :
|
|
indexSubdataset = -1
|
|
else :
|
|
#print "Error : no match of ", dataset, "$ in gdalinfo " + data
|
|
indexSubdataset = -1
|
|
|
|
|
|
if not indexSubdataset == -1 :
|
|
indexSubdataset = int(indexSubdataset) -1
|
|
newParam = "\'" + data + "?&sdataidx=" + str(indexSubdataset) + "\'"
|
|
|
|
else :
|
|
newParam = inputParameter
|
|
|
|
newparams += newParam
|
|
# no hdf5
|
|
else :
|
|
newparams += inputParameter
|
|
newparams += ";"
|
|
if newparams[-1] == ";":
|
|
newparams = newparams[:-1]
|
|
param.value = newparams
|
|
|
|
if param.value == None or param.value == "":
|
|
continue
|
|
if isinstance(param, ParameterVector):
|
|
commands.append(param.name)
|
|
if self.hasROI:
|
|
roiFile = getTempFilename('shp')
|
|
commands.append(roiFile)
|
|
self.roiVectors[param.value] = roiFile
|
|
else:
|
|
commands.append("\"" + param.value+ "\"")
|
|
elif isinstance(param, ParameterRaster):
|
|
commands.append(param.name)
|
|
if self.hasROI:
|
|
roiFile = getTempFilename('tif')
|
|
commands.append(roiFile)
|
|
self.roiRasters[param.value] = roiFile
|
|
else:
|
|
commands.append("\"" + param.value+ "\"")
|
|
elif isinstance(param, ParameterMultipleInput):
|
|
commands.append(param.name)
|
|
files = str(param.value).split(";")
|
|
paramvalue = " ".join(["\"" + f + "\"" for f in files])
|
|
commands.append(paramvalue)
|
|
elif isinstance(param, ParameterSelection):
|
|
commands.append(param.name)
|
|
idx = int(param.value)
|
|
commands.append(str(param.options[idx]))
|
|
elif isinstance(param, ParameterBoolean):
|
|
if param.value:
|
|
commands.append(param.name)
|
|
commands.append(str(param.value).lower())
|
|
elif isinstance(param, ParameterExtent):
|
|
self.roiValues = param.value.split(",")
|
|
else:
|
|
commands.append(param.name)
|
|
commands.append(str(param.value))
|
|
|
|
for out in self.outputs:
|
|
commands.append(out.name)
|
|
commands.append('"' + out.value + '"')
|
|
for roiInput, roiFile in self.roiRasters.items():
|
|
startX, startY = float(self.roiValues[0]), float(self.roiValues[1])
|
|
sizeX = float(self.roiValues[2]) - startX
|
|
sizeY = float(self.roiValues[3]) - startY
|
|
helperCommands = [
|
|
"otbcli_ExtractROI",
|
|
"-in", roiInput,
|
|
"-out", roiFile,
|
|
"-startx", str(startX),
|
|
"-starty", str(startY),
|
|
"-sizex", str(sizeX),
|
|
"-sizey", str(sizeY)]
|
|
ProcessingLog.addToLog(ProcessingLog.LOG_INFO, helperCommands)
|
|
progress.setCommand(helperCommands)
|
|
OTBUtils.executeOtb(helperCommands, progress)
|
|
|
|
if self.roiRasters:
|
|
supportRaster = self.roiRasters.itervalues().next()
|
|
for roiInput, roiFile in self.roiVectors.items():
|
|
helperCommands = [
|
|
"otbcli_VectorDataExtractROIApplication",
|
|
"-vd.in", roiInput,
|
|
"-io.in", supportRaster,
|
|
"-io.out", roiFile,
|
|
"-elev.dem.path", OTBUtils.otbSRTMPath()]
|
|
ProcessingLog.addToLog(ProcessingLog.LOG_INFO, helperCommands)
|
|
progress.setCommand(helperCommands)
|
|
OTBUtils.executeOtb(helperCommands, progress)
|
|
|
|
loglines = []
|
|
loglines.append("OTB execution command")
|
|
for line in commands:
|
|
loglines.append(line)
|
|
progress.setCommand(line)
|
|
|
|
ProcessingLog.addToLog(ProcessingLog.LOG_INFO, loglines)
|
|
import processing.algs.otb.OTBSpecific_XMLLoading
|
|
module = processing.algs.otb.OTBSpecific_XMLLoading
|
|
|
|
found = False
|
|
if 'adapt%s' % self.appkey in dir(module):
|
|
found = True
|
|
commands = getattr(module, 'adapt%s' % self.appkey)(commands)
|
|
else:
|
|
the_key = 'adapt%s' % self.appkey
|
|
if '-' in the_key:
|
|
base_key = the_key.split("-")[0]
|
|
if base_key in dir(module):
|
|
found = True
|
|
commands = getattr(module, base_key)(commands)
|
|
|
|
if not found:
|
|
ProcessingLog.addToLog(ProcessingLog.LOG_INFO, "Adapter for %s not found" % the_key)
|
|
|
|
frames = inspect.getouterframes(inspect.currentframe())[1:]
|
|
for a_frame in frames:
|
|
frame,filename,line_number,function_name,lines,index = a_frame
|
|
ProcessingLog.addToLog(ProcessingLog.LOG_INFO, "%s %s %s %s %s %s" % (frame,filename,line_number,function_name,lines,index))
|
|
|
|
OTBUtils.executeOtb(commands, progress)
|