Skip to content

Commit

Permalink
Improve ext scripts and support OutputFolder
Browse files Browse the repository at this point in the history
  • Loading branch information
Médéric Ribreux committed Nov 4, 2017
1 parent 5827513 commit 56b963e
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 88 deletions.
Expand Up @@ -72,6 +72,12 @@ def load(self):
Grass7Utils.GRASS_HELP_PATH,
self.tr('Location of GRASS docs'),
Grass7Utils.grassHelpPath()))
# Add a setting for using v.external instead of 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'),
True))
ProcessingConfig.readSettings()
self.refreshAlgorithms()
return True
Expand All @@ -83,6 +89,7 @@ def unload(self):
ProcessingConfig.removeSetting(Grass7Utils.GRASS_LOG_COMMANDS)
ProcessingConfig.removeSetting(Grass7Utils.GRASS_LOG_CONSOLE)
ProcessingConfig.removeSetting(Grass7Utils.GRASS_HELP_PATH)
ProcessingConfig.removeSetting(Grass7Utils.GRASS_USE_VEXTERNAL)

def isActive(self):
return ProcessingConfig.getSetting('ACTIVATE_GRASS7')
Expand Down
20 changes: 13 additions & 7 deletions python/plugins/processing/algs/grass7/TODO.md
Expand Up @@ -10,13 +10,19 @@ QGIS3 Processing Port
* Replace all parameters by QgsProcessingParameters.
* Re-enable GRASS algorithm by default.
* Add GRASS 7.2 new algorithms.
* Improve unit tests
* GRASS_REGION_CELLSIZE_PARAMETER is integer or double?
* GRASS_SNAP_TOLERANCE_PARAMETER is integer or double?
* Do we need to use QgsProcessingParameters::parameterFromScriptCode for description files?
We don't NEED but we have to improve getParameterFromString (or use an internal method) at least.
There is also a problem for parameterFromScriptCode: it doesn't use description very well.
We can also use parameterFromVariantMap and a custom internal Grass7Algorithm getParameterFromString.
* Improve unit tests.
* Use some raster/vector layers with spacename into their path.
* Better support for files output that are not HTML.
* Use prepareAlgorithm for algorithm preparation.
* Opens HTML files in Viewer.
* Support ParameterTable.
* Remove specific algorithms code in Grass7Algorithm.py (move them in ext).
* Convert all ext scripts.
* Support OutputFolder.
* Support multiple output raster formats.
* Support multiple output vector formats.
* Support multiple bands input rasters.
* Review all the methods of QgsProcessingAlgorithm.
* Make tests under MS-Windows 7 for Utf-8 support.

