ラベル grads の投稿を表示しています。 すべての投稿を表示
ラベル grads の投稿を表示しています。 すべての投稿を表示

2013年4月17日水曜日

Numba




Pythonでforをまわすような数値計算を行うとmatlabなどと同じで非常に遅い。
それを克服するためにpypyやcythonなどがある。しかし基本的にコードを書き換える必要があるので、もっと楽をしたい。

最近numbaというものを知った。ここのサンプルにある例だと、

from numba import autojit

@autojit

のおまじないだけで関数が劇的に早くなる。

少し、自分で例で実験してみた。
全球のSSTに対して、NINO3の相関をとるということをやってみる(これはnumbaの実験のために作った例であり、相関をとるだけならもっとエレガントな方法があるだろう)。

そのノートブックが
http://nbviewer.ipython.org/5396344

説明
(1) 図をプロットするためのおまじない。

(2) SSTアノマリとNINO3を読む関数を定義。
  元データは NOAA OISST v2でmonthly dataのsst.mnmean.ncを使う。
  データはPython Interface to GrADSを使って読む。
  1982から2010年のデータから気候値からのanomaly(Bin Guan's GrADS Script Libraryのdeseasonを使った。古いバージョンを使ったので、今は使い方が違うかも知れない)とNINO3 SSTアノマリを定義し、返す。
 ここらへんは以前の記事も参照。
 /usr/local/lib/python2.7 なんちゃらというメッセージは私の環境でインストール上のゴミなので気にしないで。

(3) 上で定義した関数を呼んでいる。

(4)  時系列xと二次元時系列(水平2次元と時間の3次元)から2次元の相関係数を返す関数。

from numba import autojit
@autojit
の部分がnumba.

(5) ベンチマーク
  この場合、5.7秒かかっている。
   
  @autojitの代わりに@jit('f8[:,:](f8[:],f8[:,:,:])')としても速度はかわらなかった。
  
  もし上で@autojitを付けない場合、7.34秒だった。
 
  つまりnumbaを使っていることで、確かに速くなっているが、劇的にではなかった。

  これは、forでまわしている中身がプリミティブな式ではなくて、numpyの関数corrcoefであるからだろうか。

  ちなみに、欠損値処理は何もやっていないので、warningが出ている。この場合はプロットするときに陸地のデータはマスクするので、これで構わない。

  欠損値処理もできるma.corrcoefを使うとかなり遅くなる。
  numbaを使わない場合で50.2秒、numbaを47.5秒だった。

(6) 実際に相関係数を求める。

(7)  land sea maskを読む関数

(8) land sea maskを読む

(9) プロット  

  エルニーニョに典型的な馬蹄形が見られる。インド洋ダイポールへの相関も見られる。


結論
今回試したケースでは、劇的というほどではないが、ちょっとした追加で、確かに速くはなった。場合によっては劇的に速くなる場合もあるだろう。。今後の進展に期待したい技術である。


  
  

2012年2月6日月曜日

GrADSで作成するpostscriptの不要な横線

GrADSでpostscript形式の図を作ると不要な横線が入ってしまうことがある。

従来の対策は、例えば
http://www.sci.hokudai.ac.jp/~sasakiyo/tips_grads.html

GrADS 2.0.0から従来のgxout shaded に加えて、gxout shade2が加わっている。
http://www.iges.org/grads/gadoc/gradcomdsetgxout.html
これで図を作ったところ、従来横線が入っていた場合に、横線が入らなくなった。常にそうであるかは要確認。

2011年5月6日金曜日

気象庁全球数値予報モデルGPV (GSM)



気象庁全球数値予報モデルGPV (GSM) の初期値データを京都大学のサイトからダウンロードして、清水慎吾さん作成のgsm2binでgrib2形式からgrads形式に変換するモジュール。

以下がそのモジュール。サンプルのメインプログラムでは、2011年1月1日6時のデータを変換し、python interface to gradsで海面気圧をプロットしている。

get_gsm.py
def get_gsm(date=[2011,1,1,0],dir="."):
    """
   download jma gsm initial data from   http://database.rish.kyoto-u.ac.jp/arch/jmadata/da
ta/gpv/original/
   and
   convert to grads file using gsm2bin by Dr. Shingo Shimizu
   (http://shimizus.hustle.ne.jp/wiki/wiki.cgi?page=%A5%E2%A5%C7%A5%EB%B4%D8%CF%A2%A5%E1%A
5%E2)

   usage:
      get_gsm(date,dir)
     
   input
     
      date: [year,month,day,hour]  hour must be multiple of 6
            default [2011,1,1,0]
      dir : directory to save data    
    """
    import os,urllib

#check
    assert date[3] % 6 ==0, "Error, hour must be multiple of 6!!!"

#names from date
    urldir,original,gradsbinname,gradsdate=name_maker(date)

# get original data
    if not os.path.exists(dir+"/"+original):
        if not os.path.exists(dir): os.mkdir(dir) 
        # Download the data
        print 'Downloading data, please wait'
        opener = urllib.urlopen(urldir+original)
        open(dir+"/"+original, 'w').write(opener.read())
        print 'Downloaded'

# convert to grads file
    os.system("gsm2bin  %(dir)s/%(original)s %(dir)s/%(gradsbinname)s" %locals())

# make ctlfile
    make_ctl(dir,gradsbinname,gradsdate)

############################################

def name_maker(date):
    """
    make filenames from date
"""
    
    import datetime
    time=datetime.datetime(*date)
    cyear=time.strftime("%Y")
    cmonth=time.strftime("%m")
    cmonth2=(time.strftime("%b")).lower()
    cday=time.strftime("%d")
    chour=time.strftime("%H")

    # URL of original data
    urldir="http://database.rish.kyoto-u.ac.jp/arch/jmadata/data/gpv/original/%(cyear)s/%(
cmonth)s/%(cday)s/" %locals()

    # File name of original data
    original="Z__C_RJTD_%(cyear)s%(cmonth)s%(cday)s%(chour)s0000_GSM_GPV_Rgl_FD0000_grib2.
