2024-11-29 15:38:02 +01:00

253 lines
8.4 KiB
Python

"""
***************************************************************************
i.py
----
Date : April 2016
Copyright : (C) 2016 by Médéric Ribreux
Email : mederic dot ribreux 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__ = "April 2016"
__copyright__ = "(C) 2016, Médéric Ribreux"
import os
from processing.tools.system import isWindows, getTempFilename
from grassprovider.grass_utils import GrassUtils
from qgis.PyQt.QtCore import QDir
from qgis.core import QgsProcessingParameterString
from qgis.core import QgsMessageLog
def orderedInput(alg, parameters, context, src, tgt, numSeq=None):
"""Import multiple rasters in order
:param alg: algorithm object.
:param parameters: algorithm parameters dict.
:param context: algorithm context.
:param src: Name of the source parameter.
:param tgt: Name of a new input parameter.
:param numSeq: List of a sequence for naming layers.
"""
rootFilename = f"rast_{os.path.basename(getTempFilename(context=context))}."
# parameters[tgt] = rootFilename
param = QgsProcessingParameterString(
tgt, "virtual input", rootFilename, False, False
)
alg.addParameter(param)
rasters = alg.parameterAsLayerList(parameters, src, context)
# Handle specific range
if numSeq is None:
numSeq = list(range(1, len(rasters) + 1))
for idx, raster in enumerate(rasters):
rasterName = f"{rootFilename}{numSeq[idx]}"
alg.loadRasterLayer(rasterName, raster, context, False, None, rasterName)
# Don't forget to remove the old input parameter
alg.removeParameter(src)
def regroupRasters(alg, parameters, context, src, group, subgroup=None, extFile=None):
"""
Group multiple input rasters into a group
* If there is a subgroupField, a subgroup will automatically be created.
* When an external file is provided, the file is copied into the respective
directory of the subgroup.
:param parameters:
:param context:
:param src: name of input parameter with multiple rasters.
:param group: name of group.
:param subgroup: name of subgroup.
:param extFile: dict : parameterName:directory name
"""
# Create a group parameter
groupName = f"group_{os.path.basename(getTempFilename(context=context))}"
param = QgsProcessingParameterString(
group, "virtual group", groupName, False, False
)
alg.addParameter(param)
# Create a subgroup
subgroupName = None
if subgroup:
subgroupName = f"subgroup_{os.path.basename(getTempFilename(context=context))}"
param = QgsProcessingParameterString(
subgroup, "virtual subgroup", subgroupName, False, False
)
alg.addParameter(param)
# Compute raster names
rasters = alg.parameterAsLayerList(parameters, src, context)
rasterNames = []
for idx, raster in enumerate(rasters):
name = f"{src}_{idx}"
if name in alg.exportedLayers:
rasterNames.append(alg.exportedLayers[name])
# Insert a i.group command
command = "i.group group={}{} input={}".format(
groupName,
f" subgroup={subgroupName}" if subgroup else "",
",".join(rasterNames),
)
alg.commands.append(command)
# Handle external files
# if subgroupField and extFile:
# for ext in extFile.keys():
# extFileName = new_parameters[ext]
# if extFileName:
# shortFileName = os.path.basename(extFileName)
# destPath = os.path.join(GrassUtils.grassMapsetFolder(),
# 'PERMANENT',
# 'group', new_parameters[group.name()],
# 'subgroup', new_parameters[subgroup.name()],
# extFile[ext], shortFileName)
# copyFile(alg, extFileName, destPath)
alg.removeParameter(src)
return groupName, subgroupName
def importSigFile(alg, group, subgroup, src, sigDir="sig"):
"""
Import a signature file into an
internal GRASSDB folder
"""
shortSigFile = os.path.basename(src)
interSig = os.path.join(
GrassUtils.grassMapsetFolder(),
"PERMANENT",
"group",
group,
"subgroup",
subgroup,
sigDir,
shortSigFile,
)
copyFile(alg, src, interSig)
return shortSigFile
def exportSigFile(alg, group, subgroup, dest, sigDir="sig"):
"""
Export a signature file from internal GRASSDB
to final destination
"""
shortSigFile = os.path.basename(dest)
grass_version = int(GrassUtils.installedVersion().split(".")[0])
if grass_version >= 8:
interSig = os.path.join(
GrassUtils.grassMapsetFolder(),
"PERMANENT",
"signatures",
sigDir,
shortSigFile,
"sig",
)
else:
interSig = os.path.join(
GrassUtils.grassMapsetFolder(),
"PERMANENT",
"group",
group,
"subgroup",
subgroup,
sigDir,
shortSigFile,
)
moveFile(alg, interSig, dest)
return interSig
def exportInputRasters(alg, parameters, context, rasterDic):
"""
Export input rasters
Use a dict to make input/output link:
{ 'inputName1': 'outputName1', 'inputName2': 'outputName2'}
"""
createOpt = alg.parameterAsString(parameters, alg.GRASS_RASTER_FORMAT_OPT, context)
metaOpt = alg.parameterAsString(parameters, alg.GRASS_RASTER_FORMAT_META, context)
# Get inputs and outputs
for inputName, outputName in rasterDic.items():
fileName = os.path.normpath(
alg.parameterAsOutputLayer(parameters, outputName, context)
)
grassName = alg.exportedLayers[inputName]
outFormat = GrassUtils.getRasterFormatFromFilename(fileName)
alg.exportRasterLayer(grassName, fileName, True, outFormat, createOpt, metaOpt)
def verifyRasterNum(alg, parameters, context, rasters, mini, maxi=None):
"""Verify that we have at least n rasters in multipleInput"""
num = len(alg.parameterAsLayerList(parameters, rasters, context))
if num < mini:
return (
False,
f"You need to set at least {mini} input rasters for this algorithm!",
)
if maxi and num > maxi:
return (
False,
f"You need to set a maximum of {maxi} input rasters for this algorithm!",
)
return True, None
# def file2Output(alg, output):
# """Transform an OutputFile to a parameter"""
# # Get the outputFile
# outputFile = alg.getOutputFromName(output)
# alg.removeOutputFromName(output)
# # Create output parameter
# param = getParameterFromString("ParameterString|{}|output file|None|False|False".format(output), 'GrassAlgorithm')
# param.value = outputFile.value
# alg.addParameter(param)
# return outputFile
def createDestDir(alg, toFile):
"""Generates an mkdir command for GRASS script"""
# Creates the destination directory
command = '{} "{}"'.format(
"MD" if isWindows() else "mkdir -p",
QDir.toNativeSeparators(os.path.dirname(toFile)),
)
alg.commands.append(command)
def moveFile(alg, fromFile, toFile):
"""Generates a move command for GRASS script"""
createDestDir(alg, toFile)
command = '{} "{}" "{}"'.format(
"MOVE /Y" if isWindows() else "mv -f",
QDir.toNativeSeparators(fromFile),
QDir.toNativeSeparators(toFile),
)
alg.commands.append(command)
def copyFile(alg, fromFile, toFile):
"""Generates a copy command for GRASS script"""
createDestDir(alg, toFile)
command = '{} "{}" "{}"'.format(
"COPY /Y" if isWindows() else "cp -f",
QDir.toNativeSeparators(fromFile),
QDir.toNativeSeparators(toFile),
)
alg.commands.append(command)