[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[dennou-ruby:002690] GGraph: lon/lat axes
- To: dennou-ruby@xxxxxxxxxxx
- Subject: [dennou-ruby:002690] GGraph: lon/lat axes
- From: KOSHIRO Tsuyoshi <koshiro@xxxxxxxxxxxxxx>
- Date: Fri, 18 Aug 2006 22:24:32 +0900
神代です.
GGraph で緯度・経度の軸を描いたとき,ラベルを 90N..EQ..90S とか
0..90E..180..90W..0 とかにしたいことがよくあるので,作ってみました.
ggraph.rb の中に DCLExt::lon_ax, DCLExt::lat_ax という名前で追加して,
GGraph::axes からは,これらを xmaplabel, ymaplabel というオプションで
呼べるようにしました.
dclext_datetime_ax.rb を参考に作りました.DCL.us[xy]axs のソースを見て
真似をして,オートスケーリングできるようにしてます.
最新のCVS版に対するパッチを添付します(先日の map_fit/map_axes に関する
パッチとは別にしてます).
テストスクリプトも添付します.gphys/sample/map_projection.rb を改変し
たものです.gphys/sample に置いて実行できます.
# 作った直接の動機は,先日メールした GPhysの地図投影の改良で,少し困っ
# たことがあったからです.これを使うと,データをいじらずに軸つき地図の
# 描画範囲を自由に変えられて便利なのですが,ウィンドウのとりかたによっ
# ては,たとえば
# GGraph.next_fig("itr"=>10, "map_fit"=>false, "map_axis"=>[210,0,0], "map_window"=>[-180,180,-90,90])
# とすると,横軸のラベルは 30..390 になってしまって,経度の値としては
# うれしくないです.なので,こういうのがほしくなりました.
--- ggraph.rb_orig 2006-08-16 12:19:01.932785000 +0900
+++ ggraph.rb 2006-08-18 21:06:09.111918007 +0900
@@ -327,6 +327,12 @@
# (if nil, internally determined)
"ylabelint" nil # Interval of y axis label
# (if nil, internally determined)
+ "xmaplabel" false # If "lon"("lat"), use
+ # DCLExt::lon_ax(DCLExt::lat_ax) to draw xaxes;
+ # otherwise, DCL::usxaxs is used.
+ "ymaplabel" false # If "lon"("lat"), use
+ # DCLExt::lon_ax(DCLExt::lat_ax) to draw yaxes;
+ # otherwise, DCL::usyaxs is used.
"help" false # show help message if true
RETURN VALUE
@@ -1035,6 +1041,45 @@
==Original methods:
+===Longitude/Latitude Axes
+---lon_ax( options=nil )
+
+ Draw longitude axis. (label format: degrees + 'E' or 'W')
+
+ ARGUMENTS
+ * options (Hash) : options to change the default behavior if specified.
+ It is a Hash with option names (String) as keys and their values.
+ Options are interpreted by a NumRu::Misc::KeywordOptAutoHelp,
+ so you can shorten the keys (by omitting tails) as long as it is
+ unambiguous.
+ option name default value # description:
+ "yax" false # true => draw y-axis, false => draw x-axis
+ "cside" nil # "b", "t", "l", "r",
+ # nil (=>left/bottom), or false (=>right/top)
+ "dtick1" nil # Interval of small tickmark
+ # (if nil, internally determined)
+ "dtick2" nil # Interval of large tickmark with labels
+ # (if nil, internally determined)
+
+---lat_ax( options=nil )
+
+ Draw latitude axis. (label format: degrees + 'N' or 'S')
+
+ ARGUMENTS
+ * options (Hash) : options to change the default behavior if specified.
+ It is a Hash with option names (String) as keys and their values.
+ Options are interpreted by a NumRu::Misc::KeywordOptAutoHelp,
+ so you can shorten the keys (by omitting tails) as long as it is
+ unambiguous.
+ option name default value # description:
+ "xax" false # true => draw x-axis, false => draw y-axis
+ "cside" nil # "b", "t", "l", "r",
+ # nil (=>left/bottom), or false (=>right/top)
+ "dtick1" nil # Interval of small tickmark
+ # (if nil, internally determined)
+ "dtick2" nil # Interval of large tickmark with labels
+ # (if nil, internally determined)
+
===Vectors
---unit_vect( vxfxratio, vyfyratio, fxunit=nil, fyunit=nil, options=nil )
@@ -1421,6 +1466,245 @@
# RELATIVELY INDEPENDENT OF DCL SUBLIBRARIES
############################################################
+ # <<< longitude/latitude axes package >>>
+
+ @@lon_ax_options = Misc::KeywordOptAutoHelp.new(
+ ['yax', false, 'true => y-axis, false => x-axis'],
+ ['cside', nil, '"b", "t", "l", "r", nil (=>left/bottom), or false (=>right/top)'],
+ ['dtick1', nil, 'Interval of small tickmark (if nil, internally determined)'],
+ ['dtick2', nil, 'Interval of large tickmark with labels (if nil, internally determined)']
+ )
+
+ def lon_ax(options=nil)
+ opt = @@lon_ax_options.interpret(options)
+
+ yax = opt['yax']
+ xax = !yax
+ if xax
+ xy='x'
+ else
+ xy='y'
+ end
+
+ if opt['cside']
+ cside = opt['cside']
+ elsif opt['cside'].nil?
+ if xax
+ cside='b'
+ else
+ cside='l'
+ end
+ else
+ if xax
+ cside='t'
+ else
+ cside='r'
+ end
+ end
+
+ vxmin, vxmax, vymin, vymax = DCL.sgqvpt
+ uxmin, uxmax, uymin, uymax = DCL.sgqwnd
+ if xax
+ vmin, vmax = [vxmin,vxmax].min, [vxmin,vxmax].max
+ umin, umax = [uxmin,uxmax].min, [uxmin,uxmax].max
+ else
+ vmin, vmax = [vymin,vymax].min, [vymin,vymax].max
+ umin, umax = [uymin,uymax].min, [uymin,uymax].max
+ end
+
+ # get dtick1 & dtick2
+ dtick1 = opt['dtick1']
+ dtick2 = opt['dtick2']
+ unless dtick1 && dtick2
+ irota = DCL.uzpget("irotl#{xy}#{cside}")
+ irota += 1 if yax
+ mode = irota.modulo(2)
+ DCL.ususcu(xy.capitalize,umin,umax,vmin,vmax,mode)
+ dtick1 = DCL.uspget("d#{xy}t") unless dtick1
+ dtick2 = DCL.uspget("d#{xy}l") unless dtick2
+ end
+
+ lepsl = DCL.glpget('lepsl')
+ repsl = DCL.glpget('repsl')
+ DCL.glpset('lepsl',true)
+
+ # generate numbers for small tickmarks
+ nn = 0
+ rx = DCL.irle(umin/dtick1)*dtick1
+ if DCL.lreq(umin,rx)
+ x = rx
+ else
+ x = rx + dtick1
+ end
+ u1 = []
+ while DCL.lrle(x,umax)
+ if x.abs < dtick1*repsl*nn
+ x = 0.0
+ end
+ u1[nn] = x
+ nn = nn + 1
+ x = x + dtick1
+ end
+
+ # generate numbers for large tickmarks and labels
+ nn = 0
+ rx = DCL.irle(umin/dtick2)*dtick2
+ if DCL.lreq(umin,rx)
+ x = rx
+ else
+ x = rx + dtick2
+ end
+ u2 = []
+ while DCL.lrle(x,umax)
+ if x.abs < dtick2*repsl*nn
+ x = 0
+ end
+ u2[nn] = x
+ nn = nn + 1
+ x = x + dtick2
+ end
+
+ # generate labels
+ c2 = NArray.to_na(u2)
+ c2[c2.gt(180)] -= 360.0
+ c2[c2.lt(-180)] += 360.0
+ c2[c2.eq(-180)] = 180.0
+ c2 = c2.to_a.collect do |c|
+ if c == 0 || c == 180
+ c.to_i.to_s
+ elsif c > 0
+ c.to_i.to_s + 'E'
+ else
+ c.abs.to_i.to_s + 'W'
+ end
+ end
+ nc = c2.collect{|c| c.size}.max
+
+ # call DCL.u[xy]axlb
+ if xax
+ DCL.uxaxlb(cside,u1,u2,c2,nc)
+ else
+ DCL.uyaxlb(cside,u1,u2,c2,nc)
+ end
+ end
+
+ @@lat_ax_options = Misc::KeywordOptAutoHelp.new(
+ ['xax', false, 'true => x-axis, false => y-axis'],
+ ['cside', nil, '"b", "t", "l", "r", nil (=>left/bottom), or false (=>right/top)'],
+ ['dtick1', nil, 'Interval of small tickmark (if nil, internally determined)'],
+ ['dtick2', nil, 'Interval of large tickmark with labels (if nil, internally determined)']
+ )
+
+ def lat_ax(options=nil)
+ opt = @@lat_ax_options.interpret(options)
+
+ xax = opt['xax']
+ yax = !xax
+ if xax
+ xy='x'
+ else
+ xy='y'
+ end
+
+ if opt['cside']
+ cside = opt['cside']
+ elsif opt['cside'].nil?
+ if xax
+ cside='b'
+ else
+ cside='l'
+ end
+ else
+ if xax
+ cside='t'
+ else
+ cside='r'
+ end
+ end
+
+ vxmin, vxmax, vymin, vymax = DCL.sgqvpt
+ uxmin, uxmax, uymin, uymax = DCL.sgqwnd
+ if xax
+ vmin, vmax = [vxmin,vxmax].min, [vxmin,vxmax].max
+ umin, umax = [uxmin,uxmax].min, [uxmin,uxmax].max
+ else
+ vmin, vmax = [vymin,vymax].min, [vymin,vymax].max
+ umin, umax = [uymin,uymax].min, [uymin,uymax].max
+ end
+
+ # get dtick1 & dtick2
+ dtick1 = opt['dtick1']
+ dtick2 = opt['dtick2']
+ unless dtick1 && dtick2
+ irota = DCL.uzpget("irotl#{xy}#{cside}")
+ irota += 1 if yax
+ mode = irota.modulo(2)
+ DCL.ususcu(xy.capitalize,umin,umax,vmin,vmax,mode)
+ dtick1 = DCL.uspget("d#{xy}t") unless dtick1
+ dtick2 = DCL.uspget("d#{xy}l") unless dtick2
+ end
+
+ lepsl = DCL.glpget('lepsl')
+ repsl = DCL.glpget('repsl')
+ DCL.glpset('lepsl',true)
+
+ # generate numbers for small tickmarks
+ nn = 0
+ rx = DCL.irle(umin/dtick1)*dtick1
+ if DCL.lreq(umin,rx)
+ x = rx
+ else
+ x = rx + dtick1
+ end
+ u1 = []
+ while DCL.lrle(x,umax)
+ if x.abs < dtick1*repsl*nn
+ x = 0.0
+ end
+ u1[nn] = x
+ nn = nn + 1
+ x = x + dtick1
+ end
+
+ # generate numbers for large tickmarks and labels
+ nn = 0
+ rx = DCL.irle(umin/dtick2)*dtick2
+ if DCL.lreq(umin,rx)
+ x = rx
+ else
+ x = rx + dtick2
+ end
+ u2 = []
+ while DCL.lrle(x,umax)
+ if x.abs < dtick2*repsl*nn
+ x = 0
+ end
+ u2[nn] = x
+ nn = nn + 1
+ x = x + dtick2
+ end
+
+ # generate labels
+ c2 = NArray.to_na(u2)
+ c2 = c2.to_a.collect do |c|
+ if c == 0
+ 'EQ'
+ elsif c > 0
+ c.to_i.to_s + 'N'
+ else
+ c.abs.to_i.to_s + 'S'
+ end
+ end
+ nc = c2.collect{|c| c.size}.max
+
+ # call DCL.u[xy]axlb
+ if xax
+ DCL.uxaxlb(cside,u1,u2,c2,nc)
+ else
+ DCL.uyaxlb(cside,u1,u2,c2,nc)
+ end
+ end
+
# <<< flow vector package >>>
def __truncate(float, order=2)
@@ -2436,7 +2720,11 @@
['xlabelint', nil,
'Interval of x axis label (if nil, internally determined)'],
['ylabelint', nil,
- 'Interval of y axis label (if nil, internally determined)']
+ 'Interval of y axis label (if nil, internally determined)'],
+ ['xmaplabel', false,
+ 'If "lon"("lat"), use DCLExt::lon_ax(DCLExt::lat_ax) to draw xaxes; otherwise, DCL::usxaxs is used.'],
+ ['ymaplabel', false,
+ 'If "lon"("lat"), use DCLExt::lon_ax(DCLExt::lat_ax) to draw yaxes; otherwise, DCL::usyaxs is used.']
)
def set_axes(options)
@@axes.set(options)
@@ -2460,26 +2748,50 @@
opts = @@axes.interpret(options)
if opts['xside'].length > 0
xai = _get_axinfo(xax)
- DCL.uscset('cxttl', (opts['xtitle'] || xai['title']) )
- DCL.uscset('cxunit',(opts['xunits'] || xai['units']) )
- DCL.uspset('dxt', opts['xtickint']) if(opts['xtickint'])
- DCL.uspset('dxl', opts['xlabelint']) if(opts['xlabelint'])
- opts['xside'].split('').each{|s| # scan('.') also works
- DCL.usxaxs(s)
- }
+ if opts['xmaplabel'] == "lon"
+ opts['xside'].split('').each{|s| # scan('.') also works
+ DCLExt.lon_ax('cside'=>s, 'dtick1'=>opts['xtickint'], 'dtick2'=>opts['xlabelint'])
+ }
+ DCL.uxsttl('b', (opts['xtitle'] || xai['title']), 0.0)
+ elsif opts['xmaplabel'] == "lat"
+ opts['xside'].split('').each{|s| # scan('.') also works
+ DCLExt.lat_ax('xax'=>true, 'cside'=>s, 'dtick1'=>opts['xtickint'], 'dtick2'=>opts['xlabelint'])
+ }
+ DCL.uxsttl('b', (opts['xtitle'] || xai['title']), 0.0)
+ else
+ DCL.uscset('cxttl', (opts['xtitle'] || xai['title']) )
+ DCL.uscset('cxunit',(opts['xunits'] || xai['units']) )
+ DCL.uspset('dxt', opts['xtickint']) if(opts['xtickint'])
+ DCL.uspset('dxl', opts['xlabelint']) if(opts['xlabelint'])
+ opts['xside'].split('').each{|s| # scan('.') also works
+ DCL.usxaxs(s)
+ }
+ end
end
if opts['yside'].length > 0
yai = _get_axinfo(yax)
- DCL.uscset('cyttl', (opts['ytitle'] || yai['title']) )
- DCL.uscset('cyunit', (un=(opts['yunits'] || yai['units'])) )
- DCL.uspset('dyt', opts['ytickint']) if(opts['ytickint'])
- DCL.uspset('dyl', opts['ylabelint']) if(opts['ylabelint'])
- opts['yside'].split('').each{|s| # scan('.') also works
- DCL.usyaxs(s)
- if s=='l' && un && un != ''
- DCL.uzpset('roffxt', DCL.uzpget('rsizec1')*1.5 )
- end
- }
+ if opts['ymaplabel'] == "lon"
+ opts['yside'].split('').each{|s| # scan('.') also works
+ DCLExt.lon_ax('yax'=>true, 'cside'=>s, 'dtick1'=>opts['ytickint'], 'dtick2'=>opts['ylabelint'])
+ }
+ DCL.uysttl('l', (opts['ytitle'] || yai['title']), 0.0)
+ elsif opts['ymaplabel'] == "lat"
+ opts['yside'].split('').each{|s| # scan('.') also works
+ DCLExt.lat_ax('cside'=>s, 'dtick1'=>opts['ytickint'], 'dtick2'=>opts['ylabelint'])
+ }
+ DCL.uysttl('l', (opts['ytitle'] || yai['title']), 0.0)
+ else
+ DCL.uscset('cyttl', (opts['ytitle'] || yai['title']) )
+ DCL.uscset('cyunit', (un=(opts['yunits'] || yai['units'])) )
+ DCL.uspset('dyt', opts['ytickint']) if(opts['ytickint'])
+ DCL.uspset('dyl', opts['ylabelint']) if(opts['ylabelint'])
+ opts['yside'].split('').each{|s| # scan('.') also works
+ DCL.usyaxs(s)
+ if s=='l' && un && un != ''
+ DCL.uzpset('roffxt', DCL.uzpget('rsizec1')*1.5 )
+ end
+ }
+ end
end
nil
end
require 'numru/ggraph'
include NumRu
wsn = ( ARGV[0] ? ARGV[0].to_i : 1 )
path = '../testdata/T.jan.nc'
var = 'T'
gp = GPhys::IO.open(path,var)
DCL.swpset('ldump',true) if wsn == 4
DCL.gropn(wsn)
DCL.sldiv('y',3,2)
#DCL.uzfact(0.8)
DCL.sgpset('lcntl',false)
GGraph.set_map('coast_world'=>true)
gpjpn = gp.cut(110..160,10..70,false)
itr = 10
# contour
GGraph.next_fig('itr'=>itr)
GGraph.contour(gp, true,'map_axes'=>true,'title'=>'default axes')
GGraph.next_fig('itr'=>itr)
GGraph.next_axes('xmaplabel'=>'lon','ymaplabel'=>'lat')
GGraph.contour(gp, true,'map_axes'=>true,'title'=>'lon/lat axes')
GGraph.next_fig('itr'=>itr)
GGraph.next_axes('xmaplabel'=>'lon','ymaplabel'=>'lat','xtickint'=>30, 'ytickint'=>10, 'xlabelint'=>90, 'ylabelint'=>30)
GGraph.contour(gp, true,'map_axes'=>true,'title'=>'lon/lat axes (set interval)')
# tone
GGraph.next_fig('itr'=>itr)
GGraph.tone(gp, true,'map_axes'=>true,'title'=>'default axes')
GGraph.next_fig('itr'=>itr)
GGraph.next_axes('xmaplabel'=>'lon','ymaplabel'=>'lat')
GGraph.tone(gp, true,'map_axes'=>true,'title'=>'lon/lat axes')
GGraph.next_fig('itr'=>itr)
GGraph.next_axes('xmaplabel'=>'lon','ymaplabel'=>'lat','xtickint'=>30, 'ytickint'=>10, 'xlabelint'=>90, 'ylabelint'=>30)
GGraph.tone(gp, true,'map_axes'=>true,'title'=>'lon/lat axes (set interval)')
# tone & contour
GGraph.next_fig('itr'=>itr)
GGraph.tone(gpjpn, true,'map_axes'=>true,'title'=>'default axes')
GGraph.contour( gpjpn, false )
GGraph.next_fig('itr'=>itr)
GGraph.next_axes('xmaplabel'=>'lon','ymaplabel'=>'lat')
GGraph.tone(gpjpn, true,'map_axes'=>true,'title'=>'lon/lat axes')
GGraph.contour( gpjpn, false )
GGraph.next_fig('itr'=>itr)
GGraph.next_axes('xmaplabel'=>'lon','ymaplabel'=>'lat','xtickint'=>10, 'ytickint'=>10, 'xlabelint'=>30, 'ylabelint'=>30)
GGraph.tone(gpjpn, true,'map_axes'=>true,'title'=>'lon/lat axes (set interval)')
GGraph.contour( gpjpn, false )
# vector ('flow_vect'=>false)
GGraph.next_fig('itr'=>itr)
GGraph.vector(gpjpn,gpjpn, true,'map_axes'=>true,'title'=>'default axes','flow_vect'=>false,'unit_vect'=>true)
GGraph.next_fig('itr'=>itr)
GGraph.next_axes('xmaplabel'=>'lon','ymaplabel'=>'lat')
GGraph.vector(gpjpn,gpjpn, true,'map_axes'=>true,'title'=>'lon/lat axes','flow_vect'=>false,'unit_vect'=>true)
GGraph.next_fig('itr'=>itr)
GGraph.next_axes('xmaplabel'=>'lon','ymaplabel'=>'lat','xtickint'=>10, 'ytickint'=>10, 'xlabelint'=>30, 'ylabelint'=>30)
GGraph.vector(gpjpn,gpjpn, true,'map_axes'=>true,'title'=>'lon/lat axes (set interval)','flow_vect'=>false,'unit_vect'=>true)
# vector ('flow_vect'=>true)
GGraph.next_fig('itr'=>itr)
GGraph.vector(gpjpn,gpjpn, true,'map_axes'=>true,'title'=>'default axes','unit_vect'=>true)
GGraph.next_fig('itr'=>itr)
GGraph.next_axes('xmaplabel'=>'lon','ymaplabel'=>'lat')
GGraph.vector(gpjpn,gpjpn, true,'map_axes'=>true,'title'=>'lon/lat axes','unit_vect'=>true)
GGraph.next_fig('itr'=>itr)
GGraph.next_axes('xmaplabel'=>'lon','ymaplabel'=>'lat','xtickint'=>10, 'ytickint'=>10, 'xlabelint'=>30, 'ylabelint'=>30)
GGraph.vector(gpjpn,gpjpn, true,'map_axes'=>true,'title'=>'lon/lat axes (set interval)','unit_vect'=>true)
DCL.grfrm
DCL.grfrm
DCL.grfrm
### DCLExt::lon_ax, DCLExt::lat_ax
DCL.grfrm
DCL.grswnd(0.0, 360.0, -90.0, 90.0)
DCL.grsvpt(0.15, 0.95, 0.3, 0.7)
DCL.grstrn(1)
DCL.grstrf
DCLExt.lon_ax
DCLExt.lat_ax
DCLExt.lon_ax('cside'=>'t')
DCLExt.lat_ax('cside'=>'r')
DCL.grfrm
DCL.grswnd(0.0, 360.0, -90.0, 90.0)
DCL.grsvpt(0.15, 0.95, 0.3, 0.7)
DCL.grstrn(1)
DCL.grstrf
DCLExt.lon_ax('dtick1'=>30, 'dtick2'=>90)
DCLExt.lat_ax('dtick1'=>10, 'dtick2'=>30)
DCLExt.lon_ax('cside'=>'t', 'dtick1'=>30, 'dtick2'=>90)
DCLExt.lat_ax('cside'=>'r', 'dtick1'=>10, 'dtick2'=>30)
DCL.grfrm
DCL.grswnd(-90.0, 90.0, 0.0, 360.0)
DCL.grsvpt(0.15, 0.95, 0.3, 0.7)
DCL.grstrn(1)
DCL.grstrf
DCLExt.lon_ax('yax'=>true,'dtick1'=>30, 'dtick2'=>90)
DCLExt.lat_ax('xax'=>true,'dtick1'=>10, 'dtick2'=>30)
DCLExt.lon_ax('yax'=>true,'cside'=>'r', 'dtick1'=>30, 'dtick2'=>90)
DCLExt.lat_ax('xax'=>true,'cside'=>'t', 'dtick1'=>10, 'dtick2'=>30)
DCL.grfrm
DCL.grswnd(90.0, -90.0, 360.0, 0.0)
DCL.grsvpt(0.15, 0.95, 0.3, 0.7)
DCL.grstrn(1)
DCL.grstrf
DCLExt.lon_ax('yax'=>true,'dtick1'=>30, 'dtick2'=>90)
DCLExt.lat_ax('xax'=>true,'dtick1'=>10, 'dtick2'=>30)
DCLExt.lon_ax('yax'=>true,'cside'=>'r', 'dtick1'=>30, 'dtick2'=>90)
DCLExt.lat_ax('xax'=>true,'cside'=>'t', 'dtick1'=>10, 'dtick2'=>30)
DCL.grfrm
DCL.grswnd(-90.0, 90.0, 1000.0, 1.0)
DCL.grsvpt(0.15, 0.95, 0.3, 0.7)
DCL.grstrn(2)
DCL.grstrf
DCL.ulpset('iytype',3)
DCL.ulylog('l', 3, 9)
DCL.ulylog('r', 3, 9)
DCLExt.lat_ax('xax'=>true,'dtick1'=>10, 'dtick2'=>30)
DCLExt.lat_ax('xax'=>true,'cside'=>'t', 'dtick1'=>10, 'dtick2'=>30)
DCL.grfrm
DCL.grswnd(-180.0, 180.0, -90.0, 90.0)
DCL.grsvpt(0.15, 0.95, 0.3, 0.7)
DCL.grstrn(1)
DCL.grstrf
DCLExt.lon_ax('dtick1'=>30, 'dtick2'=>90)
DCLExt.lat_ax('dtick1'=>10, 'dtick2'=>30)
DCLExt.lon_ax('cside'=>'t', 'dtick1'=>30, 'dtick2'=>90)
DCLExt.lat_ax('cside'=>'r', 'dtick1'=>10, 'dtick2'=>30)
DCL.grcls