Qgis 3.0を使用したPython処理スクリプトの作成


14

Qgis 3.0の更新後、Qgis 3.0での処理スクリプトの記述に関する情報を見つけることは非常に困難になりました。

@Underdark(こちらを参照)は、スケルトンの基礎を提供しています。このコードは、テンプレート(Qgis 3.0.2)から新しいスクリプトを作成するときに、Qgisにも追加されたようです。

しかし、私のようなPython初心者がそのコードを変更する方法を理解するのを助ける方法を見つけることができませんでした。特に入力層と出力層については。

私の目標は、2つのラスターレイヤーとダブルを入力として、2つのレイヤーを出力するスクリプトを作成することです。

それを可能にするためにサンプルコードに必要な変更は何ですか?

Qgis 2.xの場合、次の構文を使用します。

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

私が理解していることから、次の手順で変更を行う必要がありますが、何を配置するのかわかりません。

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

5月16日、Qgis python APIドキュメントがリリースされました。ただし、ここでの使用方法はまだ不明です。(Pythonの知識が不足している可能性があります)


1
あなたはここに利用できるようになりますQGIS 3.xの上QGIS 2.xxのドキュメントで同じ目的のために使用されるコードのサンプルを提供することができます:docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/...を通り、すぐにそれがされるよう更新しました。ドキュメントの問題はここで追跡されます:github.com/qgis/QGIS-Documentation/issues
Nono

コード例で編集された回答。リンクのおかげで、私はすでにクックブックをフォローしていましたが、残念ながらそこに私の答えを見つけることができませんでした!
カンタン

Qgis APIドキュメントについて読みましたが、それと@Underdarkのコードを関連付けることはできません。(リンクの編集を参照)
カンタン

回答:


26

QGIS2.xからQGIS3.xへの移行により、処理フレームワーク全体が作り直され、Pythonを使用して対話できるC ++クラスとして大部分が実行されるようになりました。残念ながら、データ/データセットIOの単純なパラメーター構文は無効になりました。新しいパラメーター構造は、ツールボックスにプリインストールされている組み込みの(Python-)処理アルゴリズムの後にはるかに指向されています。

私が見るように、あなたはすでに@underdarkによる新しいアルゴリズム構造の説明に従っています。ただし、要件(ラスターレイヤー、ダブル入力など)に合わせてこの構造を調整するには、スクリプトの複数の場所でコードを変更する必要があります。簡単な説明で大まかな例をコーディングしました(@underdarksの例に基づいたアルゴリズムスケルトン):

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

どのステップが実行されますか?

  1. 必要なすべてのクラスをインポートします。
  2. 継承クラスとしてのアルゴリズムを定義しますQgsProcessingAlgorithm
  3. まずINPUT_RASTER_A = 'INPUT_RASTER_A'、処理フレームワークによって提供されるパラメーターでアルゴリズムを参照するために、アルゴリズムクラスの文字列変数(パラメーター名)として入力および出力パラメーターの名前を宣言する必要があります。
  4. アルゴリズムを処理ツールボックスguiに接続するメソッドを追加し、ヘルプストリングなどを提供します。
  5. 次に、処理フレームワークのパラメーターを追加します。これらはQgsProcessingParameterType-の子クラスとして定義されます-アルゴリズムの場合:QgsProcessingParameterRasterLayerQgsProcessingParameterNumberなど。QgsProcessingParameterRasterLayer適切な引数を渡し、パラメータオブジェクトを構築するために、APIエントリ(たとえば、)を参照できます。
  6. パラメータと一緒に渡すcontextfeedbackにオブジェクトをprocessAlgorithm()使用すると、(この場合QgsRasterLayerを使用してオブジェクト実行時のパラメータから入力データセットを取得する方法parameterAsRasterLayer()など、方法を)。
  7. 計算を行います。
  8. 出力を結果ディクショナリに追加し、呼び出しの結果として返しますprocessAlgorithm()

QGIS3でPythonアルゴリズムを設計する方法について、いくつかの洞察が得られることを願っています。立ち往生しているときはいつでも、処理フレームワークの既存のアルゴリズムがどのようにパラメーターを処理するかを調べることは常に役立ちます。ここでそれらを見ることができます



qgisのドキュメントに追加していただければ光栄です。そうしてください!qgis3のPythonドキュメントをさらに提供するための前提条件はありますか?これは、スクリプト作成者やプログラマーの観点から、より広範なユーザーベースにとって不可欠だと思います。
root676

1
前提条件はありません。実際、GitHubプルリクエストを介して公式のPythonクックブックに追加するのは非常に簡単です(すべての編集はGitHubサイト(github.com/qgis/QGIS-Documentation/tree/master/source/docs/…)で行うこともできます)。公式ドキュメントにさらに例を追加することも大歓迎です!
ndawson

1
ご回答有難うございます!今日は忙しかったのですが、明日掘り下げてみます。本当に有望に見えます。
カンタン

2
詳細と参考文献に感謝します。gitHubのスクリプトへのリンクは、まさに金鉱です!最初はQVariant宣言でエラーが発生しましたが、エディターで再入力して自動補完を使用すると、エラーは消えました。今ではスクリプトの作成に大きな一歩を踏み出しました。新しいプログラマーを落胆させないことを願っています。しかし、より多くのドキュメントが利用できるようになると、それがより明確になることを望みます!
カンタン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.