GRASS7 : Pythonスクリプトと自作コマンド作成

GRASS7ではPythonで自作コマンドを作れるようになりました。
割と簡単に作れる上に、Pythonのモジュールを通してR等ほかのライブラリと連携も取りやすくなりました。
とりあえず、GRASS7のPythonについて少しメモを残しておこうと思います。

Pythonコンソールについて

GRASS GUIのLayer Manager画面の下にある”Python”タブを選択するとPythonコンソールが開きます。
Pythonコンソールの使い方は以下のリンクが詳しいです。

Using GRASS GIS through Python and tangible interfaces (workshop at FOSS4G NA 2016)

ただし(WinGRASSの場合だけでしょうか)、このリンクの最初の方にあるように、いきなりgscript.***は使えないようです。
最初に以下のコマンドを実行しておく必要があります。

<<< import grass.script as gscript

コマンドコンソール

scriptパッケージの基本的な使い方

sciptパッケージのドキュメントは以下のリンクにあります。

script package — Python library documentation documentation

いろいろな関数がありますが、主に使うのは以下の4つぐらいかなと思います(筆者が使いこなせていないだけかも。。)。

script.run_command

標準出力の取得が必要ない場合にコマンドの実行する場合に使用します。使い方は以下のようなかんじです。

gscript.run_command('r.colors', map='dem', color='grey')

script.read_command

コマンドの標準出力結果を使いたい場合に使用するコマンドです。
以下の例は、demマップのセルタイプを調べて、FCELL、DCELLのどちらでもない場合は処理を中断するというコードです。

  res = gscript.read_command('r.info', map='dem', flags='g')
  dtype = gscript.parse_key_val(res)['datatype']
  if dtype != "FCELL" and dtype != "DCELL":
    gscript.fatal(_("input data type is neither FCELL nor DCELL"))

script.write_command

標準入力を使いたい場合に使用します。
あまり多くはありませんが、GRASSのコマンドの中には標準入力からの入力をパラメータとして受け取れるものがあります。
以下の例は、r.colorsコマンドでrules='-'を指定して標準入力からカラールールを設定するものです。

  gscript.write_command('r.colors', map=t_curv, rules='-', stdin='%sn%sn%sn%sn' %
                       ("-0.2 0:0:255", "0.2 255:255:255", "nv 255:255:255", "default 255:255:255"))

script.mapcalc

GRASSといえばmapcalc、なのかどうかはわかりませんが、r.mapcalcコマンドには専用の関数が用意されています。
以下のようにして使います。

  gscript.mapcalc("$output.r = 0.2*r#$map1 + 0.2*r#$map2 + 0.2*r#$map3 + 0.2*r#$map4 + 0.2*r#$map5",
   output="output", map1="input", map2="t_slope", map3="t_slope2", map4="t_curv", map5="t_curv2")

わかりにくい例ですが、gscript.mapcalc()関数の第1引数がmapcalcの式になります。
式中の’$’がついたオペランドは第2引数以降で指定するレイヤです。
‘r#’はレイヤの表示色の赤の値を表しています。

自作コマンドの作成

よく使う一連の処理は自作コマンドとしてまとめると便利です。
とりあえず、以下のスクリプトを作ってみます。

#!/usr/bin/env python

#%module
#% description: Raster test.
#% keyword: raster
#%end
#%option G_OPT_R_INPUT
#%end

import grass.script as gscript

def main():
  input = options['input']
  gscript.run_command('r.info', map=input)

if __name__ == "__main__":
  options, flags = gscript.parser()
  main()

上のスクリプトは指定したラスタレイヤに対してr.infoを実行するだけのものです。
このコマンドを使えるようにしてみます。以下は、OSGeo4WのGRASSの場合について説明します。

ファイルの置き場

GRASSをインストール(もしくは初回起動)すると、
C:Usersユーザ名AppDataRoamingGRASS7
以下に、addons、toolboxesというフォルダがあり、さらにaddonsフォルダ内にはbin、docs、etc、scripts等のフォルダがあると思います。

コマンドを使えるようにするには、まず上記のスクリプトを「.py」の拡張子で保存し(ここではr.test.pyとします)、scriptsフォルダ内に保存します。
次に、binフォルダ内に、以下の内容を記述した.batファイルを作成します。

@"%GRASS_PYTHON%" "%GRASS_ADDON_BASE%/scripts/r.test.py" %*

このコマンドは、環境変数を展開すると

C:/OSGeo4W/bin/python.exe 
   C:/Users/ユーザ名/AppData/Roaming/GRASS7/addons/scripts/r.test.py

となります。

ここまで出来たら、Layer Managerの”Console”タブを開き、下にある欄に”r.test”と入力してみましょう。

コマンド入力

以下の画面が立ち上がったらひとまず成功です。

自作コマンド実行結果

コマンドスクリプトのGUI定義

コマンドスクリプトは、普通のスクリプトにコマンドのGUI定義と定義の読み込みが加わったものです。
上記のスクリプトの中で、GUI定義は「#%」が先頭にある行にあたります。
以下はその抜粋です。

#%module
#% description: Raster test.
#% keyword: raster
#%end
#%option G_OPT_R_INPUT
#%end

#%module#%endまでの行はコマンドの説明で、コマンド画面の上の方に表示されます。

#%option G_OPT_R_INPUTは定義済み変数で、以下の内容を表しています。

表示文字列Name of input raster map
キーinput
キーの説明name
必須かどうか必須
オプションの型文字列

このような定義済み変数の一覧は以下のリンクにあります。結構大量です。

Parser standard options

キーとは、スクリプト内で参照するときの辞書のキーです。
コマンドスクリプトでは、スクリプトが実行される最初の部分に、以下のコードをまず記述します。

  options, flags = gscript.parser()

戻り値のoptions, flagsはそれぞれコマンド画面から渡されるオプションとフラグの辞書です。
そこで、上記の入力をコード内で参照したい場合に、キーを使って取得します。

  input = options['input']

キーの説明とは、コマンド画面上のオプション入力欄の右上にある、「(input=name)」の”name”の部分のことです。

定義済みオプションは、中身を変更することもできます。例えば、表示文字列を変更するには以下のようにします。

#%option G_OPT_R_INPUT
#%description: Name of raster map for r.info
#%end

上記のコードのように、定義済みオプションと#%endの間に変更したい項目と変更内容を記述します。
なお、特に変更しない場合でも定義済みオプションは#%endで閉じる必要があります。

自作コマンド実行結果

定義済みオプションに無い独自のオプションを作成する場合は、キーや表示文字列などをコードで定義します。

#%option
#%key: myopt
#%description: custom parameter
#%answer: hogehoge
#%guisection: Required
#%end

answerはデフォルト値、guisectionは表示するタブをそれぞれ指定しています。
ここではinputオプションと同じ”Required”タブを指定していますが、別の名前を記述するとその名前のタブが新たに作成されます。

自作オプション

フラグは定義済みのものはないので、必要な情報を自分で記述します。

#%flag
#%key: f
#%description: test flag
#%guisection: Required
#%end

フラグもオプションと同様に、flags['f']のようにOn/Offを取得します。

アーカイブ