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

2014年11月11日火曜日

Surface velocity data of MOVE/MRI.com at NEAR-GOOS RRTDB



NEAR-GOOSのRegional Real Time Databaseのサイトは、最近更新されて、データのダウンロードがregistration無しでダウンロードできるようになった(自動ダウンロードを行うにはregistrationが必要)。

ここでは、その中から、気象庁(JMA)のDaily Surface Currents in the seas adjacent to Japanをプロットして見る。

2014年11月6日のデータ "move_subc_jpn_D20141106.txt"をダウンロードして置き、CartopyでプロットするIPython Notebookはこちら。
https://www.dropbox.com/s/bpow09n6x4rm9sy/MOVE_velocity.ipynb?dl=0





2014年10月30日木曜日

Colors (diverging data)



前回はsequential data用のカラーマップについてテストしたが、今回は正負のアノマリなどをプロットする diverging カラーマップについてテストした。

ipython notebookはこちら
http://nbviewer.ipython.org/urls/dl.dropbox.com/s/t8um9tdmauu8qpv/divergent_color.ipynb?dl=0

テストデータのしてはNOAA OISST version 2の海面温度アノマリを使った。データ読み込みとプロットにはIrisを使った。

Irisはイギリスのソフトのためか、日付変更線をまたぐ場合には少し癖があり、そのデモでもある。



2014年10月28日火曜日

Colors (sequential data)



最近、カラーマップに関する考察をいくつか読んだ。

いずれも"rainbow"(またの名を"jet")と呼ばれるカラーマップの弊害を述べている。

それに対する代替はいくつか提案されている。

以下のipython notebookでは、それらを試してみた。
http://nbviewer.ipython.org/urls/dl.dropbox.com/s/5t9jrhr7va3wscj/colors.ipynb?dl=0

データはGHRSST OSTIA SSTという海面温度で、2014年10月15日の117-150E, 17-40Nの範囲をIRISを使ってIPRC APDRCから読み込み、プロットさせている。

下は"cube1"と呼ばれるカラーマップでプロットした例。

ちなみに、この日の海面温度には台風19号と台風20号の通過に伴い、海水の低下した場所が見られる。


Reference
Kuroshio Oyashio Watch 2014/10/20



2014年10月26日日曜日

等値線の位置を求める



Qiu and Chen (2005)などでは、海面高度データのある等値線の位置を黒潮続流の位置とし、Decadal Variationの議論している。

等値線の位置を決めるのは、渦などの紛らわしい等値線があり、目でみていちいち確認しないで自動的に欲しい等値線の位置を決めるのは難しい。

ここでは、図作成ソフトmatplotlibのcontourルチーンから情報を取り出して、等値線の位置を決める工夫をする。

参考にしたのはstackoverflowの


ipythonノートブックは

http://nbviewer.ipython.org/urls/dl.dropbox.com/s/qt804lsufj4whyx/Kuroshio_extension_path.ipynb?dl=0

Step1 力学高度のデータをferretを使い、読み込み、図示する

データはAVISOの絶対力学高度の2009年1月21日のデータを用いる。データはAVISOからダウンロードしておく。
データの読み込みと図示には、前回紹介したferret magicを使う。



このデータでは、0.8mの等値線が黒潮続流位置としてはよさそうである。本当はheat fluxによるsteric heightの変動を考慮にいれないとならないが(Qiu and Chen, 2005)、ここではその手順は省略。
Qiu and Chen (2005)では東経141から153度のデータで議論しているので、その範囲だけ抜き出しておく。
等値線は、渦や蛇行のなどのため等値線が4つあるが、黒潮続流にあたる本来欲しい線(東西にのびる線)だけを取り出すのが課題である。


Step 2 Ferretからpythonにデータを読み込む

matlabの機能を使うために、ferretからpythonへとデータを読み込む。これもferret magicを用いる。データがちゃんと読めているかを確認もしておく。

Step 3 等値線の位置を求める

matlabのcontour routineの機能を使って、等値線の位置を求める。等値線の位置は4つ求まっている。

Step 4 等値線の位置情報から、もっとも長い等値線を選ぶ。

等値線の位置が数値的に求まったので、この中から、欲しいpathだけを選ぶ。最も長いpathが黒潮続流にあたる欲しいpathだと考えられる(渦などを避けるために、始点と終点がもっとも離れているpathという条件でも良いかもしれない。)。

まず、pathの長さを求める関数を作成する。
get_distance は2点間の距離を km で求める関数。
get_pathlength はget_distanceを用いてpath位置の情報の配列からpathの長さを求める関数。

上の4つのpathの長さを求め、path #2が最も長いことがわかる(約1432km)。
path #= 0 length= 415.785621835 km
path #= 1 length= 527.959783762 km
path #= 2 length= 1432.08536051 km
path #= 3 length= 563.215908518 km
これが、求めるpathである。


