22.7. プロセッシングアルゴリズムをコンソールから使う

コンソールを使うことによって、上級ユーザは生産性を向上させるとともに、プロセッシングフレームワークの他のどのGUI要素を使っても実現できない、複雑な操作ができるようになります。複数のアルゴリズムを必要とするモデルを、コマンドラインインターフェイスを使って定義することができます。さらにループや条件分岐などの処理を加えることによって、より柔軟で強力なワークフローを作りあげることができます。

QGISにプロセッシング専用コンソールはありませんが、プロセッシングのコマンドのすべてがQGISの内臓 Pythonコンソール で実行可能です。つまりそれらのコマンドをコンソールでの作業に組み込み、コンソールで可能なその他すべての機能(QGIS API からのメソッドもそこに含まれます)と、プロセッシングアルゴリズムをつなぐことができるということです。

Pythonコンソールで実行することのできるコードは、たとえそれが特定のプロセッシングメソッドを呼び出していないとしても、その他のすべてのアルゴリズムと同様に、後からツールボックスやグラフィカルモデラーやその他のあらゆるコンポーネントから呼び出すことのできる新しいアルゴリズムに変換することができます。実際にツールボックスにあるアルゴリズムのいくつかは、簡単なスクリプトです。

このセクションでは、QGIS Pythonコンソールからプロセッシングアルゴリズムを使用する方法と、Pythonを使ってアルゴリズムを書く方法を見ていきます。

22.7.1. Python コンソールからアルゴリズムを呼び出す

最初にやるべきことは、次のコードでプロセッシングの機能をインポートすることです。

>>> from qgis import processing

さて、読み込んだ機能を使ってコンソールでできる興味深いことは、基本的にはたったひとつだけです。つまりアルゴリズムの実行です。これは run メソッドを使うことによって行われます。このメソッドは第1引数に実行するアルゴリズムの名前をとり、そのあとにそのアルゴリズムに応じた追加パラメータが必要な数だけきます。ですので最初に知らなければならないのは、実行するアルゴリズムの名前です。この名前はツールボックスで表示されている名前ではなく、そのアルゴリズム固有のコマンドライン名です。processingRegistry クラスを使えば、この正しい名前を知ることができます。コンソールで以下のコードを入力してください。

>>> for alg in QgsApplication.processingRegistry().algorithms():
        print(alg.id(), "->", alg.displayName())

次のようなものが表示されるはずです(見やすくなるようにダッシュを余計に追加しています)。

3d:tessellate --------------> Tessellate
gdal:aspect ----------------> Aspect
gdal:assignprojection ------> Assign projection
gdal:buffervectors ---------> Buffer vectors
gdal:buildvirtualraster ----> Build Virtual Raster
gdal:cliprasterbyextent ----> Clip raster by extent
gdal:cliprasterbymasklayer -> Clip raster by mask layer
gdal:clipvectorbyextent ----> Clip vector by extent
gdal:clipvectorbypolygon ---> Clip vector by mask layer
gdal:colorrelief -----------> Color relief
gdal:contour ---------------> Contour
gdal:convertformat ---------> Convert format
gdal:dissolve --------------> Dissolve
...

これはすべての利用可能なアルゴリズムのIDと対応する名前のリストです。プロバイダ名とアルゴリズム名でソートされています。

アルゴリズムのコマンドラインでの名前が分かったら、次にすべきことはアルゴリズムを実行するための正しいシンタックスを確認することです。これは run() メソッドを呼ぶ際に必要なパラメータを確認するということです。

アルゴリズムを詳細に説明してくれるメソッドがあって、アルゴリズムが必要とするパラメータのリストと、生成される結果を記述してくれます。algorithmHelp(id_of_the_algorithm) メソッドを使うとこの情報を得ることができます。アルゴリズムの説明用の名前ではなく、IDを使ってください。

例えば native:buffer をパラメータとしてこのメソッドを呼び出すと(qgis:buffernative:buffer のエイリアスなので同様に使えます)、以下のような説明が表示されます。

>>> processing.algorithmHelp("native:buffer")
Buffer (native:buffer)

