def grassPath(): """ Find GRASS path on the operating system. Sets global variable Grass7Utils.path """ if Grass7Utils.path is not None: return Grass7Utils.path if not isWindows() and not isMac(): return '' if isMac(): folder = ProcessingConfig.getSetting(Grass7Utils.GRASS_FOLDER) or '' if not os.path.exists(folder): folder = None else: folder = None if folder is None: # Under MS-Windows, we use OSGEO4W or QGIS Path for folder if isWindows(): if "OSGEO4W_ROOT" in os.environ: testfolder = os.path.join(str(os.environ['OSGEO4W_ROOT']), "apps") else: testfolder = str(QgsApplication.prefixPath()) testfolder = os.path.join(testfolder, 'grass') if os.path.isdir(testfolder): grassfolders = sorted([f for f in os.listdir(testfolder) if f.startswith("grass-7.") and os.path.isdir(os.path.join(testfolder, f))], reverse=True, key=lambda x: [int(v) for v in x[len("grass-"):].split('.')]) if grassfolders: folder = os.path.join(testfolder, grassfolders[0]) elif isMac(): # For MacOSX, we scan some well-known directories # Start with QGIS bundle for version in ['', '7', '70', '71', '72', '74']: testfolder = os.path.join(str(QgsApplication.prefixPath()), 'grass{}'.format(version)) if os.path.isdir(testfolder): folder = testfolder break # If nothing found, try standalone GRASS installation if folder is None: for version in ['0', '1', '2', '4']: testfolder = '/Applications/GRASS-7.{}.app/Contents/MacOS'.format(version) if os.path.isdir(testfolder): folder = testfolder break if folder is not None: Grass7Utils.path = folder return folder or ''
def getSagaInstalledVersion(runSaga=False): global _installedVersion global _installedVersionFound if not _installedVersionFound or runSaga: if isWindows(): commands = [os.path.join(sagaPath(), "saga_cmd.exe"), "-v"] elif isMac(): commands = [os.path.join(sagaPath(), "saga_cmd"), "-v"] else: commands = ["saga_cmd", "-v"] proc = subprocess.Popen( commands, shell=True, stdout=subprocess.PIPE, stdin=open(os.devnull), stderr=subprocess.STDOUT, universal_newlines=True, ).stdout try: lines = proc.readlines() except: return None for line in lines: if line.startswith("SAGA Version:"): _installedVersion = line[len("SAGA Version:"):].strip().split(" ")[0] _installedVersionFound = True return _installedVersion
def grassHelpPath(): helpPath = ProcessingConfig.getSetting(Grass7Utils.GRASS_HELP_PATH) if helpPath is None: if isWindows(): localPath = os.path.join(Grass7Utils.grassPath(), 'docs/html') if os.path.exists(localPath): helpPath = os.path.abspath(localPath) elif isMac(): localPath = '/Applications/GRASS-7.0.app/Contents/MacOS/docs/html' if os.path.exists(localPath): helpPath = os.path.abspath(localPath) else: searchPaths = ['/usr/share/doc/grass-doc/html', '/opt/grass/docs/html', '/usr/share/doc/grass/docs/html'] for path in searchPaths: if os.path.exists(path): helpPath = os.path.abspath(path) break if helpPath is not None: return helpPath elif Grass7Utils.command: return 'http://grass.osgeo.org/{}/manuals/'.format(Grass7Utils.command) else: # grass not available! return 'http://grass.osgeo.org/72/manuals/'
def grassPath(): if not isWindows() and not isMac(): return "" folder = ProcessingConfig.getSetting(Grass7Utils.GRASS_FOLDER) or "" if not os.path.exists(folder): folder = None if folder is None: if isWindows(): if "OSGEO4W_ROOT" in os.environ: testfolder = os.path.join(str(os.environ["OSGEO4W_ROOT"]), "apps") else: testfolder = str(QgsApplication.prefixPath()) testfolder = os.path.join(testfolder, "grass") if os.path.isdir(testfolder): for subfolder in os.listdir(testfolder): if subfolder.startswith("grass-7"): folder = os.path.join(testfolder, subfolder) break else: folder = os.path.join(str(QgsApplication.prefixPath()), "grass7") if not os.path.isdir(folder): folder = "/Applications/GRASS-7.0.app/Contents/MacOS" return folder or ""
def grassHelpPath(): helpPath = ProcessingConfig.getSetting(Grass7Utils.GRASS_HELP_PATH) if helpPath is None: if isWindows() or isMac(): if Grass7Utils.path is not None: localPath = os.path.join(Grass7Utils.path, 'docs/html') if os.path.exists(localPath): helpPath = os.path.abspath(localPath) else: searchPaths = ['/usr/share/doc/grass-doc/html', '/opt/grass/docs/html', '/usr/share/doc/grass/docs/html'] for path in searchPaths: if os.path.exists(path): helpPath = os.path.abspath(path) break if helpPath is not None: return helpPath elif Grass7Utils.version: version = Grass7Utils.version.replace('.', '')[:2] return 'https://grass.osgeo.org/grass{}/manuals/'.format(version) else: # GRASS not available! return 'https://grass.osgeo.org/grass76/manuals/'
def unload(self): ProcessingConfig.removeSetting('ACTIVATE_SAGA') if (isWindows() or isMac()): ProcessingConfig.removeSetting(SagaUtils.SAGA_FOLDER) ProcessingConfig.removeSetting(SagaUtils.SAGA_LOG_CONSOLE) ProcessingConfig.removeSetting(SagaUtils.SAGA_LOG_COMMANDS)
def unload(self): ProcessingConfig.removeSetting('ACTIVATE_GRASS7') if isWindows() or isMac(): ProcessingConfig.removeSetting(Grass7Utils.GRASS_FOLDER) ProcessingConfig.removeSetting(Grass7Utils.GRASS_LOG_COMMANDS) ProcessingConfig.removeSetting(Grass7Utils.GRASS_LOG_CONSOLE) ProcessingConfig.removeSetting(Grass7Utils.GRASS_HELP_PATH)
def executeOtb(commands, progress, addToLog=True): loglines = [] loglines.append(tr("OTB execution console output")) os.putenv("ITK_AUTOLOAD_PATH", otbLibPath()) fused_command = "".join(['"%s" ' % re.sub(r'^"|"$', "", c) for c in commands]) with subprocess.Popen( fused_command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.DEVNULL, stderr=subprocess.STDOUT, universal_newlines=True, ) as proc: if isMac(): # This trick avoids having an uninterrupted system call exception if OTB is not installed time.sleep(1) for line in iter(proc.stdout.readline, ""): if "[*" in line: idx = line.find("[*") perc = int(line[idx - 4 : idx - 2].strip(" ")) if perc != 0: progress.setPercentage(perc) else: loglines.append(line) progress.setConsoleInfo(line) if addToLog: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, loglines) return loglines
def load(self): ProcessingConfig.settingIcons[self.name()] = self.icon() ProcessingConfig.addSetting(Setting(self.name(), 'ACTIVATE_GRASS7', self.tr('Activate'), True)) if isMac(): ProcessingConfig.addSetting(Setting( self.name(), Grass7Utils.GRASS_FOLDER, self.tr('GRASS7 folder'), Grass7Utils.grassPath(), valuetype=Setting.FOLDER)) ProcessingConfig.addSetting(Setting( self.name(), Grass7Utils.GRASS_LOG_COMMANDS, self.tr('Log execution commands'), False)) ProcessingConfig.addSetting(Setting( self.name(), Grass7Utils.GRASS_LOG_CONSOLE, self.tr('Log console output'), False)) ProcessingConfig.addSetting(Setting( self.name(), Grass7Utils.GRASS_HELP_PATH, self.tr('Location of GRASS docs'), Grass7Utils.grassHelpPath())) # Add a setting for using v.external instead of v.in.ogr # But set it to False by default because some algorithms # can't be used with external data (need a solid v.in.ogr). ProcessingConfig.addSetting(Setting( self.name(), Grass7Utils.GRASS_USE_VEXTERNAL, self.tr('For vector layers, use v.external (faster) instead of v.in.ogr'), False)) ProcessingConfig.readSettings() self.refreshAlgorithms() return True
def load(self): ProcessingConfig.settingIcons[self.name()] = self.icon() ProcessingConfig.addSetting(Setting(self.name(), 'ACTIVATE_GRASS7', self.tr('Activate'), True)) if isWindows() or isMac(): ProcessingConfig.addSetting(Setting( self.name(), Grass7Utils.GRASS_FOLDER, self.tr('GRASS7 folder'), Grass7Utils.grassPath(), valuetype=Setting.FOLDER)) ProcessingConfig.addSetting(Setting( self.name(), Grass7Utils.GRASS_LOG_COMMANDS, self.tr('Log execution commands'), False)) ProcessingConfig.addSetting(Setting( self.name(), Grass7Utils.GRASS_LOG_CONSOLE, self.tr('Log console output'), False)) ProcessingConfig.addSetting(Setting( self.name(), Grass7Utils.GRASS_HELP_PATH, self.tr('Location of GRASS docs'), Grass7Utils.grassHelpPath())) ProcessingConfig.readSettings() self.refreshAlgorithms() return True
def grassPath(): if not isWindows() and not isMac(): return '' folder = ProcessingConfig.getSetting(GrassUtils.GRASS_FOLDER) or '' if not os.path.exists(folder): folder = None if folder is None: if isWindows(): if "OSGEO4W_ROOT" in os.environ: testfolder = os.path.join(str(os.environ['OSGEO4W_ROOT']), "apps") else: testfolder = str(QgsApplication.prefixPath()) testfolder = os.path.join(testfolder, 'grass') if os.path.isdir(testfolder): for subfolder in os.listdir(testfolder): if subfolder.startswith('grass-6'): folder = os.path.join(testfolder, subfolder) break else: folder = os.path.join(QgsApplication.prefixPath(), 'grass') if not os.path.isdir(folder): folder = '/Applications/GRASS-6.4.app/Contents/MacOS' if folder: ProcessingConfig.setSettingValue(GrassUtils.GRASS_FOLDER, folder) return folder or ''
def help(self): localDoc = None html = self.grass7Name + ".html" if system.isWindows(): # For MS-Windows, use the configured GRASS7 path localPath = os.path.join(Grass7Utils.grassPath(), "docs/html", html) if os.path.exists(localPath): localDoc = os.path.abspath(localPath) elif system.isMac(): # For MacOSX official package localPath = os.path.join("/Applications/GRASS-7.0.app/Contents/MacOS/docs/html", html) if os.path.exists(localPath): localDoc = os.path.abspath(localPath) else: # For GNU/Linux distributions searchPaths = ["/usr/share/doc/grass-doc/html", "/opt/grass/docs/html", "/usr/share/doc/grass/docs/html"] for path in searchPaths: localPath = os.path.join(path, html) if os.path.exists(localPath): localDoc = os.path.abspath(localPath) # Found the local documentation if localDoc: localDoc = QUrl.fromLocalFile(localDoc).toString() return False, localDoc # Return the URL if local doc is not found return False, "http://grass.osgeo.org/grass70/manuals/" + self.grass7Name + ".html"
def getSagaInstalledVersion(runSaga=False): global _installedVersion global _installedVersionFound if not _installedVersionFound or runSaga: if isWindows(): commands = [os.path.join(sagaPath(), "saga_cmd.exe"), "-v"] elif isMac(): commands = [os.path.join(sagaPath(), "saga_cmd"), "-v"] else: # for Linux use just one string instead of separated parameters as the list # does not work well together with shell=True option # (python docs advices to use subprocess32 instead of python2.7's subprocess) commands = ["saga_cmd -v"] proc = subprocess.Popen( commands, shell=True, stdout=subprocess.PIPE, stdin=open(os.devnull), stderr=subprocess.STDOUT, universal_newlines=True, ).stdout lines = proc.readlines() for line in lines: if line.startswith("SAGA Version:"): _installedVersion = line[len("SAGA Version:"):].strip().split(" ")[0] _installedVersionFound = True return _installedVersion
def unload(self): AlgorithmProvider.unload(self) if isWindows() or isMac(): ProcessingConfig.removeSetting(Grass7Utils.GRASS_FOLDER) ProcessingConfig.removeSetting(Grass7Utils.GRASS_WIN_SHELL) ProcessingConfig.removeSetting(Grass7Utils.GRASS_LOG_COMMANDS) ProcessingConfig.removeSetting(Grass7Utils.GRASS_LOG_CONSOLE)
def prepareGrass7Execution(commands): env = os.environ.copy() if isWindows(): Grass7Utils.createGrass7Script(commands) command = ['cmd.exe', '/C ', Grass7Utils.grassScriptFilename()] else: gisrc = userFolder() + os.sep + 'processing.gisrc7' env['GISRC'] = gisrc env['GRASS_MESSAGE_FORMAT'] = 'plain' env['GRASS_BATCH_JOB'] = Grass7Utils.grassBatchJobFilename() if 'GISBASE' in env: del env['GISBASE'] Grass7Utils.createGrass7BatchJobFileFromGrass7Commands(commands) os.chmod(Grass7Utils.grassBatchJobFilename(), stat.S_IEXEC | stat.S_IREAD | stat.S_IWRITE) if isMac() and os.path.exists(Grass7Utils.grassPath() + os.sep + 'grass70.sh'): command = Grass7Utils.grassPath() + os.sep + 'grass70.sh ' \ + Grass7Utils.grassMapsetFolder() + '/PERMANENT' else: command = 'grass70 ' + Grass7Utils.grassMapsetFolder() \ + '/PERMANENT' return command, env
def unload(self): AlgorithmProvider.unload(self) if (isWindows() or isMac()) and SagaUtils.findSagaFolder() is None: ProcessingConfig.removeSetting(SagaUtils.SAGA_FOLDER) ProcessingConfig.removeSetting(SagaUtils.SAGA_LOG_CONSOLE) ProcessingConfig.removeSetting(SagaUtils.SAGA_LOG_COMMANDS)
def prepareGrassExecution(commands): env = os.environ.copy() if isWindows(): GrassUtils.createGrassScript(commands) command = ["cmd.exe", "/C ", GrassUtils.grassScriptFilename()] else: gisrc = os.path.join(userFolder(), "processing.gisrc") env["GISRC"] = gisrc env["GRASS_MESSAGE_FORMAT"] = "gui" env["GRASS_BATCH_JOB"] = GrassUtils.grassBatchJobFilename() if "GISBASE" in env: del env["GISBASE"] GrassUtils.createGrassBatchJobFileFromGrassCommands(commands) os.chmod(GrassUtils.grassBatchJobFilename(), stat.S_IEXEC | stat.S_IREAD | stat.S_IWRITE) if isMac(): command = ( os.path.join(GrassUtils.grassPath(), "grass.sh") + " " + os.path.join(GrassUtils.grassMapsetFolder(), "PERMANENT") ) else: command = "grass64 " + os.path.join(GrassUtils.grassMapsetFolder(), "PERMANENT") return command, env
def grassPath(): if not isWindows() and not isMac(): return '' folder = ProcessingConfig.getSetting(Grass7Utils.GRASS_FOLDER) or '' if not os.path.exists(folder): folder = None if folder is None: if isWindows(): if "OSGEO4W_ROOT" in os.environ: testfolder = os.path.join(unicode(os.environ['OSGEO4W_ROOT']), "apps") else: testfolder = unicode(QgsApplication.prefixPath()) testfolder = os.path.join(testfolder, 'grass') if os.path.isdir(testfolder): for subfolder in os.listdir(testfolder): if subfolder.startswith('grass-7'): folder = os.path.join(testfolder, subfolder) fn = os.path.join(folder, "etc", "VERSIONNUMBER") if not os.path.isfile(fn): continue f = open(fn, "r") Grass7Utils.version = f.read().split(' ')[0] f.close() major, minor, patch = Grass7Utils.version.split('.') Grass7Utils.command = "grass{}{}".format(major, minor) break else: folder = os.path.join(unicode(QgsApplication.prefixPath()), 'grass7') if not os.path.isdir(folder): folder = '/Applications/GRASS-7.0.app/Contents/MacOS' return folder or ''
def getInstalledVersion(runSaga=False): global _installedVersion global _installedVersionFound maxRetries = 5 retries = 0 if _installedVersionFound and not runSaga: return _installedVersion if isWindows(): commands = [os.path.join(sagaPath(), "saga_cmd.exe"), "-v"] elif isMac(): commands = [os.path.join(sagaPath(), "saga_cmd -v")] else: # for Linux use just one string instead of separated parameters as the list # does not work well together with shell=True option # (python docs advices to use subprocess32 instead of python2.7's subprocess) commands = ["saga_cmd -v"] while retries < maxRetries: with subprocess.Popen( commands, shell=True, stdout=subprocess.PIPE, stdin=subprocess.DEVNULL, stderr=subprocess.STDOUT, universal_newlines=True, ) as proc: if isMac(): # This trick avoids having an uninterrupted system call exception if SAGA is not installed time.sleep(1) try: lines = proc.stdout.readlines() for line in lines: if line.startswith("SAGA Version:"): _installedVersion = line[len("SAGA Version:"):].strip().split(" ")[0] _installedVersionFound = True return _installedVersion return None except IOError: retries += 1 except: return None return _installedVersion
def grassBin(): """ Find GRASS binary path on the operating system. Sets global variable Grass7Utils.command """ cmdList = ["grass74", "grass72", "grass71", "grass70", "grass", "grass74.sh", "grass72.sh", "grass71.sh", "grass70.sh", "grass.sh"] def searchFolder(folder): """ Inline function to search for grass binaries into a folder with os.walk """ command = None if os.path.exists(folder): for root, dirs, files in os.walk(folder): for cmd in cmdList: if cmd in files: command = os.path.join(root, cmd) break return command if Grass7Utils.command: return Grass7Utils.command path = Grass7Utils.grassPath() command = None # For MS-Windows there is a difference between GRASS Path and GRASS binary if isWindows(): # If nothing found, use OSGEO4W or QgsPrefix: if "OSGEO4W_ROOT" in os.environ: testFolder = str(os.environ['OSGEO4W_ROOT']) else: testFolder = str(QgsApplication.prefixPath()) testFolder = os.path.join(testFolder, 'bin') command = searchFolder(testFolder) elif isMac(): # Search in grassPath command = searchFolder(path) # Under GNU/Linux or if everything has failed, use shutil if not command: for cmd in cmdList: testBin = shutil.which(cmd) if testBin: command = os.path.abspath(testBin) break if command: Grass7Utils.command = command if path is '': Grass7Utils.path = os.path.dirname(command) return command
def taudemPath(): folder = ProcessingConfig.getSetting(TauDEMUtils.TAUDEM_FOLDER) if folder is None: folder = '' if isMac(): testfolder = os.path.join(QgsApplication.prefixPath(), 'bin') if os.path.exists(os.path.join(testfolder, 'pitremove')): folder = testfolder else: testfolder = '/usr/local/bin' if os.path.exists(os.path.join(testfolder, 'pitremove')): folder = testfolder return folder
def initializeSettings(self): AlgorithmProvider.initializeSettings(self) if isWindows() or isMac(): ProcessingConfig.addSetting(Setting("SAGA", SagaUtils.SAGA_FOLDER, self.tr('SAGA folder'), '')) ProcessingConfig.addSetting(Setting("SAGA", SagaUtils.SAGA_IMPORT_EXPORT_OPTIMIZATION, self.tr('Enable SAGA Import/Export optimizations'), False)) ProcessingConfig.addSetting(Setting("SAGA", SagaUtils.SAGA_LOG_COMMANDS, self.tr('Log execution commands'), True)) ProcessingConfig.addSetting(Setting("SAGA", SagaUtils.SAGA_LOG_CONSOLE, self.tr('Log console output'), True))
def mpiexecPath(): folder = ProcessingConfig.getSetting(TauDEMUtils.MPIEXEC_FOLDER) if folder is None: folder = '' if isMac(): testfolder = os.path.join(QgsApplication.prefixPath(), 'bin') if os.path.exists(os.path.join(testfolder, 'mpiexec')): folder = testfolder else: testfolder = '/usr/local/bin' if os.path.exists(os.path.join(testfolder, 'mpiexec')): folder = testfolder return folder
def findSagaFolder(): folder = None if isMac(): testfolder = os.path.join(QgsApplication.prefixPath(), 'bin') if os.path.exists(os.path.join(testfolder, 'saga_cmd')): folder = testfolder else: testfolder = '/usr/local/bin' if os.path.exists(os.path.join(testfolder, 'saga_cmd')): folder = testfolder elif isWindows(): testfolder = os.path.join(os.path.dirname(QgsApplication.prefixPath()), 'saga') if os.path.exists(os.path.join(testfolder, 'saga_cmd.exe')): folder = testfolder return folder
def initializeSettings(self): AlgorithmProvider.initializeSettings(self) if isWindows() or isMac(): ProcessingConfig.addSetting(Setting( self.getDescription(), Grass7Utils.GRASS_FOLDER, self.tr('GRASS7 folder'), Grass7Utils.grassPath(), valuetype=Setting.FOLDER)) ProcessingConfig.addSetting(Setting( self.getDescription(), Grass7Utils.GRASS_LOG_COMMANDS, self.tr('Log execution commands'), False)) ProcessingConfig.addSetting(Setting( self.getDescription(), Grass7Utils.GRASS_LOG_CONSOLE, self.tr('Log console output'), False))
def gdalHelpPath(): helpPath = ProcessingConfig.getSetting(GdalUtils.GDAL_HELP_PATH) if helpPath is None: if isWindows(): pass elif isMac(): pass else: searchPaths = ['/usr/share/doc/libgdal-doc/gdal'] for path in searchPaths: if os.path.exists(path): helpPath = os.path.abspath(path) break return helpPath if helpPath is not None else 'http://www.gdal.org/'
def createSagaBatchJobFileFromSagaCommands(commands): with open(sagaBatchJobFilename(), 'w', encoding="utf8") as fout: if isWindows(): fout.write('set SAGA=' + sagaPath() + '\n') fout.write('set SAGA_MLB=' + os.path.join(sagaPath(), 'modules') + '\n') fout.write('PATH=%PATH%;%SAGA%;%SAGA_MLB%\n') elif isMac() or platform.system() == 'FreeBSD': fout.write('export SAGA_MLB=' + os.path.join(sagaPath(), '../lib/saga') + '\n') fout.write('export PATH=' + sagaPath() + ':$PATH\n') else: pass for command in commands: fout.write('saga_cmd ' + command + '\n') fout.write('exit')
def initializeSettings(self): if isWindows() or isMac(): ProcessingConfig.addSetting(Setting("SAGA", SagaUtils.SAGA_FOLDER, self.tr('SAGA folder'), '', valuetype=Setting.FOLDER)) ProcessingConfig.addSetting(Setting("SAGA", SagaUtils.SAGA_IMPORT_EXPORT_OPTIMIZATION, self.tr('Enable SAGA Import/Export optimizations'), False)) ProcessingConfig.addSetting(Setting("SAGA", SagaUtils.SAGA_LOG_COMMANDS, self.tr('Log execution commands'), True)) ProcessingConfig.addSetting(Setting("SAGA", SagaUtils.SAGA_LOG_CONSOLE, self.tr('Log console output'), True)) ProcessingConfig.settingIcons["SAGA"] = self.getIcon() ProcessingConfig.addSetting(Setting("SAGA", "ACTIVATE_SAGA", self.tr('Activate'), self.activate))
def createSagaBatchJobFileFromSagaCommands(commands): fout = open(sagaBatchJobFilename(), 'w') if isWindows(): fout.write('set SAGA=' + sagaPath() + '\n') fout.write('set SAGA_MLB=' + sagaPath() + os.sep + 'modules' + '\n') fout.write('PATH=PATH;%SAGA%;%SAGA_MLB%\n') elif isMac(): fout.write('export SAGA_MLB=' + sagaPath() + '/../lib/saga\n') fout.write('export PATH=' + sagaPath() + ':$PATH\n') else: pass for command in commands: fout.write('saga_cmd ' + command.encode('utf8') + '\n') fout.write('exit') fout.close()
def initializeSettings(self): if (isWindows() or isMac()) and SagaUtils.findSagaFolder() is None: ProcessingConfig.addSetting( Setting("SAGA", SagaUtils.SAGA_FOLDER, self.tr("SAGA folder"), "", valuetype=Setting.FOLDER) ) ProcessingConfig.addSetting( Setting( "SAGA", SagaUtils.SAGA_IMPORT_EXPORT_OPTIMIZATION, self.tr("Enable SAGA Import/Export optimizations"), False, ) ) ProcessingConfig.addSetting( Setting("SAGA", SagaUtils.SAGA_LOG_COMMANDS, self.tr("Log execution commands"), True) ) ProcessingConfig.addSetting(Setting("SAGA", SagaUtils.SAGA_LOG_CONSOLE, self.tr("Log console output"), True)) ProcessingConfig.settingIcons["SAGA"] = self.getIcon() ProcessingConfig.addSetting(Setting("SAGA", "ACTIVATE_SAGA", self.tr("Activate"), self.activate))
def qgis_session_info(self): # import re # from processing.algs.saga.SagaAlgorithmProvider import SagaAlgorithmProvider # from processing.algs.saga import SagaUtils # from processing.algs.grass.GrassUtils import GrassUtils # from processing.algs.grass7.Grass7Utils import Grass7Utils # from processing.algs.otb.OTBAlgorithmProvider import OTBAlgorithmProvider # from processing.algs.otb.OTBUtils import getInstalledVersion # from processing.algs.taudem.TauDEMUtils import TauDEMUtils # from osgeo import gdal # from processing.tools.system import isWindows, isMac # QGIS version qgis = QGis.QGIS_VERSION # GRASS versions # grassPath returns "" if called under Linux and if there is no GRASS # installation GrassUtils.checkGrassIsInstalled() g6 = GrassUtils.isGrassInstalled if g6 is True and isWindows(): g6 = GrassUtils.grassPath() # extract everything followed by grass-, i.e. extract the version number g6 = re.findall("grass-(.*)", g6) if g6 is True and isMac(): g6 = GrassUtils.grassPath()[0:21] g6 = os.listdir(g6) delim = ';' g6 = delim.join(g6) g6 = re.findall('[0-9].[0-9].[0-9]', g6) Grass7Utils.checkGrass7IsInstalled() g7 = Grass7Utils.isGrass7Installed if g7 is True and isWindows(): g7 = Grass7Utils.grassPath() g7 = re.findall('grass-(.*)', g7) if g7 is True and isMac(): g7 = Grass7Utils.grassPath()[0:21] g7 = os.listdir(g7) delim = ';' g7 = delim.join(g7) #g7 = re.findall(';(grass[0-9].);', g7) g7 = re.findall('[0-9].[0-9].[0-9]', g7) # installed SAGA version usable with QGIS saga = SagaUtils.getSagaInstalledVersion() # supported SAGA versions my_dict = SagaAlgorithmProvider.supportedVersions saga_versions = my_dict.keys() saga_versions.sort() # GDAL gdal_v = gdal.VersionInfo('VERSION_NUM') gdal_v = '.'.join([gdal_v[0], gdal_v[2], gdal_v[4]]) ## this is good to have for the future, but so far, I would not report ## these software versions since we don't know if they actually work ## with QGIS (without additional functions such as run_taudem...) ## OTB versions # otb = getInstalledVersion() # otb = OTBUtils.getInstalledVersion() ## TauDEM versions (currently not in use because no function to extract ## Taudem version in 'TauDEMUtils') # TauDEMUtils.taudemMultifilePath() # finally, put it all into a named dictionary keys = ["qgis_version", "gdal", "grass6", "grass7", "saga",\ "supported_saga_versions"] values = [qgis, gdal_v, g6, g7, saga, saga_versions] info = dict(zip(keys, values)) return info
def unload(self): AlgorithmProvider.unload(self) if isWindows() or isMac(): ProcessingConfig.removeSetting(Grass7Utils.GRASS_FOLDER) ProcessingConfig.removeSetting(Grass7Utils.GRASS_LOG_COMMANDS) ProcessingConfig.removeSetting(Grass7Utils.GRASS_LOG_CONSOLE)
def sagaPath(): if not isWindows() and not isMac() and not platform.system() == 'FreeBSD': return '' folder = findSagaFolder() return folder or ''
def grassBin(): """ Find GRASS binary path on the operating system. Sets global variable Grass7Utils.command """ def searchFolder(folder): """ Inline function to search for grass binaries into a folder with os.walk """ if os.path.exists(folder): for root, dirs, files in os.walk(folder): for cmd in cmdList: if cmd in files: return os.path.join(root, cmd) return None if Grass7Utils.command: return Grass7Utils.command path = Grass7Utils.grassPath() command = None vn = os.path.join(path, "etc", "VERSIONNUMBER") if os.path.isfile(vn): with open(vn, "r") as f: major, minor, patch = f.readlines()[0].split(' ')[0].split('.') if patch != 'svn': patch = '' cmdList = [ "grass{}{}{}".format(major, minor, patch), "grass", "grass{}{}{}.sh".format(major, minor, patch), "grass.sh" ] else: cmdList = [ "grass76", "grass74", "grass72", "grass70", "grass", "grass76.sh", "grass74.sh", "grass72.sh", "grass70.sh", "grass.sh" ] # For MS-Windows there is a difference between GRASS Path and GRASS binary if isWindows(): # If nothing found, use OSGEO4W or QgsPrefix: if "OSGEO4W_ROOT" in os.environ: testFolder = str(os.environ['OSGEO4W_ROOT']) else: testFolder = str(QgsApplication.prefixPath()) testFolder = os.path.join(testFolder, 'bin') command = searchFolder(testFolder) elif isMac(): # Search in grassPath command = searchFolder(path) # If everything has failed, use shutil if not command: for cmd in cmdList: testBin = shutil.which(cmd) if testBin: command = os.path.abspath(testBin) break if command: Grass7Utils.command = command if path is '': Grass7Utils.path = os.path.dirname(command) return command
def grassPath(): """ Find GRASS path on the operating system. Sets global variable Grass7Utils.path """ if Grass7Utils.path is not None: return Grass7Utils.path if not isWindows() and not isMac(): return '' if isMac(): folder = ProcessingConfig.getSetting( Grass7Utils.GRASS_FOLDER) or '' if not os.path.exists(folder): folder = None else: folder = None if folder is None: # Under MS-Windows, we use OSGEO4W or QGIS Path for folder if isWindows(): if "OSGEO4W_ROOT" in os.environ: testfolder = os.path.join(str(os.environ['OSGEO4W_ROOT']), "apps") else: testfolder = str(QgsApplication.prefixPath()) testfolder = os.path.join(testfolder, 'grass') if os.path.isdir(testfolder): grassfolders = sorted( [ f for f in os.listdir(testfolder) if f.startswith("grass-7.") and os.path.isdir(os.path.join(testfolder, f)) ], reverse=True, key=lambda x: [int(v) for v in x[len("grass-"):].split('.')]) if grassfolders: folder = os.path.join(testfolder, grassfolders[0]) elif isMac(): # For MacOSX, we scan some well-known directories # Start with QGIS bundle for version in ['', '7', '70', '71', '72', '74']: testfolder = os.path.join(str(QgsApplication.prefixPath()), 'grass{}'.format(version)) if os.path.isdir(testfolder): folder = testfolder break # If nothing found, try standalone GRASS installation if folder is None: for version in ['0', '1', '2', '4']: testfolder = '/Applications/GRASS-7.{}.app/Contents/MacOS'.format( version) if os.path.isdir(testfolder): folder = testfolder break if folder is not None: Grass7Utils.path = folder return folder or ''
def sagaPath(): if not isWindows() and not isMac(): return '' folder = findSagaFolder() return folder or ''
def executeGrass(commands, feedback, outputCommands=None): loglines = [] loglines.append(Grass7Utils.tr('GRASS GIS 7 execution console output')) grassOutDone = False command, grassenv = Grass7Utils.prepareGrassExecution(commands) #QgsMessageLog.logMessage('exec: {}'.format(command), 'DEBUG', QgsMessageLog.INFO) # For MS-Windows, we need to hide the console window. if isWindows(): si = subprocess.STARTUPINFO() si.dwFlags |= subprocess.STARTF_USESHOWWINDOW si.wShowWindow = subprocess.SW_HIDE with subprocess.Popen(command, shell=True if isMac() else False, stdout=subprocess.PIPE, stdin=subprocess.DEVNULL, stderr=subprocess.STDOUT, universal_newlines=True, env=grassenv, startupinfo=si if isWindows() else None) as proc: for line in iter(proc.stdout.readline, ''): if 'GRASS_INFO_PERCENT' in line: try: feedback.setProgress( int(line[len('GRASS_INFO_PERCENT') + 2:])) except: pass else: if 'r.out' in line or 'v.out' in line: grassOutDone = True loglines.append(line) feedback.pushConsoleInfo(line) # Some GRASS scripts, like r.mapcalculator or r.fillnulls, call # other GRASS scripts during execution. This may override any # commands that are still to be executed by the subprocess, which # are usually the output ones. If that is the case runs the output # commands again. if not grassOutDone and outputCommands: command, grassenv = Grass7Utils.prepareGrassExecution( outputCommands) with subprocess.Popen( command, shell=True if isMac() else False, stdout=subprocess.PIPE, stdin=subprocess.DEVNULL, stderr=subprocess.STDOUT, universal_newlines=True, env=grassenv, startupinfo=si if isWindows() else None) as proc: for line in iter(proc.stdout.readline, ''): if 'GRASS_INFO_PERCENT' in line: try: feedback.setProgress( int(line[len('GRASS_INFO_PERCENT') + 2:])) except: pass else: loglines.append(line) feedback.pushConsoleInfo(line) if ProcessingConfig.getSetting(Grass7Utils.GRASS_LOG_CONSOLE): QgsMessageLog.logMessage('\n'.join(loglines), 'Processing', QgsMessageLog.INFO)
def runAndWait(self, commandline): '''Subprocess pdal pipeline waiting it's end. Returns stdout/error log of execution. The execution is not blocking. ''' executionLog = '' QgsMessageLog.logMessage(" ".join(commandline), 'PDALTools', Qgis.Info) self.feedback.pushConsoleInfo(" ".join(commandline)) # !Note! subprocess call is similar as in Grass7Utils.executeGrass # For MS-Windows, we need to hide the console window. si = None if isWindows(): si = subprocess.STARTUPINFO() si.dwFlags |= subprocess.STARTF_USESHOWWINDOW si.wShowWindow = subprocess.SW_HIDE proc = subprocess.Popen(commandline, shell=True if isMac() else False, stdout=subprocess.PIPE, stdin=open(os.devnull), stderr=subprocess.STDOUT, universal_newlines=True, startupinfo=si) nbsr = NonBlockingStreamReader(proc.stdout) while proc.poll() is None: if self.feedback.isCanceled(): proc.kill() out = nbsr.readline(self.readlineTimeout) if out: QgsMessageLog.logMessage(out, 'PDALTools', Qgis.Info) self.feedback.pushConsoleInfo(out) executionLog += out # allow the dialog to be responsive allowing accept cancel process QgsApplication.instance().processEvents() # proc is terminated but could have more messages in stdout to read out = nbsr.readline(self.readlineTimeout) while out is not None: QgsMessageLog.logMessage(out, 'PDALTools', Qgis.Info) self.feedback.pushConsoleInfo(out) executionLog += out out = nbsr.readline(self.readlineTimeout) # check return code depending on platform if isWindows(): pass else: # it is a unix env if proc.returncode == -(signal.SIGKILL.value): raise QgsProcessingException( "Command {} has been cancelled with signal: {}".format( commandline, proc.returncode)) # check generic return code if proc.returncode != 0: raise QgsProcessingException( "Failed execution of command {} with return code: {}".format( commandline, proc.returncode)) # return only pdal log return executionLog