最終更新: keisuketsushima 2011年11月22日(火) 17:04:18履歴
自動的に規約を解釈するNetCDFの読み込み・書き込みヘルパーです。
同様のことはArrayかNArrayを使って次のようにすることができる。
この部分集合は最後の次元は保持するが、(0..0, 1..1,..)のRangeオブジェクトによってその長さは1になることに注意する。これにより、その部分集合は元々の階数と同じ階数を持っている。出力されるGPhysオブジェクトは、ブロックの返り値で与えられるように、その次元を保持しなければならない。理由は、その次元(長さが1)がファイルに書き込まれるときに元々の次元と置き換えられるからである。よって、以下はエラーを起こす(例外を発生させる)。
- files (String, NetCDF, NArray, or Regexp): ファイル指定子。(パスを含む)Stringで1つのNetCDFファイルを指定する。複数のファイルはStringのNArrayかNetCDFかパスにマッチするRegexpによって指定できる。その場合、データと軸はVArrayCompositeで表される
- varname (String): 変数名
- 1つのファイルから
file = NetCDF.open('hogehoge.nc') gphys = GPhys::NetCDF_IO(file, 'temp') file = NetCDF.open('hogehoge.nc', 'a') # writable gphys = GPhys::NetCDF_IO(file, 'temp')
- 1つのファイルから
gphys = GPhys::NetCDF_IO('hogehoge.nc', 'temp') gphys = GPhys::NetCDF_IO('/data/netcdf/hogehoge.nc', 'temp')ファイルのパスを指定する際にStringを用いた場合、そのファイルは読み込み専用として開かれる
- 複数のファイルに分割されているデータを使う場合。例えば、現在のディレクトリにhoge_yr2000.nc、hoge_yr2001.nc、hoge_yr2002.ncが存在しているとすると、それらは次のように正規表現を使うことで使用できる
gphys = GPhys::NetCDF_IO(/hoge_yr(\d\d\d\d).nc/, 'temp')ここで、\d\d\d\dを囲んでいる括弧は必要なものである。
同様のことはArrayかNArrayを使って次のようにすることができる。
files = ['hoge_yr2000.nc', 'hoge_yr2001.nc', 'hoge_yr2002.nc'] gphys = GPhys::NetCDF_IO(files, 'temp') files = NArray['hoge_yr2000.nc', 'hoge_yr2001.nc', 'hoge_yr2002.nc'] gphys = GPhys::NetCDF_IO(files, 'temp')
- 上記と同じだが、完全パスを使う場合
gphys = GPhys::NetCDF_IO(/\/data\/nc\/hoge_yr(\d\d\d\d).nc/, 'temp')ここで、ディレクトリセパレータ'/'は'\/'とエスケープされる。
- 複数のファイルに分割されているデータを使う場合。例えば、hoge_x0y0.nc、hoge_x1y0.nc、hoge_x0y1.nc、hoge_x1y1.ncが存在するとする。データは2次元的に2*2 = 4ファイルに分割されている。
gphys = GPhys::NetCDF_IO(/hoge_x(\d)y(\d).nc/, 'temp')ここで、2つの括弧のペアは必要なものである。これは、次のようにもできる。
files = NArray[ ['hoge_x0y0.nc', 'hoge_x1y0.nc'], ['hoge_x0y1.nc', 'hoge_x1y1.nc'] ] gphys = GPhys::NetCDF_IO(files, 'temp')
- file (NetCDF): 書きこむためのNetCDFファイル。もちろん書き込み可能でなければならない
- gphys (GPhys): 書きこむGPhysオブジェクト
- name (String): (任意)name in the new file -- if you want to save with a different variable name than that of gphys.
一度にメモリ上に読み込むには大きすぎるGPhysオブジェクトを処理するイテレータ。GPhysオブジェクト(gphyses)をloopdimsで指定された次元で分割することでループを作り、filesに結果(ブロックの返り値)を書きこむ。
- gphyses (GPhys or Array of GPhys): 処理されるGPhysオブジェクト。これらの全てはloopdimsで指定された次元を持っていなければならず、それらの長さはファイル中で異なってはいけない。その他のファイルは任意であるので、例えばloopdims==["time"]である限りgphysesは[a(lon,lat,time), b(lat,time)]でもよい。
- files (NetCDF or Array of NetCDF): 結果が書き込まれるファイル。(Rubyの複数割り当てのルールに則り、)ファイルの個数は結果のGPhysオブジェクトの個数よりも少ないか同数でなければならない。
- loopdims (Array of String or Integer) : 名前(Stringの場合)かゼロから始めるカウント(Integerの場合)
- expected block : Number of arguments == number of GPhys objects in gphyses. Expected return value is an Array of GPhys objects to be written files.
- 次の場合は例外を発生させる。(引数エラーを含む)
- loopdimsで指定した次元をgphyses内のGPhysオブジェクトで共有されていない
- ブロックの返り値がGPhysのArrayオブジェクトでない
- ループに使う(loopdims)次元が、返されるGPhysオブジェクトから取り除かれている
- 例1
in = GPhys::NetCDF_IO.open(infile, varname) ofile = NetCDF.create(ofilename) out = in.mean(0) GPhys::NetCDF_IO.write( ofile, out ) ofile.closeデータオブジェクトがメモリ上から読み込まれ、平均化されている。データのサイズが一度にメモリに読み込むのに大きすぎる場合は、このイテレータを使うことでその処理を分割することができる。以下は上の結果と同じ物を得られるが、処理は最後の次元(-1となっているが、これはArrayの負のインデックスと同じ)で分割されたそれぞれの部分集合に対して行われる。
in = GPhys::NetCDF_IO.open(infile, varname) ofile = NetCDF.create(ofilename) out = GPhys::NetCDF_IO.each_along_dims_write(in, ofile, -1){|in_sub| [ in_sub.mean(0) ] } ofile.closeこの場合、each_along_dims_writeはin[false,0..0]、in[false,1..1]、in[false,2..2]、..をブロックの引数(in_sub)に代入することでループを作る。従って、ブロックの返り値(ここでは[ in_sub.mean(0) ])はin[false,0..0].mean(0)、in[false,1..1].mean(0)、..を含んでいる。このイテレータはoutの中に結果の全部分を表すGPhysオブジェクトを生成し、その中に結果の部分集合を一つ一つ書きこんでいく。そのため、イテレータから抜けたときには、出力ファイルは正しく書きこまれている。
この部分集合は最後の次元は保持するが、(0..0, 1..1,..)のRangeオブジェクトによってその長さは1になることに注意する。これにより、その部分集合は元々の階数と同じ階数を持っている。出力されるGPhysオブジェクトは、ブロックの返り値で与えられるように、その次元を保持しなければならない。理由は、その次元(長さが1)がファイルに書き込まれるときに元々の次元と置き換えられるからである。よって、以下はエラーを起こす(例外を発生させる)。
out = GPhys::NetCDF_IO.each_along_dims_write(in, ofile, 0){|in_sub| [ in_sub.mean(0) ] }ここで、ループは最初の次元(0)によって行われるが、同じ次元における平均化によって結果からは除かれる。(また、最初の次元の部分集合の長さが1であるため、この平均化は意味が無いことも注意する。)
- 例2
GPhys::NetCDF_IO.each_along_dims_write(in, ofile, -2, -1){|in_sub| ... }また、ループの次元は名前によっても指定できる。
GPhys::NetCDF_IO.each_along_dims_write(in, ofile, "y"){|in_sub| ... } GPhys::NetCDF_IO.each_along_dims_write(in, ofile, "y", "z"){|in_sub| ... }
- 例3
in1 = GPhys::NetCDF_IO.open(infile1, varname1) in2 = GPhys::NetCDF_IO.open(infile2, varname2) in3 = GPhys::NetCDF_IO.open(infile3, varname3) ofile = NetCDF.create(ofilename) outA, outB = \ GPhys::NetCDF_IO.each_along_dims_write([in1,in2,in3], ofile, -1){ |isub1,isub2,isub3| osubA = (isub1*isub2).mean(0) osubB = (isub2*isub3).mean(1) [ osubA, osubB ] } ofile.closeこの場合、2つの出力オブジェクト(outAとoutB)は3つの入力オブジェクト(in1,in2,in3)から作られ、一つのファイル(ofile)に書き込まれる。2つのファイルに分けたい場合は、以下のようにする。
in1 = GPhys::NetCDF_IO.open(infile1, varname1) in2 = GPhys::NetCDF_IO.open(infile2, varname2) in3 = GPhys::NetCDF_IO.open(infile3, varname3) ofile1 = NetCDF.create(ofilename1) ofile2 = NetCDF.create(ofilename2) outA, outB = \ GPhys::NetCDF_IO.each_along_dims_write([in1,in2,in3], [ofile1,ofile2], -1){ |isub1,isub2,isub3| osubA = (isub1*isub2).mean(0) osubB = (isub2*isub3).mean(1) [ osubA, osubB ] } ofile.close
最新コメント