Pythonスクリプトとして新しい処理アルゴリズムを書く¶
QGIS 3.4では、Pythonを使用して処理アルゴリズムを記述する唯一の方法は、 QgsProcessingAlgorithm
クラスを拡張することです。
QGIS内では、 プロセシングツールボックス の上部にある スクリプト メニューの 新しいスクリプトを作成 を使用して、自分のコードを書ける プロセシングスクリプトエディタ を開いて作成できます。タスクを簡素化するには、同じメニューの テンプレートから新しいスクリプトを作成する を使用して、スクリプトテンプレートから開始できます。これにより QgsProcessingAlgorithm
を拡張するテンプレートが開きます。
If you save the script in the scripts
folder
(the default location) with a .py
extension, the algorithm will
become available in the Processing Toolbox.
Extending QgsProcessingAlgorithm¶
The following code
takes a vector layer as input
counts the number of features
does a buffer operation
creates a raster layer from the result of the buffer operation
returns the buffer layer, raster layer and number of features
from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (QgsProcessing,
QgsProcessingAlgorithm,
QgsProcessingException,
QgsProcessingOutputNumber,
QgsProcessingParameterDistance,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterVectorDestination,
QgsProcessingParameterRasterDestination)
import processing
class ExampleProcessingAlgorithm(QgsProcessingAlgorithm):
"""
This is an example algorithm that takes a vector layer,
creates some new layers and returns some results.
"""
def tr(self, string):
"""
Returns a translatable string with the self.tr() function.
"""
return QCoreApplication.translate('Processing', string)
def createInstance(self):
# Must return a new copy of your algorithm.
return ExampleProcessingAlgorithm()
def name(self):
"""
Returns the unique algorithm name.
"""
return 'bufferrasterextend'
def displayName(self):
"""
Returns the translated algorithm name.
"""
return self.tr('Buffer and export to raster (extend)')
def group(self):
"""
Returns the name of the group this algorithm belongs to.
"""
return self.tr('Example scripts')
def groupId(self):
"""
Returns the unique ID of the group this algorithm belongs
to.
"""
return 'examplescripts'
def shortHelpString(self):
"""
Returns a localised short help string for the algorithm.
"""
return self.tr('Example algorithm short description')
def initAlgorithm(self, config=None):
"""
Here we define the inputs and outputs of the algorithm.
"""
# 'INPUT' is the recommended name for the main input
# parameter.
self.addParameter(
QgsProcessingParameterFeatureSource(
'INPUT',
self.tr('Input vector layer'),
types=[QgsProcessing.TypeVectorAnyGeometry]
)
)
self.addParameter(
QgsProcessingParameterVectorDestination(
'BUFFER_OUTPUT',
self.tr('Buffer output'),
)
)
# 'OUTPUT' is the recommended name for the main output
# parameter.
self.addParameter(
QgsProcessingParameterRasterDestination(
'OUTPUT',
self.tr('Raster output')
)
)
self.addParameter(
QgsProcessingParameterDistance(
'BUFFERDIST',
self.tr('BUFFERDIST'),
defaultValue = 1.0,
# Make distance units match the INPUT layer units:
parentParameterName='INPUT'
)
)
self.addParameter(
QgsProcessingParameterDistance(
'CELLSIZE',
self.tr('CELLSIZE'),
defaultValue = 10.0,
parentParameterName='INPUT'
)
)
self.addOutput(
QgsProcessingOutputNumber(
'NUMBEROFFEATURES',
self.tr('Number of features processed')
)
)
def processAlgorithm(self, parameters, context, feedback):
"""
Here is where the processing itself takes place.
"""
# First, we get the count of features from the INPUT layer.
# This layer is defined as a QgsProcessingParameterFeatureSource
# parameter, so it is retrieved by calling
# self.parameterAsSource.
input_featuresource = self.parameterAsSource(parameters,
'INPUT',
context)
numfeatures = input_featuresource.featureCount()
# Retrieve the buffer distance and raster cell size numeric
# values. Since these are numeric values, they are retrieved
# using self.parameterAsDouble.
bufferdist = self.parameterAsDouble(parameters, 'BUFFERDIST',
context)
rastercellsize = self.parameterAsDouble(parameters, 'CELLSIZE',
context)
if feedback.isCanceled():
return {}
buffer_result = processing.run(
'native:buffer',
{
# Here we pass on the original parameter values of INPUT
# and BUFFER_OUTPUT to the buffer algorithm.
'INPUT': parameters['INPUT'],
'OUTPUT': parameters['BUFFER_OUTPUT'],
'DISTANCE': bufferdist,
'SEGMENTS': 10,
'DISSOLVE': True,
'END_CAP_STYLE': 0,
'JOIN_STYLE': 0,
'MITER_LIMIT': 10
},
# Because the buffer algorithm is being run as a step in
# another larger algorithm, the is_child_algorithm option
# should be set to True
is_child_algorithm=True,
#
# It's important to pass on the context and feedback objects to
# child algorithms, so that they can properly give feedback to
# users and handle cancelation requests.
context=context,
feedback=feedback)
# Check for cancelation
if feedback.isCanceled():
return {}
# Run the separate rasterization algorithm using the buffer result
# as an input.
rasterized_result = processing.run(
'qgis:rasterize',
{
# Here we pass the 'OUTPUT' value from the buffer's result
# dictionary off to the rasterize child algorithm.
'LAYER': buffer_result['OUTPUT'],
'EXTENT': buffer_result['OUTPUT'],
'MAP_UNITS_PER_PIXEL': rastercellsize,
# Use the original parameter value.
'OUTPUT': parameters['OUTPUT']
},
is_child_algorithm=True,
context=context,
feedback=feedback)
if feedback.isCanceled():
return {}
# Return the results
return {'OUTPUT': rasterized_result['OUTPUT'],
'BUFFER_OUTPUT': buffer_result['OUTPUT'],
'NUMBEROFFEATURES': numfeatures}
Processing algorithm standard functions:
- createInstance (mandatory)
Must return a new copy of your algorithm. If you change the name of the class, make sure you also update the value returned here to match!
- name (mandatory)
Returns the unique algorithm name, used for identifying the algorithm.
- displayName (mandatory)
Returns the translated algorithm name.
- group
Returns the name of the group this algorithm belongs to.
- groupId
Returns the unique ID of the group this algorithm belongs to.
- shortHelpString
Returns a localised short help string for the algorithm.
- initAlgorithm (mandatory)
Here we define the inputs and outputs of the algorithm.
INPUT
andOUTPUT
are recommended names for the main input and main output parameters, respectively.If a parameter depends on another parameter,
parentParameterName
is used to specify this relationship (could be the field / band of a layer or the distance units of a layer).
- processAlgorithm (mandatory)
This is where the processing takes place.
Parameters are retrieved using special purpose functions, for instance
parameterAsSource
andparameterAsDouble
.processing.run
can be used to run other processing algorithms from a processing algorithm. The first parameter is the name of the algorithm, the second is a dictionary of the parameters to the algorithm.is_child_algorithm
is normally set toTrue
when running an algorithm from within another algorithm.context
andfeedback
inform the algorithm about the environment to run in and the channel for communicating with the user (catching cancel request, reporting progress, providing textual feedback). When using the (parent) algorithm's parameters as parameters to "child" algorithms, the original parameter values should be used (e.g.parameters['OUTPUT']
).可能な限りキャンセルのためにフィードバックオブジェクトをチェックすることをお勧めします!そうすることで、不要な処理が発生するまでユーザーを待たせる代わりに、レスポンシブなキャンセルが可能になります。
アルゴリズムは、辞書として定義したすべての出力パラメータの値を返す必要があります。この場合、それはバッファとラスタライズされた出力レイヤ、および処理された地物数です。辞書キーは、元のパラメータ/出力名と一致する必要があります。
Input and output types for Processing Algorithms¶
Here is the list of input and output types that are supported in
Processing with their corresponding alg decorator constants
(algfactory.py
contains the complete list of alg constants).
Sorted on class name.
Class |
Description |
---|---|
A band of a raster layer |
|
A boolean value |
|
A Coordinate Reference System |
|
A double numeric parameter for distance values |
|
An enumeration, allowing for selection from a set of predefined values |
|
An expression |
|
A spatial extent defined by xmin, xmax, ymin, ymax |
|
A feature sink |
|
A feature source |
|
A field in the attribute table of a vector layer |
|
A filename of an existing file |
|
A filename for a newly created output file |
|
A folder |
|
A map layer |
|
A matrix |
|
A set of layers |
|
A numerical value |
|
A point |
|
A number range |
|
A raster layer |
|
A raster layer |
|
A text string |
|
A vector layer |
|
A vector layer |
Class |
Description |
---|---|
A filename of an existing file |
|
A folder |
|
HTML |
|
A layer definition |
|
A map layer |
|
A set of layers |
|
A numerical value |
|
A raster layer |
|
A text string |
|
A vector layer |
Handing algorithm output¶
レイヤ(ラスタまたはベクタ)を表す出力を宣言すると、アルゴリズムは終了後にQGISに追加しようとします。
Raster layer output: QgsProcessingParameterRasterDestination.
Vector layer output: QgsProcessingParameterVectorDestination.
したがって、 processing.run()
メソッドが作成したレイヤをユーザの現在のプロジェクトに追加しなくても、2つの出力レイヤ(バッファとラスタバッファ)は読み込まれます。それらはユーザが入力した宛先(または、ユーザが宛先を指定しない場合は一時的な宛先)に保存されているからです。
レイヤがアルゴリズムの出力として作成される場合、そのように宣言する必要があります。そうしないと、宣言されたものがアルゴリズムが実際に作成するものと一致しないため、モデラーでアルゴリズムを適切に使用できません。
結果の辞書で文字列、数値などを指定することで返すことができます(「NUMBEROFFEATURES」で示したとおり)が、それらは常にアルゴリズムからの出力として明示的に定義する必要があります。アルゴリズムがモデルの一部として使用される場合、これらのアルゴリズムは後のアルゴリズムで使用するのに役立つ可能性があるため、アルゴリズムではできるだけ多くの有用な値を出力することをを推奨します。
ユーザーとやりとりする¶
If your algorithm takes a long time to process, it is a good idea to
inform the user about the progress. You can use feedback
(QgsProcessingFeedback
) for this.
The progress text and progressbar can be updated using two methods:
setProgressText(text)
and setProgress(percent)
.
You can provide more information to the user using
pushCommandInfo(text)
,
pushDebugInfo(text)
,
pushInfo(text)
and
reportError(text)
.
スクリプトに問題がある場合、それを処理する正しい方法は QgsProcessingException
を発生させることです。メッセージを引数として例外のコンストラクタに渡すことができます。プロセシングでは、アルゴリズムの実行元(ツールボックス、モデラー、Pythonコンソールなど)に応じてプロセシングとユーザーとの通信を処理します。
スクリプトの文書を作成する¶
You can document your scripts by overloading the
helpString()
and
helpUrl()
methods of
QgsProcessingAlgorithm
.
Flags¶
QgsProcessingAlgorithm
の flags
メソッドをオーバーライドして、アルゴリズムについてQGISに通知できます。たとえば、スクリプトをモデラーから非表示にすること、キャンセルできること、スレッドセーフではないことなどをQGISに伝えることができます。
ちなみに
デフォルトでは、処理タスクの実行中にQGISの応答性を維持するために、Processingはアルゴリズムを別のスレッドで実行します。アルゴリズムが定期的にクラッシュする場合は、おそらくバックグラウンドスレッドで安全に実行できないAPI呼び出しを使用している可能性があります。アルゴリズムのflags() メソッドからQgsProcessingAlgorithm.FlagNoThreadingフラグを返して、代わりにメインスレッドでアルゴリズムを実行するように強制します。
スクリプトアルゴリズムを書くためのベストプラクティス¶
スクリプトアルゴリズムを作成する際、特に他のQGISユーザーと共有したい場合に考慮すべきアイデアの簡単な概要を以下に示します。これらの単純な規則に従うことで、ツールボックス、モデラー、バッチ処理インターフェースなどのさまざまな処理要素間で一貫性が確保されます。
結果のレイヤーはロードしないでください。処理に結果を処理させ、必要であれば、レイヤーをロードしてください。
Always declare the outputs your algorithm creates.
メッセージボックスを表示したり、スクリプトのGUI要素を使用したりしないでください。ユーザーと通信する場合は、フィードバックオブジェクトのメソッド(
QgsProcessingFeedback
)を使用するか、QgsProcessingException
をスローします。
There are already many processing algorithms available in QGIS. You can find code on https://github.com/qgis/QGIS/blob/release-3_4/python/plugins/processing/algs/qgis.