This algorithm computes a buffer area for all the features in an
input layer, using a fixed or dynamic distance.

The segments parameter controls the number of line segments to
use to approximate a quarter circle when creating rounded
offsets.

The end cap style parameter controls how line endings are handled
in the buffer.

The join style parameter specifies whether round, miter or
beveled joins should be used when offsetting corners in a line.

The miter limit parameter is only applicable for miter join
styles, and controls the maximum distance from the offset curve
to use when creating a mitered join.


----------------
Input parameters
----------------

INPUT: Input layer

   Parameter type: QgsProcessingParameterFeatureSource

   Accepted data types:
           - str: layer ID
           - str: layer name
           - str: layer source
           - QgsProcessingFeatureSourceDefinition
           - QgsProperty
           - QgsVectorLayer

DISTANCE: Distance

   Parameter type: QgsProcessingParameterDistance

   Accepted data types:
           - int
           - float
           - QgsProperty

SEGMENTS: Segments

   Parameter type: QgsProcessingParameterNumber

   Accepted data types:
           - int
           - float
           - QgsProperty

END_CAP_STYLE: End cap style

   Parameter type: QgsProcessingParameterEnum

   Available values:
           - 0: Round
           - 1: Flat
           - 2: Square

   Accepted data types:
           - int
           - str: as string representation of int, e.g. '1'
           - QgsProperty

JOIN_STYLE: Join style

   Parameter type: QgsProcessingParameterEnum

   Available values:
           - 0: Round
           - 1: Miter
           - 2: Bevel

   Accepted data types:
           - int
           - str: as string representation of int, e.g. '1'
           - QgsProperty

MITER_LIMIT: Miter limit

   Parameter type: QgsProcessingParameterNumber

   Accepted data types:
           - int
           - float
           - QgsProperty

DISSOLVE: Dissolve result

   Parameter type: QgsProcessingParameterBoolean

   Accepted data types:
           - bool
           - int
           - str
           - QgsProperty

OUTPUT: Buffered

   Parameter type: QgsProcessingParameterFeatureSink

   Accepted data types:
           - str: destination vector file, e.g. 'd:/test.shp'
           - str: 'memory:' to store result in temporary memory layer
           - str: using vector provider ID prefix and destination URI,
                  e.g. 'postgres:...' to store result in PostGIS table
           - QgsProcessingOutputLayerDefinition
           - QgsProperty

----------------
Outputs
----------------

OUTPUT:  <QgsProcessingOutputVectorLayer>
   Buffered

これでアルゴリズムの実行に必要なことはすべて分かりました。すでに触れたように、アルゴリズムは run() を使って実行することができます。シンタックスは以下のようになります。

>>> processing.run(name_of_the_algorithm, parameters)

パラメータの箇所には実行したいアルゴリズムに応じたパラメータの辞書がきます。algorithmHelp() メソッドでリストアップされていたものをここで使います。

>>> processing.run("native:buffer", {'INPUT': '/data/lines.shp',
              'DISTANCE': 100.0,
              'SEGMENTS': 10,
              'DISSOLVE': True,
              'END_CAP_STYLE': 0,
              'JOIN_STYLE': 0,
              'MITER_LIMIT': 10,
              'OUTPUT': '/data/buffers.shp'})

パラメータが任意のもので、それを使いたくない時は、そのパラメータを辞書に含めないでください。

パラメータが指定されなかった時はデフォルト値が使われます。