Unit tests
Expand Down
11 changes: 7 additions & 4 deletions python/plugins/processing/algs/grass7/description/r.horizon.txt
Expand Up @@ -2,8 +2,11 @@ r.horizon
Horizon angle computation from a digital elevation model.
Raster (r.*)
QgsProcessingParameterRasterLayer|elevation|Name of input elevation raster map|None|False
QgsProcessingParameterNumber|direction|Direction in which you want to know the horizon height|QgsProcessingParameterNumber.Double|0.0|False|360|0
QgsProcessingParameterNumber|maxdistance|The maximum distance to consider when finding the horizon height|QgsProcessingParameterNumber.Double|10000|False|None|0
QgsProcessingParameterString|distance|Sampling distance step coefficient (0.5-1.5)|1.0
QgsProcessingParameterNumber|direction|Direction in which you want to know the horizon height|QgsProcessingParameterNumber.Double|0.0|True|0.0|360.0
QgsProcessingParameterNumber|step|Angle step size for multidirectional horizon|QgsProcessingParameterNumber.Double|None|True|0.0|360.0
QgsProcessingParameterNumber|start|Start angle for multidirectional horizon|QgsProcessingParameterNumber.Double|0.0|True|0.0|360.0
QgsProcessingParameterNumber|end|End angle for multidirectional horizon|QgsProcessingParameterNumber.Double|360.0|True|0.0|360.0
QgsProcessingParameterNumber|maxdistance|The maximum distance to consider when finding the horizon height|QgsProcessingParameterNumber.Double|None|True|0|None
QgsProcessingParameterNumber|distance|Sampling distance step coefficient|QgsProcessingParameterNumber.Double|1.0|True|0.5|1.5
QgsProcessingParameterBoolean|-d|Write output in degrees (default is radians)|False
QgsProcessingParameterRasterDestination|output|Horizon
QgsProcessingParameterFolderDestination|output|Folder to get horizon rasters
64 changes: 20 additions & 44 deletions python/plugins/processing/algs/grass7/ext/r_blend_combine.py
Expand Up @@ -16,7 +16,6 @@
* *
***************************************************************************
"""
from builtins import str

__author__ = 'Médéric Ribreux'
__date__ = 'February 2016'
Expand All @@ -27,49 +26,26 @@
__revision__ = '$Format:%H$'


def processInputs(alg):
# If there is another raster to copy categories from
# we need to import it with r.in.gdal rather than r.external
first = alg.getParameterValue(u'first')
second = alg.getParameterValue(u'second')
if first in list(alg.exportedLayers.keys()) and second in list(alg.exportedLayers.keys()):
def processInputs(alg, parameters, context):
if 'first' and 'second' in alg.exportedLayers:
return

for raster in [first, second]:
alg.setSessionProjectionFromLayer(raster, alg.commands)

destFilename = alg.getTempFilename()
alg.exportedLayers[raster] = destFilename
command = 'r.in.gdal input={} output={} --overwrite -o'.format(raster, destFilename)
alg.commands.append(command)

alg.setSessionProjectionFromProject(alg.commands)

region = str(alg.getParameterValue(alg.GRASS_REGION_EXTENT_PARAMETER))
regionCoords = region.split(',')
command = 'g.region'
command += ' -a'
command += ' n=' + str(regionCoords[3])
command += ' s=' + str(regionCoords[2])
command += ' e=' + str(regionCoords[1])
command += ' w=' + str(regionCoords[0])
cellsize = alg.getParameterValue(alg.GRASS_REGION_CELLSIZE_PARAMETER)
if cellsize:
command += ' res=' + str(cellsize)
else:
command += ' res=' + str(alg.getDefaultCellsize(parameters, context))
alignToResolution = alg.getParameterValue(alg.GRASS_REGION_ALIGN_TO_RESOLUTION)
if alignToResolution:
command += ' -a'
alg.commands.append(command)


def processOutputs(alg):
for name in ['first', 'second']:
raster = alg.parameterAsRasterLayer(parameters, name, context)
alg.setSessionProjectionFromLayer(raster)

# We need to import all the bands and color tables of the input raster
alg.commands.append(
alg.loadRasterLayer(name,
parameters[name],
False, None
)
)
alg.inputLayers.append(raster)

alg.postInputs(parameters, context)

def processOutputs(alg, parameters, context):
# Keep color table
output = alg.getOutputValue(u'output')
command = u"r.out.gdal -t createopt=\"TFW=YES,COMPRESS=LZW\" input={} output=\"{}\" --overwrite".format(
alg.exportedLayers[output],
output
)
alg.commands.append(command)
alg.outputCommands.append(command)
self.exportRasterLayer('output', parameters, context, True)

40 changes: 40 additions & 0 deletions python/plugins/processing/algs/grass7/ext/r_horizon.py
@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-

"""
***************************************************************************
r_horizon.py
------------
Date : September 2017
Copyright : (C) 2017 by Médéric Ribreux
Email : medspx at medspx dot fr
***************************************************************************
* *
* 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. *
* *
***************************************************************************
"""

__author__ = 'Médéric Ribreux'
__date__ = 'September 2017'
__copyright__ = '(C) 2017, Médéric Ribreux'

# This will get replaced with a git SHA1 when you do a git archive

__revision__ = '$Format:%H$'
import os

def processOutputs(alg, parameters, context):
# There will be as outputs as the difference between start and end divided by steps
start = alg.parameterAsDouble(parameters, 'start', context)
end = alg.parameterAsDouble(parameters, 'end', context)
step = alg.parameterAsDouble(parameters, 'step', context)
num = start + step
directory = alg.parameterAsString(parameters, 'output', context)
while num < end:
grassName = '{}_{}'.format(alg.exportedLayers['output'], int(num))
fileName = '{}.tif'.format(os.path.join(directory, '{0:0>3}'.format(int(num))))
alg.exportRasterLayer(grassName, fileName)
num += step
61 changes: 28 additions & 33 deletions python/plugins/processing/algs/grass7/ext/r_rgb.py
Expand Up @@ -27,44 +27,39 @@


def processInputs(alg, parameters, context):
# We need to import all the bands and color tables of the input raster
if 'input' in alg.exportedLayers:
return
raster = alg.parameterAsRasterLayer(parameters, 'input', context)
alg.setSessionProjectionFromLayer(raster)
alg.prepareInputs()

# We need to import all the bands and color tables of the input raster
alg.loadRasterLayerFromParameter('input', parameters, context, False, None)
alg.postInputs(parameters, context)

def processCommand(alg, parameters, context):
# We need to introduce something clever:
# if the input raster is multiband: export each component directly
raster = alg.exportedLayers[alg.getParameterValue('input')]
rasterInput = alg.exportedLayers['input']
raster = alg.parameterAsRasterLayer(parameters, 'input', context)
for color in ['red', 'green', 'blue']:
alg.exportedLayers[alg.getOutputValue(color)] = color + alg.uniqueSuffix

commands = ["if [ $(g.list type=rast pattern='{}.*' | wc -l) -eq \"0\" ]; then".format(raster)]
commands.append(" r.rgb input={} red={} green={} blue={} --overwrite".format(
raster,
alg.exportedLayers[alg.getOutputValue('red')],
alg.exportedLayers[alg.getOutputValue('green')],
alg.exportedLayers[alg.getOutputValue('blue')]
))
commands.append("fi")
alg.commands.extend(commands)

alg.exportedLayers[color] = color + alg.uniqueSuffix

# If the raster is not multiband, really do r.rgb
if raster.bandCount() == 1:
alg.commands.append(" r.rgb input={} red={} green={} blue={} --overwrite".format(
rasterInput,
alg.exportedLayers['red'],
alg.exportedLayers['green'],
alg.exportedLayers['blue']
))

def processOutputs(alg, parameters, context):
raster = alg.exportedLayers[alg.getParameterValue('input')]
commands = ["if [ $(g.list type=rast pattern='{}.*' | wc -l) -eq \"0\" ]; then".format(raster)]
for color in ['red', 'green', 'blue']:
commands.append(" r.out.gdal -t input={} output={} createopt=\"TFW=YES,COMPRESS=LZW\" --overwrite".format(
alg.exportedLayers[alg.getOutputValue(color)],
alg.getOutputValue(color)
))
commands.append("else")
for color in ['red', 'green', 'blue']:
commands.append(" r.out.gdal -t input={} output={} createopt=\"TFW=YES,COMPRESS=LZW\" --overwrite".format(
'{}.{}'.format(raster, color),
alg.getOutputValue(color)
))
commands.append("fi")
alg.commands.extend(commands)
raster = alg.parameterAsRasterLayer(parameters, 'input', context)

# if the raster was monoband, export from r.rgb
if raster.bandCount() == 1:
for color in ['red', 'green', 'blue']:
alg.exportRasterLayerFromOutput(color, parameters, context, True)
# otherwise, export directly from the multibands
else:
for color in ['red', 'green', 'blue']:
fileName = alg.parameterAsOutputLayer(parameters, color, context)
grassName = '{}{}'.format(alg.exportedLayers['input'], color)
alg.exportRasterLayer(grassName, fileName, True)
2 changes: 2 additions & 0 deletions python/plugins/processing/core/parameters.py
Expand Up @@ -60,12 +60,14 @@
QgsProcessingParameterRasterDestination, # NOQA
QgsProcessingParameterVectorDestination, # NOQA
QgsProcessingParameterFileDestination,
QgsProcessingParameterFolderDestination,
QgsProcessingParameterString, # NOQA
QgsProcessingParameterMultipleLayers,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterNumber)
# TODELETE
from qgis.core import (QgsMessageLog)

from processing.tools.vector import resolveFieldIndex
from processing.tools import dataobjects
from processing.core.outputs import OutputNumber, OutputRaster, OutputVector
Expand Down

0 comments on commit 56b963e

Please sign in to comment.