Schreiben eines Python-Verarbeitungsskripts mit Qgis 3.0

14

Nach dem Update auf Qgis 3.0 ist es sehr schwierig geworden, Informationen zum Schreiben von Verarbeitungsskripten in Qgis 3.0 zu finden.

@Underdark (siehe hier ) hat eine Basis für das Skelett bereitgestellt. Dieser Code scheint auch in Qgis hinzugefügt worden zu sein, wenn ein neues Skript aus einer Vorlage (Qgis 3.0.2) geschrieben wird.

Ich konnte jedoch keinen Weg finden, Python-Neulingen wie mir zu helfen, zu verstehen, wie dieser Code geändert wird, insbesondere für die Eingabe- und Ausgabe-Layer.

Mein Ziel ist es, ein Skript mit zwei Rasterebenen und einer doppelten als Eingabe zu schreiben, das zwei Ebenen ausgibt.

Welche Änderungen wären am Beispielcode erforderlich, um dies zu ermöglichen?

Für Qgis 2.x hätte ich die folgende Syntax verwendet:

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

Soweit ich weiß, müssen die Änderungen in der folgenden Prozedur vorgenommen werden, aber ich bin nicht sicher, was installiert werden soll.

    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))

Am 16. Mai wurde die Qgis-Python-API- Dokumentation veröffentlicht. Allerdings ist mir noch unklar, wie ich es hier verwenden soll. (Was sehr wohl ein Mangel an Python-Kenntnissen sein könnte)

Kantan
quelle
1
Können Sie ein Beispiel für Code bereitstellen, den Sie für den gleichen Zweck in qgis 2.xx verwendet haben? Die Dokumentation zu qgis 3.x finden Sie hier: docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/… sobald dies möglich ist Aktualisiert. Dokumentationsprobleme werden hier nachverfolgt: github.com/qgis/QGIS-Documentation/issues
Nono
Antwort bearbeitet mit dem Codebeispiel. Vielen Dank für die Links, ich habe das Kochbuch bereits verfolgt, aber leider konnte ich meine Antwort dort nicht finden!
Kantan
Ich habe etwas über die Qgis-API-Dokumente gelesen, kann mich aber nicht auf den Code von @Underdark beziehen. (Siehe Bearbeiten für die Links)
Kantan

Antworten:

26

Mit dem Übergang von QGIS2.x zu QGIS3.x wurde das gesamte Verarbeitungsframework überarbeitet und große Teile davon werden jetzt als C ++ - Klassen ausgeführt, mit denen Sie mit Python interagieren können. Leider ist die einfache Parametersyntax für Daten / Datensatz-E / A nicht mehr gültig. Die neue Parameterstruktur orientiert sich viel stärker an den in der Toolbox vorinstallierten (Python-) Verarbeitungsalgorithmen.

Wie ich sehe, haben Sie bereits die Beschreibung der neuen Algorithmusstruktur von @underdark befolgt. Um diese Struktur an Ihre Anforderungen anzupassen (Rasterebenen, doppelte Eingabe usw.), müssen Sie den Code an mehreren Stellen im Skript ändern. Ich habe ein grobes Beispiel mit einer kurzen Erklärung für Sie codiert (nur ein Algorithmus-Skelett basierend auf @underdarks-Beispiel):

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

Welche Schritte werden gemacht?

  1. Importieren Sie alle erforderlichen Klassen.
  2. Definieren Sie den Algorithmus als eine Klasse, von der er erbt QgsProcessingAlgorithm.
  3. Zuerst müssen Sie die Namen der Eingabe- und Ausgabeparameter als Zeichenfolgenvariablen (Parameternamen) der Algorithmusklasse (dh INPUT_RASTER_A = 'INPUT_RASTER_A') deklarieren, um auf Ihren Algorithmus mit den vom Verarbeitungsframework bereitgestellten Parametern zu verweisen.
  4. Fügen Sie die Methoden hinzu, die Ihren Algorithmus mit der Verarbeitungs-Toolbox-GUI verbinden, und stellen Sie Hilfezeichenfolgen usw. bereit.
  5. Anschließend fügen Sie die Parameter des Verarbeitungsframeworks hinzu. Diese wird als Kind Klassen definiert QgsProcessingParameterType- im Fall des Algorithmus: QgsProcessingParameterRasterLayer, QgsProcessingParameterNumber, und so weiter. Sie können die API-Einträge (dh QgsProcessingParameterRasterLayer) konsultieren , um die richtigen Argumente zu übergeben und die Parameterobjekte zu konstruieren.
  6. Übergeben die Parameter parallel contextund feedbackObjekte das processAlgorithm()Verfahren , bei dem man die Eingabedatensätze aus den Parametern zur Laufzeit zu erhalten (in diesem Fall QgsRasterLayer Aufgaben werden durch die Verwendung von parameterAsRasterLayer()Verfahren, etc.).
  7. Mach deine Berechnung.
  8. Fügen Sie die Ausgaben zum Ergebniswörterbuch hinzu und geben Sie sie als Ergebnis des Aufrufs zurück processAlgorithm().

Ich hoffe, ich konnte Ihnen einige Einblicke geben, wie Sie Ihre Python-Algorithmen in QGIS3 entwerfen können. Wenn Sie nicht weiterkommen, ist es immer hilfreich zu prüfen, wie vorhandene Algorithmen des Verarbeitungsframeworks mit den Parametern umgehen. Sie können sie hier ansehen .

root676
quelle
1
Guter Bericht! Stört es mich, wenn ich es zu github.com/qgis/QGIS/blob/master/doc/porting_processing.dox hinzufüge ?
Ndawson
Es wäre mir eine Ehre, wenn Sie es der qgis-Dokumentation hinzufügen würden. Bitte tun Sie das! Gibt es Voraussetzungen, um mehr Python-Dokumentation für qgis3 beizutragen? Ich denke, dies ist wesentlich für eine breitere Anwenderbasis in Bezug auf Skripter und Programmierer.
root676
1
Keine Voraussetzungen. Das Hinzufügen zum offiziellen Python-Kochbuch über GitHub-Pull-Requests ist eigentlich ganz einfach (alle Änderungen können sogar auf der GitHub-Site vorgenommen werden: github.com/qgis/QGIS-Documentation/tree/master/source/docs/… ). Das Hinzufügen weiterer Beispiele zu den offiziellen Dokumenten wäre ebenfalls sehr willkommen!
ndawson
1
Danke für deine Antwort! Ich war heute beschäftigt, aber ich werde versuchen, morgen zu graben. Es sieht sehr vielversprechend aus.
Kantan
2
Das ist definitiv eine großartige Antwort, danke für die Details und Hinweise. Der Link zu den Skripten auf gitHub ist eine echte Goldmine! Die QVariant-Deklaration hat mir zunächst einen Fehler gemeldet, aber als ich sie im Editor erneut eingetippt und die automatische Vervollständigung verwendet habe, ist der Fehler verschwunden. Es dauert jetzt wirklich einen großen Schritt, um in das Scripting einzutauchen. Ich hoffe, es entmutigt neue Programmierer nicht. Je mehr Dokumentation verfügbar ist, desto klarer wird es hoffentlich!
Kantan