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

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

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

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

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

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

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

>>> from qgis import processing

さて、基本的にコンソールからできる(興味深い)ことはただ一つ、アルゴリズムの実行です。これは run() メソッドを使って実行します。このメソッドは最初のパラメータとして実行するアルゴリズムの名前を取り、アルゴリズムの要求に応じて追加のパラメータを可変個数取ります。つまり、最初に知る必要があるのは、実行するアルゴリズムの名前です。これはツールボックスに表示される名前ではなく、一意のコマンドライン名です。あなたのアルゴリズムに適した名前を見つけるには、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() メソッドでリストアップされていたものをここで使います。

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オブジェクトインスタンスをすでに取得している場合は、これをパラメータとして渡すこともできます。

  • 列挙。アルゴリズムに列挙パラメータがある場合、そのパラメータの値は整数値で入力する必要があります。利用可能なオプションを知るには、上記のように algorithmHelp() コマンドを使用することができます。例えば、 native:buffer アルゴリズムには 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 の値を、カンマ ( , ) で区切って、文字列で指定しなければなりません。

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

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

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

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

run() メソッドは、1つ以上の出力名(アルゴリズムの説明に示されているもの)をキーとし、それらの出力のファイルパスを値とする辞書を返します:

 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

load() メソッドに対応するファイルパスを渡すことで、地物の出力を読み込むことができます。あるいは、 run() の代わりに runAndLoadResults() を使用すると、すぐに読み込むことができます。

コンソールからアルゴリズムダイアログを開きたい場合は、 createAlgorithmDialog メソッドを使います。必須パラメータはアルゴリズム名だけですが、パラメータの辞書を定義することで、ダイアログを自動的に埋めることもできます:

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

execAlgorithmDialog メソッドはダイアログをすぐに開きます:

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

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

Pythonコードを書くことによって自分独自のアルゴリズムを書くことができます。プロセシングスクリプトは QgsProcessingAlgorithm クラスを拡張します。そのため必要な機能を実装するためにはそこにさらにコードを追加する必要があります。プロセシングツールボックス最上部の スクリプト ドロップダウンメニューから 新しいスクリプトを作成... (白紙)と テンプレートから新しいスクリプトを作成... (必須の関数 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(): アルゴリズムのid(小文字)。

  • displayName(): アルゴリズムの人が読む名前。

  • createInstance(): アルゴリズムクラスの新しいインスタンスを作る。

  • initAlgorithm(): parameterDefinitionsと outputDefinitionsを設定する。

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

  • processAlgorithm(): 処理を行う。

    ここでは、まず smoothgeometry アルゴリズムを実行してジオメトリを平滑化し、次に平滑化された出力に対して buffer アルゴリズムを実行します。他のアルゴリズムからアルゴリズムを実行するには、 is_child_algorithm 引数を True に設定する必要があります。入力パラメータと出力パラメータが smoothgeometrybuffer アルゴリズムのパラメータとしてどのように使用されているかを見ることができます。

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

表 26.2 入出力アルゴリズムパラメータ型の一覧

QgsProcessingParameterAggregate

QgsProcessingParameterAnnotationLayer

QgsProcessingParameterAuthConfig

QgsProcessingParameterBand

QgsProcessingParameterBoolean

QgsProcessingParameterColor

QgsProcessingParameterCoordinateOperation

QgsProcessingParameterCrs

QgsProcessingParameterDatabaseSchema

QgsProcessingParameterDatabaseTable

QgsProcessingParameterDateTime

QgsProcessingParameterDistance

QgsProcessingParameterEnum

QgsProcessingParameterExpression

QgsProcessingParameterExtent

QgsProcessingParameterFeatureSink

QgsProcessingParameterFeatureSource

QgsProcessingParameterField

QgsProcessingParameterFieldMapping

QgsProcessingParameterFile

QgsProcessingParameterFileDestination

QgsProcessingParameterFolderDestination

QgsProcessingParameterGeometry

QgsProcessingParameterLayout

QgsProcessingParameterLayoutItem

QgsProcessingParameterMapLayer

QgsProcessingParameterMapTheme

QgsProcessingParameterMatrix

QgsProcessingParameterMeshLayer

QgsProcessingParameterMultipleLayers

QgsProcessingParameterNumber

QgsProcessingParameterPoint

QgsProcessingParameterPointCloudLayer

QgsProcessingParameterProviderConnection

QgsProcessingParameterRange

QgsProcessingParameterRasterDestination

QgsProcessingParameterRasterLayer

QgsProcessingParameterScale

QgsProcessingParameterString

QgsProcessingParameterVectorDestination

QgsProcessingParameterVectorLayer

QgsProcessingParameterVectorTileWriterLayers

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

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

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

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

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

26.7.2.1. フィードバック

processAlgorithm() に渡される feedback オブジェクトは、ユーザーからのフィードバックや対話に使用されます。feedback オブジェクトの setProgress() 関数を使うことで、プログレスバー(0から100)を更新してアルゴリズムの進捗をユーザに知らせることができます。これはアルゴリズムが完了するまでに時間がかかる場合にとても便利です。

feedback オブジェクトは isCanceled() メソッドを提供し、ユーザによるアルゴリズムのキャンセルを可能にするために監視する必要があります。feedbackpushInfo() メソッドはユーザに情報を送信するために使うことができます。また、 reportError() は致命的でないエラーをユーザにプッシュするのに便利です。

アルゴリズムは、ユーザにフィードバックを提供するprint文や QgsMessageLog へのロギングのような、他の形式の使用を避け、常にフィードバックオブジェクトを使うべきです。これはアルゴリズムに対する冗長なロギングを可能にし、スレッドセーフでもあります(これはアルゴリズムが通常バックグラウンドスレッドで実行されることを考えると重要です)。

26.7.2.2. エラーハンドリング

もしアルゴリズムが無効な入力値や回復できない、あるいは回復できないような状態など、実行を妨げるようなエラーに遭遇した場合、 QgsProcessingException を発生させるべきです。例.:

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

QgsProcessingException を致命的でないエラー(例えば、地物のジオメトリがNULLの場合など)に対して発生させないようにし、代わりに feedback.reportError() によってこれらのエラーを報告し、その地物をスキップするようにして下さい。これにより、致命的でないエラーに遭遇した際にアルゴリズム全体の実行を停止する必要がなくなるため、アルゴリズムを「モデルフレンドリ」にすることができます。

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

モデルの場合と同様に、スクリプトの追加ドキュメントを作成して、スクリプトの動作や使用方法を説明することができます。

QgsProcessingAlgorithm は、そのために helpString(), shortHelpString() 関数を使います。ユーザにより多くのヘルプを提供するために、これらを指定/オーバーライドして下さい。

shortDescription() は、ツールボックスでアルゴリズムにカーソルを合わせた時のツールチップで使用されます。

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

スクリプトは、アルゴリズムが実行される前と後にそれぞれ実行される実行前フックと実行後フックとしても使用できます。これは、アルゴリズムが実行されるたびに実行されるべきタスクを自動化するために使用できます。

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

プロセシングオプションダイアログの 一般情報 グループには 事前実行スクリプト事後実行スクリプト という2つの項目があり、それぞれのケースで実行するスクリプトのファイル名を入力することができます。