Reference:
Qiu, B., and S. Chen, 2005: Variability of the Kuroshio Extension Jet, Recirculation Gyre, and Mesoscale Eddies on Decadal Time Scales. Journal of Physical Oceanography, 35, 2090-2103. doi:10.1175/JPO2807.1





2014年9月6日土曜日

surface drifter




NOAA, Atlantic Oceanographic and Meteorological Laboratory (AOML)のGlobal Drifter Program (GDP), Drifter Data Assembly Center (DAC)には表層漂流ブイのアーカイブがある。このデータを読み込んで図示してみる。

サイトからftpでデータをあらかじめダウンロードしておく。このうち、buoydata_10001_mar14.dat (ブイ1万個目以降から2014年3月までのデータ)を例として扱う。

IPython Notebookはこちら。
http://nbviewer.ipython.org/urls/dl.dropbox.com/s/uzv1bktgazcf821/Test_buoys.ipynb?dl=0

まず、pandasでデータを読み込む。データが多量なので、読み込むまで時間がかかるかもしれない。

データ(data)の内で、一部に緯度が北緯25から45度、東経120から160度が含まれるデータを選びだす(selecteddata)。そのうちで、ユニークなid番号を持つもののは851個ある。

あらためて、もとのデータ(data)から、そのid番号を持つデータを抜き出し(wanteddata)、pickle形式で保存する。

次に、そのデータの中から、例として最初の10個だけcartopyを用いてプロットした。



参考文献




2014年8月7日木曜日

IrisとETOPO1



Irisはイギリスで開発されているpythonベースの気象・海洋データ解析パッケージである。

Irisを使って地形データETOPO1を読み込んで、プロットしたり、補間してみた。

ETOPO1は1/60°の海底地形で、NOAA NGDCのサイトからETOPO1 Bedrock(氷無しの地形)、cell-registered(グリッドセルの位置で定義される)の中から、netcdfファイル ETOPO1_Bed_c_gmt4.grdをダウンロードした。

IPython Notebookはこちらである。
http://nbviewer.ipython.org/urls/dl.dropbox.com/s/67khdbgzc2bf0sp/Read_ETOPO1.ipynb

下の図はプロットの一例。

2014年2月11日火曜日

bokehを使って、串本浦神の潮位差をプロット



串本と浦神の潮位差のデータをbokehを使ってプロットしてみる。bokehはpythonのプロットライブラリの一つで、ズームなどが可能なインタラクティブなプロットをweb上につくることができる。(bokehは日本語のボケから来てるらしい。何故そんな名前にしたんだか。)

ipython notebookはこちら。
http://nbviewer.ipython.org/urls/dl.dropbox.com/s/rry6nt3xs49o6s6/KushimotoUragami.ipynb

ズームなどができるのを確認してみてください。

データは以前のようにpandasで読み込んでいる。
daily dataの黒線で、30日の移動平均を赤線でプロットしている。ここでの30日平均は基準日を中心とした30日平均ではなく、基準日をさかのぼっての30日平均であることに注意。


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) プロット  

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


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


  
  

2013年4月2日火曜日

IPython Notebook




IPython Notebookで解析して、それをパブリックに表示するデモンストレーション。

作ったnotebookはIPytnon Notebook viewerを使って、ここで見られる。
http://nbviewer.ipython.org/urls/dl.dropbox.com/u/439394/ipyhon/seaice.ipynb

  1. データとしては、北極海海氷面積データのcsvでダウンロード
  2. pandasでデータを読み、9月の平均データを作る。
  3. IPythonのRmagicを使い、線形回帰を行いトレンドラインを引く



参考文献

2012年7月26日木曜日

NCEP Climate Forecast System Reanalysis




NCEP Climate Forecast System Reanalysisというデータがある。
http://cfs.ncep.noaa.gov/cfsr/

大気海洋モデル結合モデルに対してデータ同化が行われているのが特色だ。
分解能は従来のNCEPの再解析よりも高い。

大気: 水平分解能~38 km (T382)、 鉛直64 levels
海洋: 熱帯で0.25度、それ以外で0.5度の水平分解能、鉛直40 levels

また変数によっては1時間間隔のデータがある。
もっとも、データ同化が行われるのは6時間間隔だから、その間は予報データでうめてある。

このデータを見てみた。

UCARのサイトの
http://rda.ucar.edu/pub/cfsr.html
NCEP Climate Forecast System Reanalysis (CFSR) Selected Hourly Time-Series Products, January 1979 to December 2010http://rda.ucar.edu/datasets/ds093.1/
から、2001年の12月のSSTデータ(中身は海面下5mの温度)
ocnsst.gdas.200112.grb2
をダウンロードした。

これはgrib2形式なので、これをwgrib2でgrads形式に変換する。

g2ctl ocnsst.gdas.200112.grb2 > sst1hr.ctl
gribmap -i sst1hr.ctl

で、grads ctlファイルとindexファイル

sst1hr.ctl
ocnsst.gdas.200112.grb2.idx

ができる。水平分解能は0.5x0.5になっていた。

