Navigation Menu

Skip to content

Commit

Permalink
Improve cell size detection and FileDestinationOutput (but not perfect)
Browse files Browse the repository at this point in the history
  • Loading branch information
Médéric Ribreux committed Nov 4, 2017
1 parent f32bba4 commit 6bf8448
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 52 deletions.
103 changes: 51 additions & 52 deletions python/plugins/processing/algs/grass7/Grass7Algorithm.py
Expand Up @@ -57,7 +57,8 @@
QgsProcessingParameterFileDestination,
QgsProcessingOutputVectorLayer,
QgsProcessingOutputRasterLayer,
QgsProcessingOutputHtml)
QgsProcessingOutputHtml,
QgsProcessingUtils)
from qgis.utils import iface

from processing.core.ProcessingConfig import ProcessingConfig
Expand All @@ -66,7 +67,8 @@

from .Grass7Utils import Grass7Utils

from processing.tools import dataobjects, system
#from processing.tools import dataobjects, system
from processing.tools.system import isWindows, getTempFilename

pluginPath = os.path.normpath(os.path.join(
os.path.split(os.path.dirname(__file__))[0], os.pardir))
Expand Down Expand Up @@ -172,7 +174,12 @@ def initAlgorithm(self, config=None):
"""
for p in self.params:
# We use createOutput argument for automatic output creation
self.addParameter(p, True)
res = self.addParameter(p, True)
# File destinations are not automatically added as outputs
if isinstance(p, QgsProcessingParameterFileDestination):
self.addOutput(QgsProcessingOutputHtml(p.name(), p.description()))
QgsMessageLog.logMessage('initAlgorithm {} ({}):{}'.format(p.name(), p.isDestination(), res), 'Grass7', QgsMessageLog.INFO)
QgsMessageLog.logMessage('initAlgo: {}'.format(p.toOutputDefinition()), 'Grass7', QgsMessageLog.INFO)

def defineCharacteristicsFromFile(self):
"""
Expand Down Expand Up @@ -266,39 +273,27 @@ def getDefaultCellSize(self, parameters, context):
"""
Determine a default cell size from all the raster layers.
"""
if self.cellSize:
return True

