ギャラリー
あくまでも公開メモという位置づけです. 自分以外に優しくない書き方をしていると思いますが ご容赦ください.
自分の計算結果の図表作成スクリプト (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)