ギャラリー
あくまでも公開メモという位置づけです. 自分以外に優しくない書き方をしていると思いますが ご容赦ください.
自分の計算結果の図表作成スクリプト (Ruby) に関する 覚書やテンプレートを置いています. 気が向いたらライブラリ化していくかもしれません.
描画以外でよく使うコード
最初の部分
#!/usr/bin/env ruby require "pp" require 'optparse' require "numru/ggraph" include NumRu require "../load_config" # 設定を読み込む. 自作. require "../utils" # ユーティリティを読み込む. 自作. DCL::gllset('LMISS', true) # 欠損値処理を行う
デフォルト値
wsn = 4 clrmap = 1 val_min = ... val_max = ... time_start = 1000 time_start = 2000
コマンドライン引数処理
# commandline option opt = OptionParser.new opt.on('--wsn VAL') {|v| wsn = v.to_i } opt.on('--int VAL') {|v| interval = v.to_f } opt.on('--clrmap VAL') {|v| clrmap = v.to_i } opt.on('--range VAL') {|v| ary = v.split(":") if ary.size == 2 and ary[0] < ary[1] then val_min = ary[0].to_f val_max = ary[1].to_f else raise "ERROR: #{v} is invalid range." end if interval == nil then interval = (val_max - val_min) / 40.0 end } opt.parse!(ARGV) if ARGV.size > 0 raise "ERROR: invalid option: #{ARGV[0]}" end
netCDF ファイルの読み込み (準備)
以下の記述はまだ不十分.
var = 'U' path = File.join(exp_dirs[omegas[0]], var+'.nc') lat = GPhys::IO.open(path, 'lat') na_lat_weight = GPhys::IO.open(path, 'lat_weight').val nlat = lat.val.size na_sig_weight = GPhys::IO.open(path, 'sig_weight').val nsig = na_sig_weight.size
netCDF ファイルの読み込み (本番)
よくループで回すのでこのような構造にしている.
# input var = 'U' path = File.join(dir, var+'.nc') gp_u = GPhys::IO.open(path, var).cut('time'=>time_start..time_end)
余白を削って eps ファイルとして出力
ここでは必要なコマンドにパスが通っているかの確認は行なっていない.
# remove extra space of ps file if wsn == 2 then if File.exist?(TMPFILE) then puts("MESSAGE: after processing ... #{epsfn} will be generate.") `dclpsrmcm #{TMPFILE} | dclpsrot | dclpsmargin > #{epsfn}` end end
Gphys オブジェクトの使い回し
このあたりは整理中.
def gp2axis(gp) data = gp.data va = VArray.new( gp.val, {"long_name"=>data.long_name, "units"=>data.units.to_s }, data.name ) gp2axis = Axis.new.set_pos(va) end def gpdata_reuse_va(nary, gp) gpdata_reuse_va = VArray.new( nary, { "long_name"=>gp.data.long_name, "units"=>gp.data.units.to_s}, gp.data.name ) end axis_lat = gp2axis(lat) grid = Grid.new(axis_x, axis_lat) gp = GPhys.new( grid, gpdata_reuse_va(na_x, gp_x) )
描画 (GGraph)
描画準備
DCL.sgscmn(clrmap||1) # colormap DCL.gropn(wsn) GGraph.set_fig('viewport'=>[0.15,0.85,0.2,0.55]) DCL.sgpset('lcntl', false) ; DCL.uzfact(0.7) DCL.sgpset('lfull', true) # use full area in the window DCL.sgpset('lfprop',true) # use proportional font DCL.uscset('cyspos', 'B' ) # move unit y axis
描画終了
DCL.grcls
折れ線 (GGraph.line)
マーク (GGraph.mark)
MARK_SIZE = 0.015 MARK_LINE_THICKNESS = 7 MARK_TYPE = 4 # circle MARK_INDEX = 1 # black (略) opt_draw = { 'max'=>val_max, 'min'=>val_min, 'size'=>MARK_SIZE, 'legend'=>false, 'annotate'=>false, 'title'=>TITLE, 'type'=> MARK_TYPE, 'index'=> 10 * MARK_INDEX + MARK_LINE_THICKNESS } GGraph.mark( gp, true, opt_draw )
トーン, コンター (GGraph.tone, GGraph.contour)
opt_draw = { 'max'=>val_max, 'min'=>val_min, 'interval'=>interval, 'title'=>TITLE, # 'legend'=>false, 'annotate'=>false, } GGraph.tone( gp_flux, true, opt_draw ) GGraph.contour( gp_flux, false, opt_draw ) GGraph.color_bar
ベクトル (GGraph.vector)
# ベクトルの描画間隔 (単位は格子点数) xintv = 6 yintv = 2 # ベクトルの倍率 xfact1 = 1.0 yfact1 = 1.0 # 凡例の単位ベクトルの長さ uxunit = 0.03 uyunit = 0.03 (略) #DCL.sgpset('lcntl', false) ; DCL.uzfact(0.7) DCL.sgpset('lcntl', false) ; DCL.uzfact(1.0) # 球の時 #GGraph.set_fig 'itr'=>ITR, 'viewport'=>[0.15,0.95,0.2,0.8], 'map_axis'=>[LON_CNT, 0, 0] GGraph.set_fig 'viewport'=>[0.15,0.95,0.2,0.8] DCL.ugpset('LNRMAL', false) # scale vector automatically DCL.ugpset('XFACT1', xfact1) DCL.ugpset('YFACT1', yfact1) DCL.ugpset('UXUNIT', uxunit) # size of unit vector by dimentional value DCL.ugpset('UYUNIT', uyunit) DCL::ugrset('VXUNIT', 0.1) # size of unit vector DCL::ugrset('VYUNIT', 0.1) DCL::uxmttl('T', '', 0.0) # title (large character) DCL.ugpset('LMSG', false) # no message opt_vector = { 'xintv'=>xintv, 'yintv'=>yintv, 'flow_vect'=>false, 'annotate'=>false, 'unit_vect'=>true } GGraph.vector( gp_u, gp_v, true, opt_vector)
散布図 (GGraph.scatter)
TITLE = 'OLR' YNAME = 'OLR' #YUNIT = '10^15 W' TIME_START = 1000 TIME_END = 2000 XMIN = 170 XMAX = 340 YMIN = 100 YMAX = 450 (略) # 2 次元以上のデータを 1 次元配列に落とす (GGraph.scatter 対策) def flatten_gphys(gp) na_dat = gp.val.flatten n = na_dat.size axis = dummy_axis(n) data = VArray.new( na_dat, {"long_name"=>gp.data.long_name, "units"=>gp.data.units.to_s}, gp.data.name ) gp = GPhys.new( Grid.new(axis), data ) end # ダミーの gphys を作成 (GGraph.scatter での図の範囲指定のため) def dummy_gphys(na) n = na.size axis = dummy_axis(n) data = VArray.new( na, {"long_name"=>"dummy", "units"=>"1"}, "dummy" ) gp = GPhys.new( Grid.new(axis), data ) end def dummy_axis(n) axis_a = VArray.new( NArray.sfloat(n).indgen, {"long_name"=>"dummy","units"=>"1"}, "dummy" ) axis = Axis.new.set_pos(axis_a) end (略) # 範囲指定のためのダミーデータ na_xrange = NArray.to_na([XMIN, XMAX]) na_yrange = NArray.to_na([YMIN, YMAX]) gp_xrange = dummy_gphys(na_xrange) gp_yrange = dummy_gphys(na_yrange) gp_xrange.data.long_name = gp_Tg.data.long_name gp_yrange.data.long_name = gp_OLR.data.long_name gp_xrange.data.units = gp_Tg.data.units gp_yrange.data.units = gp_OLR.data.units # 図の範囲を指定する方法が分からないのでダミーの点を打つ GGraph.scatter( gp_xrange, gp_yrange, true, 'type'=>1) opt = { 'annotate'=>false, 'title'=>TITLE, 'index'=>1 } # draw opt['type'] = 1 GGraph.scatter( flatten_gphys( gp_Tg.cut('lon'=>0..179.99) ), flatten_gphys( gp_OLR.cut('lon'=>0..179.99) ), false, opt)