ログイン

GrADSスクリプトのTips

Top / GrADS / tips_script

Japanese / English

はじめに

  • 以下のコンテンツは、2014年3月時点における東北大学大学院理学研究科 流体地球物理学講座のページを、web管理者の許諾を得てコピーしたものです。
    • 従って、以下のコンテンツは講座メンバーをはじめ様々な方々の協力・助言・激励によって作成されたものです。
    • 今のところ情報は古いままですが、講座ページとは独立して今後少しずつ更新を行う予定です。
    • 講座ページとは適宜同期を行うなど、今後も協力関係を保って行けたらと思います。
  • 内容に間違いがありましたら、小玉 までご連絡ください。

目次

基本

スクリプトを実行する

スクリプトを実行するには GrADsのrunコマンドを使います。

run ファイル名 [引数]

ただし引数は省略可能です。以下にスクリプトの例を示します。 1行目のコントロールファイル名と 2行目の変数名を適当なものに変更し、 test1.gsという名前で保存して実行してください。

test1.gs

'open wind.ctl'
'd u'

実行例

ga-> run test1.gs
ga-> 

これで画面に絵が表示されます。もし何も表示されない場合は、 test1.gsの 'd u' の後に改行が入っているかどうか確かめてみてください。 GrADsスクリプトでは末尾に改行が入っている行のみ実行されます

GrADsスクリプトの拡張子(ファイル名の . の後の文字)は、ふつう gs (grads scriptの略) とします。 runの際には.gsを省略することができ、

ga-> run test1

でも上と同じように実行できます。ちなみにrunも省略可能で、

ga-> test1

でも動きます。

スクリプトの中身は、実行したいGrADsコマンドをシングルクオーテーション' 'で囲んで並べます。ダブルクオーテーション" "でも構いません。スクリプトを実行すると、上から順にコマンドが実行されていきます。

文法上は必ずしもコマンドを ' ' で囲む必要はありません。しかし、' 'で囲まないとスペースが無視されてしまいます。したがって、

test_good.gs

q

であればうまく動きますが、

test_bad.gs

q file

では

ga-> run test_bad.gs
Unknown command: qfile
ga->

とエラーが出ます。したがって、GrADsコマンドは全て' 'で囲むようにしたほうが良いでしょう。

行をコメントアウトする

コメントにしたい行の先頭(1桁目)に * をつけると、その行は無視されます。

'set lev 100'
*'set lev 1000'

必ず行の先頭に*をつけて下さい。 *の前に空白やタブが入っていても、エラーになります。

一行に複数のコマンドを記述する

";"で区切ると一行に複数のコマンドを記述することができます。

  • 'set lev 1000 1' ; 'set lat 50' ; 'set lon 135'
    

表示

文字列を表示する

say '文字列'
prompt '文字列'

sayは文字列を表示して改行しますが、promptは改行しません。

  • (例)"Hello GrADS" と表示して改行する
    say 'Hello GrADs'
    

変数

変数を使う

変数名=値

スクリプト内では文字列変数を扱うことができます。変数名は1〜8文字のアルファベット又は数字を使うことができますが、1文字目は必ずアルファベットにします。

  • (例)文字列"Eliassen Palm"を変数EPに格納する
    EP='Eliassen Palm'
    
  • (例)10.5をUに代入する
    U=10.5
    

    上のように、数値を代入する場合はクオーテーションを付ける必要はありません。

変数の内容を表示する

say 変数名
prompt 変数名
  • (例)文字列"Hello"を変数に格納して表示する
    word='Hello'
    say word
    
  • (例)変数の内容と文字列を混ぜて表示する
    name='ABC'
    value=10
    say 'name='name' value='value
    

配列を使う

変数名の末尾を".数字"とすることで、配列的に変数を扱うことができます。

  • (例)配列aを使う
    i = 1
    while( i <= 10 )
      a.i = i * i
      say a.i
      i = i + 1
    endwhile
    say a.3
    

ちなみに.の後は数字以外でも構いません。この場合は配列というよりhash変数的ですね。ただし、

a.red = 10
say a.red

のように直接使用することはできません。

color = 'red'
a.color = 10
say a.color

のように.の後を必ず変数にする必要があります。

なお、配列をたくさん取りすぎるとスクリプトがすごく重くなります。

i = 1
while( i < 100000 )
  a.i = i * i
  i = i + 1
endwhile

のようなスクリプトはお薦めできません。この処理だけでなく、この後の処理も非常に遅くなります。

コマンドの結果を表示する

say result

d や q dims などをスクリプト内に記述しても、コンソールには何も表示されません。本来表示される内容は、特殊変数resultに格納されます。

  • (例)uを描画する(直接入力した場合と同じメッセージも表示)。
    'd u'
    say result
    