gradsで最初のステップをプロットすると、こんなかんじ


0N, 180Eの最初の48ステップをプロットすると
6時間ごとに値が飛んでいるように見えるのは、6時間ごとに同化(3D-VAR)で解析値に修正していることにともなうものであろう。

grads形式に変換する時に、解析値だけ取り出すには"-0"(ハイフンゼロ)をつけて

g2ctl -0 ocnsst.gdas.200112.grb2 > sst1hr.ctl
gribmap -0 -i sst1hr.ctl


この場合、0N, 180Eの最初の8ステップ(6時間ごとなので、48時間分)をプロットすると


2012年7月24日火曜日

浦神と串本の日平均潮位差をpandasで



以前書いた、pandasでの時系列処理の続き。バージョンアップ(これを書いてる時点でversion 0.8.1)により、さらに便利になった。

浦神と串本の日平均潮位差をプロットしてみる。前回のようにwebから直接読むこともできるが、今回はhttp://www.data.kishou.go.jp/db/kobe/kuroshio/chouisa/chouisa.datからchouisa.datをダウンロードしてそれを読むことにする。

下がプログラム。
read_psvでデータを読んでいる。
前回は日付とデータの間にあるスペースをスマートに処理できなかったが、sep='\s*' (任意の数のスペース)を使えばよかったらしい。
column=0(右端)をindexとして用い(index_col=0)、日付データとして解釈する(parse_dates=Trule)。
”-”を欠損値と解釈する。

version 0.8以降、月平均を計算するのが簡単になり、data.resample("M",how='mean')で良い。


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# read data
data=pd.read_csv("chouisa.dat",sep='\s*',skiprows=1,header=None,index_col=0,parse_dates=True,names=("date","chouisa"),na_values="-")

#monthly value
data2=data.resample("M",how='mean')

#plot
plt.subplot(111)
data["chouisa"].plot(style='b-',label="Daily")
data2["chouisa"].plot(style='r-',label="Monthly",linewidth=2)
plt.legend(loc='best')
plt.savefig("choisa.png")
plt.show()



2012年3月16日金曜日

黒潮の流路をpandasで



以前、気象庁黒潮の流軸の緯度のデータをネットから読み込んでプロットしてみた。

同じことをpandas (Python Data Analysis Library)で行ってみる。

import numpy as np
from  pandas import *
import matplotlib.pyplot as plt
ds = np.DataSource(None)
f=ds.open('http://www.data.kishou.go.jp/kaiyou/shindan/b_2/kuroshio_stream/kuro_slat.txt')
data=read_csv(f,sep=" ",names=("space","val"),parse_dates=True)
f.close()
data["val"].plot()
plt.xlabel("YEAR")
plt.ylabel("Kurosho latitude")
plt.savefig("pandas_example.png")

(注記) 上のデータ読み込みでは、元データがスペースを使っている関係で、"space"という余計なデータ列(column)を作ってしまう。もっとスマートな方法があるかもしれない。
(追記:2012/7/23) 後日、改良版を書いた。

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年3月5日土曜日

気象庁MGDSST



気象庁の海面水温データ(0.25x0.25度、daily)であるMGDSSTをウェブからダンロードしてから、データを読み込むまでのモジュールをつくる。MGDSSTはNEAR-GOOSのサイトから入手が可能である。
idとpasswordが必要なので、あらかじめ登録しておく。

以下がスクリプト
usrname="xxxxx"
password="*****"
のところを自分のidとpasswordで置き換える。

import numpy as np 
import os

def downloadfile(infile="remotefile",outfile="localfile"):
    """
    download file from NEAR-GOOS data site with id and password
    input
       infile: remote file on the web
       outfile: local file
    
    set password and id below
    """
    import urllib2
    host="goos.kishou.go.jp:80"
    realm="NEAR-GOOS"
    usrname="xxxxx"
    password="*****"
    auth_handler = urllib2.HTTPBasicAuthHandler() 
    auth_handler.add_password(realm, host, usrname, password) 
    opener = urllib2.build_opener(auth_handler) 
    urllib2.install_opener(opener) 
    f=urllib2.urlopen(infile)
    open(outfile, 'w').write(f.read())

#----------------------------------------------------------
def readMGDSST(dir=".",year=2010,month=1,day=1,lonrange=(0,360),latrange=(-90,90)):
    """
    load MGDSST data from NEAR-GOOSE site
    read data with fortran (f2py)
    select region specified by lonrange and latrange 

    Usage:
    lon,lat,sst= readMGDSST(dir=".",year=2010,month=1,day=1,lonrange=(0,360),latrange=(-90,90)

    Input 
       dir: directory for data download
       year,month,day:  date of the data 
       lonrange,latrange = longitude and latitude range for data
    output
       lon, lat: longitude, latitude
       sst:  sst data
"""

# date
    import datetime
    t=datetime.datetime(year,month,day)
    syear=t.strftime("%Y")
    smon=t.strftime("%b")
    sday=t.strftime("%d")