パラメータの種別により値を指定する方法は様々です。次に入力パラメータの種別ごとにその値を指定する方法を簡単に見ていきましょう。

  • ラスタレイヤ、ベクタレイヤ、テーブル。これらは単純に、使いたいデータオブジェクトの識別名(QGIS TOCが保持している名前)か、もしくはファイル名を文字列で指定してください。ファイル名を指定した場合、対応するレイヤがまだ読み込まれていない場合はファイルを開いて読み込みますが、マップキャンバスには追加されません。レイヤのQGISオブジェクトインスタンスをすでに取得している場合は、これをパラメータとして渡すこともできます。

  • Enumeration. If an algorithm has an enumeration parameter, the value of that parameter should be entered using an integer value. To know the available options, you can use the algorithmHelp() command, as above. For instance, the native:buffer algorithm has an enumeration called JOIN_STYLE:

    JOIN_STYLE: Join style
    
       Parameter type: QgsProcessingParameterEnum
    
       Available values:
               - 0: Round
               - 1: Miter
               - 2: Bevel
    
       Accepted data types:
               - int
               - str: as string representation of int, e.g. '1'
               - QgsProperty
    

    この例では、パラメータは3つの選択肢を持ちます。値は0始まりであることに注意してください。

  • 真偽値。TrueFalse を使用してください。

  • 複数の入力。値は入力を記述したものをセミコロン (;) で区切った文字列です。各入力が単一レイヤやテーブルの場合はデータオブジェクト名やファイルパスが使えます。

  • XXX のテーブル項目名。利用する項目名の文字列を使ってください。このパラメータは大文字小文字を区別します。

  • 固定テーブル。テーブルのすべての値のリストを、各値をカンマ (,) で区切った上で、全体を引用符 (") で囲んで入力します。値は最上位列から始まり、左から右に進みます。テーブルを表す2次元の配列も使えます。

  • CRS。使いたいCRSのEPSGコード番号を入力します。

  • 範囲。xmin, xmax, ymin および ymax の値を、カンマ ( , ) で区切って、文字列で指定しなければなりません。

真偽値、ファイル、文字列および数値パラメータには特に付け加える説明はありません。

文字列、真偽値、数値などの入力パラメータはデフォルト値を持ちます。デフォルト値は対応するパラメータの入力が欠けていた時に使われます。

出力データオブジェクトには、ツールボックスから実行される時と同様に、それを保存するために使うファイルパスを入力してください。出力オブジェクトが指定されない時は、結果は一時ファイルに保存されます(もしくは出力が任意の時はスキップされます)。ファイルの拡張子はファイルフォーマットから決定されます。アルゴリズムでサポートされていないファイル拡張子を入力した場合は、その出力タイプのデフォルトファイルフォーマットが使われ、それに対応する拡張子が与えられたファイルパスに付加されます。

アルゴリズムをツールボックスから実行した時とは違って、Pythonコンソールから run() を使って実行した時は、出力はマップキャンバスに追加されません。しかし``runAndLoadResults()`` を使って実行した時は追加されます。

run メソッドは、ひとつかもしくはそれ以上の出力名をキーとし、それら出力のファイルパスを値とする辞書を返します。出力名はアルゴリズムの説明で確認できます。

>>> myresult = processing.run("native:buffer", {'INPUT': '/data/lines.shp',
              'DISTANCE': 100.0,
              'SEGMENTS': 10,
              'DISSOLVE': True,
              'END_CAP_STYLE': 0,
              'JOIN_STYLE': 0,
              'MITER_LIMIT': 10,
              'OUTPUT': '/data/buffers.shp'})
>>> myresult['OUTPUT']
/data/buffers.shp

地物の出力は、対応するファイルパスを load() メソッドに渡すことによって読み込むことができます。もしくは``run()`` の代わりに runAndLoadResults() を使えば即座に読み込むことができます。

If you want to open an algorithm dialog from the console you can use the createAlgorithmDialog method. The only mandatory parameter is the algorithm name, but you can also define the dictionary of parameters so that the dialog will be filled automatically:

>>> my_dialog = processing.createAlgorithmDialog("native:buffer", {
              'INPUT': '/data/lines.shp',
              'DISTANCE': 100.0,
              'SEGMENTS': 10,
              'DISSOLVE': True,
              'END_CAP_STYLE': 0,
              'JOIN_STYLE': 0,
              'MITER_LIMIT': 10,
              'OUTPUT': '/data/buffers.shp'})
>>> my_dialog.show()

The execAlgorithmDialog method opens the dialog immediately:

>>> processing.execAlgorithmDialog("native:buffer", {
              'INPUT': '/data/lines.shp',
              'DISTANCE': 100.0,
              'SEGMENTS': 10,
              'DISSOLVE': True,
              'END_CAP_STYLE': 0,
              'JOIN_STYLE': 0,
              'MITER_LIMIT': 10,
              'OUTPUT': '/data/buffers.shp'})

22.7.2. スクリプトを作成してツールボックスから実行する

Pythonコードを書くことによって自分独自のアルゴリズムを書くことができます。プロセッシングスクリプトは QgsProcessingAlgorithm クラスを拡張します。そのため必要な機能を実装するためにはそこにさらにコードを追加する必要があります。プロセッシングツールボックス最上部の:guilabel:スクリプト ドロップダウンメニューから 新しいスクリプトを作成... (白紙)と テンプレートから新しいスクリプトを作成... (必須の関数 QgsProcessingAlgorithm のコードを含むテンプレート)を選ぶことができます。するとコードを入力するためのプロセッシングスクリプトエディタが開きます。ここでスクリプトを保存すると scripts フォルダ(スクリプトを保存ダイアログを開いたときのデフォルトフォルダ)に .py 拡張子でアルゴリズムとして保存されます。

アルゴリズムの名前(ツールボックスに表示されるもの)はコードの中で定義されます。

プロセッシングアルゴリズムを定義する次のコード例を見てみましょう。このアルゴリズムは、最初のレイヤ平滑化の後に、ユーザによって指定されたベクタレイヤに対する、ユーザ定義のバッファ距離によるバッファ操作を行うアルゴリズムとして機能するものです。

from qgis.core import (QgsProcessingAlgorithm,
       QgsProcessingParameterNumber,
       QgsProcessingParameterFeatureSource,
       QgsProcessingParameterFeatureSink)

from qgis import processing

class algTest(QgsProcessingAlgorithm):
    INPUT_BUFFERDIST = 'BUFFERDIST'
    OUTPUT_BUFFER = 'OUTPUT_BUFFER'
    INPUT_VECTOR = 'INPUT_VECTOR'

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

    def name(self):
        return "algTest"

    def displayName(self):
        return "algTest script"

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

    def initAlgorithm(self, config=None):
        self.addParameter(QgsProcessingParameterFeatureSource(
            self.INPUT_VECTOR, "Input vector"))
        self.addParameter(QgsProcessingParameterNumber(
            self.INPUT_BUFFERDIST, "Buffer distance",
            QgsProcessingParameterNumber.Double,
            100.0))
        self.addParameter(QgsProcessingParameterFeatureSink(
            self.OUTPUT_BUFFER, "Output buffer"))

    def processAlgorithm(self, parameters, context, feedback):
        #DO SOMETHING
        algresult = processing.run("native:smoothgeometry",
            {'INPUT': parameters[self.INPUT_VECTOR],
             'ITERATIONS':2,
             'OFFSET':0.25,
             'MAX_ANGLE':180,
             'OUTPUT': 'memory:'},
            context=context, feedback=feedback, is_child_algorithm=True)
        smoothed = algresult['OUTPUT']
        algresult = processing.run('native:buffer',
            {'INPUT': smoothed,
            'DISTANCE': parameters[self.INPUT_BUFFERDIST],
            'SEGMENTS': 5,
            'END_CAP_STYLE': 0,
            'JOIN_STYLE': 0,
            'MITER_LIMIT': 10,
            'DISSOLVE': True,
            'OUTPUT': parameters[self.OUTPUT_BUFFER]},
            context=context, feedback=feedback, is_child_algorithm=True)
        buffered = algresult['OUTPUT']
        return {self.OUTPUT_BUFFER: buffered}

必要なインポートを行った後に、続いて QgsProcessingAlgorithm の諸関数が定義されます。

  • name :アルゴリズムのID(小文字で)

  • displayName :ユーザに表示されるアルゴリズムの名前

  • createInstance :アルゴリズムのクラスのインスタンスの作成

  • initAlgorithm :パラメータ定義と出力定義を設定

    ここでアルゴリズムのパラメータと出力を記述します。この例では、入力のためには feature source を、出力結果のためには feature sink とバッファ距離用の数値を定義しています。

  • processAlgorithm :ここで主たる処理を行います。

    ここではまずジオメトリ平滑化のために smoothgeometry アルゴリズムを実行します。次に平滑化された出力に対して buffer アルゴリズムを実行します。アルゴリズムの内部から別のアルゴリズムを実行できるようにするために、run 用の onFinish パラメータのためのダミー関数を定義しなければなりません。これは no_post_process 関数です。入力パラメータと出力パラメータがどのようにして smoothgeometry アルゴリズムと buffer アルゴリズムのパラメータとして使われるかがわかると思います。

入力と出力のために多くの種類のパラメータが使用可能です。以下はアルファベット順にソートされたリストです。

コンストラクタの最初のパラメータはパラメータ名です。2番目はユーザインターフェイス用のパラメータの説明です。それ以外のパラメータは、パラメータの種別に依存します。

入力は QgsProcessingAlgorithm クラスの parameterAs 関数によってQGISクラスに変換されます。例えばバッファ距離のために数値を double で取得するには次のようにします。

self.parameterAsDouble(parameters, self.INPUT_BUFFERDIST, context)).