bin" %locals()

    # grads bin name after conversion
    gradsbinname="gsm%(cyear)s%(cmonth)s%(cday)s%(chour)s.bin" %locals()

    # date in grads format
    gradsdate="%(chour)s:00Z%(cday)s%(cmonth2)s%(cyear)s"  %locals()
    return urldir,original,gradsbinname,gradsdate

###########################################
def make_ctl(dir,gradsbinname,gradsdate):
    """
    make grads ctl file for GSM data 
"""
    #ctl file text

    ctltxt="""
dset ^%(gradsbinname)s
options template
undef -999
xdef 720 LINEAR 0.0 0.5
ydef 361 LINEAR -90.0 0.5
zdef 17  LEVELS 1000 925 850 700 600 500 400 300 250 200 150 100 70 50
30 20 10
tdef 1 LINEAR %(gradsdate)s 6hr

vars 16
slp 0  0 sea level pressure
sp  0  0 surface pressure
su  0  0 surface westerly  wind
sv  0  0 surface southerly wind
st  0  0 surface temperature
srh 0  0 surface relative humidity
lca 0  0 LowCloudAmount
mca 0  0 MidCloudAmount
hca 0  0 HighCloudAmount
tca 0  0 TotalCloudAmount
z   17 0 height  
u   17 0 westerly wind
v   17 0 southerly wind
t   17 0 temperature
rh  17 0 relative humidity
w   17 0 p-velocity
endvars
"""

    # write to file
    gradsctlname=dir+"/"+gradsbinname.replace(".bin",".ctl")
    f=open(gradsctlname,"w")
    f.write(ctltxt %locals())
    f.close()

#-----------------------------------------------------------------------

if __name__ == '__main__':

    # get gsm data
    get_gsm(date=[2011,1,1,6],dir="DATA")

    # plot
    from grads.galab import GaLab  # for python interface for grads
    ga = GaLab(Bin='grads',Window=False,Echo=True,Verb=0,Port=False)
    ga.open("DATA/gsm2011010106.ctl")
    script="""
    set grads off
    set gxout shaded
    d slp/100
    cbarn
    draw title Sea level pressure (hpa)
    printim gsm.png white
    """
    ga(script)



2011年2月25日金曜日

Gradsでregrid



GrADSにおいて、二つのデータセットのグリッドをそろえて、差を見てみることをおこなった。

OpenGrADSのre関数を用いた。
下のソース例、
define sstre=re(sst.1,180,linear,0,2,89,linear,-88,2,ba)
では、変数sst.1を
経度方向に、180グリッド、0度から2度刻みで、線形
緯度方向に、89グリッド、南緯88度から2度刻みで、線形
box averageでグリッドに落としている。

例ではNOAA OISST version 2(1)とNOAA Extended Reconstructed SST version 3b(2)という二つの1月の海面水温データセットから2011年1月の値をそれぞれプロットし、3番目の図で、その差(2-1)を引いている。データはNOAAのサイトからOPeNDAPで取得している。

下がgradsのスクリプト。
"grads -p"でportraitモードで使う。
他に、mul.gs, color.gs, draws.gs という Chihiro Kodama氏のgradsスクリプトを用いている。


"reinit"
*NOAA OISST V2
"sdfopen http://www.esrl.noaa.gov/psd/thredds/dodsC/Datasets/noaa.oisst.v2/sst.m
nmean.nc"
"set time jan2011"
"mul 1 3 1 3 -yoffset -0.5"
"set grads off"
"color 0 30 2 -kind grainbow -gxout grfill"
"d sst"
"set strsiz 0.15"
"draws 1) NOAA OISST V2"

*NOAA Extended Reconstructed SST V3b
"sdfopen http://www.esrl.noaa.gov/psd/thredds/dodsC/Datasets/noaa.ersst/sst.mnme
an.nc"
"set time jan2011"
"mul 1 3 1 2  -yoffset -0.5 "
"set grads off"
"color 0 30 2 -kind grainbow -gxout grfill"
"d sst.2"
"set strsiz 0.15"
"draws 2) NOAA Extended Reconstructed SST V3b"
"cbarn 0.7 1 7.6 7.5"

*diff
"define sstre=re(sst.1,180,linear,0,2,89,linear,-88,2,ba)"
"mul 1 3 1 1  -yoffset -0.5"
"set grads off"
"color -levs -2 -1.5 -1 -0.5 0.5 1.0 1.5 2  -kind blue->white->red -gxout grfill"
"d sst.2-sstre"
"set strsiz 0.15"
"draws 2)-1)"
"cbarn 0.7 1 1. 2."
"printim sst_regrid_compare.png white"