Commit 6b0bc30f authored by Rashad Kanavath's avatar Rashad Kanavath

fix otb app path, wrapper_script on windows, linux

parent fd496f7d
......@@ -39,7 +39,8 @@ You can see OTB under "Providers".
* Expand OTB tab
* Tick Activate option
* Set OTB folder entry. This is location of your OTB installation.
* Set OTB folder. This is location of your OTB installation.
* Set OTB application folder. This is location of your OTB applications. `<OTB_FOLDER>/lib/otb/applications`
* Click "ok" to save settings and close dialog. If settings are correct, you will have OTB algorithms loaded in Processing toolbox
#### OTB settings in QGIS Processing
......@@ -52,13 +53,11 @@ This is the directory where OTB is available. Valid values are list below.
* OTB build folder (for source builds),
* Folder in which OTB is installed using `make install`, package managers or official binary packages
##### OTB application folder (optional)
##### OTB application folder
This is the location(s) of additional OTB applications.
Multiple paths are allowed to use custom/proprietary OTB applications.
This value is empty by default. `<OTB_FOLDER>/lib/otb/applications` is added automatically by OTB provider.
##### Geoid file (optional)
Path to geoid file.
......
......@@ -28,6 +28,7 @@ __copyright__ = '(C) 2018 by CNES'
__revision__ = '$Format:%H$'
import os
import re
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (Qgis, QgsApplication, QgsProcessingProvider, QgsMessageLog)
......@@ -56,7 +57,7 @@ class OTBAlgorithmProvider(QgsProcessingProvider):
def canBeActivated(self):
if not self.isActive():
return False
folder = ProcessingConfig.getSetting(OTBUtils.FOLDER)
folder = OTBUtils.otbFolder()
if folder and os.path.exists(folder):
if os.path.isfile(self.algsFile(folder)):
return True
......@@ -67,16 +68,23 @@ class OTBAlgorithmProvider(QgsProcessingProvider):
def check_app_folder(self, v):
if not self.isActive():
return
if not v:
self.setActive(False)
raise ValueError(self.tr('Cannot activate OTB provider'))
return
folder = OTBUtils.otbFolder()
otb_app_dirs = self.otb_app_dir_list(v, folder)
if len(otb_app_dirs) == 1:
utils.iface.messageBar().pushInfo("OTB", "OTB applications folder set to default: '{}'".format(otb_app_dirs[0]))
otb_app_dirs = self.otb_app_dir_list(v)
if len(otb_app_dirs) < 1:
self.setActive(False)
raise ValueError(self.tr("Invalid path given for 'OTB application folder'. OTB provider will be disabled"))
#isValid is True if there is atleast one valid otb application is given path
isValid = False
descr_folder = self.descrFolder(folder)
for app_dir in otb_app_dirs:
if not os.path.exists(app_dir):
continue
for otb_app in os.listdir(app_dir):
if not otb_app.startswith('otbapp_') or \
'TestApplication' in otb_app or \
......@@ -94,52 +102,34 @@ class OTBAlgorithmProvider(QgsProcessingProvider):
OTBUtils.executeOtb(commands, feedback=None)
if isValid:
otb_app_path_env = os.pathsep.join(otb_app_dirs)
env_profile = os.path.join(folder, 'otbenv.profile')
if os.name == 'nt':
env_profile = os.path.join(folder, 'otbenv.bat')
if os.path.exists(env_profile) and os.path.isfile(env_profile):
self.write_otbcli_wrapper_script(folder, otb_app_path_env)
utils.iface.messageBar().pushInfo("OTB", "OTB provider is activated from '{}'.".format(folder))
else:
self.setActive(False)
raise ValueError(self.tr("No OTB algorithms found in '{}'. OTB will be disabled".format(','.join(otb_app_dirs))))
def normalize_path(self, p):
# https://stackoverflow.com/a/20713238/1003090
return os.path.normpath(os.sep.join(re.split(r'\\|/', p)))
def check_otb_folder(self, v):
if not self.isActive():
return
if not v or not os.path.exists(v):
return
if not os.path.exists(os.path.join(v,'bin', otb_exe_file('otbApplicationLauncherCommandLine'))):
path = self.normalize_path(v)
if not os.path.exists(os.path.join(path,'bin', otb_exe_file('otbApplicationLauncherCommandLine'))):
self.setActive(False)
raise ValueError(self.tr("Cannot find '{}'. OTB will be disabled".format(os.path.join(v,'bin', otb_exe_file('otbApplicationLauncherCommandLine')))))
env_profile = os.path.join(v, 'otbenv.profile')
cli_filepath = os.path.join(QgsApplication.qgisSettingsDirPath(), 'processing', 'qgis_otb_cli')
if os.name == 'nt':
env_profile = os.path.join(v, 'otbenv.bat')
cli_filepath = os.path.join(QgsApplication.qgisSettingsDirPath(), 'processing', 'qgis_otb_cli.bat')
if os.path.isfile(env_profile):
if not os.path.exists(cli_filepath) or not os.path.isfile(cli_filepath):
self.write_otbcli_wrapper_script(v)
# if OTBUtils.appFolder() is None:
# ProcessingConfig.setSettingValue(OTBUtils.APP_FOLDER, os.path.join(v, 'lib', 'otb', 'applications'))
def write_otbcli_wrapper_script(self, otb_install_dir):
app_vargs = " $@"
export_cmd = 'export '
first_line = '#!/bin/sh'
env_profile = os.path.join(otb_install_dir, 'otbenv.profile')
otb_app_launcher = os.path.join(otb_install_dir, 'bin', 'otbApplicationLauncherCommandLine')
cli_filepath = os.path.join(QgsApplication.qgisSettingsDirPath(), 'processing', 'qgis_otb_cli')
lines = None
def write_otbcli_wrapper_script(self, otb_install_dir, otb_app_path_env):
gdal_data_dir = None
geotiff_csv_dir = None
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
if 'GEOTIFF_CSV='in line:
geotiff_csv_dir = line
if os.name == 'nt':
app_vargs = " %*"
export_cmd = 'SET '
......@@ -148,14 +138,32 @@ class OTBAlgorithmProvider(QgsProcessingProvider):
cli_filepath = os.path.join(QgsApplication.qgisSettingsDirPath(), 'processing', 'qgis_otb_cli.bat')
gdal_data_dir = os.path.join(otb_install_dir, 'share' , 'data')
geotiff_csv_dir = os.path.join(otb_install_dir, 'share' , 'epsg_csv')
else:
app_vargs = " $@"
export_cmd = 'export '
first_line = '#!/bin/sh'
otb_app_launcher = os.path.join(otb_install_dir, 'bin', 'otbApplicationLauncherCommandLine')
cli_filepath = os.path.join(QgsApplication.qgisSettingsDirPath(), 'processing', 'qgis_otb_cli')
lines = None
env_profile = os.path.join(otb_install_dir, 'otbenv.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:
geotiff_csv_dir = line.split("GEOTIFF_CSV=")[1]
with open(cli_filepath, 'w') as otb_cli_file:
otb_cli_file.write(first_line + os.linesep)
otb_cli_file.write(export_cmd + "LC_NUMERIC=C" + os.linesep)
otb_cli_file.write(export_cmd + "GDAL_DRIVER_PATH=disable" + os.linesep)
otb_cli_file.write(export_cmd + "GDAL_DATA=\"" + gdal_data_dir + "\"" + os.linesep)
otb_cli_file.write(export_cmd + "GEOTIFF_CSV=\"" + geotiff_csv_dir + "\"" + os.linesep)
otb_cli_file.write(export_cmd + "OTB_APPLICATION_PATH=\"" + OTBUtils.appFolder() + "\"" + os.linesep)
otb_cli_file.write(export_cmd + "\"GDAL_DATA=" + gdal_data_dir + "\"" + os.linesep)
otb_cli_file.write(export_cmd + "\"GEOTIFF_CSV=" + geotiff_csv_dir + "\"" + os.linesep)
otb_cli_file.write(export_cmd + "\"OTB_APPLICATION_PATH=" + otb_app_path_env + "\"" + os.linesep)
otb_cli_file.write("\"" + otb_app_launcher + "\"" + app_vargs + os.linesep)
if not os.name == 'nt':
......@@ -175,7 +183,7 @@ class OTBAlgorithmProvider(QgsProcessingProvider):
,validator=self.check_otb_folder
))
ProcessingConfig.addSetting(Setting(group, OTBUtils.APP_FOLDER,
self.tr("OTB application folder (optional)"),
self.tr("OTB application folder"),
OTBUtils.appFolder()
,valuetype=Setting.MULTIPLE_FOLDERS
,validator=self.check_app_folder
......@@ -250,7 +258,7 @@ class OTBAlgorithmProvider(QgsProcessingProvider):
if 'OTB Version:' in vline:
self.version = vline.split(':')[1].strip()
QgsMessageLog.logMessage(self.tr("Loading OTB '{}'.".format(self.version)), self.tr('Processing'), Qgis.Info)
QgsMessageLog.logMessage(self.tr("Loading OTB '{}'.".format(self.version)), self.tr('Processing'), Qgis.Info)
self.algs = self.createAlgsList()
for a in self.algs:
self.addAlgorithm(a)
......@@ -258,21 +266,24 @@ class OTBAlgorithmProvider(QgsProcessingProvider):
folder = OTBUtils.otbFolder()
cli_ext = ''
env_profile = os.path.join(folder, 'otbenv.profile')
if os.name == 'nt':
cli_ext = '.bat'
if os.path.isfile(os.path.join(folder, 'otbenv.profile')):
env_profile = os.path.join(folder, 'otbenv.bat')
if os.path.exists(env_profile) and os.path.isfile(env_profile):
OTBUtils.OTB_CLI_FILE = os.path.join(QgsApplication.qgisSettingsDirPath(), 'processing', 'qgis_otb_cli' + cli_ext)
else:
OTBUtils.OTB_CLI_FILE = os.path.join(folder, 'bin', 'otbcli' + cli_ext)
#print('Using OTBUtils.OTB_CLI_FILE=',OTBUtils.OTB_CLI_FILE)
QgsMessageLog.logMessage(self.tr("Using otbcli: '{}'.".format(OTBUtils.OTB_CLI_FILE)), self.tr('Processing'), Qgis.Info)
def algsFile(self, d):
return os.path.join(self.descrFolder(d), 'algs.txt')
def descrFolder(self, d):
#!hack for 6.6!#
if self.version == '6.6.0':
if os.path.exists(os.path.join(d, 'description')):
return os.path.join(d, 'description')
else:
return os.path.join(d, 'share', 'otb', 'description')
......@@ -280,15 +291,12 @@ class OTBAlgorithmProvider(QgsProcessingProvider):
def descrFile(self, d, f):
return os.path.join(self.descrFolder(d), f)
def otb_app_dir_list(self, v, otb_folder):
default_app_dir = os.path.join(otb_folder, 'lib', 'otb', 'applications')
def otb_app_dir_list(self, v):
folders = v.split(';')
app_dirs = []
for f in folders:
if f is not None and os.path.exists(f):
app_dirs.append(f)
if not default_app_dir in app_dirs:
app_dirs.append(default_app_dir)
app_dirs.append(self.normalize_path(f))
return app_dirs
def name(self):
......
......@@ -50,20 +50,22 @@ DOWNLOAD_URL = "https://orfeo-toolbox.org/packages/archives/OTB/"
DEFAULT_RAM_VALUE = 128
OTB_CLI_FILE = ''
import re
def version():
return ProcessingConfig.getSetting(VERSION) or '0.0.0'
def otbFolder():
return ProcessingConfig.getSetting(FOLDER) or None
if ProcessingConfig.getSetting(FOLDER):
return os.path.normpath(os.sep.join(re.split(r'\\|/', ProcessingConfig.getSetting(FOLDER))))
else:
return None
def appFolder():
if os.name == 'nt':
return ProcessingConfig.getSetting(APP_FOLDER) or None
app_folder = ProcessingConfig.getSetting(APP_FOLDER)
if app_folder:
return os.pathsep.join(app_folder.split(';'))
else:
otb_app_dirs = ProcessingConfig.getSetting(APP_FOLDER)
if otb_app_dirs is not None:
otb_app_dirs = otb_app_dirs.replace(';', ':')
return otb_app_dirs
return None
def srtmFolder():
return ProcessingConfig.getSetting(SRTM_FOLDER) or ''
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment