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

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

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

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

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

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

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

>>> from qgis import processing

Now, there is basically just one (interesting) thing you can do with that from the console: execute an algorithm. That is done using the run() method, which takes the name of the algorithm to execute as its first parameter, and then a variable number of additional parameters depending on the requirements of the algorithm. So the first thing you need to know is the name of the algorithm to execute. That is not the name you see in the toolbox, but rather a unique command–line name. To find the right name for your algorithm, you can use the processingRegistry. Type the following line in your console:

>>> 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() メソッドでリストアップされていたものをここで使います。

1 >>> processing.run("native:buffer", {'INPUT': '/data/lines.shp',
2               'DISTANCE': 100.0,
3               'SEGMENTS': 10,
4               'DISSOLVE': True,
5               'END_CAP_STYLE': 0,
6               'JOIN_STYLE': 0,
7               'MITER_LIMIT': 10,
8               '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 の値を、カンマ ( , ) で区切って、文字列で指定しなければなりません。

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

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

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

Unlike when an algorithm is executed from the toolbox, outputs are not added to the map canvas if you execute that same algorithm from the Python console using run(), but runAndLoadResults() will do that.

The run() method returns a dictionary with one or more output names (the ones shown in the algorithm description) as keys and the file paths of those outputs as values:

 1 >>> myresult = processing.run("native:buffer", {'INPUT': '/data/lines.shp',
 2               'DISTANCE': 100.0,
 3               'SEGMENTS': 10,
 4               'DISSOLVE': True,
 5               'END_CAP_STYLE': 0,
 6               'JOIN_STYLE': 0,
 7               'MITER_LIMIT': 10,
 8               'OUTPUT': '/data/buffers.shp'})
 9 >>> myresult['OUTPUT']
10 /data/buffers.shp

You can load feature output by passing the corresponding file paths to the load() method. Or you could use runAndLoadResults() instead of run() to load them immediately.

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:

 1 >>> my_dialog = processing.createAlgorithmDialog("native:buffer", {
 2               'INPUT': '/data/lines.shp',
 3               'DISTANCE': 100.0,
 4               'SEGMENTS': 10,
 5               'DISSOLVE': True,
 6               'END_CAP_STYLE': 0,
 7               'JOIN_STYLE': 0,
 8               'MITER_LIMIT': 10,
 9               'OUTPUT': '/data/buffers.shp'})
10 >>> my_dialog.show()

The execAlgorithmDialog method opens the dialog immediately:

1 >>> processing.execAlgorithmDialog("native:buffer", {
2               'INPUT': '/data/lines.shp',
3               'DISTANCE': 100.0,
4               'SEGMENTS': 10,
5               'DISSOLVE': True,
6               'END_CAP_STYLE': 0,
7               'JOIN_STYLE': 0,
8               'MITER_LIMIT': 10,
9               'OUTPUT': '/data/buffers.shp'})

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

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

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

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

 1from qgis.core import (QgsProcessingAlgorithm,
 2       QgsProcessingParameterNumber,
 3       QgsProcessingParameterFeatureSource,
 4       QgsProcessingParameterFeatureSink)
 5
 6from qgis import processing
 7
 8class algTest(QgsProcessingAlgorithm):
 9    INPUT_BUFFERDIST = 'BUFFERDIST'
10    OUTPUT_BUFFER = 'OUTPUT_BUFFER'
11    INPUT_VECTOR = 'INPUT_VECTOR'
12
13    def __init__(self):
14        super().__init__()
15
16    def name(self):
17        return "algTest"
18
19    def displayName(self):
20        return "algTest script"
21
22    def createInstance(self):
23        return type(self)()
24
25    def initAlgorithm(self, config=None):
26        self.addParameter(QgsProcessingParameterFeatureSource(
27            self.INPUT_VECTOR, "Input vector"))
28        self.addParameter(QgsProcessingParameterNumber(
29            self.INPUT_BUFFERDIST, "Buffer distance",
30            QgsProcessingParameterNumber.Double,
31            100.0))
32        self.addParameter(QgsProcessingParameterFeatureSink(
33            self.OUTPUT_BUFFER, "Output buffer"))
34
35    def processAlgorithm(self, parameters, context, feedback):
36        #DO SOMETHING
37        algresult = processing.run("native:smoothgeometry",
38            {'INPUT': parameters[self.INPUT_VECTOR],
39             'ITERATIONS':2,
40             'OFFSET':0.25,
41             'MAX_ANGLE':180,
42             'OUTPUT': 'memory:'},
43            context=context, feedback=feedback, is_child_algorithm=True)
44        smoothed = algresult['OUTPUT']
45        algresult = processing.run('native:buffer',
46            {'INPUT': smoothed,
47            'DISTANCE': parameters[self.INPUT_BUFFERDIST],
48            'SEGMENTS': 5,
49            'END_CAP_STYLE': 0,
50            'JOIN_STYLE': 0,
51            'MITER_LIMIT': 10,
52            'DISSOLVE': True,
53            'OUTPUT': parameters[self.OUTPUT_BUFFER]},
54            context=context, feedback=feedback, is_child_algorithm=True)
55        buffered = algresult['OUTPUT']
56        return {self.OUTPUT_BUFFER: buffered}

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

  • name(): The id of the algorithm (lowercase).

  • displayName(): A human readable name for the algorithm.

  • createInstance(): Create a new instance of the algorithm class.

  • initAlgorithm(): Configure the parameterDefinitions and outputDefinitions.

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

  • processAlgorithm(): Do the work.

    Here we first run the smoothgeometry algorithm to smooth the geometry, and then we run the buffer algorithm on the smoothed output. To be able to run algorithms from within another algorithm we have to set the is_child_algorithm argument to True. You can see how input and output parameters are used as parameters to the smoothgeometry and buffer algorithms.

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

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

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

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

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

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

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

23.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.

23.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.

23.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.