条件分岐

条件によって処理を分岐する

  • (1)
    if(条件式)
      処理
      ・・・
    endif
    
  • (2)
    if(条件式)
      処理
      ・・・
    else
      処理
      ・・・
    endif
    

    条件処理にはif〜else〜endifを使います。else〜は省略可能ですが、endifは必ず付けて下さい。 なお、else ifに相当する文法はありません。

  • (例)ifを使った処理(この例では "Good morning" と表示される)
    switch=2
    if(switch=1)
      say 'Hello'
    else
      say 'Good evening'
    endif
    
  • (例)ifを使った処理(文字列でも条件分岐ができる例)
    season='DJF'
    if(season='DJF')
      say 'DJFです'
    endif
    if(season='JJA')
      say 'JJAです'
    endif
    

繰り返し

while文

while(条件式)
  処理
  ・・・
endwhile
  • (例) t=1〜3までのUを重ねて表示する
    i=1
    while(i<=3)
      'set t 'i
      'd u'
      i=i+1
    endwhile
    
    

whileループから脱出する

break

whileループの先頭に処理を移す

continue

演算子

一覧表

優先順位 演算子 意味
1 - マイナス符号(単項演算子)
! 否定(単項演算子)
2 除算
* 乗算
3 + 加算
- 減算
4 % 連結
5 = 等しい
!= 等しくない
> 大なり
>= 大なり又は等しい
< 小なり
<= 小なり又は等しい
6 & 論理AND
7 論理OR
  • (例)a=1またはb=1のときYesと表示する
    if(a=1 | b=1)
       say 'Yes'
    else
       say 'No'
    endif
    

組み込み関数

  • スクリプト用の組み込み関数。
  • 引数としてスクリプト内で定義した文字列変数を与えることはできます。しかし(次元を持った)所謂GrADS変数を与えることはできませんのでご注意下さい。GrADS変数の場合はGrADS関数(ave, sinなど)を使ってください。
  • 組み込み関数には"Intrinsic Functions"と"Math Functions"があります(違いはよく分かりませんが)
  • Intrinsic Functions の一覧
    • strlen, sublin, subwrd, substr, read, write, close

三角関数を計算する

ret = math_sin(angle)
ret = math_cos(angle)
ret = math_tan(angle)
ret = math_asin(angle)
ret = math_acos(angle)
ret = math_atan(angle)
ret = math_atan2(angle, angle2)
ret = math_sinh(angle)
ret = math_cosh(angle)
ret = math_tanh(angle)
ret = math_asinh(angle)
ret = math_acosh(angle)
ret = math_atanh(angle)
angle 角度(ラジアン)
angle2 角度(ラジアン)
ret angle(math_atan2の場合はangle/angle2?)の三角関数

自然対数を計算する

ret = math_log(num)
num 0より大きな任意の数
ret numの自然対数

常用対数を計算する

ret = math_log10(num)
num 0より大きな任意の数
ret numの常用対数

指数関数を計算する

ret = math_pow(num, exponent)
num 任意の数
exponent 任意の数
ret 指数関数の値(num^exponent)

指数関数(exp)を計算する

ret = math_exp(exponent)
exponent 任意の数
ret 指数関数の値(exp^exponent)

平方根を計算する

ret = math_sqrt(num)
num 任意の数
ret numの平方根(ルート)

絶対値を計算する

ret = math_abs(num)
num 任意の数
ret numの絶対値

余りを計算する

ret = math_fmod(num1, num2)
num1 小数
num2 小数(非0)
ret num1/num2の余り

余りの整数部分を計算する

ret = math_mod(num1, num2)
num1 小数
num2 小数(非0)
ret num1/num2の余りの整数部分

小数を最も近い整数に直す

ret = math_nint(num)
num 小数
ret numに最も近い整数値(恐らく[num+0.5])

小数を整数に直す(切捨て)

ret = math_int(num)
num 小数
ret numの小数部分を切り捨てた整数値([num])

文字列が整数か実数かを調べる

ret = valnum(文字列)
  • 戻り値(ret)
    0 文字列は実数ではない
    1 文字列は整数である
    2 文字列は整数ではないが実数である

文字列の長さを得る

ret = math_strlen(string)
ret = strlen(string)
string 文字列
ret 文字列の長さ
  • strlen()はVersion1.8以下では使えない?

数値を整形する

ret = math_format(format, num)
format C言語風の書式指定(e.g., %5.2f, %+10.5e)
num 整形する数値
ret 整形された数値
  • (例)小数点第1位まで表示
    pi = 3.141592
    a = math_format('%.1f', pi)
    say a
    
  • (例)小数点第1位まで表示(全部で10桁になるように左側に空白を入れる)
    pi = 3.141592
    a = math_format('%10.1f', pi)
    say a
    
  • (例)符号を必ず付けて表示
    pi = 3.141592
    a = math_format('%+10.3f', pi)
    say a
    