# filename
    dataname="mgdsst."+smon+sday
    filename=dir+"/"+dataname+"."+syear
    filenamegz=filename+".gz"
    print filename
    urlname="http://goos.kishou.go.jp/rrtdb/usr/pub/JMA/mgdsst/"+syear+"/"+dataname+".gz"

# file exist?
    if not os.path.exists(filename):
        if not os.path.exists(filenamegz):
           downloadfile(infile=urlname,outfile=filenamegz)
        os.system("gunzip %(filenamegz)s" %locals())         

# temp.bin is used for temporary file
    if os.path.lexists("temp.bin"):
        raise IOError("temporary file temp.bin somehow exist! Remove it!") 
    else:
        os.system("ln -s %(filename)s temp.bin" %locals())

# data read through fortran (f2py)
    from read_sst import read_sst
    im=1440
    jm=720
    sst=np.zeros([jm,im])

    sst,ierr=read_sst()
    assert ierr==0, "data error in fortran"

    lon=0.125+0.25*np.arange(im)
    lat=-89.875+0.25*np.arange(jm)

    os.system("rm temp.bin")

# range selection
    xrange=np.logical_and(lon>=lonrange[0],lon<=lonrange[1])
    yrange=np.logical_and(lat>=latrange[0],lat<=latrange[1])
    sst=(sst[yrange,:])[:,xrange] 

    return lon[xrange],lat[yrange], sst

#-----------------------------------------------------------------------
if __name__ == '__main__':
    import cdms2,MV2,vcs #cdat

    # read data
    lon,lat,sst=readMGDSST(dir="DATA",year=2011,month=1,day=1,lonrange=(0,360),latrange=(-90,90))

    # hearafter plot with cdat
    # First let's create a variable
    var = MV2.masked_array(sst,mask=(sst<-990.),id="SST")

    # Now create the axis
    lons=cdms2.createAxis(lon)
    lats=cdms2.createAxis(lat)

    # And decorate it
    lons.id = 'longitude'
    lats.id = 'latitude'
    lons.units = 'degrees_east'
    lats.units = 'degrees_north'

    # Just to make sure we will describe this axis as a longitude one
    lons.designateLongitude()
    lats.designateLatitude()

    # Now let's apply these to the variable
    var.setAxisList((lats,lons))

    #var.info() to see info

    #plot 
    v = vcs.init()
    v.plot(var)
    v.png("MGDSST.png")
    del v

上のサンプルメインプログラムでは、2011年1月1日のデータをディレクトリ"DATA"にダウンロードし、経度0から360度、緯度-90度から90度の範囲で読み込んでいる。
その上で、cdatを用いて可視化した。
結果は以下の図。

ダウンロードしたバイナリファイルを読むのにfortranのプログラムをモジュールとしてつかう。清水慎吾さんのデータを読むサンプルプログラムを参考に、以下のようなfortranサブルーチンを作った(配列はpython風に緯度と経度を入れ替えている。欠損値は-999.)。
このプログラムをf2pyを使って以下のようにコンパイルすればpythonのモジュールとして使用が可能になる(上のプログラムのread_sst)。
f2py --f90exec=gfortran -c -m read_sst read_sst.f90
(ここではgfortranを使っている。)

read_sst.f90
subroutine READ_SST(sst,ierr)
  implicit none
  integer   :: year,mon,day
  integer   :: i,j,jj
  
  integer,parameter :: im=1440
  integer,parameter :: jm=720
! 
  real,intent(out):: sst(jm,im)
  integer, intent(out):: ierr
!
  integer   :: isst(im,jm),ist
  real      :: undef = -999.
  
  open(55,file="temp.bin",status='old',form='formatted',iostat=ierr,err=999)
  read(55,*) year,mon,day
  write(6,*) year,mon,day

  do j=1,jm
     read(55,10,iostat=ierr,err=999) (isst(i,j),i=1,im)
  enddo
  close(55)
10 format(1440i3)

  do j=1,jm
     do i=1,im
        jj = jm -j +1
        ist = isst(i,jj)
        if(ist .eq. 888 .or. ist.eq.999) then
           sst(j,i) = undef
        else
           sst(j,i) = real(ist)*0.1 
        endif        
     enddo
  enddo
  return 
999 print *, "Read Error!"

end subroutine READ_SST

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"




2010年12月17日金曜日

気象庁全国合成レーダー降雨



気象庁の全国合成レーダー降雨データがこちらで配布されている。
データは10分ごとにある。
データはtarでアーカイブされており、その中に含まれるデータはgrib2形式である。
清水慎吾さんがこちらで、データをgrads形式に変換するプログラムを公開している(全国合成気象庁レーダ雨量,GRIB2形式)。

以下のプログラムはファイルをネットから読み込んで、清水さんのツールでgrads形式に変換するpythonスクリプトである。

