QGIS/python/plugins/processing/algs/otb/OTBAlgorithm.py

348 lines
15 KiB
Python
Raw Normal View History

2012-10-05 23:28:47 +02:00
# -*- coding: utf-8 -*-
"""
***************************************************************************
OTBAlgorithm.py
---------------------
Date : August 2012
Copyright : (C) 2012 by Victor Olaya
2014-01-17 19:39:17 +01:00
(C) 2013 by CS Systemes d'information (CS SI)
2012-10-05 23:28:47 +02:00
Email : volayaf at gmail dot com
2014-01-17 19:39:17 +01:00
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
2012-10-05 23:28:47 +02:00
***************************************************************************
* *
* 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$'
2012-09-15 18:25:25 +03:00
import os
2014-01-17 19:39:17 +01:00
import re
from PyQt4.QtCore import QCoreApplication
from PyQt4.QtGui import QIcon
2013-08-12 20:44:27 +02:00
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.parameters import ParameterMultipleInput
from processing.core.parameters import ParameterRaster
from processing.core.parameters import ParameterVector
from processing.core.parameters import ParameterBoolean
from processing.core.parameters import ParameterSelection
2014-01-17 19:39:17 +01:00
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.ProcessingLog import ProcessingLog
from processing.core.parameters import getParameterFromString
from processing.core.outputs import getOutputFromString
import OTBUtils
from processing.core.parameters import ParameterExtent
from processing.tools.system import getTempFilename
2014-01-17 19:39:17 +01:00
import xml.etree.ElementTree as ET
import traceback
pluginPath = os.path.normpath(os.path.join(
os.path.split(os.path.dirname(__file__))[0], os.pardir))
2012-09-15 18:25:25 +03:00
class OTBAlgorithm(GeoAlgorithm):
2014-01-17 19:39:17 +01:00
REGION_OF_INTEREST = "ROI"
2012-09-15 18:25:25 +03:00
def __init__(self, descriptionfile):
GeoAlgorithm.__init__(self)
self.roiFile = None
self.descriptionFile = descriptionfile
self.defineCharacteristicsFromFile()
self.numExportedLayers = 0
self.hasROI = None
2014-01-17 19:39:17 +01:00
def __str__(self):
return("Algo : " + self.name + " from app : " + self.cliName + " in : " + self.group)
2012-09-15 18:25:25 +03:00
def getCopy(self):
newone = OTBAlgorithm(self.descriptionFile)
newone.provider = self.provider
return newone
def getIcon(self):
return QIcon(os.path.join(pluginPath, 'images', 'otb.png'))
2012-09-15 18:25:25 +03:00
def help(self):
version = OTBUtils.getInstalledVersion()
folder = OTBUtils.compatibleDescriptionPath(version)
if folder is None:
return False, None
2016-01-13 18:30:08 +02:00
folder = os.path.join(folder, 'doc')
helpfile = os.path.join(unicode(folder), self.appkey + ".html")
if os.path.exists(helpfile):
return False, helpfile
else:
return False, None
2014-01-17 19:39:17 +01:00
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":
2014-04-19 22:04:24 +02:00
a_list[3] = 4
2014-01-17 19:39:17 +01:00
else:
a_list[3] = -1
a_list[1] = "-%s" % a_list[1]
b_list = map(lambda x: ";".join(x) if isinstance(x, list) else unicode(x), a_list)
2014-01-17 19:39:17 +01:00
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 each.tag not in ["hidden"]:
if len(list(each)) == 0:
2014-01-17 19:39:17 +01:00
rebuild.append(each.text)
else:
rebuild.append([item.text for item in each.iter('choice')])
all_params.append(rebuild)
return all_params
2012-09-15 18:25:25 +03:00
def defineCharacteristicsFromFile(self):
2014-01-17 19:39:17 +01:00
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.i18n_name = QCoreApplication.translate("OTBAlgorithm", self.name)
2014-01-17 19:39:17 +01:00
self.group = dom_model.find('group').text
self.i18n_group = QCoreApplication.translate("OTBAlgorithm", self.group)
2014-01-17 19:39:17 +01:00
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 as e:
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
self.tr('Could not open OTB algorithm: %s\n%s' % (self.descriptionFile, traceback.format_exc())))
2014-01-17 19:39:17 +01:00
raise e
for line in the_result:
2012-09-15 18:25:25 +03:00
try:
if line.startswith("Parameter") or line.startswith("*Parameter"):
if line.startswith("*Parameter"):
param = getParameterFromString(line[1:])
param.isAdvanced = True
2014-08-17 09:10:31 +02:00
else:
param = getParameterFromString(line)
2014-01-17 19:39:17 +01:00
# 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:
2012-09-15 18:25:25 +03:00
param.default = OTBUtils.otbSRTMPath()
2014-01-17 19:39:17 +01:00
elif param.name == "-elev.dem.geoid" or param.name == "-elev.geoid" or "elev.geoid" in param.name:
2012-09-15 18:25:25 +03:00
param.default = OTBUtils.otbGeoidPath()
self.addParameter(param)
2014-01-17 19:39:17 +01:00
elif line.startswith("Extent"):
self.addParameter(ParameterExtent(self.REGION_OF_INTEREST, "Region of interest", "0,1,0,1"))
2012-09-15 18:25:25 +03:00
self.hasROI = True
else:
self.addOutput(getOutputFromString(line))
except Exception as e:
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
self.tr('Could not open OTB algorithm: %s\n%s' % (self.descriptionFile, line)))
2012-09-15 18:25:25 +03:00
raise e
def processAlgorithm(self, progress):
2014-01-17 19:39:17 +01:00
currentOs = os.name
2012-09-15 18:25:25 +03:00
path = OTBUtils.otbPath()
commands = []
commands.append(path + os.sep + self.cliName)
self.roiVectors = {}
self.roiRasters = {}
for param in self.parameters:
2014-01-17 19:39:17 +01:00
# get the given input(s)
if param.name in ["-il", "-in"]:
2014-01-17 19:39:17 +01:00
newparams = ""
listeParameters = param.value.split(";")
for inputParameter in listeParameters:
2014-01-17 19:39:17 +01:00
# if HDF5 file
if "HDF5" in inputParameter:
if currentOs == "posix":
2014-01-17 19:39:17 +01:00
data = inputParameter[6:]
else:
2014-01-17 19:39:17 +01:00
data = inputParameter[5:]
dataset = data
2014-01-17 19:39:17 +01:00
#on windows, there isn't "
#if data[-1] == '"':
if currentOs == "posix":
2014-01-17 19:39:17 +01:00
data = data[:data.index('"')]
else:
2014-01-17 19:39:17 +01:00
data = data[:data.index('://')]
#try :
if currentOs == "posix":
2014-01-17 19:39:17 +01:00
dataset.index('"')
dataset = os.path.basename(data) + dataset[dataset.index('"'):]
2014-01-17 19:39:17 +01:00
#except ValueError :
else:
2014-01-17 19:39:17 +01:00
#dataset = os.path.basename( data ) + '"' + dataset[dataset.index('://'):]
dataset = dataset[dataset.index('://'):]
2014-01-17 19:39:17 +01:00
#get index of the subdataset with gdal
if currentOs == "posix":
2014-01-17 19:39:17 +01:00
commandgdal = "gdalinfo " + data + " | grep '" + dataset + "$'"
else:
2014-01-17 19:39:17 +01:00
commandgdal = "gdalinfo " + data + " | findstr \"" + dataset + "$\""
resultGDAL = os.popen(commandgdal).readlines()
2014-01-17 19:39:17 +01:00
indexSubdataset = -1
if resultGDAL:
2014-01-17 19:39:17 +01:00
indexSubdatasetString = re.search("SUBDATASET_(\d+)_", resultGDAL[0])
if indexSubdatasetString:
2014-01-17 19:39:17 +01:00
#match between ()
indexSubdataset = indexSubdatasetString.group(1)
else:
2014-01-17 19:39:17 +01:00
indexSubdataset = -1
else:
#print "Error : no match of ", dataset, "$ in gdalinfo " + data
2014-01-17 19:39:17 +01:00
indexSubdataset = -1
if not indexSubdataset == -1:
indexSubdataset = int(indexSubdataset) - 1
newParam = "\'" + data + "?&sdataidx=" + unicode(indexSubdataset) + "\'"
else:
2014-01-17 19:39:17 +01:00
newParam = inputParameter
2014-01-17 19:39:17 +01:00
newparams += newParam
# no hdf5
else:
2014-01-17 19:39:17 +01:00
newparams += inputParameter
newparams += ";"
if newparams[-1] == ";":
newparams = newparams[:-1]
param.value = newparams
if param.value is None or param.value == "":
2012-09-15 18:25:25 +03:00
continue
if isinstance(param, ParameterVector):
commands.append(param.name)
if self.hasROI:
2014-01-31 16:12:28 +01:00
roiFile = getTempFilename('shp')
2012-09-15 18:25:25 +03:00
commands.append(roiFile)
self.roiVectors[param.value] = roiFile
else:
commands.append("\"" + param.value + "\"")
2013-03-11 22:58:43 +01:00
elif isinstance(param, ParameterRaster):
2012-09-15 18:25:25 +03:00
commands.append(param.name)
if self.hasROI:
2014-01-31 16:12:28 +01:00
roiFile = getTempFilename('tif')
2012-09-15 18:25:25 +03:00
commands.append(roiFile)
self.roiRasters[param.value] = roiFile
else:
commands.append("\"" + param.value + "\"")
2012-09-15 18:25:25 +03:00
elif isinstance(param, ParameterMultipleInput):
commands.append(param.name)
files = unicode(param.value).split(";")
paramvalue = " ".join(["\"" + f + " \"" for f in files])
commands.append(paramvalue)
2012-09-15 18:25:25 +03:00
elif isinstance(param, ParameterSelection):
commands.append(param.name)
idx = int(param.value)
commands.append(unicode(param.options[idx]))
2012-09-15 18:25:25 +03:00
elif isinstance(param, ParameterBoolean):
if param.value:
commands.append(param.name)
commands.append(unicode(param.value).lower())
2012-09-15 18:25:25 +03:00
elif isinstance(param, ParameterExtent):
2014-01-17 19:39:17 +01:00
self.roiValues = param.value.split(",")
2012-09-15 18:25:25 +03:00
else:
commands.append(param.name)
commands.append(unicode(param.value))
2012-09-15 18:25:25 +03:00
for out in self.outputs:
commands.append(out.name)
commands.append('"' + out.value + '"')
2014-01-17 19:39:17 +01:00
for roiInput, roiFile in self.roiRasters.items():
startX, startY = float(self.roiValues[0]), float(self.roiValues[1])
2012-09-15 18:25:25 +03:00
sizeX = float(self.roiValues[2]) - startX
sizeY = float(self.roiValues[3]) - startY
helperCommands = [
"otbcli_ExtractROI",
"-in", roiInput,
"-out", roiFile,
"-startx", unicode(startX),
"-starty", unicode(startY),
"-sizex", unicode(sizeX),
"-sizey", unicode(sizeY)
]
2013-08-12 20:44:27 +02:00
ProcessingLog.addToLog(ProcessingLog.LOG_INFO, helperCommands)
2012-09-15 18:25:25 +03:00
progress.setCommand(helperCommands)
OTBUtils.executeOtb(helperCommands, progress)
if self.roiRasters:
supportRaster = self.roiRasters.itervalues().next()
2014-01-17 19:39:17 +01:00
for roiInput, roiFile in self.roiVectors.items():
2012-09-15 18:25:25 +03:00
helperCommands = [
"otbcli_VectorDataExtractROIApplication",
"-vd.in", roiInput,
"-io.in", supportRaster,
"-io.out", roiFile,
"-elev.dem.path", OTBUtils.otbSRTMPath()]
2013-08-12 20:44:27 +02:00
ProcessingLog.addToLog(ProcessingLog.LOG_INFO, helperCommands)
2012-09-15 18:25:25 +03:00
progress.setCommand(helperCommands)
OTBUtils.executeOtb(helperCommands, progress)
loglines = []
loglines.append(self.tr('OTB execution command'))
2012-09-15 18:25:25 +03:00
for line in commands:
loglines.append(line)
progress.setCommand(line)
2012-09-15 18:25:25 +03:00
2013-08-12 20:44:27 +02:00
ProcessingLog.addToLog(ProcessingLog.LOG_INFO, loglines)
import processing.algs.otb.OTBSpecific_XMLLoading
module = processing.algs.otb.OTBSpecific_XMLLoading
2014-01-17 19:39:17 +01:00
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,
self.tr("Adapter for %s not found" % the_key))
2012-12-10 00:12:07 +01:00
#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))
2012-09-15 18:25:25 +03:00
OTBUtils.executeOtb(commands, progress)