Network Analyst のライセンスで利用可能。
arcpy.nax Python モジュールを使用すると、ネットワーク解析ワークフローを自動化できます。 arcpy.nax を使用して Python を記述したら、スクリプトをスクリプト ツールに変換して、他のジオプロセシング ツールと同様に実行できるようになります。 このチュートリアルでは、簡単なネットワーク解析ワークフローのコードを記述し、スクリプト ツールを構成して実行する方法を説明します。
注意:
このチュートリアルでは、.atbx ツールボックス内にスクリプト ツールを作成する方法を説明しますが、Python ツールボックス (.pyt) を使用して、Python と arcpy.nax モジュールでカスタム ジオプロセシング ツールを作成することもできます。 スクリプト ツールと Python ツールボックス (.pyt) の違いについて説明します。 このチュートリアルのレッスンの多くは、両方のタイプのツールを対象としています。
このチュートリアルで作成するスプリプト ツールは、「到達圏」解析を実行し、結果として生成される到達圏ポリゴンをフィーチャクラスに書き込みます。
注意:
このチュートリアルでは、例として到達圏解析を使用しますが、スクリプト ツールを作成することで、あらゆる種類のネットワーク解析を実行できます。
スクリプト ツールには、以下のパラメーターが含まれます。これらは、ツールのユーザーが設定できます。
- [入力施設] - 到達圏ポリゴンが計算される中心となるポイント
- [出力ポリゴン] - ツールにより作成される出力フィーチャクラス
- [ネットワーク] - 到達圏の計算に使用されるネットワーク データセットまたはネットワーク解析サービス
- [移動モード] - 解析に使用される「移動モード」
- [カットオフ] - 到達圏の移動時間または距離の制限
- [カットオフ単位] - [カットオフ] のパラメーター値を解釈する時間または距離の単位
- [時刻] - 解析に使用する日付と時刻
テスト データの収集
このチュートリアルの目的は、入力データとともに使用できるスクリプト ツールを作成することです。 特別なデータは必要ありませんが、スクリプト ツールのテストには、以下を準備する必要があります。
- ネットワーク データセット、またはネットワーク解析サービスへのアクセス権
- 同じ地理範囲内にネットワークとして複数のテスト ポイントを持つ 1 つのポイント フィーチャクラス
独自のデータがない場合は、提供されたチュートリアル データをダウンロードして、使用することもできます。
注意:
このチュートリアルを完了するには、ネットワーク データ ソースとして、解析の入力データの地理をカバーするネットワーク データセットを使用して公開された、指定されたチュートリアル ネットワーク データセットである ArcGIS Online、または ArcGIS Enterprise ルート検索サービスを使用します。 ArcGIS Online を使用すると、「クレジット」が消費されます。 「サービスを使用したネットワーク解析の詳細」。ヒント:
用意されているチュートリアル データには、このチュートリアルの手順に従って作成された完成済みのスクリプト ツールが含まれています。 こちらは抽出したチュートリアル データの Tutorial\ScriptTool フォルダーにあります。
- 「データ ダウンロード ページ」に移動します。
- [ダウンロード] ボタンをクリックしてファイルをローカルに保存します。
- ダウンロードしたファイルを展開します。
ツールの作成
まず、新しいツールボックスにツールを作成し、その入力パラメーターと出力パラメーターを定義します。
ツールボックスの作成
スクリプト ツールを格納するツールボックスを作成します。
- ArcGIS Pro を開いて、マップで新しいプロジェクトを作成します。
- [カタログ] ウィンドウ (デフォルトではアプリケーションの右側にあります) で [フォルダー] を右クリックし、[フォルダー接続の追加] を選択します。
[フォルダー接続の追加] ダイアログ ボックスが表示されます。
- 任意のフォルダーに接続します。
ツールボックスを作成して、このフォルダーにスクリプト ツールの Python .py ファイルを格納します。
- フォルダー接続を右クリックして、[新規] > [ツールボックス (.atbx)] をクリックします。
.atbx 拡張子が付いたツールボックス ファイルが作成されます。 ツールボックスの名前が編集モードになります。
- ツールボックスの名前を「TutorialScriptTool.atbx」に変更します。
- ツールボックスを右クリックして、[プロパティ] をクリックします。
[ツールボックス プロパティ] ダイアログ ボックスが表示されます。
- [ラベル] ボックスで、ツールボックスのラベルを「Tutorial Script Tool」に変更します。
- [エイリアス] ボックスで、ツールボックスのエイリアスを「TutorialScriptTool」に変更します。
ツールボックスのエイリアスは、Python プロセスからツールを呼び出すときに使用されます。
- [OK] をクリックして、[ツールボックス プロパティ] ダイアログ ボックスを閉じます。
ツールボックスにスクリプト ツールを作成
次に、ツールボックスにスクリプト ツールを作成し、その基本プロパティを更新します。
- 前項で作成したツールボックスを右クリックして、[新規] > [スクリプト] の順にクリックします。
[ツール プロパティ] ダイアログ ボックスが表示されます。
- サイド タブのリストにある [一般] タブをまだ選択していない場合は、クリックします。
- [名前] テキスト ボックスに「ServiceAreaTutorialScriptTool」と入力します。
この名前は、Python プロセスからツールを呼び出すときに使用されます。 名前には、英数字のみを使用してください。 スペースや特殊文字は使用できません。
- [ラベル] テキスト ボックスに「Service Area Tutorial Script Tool」と入力します。
ラベルはスクリプト ツールの ([ジオプロセシング] ウィンドウに表示される) 表示名で、スペースを使用できます。
- [説明] テキスト ボックスに、必要に応じて、スクリプト ツールの説明を入力します。
ツール パラメーターの定義
次に、ツールのパラメーターを定義します。 パラメーターは、ツールのダイアログ ボックスに表示され、そこで入力データ、出力場所、その他のオプションを選択できます。 ツールを実行すると、パラメーター値がツールの Python スクリプトに送信されます。 スクリプトによりパラメーター値が取得され、解析に使用されます。
このチュートリアルの最初に説明したとおり、7 つのパラメーターを作成します。
- サイド タブのリスト内の [パラメーター] タブをクリックします。
- [入力施設] パラメーターを作成するには、以下のサブステップを行います。
[入力施設] パラメーターを使用すると、到達圏ポリゴンが計算される中心となるポイントのフィーチャクラスまたはフィーチャ レイヤーを選択できます。
- [ラベル] 列の最初の空白セルをクリックして「入力施設」と入力し、Enter キーを押します。
[入力施設] パラメーターが作成されます。 [名前] 列のセルが自動的に [入力施設] に更新されます。
- [データ タイプ] セルのオプション ボタン をクリックして、[パラメーターのデータ タイプ] ダイアログ ボックスを開きます。
- [パラメーターのデータ タイプ] ダイアログ ボックスのドロップダウン メニューから、[Feature Layer] を選択して [OK] をクリックし、ダイアログ ボックスを閉じます。
[Feature Layer] タイプのパラメーターを使用することで、ツールのユーザーは、マップからレイヤーを選択するか、フィーチャクラスへのカタログ パスをこのパラメーターへの入力として使用できます。
- [フィルター] 列のセルをクリックします。 必要に応じて右にスクロールし、この列を見つけます。
- ドロップダウン メニューを使用して、[フィーチャ タイプ] オプションを選択します。
[フィーチャ タイプ フィルター] ダイアログ ボックスが表示されます。
- [フィーチャ タイプ フィルター] ダイアログ ボックスで、[ポイント] オプションのチェックボックスをオンにし、[OK] をクリックして、ダイアログ ボックスを閉じます。
到達圏の施設は、ポイントである必要があります。 このフィーチャ タイプ フィルターを設定すると、[入力施設] パラメーターには、ポイント フィーチャクラスとポイント フィーチャ レイヤーしか入力できなくなります。 たとえば、ポリゴンかライン フィーチャクラスを選択すると、ツール パラメーターが自動的にエラーを返します。
- [ラベル] 列の最初の空白セルをクリックして「入力施設」と入力し、Enter キーを押します。
- [出力ポリゴン] パラメーターを作成するには、以下のサブステップを行います。
[出力ポリゴン] パラメーターを使用すると、ツールの実行中に作成された到達圏ポリゴン フィーチャクラスを保存する場所を選択できます。
- [ラベル] 列の最初の空白セルをクリックして「出力ポリゴン」と入力し、Enter キーを押します。
[出力ポリゴン] パラメーターが作成されます。 [名前] 列のセルが自動的に [出力ポリゴン] に更新されます。
- [入力施設] パラメーターのデータ タイプを定義した時と同じように、[データ タイプ] セルをクリックして、[パラメーターのデータ タイプ] ダイアログ ボックスを開きます。 今回は、データ タイプを [Feature Class] に設定します。
[Feature Class] タイプの出力パラメーターを使用すると、ツールのユーザーが新しいフィーチャクラスやシェープファイルのカタログ パスを選択できます。
- [方向] 列のセルをクリックして、ドロップダウン メニューから [出力] オプションを選択します。
このパラメーターを出力パラメーターとして構成したため、まだ存在しないフィーチャクラスの出力ファイルのパスと名前を選択できます。
- [ラベル] 列の最初の空白セルをクリックして「出力ポリゴン」と入力し、Enter キーを押します。
- [ネットワーク] パラメーターを作成するには、以下のサブステップを行います。
[ネットワーク] パラメーターを使用すると、到達圏の計算にネットワーク データセットかネットワーク解析サービスを選択できるようになります。
- [ラベル] 列の最初の空白セルをクリックして「ネットワーク」と入力し、Enter キーを押します。
[ネットワーク] パラメーターが作成されます。 [名前] 列のセルが自動的に [ネットワーク] に更新されます。
- [データ タイプ] 列で、データ タイプを [Network Data Source] に設定します。
[Network Data Source] パラメーター タイプを使用すると、ネットワーク データセット レイヤー、ネットワーク データセット カタログ パス、またはネットワーク解析サービスの URL を選択できるようになります。 [Network Dataset Layer] タイプのパラメーターとして、サービス URL を使用せずに、ネットワーク データセット レイヤーまたはネットワーク データセット カタログ パスのみを選択できます。 [Network Dataset] パラメーター タイプを指定すると、ネットワーク データセット カタログ パスのみを使用でき、入力用よりは出力パラメーター タイプとして使用されるのがより一般的です。
- [ラベル] 列の最初の空白セルをクリックして「ネットワーク」と入力し、Enter キーを押します。
- [移動モード] パラメーターを作成するには、以下のサブステップを行います。
[移動モード] パラメーターを使用すると、解析に使用される「移動モード」を選択できるようになります。 選択した [ネットワーク] パラメーター値に従って使用可能な移動モードを反映するために選択リストが自動更新されるよう、このパラメーターに依存関係を設定します。
- [ラベル] 列の最初の空白セルをクリックし、「移動モード」と入力して、Enter キーを押します。
[移動モード] パラメーターが作成されます。 [名前] 列のセルが自動的に [移動モード] に更新されます。
- [データ タイプ] 列で、データ タイプを [Network Travel Mode] に設定します。
- [依存関係] 列のセルをクリックします。 必要に応じて右にスクロールし、この列を見つけます。
- [依存関係] 列のドロップダウン メニューから、[ネットワーク] オプションを選択します。
[移動モード] パラメーターが [ネットワーク] パラメーターにリンクされました。 ツールのダイアログ ボックスが、[ネットワーク] パラメーターに設定された値に従って、[移動モード] パラメーターの選択リストを自動更新します。
- [ラベル] 列の最初の空白セルをクリックし、「移動モード」と入力して、Enter キーを押します。
- [カットオフ] パラメーターを作成するには、以下のサブステップを行います。
[カットオフ] パラメーターを使用すると、到達圏の移動時間または距離の制限を設定する 1 つ以上の数字を選択できるようになります。 到達圏ポリゴンは、これらの制限範囲内の入力施設から到達可能なエリアを示します。 複数の値を入力すると、カットオフ値ごと、施設ごとに 1 つの到達圏ポリゴンが作成されます。 たとえば、出力には、各施設から車で 10 分および 15 分の移動時間を表すポリゴンが含まれることがあります。
- [ラベル] 列の最初の空白セルをクリックして「カットオフ」と入力し、Enter キーを押します。
[カットオフ] パラメーターが作成されます。 [名前] 列のセルが自動的に [カットオフ] に更新されます。
- [データ タイプ] セルのオプション ボタン をクリックして、[パラメーターのデータ タイプ] ダイアログ ボックスを開きます。
- [パラメーターのデータ タイプ] ダイアログ ボックスのドロップダウン メニューから、[Double] を選択します。
- [パラメーターのデータ タイプ] ダイアログ ボックスで、[複数値] オプションのチェックボックスをオンにします。
[複数値] オプションを有効にすると、パラメーターに複数の値を入力できるようになります。
- [OK] をクリックして [パラメーターのデータ タイプ] ダイアログ ボックスを閉じます。
到達圏のカットオフはゼロより大きくなければなりません。 0 分または負の値の運転時間を表すポリゴンを作成する意味はありません。 [フィルター] 列の [範囲] オプションを選択すると、範囲フィルターを使用して数値パラメーターを構成できます。 ユーザーがこの範囲外の数値を選択すると、エラー メッセージが自動的に表示されます。 ただし、範囲フィルターは、上限値と下限値を含む数値範囲のみをサポートしているため、0 を下限値とせず、0.5 などの小数値を採用することをお勧めします。 そのため、既定の範囲フィルターを使用するのではなく、ツールの検証を行い、Python コードを使用して、独自の範囲フィルターを構築します。 これについては、このチュートリアルの中で後ほど説明します。
- [ラベル] 列の最初の空白セルをクリックして「カットオフ」と入力し、Enter キーを押します。
- [カットオフ単位] パラメーターを作成するには、以下のサブステップを行います。
[カットオフ単位] パラメーターを使用すると、[カットオフ] パラメーター値を解釈するときに適用する計測単位を指定できるようになります。
- [ラベル] 列の最初の空白セルをクリックして「カットオフ単位」と入力し、Enter キーを押します。
[カットオフ単位] パラメーターが作成されます。 [名前] 列のセルが自動的に [カットオフ単位] に更新されます。
- [データ タイプ] 列で、データ タイプが [String] に設定されていることを確認し、必要に応じてこれを更新します。
あるパラメーターの選択リストを構成するには、[フィルター] 列の [値のリスト] オプションを選択して、ユーザーに提示する値のリストを入力できます。 ただし、[カットオフ単位] パラメーターについては、ユーザーが選択した [移動モード] パラメーター値の単位が時間単位か距離単位かによって選択リストを動的に更新することをお勧めします。 次の項では、ツール検証を行い、Python コードを使用して、動的な選択リストを作成します。
- [ラベル] 列の最初の空白セルをクリックして「カットオフ単位」と入力し、Enter キーを押します。
- [時刻] パラメーターを作成するには、以下のサブステップを行います。
[時刻] パラメーターを使用すると、解析の日時を設定できるようになります。 これは、車か歩行者が施設を出発する日時です。 時刻は必ずしも関連性がないため、このパラメーターを任意となるよう設定します。 必要に応じて設定しても、空白のままにしてもかまいません。
- [ラベル] 列の最初の空白セルをクリックして「時刻」と入力し、Enter キーを押します。
[時刻] パラメーターが作成されます。 [名前] 列のセルが自動的に [時刻] に更新されます。
- [データ タイプ] 列で、データ タイプを [Date] に設定します。
- [タイプ] 列のセルをクリックして、ドロップダウン メニューから [オプション] オプションを選択します。
このパラメーターを任意として構成したため、これを空白のままにしてもエラーは発生しません。
- [ラベル] 列の最初の空白セルをクリックして「時刻」と入力し、Enter キーを押します。
- パラメーターの構成を確認します。 パラメーターは、次の画像にようになります。
- [ツール プロパティ] ダイアログ ボックスの [OK] をクリックし、変更内容を確定してダイアログ ボックスを閉じます。
ツール パラメーターの検証
ツール パラメーターを構成したところで、パラメーターが期待どおり機能するかを検証する必要があります。 一部のパラメーターのカスタム検証を構成するためにまだ行うべきことがあり、ツールの実行コードをまだ記述していないため、ツールをまだ実行できませんが、ここで、現時点でのパラメーターの構成を検証してみましょう。
- [カタログ] ウィンドウで、ツールボックスで新しい [Service Area Tutorial Script Tool] スクリプト ツールを探します。
- ツールをダブルクリックして開きます。
[ジオプロセシング] ウィンドウで [Service Area Tutorial Script Tool] が開きます。 前項で作成した 7 つのパラメーターが表示されます。
- 各パラメーターを検証し、予測どおり動作するかを確認します。
- [入力施設] パラメーターを検証します。
このパラメーターを使用した場合に、ポイント レイヤーとフィーチャクラスのみを選択できる必要があります。 ポリゴンとライン フィーチャクラスは選択リストには表示されず、手動で入力すると、入力のジオメトリ タイプが無効であることを示すエラー メッセージが表示されます。
ヒント:
マップにフィーチャ レイヤーがない場合は、選択リストは表示されません。 パラメーターの動作を確認したい場合は、いくつかのレイヤーをマップに追加します。 - [出力ポリゴン] パラメーターを検証します。
出力場所を選択できる必要があります。 既存のフィーチャクラスを選択すると、パラメーターにより、出力がすでに存在することを示す警告が表示される必要があります。
- [ネットワーク] パラメーターと [移動モード] パラメーターを検証します。
[移動モード] パラメーターを最初は空白とし、選択リストを持たせないようにする必要があります。 [ネットワーク] パラメーターを使用することで、ネットワーク データセット レイヤー、ネットワーク データセット カタログ パス、またはネットワーク解析サービスの URL を選択できる必要があります。
- [ネットワーク] パラメーターの値を選択します。
[移動モード] パラメーターの選択リストは、[ネットワーク] 値に関連付けられた、使用可能な移動モードのリストを持つよう自動更新されます。
- [カットオフ] パラメーターを検証します。
複数の数値を入力できます。
現時点では、負の数値か 0 を入力しても、パラメーターにはエラーが表示されません。 後でツール検証を行って、この動作を更新します。
- [カットオフ単位] パラメーターを検証します。
現時点では、このパラメーターは、選択リストを表示しません。 後でツール検証を行って、[移動モード] 値に応じた選択リストを準備します。
- [時刻] パラメーターを検証します。
他のパラメーターとは異なり、このパラメーターは任意のため、空白時にも赤いアスタリスクが表示されません。 日時セレクター ユーティリティを使用することも、手動で日時を入力することもできます。
- [入力施設] パラメーターを検証します。
Python スクリプトの記述
この項では、スクリプト ツールが実行する Python スクリプトを記述します。 スクリプト ツールは、以下を行います。
- 入力パラメーターを取得します。
- ArcGIS Network Analyst extension ライセンスを必要に応じてチェック アウトします。
- 到達圏解析を初期化します。
- 到達圏解析を設定します。
- 入力施設を読み込みます。
- 到達圏解析を実行し、解析実行エラーを処理します。
- 出力到達圏ポリゴンをフィーチャクラスに書き込みます。
- 先にツールボックスを作成したのと同じフォルダーに ServiceAreaTutorialScriptTool.py というファイルを作成し、これを開いて、希望の統合開発環境 (IDE) またはテキスト エディターで編集します。
この演習では、Python IDE またはテキスト エディターを使用できます。
- 下のサブセクションを読み、スクリプト ツールに使用するコードのコンポーネントを理解してください。
- 完全なコードは、この項の最後に掲載しています。 このコードをコピーして ServiceAreaTutorialScriptTool.py ファイルに貼り付け、ファイルを保存します。
注意:
ServiceAreaTutorialScriptTool.py ファイルに貼り付けた後で、コードのインデントが正しいか確認します。
入力パラメーターの取得
スクリプト ツールのコードは、「GetParameter」または「GetParameterAsText」ArcPy 関数を使用して、ツールのパラメーターからユーザーの入力を取得する必要があります。 GetParameter 関数は、パラメーターの定義済みデータ タイプのパラメーター値を返し、GetParameterAsText 関数は、パラメーターの値を必ず文字列として返します。
このコード スニペットでは、スクリプトがツール パラメーターを取得し、これを変数に割り当てます。 GetParameter 関数は、入力パラメーターのデータ タイプを保持したいときに使用します。 GetParameterAsText 関数は、レイヤーの文字列名がジオプロセシング ツールと ArcPy 関数への有効な入力として使用できるため、入力がレイヤーの可能性があっても、入力施設とネットワーク データ ソースの取得時に使用されます。 ここで GetParameter および GetParameterAsText とともに使用されるインデックス値は、先に定義したパラメーターの順番と一致します。input_facilities = arcpy.GetParameterAsText(0)
output_polygons = arcpy.GetParameterAsText(1)
network = arcpy.GetParameterAsText(2)
travel_mode = arcpy.GetParameter(3)
cutoffs = arcpy.GetParameter(4)
cutoff_units = arcpy.GetParameterAsText(5)
time_of_day = arcpy.GetParameter(6)
ArcGIS Network Analyst extension ライセンスのチェック アウト
ツールのユーザーが [ネットワーク] パラメーターにネットワーク データセットを選択した場合、ArcGIS Network Analyst extension ライセンスが必要となります。 ユーザーが代わりにポータルの URL を指定して、ネットワーク解析サービスを使用することを選択した場合、ArcGIS Network Analyst extension ライセンスは必要ありません。
このコード スニペットでは、入力ネットワークが「http」で始まらず、ネットワーク解析サービスと想定される場合、スクリプトがエクステンション ライセンスのチェック アウトを試みます。 エクステンションを利用できない場合は、エラーが返されます。 エラー処理については、このチュートリアル内で後ほど説明します。# Check out the Network Analyst extension license if the input network
# is a local network dataset and not a service.
if not network.startswith("http"):
if arcpy.CheckExtension("network") == "Available":
arcpy.CheckOutExtension("network")
else:
# Throw an error if the license cannot be checked out.
arcpy.AddError("The Network Analyst license is unavailable.")
raise CustomError
到達圏解析の初期化
arcpy.nax を使用してネットワーク解析ワークフローで最初に行うのは、指定されたネットワーク データ ソースを使用して解析の解析オブジェクトをインスタンス化することです。
arcpy.nax を使用したネットワーク解析ワークフローのステップの詳細
このコード スニペットでは、到達圏解析オブジェクトが初期化されます。# Instantiate the ServiceArea solver object
sa = arcpy.nax.ServiceArea(network)
到達圏解析の設定
この解析では、ユーザーに変更してほしくない到達圏解析の設定をハードコード化します。 ツール パラメーターからのユーザーの選択に基づき、他の設定を行います。
このコード スニペットでは、一部の解析設定がハードコード化されています。 移動モード、時刻、デフォルト インピーダンス カットオフは、ツール パラメーターから取得される値を使用して設定されます。# Hard-code some non-default Service Area settings that we don't want
# the user to change
sa.geometryAtCutoff = arcpy.nax.ServiceAreaPolygonCutoffGeometry.Disks
sa.polygonBufferDistance = 150
sa.polygonBufferDistanceUnits = arcpy.nax.DistanceUnits.Feet
# Set analysis properties chosen by the user and passed in via tool
# parameters
sa.travelMode = travel_mode
sa.timeOfDay = time_of_day
sa.defaultImpedanceCutoffs = cutoffs
カットオフ単位も設定する必要がありますが、これには、少々別の処理が必要です。 ツール パラメーターは文字列として構成され、文字列を使用した単位名を適切な「TimeUnits」または「DistanceUnits」の列挙値に変換する必要があります。
このコード スニペットでは、文字列値から適切な列挙値に変換するための 2 つの関数によりツール パラメーターから渡される値に応じて、時間単位または距離単位が設定されます。 このツールの例では、想定される時間単位と距離単位の限定的なリストのみを使用します。 ツール パラメーターについては、このチュートリアル内で後ほど説明します。# Do special handling of cutoff units to convert them to the correct
# arcpy.nax enum
if cutoff_units in ["Hours", "Minutes"]:
sa.timeUnits = convert_time_units_to_nax(cutoff_units)
elif cutoff_units in ["Kilometers", "Meters", "Miles", "Yards", "Feet"]:
sa.distanceUnits = convert_distance_units_to_nax(cutoff_units)
このコード スニペットでは、文字列を使用した単位名を正しい列挙値に変換するための 2 つの関数が定義されます。 この例では、ユーザーに提示される単位の選択肢を限定するため、取り得る TimeUnits と DistanceUnits 列挙のすべての値が含まれているわけではありません。 無効な単位が渡されると、これらの関数がエラーを返します。def convert_time_units_to_nax(time_units_str):
"""Convert string-based time units to the correct arcpy.nax enum."""
if time_units_str == "Hours":
return arcpy.nax.TimeUnits.Hours
if time_units_str == "Minutes":
return arcpy.nax.TimeUnits.Minutes
arcpy.AddError(f"Invalid time units: {time_units_str}")
raise CustomError
def convert_distance_units_to_nax(dist_units_str):
"""Convert string-based distance units to the correct arcpy.nax enum."""
if dist_units_str == "Kilometers":
return arcpy.nax.DistanceUnits.Kilometers
if dist_units_str == "Meters":
return arcpy.nax.DistanceUnits.Meters
if dist_units_str == "Miles":
return arcpy.nax.DistanceUnits.Miles
if dist_units_str == "Yards":
return arcpy.nax.DistanceUnits.Yards
if dist_units_str == "Feet":
return arcpy.nax.DistanceUnits.Feet
arcpy.AddError(f"Invalid distance units: {dist_units_str}")
raise CustomError
入力施設の読み込み
次に、load メソッドを使用して、ユーザーの施設を到達圏解析に追加します。
このコード スニペットでは、load メソッドを使用して、入力施設が到達圏解析に追加されます。 「ServiceAreaInputDataType.Facilities」列挙値は、入力を施設として追加する必要があることを示すため、load メソッドのパラメーターとして使用されます。# Load the input facilities
sa.load(arcpy.nax.ServiceAreaInputDataType.Facilities, input_facilities)
到達圏解析の実行と解析実行エラーの処理
到達圏の設定が完了し、入力データが読み込まれたところで、解析を実行して結果を取得できるようになりました。 解析実行メソッドを使用して解析を実行すると、「ServiceAreaResult」オブジェクトのインスタンスが作成されます。これには、解析の出力を操作するためのプロパティとメソッドが含まれます。
このコード スニペットでは、solve メソッドを使用して、到達圏解析が実行されます。 result 変数を使用すると、解析の出力を操作できます。# Solve the analysis
result = sa.solve()
場合により、解析が失敗したり、成功したりするものの、考えられる問題に関する警告メッセージが表示されることがあります。 ツールで、解析のエラーと警告をユーザーに返すことをお勧めします。 解析の実行が失敗した場合は、ツールの実行を停止することをお勧めします。
このコード スニペットでは、「MessageSeverity.Warning」列挙値を使用して警告メッセージを取得するため、ServiceAreaResult オブジェクトの solverMessages メソッドが使用されます。 表示された各警告メッセージは、「AddWarning」関数を使用して、ツールの警告メッセージに追加されます。# Print warning messages if there are any
for warning in result.solverMessages(arcpy.nax.MessageSeverity.Warning):
arcpy.AddWarning(warning[1])
このコード スニペットでは、ServiceAreaResult オブジェクトの solveSucceeded プロパティを使用して、到達圏解析が成功したかを確認します。 成功しなかった場合は、エラー メッセージを取得するために solverMessages メソッドが使用され、「AddError」関数によってエラー メッセージがツールのエラーに追加されます。 さらに、ツールの実行を停止するためのエラーが返されます。 エラー処理の詳細については、後ほど説明します。# Handle failed solves
if not result.solveSucceeded:
arcpy.AddError("The Service Area solve failed.")
# Print error messages and stop the tool from running further
for error in result.solverMessages(arcpy.nax.MessageSeverity.Error):
arcpy.AddError(error[1])
# Stop tool run by raising an error
raise CustomError
フィーチャクラスへ出力到達圏ポリゴンを書き込み
最後に、export メソッドを使用して到達圏解析の出力をユーザー指定のフィーチャクラスに書き込みます。 また、count method を使用して出力のポリゴン数をカウントし、この情報をメッセージとして書き込みます。
このコード スニペットでは、出力のポリゴン数が「AddMessage」関数を使用してメッセージとして書き込まれ、到達圏ポリゴンがフィーチャクラスにエクスポートされます。 「ServiceAreaOutputDataType.Polygons」列挙値は、他の解析出力タイプの 1 つの代わりに、出力ポリゴンを操作するために使用されます。# Add a message with the total number of polygons that were generated
# in the analysis
num_polygons = result.count(
arcpy.nax.ServiceAreaOutputDataType.Polygons)
arcpy.AddMessage(f"Number of polygons generated: {num_polygons}.")
# Export the Service Area polygons to the output feature class
result.export(
arcpy.nax.ServiceAreaOutputDataType.Polygons, output_polygons)
エラーの処理
既知のエラーが発生した場合は、ツールが実行を停止し、有用なエラー メッセージを表示することが望ましいです。 これを行うには、カスタム例外を発生させ、ツールの実行コードを try/except ブロック内で折り返します。
このコード スニペットでは、カスタム例外が定義されます。 これで何かが行われるわけではありませんが、既知の問題が発生したときにツールの実行を停止するのに役立ちます。class CustomError(Exception):
pass
ツールの実行コードは、try/except ブロック内で折り返されます。 CustomError が捉えられた場合、エラー メッセージがすでにツールのエラーに追加されているため、コードは何も行いません。 未知のエラーが発生した場合、コードは、トレースバックを取得し、デバッグに役立つよう、これをツールのエラーとして追加します。try:
[...]
except CustomError:
# We caught a known error and already added the message. Do nothing.
pass
except Exception:
# An unknown error occurred. Add the traceback as an error message.
arcpy.AddError(
"An unknown error occurred when generating Service Areas.")
import traceback
arcpy.AddError(traceback.format_exc())
まとめ
以下のコード スニペットには、前述のすべてのコンポーネントを含む完全な Python スクリプトが含まれています。 このコードをコピーして、ServiceAreaTutorialScriptTool.py ファイルに貼り付けることができます。import arcpy
class CustomError(Exception):
pass
def convert_time_units_to_nax(time_units_str):
"""Convert string-based time units to the correct arcpy.nax enum."""
if time_units_str == "Hours":
return arcpy.nax.TimeUnits.Hours
if time_units_str == "Minutes":
return arcpy.nax.TimeUnits.Minutes
arcpy.AddError(f"Invalid time units: {time_units_str}")
raise CustomError
def convert_distance_units_to_nax(dist_units_str):
"""Convert string-based distance units to the correct arcpy.nax enum."""
if dist_units_str == "Kilometers":
return arcpy.nax.DistanceUnits.Kilometers
if dist_units_str == "Meters":
return arcpy.nax.DistanceUnits.Meters
if dist_units_str == "Miles":
return arcpy.nax.DistanceUnits.Miles
if dist_units_str == "Yards":
return arcpy.nax.DistanceUnits.Yards
if dist_units_str == "Feet":
return arcpy.nax.DistanceUnits.Feet
arcpy.AddError(f"Invalid distance units: {dist_units_str}")
raise CustomError
def generate_service_areas():
"""Generate Service Area polygons."""
try:
input_facilities = arcpy.GetParameterAsText(0)
output_polygons = arcpy.GetParameterAsText(1)
network = arcpy.GetParameterAsText(2)
travel_mode = arcpy.GetParameter(3)
cutoffs = arcpy.GetParameter(4)
cutoff_units = arcpy.GetParameterAsText(5)
time_of_day = arcpy.GetParameter(6)
# Check out the Network Analyst extension license if the input network
# is a local network dataset and not a service.
if not network.startswith("http"):
if arcpy.CheckExtension("network") == "Available":
arcpy.CheckOutExtension("network")
else:
# Throw an error if the license cannot be checked out.
arcpy.AddError("The Network Analyst license is unavailable.")
raise CustomError
# Instantiate the ServiceArea solver object
sa = arcpy.nax.ServiceArea(network)
# Hard-code some non-default Service Area settings that we don't want
# the user to change
sa.geometryAtCutoff = arcpy.nax.ServiceAreaPolygonCutoffGeometry.Disks
sa.polygonBufferDistance = 150
sa.polygonBufferDistanceUnits = arcpy.nax.DistanceUnits.Feet
# Set analysis properties chosen by the user and passed in via tool
# parameters
sa.travelMode = travel_mode
sa.timeOfDay = time_of_day
sa.defaultImpedanceCutoffs = cutoffs
# Do special handling of cutoff units to convert them to the correct
# arcpy.nax enum
if cutoff_units in ["Hours", "Minutes"]:
sa.timeUnits = convert_time_units_to_nax(cutoff_units)
elif cutoff_units in ["Kilometers", "Meters", "Miles", "Yards", "Feet"]:
sa.distanceUnits = convert_distance_units_to_nax(cutoff_units)
# Load the input facilities
sa.load(arcpy.nax.ServiceAreaInputDataType.Facilities, input_facilities)
# Solve the analysis
result = sa.solve()
# Print warning messages if there are any
for warning in result.solverMessages(arcpy.nax.MessageSeverity.Warning):
arcpy.AddWarning(warning[1])
# Handle failed solves
if not result.solveSucceeded:
arcpy.AddError("The Service Area solve failed.")
# Print error messages and stop the tool from running further
for error in result.solverMessages(arcpy.nax.MessageSeverity.Error):
arcpy.AddError(error[1])
# Stop tool run by raising an error
raise CustomError
# Add a message with the total number of polygons that were generated
# in the analysis
num_polygons = result.count(
arcpy.nax.ServiceAreaOutputDataType.Polygons)
arcpy.AddMessage(f"Number of polygons generated: {num_polygons}.")
# Export the Service Area polygons to the output feature class
result.export(
arcpy.nax.ServiceAreaOutputDataType.Polygons, output_polygons)
except CustomError:
# We caught a known error and already added the message. Do nothing.
pass
except Exception:
# An unknown error occurred. Add the traceback as an error message.
arcpy.AddError(
"An unknown error occurred when generating Service Areas.")
import traceback
arcpy.AddError(traceback.format_exc())
if __name__ == "__main__":
generate_service_areas()
Python スクリプト ファイル実行のためのスクリプト ツールの構成
これまでにスクリプト ツールを作成し、そのパラメーターを定義しました。 次に、解析を行うための Python スクリプトを記述しました。 次は、Python スクリプトを実行するようツールを構成する必要があります。 ツールを実行すると、ツールが Python スクリプトのコードを実行し、Python スクリプトがツールのパラメーターから渡された入力を取得して、解析を行います。
- スクリプト ツールを右クリックし、[プロパティ] をクリックして、スクリプト ツールのプロパティ ダイアログ ボックスを開きます。
[ツール プロパティ] ダイアログ ボックスが表示されます。
- サイド タブのリスト内の [実行] タブをクリックします。
- [フォルダー] ボタン をクリックして、ServiceAreaTutorialScriptTool.py スクリプト ファイルの場所に移動します。
ヒント:
ServiceAreaTutorialScriptTool.py ファイルが参照ダイアログ ボックスに表示されない場合は、上のアドレス バーの隣の [更新] ボタンをクリックします。[実行] タブに表示されたコードが、Python スクリプト ファイルの内容を示すよう更新されます。 これで、Python スクリプトを実行するよう、ツールが構成されました。
ツール検証をカスタマイズ
検証とは、ツールの実行前にツールのパラメーターの値を確認、更新するプロセスをいいます。 検証することで、パラメーターの入力値のタイプと値の範囲が正しいか確認できます。 また、検証により、パラメーター選択リストを更新したり、他のパラメーターの値に応じてパラメーターを非表示にしたり、表示したりできます。
検証のプロセスによっては、特定のパラメーター タイプと構成に組み込まれるものもあります。 たとえば、先ほど、ポイント フィーチャクラスのみを受け付けるよう、[フィーチャ タイプ] フィルターを使用して [入力施設] パラメーターを構成しました。 ユーザーがこのパラメーターの入力を選択すると、検証によって入力のタイプが正しいか検証され、正しくない場合はエラー メッセージが表示されます。
ただし、場合によっては、スクリプト ツールの記述者が、より高度でカスタマイズされた検証を行う必要があります。 これは「ToolValidator」クラスを使用して行えます。 この特殊な Python クラスは、カスタム コードを使用して更新することで、パラメーターを更新し、必要に応じてエラー メッセージと警告メッセージを表示するチェックを実施できます。
このチュートリアルでは、[カットオフ] パラメーターが 0 以下になったらエラーを発し、[移動モード] パラメーターの値に応じて、時間単位または距離単位のリストで [カットオフ単位] パラメーターの選択リストを更新するよう、スクリプト ツールで ToolValidator クラスをプログラムします。
ToolValidator コードは、先ほど記述した Python スクリプトとは別のもので、ツールが実行し、別々にアクセス、編集されます。
注意:
「Python ツールボックス (.pyt)」にカスタム ジオプロセシング ツールを作成することもできます。 この場合、検証コードとツール実行コードの両方が同じ Python スクリプトに含まれます。
ToolValidator クラスを探し、開いて編集
スクリプト ツールを作成すると、ToolValidator クラスが自動的に作成されます。 このクラスには、スクリプト ツールのプロパティ ダイアログ ボックスからアクセスし、開いて編集できます。
- 必要に応じて、スクリプト ツールを右クリックし、[プロパティ] をクリックして、スクリプト ツールのプロパティ ダイアログ ボックスを開きます。
[ツール プロパティ] ダイアログ ボックスが表示されます。
- サイド タブのリスト内の [検証] タブをクリックします。
スクリプト ツールの ToolValidator クラスが表示されます。 ダイアログ ボックスで直接コードを編集し、[スクリプト エディターで開く] ボタンをクリックして、IDE またはテキスト エディターで別ファイルとして ToolValidator を開くこともできます。
ヒント:
「ジオプロセシング オプション」の [スクリプト エディター] 設定で、IDE かテキスト エディターのどちらでファイルを開くかを制御できます。
[カットオフ] パラメーター値が 0 以下でエラーを表示
ToolValidator クラスの updateMessages メソッドを使用して、パラメーター値を確認し、エラー メッセージまたは警告メッセージを追加できます。 この項では、[カットオフ] パラメーターの値が 0 以下の場合もエラーを表示するよう updateMessages メソッドを修正します。
- ToolValidator クラスで updateMessages メソッドを探します。
デフォルトでは、updateMessages メソッドには、return ステートメントしか含まれていません。 そのため、カスタム検証が行われません。
- 以下のコードを使用するよう、updateMessages メソッドを変更します。
注意:
検証コードを ToolValidator クラスに渡したら、検証コードのインデントを確認します。def updateMessages(self): # Customize messages for the parameters. # This gets called after standard validation. # Raise an error if any of the cutoffs are <= 0 cutoffs_param = self.params[4] if cutoffs_param.valueAsText: for cutoff in cutoffs_param.values: if cutoff <= 0: cutoffs_param.setErrorMessage("Cutoffs must be positive.") break return
このコード スニペットでは、[カットオフ] パラメーターの値が 0 以下の場合、エラー メッセージが追加されます。
[カットオフ] パラメーターは、ToolValidator クラスに組み込まれたツール パラメーターのリストである self.params 変数を使用して取得されます。 [カットオフ] パラメーターは 5 番目のパラメーターであるため、リストのインデックス 4 を使用してアクセスします。 取得される値は、「Parameter」オブジェクトです。
パラメーターが空の場合、値を確認する必要はありません。 Parameter オブジェクトの valueAsText プロパティから、パラメーターが空かどうかを簡単に判断できます。
これは複数値パラメーターであるため、値のリストは、values プロパティを使用して取得されます。 コードにより、パラメーターの現在の値が反復処理されます。
カットオフ値が 0 以下の場合、エラー メッセージの設定により Parameter オブジェクトの setErrorMessage が使用されます。 このメッセージは、ツールのユーザー インターフェイスのパラメーターに表示されます。
無効な値が認められたら、break ステートメントが反復処理を停止します。 無効な値が見つかったら、残りの値を確認する必要はありません。
注意:
カスタム検証コードを追加しても、各パラメーターに関連付けられた基本内部検証が引き続き適用されます。 たとえば、[カットオフ] パラメーターを Double 型に定義したため、内部検証により、入力が有効な数値となっていて、必要に応じてエラーを返すかが自動的に確認されます。 パラメーターに対して追加したカスタム検証は、そのパラメーター タイプについて自動的に実施された内部検証に引き続いて行われます。
[カットオフ単位] パラメーターへの時間単位または距離単位のリストの入力
移動モードには、ネットワーク内の移動をモデル化する方法を制御する複数の設定が含まれます。 移動モードにより、ネットワーク内の最短パスを探す場合にどの変数が最適化されるかが決定されます。 通常、これは、時間または距離の尺度ですが、ネットワーク データセットを構成して、移動にかかるエネルギーまたは金銭的コストなどの他のタイプの変数を最適化することもできます。
[カットオフ] パラメーターを使用すると、到達圏の移動コストの制限を示す数値を指定できるようになります。 [カットオフ単位] パラメーターを使用すると、これらの値を解釈するときに適用する計測単位を指定できるようになります。
ツールには、有効な単位のリストを提示することをお勧めします。ただし、選択した移動モードにより時間が最適化される場合は、時間単位のみを表示し、選択した移動モードにより距離が最適化される場合は、距離単位のみを表示することをお勧めします。 万が一、移動モードにより他のタイプのコストが最適化される場合は、時間単位も距離単位も表示しないことをお勧めします。
ToolValidator クラスの updateParameters メソッドを使用して、パラメーターの選択リストを更新できます。 この項では、updateParameters メソッドを修正し、[移動モード] パラメーターの値に応じて、適切な単位のリストを使用して [カットオフ単位] 選択リストを設定します。
- ToolValidator クラスで updateParameters メソッドを探します。
デフォルトでは、updateParameters メソッドには、return ステートメントしか含まれていません。 これによりパラメーターが更新されることはありません。
- 以下のコードを使用するよう、updateParameters メソッドを変更します。
注意:
検証コードを ToolValidator クラスに渡したら、検証コードのインデントを確認します。def updateParameters(self): # Modify parameter values and properties. # This gets called each time a parameter is modified, before # standard validation. # Set filter list of units in cutoff units parameter based on what type # of travel mode is selected travel_mode_param = self.params[3] cutoff_units_param = self.params[5] if travel_mode_param.valueAsText: try: tm_object = travel_mode_param.value if tm_object.impedance == tm_object.timeAttributeName: # The impedance has units of time, so present time units as # options cutoff_units_param.filter.list = ["Hours", "Minutes"] elif tm_object.impedance == tm_object.distanceAttributeName: # The impedance has units of distance, so present distance # units as options cutoff_units_param.filter.list = [ "Kilometers", "Meters", "Miles", "Yards", "Feet"] else: # The impedance has units that are neither time nor # distance, so present only one option, "Other". The # Service Area cutoffs will be interpreted in the impedance # units. cutoff_units_param.filter.list = ["Other"] except Exception: pass return
このコード スニペットでは、[カットオフ単位] パラメーターで想定される値のリストが [移動モード] パラメーターの現在の値に基づき更新されます。
これらのパラメーターは、self.params 変数を使用して取得されます。 [移動モード] パラメーターはインデックス 3 (4 番目のパラメーター)、[カットオフ単位] パラメーターはインデックス 5 (6 番目のパラメーター) にあります。
[移動モード] パラメーターが空の場合、[カットオフ単位] パラメーターを更新する必要はありません。 Parameter オブジェクトの valueAsText プロパティから、パラメーターが空かどうかを簡単に判断できます。
[移動モード] パラメーター値は、Parameter オブジェクトの value プロパティを使用して、「TravelMode」オブジェクトとして取得されます。
移動モードにより時間、距離、またはその他の計測単位が最適化されるかを判断する最も簡単な方法には、TravelMode オブジェクトの impedance プロパティと timeAttributeName プロパティおよび distanceAttributeName プロパティを比較する方法があります。 impedance プロパティは、最適化されるネットワーク属性の名前を返します。 移動モードには、デフォルトの時間属性 (timeAttributeName) と距離属性 (distanceAttributeName) も含まれます。 impedance が timeAttributeName と一致する場合、移動モードにより時間が最適化され、[カットオフ単位] パラメーターが時間単位のリストを表示するよう更新されます。 impedance が distanceAttributeName と一致する場合、移動モードにより距離が最適化され、[カットオフ単位] パラメーターが距離単位のリストを表示するよう更新されます。 impedance がどちらとも一致しない場合、移動モードにより他の変数が最適化され、到達圏のカットオフが該当の単位で解釈されます。 [カットオフ単位] パラメーターは、[その他] という 1 つの選択肢のみを表示するよう更新されます。
いずれの場合も、[カットオフ単位] の Parameter オブジェクトの filter.list プロパティを設定することで、選択リストが指定されます。
コード ブロックは、try/except ブロック内で折り返されます。 移動モード読み込み中にエラーが発生した場合、コードは何も処理せず、選択リストを更新しません。
ツール検証を確認
この項では、検証コードを保存、テストします。
- IDE またはテキスト エディターで ToolValidator クラスを開いたら、ファイルを保存して閉じます。
- [ツール プロパティ] ダイアログ ボックスの [OK] をクリックして、変更内容を確定します。
- [カタログ] ウィンドウで、ツールをダブルクリックして開きます。
[ジオプロセシング] ウィンドウで [Service Area Tutorial Script Tool] が開きます。
- [カットオフ] パラメーターに 0 以下の数値を入力します。
[カットオフ] パラメーターにエラー シンボルが表示されます。 エラー シンボルにカーソルを合わせるかクリックすると、エラー メッセージがツールチップに表示されます。
- [移動モード] パラメーターの値を選択したときに [カットオフ単位] 選択リストが正しい単位のリストを表示するよう更新されるかを確認します。
- [ネットワーク] パラメーターの値を選択します。
ヒント:
提供されたチュートリアル データを使用する場合は、[ネットワーク] パラメーターにネットワーク データセットである SanFrancisco.gdb/Transportation/Streets_ND を使用します。 ネットワーク データセットのカタログ パスを使用することも、最初にマップにカタログ パスを追加して、そのレイヤー表現をツールの入力として使用することもできます。[ネットワーク] パラメーターが空の場合、[移動モード] パラメーターには選択リストが格納されません。 [ネットワーク] パラメーターに値を入力すると、[移動モード] パラメーターの選択リストは、[ネットワーク] 値に関連付けられた、使用可能な移動モードのリストを持つよう自動更新されます。
- [移動モード] パラメーターの値を選択します。
[移動モード] パラメーターが空の場合、[カットオフ単位] パラメーターには選択リストが格納されません。 [移動モード] パラメーターの値を入力したら、[カットオフ単位] パラメーターの選択リストは、時間単位または距離単位のリスト (または [その他] の単独オプション) を表示するよう自動更新されます。
- [ネットワーク] パラメーターの値を選択します。
ツールの実行
スクリプト ツールを作成、構成し、ツールのコードを記述して、ツールの検証をカスタマイズしました。 ツールを実行し、他のジオプロセシング ツールと同様に使用できるようになりました。 [ジオプロセシング] ウィンドウからツールを実行するだけでなく、ツールをモデルに追加して、Python スクリプトからツールを呼び出して、「Web ツールとして共有する」こともできます。
- 必要に応じて、[カタログ] ウィンドウでツールをダブルクリックして開きます。
- ツールの各パラメーターの有効オプションを選択します。
[入力施設] パラメーターに使用するポイントが [ネットワーク] パラメーターに使用しているネットワークと同じ地理範囲にあるかを確認します。
ヒント:
提供されたチュートリアル データを使用する場合は、SanFrancisco.gdb ジオデータベースのデータセットを使用して、ツールをテストします。 消防署のポイント フィーチャクラスである SanFrancisco.gdb/Analysis/FireStations を [入力施設] パラメーターに使用し、ネットワーク データセットである SanFrancisco.gdb/Transportation/Streets_ND を [ネットワーク] パラメーターに使用できます。 データのカタログ パスを使用することも、最初にデータをマップに追加してから、レイヤーをツールの入力として使用することもできます。 消防署の対応時間をモデル化するための適切なカットオフは 2 ~ 4 分です。 - ツールの下部にある [実行] ボタンをクリックします。
ツールが無事実行されたら、ポリゴン レイヤーがマップに追加されます。
注意:
ツールが警告メッセージを発することもあります。