RadarToGradsはファイル(tarファイル)をネットから呼んで、tarファイルから降雨データのバイナリファイル(grib2)を取り出し、gradsファイルを作る。
grib2からgradsへのファイル変換は清水さんのjmaradar2binで行っている。gradsコントロールファイル("view_radar.ctl")が自動的にできるようにmain.cで"gradsout=1"としている。

PlotByGradsは作ったgradsデータを使って、gradsでプロットしている。gradsを操作するのに、pythonインターフェイスを使っている。

メインでは、これらを使って、2010年10月20日午前8時00分世界標準時(日本時間午後5時)の降水を東経125-135度北緯24-35度でgradsデータに変換して、それをプロットしている。これは奄美大島で豪雨が発生したころにあたる。

import_jmaradar.py
def RadarToGrads(dir=".",gradsbinname="temp.bin",year=2010,mon=1,day=1,hour=0,mi
n=0,slon=118.,elon=150.,slat=20.,elat=48.):
    """
   Import JMA rain radar data (every 10min) from http://database.rish.kyoto-u.ac
.jp/arch/jmadata/synthetic-original.html
   Then convert data to grads file using tool by Dr. Shingo Shimizu (http://shim
izus.hustle.ne.jp/wiki/wiki.cgi?page=%A5%EC%A1%BC%A5%C0%B4%D8%CF%A2%A5%E1%A5%E2)
 

   usage:
       RadarToGrads(dir=".",gradsbinname="temp.bin",year=2010,mon=1,day=1,hour=0
,min=0,slon=118.,elon=150.,slat=20.,elat=48.):
     
   input
      dir: directory to import tar file
      gradsbinname: file name for grads binary
      year, mon, day, hour, min  : time for data (every 10 min) in UTC
      slon,elon  Western,East bounday
      slat,elat  South,North bounday


   output files
      grads binary: gradsbinname
      grads control: view_radar.ctl        
         
    """


    import os
    import tarfile
    import urllib

    # filenames
    syear="%04d" % year
    smon="%02d" % mon
    sday="%02d" % day
    shour="%02d" % hour
    smin="%02d" % min
    date=syear+smon+sday+shour+smin
    tarname="Z__C_RJTD_%(date)s00_RDR_JMAGPV__grib2.tar" %locals()
    urldir="http://database.rish.kyoto-u.ac.jp/arch/jmadata/data/jma-radar/synth
etic/original/%(syear)s/%(smon)s/%(sday)s/" %locals()
    filename="Z__C_RJTD_%(date)s00_RDR_JMAGPV_Ggis1km_Prr10lv_ANAL_grib2.bin" %l
ocals()

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

    # extract radar precipitation file
    tarfile.open(dir+"/"+tarname, 'r').extract(filename)

    # convert to grads file
    os.system("jmaradar2bin %(filename)s %(gradsbinname)s %(slon)s %(elon)s %(sl
at)s %(elat)s" %locals())
    os.system("rm %(filename)s" %locals())

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

def PlotByGrads(pngname):
    """
      plot converted JMA radar rain data
    """
    from grads.galab import GaLab  # for python interface for grads
    ga = GaLab(Bin='grads',Window=False,Echo=False,Verb=0,Port=False)
    ga.open("view_radar.ctl")
    script="""
    set grads off
    set mpdset hires
    set gxout shaded
    set clevs 0 1 5 10 20 30 50 80
    d rr
    cbarn
    printim %(pngname)s white
"""
    ga(script %locals())


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

if __name__ == '__main__':

# radar file to grads 
    RadarToGrads(dir="DATA",gradsbinname="jmaradar.bin",year=2010,mon=10,day=20,
hour=8,min=00,slon=125.,elon=135.,slat=24.,elat=35.)

# plot by grads
    PlotByGrads("jmaradar.png")


2010年10月1日金曜日

富士山の初冠雪日(1) データ取得



富士山 一気に冬の顔
初冠雪、平年より6日早く
山頂から8合目付近にかけてうっすらと雪をかぶった富士山=富士吉田市上吉田 甲府地方気象台は25日、富士山が初冠雪したと発表した。平年より6日、昨年より12日早い。独自に観測している富士吉田市も同日、昨年より15日早く「富士山初雪化粧」を宣言した。山梨県内は22日に甲府など3地点で最高気温が35度以上の猛暑日を記録したばかり。富士山は早くも冬に向けての“衣替え”が始まった。
2010年09月26日 山梨日日新聞 web魚拓

甲府気象台のwebページ表から、富士山初冠雪日を取得するプログラムを作る。
以下がプログラム。
関数 read_FirstSnowFuji()が初冠雪日を取得するモジュールで、年、月、日をnumpyの配列として返す。HTMLから表を読むのにtable parserを用いている。
メインプログラムでは、日付をscikits.timeseriesで年初からの日にち(1月1日を1とする)に変換し、グラフにしている。平均値を黒い実線で、平均値から標準偏差(約14日)の2倍離れた値に黒点線を引いた。ばらつきがかなり大きい印象だ。今年は少しだけ平年より早い。