文字列を取り出す

ret = substr(string, start, length)
string 文字列
start 整数値(開始位置)>0
length 整数値(長さ)
ret 指定した文字列
  • stringが短すぎる場合、NULL("")が返ります。

行を指定して文字列を取り出す

ret = sublin(string, n)
string 文字列
n 整数値
ret n行目の文字列
  • stringの行数がnより小さい場合、NULL("")が返ります。

空白で区切られた文字列から、n番目の文字列を取り出す

ret = subwrd(string, n)
string 文字列
n 整数値
ret n番目の文字列
  • stringが短すぎる場合、NULL("")が返ります。

空白で区切られた文字列から、n番目の文字列の位置を取得する

ret = wrdpos(string, int)
string 文字列
int 整数値
ret n番目の文字列の開始位置

テキストファイルの読み込み

ret = read(filename)

retには2行の情報が返される。1行目がファイル状態、2行目にファイルの内容である。~ ファイル状態は「0」で正常、「1」でエラー、「2」でファイルの最後まで来ています、などとなる。~ 一度のreadで1行分の情報しか読み取らないために、複数の行を読み取りたい場合は、複数回実行する必要がある。~ 以下サンプル。

(test.dat)
this data is test.dat
1.0 2.0 3.0
4.0 5.0 6.0
(サンプルスクリプト)
ret = read('test.dat')
a = sublin(ret,1)
b = sublin(ret,2)
say 'a is 'a
say 'b is 'b
ret = read('test.dat')
a = sublin(ret,1)
b = sublin(ret,2)
say 'a is 'a
say 'b is 'b
(結果)
a is 0
b is this data is test.dat
a is 0
b is 1.0 2.0 3.0

テキストファイルの書き込み

ret = write( filename, record )           <- 上書き
ret = write( filename, record, append )   <- 追記

appendを指定しない場合、最初のwriteで元のファイルが消えてしまうので注意が必要です。書き込みに成功すると0、失敗すると1又は8が返されます。

ファイルのクローズ

ret = close( filename )

writeで書き込んだファイルをreadで読む場合など、明示的なファイルのクローズが必要な場合に用います。

自作の関数

  • スクリプト用の自作関数。

使いかたは組込み関数と基本的に同様ですが、使用前に

rc = gsfallow("on")

を実行しておく必要があります。

関数の作成

function 関数名(引数1, 引数2, ...)
...
return 戻り値

引数や戻り値は省略できます。

デフォルトのスクリプト

cbar.gs, cbarn.gs, cbarc.gs

カラーバーを表示する。「set gxout shaded」のときのみ有効。

ga-> cbar         //長方形
ga-> cbarn        //基本的に上と同じ、但し端が三角
ga-> cbarc        //隅に小さく

font.gs

font set に含まれる全てのフォントを表示する

ga-> font

zoom.gs

マウスでクリックした範囲をズームする。 LAT-LON図でのみ有効。

ga-> d u         //2次元の図を描画しておく
ga-> zoom
click right botton .. to clear any previous mouse clicks
click on bottom left corner of zoom area
click on top right corner of zoom area
ga-> d u         //ズーム領域を描画

応用例

図の日付を描画する

set time (またはset t)で設定した日付を図中に入れます。

'set time 01jan2000'
'q dims'                       // 次元の情報を変数resultに格納
temp=sublin(result,5)          // 日付を表す行を取り出す
tim=subwrd(temp,6)             // 日付を表す部分を取り出す
'set strsiz 0.2 0.2'           // 文字の大きさを設定
'draw string 2.0 2.0 'tim      // 描画

ある物理量の最大値・最小値をファイルに保存する

T(温度)の最大値・最小値を画面に出力し、ファイル(t_minmax.txt)に保存します。スクリプトの中で有効。

'set gxout stat'                  // 統計量を出力
'd t'                             // 温度の出力
res=sublin(result,8)              // 最大値・最小値の行(この場合、8行目)を取り出す
min=subwrd(res,4)                 // 最小値(この場合、4行目)を取り出す
max=subwrd(res,5)                 // 最大値(この場合、5行目)を取り出す
say 'min/max:'min' 'max           // 画面に取り出した最小値・最大値を出力
dum=write(t_minmax.txt,min' 'max) // ファイル(t_minmax.txt)に最小値・最大値を保存

その他

自作したスクリプトファイルはどこに置くべきか

ga-> run test

