スクリプト ツールの動作のカスタマイズ
スクリプト ツールのダイアログ ボックスに、パラメータの有効化と無効化、デフォルト値の設定、文字列キーワードの更新など、カスタム動作を設定することができます。スクリプト ツールにカスタム動作を追加するには、スクリプト ツールを右クリックしてから、[プロパティ] → [確認] タブの順にクリックします。[確認] パネルでは、ToolValidator という Python クラスを実装する Python コードを記述できます。Python コードを追加することで、以下のことができます。
- 他のパラメータに含まれる値に基づく、パラメータの有効化または無効化。
- パラメータのフィルタの更新。フィールド フィルタを使用すると、LONG や DOUBLE など、有効なフィールド タイプのリストを作成できます。文字列フィルタを使用すると、次のように、有効なキーワードのリストを設定できます。フィルタには、値のリスト、範囲、フィーチャクラス、ファイル、フィールド、ワークスペースの 6 種類があります。
- ラスタのセルサイズなど、パラメータのデフォルト値の設定。
- ダイアログ ボックスに表示される警告およびエラー メッセージのカスタマイズ。
- さまざまなカテゴリへのパラメータの配置。
- ModelBuilder で使用される出力データセットの記述の更新。
ToolValidator の仕組み
ToolValidator クラスは、Python コードのブロックです。ジオプロセシングがこのクラスを使用して、ツール ダイアログ ボックスおよび Python ウィンドウがユーザ入力に応じてどのように変化するかを制御します。ToolValidator クラスは、モデルを構築するときに重要なツールの出力データを記述するためにも使用されます。システム ツール(Esri が提供するツール)には、ユーザ入力に応じてツールのダイアログ ボックスを変更するという上記の機能が備わっています。
ArcGIS 9.3 までは、スクリプト ツールにこの機能はありませんでした。ツール ダイアログ ボックスは静的で、スクリプト ツールの出力には更新された記述は含まれていませんでした。このため、ModelBuilder でスクリプト ツールを操作するのは大変でした。ToolValidator クラスを使用すると、システム ツールのすべての機能が利用できます。
ToolValidator クラスは Python コードを使用して実装されていますが、ツールの実際の処理には任意のスクリプト言語を使用できます。
ToolValidator と整合チェック
整合チェックは、ツールの全パラメータが正しいことを確認し、不正なパラメータがある場合は適切なメッセージを表示します。整合チェックは、2 つの部分で構成されています。
- ToolValidator クラスにコードを追加することで処理を実行できる部分。
- ArcGIS が自動的に処理を実行する部分。この部分の整合チェックは、ArcGIS のジオプロセシングが内部で行う基本的な整合チェックであるため、内部整合チェック(または基本整合チェック)と呼ばれます。
まず、内部整合チェックの処理について説明します。
- パラメータが必要な場合、空(まだ何も入力されていない状態)かどうかをチェックします。空の場合は、ツールのダイアログ ボックスに「値は必要です」というメッセージを設定します(赤の X 印の代わりに緑色のドットを使用します)。
- ユーザが入力した値が正しいタイプかどうかチェックします。たとえば、フィーチャクラスではなくラスタ、あるいは数値ではなくアルファベット文字が入力されていないかチェックします。
- フィルタのメンバーシップをチェックします。値のリスト フィルタに RED、ORANGE、YELLOW などのキーワードが含まれている場合、BLUE を入力すると、BLUE は値のリスト フィルタにないため、エラー メッセージが表示されます。
- 入力データセットが存在しているかチェックします。
- 出力データセットのデフォルト カタログ パスを生成します。
- Schema という特別なオブジェクトに含まれる一連のルールに基づいて、出力データの記述を更新します。
- overwriteOutput 環境設定に対して、出力データセットが存在しているかチェックします。データセットが存在していて overwriteOutput が false の場合、エラーが生成されます。それ以外の場合は警告が生成されます。
- パラメータがフィールド データ タイプの場合、関連するテーブルにそのフィールドが存在するかチェックします。
- 出力データセットが入力データセットと同じでないかチェックします([フィールドの追加(Add Field)] のように出力が派生である場合以外)。
- 距離単位や面積単位のデータ タイプを含むパラメータでは、(ArcMap から実行している場合は)ArcMap の対応する値を調べてデフォルト値を設定します。
- 出力がカバレッジ、グリッド、または INFO テーブルの場合は、これらのデータセットのファイル名について、13 文字の制限をチェックします。
内部整合チェックは、以下の処理を行いません(ToolValidator クラスを使用すれば実行できます)。
- 他のパラメータとの関係に基づいたフィルタの更新。たとえば、ユーザが最初のパラメータにポイント フィーチャクラスを入力したら、ツール ダイアログ ボックスの 3 番目のパラメータに RED、ORANGE、YELLOW を表示させ、ポリゴン フィーチャクラスを入力したら、3 番目のパラメータに BLUE、INDIGO、VIOLET を表示させたい場合があります。
- パラメータの有効化/無効化。
- デフォルト値の計算。
- ツール固有のパラメータとの対話。
ToolValidator クラスに追加したコードは、次のようにして、内部整合チェックと組み合わせて使用されます。
- 内部整合チェックが出力データセットの記述を更新するのに使用する一連のルールを設定できます。これらのルールは、Schema オブジェクトに含まれます。
- 内部整合チェックの実行前にフィルタを更新できます。前述の例を使用すれば、ポイント フィーチャクラスを入力した場合は、RED、ORANGE、YELLOW を含むようにフィルタを更新します。内部整合チェックは、ユーザが入力した値をフィルタ内にある値に対してチェックします。
また、前述したように、ToolValidator でデフォルト値を計算したり、パラメータを有効化/無効化したり、メッセージをカスタマイズしたりできます。これらの種類の処理は、内部整合チェックに影響しません。影響があるのは、ツール ダイアログ ボックスの外観だけです。
ToolValidator クラスを使用したツール ダイアログ ボックスのカスタマイズ
ToolValidator は、initializeParameters(self)、updateParameters(self)、updateMessages(self) の 3 つのメソッドを持つ Python コードです。また、標準 Python クラスの初期化メソッドである __init__(self) も含まれています。ToolValidator クラスを表示および編集するには、スクリプト ツールを右クリックして、[プロパティ] → [確認] タブの順にクリックします。次の図は、デフォルト ToolValidator クラスのコードの [確認] タブです。コードを編集するには、[編集] ボタンをクリックします。編集後は、[OK] または [適用] をクリックして、編集内容を適用します。
方法 |
説明 |
---|---|
__init__ |
ToolValidator クラスを初期化します。必要なライブラリをインポートし、オブジェクト(self)を初期化します。 |
initializeParameters |
ツールのダイアログ ボックスを最初に開いたとき、またはツールがコマンド ラインで最初に使用されるときに 1 度呼び出されます。 |
updateParameters |
ツール ダイアログ ボックスまたはコマンド ラインでユーザがパラメータを変更するたびに呼び出されます。updateParameters が終了すると、ジオプロセシングは内部整合チェック ルーチンを呼び出します。 |
updateMessages |
内部整合チェック ルーチンが終了すると呼び出されます。内部整合チェックで作成されたメッセージは、必要に応じて変更できます。 |
ToolValidator は、ツール ダイアログ ボックスでユーザが何かを変更するたびに実行されるため、ToolValidator 内で他のジオプロセシング ツールを呼び出したり、データセットを開いたりしないでください。ジオプロセシング ツールは、ToolValidator ではなく、スクリプト内で使用してください。
initializeParameters(self)、updateParameters(self)、updateMessages(self) の 3 つのメソッドを実装する必要があります。これらのメソッドはリターン以外に必須の処理はありませんが、ToolValidator が有効な Python クラスであるために、必ず記述しておく必要があります。
ToolValidator コードの例を、次にいくつか示します。すべてのメソッドの詳細やその他の例については、「ToolValidator クラスのプログラミング」をご参照ください。
パラメータを有効化または無効化する
次の例は、[ホット スポット分析(Hot Spot Analysis)] ツールからのものです。
def updateParameters(self): # If the option to use a weights file is selected (the user chose # "Get Spatial Weights From File", enable the parameter for specifying # the file, otherwise disable it # if self.params[3].value == "Get Spatial Weights From File": self.params[8].enabled = 1 else: self.params[8].enabled = 0
コーディングの注意:Enabled などの Boolean 変数を設定する場合は、次の構文を使用できます。
self.params[8].enabled = 1 self.params[8].enabled = bool(1) self.params[8].enabled = True # Note upper case: "True", not "true"
0 以外の数値または値は true と見なされます。
デフォルト値を設定する
次の例も、[ホット スポット分析(Hot Spot Analysis)] ツールからのものです。
def updateParameters(self): # Set the default distance threshold to 1/100 of the larger of the width # or height of the extent of the input features. Do not set if there is no # input dataset yet, or the user has set a specific distance (Altered is true). # import string if self.params[0].value: if not self.params[6].altered: extent = string.split(arcpy.Describe(self.params[0].value).extent, " ") width = float(extent[2]) - float(extent[0]) height = float(extent[3]) - float(extent[1]) if width > height: self.params[6].value = width / 100 else: self.params[6].value = height / 100 return
フィルタを更新する
次の例では、キーワードの選択肢が含まれる値のリスト フィルタを動的に更新しています。ユーザが 2 番目のパラメータに「OLD_FORMAT」を入力した場合、3 番目のパラメータには「POINT、LINE、POLYGON」が含まれます。「NEW_FORMAT」を入力した場合、3 番目のパラメータには、さらに 3 つの選択肢が含まれます。
class ToolValidator: def __init__(self): import arcpy self.params = arcpy.GetParameterInfo() def initializeParameters(self): return def updateParameters(self): # Provide default values for "file format type" and # "feature type in file" # if not self.params[1].altered: self.params[1].value = "OLD_FORMAT" if not self.params[2].altered: self.params[2].value = "POINT" # Update the value list filter of the "feature type in file" parameter # depending on the type of file (old vs. new format) input # if self.params[1].value == "OLD_FORMAT": self.params[2].filter.list = ["POINT", "LINE", "POLYGON"] elif self.params[1].value == "NEW_FORMAT": self.params[2].filter.list = ["POINT", "LINE", "POLYGON", "POINT_WITH_ANNO", "LINE_WITH_ANNO", "POLYGON_WITH_ANNO"] return def updateMessages(self): return
次の例では、2 番目のパラメータの値のリスト フィルタが、最初のパラメータであるフィーチャクラスの形状タイプに基づいて変化します。
def updateParameters(self): # Update the value list filter in the second parameter based on the # shape type in the first parameter # stringFilter = self.params[1].filter fc = self.params[0].value if fc: shapetype = arcpy.Describe(fc).shapeType.lower() if shapetype == "point" or shapetype == "multipoint": stringFilter.list = ["RED", "GREEN", "BLUE"] elif shapetype == "polygon": stringFilter.list = ["WHITE", "GRAY", "BLACK"] else: stringFilter.list = ["ORANGE", "INDIGO", "VIOLET"] else: stringFilter.list = ["RED", "GREEN", "BLUE"] # If the user hasn't changed the keyword value, set it to the default value # (first value in the value list filter). # if not self.params[1].altered: self.params[1].value = stringFilter.list[0] return
メッセージをカスタマイズする
def updateMessages(self): self.params[6].clearMessage() # Check to see if the threshold distance contains a value of zero and the user has # specified a fixed distance band. # if self.params[6].value <= 0: if self.params[3].value == "Fixed Distance Band": self.params[6].setErrorMessage("Zero or a negative distance is invalid \ when using a fixed distance band. Please \ use a positive value greater than zero." ) elif self.params[6].value < 0: self.params[6].setErrorMessage("A positive distance value is required \ when using a fixed distance band. \ Please specify a distance.") return
Schema オブジェクトを使用した出力データの記述の更新
ツール ダイアログ ボックスの動作をカスタマイズする他に、ToolValidator を使用して、ModelBuilder の出力データ変数の記述を更新することができます。ModelBuilder 内のデータ変数は、次の図のように、データセットの簡単な説明と考えることができます。データ変数には、Python の Describe 関数を使用してアクセスできるすべてのプロパティが含まれています。
すべてのツールは、ModelBuilder で使用できるように、出力データの記述を更新する必要があります。記述を更新することで、ModelBuilder の後続のプロセスが、任意のプロセスの実行前にデータへの適用前の変更内容を参照できます。次の 2 つの例では、後続のプロセスが適用前の変更内容を参照しています。
次に示す最初の例は、[フィールドの追加(Add Field)] と [フィールド演算(Calculate Field)] ツールを含むモデルです。[フィールドの追加(Add Field)] では、Parks (2) という出力データ変数が TrackingID という新しいフィールドを持つように更新されています。出力が更新されたため、[フィールド演算(Calculate Field)] ダイアログ ボックスの [フィールド名] のリストには、[TrackingID] が表示されます。
2 番目の例(図はありません)は、[クリップ(Clip)] ツールの出力を [ポリゴン → ラスタ(Polygon to Raster)] ツールの入力として使用しているモデルです。[クリップ(Clip)] ツールは、入力フィーチャを単純に「くり抜く」方法を使用するので、出力フィーチャクラスには、地理範囲という 1 つの大きな例外を除いて、入力フィーチャクラスと同じプロパティをすべて持ちます。出力フィーチャクラスの地理範囲は、入力およびクリップ フィーチャの範囲の交差部分です。[ポリゴン → ラスタ(Polygon to Raster)] ツールは、新しい地理範囲を使用して、デフォルトのセル サイズを決定します。
ToolValidator クラス内では、Schema オブジェクトを使用して、出力の記述を構築するためのルールを設定できます。たとえば、次のようなルールを設定できます。
- 入力データセットの記述のコピーを作成して、([フィールドの追加(Add Field)] のように)新しいフィールドをフィールドのリストに追加したり、([XY 座標の追加(Add XY Coordinates)] のように)固定フィールドのリストを追加したりします。
- ([ユニオン(Union)] や [インターセクト(Intersect)] のように)出力フィールドのリストがデータセットのコレクション内にあるすべてのフィールドになるように設定し、必要に応じて、データセットのコレクションからフィーチャ ID を含むフィールドを追加します。
- 範囲を、別のパラメータのデータセットの範囲や、パラメータのリスト内にあるデータセットのユニオンまたは([クリップ(Clip)] のように)インターセクトに設定します。
- 特定のジオメトリ タイプ(ポイント、ライン、ポリゴン)を設定します。または、別のパラメータ内にあるデータセットのジオメトリ タイプや、パラメータのリストにある最小または最大のタイプに設定します。最小および最大のジオメトリ タイプの定義は、ポイントは 0、ポリラインは 1、ポリゴンは 2 です。そのため、ポイント、ポリライン、ポリゴンの中で最小のジオメトリ タイプはポイントで、最大はポリゴンです。
出力パラメータが持つ Schema
Schema オブジェクトは、ジオプロセシングによって作成されます。タイプがフィーチャクラス、テーブル、ラスタ、ワークスペースである出力パラメータはすべて、Schema オブジェクトを持ちます。フィーチャクラス、テーブル、ラスタ、ワークスペースの出力データ タイプだけがスキーマを持ちます。他のデータ タイプは持ちません。このスキーマには、パラメータ オブジェクトを通してアクセスし、出力を記述するためのルールを設定します。updateParameters が終了すると、内部整合チェック ルーチンが設定したルールを調べて、出力の記述を更新します。
依存性の設定
「パラメータ 3 のデータセットのフィールドをコピーしてから、フィールドを追加する」といったルールを作成する際は、コピー元のパラメータ(パラメータ 3)を Schema オブジェクトに教える必要があります。これには、パラメータ オブジェクトに依存性を追加します。依存性は、複数追加することができます。
def initializeParameters(self): # Set the dependencies for the output and its schema properties # self.params[2].parameterDependencies = [0, 1]
ParameterDependencies は、Python リストを使用します。
リストまたはリストのリストを使用したことがない場合、最初は混乱するかもしれませんが、すぐに慣れて何をするにも便利であることがわかるでしょう。リストとリストのリストを示す Python コードを以下に示します。これらの例は、対話モード(Python ウィンドウ、PythonWin の対話式ウィンドウ、または IDLE の Python シェル)で表示でき、コードを入力すれば、すぐに結果を得ることができます。
例 1: Python では、角括弧で囲まれた変数またはリテラルはリストになります。リストを印刷すると、必ず角括弧が追加されます。
>>> a = [1] >>> print a [1] >>> b = 2 >>> c = [b] >>> print c [2]
例 2: リストには、任意のタイプのエレメントを任意の数だけ含めることができます。リストのエレメントにアクセスするには、エレメントのインデックスを含む括弧を使用します。リスト内の最初のエレメントは、必ず [0] になります。
>>> a = [1, "two", 12.6] >>> print a [1, 'two', 12.6] >>> print a[0] 1
例 3: 単純なリストのリスト
>>> listOfLists = [ [1,2,3], ["one", "two", "three"] ] >>> print listOfLists [[1, 2, 3], ['one', 'two', 'three']] >>> print listOfLists[0] [1, 2, 3] >>> print listOfLists[0][2] 3 >>> print listOfLists[1][2] three
例 4: 別のリストのリスト。メンバー リストは、同じ長さである必要はないことに注意してください。
>>> listA = [1, 2, 3] >>> listB = ["a", "b", "C", "Z"] >>> listOfLists = [listA, listB] >>> print listOfLists [[1, 2, 3], ['a', 'b', 'C', 'Z']] >>> print listOfLists[1][3] Z
例 5: 空のリストを作成してから、項目を追加および削除します。
>>> a = [] >>> a.append("zero") >>> print a ['zero'] >>> b = [1, 2, 3] >>> a.append(b) >>> print a ['zero', [1, 2, 3]] >>> a.remove([1, 2, 3]) >>> print a ['zero']
Python リスト(または Python に関するその他)の詳細については、http://docs.python.org/ をご覧ください。
以下の例は、依存性の設定と使用法を示しています。
依存性の設定の例:クリップ(Clip)とフィールドの追加(Add Field)
[クリップ(Clip)] は、入力フィーチャ定義のコピーを作成してから、入力フィーチャとクリップ フィーチャのインターセクトに範囲を設定します。次の例では、ToolValidator でこのルールを実装しています。([クリップ(Clip)] は組み込みツールであり、スクリプトではないため、Python の ToolValidator クラスは使用していません。組み込みツールは内部ルーチンを使用して整合チェックを行いますが、本質的には ToolValidator と同じです。しかし、もし Python の ToolValidator クラスを使用しているとすると、次のようになります。)
def initializeParameters(self): # Set the dependencies for the output and its schema properties # self.params[2].parameterDependencies = [0, 1] # Feature type, geometry type, and fields all come from the first # dependent (parameter 0), the input features # self.params[2].schema.featureTypeRule = "FirstDependency" self.params[2].schema.geometryTypeRule = "FirstDependency" self.params[2].schema.fieldsRule = "FirstDependency" # The extent of the output is the intersection of the input features and # the clip features (parameter 1) # self.params[2].schema.extentRule = "Intersection" return def updateParameter(self): return
[フィールドの追加(Add Field)] は、入力パラメータの定義をコピーして、ユーザ指定フィールドを追加します。次のリンクは、[フィールドの追加(Add Field)] を ToolValidator で実装した場合を示しています。
initializeParameters 対 updateParameters でのスキーマの設定
上記の [クリップ(Clip)] の例は initializeParameters で Schema オブジェクトを変更し、updateParameters はリターン以外何もしていないことに注意してください。一方、[フィールドの追加(Add Field)] は、ユーザが情報を設定し(updateParameters が呼び出されるまで)、追加するフィールドの定義を持たないため、Schema オブジェクトは updateParameters で変更する必要があります。
これら 2 つは、静的な場合と動的な場合と考えることができます。[クリップ(Clip)] は従属パラメータ内のデータセット以外は使用しません(静的な場合)。一方、[フィールドの追加(Add Field)] は(フィールド名やフィールド タイプなど)従属パラメータでない他のパラメータを調べる必要があります(動的な場合)。
この静的な場合と動的な場合の動作の違いは、次のように、ToolValidator クラスの呼び出し方において明白になります。
- ツールのダイアログが最初に開いたとき、initializeParameters が呼び出されます。ここには、出力を記述するための静的なルールを設定します。この時点では、ユーザはパラメータに値を指定していないため、出力の記述は作成されません。
- ユーザがツール ダイアログ ボックスと何らかの対話を行うと、updateParameters が呼び出されます。
- updateParameters は、[フィールドの追加(Add Field)] での新しいフィールドの追加といった、パラメータの依存性から決定できない動的な動作を扱うスキーマを変更できます。
- updateParameters の終了後、内部整合チェック ルーチンが呼び出され、Schema オブジェクト内にあるルールが適用されて、出力データの記述が更新されます。
- 次に、updateMessages が呼び出されます。内部整合チェックが作成した警告およびエラー メッセージを調べて、それらを変更したり、警告やエラーを追加したりできます。
出力データセット名:派生出力のクローン対必須出力
Schema.Clone プロパティを true に設定した場合、ジオプロセシングは、パラメータ依存性リストの最初の従属パラメータ内にある記述の厳密なコピー(クローン)を作成します。通常、Clone を true に設定するのは 1 回だけなので、設定は updateParameters ではなく initializeParameters で行います。
出力パラメータの ParameterType が Derived に設定されている場合、厳密なコピーが作成されます。[フィールドの追加(Add Field)] ツールの動作はこれです。
ParameterType が Required に設定されている場合、厳密なコピーも作成されますが、データセットへのカタログ パスが変更されます。ほとんどのツールは新しいデータを作成するため、これが最も一般的な動作です。
参考情報
「ToolValidator クラスのプログラミング」は、Parameter、Schema、Filter の各オブジェクトの詳細を説明して、コードの例を提示しています。
[多重リング バッファ(Multiple Ring Buffer)] など、すべてのスクリプトベースのシステム ツールには、参考になる ToolValidator コードがあります。[空間統計] ツールボックス内のほとんどのツールはスクリプト ツールなので、ToolValidator の実装を調べることができます。
ToolValidator の実装時に、構文やランタイムあるいはロジックのエラーといった誤りを犯すことがあります。「ToolValidator クラスのデバッグ」では、ジオプロセシングをトラップし、エラーを報告し、デバッグのための方針を得るための方法を説明しています。