2019-01-08 17:38:42 +01:00
# -*- coding: utf-8 -*-
"""
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
OtbUtils . 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 , Oscar Picas ( CS SI ) - add functions to manage xml tree
Alexia Mondot ( CS SI ) - add a trick for OTBApplication SplitImages
Rashad Kanavath ( CS SI ) - re - integration of provider to QGIS
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
"""
from builtins import str
__author__ = ' Victor Olaya '
__date__ = ' August 2012 '
__copyright__ = ' (C) 2012, Victor Olaya '
import os
2019-03-06 04:54:21 +01:00
import sys
2019-01-08 17:38:42 +01:00
import re
import subprocess
from processing . core . ProcessingConfig import ProcessingConfig
from qgis . core import ( Qgis , QgsApplication , QgsMessageLog )
from qgis . PyQt . QtCore import QCoreApplication
2019-03-18 12:12:44 +01:00
2019-03-06 04:39:24 +01:00
class OtbUtils :
2019-03-06 04:54:21 +01:00
# Checkbox to enable/disable otb provider (bool).
ACTIVATE = " OTB_ACTIVATE "
# Path to otb installation folder (string, directory).
FOLDER = " OTB_FOLDER "
# Path to otb application folder. multiple paths are supported (string, directory).
APP_FOLDER = " OTB_APP_FOLDER "
# A string to hold current version number. Useful for bug reporting.
VERSION = " OTB_VERSION "
# Default directory were DEM tiles are stored. It should only contain ```.hgt`` or or georeferenced ``.tif`` files. Empty if not set (no directory set).
SRTM_FOLDER = " OTB_SRTM_FOLDER "
# Default path to the geoid file that will be used to retrieve height of DEM above ellipsoid. Empty if not set (no geoid set).
GEOID_FILE = " OTB_GEOID_FILE "
# Default maximum memory that OTB should use for processing, in MB. If not set, default value is 128 MB.
# This is set through environment variable ``OTB_MAX_RAM_HINT``
MAX_RAM_HINT = ' OTB_MAX_RAM_HINT '
# ``OTB_LOGGER_LEVEL``: Default level of logging for OTB. Should be one of ``DEBUG``, ``INFO``, ``WARNING``, ``CRITICAL`` or ``FATAL``, by increasing order of priority. Only messages with a higher priority than the level of logging will be displayed. If not set, default level is ``INFO``.
LOGGER_LEVEL = ' OTB_LOGGER_LEVEL '
@staticmethod
def settingNames ( ) :
return [
OtbUtils . ACTIVATE ,
OtbUtils . FOLDER ,
OtbUtils . SRTM_FOLDER ,
OtbUtils . GEOID_FILE ,
OtbUtils . LOGGER_LEVEL ,
OtbUtils . MAX_RAM_HINT
]
2019-03-06 04:39:24 +01:00
@staticmethod
def version ( ) :
2019-03-06 04:54:21 +01:00
return ProcessingConfig . getSetting ( OtbUtils . VERSION ) or ' 0.0.0 '
2019-03-06 04:39:24 +01:00
@staticmethod
def loggerLevel ( ) :
2019-03-06 04:54:21 +01:00
return ProcessingConfig . getSetting ( OtbUtils . LOGGER_LEVEL ) or ' INFO '
2019-03-06 04:39:24 +01:00
@staticmethod
def maxRAMHint ( ) :
2019-03-06 04:54:21 +01:00
return ProcessingConfig . getSetting ( OtbUtils . MAX_RAM_HINT ) or ' '
2019-03-06 04:39:24 +01:00
@staticmethod
def otbFolder ( ) :
2019-03-06 04:54:21 +01:00
if ProcessingConfig . getSetting ( OtbUtils . FOLDER ) :
return os . path . normpath ( os . sep . join ( re . split ( r ' \\ |/ ' , ProcessingConfig . getSetting ( OtbUtils . FOLDER ) ) ) )
2019-03-06 04:39:24 +01:00
else :
return None
@staticmethod
def appFolder ( ) :
2019-03-06 04:54:21 +01:00
app_folder = ProcessingConfig . getSetting ( OtbUtils . APP_FOLDER )
2019-03-06 04:39:24 +01:00
if app_folder :
return os . pathsep . join ( app_folder . split ( ' ; ' ) )
else :
return None
@staticmethod
def srtmFolder ( ) :
2019-03-06 04:54:21 +01:00
return ProcessingConfig . getSetting ( OtbUtils . SRTM_FOLDER ) or ' '
2019-03-06 04:39:24 +01:00
@staticmethod
def geoidFile ( ) :
2019-03-06 04:54:21 +01:00
return ProcessingConfig . getSetting ( OtbUtils . GEOID_FILE ) or ' '
2019-03-06 04:39:24 +01:00
@staticmethod
def getExecutableInPath ( path , exe ) :
ext = ' .exe ' if os . name == ' nt ' else ' '
return os . path . join ( path , ' bin ' , exe + ext )
@staticmethod
def getAuxiliaryDataDirectories ( ) :
gdal_data_dir = None
gtiff_csv_dir = None
otb_folder = OtbUtils . otbFolder ( )
if os . name == ' nt ' :
gdal_data_dir = os . path . join ( otb_folder , ' share ' , ' data ' )
gtiff_csv_dir = os . path . join ( otb_folder , ' share ' , ' epsg_csv ' )
else :
env_profile = os . path . join ( otb_folder , ' otbenv.profile ' )
try :
if os . path . exists ( env_profile ) :
with open ( env_profile ) as f :
lines = f . readlines ( )
lines = [ x . strip ( ) for x in lines ]
for line in lines :
if not line or line . startswith ( ' # ' ) :
continue
if ' GDAL_DATA= ' in line :
gdal_data_dir = line . split ( " GDAL_DATA= " ) [ 1 ]
if ' GEOTIFF_CSV= ' in line :
gtiff_csv_dir = line . split ( " GEOTIFF_CSV= " ) [ 1 ]
except BaseException as exc :
errmsg = " Cannot find gdal and geotiff data directory. " + str ( exc )
QgsMessageLog . logMessage ( errmsg , OtbUtils . tr ( ' Processing ' ) , Qgis . Info )
pass
return gdal_data_dir , gtiff_csv_dir
@staticmethod
def executeOtb ( commands , feedback , addToLog = True ) :
otb_env = {
' LC_NUMERIC ' : ' C ' ,
' GDAL_DRIVER_PATH ' : ' disable '
}
gdal_data_dir , gtiff_csv_dir = OtbUtils . getAuxiliaryDataDirectories ( )
if gdal_data_dir and os . path . exists ( gdal_data_dir ) :
otb_env [ ' GDAL_DATA ' ] = gdal_data_dir
if gtiff_csv_dir and os . path . exists ( gtiff_csv_dir ) :
otb_env [ ' GEOTIFF_CSV ' ] = gtiff_csv_dir
otb_env [ ' OTB_LOGGER_LEVEL ' ] = OtbUtils . loggerLevel ( )
max_ram_hint = OtbUtils . maxRAMHint ( )
if max_ram_hint and int ( max_ram_hint ) > 256 :
otb_env [ ' OTB_MAX_RAM_HINT ' ] = max_ram_hint
kw = { }
kw [ ' env ' ] = otb_env
if os . name == ' nt ' and sys . version_info > = ( 3 , 6 ) :
kw [ ' encoding ' ] = " cp {} " . format ( OtbUtils . getWindowsCodePage ( ) )
QgsMessageLog . logMessage ( " {} " . format ( kw ) , OtbUtils . tr ( ' Processing ' ) , Qgis . Info )
QgsMessageLog . logMessage ( " cmd= {} " . format ( commands ) , OtbUtils . tr ( ' Processing ' ) , Qgis . Info )
with subprocess . Popen (
commands ,
shell = True ,
stdout = subprocess . PIPE ,
stdin = subprocess . DEVNULL ,
stderr = subprocess . STDOUT ,
universal_newlines = True ,
* * kw
) as proc :
2019-01-08 17:38:42 +01:00
for line in iter ( proc . stdout . readline , ' ' ) :
line = line . strip ( )
#'* ]' and ' ]' says its some progress update
2019-03-06 04:39:24 +01:00
if ' % [ ' in line :
2019-01-08 17:38:42 +01:00
part = line . split ( ' : ' ) [ 1 ]
percent = part . split ( ' % ' ) [ 0 ]
try :
if int ( percent ) > = 100 :
2019-03-06 04:39:24 +01:00
feedback . pushConsoleInfo ( line )
2019-01-08 17:38:42 +01:00
feedback . setProgress ( int ( percent ) )
except :
pass
else :
2019-03-06 04:39:24 +01:00
if feedback is None :
QgsMessageLog . logMessage ( line , OtbUtils . tr ( ' Processing ' ) , Qgis . Info )
else :
2019-03-18 12:12:44 +01:00
if any ( [ l in line for l in [ ' (WARNING) ' , ' WARNING: ' ] ] ) :
feedback . reportError ( line , False )
elif any ( [ l in line for l in [ ' (FATAL) ' , ' ERROR: ' , ' ERROR ' ] ] ) :
feedback . reportError ( line , True )
2019-03-06 04:39:24 +01:00
else :
feedback . pushConsoleInfo ( line . strip ( ) )
@staticmethod
def getWindowsCodePage ( ) :
"""
Determines MS - Windows CMD . exe shell codepage .
Used into GRASS exec script under MS - Windows .
"""
from ctypes import cdll
return str ( cdll . kernel32 . GetACP ( ) )
@staticmethod
def tr ( string , context = ' ' ) :
if context == ' ' :
context = ' OtbUtils '
return QCoreApplication . translate ( context , string )