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 |
必須かどうか | 必須 |
オプションの型 | 文字列 |
このような定義済み変数の一覧は以下のリンクにあります。結構大量です。
キーとは、スクリプト内で参照するときの辞書のキーです。
コマンドスクリプトでは、スクリプトが実行される最初の部分に、以下のコードをまず記述します。
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を取得します。