read_FirstSnowFuji.py
import numpy as np
# table parser from http://simbot.wordpress.com/2006/05/17/html-table-parser-using-python/
from table_parser import *

def read_FirstSnowFuji():
    import urllib
    """
   read first snow cover day of the FUJI mountain from KOFU local meteorological observatory
   usage:
      year,month,day=read_FirstSnowFuji()
   input
      none
   output
      year,month,day:  first snow cover day (numpy array)
   
   """

    f = urllib.urlopen('http://www.jma-net.go.jp/kofu/menu/siryo_hatsukansetsu.dat.html')
    p = TableParser()
    p.feed(f.read())
    f.close()
    data=p.doc # Get to the data

    #get 
    year=[[],[],[]] # 3 column
    month=[[],[],[]] # 3 column
    day=[[],[],[]] # 3 column
    for d in data[0][1:]:
        for n,c in enumerate([0,4,8]):
            if not d[c]=="":
                year[n].append(int(d[c]))
                mi,di=d[c+1].split("/")
                month[n].append(int(mi))
                day[n].append(int(di))
    # to numpy array
    ayear=np.array([],dtype="i4")
    amonth=np.array([],dtype="i4")
    aday=np.array([],dtype="i4")
    for n in range(3):
        ayear=np.append(ayear,year[n])
        amonth=np.append(amonth,month[n])
        aday=np.append(aday,day[n])

    return ayear,amonth,aday

############################################
if __name__ == '__main__':
    import matplotlib.pyplot as plt
    import scikits.timeseries as ts

    ayear,amonth,aday= read_FirstSnowFuji()

    days=np.array([],dtype="i4")
    for  n in range(ayear.size):
        td=ts.Date("D",year=ayear[n],month=amonth[n],day=aday[n])
        days=np.append(days,td.day_of_year)

    #plot
    plt.plot(ayear,days,"b-")
    mean=days.mean()
    stdp=days.mean()+2*days.std()
    stdm=days.mean()-2*days.std()
    plt.plot([ayear[0],ayear[-1]],[mean,mean],"k-")
    plt.plot([ayear[0],ayear[-1]],[stdp,stdp],"k--")
    plt.plot([ayear[0],ayear[-1]],[stdm,stdm],"k--")
    plt.xlim(ayear[0],ayear[-1])
    plt.xlabel("year")
    plt.ylabel("day of year")
    plt.savefig("FujiFirstSnow.png")
    plt.show()

2010年9月25日土曜日

TRMM 3B42 降水データ

人工衛星TRMMの降水データ3B42をプロットする。
この降水データは水平分解能0.25度で3時間ごとにデータがある。
このデータをNASA MiradorからOPeNDAPを通して入手する。
以下の例は7月27日0時世界標準時(日本標準時9時)の日本付近のデータをプロットする例である。この日は東シナ海に熱帯低気圧が存在し、それによる雨が見える。
OPeNDAPからはPyNIOを使ってデータを入手する。
関数name_makerはファイルのあるURLはこういう規則だろうと推測して作ったものである。間違いかもしれないので確認すること。

import Nio
import numpy as np

def read_TRMM_3B42(date,lon1,lon2,lat1,lat2):
    """
   read TRMM 3B42 3 hourly rainfall  from NASA Mirador

   usage:
      lon,lat,sst=read__TRMM_3B42(date,lon1,lon2,lat1,lat2)
     
   input
     
      date (year,month,day,hour) 
      lon1,lon2  Western,East bounday
      lat1,lat2  South,West bounday
   output
      lon longitude
      lat latitude
      rainfall data (mm/hour)         
    """
#check
    assert date[3] % 3 ==0, "Error, hour must be multiple of 3!!!"
# open OPENDAP
    fname=name_maker(date[0],date[1],date[2],date[3])
    f = Nio.open_file(fname)
## variable name check
    #variables = f.variables.keys()
    #print f
    #print "variables",variables

# read data
    temp=f.variables["DATA_GRANULE.PlanetaryGrid.precipitation"]

#grid
    # grid
    lon=-179.875+np.arange(temp.shape[1])*0.25
    lat=-49.875 +np.arange(temp.shape[2])*0.25
    # selection
    xrange=np.where(np.logical_and(lon>=lon1,lon<=lon2))
    yrange=np.where(np.logical_and(lat>=lat1,lat<=lat2))
    
#precipitation
    x=xrange[0]
    y=yrange[0]
    precip=(temp[0,x[0]:x[-1]+1,y[0]:y[-1]+1].T).reshape((len(y),len(x)))

# closing 
    f.close()
    return lon[xrange],lat[yrange],precip

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

