NetCDFの読み込み編
importするモジュール
import netCDF4
と先頭に記載する
コマンドの引数からデータを読むために
import sys
を先頭に記載。
if len(sys.argv) < 5: print ("ARGV error: infile var t k") exit(1)
などとして、引数の数が5個以下なら、入力ファイル名や変数名、時間断面、層番号を入力させる。
infile = sys.argv[1] var = sys.argv[2] tt = int(sys.argv[3]) kk = int(sys.argv[4]) print ("infile=", infile) print ("var=", var) print ("time=",tt) print ("layer=",kk)
として、引数をコマンドラインから取れる。そして、printで確認
読み込み用としてopen
nc = netCDF4.Dataset(infile,'r')
netcdfの最上位のクラスの中身を確認する
import netCDF4 import inspect
とした上で、
nc = netCDF4.Dataset(infile,"r") for x in inspect.getmembers(nc): print (x)
とすると、
nc.(個々に関数や変数を設定でき、いろいろな情報が得られる)
の全種類を閲覧することができる。これでnetcdfのデータの読み方が分かるはずです。
以下、主要な種類を上げておきます。
種類 | 意味 |
---|---|
dimensions | 次元に関する情報 |
variable | 変数に関する情報 |
close | 関数であり、netcdfを閉じる |
試しに、
nc = netCDF4.Dataset(infile,"r") print (nc.dimensions) print (nc.variable) print (nc.ndims)
とすることで、情報を得られることを確かめてください。
有る変数の情報を取得する
上記のクラスの中身の見方が分かると、マニュアルが無くても、pythonで
netcdfのデータの読み方がほぼ分かることになる。
netcdfのクラスは階層上になっており、nc.variable['SU']のように変数SUの情報だけを取得できるようになる。
例えば、変数SUが何次元で、どの次元を持つかを調べたいときには、
print (nc.variable['SU'].ndim) print (nc.variable['SU'].dimensions)
とすれば、いい。
nc.variable[変数名].知りたい情報
のようになっている。知りたい情報をどうやって指定したらいいか分からない場合は、
a = nc.variable['SU'] for x in inspect.getmembers(a): print (x)
とやれば、知りたい情報の一覧が表示されるので、その情報を.の後に付ければいい。
様々なサンプル集
ある変数Xが存在するかの確認
a = nc.variable if "X" in a: print ("X is included") else : print ("X is not included")
有る変数Xの次元数と次元の種類を知りたい
ndim = nc.variable['X'].ndim dims = nc.variable["X"].dimensions print ("ndims=",ndim) print ("dims=",dims)
有る次元変数Yが存在するかの確認
a = nc.dimension if "Y" in a
LAT-LON座標系だと確定している場合の格子数を取得したい
lon = nc.dimension['LON'] XNUM = len(lon) lat = nc.dimension['LAT'] YNUM = len(lat)
変数Uが4次元(TIME,LEV,LAT,LON)で格納されており、ある時刻tの3次元分布を取得したい
U3D = nc.variable['U'][t][:][:][:]
変数Uが4次元(TIME,LEV,LAT,LON)で格納されており、ある時刻tと層番号kの2次元分布を取得したい
U2D = nc.variable['U'][t][k][:][:]
2バイトで圧縮されているデータを4バイトfloatにして取得したい
TMP = nc.variable['U'][t][k][:][:] add_offset = nc.variable['U'].add_offset scale_factor = nc.variable['U'].scale_factor U2D = TMP * scale_factor + add_offset
変数Uが2バイト圧縮されているかどうかを調べたい
dtype = nc.variable['U'].dtype if dtype == 'int16': print ("short compress") elif dtype == 'float32': print ("float: no compress")
そもそも、pythonでnetCDFを読むと自動的にfloatになっている!
どうやらユーザーはadd_offsetやscale_factor,missing_valueなどは読まなくていいようです。
自動的にshortから正しい実数に変換され、missing_valueの場所には、その配列の要素は、未定義となるようです。
サンプルプログラム
main.pyとread_NC.pyの2つのファイルに分けて、netCDFを読み込むプログラムをすべて
read_NC.pyにまとめた。二つのファイルは、同じディレクトリにあることを想定しています。
main.py(381)
read_NC.py(381)
ソースコード
main.py
import sys from read_NC import read_NC def main(): if len(sys.argv) < 3: print ("ARGV error: infile var [t] [k]") exit(1) infile = sys.argv[1] varname = sys.argv[2] if len(sys.argv) > 4: t = sys.argv[3] else : t = 0 if len(sys.argv) > 5: k = sys.argv[4] else : k = 0 DATA = read_NC(infile,varname,t,k) print (DATA) #################################### if __name__ == "__main__": main()
read_NC.py
import netCDF4 def check_NC_type(infile,varname): nc = netCDF4.Dataset(infile,'r') if not varname in nc.variables: print ("not found ", varname) exit(1) dim = nc.variables[varname].dimensions nc.close() dim_check = [0,0,0,0] if "TIME" in dim: dim_check[0] = 1 else: dim_check[0] = 0 if "LEV" in dim or "ALT" in dim: dim_check[1] = 1 else: dim_check[1] = 0 if "LAT" in dim: dim_check[2] = 1 else: dim_check[2] = 0 if "LON" in dim: dim_check[3] = 1 else: dim_check[3] = 0 return dim_check def read_NC_T2D(infile,varname,t): nc = netCDF4.Dataset(infile,'r') if not varname in nc.variables: print ("not found ", varname) exit(1) DATA2D = nc.variables[varname][t][:][:] nc.close() return DATA2D def read_NC_T3D(infile,varname,t,k): nc = netCDF4.Dataset(infile,'r') if not varname in nc.variables: print ("not found ", varname) exit(1) DATA2D = nc.variables[varname][t][k][:][:] nc.close() return DATA2D def read_NC_2D(infile,varname): nc = netCDF4.Dataset(infile,'r') if not varname in nc.variables: print ("not found ", varname) exit(1) DATA2D = nc.variables[varname][:][:] nc.close() return DATA2D def read_NC_1D(infile,varname): nc = netCDF4.Dataset(infile,'r') if not varname in nc.variables: print ("not found ", varname) exit(1) DATA1D = nc.variables[varname][:] nc.close() return DATA1D def read_NC(infile, varname,t=0,k=0): type = check_NC_type(infile,varname) ndim = sum(type) if type == [1,0,1,1] : print ("2D evolution") DATA = read_NC_T2D(infile,varname,t) elif type == [1,1,1,1] : print ("3D evolution") DATA = read_NC_T3D(infile,varname,t,k) elif type == [0,1,1,1] : print ("3D static") DATA = read_NC_T2D(infile,varname,k) elif type == [0,0,1,1] : print ("2D static") DATA = read_NC_2D(infile,varname) elif ndim == 1: print ("1dimensional") DATA = read_NC_1D(infile,varname) return DATA
解説
main.py は引数として、入力ファイル、変数、(時間指定)(層番号指定)
として、最低でも2つの引数を、必要であれば、時間と高さの指定を行い、4つまでの引数を受け付けます。
main.py は、read_NC.pyを呼び出して、DATAという2次元配列を取得することを目的とします。
この2次元配列は、X-Y平面を想定しています。抜き出したい変数がどんな次元でも抜き出せるように
read_NC.pyは工夫しています。ただし、次元変数としては、TIME,ALTもしくはLEV, LAT, LONという
次元変数名であることを想定しています。この次元変数とマッチするかどうかを確かめて、read_NC.pyの
中で、呼び出す関数を選択しています。read_NC.py の引数は、入力ファイルと変数名を
必須として、時間と層番号については任意選択できるようにしています。引数で
t=0,k=0と設定しているのは、引数設定が無い場合には、デフォルトで0が割当てられる
デフォルト引数というものを設定しています。
main.pyの一番下にある文は、端末から入力された場合には__main__という名前空間が
割り当てられるので、その場合、mainを実施するという意味である。
各サブルーチンもこうした__main__という名前空間を持たせた場合の実験ができる。