を実行すると、GrADSは以下の順番でスクリプトを実行しようとします。

  1. 現在のディレクトリのtest
  2. 現在のディレクトリのtest.gs
  3. 環境変数GASCRPで指定したディレクトリのtest
  4. 環境変数GASCRPで指定したディレクトリのtest.gs

何度も使わないスクリプトであれば、好きな場所に置いてそこからGrADSを実行するとよいでしょう。汎用性のある(=何度も使う)スクリプトの場合は、GASCRPで指定したディレクトリに置くのがよいでしょう。好きな場所に置いて絶対パスでディレクトリを指定することも可能ですが、入力が面倒になります。

なお、GASCRPはスペース区切りで複数指定することが可能です。たとえば

GASCRP="/usr/local/lib/grads /home/hoge/myscripts"

のように、デフォルトのスクリプトと自作のスクリプトを分ける使い方が考えられます。

自作した関数を別ファイルにするには

同一ファイルに存在しない関数(たとえばmyfunc())は、

  1. 呼出元のスクリプトがあるディレクトリのmyfunc.gsf
  2. 環境変数GASCRPで指定したディレクトリのmyfunc.gsf

の順に関数が入ったファイルを探します。また、スクリプト内でgsfpath()関数を使って指定することも可能です。例えばgsfpath("aaa bbb")と予め指定すると、

  1. 呼出元のスクリプトがあるディレクトリのmyfunc.gsf
  2. 呼出元のスクリプトがあるディレクトリのaaa/myfunc.gsf
  3. 呼出元のスクリプトがあるディレクトリのbbb/myfunc.gsf
  4. 環境変数GASCRPで指定したディレクトリのmyfunc.gsf

となります。

ここからは経験則ですが、gsfpath を複数回実行すると、以前に gsfpath で設定したパスは原則として上書きされます。但し、一度でも実行された関数は gsfpath の設定値が変わっても実行可能です。また、gsfpath で設定するパスは呼び出し元の gs から見たパスを設定します。以上を例で分かりやすく説明すると、

  • dir1/func1.gsf
    function func1()
    return 'func1 in dir1'
    
  • dir1/func2.gsf
    function func2()
    return 'func2 in dir1'
    
  • dir2/func1.gsf
    function func1()
    return 'func1 in dir2'
    
  • dir2/func2.gsf
    function func2()
    return 'func2 in dir2'
    
  • test1.gs
    rc = gsfallow('on')
    rc = gsfpath('dir1')
    say func1()
    say func2()
    
  • test2.gs
    rc = gsfallow('on')
    rc = gsfpath('dir1')
    say func1()
    rc = gsfpath('dir2')
    say func1()
    say func2()
    

というファイルを用意しておき、test*.gs をそれぞれ実行すると、

ga-> test1
func1 in dir1
func2 in dir1
ga-> test2
func1 in dir1
func1 in dir1
func2 in dir2

となります。さらに追加で

  • dir1/func3.gsf
    function func3()
     rc = gsfpath('dir2')
     say func2()
    return 'func3 in dir1'
    
  • dir1/func4.gsf
    function func4()
     rc = gsfpath('../dir2')
     say func2()
    return 'func4 in dir1'
    
  • test3.gs
    rc = gsfallow('on')
    rc = gsfpath('dir1')
    say func3()
    say func1()
    
  • test4.gs
    rc = gsfallow('on')
    rc = gsfpath('dir1')
    say func4()
    say func1()
    

を用意すると、

ga-> test3
func2 in dir2
func3 in dir1
func1 in dir2
ga-> test4
Function not found: func2
Error occurred on line 3
  In file dir1/func4.gsf
Error occurred on line 3
  In file test4.gs

となり、gsf ファイル内で呼び出す gsfpath は呼び出し元の gs から見たパスを指定する必要があることが分かります。

スクリプトを明示的に終了する

exit

スクリプトファイルの終端に達する前に動作を終了します。

  • (例)Uのみ描画する
    'd U'
    exit
    'd V'
    

    exitはスクリプトのデバッグに重宝します。

バグ:NetCDFファイルとGridファイルは同時に開けない。

open ***.grd
sdfopen ***.nc
  • の後、ある変数を描画しようとすると、「セグメンテーション違反です」と警告が出て異常終了する。

バグ:"e"と"+"の区別ができない(1.8系、1.9系)

if( 'e' = '+' ) ; say 'fail' ; endif

というスクリプトを実行すると、failと表示されます。つまり、"e"と"+"は条件分岐で区別できません。このバグは2.0系では修正されています。おそらく浮動小数点まわりのバグかと。

  • (回避方法の例) 文字列charがeか+か判断する
    char='e'
    *char='+'
    temp='1'char'5'
    if( temp = 1e+5 )  ; say 'char is e' ; endif
    if( temp = '1+5' ) ; say 'char is +' ; endif
    

Link