def name_maker(year,month,day,hour):
    import scikits.timeseries as ts
    #
    t=ts.Date('H', year=year,month=month,day=day,hour=hour)
    if t.hour==0:
        tc=t-1
    else:
        tc=t
    cyear = "%04d"  % tc.year
    cyear2= "%02d"  % (t.year-2000)
    cmonth2= "%02d" % t.month
    cday2=   "%02d" % t.day
    shour = str(t.hour)
    yd3= "%03d" % tc.day_of_year
    #
    fname="http://disc2.nascom.nasa.gov/opendap/TRMM_L3//TRMM_3B42//%(cyear)s/%(yd3)s/3B42.%(cyear2)s%(cmonth2)s%(cday2)s.%(shour)s.6A.HDF.Z" %locals()
    return fname

############################################
if __name__ == '__main__':
    import matplotlib.pyplot as plt
    from mpl_toolkits.basemap import Basemap
    # example plot

# range
    lon1=120.
    lon2=145.
    lat1=20.
    lat2=40.

#date
    year=2009
    month=7
    day=27
    hour=0 
    lon,lat,precip=read_TRMM_3B42(date=(year,month,day,hour),lon1=lon1,lon2=lon2,lat1=lat1,lat2=lat2)

   #plot
    vmax=int(precip.max())
    vmin=int(precip.min())
    fig=plt.figure()
    ax = fig.add_axes([0.1,0.1,0.8,0.8])
    map = Basemap(projection='merc',llcrnrlat=lat1,urcrnrlat=lat2,\
                      llcrnrlon=lon1,urcrnrlon=lon2,resolution='i')
    lons,lats=np.meshgrid(lon[:],lat[:])
    x,y=map(lons,lats)
    map.drawcoastlines()
    map.drawmapboundary()
    map.pcolor(x,y,precip,vmin=vmin,vmax=vmax,cmap=plt.cm.Blues)
    ti=str(year)+"/"+str(month)+"/"+str(day)+":"+str(hour)+"Z"
    plt.title(ti)
# colorbar
    pos = ax.get_position()
    l, b, w, h = pos.bounds
    cax = plt.axes([l+w+0.02, b, 0.03, h]) # setup colorbar axes.
    plt.colorbar(cax=cax) # draw colorbar
    plt.savefig("TRMM_3B42.png")
    plt.show()


参考
NASA Giovanniのサイト
http://disc2.nascom.nasa.gov/Giovanni/tovas/TRMM_V6.3B42.2.shtml

TRMM 3B42 readme
ftp://meso-a.gsfc.nasa.gov/pub/trmmdocs/3B42_3B43_doc.pdf

2010年9月4日土曜日

EORC MODIS SST



JAXA EORC提供のMODIS SSTをプロットするスクリプトを作成した。
データのバイナリはEORCに提供していただいた。
下の例ではは2010年8月2日の領域6のデータから紀伊半島付近をプロットしている。 A2GL11008020431OD1_OSTAQ_01000_01000_sst_06
ファイルのフォーマットの情報はここ。


import numpy as np

def read_MODIS_EORC(file,lon1,lon2,lat1,lat2):
    """
   read MODIS_SST from EORC

   usage:
      lon,lat,sst=read_MODIS_EORC(file,lon1,lon2,lat1,lat2)
     
   input
     
      file filename 
      lon1,lon2  Western,East bounday
      lat1,lat2  South,West bounday
   output
      lon longitude
      lat latitude
      SST sst data (masked array) in C          
    """
    # open file
    f=open(file, 'r')
    # read header
    pixel=f.read(6); print "pixel=",pixel
    line=f.read(6); print "line=",line
    nwlon=f.read(8); print "NW lon.=",nwlon
    nwlat=f.read(8); print "NW lat.=",nwlat
    res=f.read(8);   print "resolution=",res
    slope=f.read(9);   print "slope=",slope
    offset=f.read(9);  print "ofset=",offset
    dummy=f.read(1)
    parameter=f.read(8); print "parameter name=",parameter
    dummy=f.read(1)
    filename=f.read(45); print "file name=",filename
    f.close()
    # read data
    f=open(file,'r')
    f.seek(int(pixel)*2) #skip header
    data=np.fromfile(f,dtype=">u2")
    data=data.reshape((int(line),int(pixel)))
    msk=np.logical_or(data==0,data>=65534) # 0 cloud, 65534 out of obs., 65535 land 
    data=np.ma.masked_array(data[::-1],mask=msk[::-1,:])
    data=data*float(slope)+float(offset)-273.15 # to degree C
    f.close()
    # grid
    lon=float(nwlon)+np.arange(int(pixel))*float(res)
    lat=float(nwlat)-np.arange(int(line))*float(res)
    lat=lat[::-1]
    # selection
    xrange=np.logical_and(lon>=lon1,lon<=lon2)
    yrange=np.logical_and(lat>=lat1,lat<=lat2)
    sst=(data[yrange,:])[:,xrange] 

    return lon[xrange],lat[yrange], sst

