def validateAppFolders(self, v): if not self.isActive(): return if not v: self.setActive(False) raise ValueError(self.tr('Cannot activate OTB provider')) folder = OtbUtils.otbFolder() otb_app_dirs = self.appDirs(v) if len(otb_app_dirs) < 1: self.setActive(False) raise ValueError( self.tr("'{}' does not exist. OTB provider will be disabled". format(v))) #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 \ 'ApplicationExample' in otb_app: continue app_name = os.path.basename(otb_app).split('.')[0][7:] dfile = os.path.join(descr_folder, app_name + '.txt') isValid = True if not os.path.exists(dfile): cmdlist = [ OtbUtils.getExecutableInPath(folder, 'otbQgisDescriptor'), app_name, app_dir, descr_folder + '/' ] commands = ' '.join(cmdlist) QgsMessageLog.logMessage(self.tr(commands), self.tr('Processing'), Qgis.Critical) OtbUtils.executeOtb(commands, feedback=None) if isValid: # if check needed for testsing if utils.iface is not None: 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 createAlgsList(self): algs = [] try: folder = OtbUtils.otbFolder() alg_names = [] algs_txt = self.algsFile(folder) with open(algs_txt) as lines: line = lines.readline().strip('\n').strip() if line != '' and line.startswith('#'): line = lines.readline().strip('\n').strip() while line != '' and not line.startswith('#'): data = line.split('|') descriptionFile = self.descrFile(folder, str(data[1]) + '.txt') group, name = str(data[0]), str(data[1]) if name not in alg_names: algs.append(OtbAlgorithm(group, name, descriptionFile)) #avoid duplicate algorithms from algs.txt file (possible but rare) alg_names.append(name) line = lines.readline().strip('\n').strip() except Exception as e: import traceback errmsg = "Could not open OTB algorithm from file: \n" + descriptionFile + "\nError:\n" + traceback.format_exc( ) QgsMessageLog.logMessage(self.tr(errmsg), self.tr('Processing'), Qgis.Critical) return algs
def canBeActivated(self): if not self.isActive(): return False folder = OtbUtils.otbFolder() if folder and os.path.exists(folder): if os.path.isfile(self.algsFile(folder)): return True utils.iface.messageBar().pushWarning("OTB", "Cannot find '{}'. OTB provider will be disabled".format(self.algsFile(folder))) self.setActive(False) return False
def validateOtbFolder(self, v): if not self.isActive(): return if not v or not os.path.exists(v): self.setActive(False) raise ValueError(self.tr("'{}' does not exist. OTB provider will be disabled".format(v))) path = self.normalize_path(v) app_launcher_path = OtbUtils.getExecutableInPath(path, 'otbApplicationLauncherCommandLine') if not os.path.exists(app_launcher_path): self.setActive(False) raise ValueError(self.tr("Cannot find '{}'. OTB will be disabled".format(app_launcher_path)))
def validateAppFolders(self, v): if not self.isActive(): return if not v: self.setActive(False) raise ValueError(self.tr('Cannot activate OTB provider')) folder = OtbUtils.otbFolder() otb_app_dirs = self.appDirs(v) if len(otb_app_dirs) < 1: self.setActive(False) raise ValueError(self.tr("'{}' does not exist. OTB provider will be disabled".format(v))) #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 \ 'ApplicationExample' in otb_app: continue app_name = os.path.basename(otb_app).split('.')[0][7:] dfile = os.path.join(descr_folder, app_name + '.txt') isValid = True if not os.path.exists(dfile): cmdlist = [OtbUtils.getExecutableInPath(folder, 'otbQgisDescriptor'), app_name, app_dir, descr_folder + '/'] commands = ' '.join(cmdlist) QgsMessageLog.logMessage(self.tr(commands), self.tr('Processing'), Qgis.Critical) OtbUtils.executeOtb(commands, feedback=None) if isValid: # if check needed for testsing if utils.iface is not None: 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 loadAlgorithms(self): if not self.canBeActivated(): return version_file = os.path.join(OtbUtils.otbFolder(), 'share', 'doc', 'otb', 'VERSION') if not os.path.isfile(version_file): version_file = os.path.join(OtbUtils.otbFolder(), 'VERSION') if os.path.isfile(version_file): with open(version_file) as vf: vlines = vf.readlines() vlines = [l.strip() for l in vlines] vline = vlines[0] 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) self.algs = self.createAlgsList() for a in self.algs: self.addAlgorithm(a) self.algs = []
def load(self): group = self.name() ProcessingConfig.settingIcons[group] = self.icon() ProcessingConfig.addSetting( Setting(group, OtbUtils.ACTIVATE, self.tr('Activate'), True)) ProcessingConfig.addSetting( Setting(group, OtbUtils.FOLDER, self.tr("OTB folder"), OtbUtils.otbFolder(), valuetype=Setting.FOLDER, validator=self.validateOtbFolder)) ProcessingConfig.addSetting( Setting(group, OtbUtils.APP_FOLDER, self.tr("OTB application folder"), OtbUtils.appFolder(), valuetype=Setting.MULTIPLE_FOLDERS, validator=self.validateAppFolders)) ProcessingConfig.addSetting( Setting(group, OtbUtils.SRTM_FOLDER, self.tr("SRTM tiles folder"), OtbUtils.srtmFolder(), valuetype=Setting.FOLDER)) ProcessingConfig.addSetting( Setting(group, OtbUtils.GEOID_FILE, self.tr("Geoid file"), OtbUtils.geoidFile(), valuetype=Setting.FOLDER)) ProcessingConfig.addSetting( Setting(group, OtbUtils.MAX_RAM_HINT, self.tr("Maximum RAM to use"), OtbUtils.maxRAMHint(), valuetype=Setting.STRING)) ProcessingConfig.addSetting( Setting(group, OtbUtils.LOGGER_LEVEL, self.tr("Logger level"), OtbUtils.loggerLevel(), valuetype=Setting.STRING, validator=self.validateLoggerLevel)) ProcessingConfig.readSettings() self.refreshAlgorithms() return True
def createAlgsList(self): algs = [] try: folder = OtbUtils.otbFolder() alg_names = [] algs_txt = self.algsFile(folder) with open(algs_txt) as lines: line = lines.readline().strip('\n').strip() if line != '' and line.startswith('#'): line = lines.readline().strip('\n').strip() while line != '' and not line.startswith('#'): data = line.split('|') descriptionFile = self.descrFile(folder, str(data[1]) + '.txt') group, name = str(data[0]), str(data[1]) if name not in alg_names: algs.append(OtbAlgorithm(group, name, descriptionFile)) #avoid duplicate algorithms from algs.txt file (possible but rare) alg_names.append(name) line = lines.readline().strip('\n').strip() except Exception as e: import traceback errmsg = "Could not open OTB algorithm from file: \n" + descriptionFile + "\nError:\n" + traceback.format_exc() QgsMessageLog.logMessage(self.tr(errmsg), self.tr('Processing'), Qgis.Critical) return algs
def load(self): group = self.name() ProcessingConfig.settingIcons[group] = self.icon() ProcessingConfig.addSetting(Setting(group, OtbUtils.ACTIVATE, self.tr('Activate'), True)) ProcessingConfig.addSetting(Setting(group, OtbUtils.FOLDER, self.tr("OTB folder"), OtbUtils.otbFolder(), valuetype=Setting.FOLDER, validator=self.validateOtbFolder )) ProcessingConfig.addSetting(Setting(group, OtbUtils.APP_FOLDER, self.tr("OTB application folder"), OtbUtils.appFolder(), valuetype=Setting.MULTIPLE_FOLDERS, validator=self.validateAppFolders )) ProcessingConfig.addSetting(Setting(group, OtbUtils.SRTM_FOLDER, self.tr("SRTM tiles folder"), OtbUtils.srtmFolder(), valuetype=Setting.FOLDER )) ProcessingConfig.addSetting(Setting(group, OtbUtils.GEOID_FILE, self.tr("Geoid file"), OtbUtils.geoidFile(), valuetype=Setting.FOLDER )) ProcessingConfig.addSetting(Setting(group, OtbUtils.MAX_RAM_HINT, self.tr("Maximum RAM to use"), OtbUtils.maxRAMHint(), valuetype=Setting.STRING )) ProcessingConfig.addSetting(Setting(group, OtbUtils.LOGGER_LEVEL, self.tr("Logger level"), OtbUtils.loggerLevel(), valuetype=Setting.STRING, validator=self.validateLoggerLevel )) ProcessingConfig.readSettings() self.refreshAlgorithms() return True
def processAlgorithm(self, parameters, context, feedback): app_launcher_path = OtbUtils.getExecutableInPath(OtbUtils.otbFolder(), 'otbApplicationLauncherCommandLine') command = '"{}" {} {}'.format(app_launcher_path, self.name(), OtbUtils.appFolder()) outputPixelType = None for k, v in parameters.items(): # if value is None for a parameter we don't have any businees with this key if not v or v is None: continue # for 'outputpixeltype' parameter we find the pixeltype string from self.pixelTypes if k == 'outputpixeltype': pixel_type = self.pixelTypes[int(parameters['outputpixeltype'])] outputPixelType = None if pixel_type == 'float' else pixel_type continue param = self.parameterDefinition(k) if param.isDestination(): continue if isinstance(param, QgsProcessingParameterEnum): value = self.parameterAsEnum(parameters, param.name(), context) elif isinstance(param, QgsProcessingParameterBoolean): value = self.parameterAsBoolean(parameters, param.name(), context) elif isinstance(param, QgsProcessingParameterCrs): crsValue = self.parameterAsCrs(parameters, param.name(), context) authid = crsValue.authid() if authid.startswith('EPSG:'): value = authid.split('EPSG:')[1] else: raise QgsProcessingException( self.tr("Incorrect value for parameter '{}'. No EPSG code found in '{}'".format( param.name(), authid))) elif isinstance(param, QgsProcessingParameterFile): value = self.parameterAsFile(parameters, param.name(), context) elif isinstance(param, QgsProcessingParameterMultipleLayers): layers = self.parameterAsLayerList(parameters, param.name(), context) if layers is None or len(layers) == 0: continue value = ' '.join(['"{}"'.format(self.getLayerSource(param.name(), layer)) for layer in layers]) elif isinstance(param, QgsProcessingParameterNumber): if param.dataType() == QgsProcessingParameterNumber.Integer: value = self.parameterAsInt(parameters, param.name(), context) else: value = self.parameterAsDouble(parameters, param.name(), context) elif isinstance(param, (QgsProcessingParameterRasterLayer, QgsProcessingParameterVectorLayer)): value = '"{}"'.format(self.getLayerSource(param.name(), self.parameterAsLayer(parameters, param.name(), context))) elif isinstance(param, QgsProcessingParameterString): value = '"{}"'.format(self.parameterAsString(parameters, param.name(), context)) else: # Use whatever is given value = '"{}"'.format(parameters[param.name()]) # Check if value is set in above if elif ladder and update command string if value and value is not None: command += ' -{} {}'.format(k, value) output_files = {} for out in self.destinationParameterDefinitions(): filePath = self.parameterAsOutputLayer(parameters, out.name(), context) if filePath: output_files[out.name()] = filePath if outputPixelType is not None: command += ' -{} "{}" "{}"'.format(out.name(), filePath, outputPixelType) else: command += ' -{} "{}"'.format(out.name(), filePath) OtbUtils.executeOtb(command, feedback) result = {} for o in self.outputDefinitions(): if o.name() in output_files: result[o.name()] = output_files[o.name()] return result
def defineCharacteristicsFromFile(self): line = None try: with open(self._descriptionfile) as lines: line = lines.readline().strip('\n').strip() self._name = line.split('|')[0] self.appkey = self._name line = lines.readline().strip('\n').strip() self.doc = line self.i18n_doc = QCoreApplication.translate("OtbAlgorithm", self.doc) #self._name = self._name #+ " - " + self.doc self._display_name = self.tr(self._name) self.i18n_name = QCoreApplication.translate("OtbAlgorithm", self._name) line = lines.readline().strip('\n').strip() self._group = line self.i18n_group = QCoreApplication.translate("OtbAlgorithm", self._group) line = lines.readline().strip('\n').strip() while line != '': line = line.strip('\n').strip() if line.startswith('#'): line = lines.readline().strip('\n').strip() continue param = None if 'OTBParameterChoice' in line: tokens = line.split("|") params = [t if str(t) != str(None) else None for t in tokens[1:]] options = params[2].split(';') param = OtbParameterChoice(params[0], params[1], options, params[3], params[4]) else: param = getParameterFromString(line, 'OtbAlgorithm') #if parameter is None, then move to next line and continue if param is None: line = lines.readline().strip('\n').strip() continue name = param.name() if '.' in name and len(name.split('.')) > 2: p = name.split('.')[:-2] group_key = '.'.join(p) group_value = name.split('.')[-2] metadata = param.metadata() metadata['group_key'] = group_key metadata['group_value'] = group_value param.setMetadata(metadata) #'elev.dem.path', 'elev.dem', 'elev.dem.geoid', 'elev.geoid' are special! #Even though it is not typical for OTB to fix on parameter keys, #we current use below !hack! to set SRTM path and GEOID files #Future releases of OTB must follow this rule keep #compatibility or update this checklist. if name in ["elev.dem.path", "elev.dem"]: param.setDefaultValue(OtbUtils.srtmFolder()) if name in ["elev.dem.geoid", "elev.geoid"]: param.setDefaultValue(OtbUtils.geoidFile()) # outputpixeltype is a special parameter associated with raster output # reset list of options to 'self.pixelTypes'. if name == 'outputpixeltype': param.setOptions(self.pixelTypes) param.setDefaultValue(self.pixelTypes.index('float')) self.addParameter(param) #parameter is added now and we must move to next line line = lines.readline().strip('\n').strip() except BaseException as e: import traceback errmsg = "Could not open OTB algorithm from file: \n" + self._descriptionfile + "\nline=" + line + "\nError:\n" + traceback.format_exc() QgsMessageLog.logMessage(self.tr(errmsg), self.tr('Processing'), Qgis.Critical) raise e
def unload(self): for setting in OtbUtils.settingNames(): ProcessingConfig.removeSetting(setting)