cellsize = 0
parameters = [p for p in self.parameterDefinitions()
cellsize = 0.0
layerParams = [p for p in self.parameterDefinitions()
if isinstance(p, (QgsProcessingParameterRasterLayer,
QgsProcessingParameterMultipleLayers))]
cz = lambda l, cellsize: max(cellsize, (l.extent().xMaximum() - l.extent().xMinimum()) / l.width())

for param in parameters:
for param in layerParams:
paramName = param.name()
if isinstance(param, QgsProcessingParameterRasterLayer):
layer = self.parameterAsExtent(parameters, paramName, context)
cellsize = max(cellsize, (layer.extent().xMaximum() -
layer.extent().xMinimum()) /
layer.width())
#cellsize = cz(layer, cellsize)
layer = self.parameterAsLayer(parameters, paramName, context)
cellsize = cz(layer, cellsize)
elif isinstance(param, QgsProcessingParameterMultipleLayers):
layers = self.parameterAsLayerList(parameters, paramName, context)
for layer in layers:
if layer.type() == QgsMapLayer.RasterLayer:
#cellsize = cz(layer, cellsize)
cellsize = max(cellsize, (
layer.extent().xMaximum() -
layer.extent().xMinimum()) /
layer.width())

QgsMessageLog.logMessage('cellSize: {}'.format(cellsize), 'Grass7', QgsMessageLog.INFO)
if cellsize == 0:
return False
else:
self.cellSize = cellsize
return True
cellsize = cz(layer, cellsize)

if cellsize == 0.0:
cellsize = 100.0

return cellsize

def grabDefaultGrassParameters(self, parameters, context):
"""
Expand All @@ -309,11 +304,11 @@ def grabDefaultGrassParameters(self, parameters, context):
self.region = self.parameterAsExtent(parameters,
self.GRASS_REGION_EXTENT_PARAMETER,
context)
QgsMessageLog.logMessage('processAlgorithm self.region: {}'.format(self.region.isEmpty()), 'Grass7', QgsMessageLog.INFO)
# GRASS cell size
self.cellSize = self.parameterAsString(parameters,
self.GRASS_REGION_CELLSIZE_PARAMETER,
context)
if self.parameterDefinition(self.GRASS_REGION_CELLSIZE_PARAMETER):
self.cellSize = self.parameterAsDouble(parameters,
self.GRASS_REGION_CELLSIZE_PARAMETER,
context)
# GRASS snap tolerance
self.snapTolerance = self.parameterAsDouble(parameters,
self.GRASS_SNAP_TOLERANCE_PARAMETER,
Expand All @@ -332,7 +327,7 @@ def grabDefaultGrassParameters(self, parameters, context):
context)

def processAlgorithm(self, parameters, context, feedback):
if system.isWindows():
if isWindows():
path = Grass7Utils.grassPath()
if path == '':
raise QgsProcessingException(
Expand Down Expand Up @@ -407,6 +402,7 @@ def processAlgorithm(self, parameters, context, feedback):
Grass7Utils.endGrass7Session()

# Return outputs map
QgsMessageLog.logMessage('outputDefinitions: {}'.format(self.outputDefinitions()), 'Grass7', QgsMessageLog.INFO)
outputs = {}
for outName in [o.name() for o in self.outputDefinitions()]:
if outName in parameters:
Expand Down Expand Up @@ -484,8 +480,12 @@ def processInputs(self, parameters, context):
self.region.xMaximum(), self.region.xMinimum()
)
# Handle cell size
if self.getDefaultCellSize(parameters, context):
command += ' res={}'.format(self.cellSize)
if self.parameterDefinition(self.GRASS_REGION_CELLSIZE_PARAMETER):
if self.cellSize:
cellSize = self.cellSize
else:
cellSize = self.getDefaultCellSize(parameters, context)
command += ' res={}'.format(cellSize)

# Handle align to resolution
if self.alignToResolution:
Expand All @@ -496,7 +496,8 @@ def processInputs(self, parameters, context):
QgsMessageLog.logMessage('processInputs end. Commands: {}'.format(self.commands), 'Grass7', QgsMessageLog.INFO)

def processCommand(self, parameters, context):
"""Prepare the GRASS algorithm command
"""
Prepare the GRASS algorithm command
:param parameters:
"""
noOutputs = [o for o in self.parameterDefinitions() if o not in self.destinationParameterDefinitions()]
Expand Down Expand Up @@ -646,6 +647,19 @@ def processOutputs(self, parameters, context):
self.outputCommands.append(command)
QgsMessageLog.logMessage('processOutputs. Commands: {}'.format(self.commands), 'Grass7', QgsMessageLog.INFO)

def exportRasterLayer(self, layerKey, layerSrc):
"""
Creates a dedicated command to load a raster into
temporary GRASS DB.
"""
# TODO: handle multiple bands
#destFileName = QgsProcessingUtils.generateTempFilename(layerKey)
destFilename = 'a' + os.path.basename(getTempFilename())
self.exportedLayers[layerKey] = destFilename
command = 'r.external input="{}" band=1 output={} --overwrite -o'.format(
layerSrc, destFilename)
return command

def exportVectorLayer(self, layerKey, layerSrc):
# TODO: learn about ProcessingContexts
#context = dataobjects.createContext()
Expand All @@ -671,7 +685,8 @@ def exportVectorLayer(self, layerKey, layerSrc):
# filename = orgFilename
# TODO handle selection with a where_clause?
# TODO use v.external as an option!
destFileName = 'a' + os.path.basename(self.getTempFilename())
#destFileName = QgsProcessingUtils.generateTempFilename(layerKey)
destFileName = 'a' + os.path.basename(getTempFilename())
self.exportedLayers[layerKey] = destFileName
layerFileName= os.path.basename(layerSrc)
layerName = os.path.splitext(layerFileName)[0]
Expand All @@ -698,29 +713,13 @@ def setSessionProjectionFromLayer(self, layer):
Set the projection from a QgsVectorLayer.
We creates a PROJ4 definition which is transmitted to Grass
"""
context = dataobjects.createContext()
#context = dataobjects.createContext()
if not Grass7Utils.projectionSet:
proj4 = str(layer.crs().toProj4())
command = 'g.proj -c proj4="{}"'.format(proj4)
self.commands.append(command)
Grass7Utils.projectionSet = True

def exportRasterLayer(self, layerKey, layerSrc):
"""
Creates a dedicated command to load a raster into
temporary GRASS DB.
"""
# TODO: handle multiple bands
destFilename = 'a' + os.path.basename(self.getTempFilename())
self.exportedLayers[layerKey] = destFilename
command = 'r.external input="{}" band=1 output={} --overwrite -o'.format(
layerSrc, destFilename)
return command

def getTempFilename(self):
# TODO Replace with QgsProcessingUtils generateTempFilename
return system.getTempFilename()

def canExecute(self):
message = Grass7Utils.checkGrass7IsInstalled()
return not message, message
Expand Down
Expand Up @@ -125,6 +125,12 @@ def icon(self):
def svgIconPath(self):
return QgsApplication.iconPath("providerGrass.svg")

def supportsNonFileBasedOutput(self):
"""
GRASS7 Provider doesn't support non file based outputs
"""
return False

def supportedOutputVectorLayerExtensions(self):
# We use the same extensions than QGIS because:
# - QGIS is using OGR like GRASS
Expand Down

0 comments on commit 6bf8448

Please sign in to comment.