############################################
if __name__ == '__main__':
    import matplotlib.pyplot as plt
    from mpl_toolkits.basemap import Basemap
    # example plot

    #read data
    filename="A2GL11008020431OD1_OSTAQ_01000_01000_sst_06"
    lon1=135.
    lon2=138.
    lat1=32.
    lat2=35.
    lon,lat,sst=read_MODIS_EORC(filename,lon1,lon2,lat1,lat2)

    #plot
    tmax=int(sst.max())
    tmin=int(sst.min())
    fig=plt.figure()
    ax = fig.add_axes([0.1,0.1,0.8,0.8])
    map = Basemap(projection='merc',llcrnrlat=lat1,urcrnrlat=lat2,\
                      llcrnrlon=lon1,urcrnrlon=lon2,resolution='i')
    lons,lats=np.meshgrid(lon[:],lat[:])
    x,y=map(lons,lats)
    map.drawcoastlines()
    map.drawmapboundary()
    map.pcolor(x,y,sst,vmin=tmin,vmax=tmax)
# colorbar
    pos = ax.get_position()
    l, b, w, h = pos.bounds
    cax = plt.axes([l+w+0.02, b, 0.03, h]) # setup colorbar axes.
    plt.colorbar(cax=cax) # draw colorbar
    plt.savefig("MODIS_EORC_SST.png")
    plt.show()



謝辞
ここで用いたSSTバイナリは宇宙航空研究開発機構(JAXA)地球観測研究センター(EORC)から提供されたものである。ここに感謝する。

関連ポスト
MODIS aqua Global Level 3 Mapped Mid-IR SST (4km)
http://oceansciencehack.blogspot.com/2010/09/modis-aqua-global-level-3-mapped-mid-ir.html

参考
MODIS EORC SST FAQ
http://kuroshio.eorc.jaxa.jp/ADEOS/mod_nrt_new/html/05_faq.html
JAXA MODISページ
http://www.eorc.jaxa.jp/hatoyama/satellite/sendata/modis_j.html
MODIS wikipedia
http://ja.wikipedia.org/wiki/MODIS

2010年9月3日金曜日

CEReS NOAA/AVHRR SST



CEReSで配布しているNOAA AVHRR SSTをプロットしてみた。

FTPサイトからデータをダウンロードして、解凍する。
ここでは n1810080316.sst.giを利用する。
(NOAA 18 ,2010年,8月3日,16世界標準時)
以下がスクリプト。
このデータには雲や陸地のマスクはないようだ。
前回はPyNGLでプロットしたが、今回はmatplotlib basemap toolkitを利用した。
matlabのpplot関数に対応する関数を使いたかったからだ(PyNGLにはあるのかな?)。

import numpy as np
import matplotlib.pyplot as plt

def read_CEReS_SST(dir,file,lon1,lon2,lat1,lat2):
    """
   read CERes SST
   usage:
      lon,lat,sst=read_CEReS_SST(dir,file,lon1,lon2,lat1,lat2)     
   input
      dir working dir
      file filename 
           gzipped file is fine.
           URL also works
      lon1,lon2  Western,East bounday
      lat1,lat2  South,West bounday
   output
      lon longitude
      lat latitude
      SST sst data (masked array) in C          
    """
    # read data
    ds=np.DataSource(dir)
    f=ds.open(file, 'r')
    f.seek(80) # skip header
    ssttemp=np.frombuffer(f.read(),dtype=">i2",count=6378*5562)
    f.close()
    # as masked array
    sst=ssttemp.reshape((5562,6378))*0.1
    sst=np.ma.masked_array(sst[::-1,:],mask=(sst[::-1,:]==0  ))

    # grid
    lon=100.+np.arange(6378)*0.01097869
    lat=9.97971+np.arange(5562)*0.00899322
    # selection
    xrange=np.logical_and(lon>=lon1,lon<=lon2)
    yrange=np.logical_and(lat>=lat1,lat<=lat2)
    sst=(sst[yrange,:])[:,xrange]-273.15 # Kelvin to C

    return lon[xrange],lat[yrange], sst
############################################
if __name__ == '__main__':
    from mpl_toolkits.basemap import Basemap
    # example plot

    #read data
    filename="n1810080316.sst.gi"
    lon1=130.
    lon2=140.
    lat1=30.
    lat2=36.
    lon,lat,sst=read_CEReS_SST(".",filename,lon1,lon2,lat1,lat2)

    #plot
    tmax=30.
    tmin=20.
    fig=plt.figure()
    ax = fig.add_axes([0.1,0.1,0.8,0.8])
    map = Basemap(projection='merc',llcrnrlat=lat1,urcrnrlat=lat2,\
                      llcrnrlon=lon1,urcrnrlon=lon2,resolution='i')
    lons,lats=np.meshgrid(lon[:],lat[:])
    x,y=map(lons,lats)
    map.drawcoastlines()
    map.drawmapboundary()
    map.pcolor(x,y,sst,vmin=tmin,vmax=tmax)
 # colorbar
    pos = ax.get_position()
    l, b, w, h = pos.bounds
    cax = plt.axes([l+w+0.02, b, 0.03, h]) # setup colorbar axes.
    plt.colorbar(cax=cax) # draw colorbar
    plt.savefig("CEReS_SST.png")
    plt.show()