processAlgorithm 関数は、アルゴリズムで定義されたすべての出力値を含む辞書を返さなければなりません。これによって、同一モデル内の別のアルゴリズムを含む他のアルゴリズムから、これらの出力にアクセスすることが可能になります。

行儀のよいアルゴリズムは、意味のある限りより多くの出力を定義し返さなければなりません。取り立てて特色のない数値や文字列などの出力は、アルゴリズムをより大きなモデルの一部として実行する時に役立ちます。これらの値は、モデル中で続くアルゴリズムの入力パラメータとして使うことができるからです。処理された地物の数や、処理中に見つかった不正な地物の数、出力される地物の数のような数値を、出力に加えることを検討してください。より多くの出力を返せば返すほど、そのアルゴリズムはより役立つものになります。

22.7.2.1. フィードバック

The feedback object passed to processAlgorithm should be used for user feedback / interaction. You can use the setProgress function of the feedback object to update the progress bar (0 to 100) to inform the user about the progress of the algorithm. This is very useful if your algorithm takes a long time to complete.

The feedback object provides an isCanceled method that should be monitored to enable cancelation of the algorithm by the user. The pushInfo method of feedback can be used to send information to the user, and reportError is handy for pushing non-fatal errors to users.

Algorithms should avoid using other forms of providing feedback to users, such as print statements or logging to QgsMessageLog, and should always use the feedback object instead. This allows verbose logging for the algorithm, and is also thread-safe (which is important, given that algorithms are typically run in a background thread).

