19 votos

Escribir un script de procesamiento en python con QGIS 3.0

Tras la actualización a QGIS 3.0, se ha vuelto muy difícil encontrar cualquier información relativa a la escritura de scripts de procesamiento en QGIS 3.0.

@Underdark (ver ici ) ha proporcionado una base para el esqueleto. Este código también parece haber sido añadido en QGIS, al escribir un nuevo script desde plantilla (QGIS 3.0.2).

Sin embargo, no pude encontrar ninguna forma de ayudar a los novatos en Python como yo a entender cómo cambiar ese código, especialmente para las capas de entrada y salida.

Mi objetivo es escribir un script que tome 2 capas rasterizadas y una doble como entrada, dando como salida dos capas.

¿Qué cambios habría que introducir en el código de ejemplo para permitirlo?

Para QGIS 2.x habría utilizado la siguiente sintaxis :

##Layer1=raster
##Layer2=raster 
##myDouble=Double
##OutLayer1=output raster
##OutLayer2=output raster   

Por lo que tengo entendido, los cambios hay que hacerlos en el siguiente procedimiento, pero no estoy seguro de lo que hay que poner.

def initAlgorithm(self, config=None):
    self.addParameter(QgsProcessingParameterFeatureSource(
        self.INPUT,
        self.tr("Input layer"),
        [QgsProcessing.TypeVectorAnyGeometry]))
    self.addParameter(QgsProcessingParameterFeatureSink(
        self.OUTPUT,
        self.tr("Output layer"),
        QgsProcessing.TypeVectorAnyGeometry))

El 16 de mayo, el API Python de QGIS se publicó la documentación. Sin embargo, aún no tengo claro cómo utilizarla aquí. (Que bien podría ser una falta de conocimiento de Python)

33voto

Jordan Stewart Puntos 524

Con la transición de QGIS2.x a QGIS3.x todo el marco de procesamiento ha sido reelaborado y grandes partes de él se ejecutan ahora como clases C++ con las que se puede interactuar utilizando Python. Desafortunadamente, la sintaxis simple de parámetros para IO de datos/conjuntos de datos ya no es válida. La nueva estructura de parámetros está mucho más orientada a los algoritmos de procesamiento (Python) que se encuentran preinstalados en la caja de herramientas.

Por lo que veo, ya has seguido la descripción de la nueva estructura del algoritmo realizada por @underdark. Pero con el fin de ajustar esta estructura para sus necesidades (capas de trama, de doble entrada, etc) que tiene que cambiar el código en varios lugares en la secuencia de comandos. He codificado un ejemplo aproximado con una breve explicación para usted (sólo un esqueleto algoritmo basado en @underdarks ejemplo):

from qgis.PyQt.QtCore import QCoreApplication, QVariant
from qgis.core import (QgsProcessing, QgsProcessingAlgorithm, 
QgsProcessingParameterRasterLayer,QgsProcessingParameterNumber, 
QgsProcessingParameterRasterDestination)

class RasterAlg(QgsProcessingAlgorithm):
    INPUT_RASTER_A = 'INPUT_RASTER_A'
    INPUT_RASTER_B = 'INPUT_RASTER_B'
    INPUT_DOUBLE = 'INPUT_DOUBLE'
    OUTPUT_RASTER_A = 'OUTPUT_RASTER_A'
    OUTPUT_RASTER_B = 'OUTPUT_RASTER_B'

    def __init__(self):
        super().__init__()

    def name(self):
        return "RasterAlg"

    def tr(self, text):
        return QCoreApplication.translate("RasterAlg", text)

    def displayName(self):
        return self.tr("RasterAlg script")

    def group(self):
        return self.tr("RasterAlgs")

    def groupId(self):
        return "RasterAlgs"

    def shortHelpString(self):
        return self.tr("RasterAlg script without logic")

    def helpUrl(self):
        return "https://qgis.org"

    def createInstance(self):
        return type(self)()

    def initAlgorithm(self, config=None):
        self.addParameter(QgsProcessingParameterRasterLayer(
            self.INPUT_RASTER_A,
            self.tr("Input Raster A"), None, False))
        self.addParameter(QgsProcessingParameterRasterLayer(
            self.INPUT_RASTER_B,
            self.tr("Input Raster B"), None, False))
        self.addParameter(QgsProcessingParameterNumber(
            self.INPUT_DOUBLE, 
            self.tr("Input Double"), 
            QgsProcessingParameterNumber.Double,
            QVariant(1.0)))
        self.addParameter(QgsProcessingParameterRasterDestination(
            self.OUTPUT_RASTER_A,
            self.tr("Output Raster A"),
            None, False))
        self.addParameter(QgsProcessingParameterRasterDestination(
            self.OUTPUT_RASTER_B,
            self.tr("Output Raster B"),
            None, False))

    def processAlgorithm(self, parameters, context, feedback):
        raster_a = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER_A, context)
        raster_b = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER_B, context)
        double_val = self.parameterAsDouble(parameters, self.INPUT_DOUBLE,context)
        output_path_raster_a = self.parameterAsOutputLayer(parameters, self.OUTPUT_RASTER_A, context)
        output_path_raster_b = self.parameterAsOutputLayer(parameters, self.OUTPUT_RASTER_B, context)

        #DO SOME CALCULATION

        results = {}
        results[self.OUTPUT_RASTER_A] = output_path_raster_a
        results[self.OUTPUT_RASTER_B] = output_path_raster_b
        return results

¿Qué pasos se dan?

  1. Importe todas las clases necesarias.
  2. Define el algoritmo como una clase que hereda de QgsProcessingAlgorithm .
  3. Primero tienes que declarar los nombres de los parámetros de entrada y salida como variables de cadena (nombres de parámetros) de la clase algoritmo (ie. INPUT_RASTER_A = 'INPUT_RASTER_A' ) para hacer referencia a su algoritmo con los parámetros proporcionados por el marco de procesamiento.
  4. Añade los métodos que conectan tu algoritmo a la guía de la caja de herramientas de procesamiento y proporciona cadenas de ayuda, etc.
  5. A continuación, se añaden los parámetros del marco de procesamiento. Éstos se definen como clases hijas de QgsProcessingParameterType - en el caso de su algoritmo: QgsProcessingParameterRasterLayer , QgsProcessingParameterNumber etc. Puede consultar las entradas de la API (es decir. QgsProcessingParameterRasterLayer ) para pasar los argumentos correctos y construir los objetos parámetro.
  6. Pasar los parámetros junto a context y feedback objetos a la processAlgorithm() en el que se obtienen los conjuntos de datos de entrada a partir de los parámetros en tiempo de ejecución (en este caso, objetos QgsRasterLayer mediante el método parameterAsRasterLayer() etc.).
  7. Haz tus cálculos.
  8. Añade las salidas al diccionario de resultados y las devuelve como resultado de llamar a processAlgorithm() .

Espero haber podido darte algunas ideas sobre cómo diseñar tus algoritmos python en QGIS3. Siempre que estés atascado, es útil mirar cómo los algoritmos existentes del marco de procesamiento manejan los parámetros. Puedes echarles un vistazo ici .

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X