2014-04-19 15:53:43 +02:00
# -*- coding: utf-8 -*-
"""
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Grass7Algorithm . py
- - - - - - - - - - - - - - - - - - - - -
2015-02-07 21:53:30 +01:00
Date : February 2015
Copyright : ( C ) 2014 - 2015 by Victor Olaya
2014-04-19 15:53:43 +02:00
Email : volayaf at gmail dot com
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
"""
2016-09-21 18:24:26 +02:00
from builtins import str
from builtins import range
2014-04-19 15:53:43 +02:00
__author__ = ' Victor Olaya '
2015-02-07 21:53:30 +01:00
__date__ = ' February 2015 '
__copyright__ = ' (C) 2012-2015, Victor Olaya '
2014-04-19 15:53:43 +02:00
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = ' $Format: % H$ '
2017-09-03 17:42:13 +02:00
import sys
2014-04-19 15:53:43 +02:00
import os
import uuid
import importlib
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
2016-04-22 10:38:48 +02:00
from qgis . PyQt . QtCore import QCoreApplication , QUrl
2015-07-26 03:48:27 +02:00
2017-01-09 12:34:46 +10:00
from qgis . core import ( QgsRasterLayer ,
2017-04-24 14:35:50 +10:00
QgsApplication ,
QgsProcessingUtils ,
2017-05-16 15:21:41 +10:00
QgsMessageLog ,
2017-05-16 16:36:00 +10:00
QgsProcessingAlgorithm ,
2017-09-01 17:53:33 +02:00
QgsProcessingParameterDefinition ,
QgsProcessingException ,
QgsProcessingParameterExtent ,
2017-09-03 17:42:13 +02:00
QgsProcessingParameterNumber ,
QgsProcessingParameterString ,
QgsProcessingParameterPoint ,
QgsProcessingParameterBoolean ,
QgsProcessingParameterVectorLayer ,
QgsProcessingParameterRasterLayer ,
QgsProcessingParameterMultipleLayers ,
QgsProcessingOutputVectorLayer ,
QgsProcessingOutputRasterLayer ,
QgsProcessingOutputHtml )
2014-05-20 16:30:59 +02:00
from qgis . utils import iface
2014-04-19 15:53:43 +02:00
2017-09-01 17:53:33 +02:00
#from processing.core.GeoAlgorithm import GeoAlgorithm (replaced by QgsProcessingAlgorithm)
2014-04-19 15:53:43 +02:00
from processing . core . ProcessingConfig import ProcessingConfig
2017-09-01 17:53:33 +02:00
#from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException (replaced by QgsProcessingException).
2014-04-19 15:53:43 +02:00
2017-09-03 17:42:13 +02:00
from processing . core . parameters import ( getParameterFromString )
#ParameterVector,
#ParameterMultipleInput,
2017-09-01 17:53:33 +02:00
#ParameterExtent,
#ParameterNumber,
#ParameterSelection,
2017-09-03 17:42:13 +02:00
#ParameterRaster,
#ParameterTable,
#ParameterBoolean,
#ParameterString,
#ParameterPoint)
#from processing.core.outputs import (getOutputFromString,
# OutputRaster,
# OutputVector,
# OutputFile,
# OutputHTML)
2014-04-19 15:53:43 +02:00
2016-03-21 04:58:12 +01:00
from . Grass7Utils import Grass7Utils
2014-04-19 15:53:43 +02:00
from processing . tools import dataobjects , system
2015-05-18 19:51:26 +03:00
pluginPath = os . path . normpath ( os . path . join (
os . path . split ( os . path . dirname ( __file__ ) ) [ 0 ] , os . pardir ) )
2014-04-19 15:53:43 +02:00
2017-09-01 17:53:33 +02:00
class Grass7Algorithm ( QgsProcessingAlgorithm ) :
2014-04-19 15:53:43 +02:00
GRASS_OUTPUT_TYPE_PARAMETER = ' GRASS_OUTPUT_TYPE_PARAMETER '
GRASS_MIN_AREA_PARAMETER = ' GRASS_MIN_AREA_PARAMETER '
GRASS_SNAP_TOLERANCE_PARAMETER = ' GRASS_SNAP_TOLERANCE_PARAMETER '
GRASS_REGION_EXTENT_PARAMETER = ' GRASS_REGION_PARAMETER '
GRASS_REGION_CELLSIZE_PARAMETER = ' GRASS_REGION_CELLSIZE_PARAMETER '
GRASS_REGION_ALIGN_TO_RESOLUTION = ' -a_r.region '
OUTPUT_TYPES = [ ' auto ' , ' point ' , ' line ' , ' area ' ]
def __init__ ( self , descriptionfile ) :
2017-09-01 17:53:33 +02:00
super ( ) . __init__ ( )
#GeoAlgorithm.__init__(self)
2017-03-29 12:51:59 +10:00
self . _name = ' '
self . _display_name = ' '
2017-03-29 12:04:09 +10:00
self . _group = ' '
2017-09-01 17:53:33 +02:00
self . grass7Name = ' '
2017-09-03 17:42:13 +02:00
self . params = [ ]
2015-10-22 09:44:19 +02:00
self . hardcodedStrings = [ ]
2014-04-19 15:53:43 +02:00
self . descriptionFile = descriptionfile
self . defineCharacteristicsFromFile ( )
self . numExportedLayers = 0
2017-03-04 16:23:36 +01:00
self . uniqueSuffix = str ( uuid . uuid4 ( ) ) . replace ( ' - ' , ' ' )
2015-12-16 17:39:16 +01:00
# Use the ext mechanism
2017-04-03 20:35:03 +10:00
name = self . name ( ) . replace ( ' . ' , ' _ ' )
2015-12-16 17:39:16 +01:00
try :
self . module = importlib . import_module ( ' processing.algs.grass7.ext. ' + name )
except ImportError :
self . module = None
2014-04-19 15:53:43 +02:00
2017-03-29 12:51:59 +10:00
def name ( self ) :
return self . _name
def displayName ( self ) :
return self . _display_name
2017-03-29 12:04:09 +10:00
def group ( self ) :
return self . _group
2017-03-29 10:42:42 +10:00
def icon ( self ) :
return QgsApplication . getThemeIcon ( " /providerGrass.svg " )
def svgIconPath ( self ) :
return QgsApplication . iconPath ( " providerGrass.svg " )
2016-09-14 06:42:04 +10:00
2017-09-01 17:53:33 +02:00
def tr ( self , string , context = ' ' ) :
if context == ' ' :
context = self . __class__ . __name__
return QCoreApplication . translate ( context , string )
2017-05-15 13:09:41 +10:00
def helpUrl ( self ) :
2017-01-09 15:32:42 +02:00
helpPath = Grass7Utils . grassHelpPath ( )
if helpPath == ' ' :
2017-05-15 13:09:41 +10:00
return None
2017-01-09 15:32:42 +02:00
if os . path . exists ( helpPath ) :
2017-05-15 13:09:41 +10:00
return QUrl . fromLocalFile ( os . path . join ( helpPath , ' {} .html ' . format ( self . grass7Name ) ) ) . toString ( )
2016-03-06 11:48:41 +01:00
else :
2017-05-15 13:09:41 +10:00
return helpPath + ' {} .html ' . format ( self . grass7Name )
2014-04-19 15:53:43 +02:00
def getParameterDescriptions ( self ) :
descs = { }
2014-08-17 09:10:31 +02:00
_ , helpfile = self . help ( )
2014-04-19 15:53:43 +02:00
try :
2016-11-07 10:35:15 +10:00
with open ( helpfile ) as infile :
lines = infile . readlines ( )
for i in range ( len ( lines ) ) :
if lines [ i ] . startswith ( ' <DT><b> ' ) :
2017-05-17 08:12:43 +10:00
for param in self . parameterDefinitions ( ) :
searchLine = ' <b> ' + param . name ( ) + ' </b> '
2016-11-07 10:35:15 +10:00
if searchLine in lines [ i ] :
i + = 1
2017-05-17 08:12:43 +10:00
descs [ param . name ( ) ] = ( lines [ i ] ) [ 4 : - 6 ]
2016-11-07 10:35:15 +10:00
break
2014-07-14 14:19:09 +02:00
except Exception :
pass
2014-04-19 15:53:43 +02:00
return descs
2017-09-03 17:42:13 +02:00
def initAlgorithm ( self , config = None ) :
for p in self . params :
self . addParameter ( p )
2014-04-19 15:53:43 +02:00
def defineCharacteristicsFromFile ( self ) :
2017-09-01 17:53:33 +02:00
"""
Create algorithm parameters and outputs from a text file .
"""
2016-11-07 10:35:15 +10:00
with open ( self . descriptionFile ) as lines :
2017-09-01 17:53:33 +02:00
# First line of the file is the Grass algorithm name
2016-11-07 10:35:15 +10:00
line = lines . readline ( ) . strip ( ' \n ' ) . strip ( )
self . grass7Name = line
2017-09-01 17:53:33 +02:00
# Second line if the algorithm name in Processing
2016-11-07 10:35:15 +10:00
line = lines . readline ( ) . strip ( ' \n ' ) . strip ( )
2017-03-29 12:51:59 +10:00
self . _name = line
self . _display_name = QCoreApplication . translate ( " GrassAlgorithm " , line )
if " - " not in self . _name :
self . _name = self . grass7Name + " - " + self . _name
self . _display_name = self . grass7Name + " - " + self . _display_name
2017-03-29 17:09:39 +10:00
self . _name = self . _name [ : self . _name . find ( ' ' ) ] . lower ( )
2017-09-01 17:53:33 +02:00
# Read the grass group
2016-11-07 10:35:15 +10:00
line = lines . readline ( ) . strip ( ' \n ' ) . strip ( )
2017-03-29 12:04:09 +10:00
self . _group = QCoreApplication . translate ( " GrassAlgorithm " , line )
2016-11-07 10:35:15 +10:00
hasRasterOutput = False
hasVectorInput = False
vectorOutputs = 0
2017-09-01 17:53:33 +02:00
# Then you have parameters/output definition
2016-11-07 10:35:15 +10:00
line = lines . readline ( ) . strip ( ' \n ' ) . strip ( )
while line != ' ' :
try :
line = line . strip ( ' \n ' ) . strip ( )
if line . startswith ( ' Hardcoded ' ) :
self . hardcodedStrings . append ( line [ len ( ' Hardcoded| ' ) : ] )
parameter = getParameterFromString ( line )
if parameter is not None :
2017-09-03 17:42:13 +02:00
self . params . append ( parameter )
if isinstance ( parameter , QgsProcessingParameterVectorLayer ) :
2016-11-07 10:35:15 +10:00
hasVectorInput = True
2017-09-03 17:42:13 +02:00
if isinstance ( parameter , QgsProcessingParameterMultipleLayers ) \
and parameter . layerType ( ) < 3 :
2016-11-07 10:35:15 +10:00
hasVectorInput = True
2017-09-03 17:42:13 +02:00
#else:
# output = Grass7Utils.getOutputFromString(line)
# self.addOutput(output)
# if isinstance(output, QgsProcessingOutputRasterLayer):
# hasRasterOutput = True
# elif isinstance(output, QgsProcessingOutputVectorLayer):
# vectorOutputs += 1
# if isinstance(output, QgsProcessingOutputHtml):
# self.addOutput(OutputFile("rawoutput",
# self.tr("{0} (raw output)").format(output.description()),
# "txt"))
2016-11-07 10:35:15 +10:00
line = lines . readline ( ) . strip ( ' \n ' ) . strip ( )
except Exception as e :
2017-04-26 12:52:23 +10:00
QgsMessageLog . logMessage ( self . tr ( ' Could not open GRASS GIS 7 algorithm: {0} \n {1} ' ) . format ( self . descriptionFile , line ) , self . tr ( ' Processing ' ) , QgsMessageLog . CRITICAL )
2016-11-07 10:35:15 +10:00
raise e
2014-04-19 15:53:43 +02:00
2017-09-01 17:53:33 +02:00
self . addParameter ( QgsProcessingParameterExtent (
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
self . GRASS_REGION_EXTENT_PARAMETER ,
self . tr ( ' GRASS GIS 7 region extent ' ) )
)
2014-04-19 15:53:43 +02:00
if hasRasterOutput :
2017-09-01 17:53:33 +02:00
self . addParameter ( QgsProcessingParameterNumber (
2014-04-19 15:53:43 +02:00
self . GRASS_REGION_CELLSIZE_PARAMETER ,
2015-01-16 15:56:05 +02:00
self . tr ( ' GRASS GIS 7 region cellsize (leave 0 for default) ' ) ,
2017-09-01 17:53:33 +02:00
type = QgsProcessingParameterNumber . Double ,
2017-09-03 17:42:13 +02:00
minValue = 0.0 , maxValue = sys . float_info . max + 1 , defaultValue = 0.0 )
2017-09-01 17:53:33 +02:00
)
2014-04-19 15:53:43 +02:00
if hasVectorInput :
2017-09-01 17:53:33 +02:00
param = QgsProcessingParameterNumber ( self . GRASS_SNAP_TOLERANCE_PARAMETER ,
self . tr ( ' v.in.ogr snap tolerance (-1 = no snap) ' ) ,
type = QgsProcessingParameterNumber . Double ,
2017-09-03 17:42:13 +02:00
minValue = - 1.0 , maxValue = sys . float_info . max + 1 ,
defaultValue = - 1.0 )
2017-05-16 16:36:00 +10:00
param . setFlags ( param . flags ( ) | QgsProcessingParameterDefinition . FlagAdvanced )
2014-04-19 15:53:43 +02:00
self . addParameter ( param )
2017-09-01 17:53:33 +02:00
param = QgsProcessingParameterNumber ( self . GRASS_MIN_AREA_PARAMETER ,
self . tr ( ' v.in.ogr min area ' ) ,
2017-09-03 17:42:13 +02:00
type = QgsProcessingParameterNumber . Double ,
minValue = 0.0 , maxValue = sys . float_info . max + 1 ,
defaultValue = 0.0001 )
2017-05-16 16:36:00 +10:00
param . setFlags ( param . flags ( ) | QgsProcessingParameterDefinition . FlagAdvanced )
2014-04-19 15:53:43 +02:00
self . addParameter ( param )
if vectorOutputs == 1 :
2017-09-01 17:53:33 +02:00
param = QgsProcessingParameterEnum ( self . GRASS_OUTPUT_TYPE_PARAMETER ,
self . tr ( ' v.out.ogr output type ' ) ,
self . OUTPUT_TYPES )
2017-05-16 16:36:00 +10:00
param . setFlags ( param . flags ( ) | QgsProcessingParameterDefinition . FlagAdvanced )
2014-04-19 15:53:43 +02:00
self . addParameter ( param )
2017-05-17 08:12:43 +10:00
def getDefaultCellsize ( self , parameters , context ) :
2014-04-19 15:53:43 +02:00
cellsize = 0
2017-05-17 08:12:43 +10:00
for param in self . parameterDefinitions ( ) :
if param . name ( ) in parameters :
value = parameters [ param . name ( ) ]
2014-04-19 15:53:43 +02:00
if isinstance ( param , ParameterRaster ) :
2017-05-17 08:12:43 +10:00
if isinstance ( value , QgsRasterLayer ) :
layer = value
2014-04-19 15:53:43 +02:00
else :
2017-05-02 13:40:49 +10:00
layer = QgsProcessingUtils . mapLayerFromString ( param . value , context )
2017-03-04 16:23:36 +01:00
cellsize = max ( cellsize , ( layer . extent ( ) . xMaximum ( ) -
layer . extent ( ) . xMinimum ( ) ) /
layer . width ( ) )
2014-04-19 15:53:43 +02:00
elif isinstance ( param , ParameterMultipleInput ) :
2017-05-17 08:12:43 +10:00
layers = value . split ( ' ; ' )
2014-04-19 15:53:43 +02:00
for layername in layers :
2017-05-02 13:40:49 +10:00
layer = QgsProcessingUtils . mapLayerFromString ( layername , context )
2014-04-19 15:53:43 +02:00
if isinstance ( layer , QgsRasterLayer ) :
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
cellsize = max ( cellsize , (
2017-03-04 16:23:36 +01:00
layer . extent ( ) . xMaximum ( ) -
layer . extent ( ) . xMinimum ( ) ) /
layer . width ( )
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
)
2014-04-19 15:53:43 +02:00
if cellsize == 0 :
2015-04-26 11:33:03 +01:00
cellsize = 100
2014-04-19 15:53:43 +02:00
return cellsize
2017-05-15 16:19:46 +10:00
def processAlgorithm ( self , parameters , context , feedback ) :
2014-04-19 15:53:43 +02:00
if system . isWindows ( ) :
path = Grass7Utils . grassPath ( )
if path == ' ' :
2017-09-01 17:53:33 +02:00
raise QgsProcessingException (
2015-01-16 15:56:05 +02:00
self . tr ( ' GRASS GIS 7 folder is not configured. Please '
' configure it before running GRASS GIS 7 algorithms. ' ) )
2016-01-02 16:14:41 +01:00
2015-12-16 17:39:16 +01:00
# Create brand new commands lists
self . commands = [ ]
self . outputCommands = [ ]
2014-04-19 15:53:43 +02:00
self . exportedLayers = { }
# If GRASS session has been created outside of this algorithm then
# get the list of layers loaded in GRASS otherwise start a new
# session
existingSession = Grass7Utils . sessionRunning
if existingSession :
self . exportedLayers = Grass7Utils . getSessionLayers ( )
else :
Grass7Utils . startGrass7Session ( )
2015-12-16 17:39:16 +01:00
# Handle ext functions for inputs/command/outputs
if self . module :
if hasattr ( self . module , ' processInputs ' ) :
func = getattr ( self . module , ' processInputs ' )
func ( self )
else :
2017-05-22 16:19:13 +10:00
self . processInputs ( parameters , context )
2016-01-02 16:14:41 +01:00
2015-12-16 17:39:16 +01:00
if hasattr ( self . module , ' processCommand ' ) :
func = getattr ( self . module , ' processCommand ' )
func ( self )
else :
self . processCommand ( )
2016-01-02 16:14:41 +01:00
2015-12-16 17:39:16 +01:00
if hasattr ( self . module , ' processOutputs ' ) :
func = getattr ( self . module , ' processOutputs ' )
func ( self )
else :
self . processOutputs ( )
else :
2017-05-22 16:19:13 +10:00
self . processInputs ( parameters , context )
2015-12-16 17:39:16 +01:00
self . processCommand ( )
self . processOutputs ( )
# Run GRASS
loglines = [ ]
2016-01-14 12:19:31 +01:00
loglines . append ( self . tr ( ' GRASS GIS 7 execution commands ' ) )
2015-12-16 17:39:16 +01:00
for line in self . commands :
2017-01-06 20:04:00 +10:00
feedback . pushCommandInfo ( line )
2015-12-16 17:39:16 +01:00
loglines . append ( line )
if ProcessingConfig . getSetting ( Grass7Utils . GRASS_LOG_COMMANDS ) :
2017-04-30 12:46:31 +03:00
QgsMessageLog . logMessage ( " \n " . join ( loglines ) , self . tr ( ' Processing ' ) , QgsMessageLog . INFO )
2015-12-16 17:39:16 +01:00
2017-01-06 20:04:00 +10:00
Grass7Utils . executeGrass7 ( self . commands , feedback , self . outputCommands )
2015-12-16 17:39:16 +01:00
for out in self . outputs :
if isinstance ( out , OutputHTML ) :
with open ( self . getOutputFromName ( " rawoutput " ) . value ) as f :
rawOutput = " " . join ( f . readlines ( ) )
with open ( out . value , " w " ) as f :
f . write ( " <pre> %s </pre> " % rawOutput )
# If the session has been created outside of this algorithm, add
# the new GRASS GIS 7 layers to it otherwise finish the session
if existingSession :
Grass7Utils . addSessionLayers ( self . exportedLayers )
else :
Grass7Utils . endGrass7Session ( )
2014-04-19 15:53:43 +02:00
2017-05-17 08:12:43 +10:00
def processInputs ( self , parameters , context ) :
2015-12-16 17:39:16 +01:00
""" Prepare the GRASS import commands """
2017-05-17 08:12:43 +10:00
for param in self . parameterDefinitions ( ) :
2014-04-19 15:53:43 +02:00
if isinstance ( param , ParameterRaster ) :
2017-05-17 08:12:43 +10:00
if not param . name ( ) in parameters ( ) :
2014-04-19 15:53:43 +02:00
continue
2017-05-17 08:12:43 +10:00
value = parameters [ param . name ( ) ]
2014-04-19 15:53:43 +02:00
# Check if the layer hasn't already been exported in, for
# example, previous GRASS calls in this session
2016-09-21 18:24:26 +02:00
if value in list ( self . exportedLayers . keys ( ) ) :
2014-04-19 15:53:43 +02:00
continue
else :
2015-12-16 17:39:16 +01:00
self . setSessionProjectionFromLayer ( value , self . commands )
self . commands . append ( self . exportRasterLayer ( value ) )
2014-04-19 15:53:43 +02:00
if isinstance ( param , ParameterVector ) :
2017-05-17 08:12:43 +10:00
if not param . name ( ) in parameters ( ) :
2014-04-19 15:53:43 +02:00
continue
2017-05-17 08:12:43 +10:00
value = parameters [ param . name ( ) ]
2016-09-21 18:24:26 +02:00
if value in list ( self . exportedLayers . keys ( ) ) :
2014-04-19 15:53:43 +02:00
continue
else :
2015-12-16 17:39:16 +01:00
self . setSessionProjectionFromLayer ( value , self . commands )
self . commands . append ( self . exportVectorLayer ( value ) )
2014-04-19 15:53:43 +02:00
if isinstance ( param , ParameterTable ) :
pass
if isinstance ( param , ParameterMultipleInput ) :
2017-05-17 08:12:43 +10:00
if not param . name ( ) in parameters ( ) :
2014-04-19 15:53:43 +02:00
continue
2017-05-17 08:12:43 +10:00
value = parameters [ param . name ( ) ]
layers = value . split ( ' ; ' )
2014-04-19 15:53:43 +02:00
if layers is None or len ( layers ) == 0 :
continue
2016-08-23 19:33:42 +03:00
if param . datatype == dataobjects . TYPE_RASTER :
2014-04-19 15:53:43 +02:00
for layer in layers :
2016-09-21 18:24:26 +02:00
if layer in list ( self . exportedLayers . keys ( ) ) :
2014-04-19 15:53:43 +02:00
continue
else :
2015-12-16 17:39:16 +01:00
self . setSessionProjectionFromLayer ( layer , self . commands )
self . commands . append ( self . exportRasterLayer ( layer ) )
2016-08-23 19:33:42 +03:00
elif param . datatype in [ dataobjects . TYPE_VECTOR_ANY ,
dataobjects . TYPE_VECTOR_LINE ,
dataobjects . TYPE_VECTOR_POLYGON ,
dataobjects . TYPE_VECTOR_POINT ] :
2014-04-19 15:53:43 +02:00
for layer in layers :
2016-09-21 18:24:26 +02:00
if layer in list ( self . exportedLayers . keys ( ) ) :
2014-04-19 15:53:43 +02:00
continue
else :
2015-12-16 17:39:16 +01:00
self . setSessionProjectionFromLayer ( layer , self . commands )
self . commands . append ( self . exportVectorLayer ( layer ) )
2014-04-19 15:53:43 +02:00
2015-12-16 17:39:16 +01:00
self . setSessionProjectionFromProject ( self . commands )
2014-04-19 15:53:43 +02:00
2015-07-26 03:48:27 +02:00
region = \
2016-09-21 18:24:26 +02:00
str ( self . getParameterValue ( self . GRASS_REGION_EXTENT_PARAMETER ) )
2017-05-17 07:41:15 +10:00
if not region :
region = QgsProcessingUtils . combineLayerExtents ( layers )
2014-04-19 15:53:43 +02:00
regionCoords = region . split ( ' , ' )
command = ' g.region '
2016-09-21 18:24:26 +02:00
command + = ' n= ' + str ( regionCoords [ 3 ] )
command + = ' s= ' + str ( regionCoords [ 2 ] )
command + = ' e= ' + str ( regionCoords [ 1 ] )
command + = ' w= ' + str ( regionCoords [ 0 ] )
2014-04-19 15:53:43 +02:00
cellsize = self . getParameterValue ( self . GRASS_REGION_CELLSIZE_PARAMETER )
if cellsize :
2016-09-21 18:24:26 +02:00
command + = ' res= ' + str ( cellsize )
2014-04-19 15:53:43 +02:00
else :
2017-05-17 08:12:43 +10:00
command + = ' res= ' + str ( self . getDefaultCellsize ( parameters , context ) )
2014-04-19 15:53:43 +02:00
alignToResolution = \
self . getParameterValue ( self . GRASS_REGION_ALIGN_TO_RESOLUTION )
if alignToResolution :
command + = ' -a '
2015-12-16 17:39:16 +01:00
self . commands . append ( command )
2014-04-19 15:53:43 +02:00
2017-05-15 16:19:46 +10:00
def processCommand ( self , parameters ) :
""" Prepare the GRASS algorithm command
: param parameters :
"""
2015-05-20 11:24:05 +03:00
command = self . grass7Name
2015-10-22 09:44:19 +02:00
command + = ' ' + ' ' . join ( self . hardcodedStrings )
2015-12-16 17:39:16 +01:00
# Add algorithm command
2017-05-16 16:36:00 +10:00
for param in self . parameterDefinitions ( ) :
2014-04-19 15:53:43 +02:00
if param . value is None or param . value == ' ' :
continue
2015-08-22 14:29:41 +02:00
if param . name in [ self . GRASS_REGION_CELLSIZE_PARAMETER , self . GRASS_REGION_EXTENT_PARAMETER , self . GRASS_MIN_AREA_PARAMETER , self . GRASS_SNAP_TOLERANCE_PARAMETER , self . GRASS_OUTPUT_TYPE_PARAMETER , self . GRASS_REGION_ALIGN_TO_RESOLUTION ] :
2014-04-19 15:53:43 +02:00
continue
if isinstance ( param , ( ParameterRaster , ParameterVector ) ) :
value = param . value
2016-09-21 18:24:26 +02:00
if value in list ( self . exportedLayers . keys ( ) ) :
2017-05-16 16:36:00 +10:00
command + = ' ' + param . name ( ) + ' = ' \
2014-04-19 15:53:43 +02:00
+ self . exportedLayers [ value ]
else :
2017-05-16 16:36:00 +10:00
command + = ' ' + param . name ( ) + ' = ' + value
2014-04-19 15:53:43 +02:00
elif isinstance ( param , ParameterMultipleInput ) :
s = param . value
2016-09-21 18:24:26 +02:00
for layer in list ( self . exportedLayers . keys ( ) ) :
2014-04-19 15:53:43 +02:00
s = s . replace ( layer , self . exportedLayers [ layer ] )
s = s . replace ( ' ; ' , ' , ' )
2017-05-16 16:36:00 +10:00
command + = ' ' + param . name ( ) + ' = ' + s
2014-04-19 15:53:43 +02:00
elif isinstance ( param , ParameterBoolean ) :
if param . value :
2017-05-16 16:36:00 +10:00
command + = ' ' + param . name ( )
2017-09-01 17:53:33 +02:00
elif isinstance ( param , QgsProcessingParameterEnum ) :
2014-04-19 15:53:43 +02:00
idx = int ( param . value )
2017-05-16 16:36:00 +10:00
command + = ' ' + param . name ( ) + ' = ' + str ( param . options [ idx ] [ 1 ] )
2014-04-19 15:53:43 +02:00
elif isinstance ( param , ParameterString ) :
2017-05-16 16:36:00 +10:00
command + = ' ' + param . name ( ) + ' = " ' + str ( param . value ) + ' " '
2016-02-22 20:14:28 +02:00
elif isinstance ( param , ParameterPoint ) :
2017-05-16 16:36:00 +10:00
command + = ' ' + param . name ( ) + ' = ' + str ( param . value )
2014-04-19 15:53:43 +02:00
else :
2017-05-16 16:36:00 +10:00
command + = ' ' + param . name ( ) + ' = " ' + str ( param . value ) + ' " '
2016-01-02 16:14:41 +01:00
2014-04-19 15:53:43 +02:00
for out in self . outputs :
if isinstance ( out , OutputFile ) :
2015-06-23 13:31:42 +02:00
command + = ' > ' + out . value
2014-04-19 15:53:43 +02:00
elif not isinstance ( out , OutputHTML ) :
2015-06-23 13:31:42 +02:00
# We add an output name to make sure it is unique if the session
# uses this algorithm several times.
2017-03-04 16:23:36 +01:00
uniqueOutputName = out . name + self . uniqueSuffix
2014-04-19 15:53:43 +02:00
command + = ' ' + out . name + ' = ' + uniqueOutputName
# Add output file to exported layers, to indicate that
# they are present in GRASS
self . exportedLayers [ out . value ] = uniqueOutputName
command + = ' --overwrite '
2015-12-16 17:39:16 +01:00
self . commands . append ( command )
2016-01-02 16:14:41 +01:00
2015-12-16 17:39:16 +01:00
def processOutputs ( self ) :
""" Prepare the GRASS v.out.ogr commands """
2014-04-19 15:53:43 +02:00
for out in self . outputs :
if isinstance ( out , OutputRaster ) :
filename = out . value
# Raster layer output: adjust region to layer before
# exporting
2017-03-04 16:23:36 +01:00
self . commands . append ( ' g.region raster= ' + out . name + self . uniqueSuffix )
self . outputCommands . append ( ' g.region raster= ' + out . name +
self . uniqueSuffix )
2015-05-27 10:34:32 +03:00
2015-05-30 07:24:41 +01:00
if self . grass7Name == ' r.statistics ' :
2015-05-27 10:34:32 +03:00
# r.statistics saves its results in a non-qgis compatible
# way. Post-process them with r.mapcalc.
2017-03-04 16:23:36 +01:00
calcExpression = ' correctedoutput ' + self . uniqueSuffix
calcExpression + = ' =@ ' + out . name + self . uniqueSuffix
2015-05-19 17:13:42 +02:00
command = ' r.mapcalc expression= " ' + calcExpression + ' " '
2015-12-16 17:39:16 +01:00
self . commands . append ( command )
self . outputCommands . append ( command )
2015-05-27 10:34:32 +03:00
2016-02-09 09:46:12 +01:00
command = ' r.out.gdal --overwrite -c createopt= " TFW=YES,COMPRESS=LZW " '
2015-05-19 17:13:42 +02:00
command + = ' input= '
2017-03-04 16:23:36 +01:00
command + = ' correctedoutput ' + self . uniqueSuffix
2015-05-19 17:13:42 +02:00
command + = ' output= " ' + filename + ' " '
2014-04-19 15:53:43 +02:00
else :
2016-02-09 09:46:12 +01:00
command = ' r.out.gdal --overwrite -c createopt= " TFW=YES,COMPRESS=LZW " '
2014-04-19 15:53:43 +02:00
command + = ' input= '
2015-05-20 11:24:05 +03:00
if self . grass7Name == ' r.horizon ' :
2017-03-04 16:23:36 +01:00
command + = out . name + self . uniqueSuffix + ' _0 '
2015-05-27 10:34:32 +03:00
elif self . grass7Name == ' r.statistics ' :
2015-12-16 17:39:16 +01:00
self . commands . append ( command )
self . outputCommands . append ( command )
2014-04-19 15:53:43 +02:00
else :
2017-03-04 16:23:36 +01:00
command + = out . name + self . uniqueSuffix
2014-04-19 15:53:43 +02:00
command + = ' output= " ' + filename + ' " '
2015-12-16 17:39:16 +01:00
self . commands . append ( command )
self . outputCommands . append ( command )
2014-04-19 15:53:43 +02:00
if isinstance ( out , OutputVector ) :
filename = out . value
2015-08-16 20:57:24 +02:00
typeidx = self . getParameterValue ( self . GRASS_OUTPUT_TYPE_PARAMETER )
2015-06-04 16:55:27 +01:00
outtype = ( ' auto ' if typeidx
2015-08-22 14:29:41 +02:00
is None else self . OUTPUT_TYPES [ typeidx ] )
2015-05-24 12:22:11 +01:00
if self . grass7Name == ' r.flow ' :
2017-03-04 16:23:36 +01:00
command = ' v.out.ogr type=line layer=0 -s -e input= ' + out . name + self . uniqueSuffix
2015-06-04 16:55:27 +01:00
elif self . grass7Name == ' v.voronoi ' :
2015-12-16 17:39:16 +01:00
if ' -l ' in self . commands [ - 1 ] :
2017-03-04 16:23:36 +01:00
command = ' v.out.ogr type=line layer=0 -s -e input= ' + out . name + self . uniqueSuffix
2015-08-22 14:29:41 +02:00
else :
2017-03-04 16:23:36 +01:00
command = ' v.out.ogr -s -e input= ' + out . name + self . uniqueSuffix
2015-08-22 14:29:41 +02:00
command + = ' type= ' + outtype
2015-09-28 18:08:13 +01:00
elif self . grass7Name == ' v.sample ' :
2017-03-04 16:23:36 +01:00
command = ' v.out.ogr type=point -s -e input= ' + out . name + self . uniqueSuffix
2015-05-24 12:22:11 +01:00
else :
2017-03-04 16:23:36 +01:00
command = ' v.out.ogr -s -e input= ' + out . name + self . uniqueSuffix
2015-08-22 14:29:41 +02:00
command + = ' type= ' + outtype
2015-06-04 16:55:27 +01:00
command + = ' output= " ' + os . path . dirname ( out . value ) + ' " '
command + = ' format=ESRI_Shapefile '
2015-10-25 17:08:37 +00:00
command + = ' output_layer= ' + os . path . basename ( out . value ) [ : - 4 ]
2016-02-09 09:46:12 +01:00
command + = ' --overwrite '
2015-12-16 17:39:16 +01:00
self . commands . append ( command )
self . outputCommands . append ( command )
2016-01-02 16:14:41 +01:00
2014-04-19 15:53:43 +02:00
def exportVectorLayer ( self , orgFilename ) :
2017-05-01 17:40:47 +10:00
context = dataobjects . createContext ( )
2014-04-19 15:53:43 +02:00
# TODO: improve this. We are now exporting if it is not a shapefile,
# but the functionality of v.in.ogr could be used for this.
# We also export if there is a selection
if not os . path . exists ( orgFilename ) or not orgFilename . endswith ( ' shp ' ) :
2017-05-02 13:40:49 +10:00
layer = QgsProcessingUtils . mapLayerFromString ( orgFilename , context , False )
2014-04-19 15:53:43 +02:00
if layer :
filename = dataobjects . exportVectorLayer ( layer )
else :
2017-05-02 13:40:49 +10:00
layer = QgsProcessingUtils . mapLayerFromString ( orgFilename , context , False )
2014-04-19 15:53:43 +02:00
if layer :
2017-06-05 16:41:08 +10:00
#TODO
#useSelection = \
# ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED)
2014-04-19 15:53:43 +02:00
if useSelection and layer . selectedFeatureCount ( ) != 0 :
filename = dataobjects . exportVectorLayer ( layer )
else :
filename = orgFilename
else :
filename = orgFilename
2017-03-24 08:35:57 +07:00
destFilename = ' a ' + os . path . basename ( self . getTempFilename ( ) )
2014-04-19 15:53:43 +02:00
self . exportedLayers [ orgFilename ] = destFilename
command = ' v.in.ogr '
min_area = self . getParameterValue ( self . GRASS_MIN_AREA_PARAMETER )
2016-09-21 18:24:26 +02:00
command + = ' min_area= ' + str ( min_area )
2014-04-19 15:53:43 +02:00
snap = self . getParameterValue ( self . GRASS_SNAP_TOLERANCE_PARAMETER )
2016-09-21 18:24:26 +02:00
command + = ' snap= ' + str ( snap )
2014-12-04 21:57:19 +01:00
command + = ' input= " ' + os . path . dirname ( filename ) + ' " '
2014-04-19 15:53:43 +02:00
command + = ' layer= ' + os . path . basename ( filename ) [ : - 4 ]
command + = ' output= ' + destFilename
command + = ' --overwrite -o '
return command
def setSessionProjectionFromProject ( self , commands ) :
2016-05-06 12:02:59 +02:00
if not Grass7Utils . projectionSet and iface :
2016-01-20 16:39:13 +02:00
proj4 = iface . mapCanvas ( ) . mapSettings ( ) . destinationCrs ( ) . toProj4 ( )
2014-04-19 15:53:43 +02:00
command = ' g.proj '
command + = ' -c '
command + = ' proj4= " ' + proj4 + ' " '
2015-12-16 17:39:16 +01:00
self . commands . append ( command )
2014-04-19 15:53:43 +02:00
Grass7Utils . projectionSet = True
def setSessionProjectionFromLayer ( self , layer , commands ) :
2017-05-01 17:40:47 +10:00
context = dataobjects . createContext ( )
2014-04-19 15:53:43 +02:00
if not Grass7Utils . projectionSet :
2017-05-02 13:40:49 +10:00
qGisLayer = QgsProcessingUtils . mapLayerFromString ( layer , context )
2014-04-19 15:53:43 +02:00
if qGisLayer :
2016-09-21 18:24:26 +02:00
proj4 = str ( qGisLayer . crs ( ) . toProj4 ( ) )
2014-04-19 15:53:43 +02:00
command = ' g.proj '
command + = ' -c '
command + = ' proj4= " ' + proj4 + ' " '
2015-12-16 17:39:16 +01:00
self . commands . append ( command )
2014-04-19 15:53:43 +02:00
Grass7Utils . projectionSet = True
def exportRasterLayer ( self , layer ) :
2017-03-24 08:35:57 +07:00
destFilename = ' a ' + os . path . basename ( self . getTempFilename ( ) )
2014-04-19 15:53:43 +02:00
self . exportedLayers [ layer ] = destFilename
command = ' r.external '
command + = ' input= " ' + layer + ' " '
command + = ' band=1 '
command + = ' output= ' + destFilename
command + = ' --overwrite -o '
return command
def getTempFilename ( self ) :
2017-09-01 17:53:33 +02:00
# TODO Replace with QgsProcessingUtils generateTempFilename
2017-01-31 12:41:37 +01:00
return system . getTempFilename ( )
2014-04-19 15:53:43 +02:00
2017-05-15 12:08:26 +10:00
def canExecute ( self ) :
message = Grass7Utils . checkGrass7IsInstalled ( )
return not message , message
2014-04-19 15:53:43 +02:00
2017-05-16 15:21:41 +10:00
def checkParameterValues ( self , parameters , context ) :
2015-12-16 17:39:16 +01:00
if self . module :
if hasattr ( self . module , ' checkParameterValuesBeforeExecuting ' ) :
func = getattr ( self . module , ' checkParameterValuesBeforeExecuting ' )
2017-05-16 15:21:41 +10:00
return func ( self ) , None
return super ( Grass7Algorithm , self ) . checkParameterValues ( parameters , context )