GrADS のファイルを読み込む例を示して
を見ていきたいと思います。ファイルのオープンとクローズは File クラスまたは 組み込み関数 open を使用して
file = File.open(filename [,mode]) or file = open(filename [,mode]) : file.close |
File.open(filename [,mode]){|file| : } |
読み込みには
line = file.gets # 1行読み込む str = file.read(n) # nバイト読み込む file.each_byte{|ch| hoge} # 1バイトづつ読み込んでブロックを実行する file.each_line{|line| hoge} # 1行づつ読み込んでブロックを実行する |
File.foreach(filename){|line| hoge} # File.open{|file|file.each_line{|line|hoge}}とほぼ同じ lines = file.readlines # linesは各行の配列 |
書き込みは
file.puts(strings) file.print(strings) |
file << str1 << str2 |
では GrADS のコントロールファイルをよんでいきましょう
grads.ctl
ruby がもっとも得意とするのがこの文字列操作です。 String クラス には様々なメソッドが用意させており、 また強力な 正規表現 も使うことができます。
コントロールファイルの各行はスペースで区切られた要素から成り立っています。 この要素からなる Array クラス を作ってみましょう。
open('grads.ctl','r'){|file| ary = file.gets.split # ary = ["DSET","^./data"] } |
data = Hash.new open('grads.ctl','r'){|file| while line = file.gets do ary = line.split data[ary[0]] = ary[1..-1] end } |
if line =~ /^\s/ then data[last] = data[last]+ary else last = ary[0] data[last] = ary[1..-1] end |
変数は別の Hash に入れたいと思います。
longname = Hash.new unit = Hash.new var = false if line =~ /^VARS/ then nvar = line.split[1] var = true elsif line =~ /^ENDVARS/ then var = false elsif var then ary = line.split name = ary[0] str = ary[3..-1].join(' ') longname[name] = str[0..str.index('[')-2] unit[name] = str[str.index('[')+1..-3] end |
軸は少し工夫が必要です。
dims = Hash.new data.each_key{|key| if key =~ /^.DEF$/ ary = data[key] name = key[0].downcase if ary[1] == 'LINEAR' dims[name] = NArray.sfloat(ary[0].to_i).indgen!(ary[2].to_f,ary[3].to_f) elsif ary[1] == 'LEVELS' dims[name] = NArray.to_na( ary[2..-1].collect{|str| str.to_f} ) end data.delete(key) } |
あとは個別の処理
data.each_key{|key| if key == 'TITLE' then data[key] = data[key].join(' ') elsif key == 'UNDEF' data[key] = data[key][0].to_f end } |
以上まとめると
grads1.rb
となり各データがそろったことになります。
ではコントロールファイルが読めたところで
今度はバイナリファイルを読みたいと思います。
grads1.data
128(x) x 64(y) x 10(z) x 2(var) x 12(month) x 4(sfloat)
というようにデータが入っています。
NArray.to_na(str,"sfloat",dim0,dim1,..) |
idim = x.length jdim = y.length kdim = z.length tdim = t.length u = NArray.sfloat(idim,jdim,kdim,tdim) v = NArray.sfloat(idim,jdim,kdim,tdim) file = open('grads.data','r') for m in 0..tdim-1 str = file.read(4*idim*jdim*kdim) u[true,true,true,m] = NArray.to_na(str,"sfloat",idim,jdim,kdim) str = file.read(4*idim*jdim*kdim) v[true,true,true,m] = NArray.to_na(str,"sfloat",idim,jdim,kdim) end file.close |
ary = str.unpack('f*') |
もしこのデータのエンディアンが異なる場合
grads2.data
NArray.to_na(str,.....).swap_byte str.unpack('e*') (リトルエンディアン) or str.unpack('g*') (ビッグエンディアン) |
あとはこのデータを煮ても焼いてもあなた次第です。