22.7.2.2. エラーハンドリング

If your algorithm encounters an error which prevents it from executing, such as invalid input values or some other condition from which it cannot or should not recover, then you should raise a QgsProcessingException. E.g.:

if feature['value'] < 20:
  raise QgsProcessingException('Invalid input value {}, must be >= 20'.format(feature['value']))

Try to avoid raising QgsProcessingException for non-fatal errors (e.g. when a feature has a null geometry), and instead just report these errors via feedback.reportError() and skip the feature. This helps make your algorithm "model-friendly", as it avoids halting the execution of an entire algorithm when a non-fatal error is encountered.

22.7.2.3. スクリプトのドキュメントを作成する

As in the case of models, you can create additional documentation for your scripts, to explain what they do and how to use them.

QgsProcessingAlgorithm provides the helpString, shortHelpString and helpUrl functions for that purpose. Specify / override these to provide more help to the user.

shortDescription is used in the tooltip when hovering over the algorithm in the toolbox.

22.7.3. 実行前後のスクリプトのフック

Scripts can also be used as pre- and post-execution hooks that are run before and after an algorithm is run, respectively. This can be used to automate tasks that should be performed whenever an algorithm is executed.

文法は上述のものと同様ですが、 alg という名前のグローバル変数を追加で使用でき、これはたった今(あるいはまさにこれから)実行されるアルゴリズムを表します。

In the General group of the processing options dialog, you will find two entries named Pre-execution script and Post-execution script where the filenames of the scripts to be run in each case can be entered.