[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[dennou-ruby:002127] gpview fix
- To: dennou-ruby@xxxxxxxxxxx
- Subject: [dennou-ruby:002127] gpview fix
- From: tsukahara daisuke <daktu32@xxxxxxxxxxxxxxxxxxxx>
- Date: Thu, 10 Feb 2005 22:46:18 +0900 (JST)
塚原です.
gpview を fix しました. 具体的には
1. オプションパーサ取り替え
+ getopts から getoptlong ヘ
2. --map, --m オプション追加
+ 地図投影(--itr 1-4 では無効.)
3. --reverse, --Gr オプション追加
+ アニメーション時, 逆回しにパラパラする
です. CVS に反映しましたが, メール末尾に添付させていただき
ます.
アニメーションの方向を指定する機能は, 以前のバージョンでは
変数の範囲の指定の仕方で決めてましたが, 値の大きい座標が配
列の先頭に入っていない場合にうまく作用しない等不具合があり,
やや複雑なコードになっていたので陽に指定することにしました.
--dump オプションの処置については, 中野さんに相談しつつ考え
てみたのですが, 人によって dump に求める挙動が異なるようです
ので, ここはむしろ gtview 同様に DCL の swpack の内部変数
を直接設定するオプションを用意するほうがいいように思います.
そのほうがコードも読みやすくなりそうですし. 更に手を加えた
い方は個々人で gpview を叩き台にカスタムしてもらえればと思
います. よって --dump なるオプションは用意しないことにしよ
うと思います. (中野さんには同意をいただきました)
--------------------------------------
北海道大学院理学研究科 地球惑星科学専攻
地球流体力学研究室 M2 塚原大輔
email::daktu32@xxxxxxxxxxxxxxxxxxxx
--------------------------------------
#!/usr/bin/env ruby
##################################################
=begin
=gpview
quick viewer for the values of a variable specified by
a gtool4-type URL.
(1) for 1-dimensional variable, make line plot.
(2) for 2-dimensional variable, make contour/tone plot.
(3) for 3/more-dimensional variable, make contour/tone
plot, select first 2D. possible to make animation.
==USAGE
% gpview [options] url
where the format of the url is
path@varname[,dimname=pos1[:pos2[:thinning_intv]][,dimname=...]]
==OPTIONS
if you want to know more description, please read
http://www.gfd-dennou.org/arch/gtool4/gtool4-1.0/doc/gtview.htm
===GLOBAL OPTIONS
--wsn [1-4] : set work staion number. each number represent
output device:
1 : X window.
2 : PS file. (named dcl.ps)
3 : Tcl/Tk file.
4 : GTK Windows (depend on dcl-5.3)
--itr [1-4,5-7,10-15,20-23,30-33]
: set axis scale. default is 1.
1 : linear scale for x/y axis
2 : linear scale for x , log scale for y axis
3 : log scale for x , linear scale for y axis
4 : log scale for x/y axis
--similar [simfac,vxoff,vyoff]
: (for 5<=itr<=7) set similarity parameters
which are fed in DCL.grssim.
--map_axis [uxc,uyc,rot]
: (for 10<=itr<=33) set mapping parameters
which are fed in DCL.umpcnt.
--title : set title of figure
--aspect <aspect> : set aspect ratio of Viewport. default is 2.0.
--animate/anim <dim> : plot animation along <dim>.
<dim> must be name of dimension.
--alternate, --Ga : enable to backing store.
--nowait, --Gw : not wait for any actions if animate
--reverse, --Gr : plot animation reversible if animate
--smooth, --Gaw : equal to --anlternate && --nowait
--exch : exchange(transpose) x/y axis.
--mean <dim> : mean along axis <dim>.
--m, --map <map_type> : plot map. itr number must be set.
this option is neglect if itr number is 1-4.
abailable map type is
coast_world, border_world, plate_world, state_usa,
coast_japan, pref_japan
===LINE OPTIONS
--line : make line plot forced. (about first 1D)
--index : set DCL line index, which set the color/thickness
of the line primitive. please see DCL documents.
--type : set line type.
===CONTOUR/TONE OPTIONS
--shade : make contour and tone plot.
--noshade : make contour plot, without tone.
--nocont : make tone plot, without contour.
--range [min:max] : set min/max value for contour/tone plot.
min or max must be set.
--crange : set min/max value for contour plot. this is more
dominant than --range
--srange : set min/max value for tone plot. this is more
dominant than --interval/int
--interval,--int [num]: set interval value for contour/tone plot.
set the number of lines if you set negative value.
--cint : set interval value for contour plot. this is more
dominant than --interval/int
--sint : set interval value for tone plot. this is more
dominant than --interval/int.
==EXAMPLES
% gpview data.nc@temp
% gpview data.nc@temp,lon=130:150,lat=0:90:2
% gpview --nocont data.nc@temp,lon=130:150,lat=0
% gpview --noshade data.nc@temp,lon=130:150,lat=0
% gpview --mean lon data.nc@temp,lon=130:150,lat=0
% gpview --exch data.nc@temp,lon=130:150,lat=0
% gpview --animate lon data.nc@temp,lon=130:150
% gpview --animate lon --alternate data.nc@temp
% gpview --smooth lon data.nc@temp,lon=130:150
==HISTORY
2004/12/14 D Tsukahara && T Horinouti(parse_gturl)
2005/01/08 D Tsukahara (add option --exch and able to invalid value)
2005/01/09 D Tsukahara (add option --animate, smooth, alternate, index )
2005/01/10 D Tsukahara (transpose axis with attr "positive:down" ,
abailable loopsense_flag. )
2005/01/10 D Tsukahara (implement GGraph::color_bar, and margin_info,
which file name, date, and toolname. )
2005/01/11 D Tsukahara ( 1. write document about OPTIONS.
2. add many options. more info please see document. )
2005/01/23 S Takehiro (add option --similar, map_axis)
2005/02/09 D Tsukahara && M Nakano (add option --reverse, --Gr, --map)
2005/02/10 D Tsukahara (change option parser (getopts => getoptlong))
=end
#################################################
require "getoptlong" # for option_parse
require "numru/ggraph" # ggraph library
include NumRu
#####################################################
## Default param.
VIEWPORT = [0.15,0.85,0.2,0.55]
URLfmt = "path@varname[,dimname=pos1[:pos2[:thinning_intv]][,dimname=...]]"
#####################################################
## -- parse gturl --
def parse_gturl(gturl)
if /(.*)@(.*)/ =~ gturl
file = $1
var = $2
else
raise "invalid URL: '@' between path & variable is not found" +
"URL format: " + URLfmt
end
if /,/ =~ var
slice = Hash.new
thinning = Hash.new
var_descr = var.split(/,/)
var = var_descr.shift
var_descr.each do |s|
if /(.*)=(.*)/ =~ s
dimname = $1
subset = $2
case subset
when /(.*):(.*):(.*)/
slice[dimname] = ($1.to_f)..($2.to_f)
thinning[dimname] = {0..-1,$3.to_i}
when /(.*):(.*)/
slice[dimname] = ($1.to_f)..($2.to_f)
else
slice[dimname] = subset.to_f
end
else
raise "invalid URL: variable subset specification error\n\n"
"URL format: " + URLfmt
end
end
thinning = nil if thinning.length == 0
else
slice = nil
thinning = nil
end
[file, var, slice, thinning]
end
def GGraph::annotate(str_ary)
lnum = 0
str_ary.each{ |str|lnum += 1 }
charsize = 0.7 * DCL.uzpget('rsizec1')
dvx = 0.01
dvy = charsize*1.5
raise TypeError,"Array expected" if ! str_ary.is_a?(Array)
vxmin,vxmax,vymin,vymax = DCL.sgqvpt
vx = 0.70
vy = 0.045 + (lnum-1)*dvy
str_ary.each{|str|
DCL::sgtxzv(vx,vy,str,charsize,0,-1,1)
vy -= dvy
}
nil
end
def each_along_dims(gphys, loopdim)
raise ArgumentError,"1st argument must be an GPhys." if !gphys.is_a?(GPhys)
if loopdim.is_a?(String)
dimname = loopdim
elsif
if loopdim < 0
dimname = gphys.coord(gphys.rank + loopdim).name
else
dimname = gphys.coord(loopdim).name
end
else
raise ArgumentError,"loopdims must consist of Integer and/or String"
end
loopdim_na = gphys.coord(dimname).val # get coord ary
loopdim_na = loopdim_na[-1..0] if $OPT_reverse || $OPT_Gr # reverse
loopdim_na.each { |x|
yield( gphys.cut(dimname=>x) )
}
end
def draw_setup(gp)
# set missing value
DCLExt.gl_set_params('lmiss'=>true,
'rmiss'=>gp.data.get_att('missing_value')[0]
) if gp.data.get_att('missing_value')
# fontsize
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
# viewport size
GGraph.set_fig('viewport'=>$VIEWPORT)
GGraph.set_fig( 'itr'=>($OPT_itr == nil) ? 1 : $OPT_itr.to_i )
GGraph.set_fig("xrev"=>"units:mb,units:hPa,units:millibar,positive:down",
"yrev"=>"units:mb,units:hPa,units:millibar,positive:down")
# set options
min_range, max_range = __split_range($OPT_srange)
min_crange, max_crange = __split_range($OPT_crange)
min_srange, max_srange = __split_range($OPT_range)
GGraph.set_linear_contour_options(
'int' => ( $OPT_cint || $OPT_interval ),
'min' => ( min_crange || min_range ),
'max' => ( max_crange || max_range )
)
GGraph.set_linear_tone_options(
'int' => ( $OPT_sint || $OPT_interval ),
'min' => ( min_srange || min_range ),
'max' => ( max_srange || max_range )
)
# judge draw kind
gp_rank = gp.rank
gp_rank = gp_rank - 1 if ( $OPT_animate || $OPT_anim )
if ($OPT_line || gp_rank == 1)
draw_flag = "line"
elsif (!$OPT_line && gp_rank >= 2) && !$OPT_noshade && $OPT_nocont
draw_flag = "nocont"
elsif (!$OPT_line && gp_rank >= 2) && $OPT_noshade && !$OPT_nocont
draw_flag = "noshade"
elsif (!$OPT_line && gp_rank >= 2) && !$OPT_noshade && !$OPT_nocont
draw_flag = "full"
end
# similar projection
if ($OPT_similar)
if /([\d\-.]*),([\d\-.]*),([\d\-.]*)/ =~ $OPT_similar
similar=[$1.to_f,$2.to_f,$3.to_f]
elsif /([\d\-.]*),([\d\-.]*)/ =~ $OPT_similar
similar=[$1.to_f,$2.to_f,0]
elsif /([\d\-.]*)/ =~ $OPT_similar
similar=[$1.to_f,0,0]
end
GGraph.set_fig('similar'=>similar)
end
# similar projection
if ($OPT_map_axis)
if /([\d\-.]*),([\d\-.]*),([\d\-.]*)/ =~ $OPT_map_axis
map_axis=[$1.to_f,$2.to_f,$3.to_f]
elsif /([\d\-.]*),([\d\-.]*)/ =~ $OPT_map_axis
map_axis=[$1.to_f,$2.to_f,0]
elsif /([\d\-.]*)/ =~ $OPT_similar
map_axis=[$1.to_f,0,0]
end
GGraph.set_fig('map_axis'=>map_axis)
end
# map
if ( $OPT_m || $OPT_map)
map_type = "coast_world" if $OPT_m
map_type = $OPT_map if $OPT_map
GGraph::set_map(map_type=>true)
end
return draw_flag
end
def draw(gp, draw_flag)
# draw hontai
case draw_flag
when "line"
GGraph.line(gp,
true,
"title"=>$OPT_title,
"index"=>($OPT_index||1),
"type" =>($OPT_type ||1),
"exchange"=>$OPT_exch
)
when "full"
GGraph.tone(gp,
true,
"title"=>$OPT_title,
"transpose"=>$OPT_exch
)
GGraph.contour(gp, false, "transpose"=>$OPT_exch)
when "nocont"
GGraph.tone(gp,
true,
"title"=>$OPT_title,
"transpose"=>$OPT_exch
)
when "noshade"
mj = DCL.udpget('indxmj')
mn = DCL.udpget('indxmn')
GGraph.contour(gp,
true,
"title" =>$OPT_title,
"label" =>true,
"transpose"=>$OPT_exch
)
end
# color bar
if ( draw_flag == "full") || ( draw_flag == "nocont")
GGraph::color_bar(
"left" => true,
"landscape" => true
)
end
end
def set_vpsize( default_vp, aspect=2.0 )
raise "#{aspect} must be a positive Numeric" if (aspect.to_f <= 0.0)
aspect = aspect.to_f
# default viewport
x0 = default_vp[0]; x1 = default_vp[1]
y0 = default_vp[2]; y1 = default_vp[3]
# viewport size
hlength = x1 - x0
vlength = y1 - y0
# center grid of viewport
cen_of_vp = [ x0 + hlength/2.0, y0 + vlength/2.0 ]
if aspect <= 2.0
hlength = vlength * aspect
x0 = cen_of_vp[0] - hlength/2.0
x1 = cen_of_vp[0] + hlength/2.0
else
vlength = hlength / aspect
y0 = cen_of_vp[1] - vlength/2.0
y1 = cen_of_vp[1] + vlength/2.0
end
return [ x0, x1, y0, y1 ]
end
def __split_range(range)
if /(.*):(.*)/ =~ range
if $1 == ""
min = nil
else
min = $1.to_f
end
if $2 == ""
max = nil
else
max = $2.to_f
end
elsif range == nil
min = max = nil
else
raise "invalid range: variable subset specification error. split range with ':'\n\n"
end
return min, max
end
#####################################################
###++++++ Main Routine ++++++###
## parse options
parser = GetoptLong.new
parser.set_options(
### global option ###
['--wsn', GetoptLong::REQUIRED_ARGUMENT],
['--itr', GetoptLong::REQUIRED_ARGUMENT],
['--similar', GetoptLong::REQUIRED_ARGUMENT],
['--map_axis', GetoptLong::REQUIRED_ARGUMENT],
['--aspect', GetoptLong::REQUIRED_ARGUMENT],
['--animate', GetoptLong::REQUIRED_ARGUMENT],
['--anim', GetoptLong::REQUIRED_ARGUMENT],
['--alternate', GetoptLong::NO_ARGUMENT],
['--Ga', GetoptLong::NO_ARGUMENT],
['--nowait', GetoptLong::NO_ARGUMENT],
['--Gw', GetoptLong::NO_ARGUMENT],
['--smooth', GetoptLong::NO_ARGUMENT],
['--Gaw', GetoptLong::NO_ARGUMENT],
['--exch', GetoptLong::NO_ARGUMENT],
['--reverse', GetoptLong::NO_ARGUMENT],
['--Gr', GetoptLong::NO_ARGUMENT],
['--mean', GetoptLong::REQUIRED_ARGUMENT],
['--map', GetoptLong::REQUIRED_ARGUMENT],
['--m', GetoptLong::NO_ARGUMENT],
### line option ###
['--line', GetoptLong::NO_ARGUMENT],
['--index', GetoptLong::REQUIRED_ARGUMENT],
['--type', GetoptLong::REQUIRED_ARGUMENT],
### tone or cont option ###
['--nocont', GetoptLong::NO_ARGUMENT],
['--noshade', GetoptLong::NO_ARGUMENT],
['--range', GetoptLong::REQUIRED_ARGUMENT],
['--crange', GetoptLong::REQUIRED_ARGUMENT],
['--srange', GetoptLong::REQUIRED_ARGUMENT],
['--interval', GetoptLong::REQUIRED_ARGUMENT],
['--int', GetoptLong::REQUIRED_ARGUMENT],
['--cint', GetoptLong::REQUIRED_ARGUMENT],
['--sint', GetoptLong::REQUIRED_ARGUMENT]
# ['--help', GetoptLong::NO_ARGUMENT], # to be defined
# ['--version', GetoptLong::NO_ARGUMENT] # to be defined
)
begin
parser.each_option do |name, arg|
eval "$OPT_#{name.sub(/^--/, '').gsub(/-/, '_')} = '#{arg}'" # strage option value to $OPT_val
end
rescue
exit(1)
end
## open netcdf variable
gturl = ARGV[0]
file, var, slice,thinning = parse_gturl(gturl)
gp = GPhys::IO.open(file,var)
gp = gp.cut(slice) if slice
gp = gp[thinning] if thinning
## mean along any axis
if ($OPT_mean)
dims = ($OPT_mean).split(/\s*,\s*/)
dims.each{|dim|
dim = dim.to_i if dim.to_i.to_s == dim
gp = gp.mean(dim)
}
end
## set some figure option
DCL::swlset('lwait', false) if ($OPT_nowait || $OPT_Gw || $OPT_smooth || $OPT_Gaw)
# set wait or nowait
DCL::swlset('lalt', true) if ($OPT_alternate || $OPT_Ga || $OPT_smooth || $OPT_Gaw)
# set backing store option
## decide VIEWPORT
$VIEWPORT = set_vpsize( VIEWPORT, ($OPT_aspect||2.0) )
## draw figure
loopdim = ( $OPT_animate || $OPT_anim )
loopdim = loopdim.to_i if loopdim.to_i.to_s == loopdim
DCL.gropn($OPT_wsn||1) # open work station
GGraph.margin_info($0, gturl) # draw margin infomation
kind_of_fig = draw_setup(gp) # determine figure kind
if loopdim # animation
each_along_dims(gp, loopdim){|gp_subset|
draw(gp_subset, kind_of_fig)
}
else
draw( gp, kind_of_fig ) # single figure
end
DCL.grcls