require "numru/gphys"
require "numru/dcl"
require "numru/misc"
require "date"
require "numru/dclext_datetime_ax"
############################################################
=begin
=module NumRu::GGraph and others in ggraph.rb
==Index
* ((<module NumRu::GGraph>))
* ((<margin_info>))
Sets the strings to appear in the bottom margin.
* ((<title>))
Shows title by (({DCL.uxmttl('t',string,0.0)})).
Graphic methods such as ((<contour>)) calls this by default.
* ((<annotate>))
Show texts on the right margin of the viewport.
Graphic methods such as ((<contour>)) calls this by default.
* ((<fig>))
Define a figure by setting viewport, window, and coordinate transform
id (itr) from two 1D VArrays (({xax})) and (({yax})).
* ((<set_fig>))
Change the default option values for ((<fig>)).
* ((<next_fig>))
Set the option values effective only in the next call of ((<fig>))
(cleared then).
* ((<axes>))
Draw axes using (by default) info in (({xax})) and (({yax})) if non-nil.
* ((<set_axes>))
Change the default option values for ((<axes>)).
* ((<next_axes>))
Set the option values effective only in the next call of ((<axes>))
(cleared then).
* ((<map_trn?>))
Returns whether the current coordinate transformation is a map projection.
* ((<map>))
(For map projection) Draws map grid and/or lim and/or coast lines etc.
* ((<set_map>))
Change the default option values for ((<map>)).
* ((<next_map>))
Set the option values effective only in the next call of ((<map>))
* ((<line>))
Plot a poly-line by selecting the first dimension (with GPhys#first1D)
if (({gphys})) is more than 2D.
* ((<mark>))
Similar to ((<line>)) but plots marks instead of drawing a poly-line.
* ((<contour>))
Contour plot by selecting the first 2 dimensions (with GPhys#first2D)
if (({gphys})) is more than 3D.
* ((<set_contour>))
Set options for contour in general.
* ((<next_contour>))
Set options for contour in general, which is applied only to the next call.
* ((<set_contour_levels>))
Set contour levels for ((<contour>)) explicitly by values with the option (({levels})).
* ((<clear_contour_levels>))
Clear contour levels set by ((<set_contour_levels>)).
* ((<set_linear_contour_options>))
Change the default option values regarding linear contour level
setting in ((<contour>)).
* ((<next_linear_contour_options>))
Similar to ((<set_linear_contour_options>)) but the setting
is effective only for the next call of ((<contour>)).
* ((<tone>))
Color tone or shading by selecting the first 2 dimensions
(with GPhys#first2D) if (({gphys})) is more than 3D.
* ((<color_bar >)) Color bar
* ((<set_tone_levels>))
Set tone levels for ((<tone>)) explicitly by values.
* ((<set_tone>))
Set options for tone in general.
* ((<next_tone>))
Set options for tone in general, which is applied only to the next call.
* ((<clear_tone_levels>))
Clear tone levels set by ((<set_tone_levels>)).
* ((<set_linear_tone_options>))
Change the default option values regarding linear tone level
setting in ((<tone>)).
* ((<next_linear_tone_options>))
Similar to ((<set_linear_tone_options>)) but the setting
is effective only for the next call of ((<tone>)).
* ((<vector>)) 2-D vector plot using DCL_Ext::((<flow_vect>))
* ((<module NumRu::DCLExt>))
* ((<gl_set_params>))
Calls (({DCL.glpset})) multiple times (for each key and val of (({hash}))).
* ((<sg_set_params>))
Calls (({DCL.sgpset})) multiple times (for each key and val of (({hash}))).
* ((<sl_set_params>))
Calls (({DCL.slpset})) multiple times (for each key and val of (({hash}))).
* ((<sw_set_params>))
Calls (({DCL.swpset})) multiple times (for each key and val of (({hash}))).
* ((<uz_set_params>))
Calls (({DCL.uzpset})) multiple times (for each key and val of (({hash}))).
* ((<ul_set_params>))
Calls (({DCL.ulpset})) multiple times (for each key and val of (({hash}))).
* ((<uc_set_params>))
Calls (({DCL.ucpset})) multiple times (for each key and val of (({hash}))).
* ((<uu_set_params>))
Calls (({DCL.uupset})) multiple times (for each key and val of (({hash}))).
* ((<us_set_params>))
Calls (({DCL.uspset})) multiple times (for each key and val of (({hash}))).
* ((<ud_set_params>))
Calls (({DCL.udpset})) multiple times (for each key and val of (({hash}))).
* ((<ud_set_linear_levs>))
Set contour levels with a constant interval
* ((<ud_set_contour>))
Set contours of at specified levels.
* ((<ud_add_contour>))
Same as ((<ud_set_contour>)), but does not clear the contour levels that have
been set.
* ((<ue_set_params>))
Calls (({DCL.uepset})) multiple times (for each key and val of (({hash}))).
* ((<ue_set_linear_levs>))
Set tone levels with a constant interval
* ((<ue_set_tone>))
Set tone levels and patterns.
* ((<ue_add_tone>))
Same as ((<ue_set_tone>)), but does not clear the tone levels that have
been set.
* ((<ug_set_params>))
Calls (({DCL.ugpset})) multiple times (for each key and val of (({hash}))).
See ((<gl_set_params>)) for usage.
* ((<um_set_params>))
Calls (({DCL.umpset})) multiple times (for each key and val of (({hash}))).
* ((<set_unit_vect_options>))
* ((<next_unit_vect_options>))
* ((<unit_vect>)) Show the "unit vector", which indicate the vector scaling.
* ((<flow_vect>)) 2D Vector plot. Unlike (({DCL::ugvect})), scaling are made in term of the physical (or "U") coordinate.
* ((<flow_itr5>)) 2D Vector plot on the 2-dim polar coodinate.
* ((<color_bar>)) Color Bar
=module NumRu::GGraph
A graphic library for GPhys using RubyDCL.
This module uses GPhys but is not a part of it.
More specifically, even though this module is included in
the GPhys distribution, the class NumRu::GPhys knows nothing about it,
and GGraph accesses GPhys only though public methods.
So GGraph is not an insider, and you can make another graphic
library if you like.
==Module Functions
---margin_info(program=nil, data_source=nil, char_height=nil, date=nil, xl=0.0, xr=0.0, yb=nil, yt=0.0)
Sets the strings to appear in the bottom margin.
This method sets margin widths as DCL.slmgn(xl, xr, yb, yt),
and sets the 1st and 2nd margin strings as (({program}))
and (({data})).
ARGUMENTS
* program (String or nil) : String to be put on the left side in
the bottom margin. This is meant to represent the name of the
execution program. Therefore, if it is nil, the full path of
$0 is used.
* data_source (String or nil) : String to be put on the right side in
the bottom margin. This is meant to represent the data file name or the
directory in which the data are situated.
If nil, the full path of the current directory is used
(but nothing is shown if it is equal to the directory of the program).
* date (true, false, nil) : whether to put todays date --
true: always, nil: if program.length is short enough, false: never
* char_height (Float or nil) : height of the string to appear
in the V coordinate. If nil, internally defined.
* xl, xr, yb, yl (Float --- nil is available for yb) : margin
size in the V coordinate. The margin is set as
DCL.slmgn(xl, xr, yb, yt). If (({yb})) is nil, it is determined
internally as (({2.0 * char_height})).
---title(string)
Shows title by (({DCL.uxmttl('t',string,0.0)})).
Graphic methods such as ((<contour>)) calls this by default.
RETURN VALUE
* nil
---annotate(str_ary)
Show texts on the right margin of the viewport.
Graphic methods such as ((<contour>)) calls this by default.
ARGUMENTS
* str_ary (Array of String) :
RETURN VALUE
* nil
---fig(xax=nil, yax=nil, options=nil)
Define a figure by setting viewport, window, and coordinate transform
id (itr) from two 1D VArrays (({xax})) and (({yax})) (which are
not needed if a map projection is specified with the optional
parameter 'itr').
(({DCL.grfrm})) or (({DCL.grfig})) is called depending options provided.
ARGUMENTS
* xax (VArray): (Used only if not map projection)
A VArray representing the x (horizontal) coordinate
of the figure.
The x range of the window (UXMIN & UYMAX in DCL) are determined
with the max and min of (({xax.val})). By default,
the min and max values are assigned to the left and right
boundaries, respectively, but it is reversed if (({xax})) has
a 'positive' attribute and its value is 'down' etc (see (({options}))).
* yax (VArray): (Used only if not map projection)
Similar to (({xax})) but for the y (vertical) coordinate
of the figure.
* 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:
"new_frame" true # whether to define a new frame by DCL.grfrm
# (otherwise, DCL.grfig is called)
"no_new_fig" false # If true, neither DCL.grfrm nor DCL.grfig
# is called (overrides new_frame) -- Then, you need
# to call one of them in advance. Convenient to set
# DCL parameters that are reset by grfrm or grfig.
"itr" 1 # coordinate transformation number
"viewport" [0.2, 0.8, 0.2, 0.8] # [vxmin, vxmax, vymin, vymax]
"window" nil # (for itr<10,>50) [uxmin, uxmax, uymin, uymax],
# each element allowed nil (only for itr<5,>50)
"xreverse" "positive:down,units:hPa" # (for itr<10,>50) Assign
# max value to UXMIN and min value to UXMAX if
# condition is satisfied (nil:never, true:always,
# String: when an attibute has the value specified
# ("key:value,key:value,..")
"yreverse" "positive:down,units:hPa" # (for itr<10,>50) Assign
# max value to UYMIN and min value to UYMAX if
# condition is satisfied (nil:never, true:always,
# String: when an attibute has the value specified
# ("key:value,key:value,..")
"similar" nil # (for rectangular curvilinear coordinate only)
# 3-element float array for similar transformation
# in a rectangular curvilinear coordinate, which
# is fed in DCL:grssim:[simfac,vxoff,vyoff],where
# simfac and [vxoff,vyoff] represent scaling
# factor and origin shift, respectively.
"map_axis" nil # (for all map projections) 3-element float
# array to be fed in DCL::umscnt: [uxc, uxy, rot],
# where [uxc, uyc] represents the tangential point
# (or the pole at top side for cylindrical
# projections), and rot represents the rotation
# angle. If nil, internally determined. (units:
# degrees)
"map_radius" nil # (for itr>=20: conical/azimuhal map
# projections) raidus around the tangential point.
# (units: degrees)
"map_fit" nil # (Only for itr=10(cylindrical) and 11 (Mercator))
# true: fit the plot to the data window
# (overrides map_window and map_axis); false: do
# not fit (then map_window and map_axis are used);
# nil: true if itr==10, false if itr==11
"map_window" [-180, 180, -75, 75] # (for itr<20: cylindrical
# map projections) lon-lat window [lon_min,
# lon_max, lat_min, lat_max ] to draw the map
# (units: degres)
"help" false # show help message if true
RETURN VALUE
* nil
POSSIBLE EXCEPTIONS
* those from NumRu::DCL if any / TypeError if any
* options has a key that does not match any of the option names.
* options has a key that is ambiguous
---set_fig(options)
Change the default option values for ((<fig>)).
ARGUMENTS
* options (Hash) : The usage is the same as (({options})) for ((<fig>)).
RETURN VALUE
* a Hash containing the values replaced (the ones before calling this
method)
POSSIBLE EXCEPTIONS
* see ((<fig>)).
---next_fig(options)
Set the option values effective only in the next call of ((<fig>))
(cleared then).
These value are overwritten if specified explicitly in the next
call of ((<fig>)).
ARGUMENTS
* options (Hash) : The usage is the same as (({options})) for ((<fig>)).
RETURN VALUE
* nil
POSSIBLE EXCEPTIONS
* see ((<fig>)).
---axes(xax=nil, yax=nil, options=nil)
Draw axes using (by default) info in (({xax})) and (({yax})) if non-nil.
ARGUMENTS
* xax (nil or VArray): if non-nil, attributes 'long_name' and 'units'
are read to define (({xtitle})) and (({xunits})) (see below).
These are overwritten by explicitly specifying (({xtitle})) and
(({xunits})).
* yax (nil or VArray): if non-nil, attributes 'long_name' and 'units'
are read to define (({ytitle})) and (({yunits})) (see below).
These are overwritten by explicitly specifying (({ytitle})) and
(({yunits})).
* 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:
"xside" "tb" # Where to draw xaxes (combination of t, b and u)
"yside" "lr" # Where to draw yaxes (combination of l, r and u)
"xtitle" nil # Title of x axis (if nil, internally determined)
"ytitle" nil # Title of y axis (if nil, internally determined)
"xunits" nil # Units of x axis (if nil, internally determined)
"yunits" nil # Units of y axis (if nil, internally determined)
"xtickint" nil # Interval of x axis tickmark
# (if nil, internally determined)
"ytickint" nil # Interval of y axis tickmark
# (if nil, internally determined)
"xlabelint" nil # Interval of x axis label
# (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.
"time_ax" nil # Type of calendar-type time axis: nil (=> auto
# slection), false (do not use the time axis even
# if the units of the axis is a time one with since
# field), "h" (=> like nil, but always use the
# hour-resolving datetime_ax method in
# dclext_datetime_ax.rb), or "ymd" (=> like "h" but
# for y-m-d type using DCL.uc[xy]acl)
"help" false # show help message if true
RETURN VALUE
* nil
POSSIBLE EXCEPTIONS
* those from NumRu::DCL if any / TypeError if any
* options has a key that does not match any of the option names.
* options has a key that is ambiguous
---set_axes(options)
Change the default option values for ((<axes>)).
ARGUMENTS
* options (Hash) : The usage is the same as (({options})) for ((<axes>)).
RETURN VALUE
* a Hash containing the values replaced (the ones before calling this
method)
POSSIBLE EXCEPTIONS
* see ((<axes>)).
---next_axes(options)
Set the option values effective only in the next call of ((<axes>))
(cleared then).
These value are overwritten if specified explicitly in the next
call of ((<axes>)).
ARGUMENTS
* options (Hash) : The usage is the same as (({options})) for ((<axes>)).
RETURN VALUE
* nil
POSSIBLE EXCEPTIONS
* see ((<axes>)).
---sim_trn?
Returns whether the current coordinate transformation is a rectangular
curvelinear coordinate. A coordinate transformation must have been
established with ((<fig>)) or (({DCL::grstrf})).
Mainly for internal usage, but a user can use it too.
RETURN VALUE
* true or false
---polar_coordinate_boundaries(xax=nil,yax=nil)
Draw boundaries in a polar coordinate.
ARGUMENTS
* xax (VArray): Grid points of the radial coordinate.
* yax (VArray): Grid points of the azimuthal coordinate.
RETURN VALUE
* nil
---map_trn?
Returns whether the current coordinate transformation is a map projection.
A coordinate transformation must have been established
with ((<fig>)) or (({DCL::grstrf})).
Mainly for internal usage, but a user can use it too.
RETURN VALUE
* true or false
---map(options=nil)
(For map projection) Draws map grid and/or lim and/or coast lines etc.
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:
"lim" true # draw map lim (t or f)
"grid" true # draw map grid (t or f)
"vpt_boundary" false # draw viewport boundaries (f, t or
# 1,2,3.., representing the line width)
"wwd_boundary" false # draw worksation window boundaries (f, t
# or 1,2,3.., representing the line width)
"fill" false # fill the map if coast_world or coast_japan is
# true (t or f)
"coast_world" false # draw world coast lines (t or f)
"border_world" false # draw nation borders (t or f)
"plate_world" false # draw plate boundaries (t or f)
"state_usa" false # draw state boundaries of US (t or f)
"coast_japan" false # draw japanese coast lines (t or f)
"pref_japan" false # draw japanese prefecture boundaries (t or
# f)
"dgridmj" nil # the interval between the major lines of
# latitudes and longitudes. If nil, internally
# determined. (units: degrees) (this is a UMPACK
# parameter, which is nullified when uminit or
# grfrm is called)
"dgridmn" nil # the interval between the minor lines of
# latitudes and longitudes. If nil, internally
# determined. (units: degrees) (this is a UMPACK
# parameter, which is nullified when uminit or
# grfrm is called)
"help" false # show help message if true
RETURN VALUE
* nil
POSSIBLE EXCEPTIONS
* if called when the coordinate tansformation has not been established or
the transformation is not a map projection.
* those from NumRu::DCL if any / TypeError if any
* options has a key that does not match any of the option names.
* options has a key that is ambiguous
---set_map(options)
Change the default option values for ((<map>)).
ARGUMENTS
* options (Hash) : The usage is the same as (({options})) for ((<map>)).
RETURN VALUE
* a Hash containing the values replaced (the ones before calling this
method)
POSSIBLE EXCEPTIONS
* see ((<map>)).
---next_map(options)
Set the option values effective only in the next call of ((<map>))
(cleared then).
These value are overwritten if specified explicitly in the next
call of ((<map>)).
ARGUMENTS
* options (Hash) : The usage is the same as (({options})) for ((<map>)).
RETURN VALUE
* nil
POSSIBLE EXCEPTIONS
* see ((<map>)).
---line(gphys, newframe=true, options=nil)
Plot a poly-line by selecting the first dimension (with GPhys#first1D)
if (({gphys})) is more than 2D.
ARGUMENTS
* gphys (GPhys) : a GPhys whose data is plotted.
* newframe (true/false) : if true, calls ((<fig>)), ((<axes>)),
((<title>)), and ((<annotate>)) internally; if false, only
the poly-line is drawn (overlaid to the exiting figure).
* 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:
"title" nil # Title of the figure(if nil, internally
# determined)
"annotate" true # if false, do not put texts on the right
# margin even when newframe==true
"exchange" false # whether to exchange x and y axes
"index" 1 # line/mark index
"type" 1 # line type
"label" nil # if a String is given, it is shown as the label
"max" nil # maximum data value
"min" nil # minimum data value
"legend" nil # legend to annotate the line type and index. nil
# (defalut -- do not show); a String as the legend;
# true to use the name of the GPhys as the legend
"legend_vx" nil # (effective if legend) viewport x values of
# the lhs of the legend line (positive float); or
# nil for automatic settting (shown to the right of
# vpt); or move it to the left relatively (negtive
# float)
"legend_dx" nil # (effective if legend) length of the legend
# line
"legend_vy" nil # (effective if legend) viewport y value of the
# legend (Float; or nil for automatic settting)
"legend_size" nil # (effective if legend) character size of the
# legend
"help" false # show help message if true
RETURN VALUE
* nil
---mark(gphys, newframe=true, options=nil)
Similar to ((<line>)) but plots marks instead of drawing a poly-line.
ARGUMENTS
* gphys (GPhys) : a GPhys whose data is plotted.
* newframe (true/false) : if true, calls ((<fig>)), ((<axes>)),
((<title>)), and ((<annotate>)) internally; if false, only
the poly-line is drawn (overlaid to the exiting figure).
* 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:
"title" nil # Title of the figure(if nil, internally
# determined)
"annotate" true # if false, do not put texts on the right
# margin even when newframe==true
"exchange" false # whether to exchange x and y axes
"index" 1 # mark index
"type" 2 # mark type
"size" 0.01 # marks size
"max" nil # maximum data value
"min" nil # minimum data value
"legend" nil # legend to annotate the mark type, index, and
# size. nil (defalut -- do not to show); a String
# as the legend; true to use the name of the GPhys
# as the legend
"legend_vx" nil # (effective if legend) viewport x values of
# the lhs of the legend line (positive float); or
# nil for automatic settting (shown to the right of
# vpt); or move it to the left relatively (negtive
# float)
"legend_vy" nil # (effective if legend) viewport y value of the
# legend (Float; or nil for automatic settting)
"legend_size" nil # (effective if legend) character size of the
# legend
"help" false # show help message if true
RETURN VALUE
* nil
---tone_and_contour(gphys, newframe=true, options=nil)
Calls ((<tone>)) and ((<contour>)) successively. You can
specify the options for any of these.
NOTE:
* The option keys that are not existent in these methods
are simply neglected -- thus no spell-check-like feedback
is made, contrary to the indivisual call of contour or tone.
Also, only the help menu of ((<tone>)) can be shown.
* Requires numru-misc-0.0.6 or later.
---contour(gphys, newframe=true, options=nil)
Contour plot by selecting the first 2 dimensions (with GPhys#first2D)
if (({gphys})) is more than 3D.
Contour levels are determined as follows:
* contour levels are set in this method if not set by
((<set_contour_levels>)) or the option (({"levels"})) is specified
explicitly.
* When contour levels are set in this method, the option (({"levels"}))
has the highest precedence. If it is specified, options
(({"index"})), (({"line_type"})), (({"label"})), and (({"label_height"}))
are used.
If (({"levels"})) are not specified, contour levels with a linear
increment are set by using the options (({"min"})), (({"max"})),
(({"nlev"})), (({"interval"})), (({"nozero"})), (({"coloring"})),
(({"clr_min"})), and (({"clr_max"})), which are interpreted by
DCLExt::((<ud_set_linear_levs>)). The default values
of the linear level setting can be changed with
((<set_linear_contour_options>)).
ARGUMENTS
* gphys (GPhys) : a GPhys whose data is plotted.
* newframe (true/false) : if true, calls ((<fig>)), ((<axes>)) (or ((<map>))),
((<title>)), and ((<annotate>)) internally; if false, only
the poly-line is drawn (overlaid to the exiting figure).
* 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:
"title" nil # Title of the figure(if nil, internally
# determined)
"annotate" true # if false, do not put texts on the right
# margin even when newframe==true
"transpose" false # if true, exchange x and y axes
"exchange" false # same as the option transpose
"map_axes" false # [USE IT ONLY WHEN itr=10 (cylindrical)] If
# true, draws axes by temprarilly switching to
# itr=1 and calling GGraph::axes.
"keep" false # Use the contour levels used previously
"min" nil # minimum contour level
"max" nil # maximum contour level
"nlev" nil # number of levels
"interval" nil # contour interval
"nozero" nil # delete zero contour
"coloring" false # set color contours with ud_coloring
"clr_min" 13 # (if coloring) minimum color number for the
# minimum data values
"clr_max" 99 # (if coloring) maximum color number for the
# maximum data values
"help" false # show help message if true
"levels" nil # contour levels (Array/NArray of Numeric)
"index" nil # (if levels) line index(es) (Array/NArray of
# integers, Integer, or nil)
"line_type" nil # (if levels) line type(s) (Array/NArray of
# integers, Integer, or nil)
"label" nil # (if levels) contour label(s) (Array/NArray of
# String, String, true, false, nil). nil is
# recommended.
"label_height" nil # (if levels) label height(s)
# (Array/NArray of Numeric, Numeric, or nil).
# nil is recommended.
RETURN VALUE
* nil
---set_contour_levels(options)
Set contour levels for ((<contour>)) explicitly by values with the option (({levels})).
ARGUMENTS
* options (Hash) : options to change the default behavior.
The option (({"levels"})) is mandatory (so it is not optional!).
Supported options are (({"levels"})), (({"index"})),
(({"line_type"})), (({"label"})), and (({"label_height"})).
See ((<contour>)) for their description.
---clear_contour_levels
Clear contour levels set by ((<set_contour_levels>)).
---set_linear_contour_options(options)
Change the default option values regarding linear contour level
setting in ((<contour>)).
ARGUMENTS
* options (Hash) : The usage is the same as (({options}))
for ((<contour>)) but supported options here are limited to
(({"min"})), (({"max"})), (({"nlev"})), (({"interval"})),
(({"nozero"})), (({"coloring"})), (({"clr_min"})), and (({"clr_max"})).
RETURN VALUE
* a Hash containing the values replaced (the ones before calling this
method)
---next_linear_contour_options(options)
Similar to ((<set_linear_contour_options>)) but the setting
is effective only for the next call of ((<contour>)).
---tone(gphys, newframe=true, options=nil)
Color tone or shading by selecting the first 2 dimensions
(with GPhys#first2D) if (({gphys})) is more than 3D.
Tone levels are determined as follows:
* Tone levels are set in this method if not set by
((<set_tone_levels>)) or the option (({"levels"})) (and
optionally, (({"patterns"}))) is (are) specified explicitly.
* When contour levels & patterns are set in this method,
* (({"levels"})) has the highest precedence. If it is specified,
tone levels and patterns are determined by DCLExt::((<ue_set_tone>)).
Here, tone patterns can be specified with the option (({"patterns"})).
* Currently, option (({"patterns"})) is effective only if (({"levels"}))
is specified. Otherwise, it is ignored and patterns are
determined internally (by using DCL.uegtlb).
* If not, a linear tone levels are set if (({"ltone"=true}))
(this is the default), or shading is made if (({"ltone"=false})).
Shading is determined by following the parameters in the UDPACK
in DCL. Therefore, coloring is made if DCL.udpget('ltone')==true
regardless the option (({"ltone"=false})) here.
When linear levels are set in this method, options
(({"min"})), (({"max"})), (({"nlev"})), and (({"interval"}))
are used if specified, which are interpreted by
DCLExt::((<ue_set_linear_levs>)).
Their default values can be changed by
((<set_linear_tone_options>)).
ARGUMENTS
* gphys (GPhys) : a GPhys whose data is plotted.
* newframe (true/false) : if true, calls ((<fig>)), ((<axes>)) (or ((<map>))),
((<title>)), and ((<annotate>)) internally; if false, only
the poly-line is drawn (overlaid to the exiting figure).
* 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:
"title" nil # Title of the figure(if nil, internally
# determined)
"annotate" true # if false, do not put texts on the right
# margin even when newframe==true
"ltone" true # Same as udpack parameter ltone
"tonf" false # Use DCL.uetonf instead of DCL.uetone
"tonc" false # Use DCL.uetonc instead of DCL.uetone
"clr_min" nil # if an integer (in 10..99) is specified, used as
# the color number for the minimum data values.
# (the same can be done by setting the uepack
# parameter "icolor1")
"clr_max" nil # if an integer (in 10..99) is specified, used as
# the color number for the maximum data values.
# (the same can be done by setting the uepack
# parameter "icolor2")
"transpose" false # if true, exchange x and y axes
"exchange" false # same as the option transpose
"map_axes" false # [USE IT ONLY WHEN itr=10 (cylindrical)] If
# true, draws axes by temprarilly switching to
# itr=1 and calling GGraph::axes.
"keep" false # Use the tone levels and patterns used previously
"min" nil # minimum tone level
"max" nil # maximum tone level
"nlev" nil # number of levels
"interval" nil # contour interval
"help" false # show help message if true
"levels" nil # tone levels (Array/NArray of Numeric). Works
# together with patterns
"patterns" nil # tone patters (Array/NArray of Numeric). Works
# together with levels
RETURN VALUE
* nil
---color_bar (options=nil)
* Descroption:
Draws color bars. Calls (({DCLext.color_bar})).
---set_tone_levels(options)
Set tone levels for ((<tone>)) explicitly by values.
ARGUMENTS
* options (Hash) : options to change the default behavior.
Supported options are (({"levels"})) and (({"patterns"})).
Both of them must be specified explicitly (so they are
not optional!).
---clear_tone_levels
Clear tone levels set by ((<set_tone_levels>)).
---set_linear_tone_options(options)
Change the default option values regarding linear tone level
setting in ((<tone>)).
ARGUMENTS
* options (Hash) : The usage is the same as (({options}))
for ((<tone>)) but supported options here are limited to
(({"min"})), (({"max"})), (({"nlev"})), and (({"interval"})).
RETURN VALUE
* a Hash containing the values replaced (the ones before calling this
method)
---next_linear_tone_options(options)
Similar to ((<set_linear_tone_options>)) but the setting
is effective only for the next call of ((<tone>)).
---vector(fx, fy, newframe=true, options=nil)
2-D vector plot using DCL_Ext::((<flow_vect>)),
which scales vectors in physical ("U") coordinates.
ARGUMENTS
* fx, fy (GPhys) : represent vectors
* newframe (true/false) : if true, calls ((<fig>)), ((<axes>)) (or ((<map>))),
((<title>)), and ((<annotate>)) internally; if false, only
the poly-line is drawn (overlaid to the exiting figure).
* 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:
"title" nil # Title of the figure(if nil, internally
# determined)
"annotate" true # if false, do not put texts on the right
# margin even when newframe==true
"transpose" false # if true, exchange x and y axes
"exchange" false # same as the option transpose
"map_axes" false # [USE IT ONLY WHEN itr=10 (cylindrical)] If
# true, draws axes by temprarilly switching to
# itr=1 and calling GGraph::axes.
"flow_vect" true # If true, use DCLExt::flow_vect to draw
# vectors; otherwise, DCL::ugvect is used.
"flow_itr5" false # If true, use DCLExt::flow_itr5 to draw
# vectors; otherwise, DCLExt::flow_vect or
# DCL::ugvect is used.
"keep" false # Use the same vector scaling as in the previous
# call. -- Currently, works only when "flow_vect"
# is true
"xintv" 1 # (Effective only if flow_vect) interval of data
# sampling in x
"yintv" 1 # (Effective only if flow_vect) interval of data
# sampling in y
"factor" 1.0 # (Effective only if flow_vect) scaling factor to
# strech/reduce the arrow lengths
"unit_vect" false # Show the unit vector
"max_unit_vect" false # (Effective only if flow_vect &&
# unit_vect) If true, use the maximum arrows to
# scale the unit vector; otherwise, normalize in V
# coordinate.
"help" false # show help message if true
RETURN VALUE
* nil
=module NumRu::DCLExt
Collection of various compound DCL functions for convenience.
This module is to be separated but temporarily included in ggraph.rb
while it is premature.
==Index
MATH1
* ((<glpack>))
GRPH1
* ((<sgpack>))
* ((<slpack>))
* ((<swpack>))
GRPH2
* ((<uzpack>))
* ((<ulpack>))
* ((<ucpack>))
* ((<uupack>))
* ((<uspack>))
* ((<udpack>))
* ((<uepack>))
* ((<ugpack>))
* ((<umpack>))
==Module Functions
===glpack
---gl_set_params(hash)
Calls (({DCL.glpset})) multiple times (for each key and val of (({hash}))).
ARGUMENTS
* hash (Hash) : combinations of parameter names and values for udpset
RETURN VALUE
* a Hash containing the parameter names and their old values that were
replaced.
EXAMPLES
* You can modify parameters temporarily as follows.
before = DCLExt.gl_set_params({'lmiss'=>true,'rmiss'=>9999.0})
....
DCLExt.gl_set_params(before) # reset the change
===sgpack
---sg_set_params(hash)
Calls (({DCL.sgpset})) multiple times (for each key and val of (({hash}))).
See ((<gl_set_params>)) for usage.
===slpack
---sl_set_params(hash)
Calls (({DCL.slpset})) multiple times (for each key and val of (({hash}))).
See ((<gl_set_params>)) for usage.
===swpack
---sw_set_params(hash)
Calls (({DCL.swpset})) multiple times (for each key and val of (({hash}))).
See ((<gl_set_params>)) for usage.
===uzpack
---uz_set_params(hash)
Calls (({DCL.uzpset})) multiple times (for each key and val of (({hash}))).
See ((<gl_set_params>)) for usage.
===ulpack
---ul_set_params(hash)
Calls (({DCL.ulpset})) multiple times (for each key and val of (({hash}))).
See ((<gl_set_params>)) for usage.
===ucpack
---uc_set_params(hash)
Calls (({DCL.ucpset})) multiple times (for each key and val of (({hash}))).
See ((<gl_set_params>)) for usage.
===uupack
---uu_set_params(hash)
Calls (({DCL.uupset})) multiple times (for each key and val of (({hash}))).
See ((<gl_set_params>)) for usage.
===uspack
---us_set_params(hash)
Calls (({DCL.uspset})) multiple times (for each key and val of (({hash}))).
See ((<gl_set_params>)) for usage.
===udpack
---ud_set_params(hash)
Calls (({DCL.udpset})) multiple times (for each key and val of (({hash}))).
ARGUMENTS
* hash (Hash) : combinations of parameter names and values for udpset
RETURN VALUE
* a Hash containing the parameter names and their old values that were
replaced.
EXAMPLES
* You can modify parameters temporarily as follows.
before = DCLExt.ud_set_params('indxmj'=>4,'lmsg'=>false)
DCL.udcntz(data)
DCLExt.ud_set_params(before) # reset the change
---ud_set_linear_levs(v, options)
Set contour levels with a constant interval
ARGUMENTS
* v : Data values to be fed to udcnt[rz]
* options (Hash) : option specification by keys and values. Available
options are
name default value description
'min' nil minimum contour value (Numeric)
'max' nil maximum contour value (Numeric)
'nlev' nil number of levels (Integer)
'interval' nil contour interval (Numeric)
'nozero' nil delete zero contour (true/false)
'coloring' false set color contours with ud_coloring (true/false)
'clr_min' 13 (if coloring) minimum color id (Integer)
'clr_max' 99 (if coloring) maximum color id (Integer)
Here, (({interval})) has a higher precedence over (({nlev})).
Since all the default values are nil, only those explicitly specified
are interpreted. If no option is provided, the levels generated will
be the default ones set by udcnt[rz] without any level specification.
---ud_set_contour(levels,index=nil,line_type=nil,label=nil,label_height=nil)
Set contours of at specified levels.
Normally you do not have to specify (({label})) and (({label_height})).
It calls DCL.udsclv for each level. So the arguments are basically
the same as DCL.udsclv, but only levels are mandatory here.
ARGUMENTS
* levels (Array, NArray, or Numeric) : contour levels to be set.
If Numeric, a single level is set.
* index (Array of integers, Integer, or nil) :
index(es) of the contours. If it is an Array and its length is
shorter than that of (({levels})), the same Array is repeated (so
for instance [1,1,3] is interpreted as [1,1,3,1,1,3,1,1,3,...]).
If it is a single Integer, all the contour will have the same index.
If nil, the value of 'indxmn' is used.
* line_type (Array of integers, Integer, or nil) :
line type(s) of the contours. If it is an Array and its length is
shorter than that of (({levels})), the same Array is repeated.
the length must agree with that of (({levels})).
If it is a single Integer, all the contour will have the same type.
If nil, set to be 1.
* label (Array of String, String, true, false, nil) :
Label(s) of the contours. If it is an Array and its length is
shorter than that of (({levels})), the same Array is repeated.
the length must agree with that of (({levels})).
If it is a single String, all the contour will have the same label.
If true, all the contours will have the labels representing the levels.
If false, no label will be drawn (set to "").
If nil, same as true for the contours whose index is equal to "INDXMJ",
and same as false otherwise.
* label_height (Array of Numeric, Numeric, or nil) :
Heigh of Labels. Normally you do not have to use this.
If it is an Array and its length is
shorter than that of (({levels})), the same Array is repeated.
If nil, the default value ("RSIZEL") is used for non-empty labels.
If a single Numeric, the same value is used for all the contours.
Note that it is recommended to not to use this parameter but
use DCL.udpset('RZISEL'. label_height), since a positive value
here always means to draw labels even when the label is empty.
RETURN VALUE
* nil
---ud_add_contour(levels,index=nil,line_type=nil,label=nil,label_height=nil)
Same as ((<ud_set_contour>)), but does not clear the contour levels that have
been set.
===uepack
---ue_set_params(hash)
Calls (({DCL.uepset})) multiple times (for each key and val of (({hash}))).
See ((<gl_set_params>)) for usage.
---ue_set_linear_levs(v, options)
Set tone levels with a constant interval
ARGUMENTS
* v : Data values to be fed to udcnt[rz]
* options (Hash) : option specification by keys and values. Available
options are
name default value description
'min' nil minimum tone level (Numeric)
'max' nil maximum tone level (Numeric)
'nlev' nil number of levels (Integer)
'interval' nil tone-level interval (Numeric)
Here, (({interval})) has a higher precedence over (({nlev})).
Since all the default values are nil, only those explicitly specified
are interpreted. If no option is provided, the levels generated will
be the default ones set by udcnt[rz] without any level specification.
---ue_set_tone(levels, patterns)
Set tone levels and patterns.
patterns are set between levels as follows:
when (levels.length == patterns.length+1)
levels[0] | levels[1] | levels[2] ... | levels[-2] | levels[-1]
patterns[0] patterns[1] ... patterns[-2] patterns[-1]
when (levels.length == patterns.length)
levels[0] | levels[1] | levels[2] ... | levels[-1] | +infty
patterns[0] patterns[1] ... patterns[-2] patterns[-1]
when (levels.length == patterns.length-1)
-infty | levels[0] | levels[1] ... | levels[-1] | +infty
patterns[0] patterns[1] ... patterns[-2] patterns[-1]
else
error (exception raised)
ARGUMENTS
* levels (Array or NArray of Numeric) : tone levels. Its length must be
either 1 larger than, equal to, or 1 smaller than the length of patterns
* patterns (Array or NArray of Numeric) : tone patterns
RETURN VALUE
* nil
---ue_add_tone(levels, patterns)
Same as ((<ue_set_tone>)), but does not clear the tone levels that have
been set.
===ugpack
---ug_set_params(hash)
Calls (({DCL.ugpset})) multiple times (for each key and val of (({hash}))).
See ((<gl_set_params>)) for usage.
===umpack
---um_set_params(hash)
Calls (({DCL.umpset})) multiple times (for each key and val of (({hash}))).
See ((<gl_set_params>)) for usage.
==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 )
Show the "unit vector", which indicate the vector scaling.
ARGUMENTS
* vxfxratio (Float) : (V cood length)/(actual length) in x
* vyfyratio (Float) : (V cood length)/(actual length) in y
* fxunit (Float) : If specified, x unit vect len
* fyunit (Float) : If specified, y unit vect len
* 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:
"vxunit" 0.05 # x unit vect len in V coord. Used only when
# fxunit is omitted (default)
"vyunit" 0.05 # y unit vect len in V coord. Used only when
# fyunit is omitted (default)
"vxuloc" nil # Starting x position of unit vect
"vyuloc" nil # Starting y position of unit vect
"vxuoff" 0.05 # Specify vxuloc by offset from right-bottom
# corner
"vyuoff" 0.0 # Specify vyuloc by offset from right-bottom
# corner
"inplace" true # Whether to print labels right by the unit
# vector (true) or below the x axis (false)
"rsizet" nil # Label size(default taken from uz-parameter
# 'rsizel1')
"index" 3 # Line index of the unit vector
"help" false # show help message if true
---set_unit_vect_options(options)
Change the default option values for ((<unit_vect>)).
---next_unit_vect_options(options)
Set the option values effective only in the next call of ((<unit_vect>))
---flow_vect( fx, fy, factor=1.0, xintv=1, yintv=1)
2D Vector plot. Unlike (({DCL::ugvect})), scaling are made in term of the physical (or "U") coordinate.
This method is meant to substitute (({DCL::ugvect})). The scaling
is made in terms of the U coordinate. This method is suitable to
show vectors such as velocity, since the arrow direction represets
the direction in the U coordinate. Also, one can re-scale the
vector length easily by using the argument (({factor})).
Currently, this method is not compatible with map projection,
since it calls (({DCL::ugvect})) internally.
ARGUMENTS
* fx, fy (2D NArray or Array) : the vector field.
* factor (Integer) : factor to change the arrow length.
By default, arrows are scaled so that the longest one
match the grid interval.
* xintv, yintv (Interger) : interval to thin out (({fx})) and (({fy})),
respectively. Useful if the grid points are too many.
---flow_itr5( fx, fy, factor=1.0, unit_vect=false )
2D Vector plot on the polar coodinate.
This method just perform rotatation of the vector in U-coordinate
to N-coordinate and passed to DCL.ugvect.
ARGUMENTS
* fx, fy (2D GPhys) : the vector field.
* factor (Integer) : factor for scaling in ugvect. When it equals 1,
vector field will be scaled in DCL.ugvect automatically.
* unit_vect() : Show the unit vector
===Color bars
---set_color_bar_options(options)
To set options of ((<color_bar>)) effective in the rest.
---color_bar(options=nil)
* Descroption:
Draws color bars
* Example
Here is the simplest case, where no argument is given to color_bar.
DCL.uetone(hoge)
DCL.usdaxs
...
DCL.color_bar
This draws a color bar by using the levels and tone patterns(colors)
set previously. There are many parameters you can set manually,
as introduced below:
* Description of options
option name default value # description:
"levels" nil # tone levels (if omitted, latest ones are used)
"patterns" nil # tone patterns (~colors) (if omitted, latest
# ones are used)
"voff" nil # how far is the bar from the viewport in the V
# coordinate
"vcent" nil # center position of the bar in the V coordinate
# (VX or VY)
"vlength" 0.3 # bar length in the V coordinate
"vwidth" 0.02 # bar width in the V coordinate
"landscape" false # if true, horizonlly long (along x axes)
"portrait" true # if true, vertically long (along y axes)
"left" false # place the bar in the left (effective if
# portrait)
"top" false # place the bar at the top (effective if portrait)
"tickintv" 1 # 0,1,2,3,.. to specify how frequently the
# dividing tick lines are drawn (0: no tick lines,
# 1:every time, 2:ever other:,...)
"labelintv" nil # 1,2,3,.. to specify how frequently labels are
# drawn (1:every time, 2:ever other:,... default:
# internally determined)
"charfact" 0.9 # factor to change the label character size
# (relative to 'rsizel1')
"log" false #
"constwidth" false # if true, each color is drawn with the same width
"index" nil # line index of bar frame
# (so far, valid only when "constwidth")
"help" false # show help message if true
=end
############################################################
module NumRu
module DCLExt
# to be included in the RubyDCL distribution
module_function
#<<< for many packages >>>
%w!gl sg sl sw uz ul uc uu us ud ue ug um!.each do |pkg|
eval <<-EOS, nil, __FILE__, __LINE__+1
def #{pkg}_set_params(hash)
before = Hash.new
hash.each{|k,v|
before[k]=DCL.#{pkg}pget(k)
if(v.is_a? String) then
DCL.#{pkg}cset(k,v)
else
DCL.#{pkg}pset(k,v)
end
}
before
end
EOS
end
#<<< module data >>>
@@empty_hash = Hash.new
#<<< udpack >>>
def ud_coloring(clr_min=13, clr_max=99)
# change the colors of existing contours to make a gradation
# (rainbow colors with the default color map).
nlev = DCL.udqcln
cont_params = Array.new
for i in 1..nlev
cont_params.push( DCL.udqclv(i) ) # => [zlev,indx,ityp,clv,hl]
end
DCL.udiclv # clear the contours
colors = clr_min +
NArray.int(nlev).indgen! * (clr_max-clr_min) / nlev
cont_params.sort!
for i in 0...nlev
cont_params[i][1] += colors[i]*10 # indx += colors[i]*10
DCL.udsclv(*cont_params[i])
end
end
def ud_set_linear_levs(v, options=nil)
#Accepted options
# name default description
# 'min' nil minimum contour value (Numeric)
# 'max' nil maximum contour value (Numeric)
# 'nlev' nil number of levels (Integer)
# 'interval' nil contour interval (Numeric)
# 'nozero' false delete zero contour (true/false)
# 'coloring' false set color contours with ud_coloring (true/false)
# 'clr_min' 13 (if coloring) minimum color number for the
# maximum data values (Integer)
# 'clr_max' 99 (if coloring) maximum color number for the
# maximum data values (Integer)
options = @@empty_hash if !options
raise TypeError, "options must be a Hash" if !options.is_a?(Hash)
min = options['min']
max = options['max']
nlev = options['nlev']
interval = options['interval']
nozero = options['nozero']
if interval
dx = interval
elsif nlev
dx = -nlev
else
dx = 0
end
if min || max
min = v.min if !min
max = v.max if !max
DCL.udgcla(min, max, dx)
else
DCL.udgclb(v, dx)
end
if nozero
DCL.uddclv(0.0)
end
if options['coloring']
clr_min = ( options['clr_min'] || 13 )
clr_max = ( options['clr_max'] || 99 )
ud_coloring( clr_min, clr_max )
end
end
def ud_set_contour(*args)
DCL.udiclv
ud_add_contour(*args)
end
def ud_add_contour(levels,index=nil,line_type=nil,label=nil,label_height=nil)
# < check levels >
case levels
when Array, NArray
# This is expected. Nothing to do.
when Numric
levels = [levels]
else
raise ArgumentError, "invalid level specification (#{levels})"
end
nlev = levels.length
# < index >
index = index.to_a if index.is_a?(NArray)
case index
when Array
raise ArgumentError, "index is an empty array" if index.length == 0
while (index.length < nlev )
index += index
end
when Numeric
index = [index]*nlev
when nil
index = [DCL.udpget('indxmn')]*nlev
else
raise ArgumentError, "unsupported index type (#{index.class})"
end
# < line_type >
line_type = line_type.to_a if line_type.is_a?(NArray)
case line_type
when Array
raise ArgumentError, "line_type is an empty array" if line_type.length == 0
while (line_type.length < nlev )
line_type += line_type
end
when Numeric
line_type = [line_type]*nlev
when nil
line_type = [1]*nlev
else
raise ArgumentError, "unsupported index type (#{index.class})"
end
# < label >
label = label.to_a if label.is_a?(NArray)
case label
when Array
raise ArgumentError, "label is an empty array" if label.length == 0
while (label.length < nlev )
label += label
end
when String
label = [label]*nlev
when false
label = [""]*nlev
when true
label = (0...nlev).collect{|i|
DCL.udlabl(levels[i])
}
when nil
indxmj = DCL.udpget('indxmj')
label = (0...nlev).collect{|i|
if index[i]==indxmj
DCL.udlabl(levels[i])
else
""
end
}
else
raise ArgumentError, "unsupported index type (#{index.class})"
end
# < label_height >
label_height = label_height.to_a if label_height.is_a?(NArray)
case label_height
when Array
raise ArgumentError, "label_height is an empty array" if label_height.length == 0
while (label_height.length < nlev )
label_height += label_height
end
when Numeric
label_height = [label_height]*nlev
when nil
label_height = label.collect{|lv| lv=="" ? 0.0 : DCL.udpget('rsizel')}
else
raise ArgumentError, "unsupported index type (#{index.class})"
end
# < set levels >
for i in 0...nlev
DCL.udsclv(levels[i],index[i],line_type[i],label[i],label_height[i])
end
nil
end
#<<< uepack >>>
def ue_set_linear_levs(v, options=nil)
# 'min' nil minimum tone level (Numeric)
# 'max' nil maximum tone level (Numeric)
# 'nlev' nil number of levels (Integer)
# 'interval' nil tone-level interval (Numeric)
options = @@empty_hash if !options
raise TypeError, "options must be a Hash" if !options.is_a?(Hash)
min = options['min']
max = options['max']
nlev = options['nlev']
interval = options['interval']
if interval
dx = interval
elsif nlev
dx = -nlev
else
dx = 0
end
if min || max
min = v.min if !min
max = v.max if !max
DCL.uegtla(min, max, dx)
else
DCL.uegtlb(v, dx)
end
end
def ue_set_tone(levels, patterns)
DCL.ueitlv
ue_add_tone(levels, patterns)
end
def ue_add_tone(levels, patterns)
# < check types >
if !levels.is_a?(Array) && !levels.is_a?(NArray)
raise TypeError, "levels: Array or NArray expected (#{levels.inspect})"
end
if !patterns.is_a?(Array) && !patterns.is_a?(NArray)
raise TypeError, "patterns: Array or NArray expected (#{patterns.inspect})"
end
# < set levels >
nlev = levels.length
npat = patterns.length
case (nlev - npat)
when 1
for i in 0...nlev-1
DCL.uestlv(levels[i],levels[i+1],patterns[i])
end
when 0
for i in 0...nlev-1
DCL.uestlv(levels[i],levels[i+1],patterns[i])
end
DCL.uestlv(levels[-1],DCL.glpget('rmiss'),patterns[-1])
when -1
DCL.uestlv(DCL.glpget('rmiss'),levels[0],patterns[0])
for i in 1...nlev
DCL.uestlv(levels[i-1],levels[i],patterns[i])
end
DCL.uestlv(levels[-1],DCL.glpget('rmiss'),patterns[-1])
else
raise ArgumentError,
"lengths of levels(#{nlev}) and patterns(#{npat}) are inconsistent"
end
nil
end
############################################################
# 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)
# truncate (round) a floating number with the number digits
# specified by "order".
# e.g., if order=3, -0.012345 => -0.0123; 6.6666 => 6.67
exponent = 10**(-Math::log10(float.abs).floor+order-1)
(float * exponent).round.to_f/exponent
end
@@unit_vect_options = Misc::KeywordOptAutoHelp.new(
['vxunit', 0.05, "x unit vect len in V coord. Used only when fxunit is omitted (default)"],
['vyunit', 0.05, "y unit vect len in V coord. Used only when fyunit is omitted (default)"],
['vxuloc', nil, "Starting x position of unit vect"],
['vyuloc', nil, "Starting y position of unit vect"],
['vxuoff', 0.05, "Specify vxuloc by offset from right-bottom corner"],
['vyuoff', 0.0, "Specify vyuloc by offset from right-bottom corner"],
['inplace',true, "Whether to print labels right by the unit vector (true) or below the x axis (false)"],
['rsizet', nil, "Label size(default taken from uz-parameter 'rsizel1')"],
['index', 3," Line index of the unit vector"]
)
def set_unit_vect_options(options)
@@unit_vect_options.set(options)
end
@@next_unit_vect_options = nil
def next_unit_vect_options(options)
if options.is_a?(Hash)
@@next_unit_vect_options = options
else
raise TypeError,"Hash expected"
end
nil
end
def unit_vect( vxfxratio, # (V cood length)/(actual length) in x
vyfyratio, # (V cood length)/(actual length) in y
fxunit=nil, # If specified, x unit vect len
fyunit=nil, # If specified, y unit vect len
options=nil )
#< options >
if @@next_unit_vect_options
options = ( options ? @@next_unit_vect_options.update(options) :
@@next_unit_vect_options )
@@next_unit_vect_options = nil
end
opt = @@unit_vect_options.interpret(options)
vxunit = opt['vxunit']
vyunit = opt['vyunit']
vxuloc = opt['vxuloc']
vyuloc = opt['vyuloc']
rsizet = opt['rsizet']
index = opt['index']
#< unit vector >
if fxunit
vxunit = vxfxratio * fxunit
else
fxunit = vxunit / vxfxratio
end
if fyunit
vyunit = vyfyratio * fyunit
else
fyunit = vyunit / vyfyratio
end
fxunit = __truncate( (uxusv=fxunit) )
fyunit = __truncate( (uyusv=fyunit) )
vxunit = vxunit * (fxunit/uxusv)
vyunit = vyunit * (fyunit/uyusv)
if !(vxuloc && vyuloc)
vx0,vx1,vy0,vy1 = DCL.sgqvpt
vxuloc = vx1 + opt['vxuoff'] if !vxuloc
vyuloc = vy0 + opt['vyuoff'] if !vyuloc
end
DCL.sglazv( vxuloc, vyuloc, vxuloc+vxunit, vyuloc, 1, index )
DCL.sglazv( vxuloc, vyuloc, vxuloc, vyuloc+vyunit, 1, index )
#< labelling >
sfxunit = sprintf("%.2g",fxunit)
sfyunit = sprintf("%.2g",fyunit)
rsizet = DCL.uzpget('rsizel1') if !rsizet
if opt['inplace']
DCL.sgtxzv(vxuloc, vyuloc-1.2*rsizet,
sfxunit, rsizet, 0, -1, index)
DCL.sgtxzv(vxuloc+1.2*rsizet, vyuloc+0.5*rsizet,
sfyunit, rsizet, 90, -1, index)
else
msg= "UNIT VECTOR X:#{sfxunit} Y:#{sfyunit}"
before = uz_set_params({'rsizec1'=>rsizet})
DCL.uxsttl('b',' ',0.0)
DCL.uxsttl('b',msg,0.0)
uz_set_params(before)
end
end
def flow_vect( fx, fy, factor=1.0, xintv=1, yintv=1,
vxfxratio=nil, vyfyratio=nil)
raise ArgumentError,"Expect 2D arrays" if fx.rank != 2 || fy.rank != 2
raise ArgumentError,"fx.shape != fy.shape" if fx.shape != fy.shape
raise ArgumentError,"xintv must be a positive integer" if xintv < 0
raise ArgumentError,"yintv must be a positive integer" if yintv < 0
nx, ny = fx.shape
if xintv >= 2
idx = NArray.int(nx/xintv).indgen!*xintv # [0,xintv,2*xintv,..]
fx = fx[idx, true]
fy = fy[idx, true]
end
if yintv >= 2
idx = NArray.int(ny/yintv).indgen!*yintv # [0,yintv,2*yintv,..]
fx = fx[true, idx]
fy = fy[true, idx]
end
nx, ny = fx.shape # again, because of xintv & yintv
vx0,vx1,vy0,vy1 = DCL.sgqvpt
wnd = DCL.sgqwnd
if wnd.include?(DCL.glrget('rundef'))
ux0,ux1,uy0,uy1 = DCL.sgqtxy
else
ux0,ux1,uy0,uy1 = wnd
end
dvx = (vx1-vx0)/nx
dvy = (vy1-vy0)/ny
ax = (vx1-vx0)/(ux1-ux0) # factor to convert from U to V coordinate
ay = (vy1-vy0)/(uy1-uy0) # factor to convert from U to V coordinate
fxmx = fx.abs.max
fymx = fy.abs.max
raise "fx has no data or all zero" if fxmx == 0
raise "fy has no data or all zero" if fymx == 0
cn = [ dvx/(ax*fxmx), dvy/(ay*fymx) ].min # normarization constant
vxfxratio = factor*cn*ax if !vxfxratio
vyfyratio = factor*cn*ay if !vyfyratio
before = ug_set_params( {'LNRMAL'=>false, 'LMSG'=>false,
'XFACT1'=>1.0, 'YFACT1'=>1.0} )
DCL.ugvect( vxfxratio*fx, vyfyratio*fy )
ug_set_params( before )
unit_vect_info = [ vxfxratio, vyfyratio, fxmx, fymx ]
return unit_vect_info
end
def flow_itr5( gpx, gpy, factor=1.0, unit_vect=false )
raise ArgumentError,"Expect 2D arrays" if gpx.rank != 2 || gpy.rank != 2
raise ArgumentError,"gpx.shape != gpy.shape" if gpx.shape != gpy.shape
raise "Transform. No. should be 5" if DCL.sgpget('itr') != 5
theta = gpx.coord(1) / 180 * Math::PI
theta = theta.reshape(1,theta.shape[0])
vx = gpx * theta.cos - gpy * theta.sin # UC component -> VC
vy = gpx * theta.sin + gpy * theta.cos # UC component -> VC
DCL.sglset('LCLIP',false)
before1 = DCLExt.ug_set_params(
{'LUNIT'=>true, 'LUMSG'=>true} ) if unit_vect
before2 = DCLExt.ug_set_params(
{'LNRMAL'=>false,
'XFACT1'=>factor, 'YFACT1'=>factor} ) if factor != 1.0
DCL.ugvect( vx.val, vy.val )
if unit_vect
uxunit = sprintf("%.2g",DCL.ugrget('UXUNIT'))
uyunit = sprintf("%.2g",DCL.ugrget('UXUNIT'))
vxuloc = DCL.ugrget('VXULOC')
vyuloc = DCL.ugrget('VYULOC')
rsize = DCL.ugrget('RSIZET')
dv = rsize
DCL.sgtxzv(vxuloc, vyuloc-dv, uxunit, rsize, 0, -1, 3 )
DCL.sgtxzv(vxuloc-dv, vyuloc, uyunit, rsize, 90, -1, 3 )
end
ug_set_params( before2 ) if factor != 1.0
ug_set_params( before1 ) if unit_vect
end
######################################
# <<< color bar >>>
@@color_bar_options = Misc::KeywordOptAutoHelp.new(
["levels", nil, "tone levels (if omitted, latest ones are used)"],
["patterns", nil, "tone patterns (~colors) (if omitted, latest ones are used)"],
["voff", nil, "how far is the bar from the viewport in the V coordinate"],
["vcent",nil, "center position of the bar in the V coordinate (VX or VY)"],
["vlength", 0.3, "bar length in the V coordinate"],
["vwidth", 0.02, "bar width in the V coordinate"],
["landscape", false, "if true, horizonlly long (along x axes)"],
["portrait", true, "if true, vertically long (along y axes)"],
["left", false,"place the bar in the left (effective if portrait)"],
["top", false,"place the bar at the top (effective if portrait)"],
["tickintv", 1, "0,1,2,3,.. to specify how frequently the dividing tick lines are drawn (0: no tick lines, 1:every time, 2:ever other:,...)"],
["labelintv", nil, "1,2,3,.. to specify how frequently labels are drawn (1:every time, 2:ever other:,... default: internally determined)"],
["charfact", 0.9, "factor to change the label character size (relative to 'rsizel1')"],
["log" , false, ""],
["constwidth", false, "if true, each color is drawn with the same width(length)"],
["index", nil, "index of bar frame (so far, valid only when constwidth) "],
["chval_fmt", nil, "string to specify the DCL.chval format for labeling"]
)
def set_color_bar_options(options)
@@color_bar_options.set(options)
end
def level_chval_fmt(max,min,dx)
# returns a format for DCL.chval suitable for color-ba labels
eps = 1e-4 * dx.abs
if ( dx.abs % 10**Math::log10(dx.abs) < eps )
# 1 keta
least_order = Math::log10(dx.abs).floor
else
# >=2 keta --> limit to 2 keta
least_order = Math::log10(dx.abs).floor - 1
end
ng = Math::log10([max.abs,min.abs,eps].max).floor - least_order + 1
if ng <= 3
fmt = 'b'
else
n = Math::log10([max.abs,min.abs].max).floor
nn = Math::log10([max.abs,min.abs].min).floor
if least_order >= 0 and nn >= 0
ifg = 'i'
elsif 0 <= n and n <= 4
ifg = 'f'
else
ifg = 'g'
end
case(ifg)
when 'i'
fmt = '(i15)'
when 'g'
ng = Math::log10([max.abs,min.abs,eps].max).floor - least_order + 1
ng = [ ng, 2 ].max
fmt = "(g15.#{ng})"
when 'f'
nf = [ -least_order, 0].max
fmt = "(f15.#{nf})"
end
end
fmt
end
def sprintf_level(x,max,min,dx)
# format a float for color-bar labels.
# like DCL.hval('b',x) but changes according to dx
if x==0
fg = 'f'
else
n = Math::log10(x.abs).floor
if 0 <= n and n <= 4
fg = 'f'
else
fg = 'g'
end
end
eps = 1e-6
if ( dx.abs % 10**Math::log10(dx.abs) < eps )
# 1 keta
least_order = Math::log10(dx.abs).floor
else
# >=2 keta --> limit to 2 keta
least_order = Math::log10(dx.abs).floor - 1
end
if fg == 'g'
ng = Math::log10([max.abs,min.abs,eps].max).floor - least_order + 1
ng = [ ng, 2 ].max
fmt = "%.#{ng}g"
else
nf = [ -least_order, 0].max
fmt = "%.#{nf}f"
end
sprintf(fmt,x).sub(/\.0*$/,'')
end
def color_bar(options=nil)
opt = @@color_bar_options.interpret(options)
levels = opt['levels']
patterns = opt['patterns']
if (levels.nil? && !patterns.nil?) || (!levels.nil? && patterns.nil?) then
raise "levels and patterns must be set at same time\n"
end
landscape = opt["landscape"] || !opt["portrait"]
portrait = ! landscape
miss = DCL::glrget("rmiss")
if !levels.nil? then
ue_set_tone(levels,patterns)
end
nton = DCL::ueqntl
if nton==0 then
raise "no tone patern was set\n"
end
lev1 = Array.new
lev2 = Array.new
patterns = Array.new if !opt['patterns']
for n in 0..nton-1
tlev1,tlev2,ipat = DCL::ueqtlv(n+1)
lev1.push(tlev1)
lev2.push(tlev2)
patterns.push(ipat) if !opt['patterns']
end
#levels = lev1+lev2
#levels = levels.uniq.sort
#levels.delete(miss)
#if levels.ne(levels.sort).any? then
# raise "levels is not in order\n"
#end
levels = lev1.push(lev2[-1]) if !levels
levels = NArray.to_na(levels) if levels.is_a?(Array)
patterns = NArray.to_na(patterns) if patterns.is_a?(Array)
rmiss = DCL.glrget('rmiss')
vx1, vx2, vy1, vy2 = DCL.sgqvpt
if opt['log']
lv = levels[levels.ne(miss).where]
if lv.length >= 4 && lv[0]*lv[-1]<0
iturn = 0
for i in 0...levels.length
if levels[i] != rmiss
if levels[i]*lv[0] < 0
iturn = i
break
end
end
end
opt['vlength'] /= 2
vc0 = opt['vcent'] || ( portrait && (vy1+vy2)/2) || (vx1+vx2)/2
opt["voff"] ||=
DCL.uzpget('pad1')*DCL::uzrget("rsizec2") +
( portrait ? DCL.uzpget('roffyr') : - DCL.uzpget('roffxb') )
vsep2 = 0.02
opt['levels'] = levels[0..iturn-1]
opt['patterns'] = patterns[0..iturn-2]
opt['vcent'] = vc0 - opt['vlength']/2 - vsep2
color_bar(opt)
opt['levels'] = levels[iturn..-1]
opt['patterns'] = patterns[iturn..-1]
opt['vcent'] = vc0 + opt['vlength']/2 + vsep2
color_bar(opt)
# fill between the two bars
if portrait
x1 = vx2 + opt["voff"]
x2 = x1 + opt['vwidth']
y1 = vc0 - vsep2
y2 = vc0 + vsep2
else
x1 = vc0 - vsep2
x2 = vc0 + vsep2
y1 = vy1 - opt["voff"]
y2 = y1 - opt['vwidth']
end
bk = DCLExt.sg_set_params({'lclip'=>false})
DCL.sgtnzv([x1,x2,x2,x1],[y1,y1,y2,y2],patterns[iturn-1])
DCL.sgplzv([x1,x2,x2,x1,x1],[y1,y1,y2,y2,y1],1,3)
DCLExt.sg_set_params(bk)
return
end
end
if levels.length <= 1
$stderr.print( "WARNING #{__FILE__}:#{__LINE__}: # of levels <= 1. No color bar is drawn." )
return
end
itrsv = DCL::sgqtrn
if itrsv <= 4
ux1sv, ux2sv, uy1sv, uy2sv = DCL.sgqwnd
else
simfacsv, vxoffsv, vyoffsv = DCL.sgqsim
plxsv, plysv, plrotsv = DCL.sgqmpl()
end
vwidth = opt["vwidth"]
vlength = opt["vlength"]
if portrait
if !opt["left"]
voff = opt["voff"] ||
DCL.uzpget('roffyr') + DCL.uzpget('pad1')*DCL::uzrget("rsizec2")
vxmin = vx2 + voff
vxmax = vx2 + voff + vwidth
else
voff = opt["voff"] ? -opt["voff"] : \
DCL.uzpget('roffyl') - DCL.uzpget('pad1')*DCL::uzrget("rsizec2")
vxmax = vx1 + voff
vxmin = vx1 + voff - vwidth
end
vymin =( opt["vcent"] ? opt["vcent"]-vlength/2 : vy1 )
vymax =( opt["vcent"] ? opt["vcent"]+vlength/2 : vy1+vlength )
else
vxmin =( opt["vcent"] ? opt["vcent"]-vlength/2 : (vx1+vx2)/2-vlength/2 )
vxmax =( opt["vcent"] ? opt["vcent"]+vlength/2 : (vx1+vx2)/2+vlength/2 )
if opt["top"]
# top
voff = opt["voff"] ||
DCL.uzpget('roffxt') + DCL.uzpget('pad1')*DCL::uzrget("rsizec2")
vymin = vy2 + voff
vymax = vy2 + voff + vwidth
else
# bottom
voff = opt["voff"] ? -opt["voff"] : \
DCL.uzpget('roffxb') - DCL.uzpget('pad1')*DCL::uzrget("rsizec2")
vymax = vy1 + voff
vymin = vy1 + voff - vwidth
end
end
min = levels[levels.ne(miss).where].min
max = levels[levels.ne(miss).where].max
if levels[0] == miss
inf0 = true
dummy1,dummy2,ipat0 = DCL::ueqtlv(1)
else
inf0 = false
end
if levels[-1] == miss
inf1 = true
dummy1,dummy2,ipat1 = DCL::ueqtlv(nton)
else
inf1 = false
end
lclip = DCL::sgpget("lclip")
DCL::sgpset("lclip", false) if lclip
if opt["constwidth"]
nlev = levels.length
npat = patterns.length
if opt["index"]
index = opt["index"]
else
index = DCL::uzpget("indext2")
end
if portrait then
vy = (NArray.sfloat(npat+1).indgen!)*(vymax-vymin)/npat + vymin
for i in 0..npat-1
if( i==0 && inf0 )
DCL::sgtnzv([(vxmin+vxmax)/2,vxmax,vxmin],[vy[0],vy[1],vy[1]],patterns[0])
DCL::sgplzv([vxmin,(vxmin+vxmax)/2],[vy[1],vy[0]],1,index)
DCL::sgplzv([vxmax,(vxmin+vxmax)/2],[vy[1],vy[0]],1,index)
elsif( i==npat-1 && inf1 )
DCL::sgtnzv([vxmin,vxmax,(vxmax+vxmin)/2],[vy[npat-1],vy[npat-1],vy[npat]],patterns[npat-1])
DCL::sgplzv([vxmin,(vxmax+vxmin)/2],[vy[npat-1],vy[npat]],1,index)
DCL::sgplzv([vxmax,(vxmax+vxmin)/2],[vy[npat-1],vy[npat]],1,index)
else
DCL::sgtnzv([vxmin,vxmax,vxmax,vxmin],[vy[i],vy[i],vy[i+1],vy[i+1]],patterns[i])
DCL::sgplzv([vxmin,vxmin],[vy[i],vy[i+1]],1,index)
DCL::sgplzv([vxmax,vxmax],[vy[i],vy[i+1]],1,index)
end
end
else
vx = (NArray.sfloat(npat+1).indgen!)*(vxmax-vxmin)/npat + vxmin
for i in 0..npat-1
if( i==0 && inf0 )
DCL::sgtnzv([vx[0],vx[1],vx[1]],[(vymin+vymax)/2,vymax,vymin],patterns[0])
DCL::sgplzv([vx[1],vx[0]],[vymin,(vymin+vymax)/2],1,index)
DCL::sgplzv([vx[1],vx[0]],[vymax,(vymin+vymax)/2],1,index)
elsif( i==npat-1 && inf1 )
DCL::sgtnzv([vx[npat-1],vx[npat-1],vx[npat]],[vymin,vymax,(vymax+vymin)/2],patterns[npat-1])
DCL::sgplzv([vx[npat-1],vx[npat]],[vymin,(vymax+vymin)/2],1,index)
DCL::sgplzv([vx[npat-1],vx[npat]],[vymax,(vymax+vymin)/2],1,index)
else
DCL::sgtnzv([vx[i],vx[i],vx[i+1],vx[i+1]],[vymin,vymax,vymax,vymin],patterns[i])
DCL::sgplzv([vx[i],vx[i+1]],[vymin,vymin],1,index)
DCL::sgplzv([vx[i],vx[i+1]],[vymax,vymax],1,index)
end
end
end
else
nbar =100
bar = NArray.float(nbar,2)
for i in 0..nbar-1
bar[i,true] = min + (max-min).to_f/(nbar-1)*i
end
xb = DCL::uzlget("labelxb")
yl = DCL::uzlget("labelyl")
if portrait then
xmin = 0.0
xmax = 1.0
ymin = min
ymax = max
DCL::uzlset("labelxb",false)
DCL::uzlset("labelyl",true)
bar = bar.transpose(-1,0)
DCL::uwsgxa([0,1])
DCL::uwsgya(bar[0,true])
else
xmin = min
xmax = max
ymin = 0.0
ymax = 1.0
DCL::uzlset("labelxb",true)
DCL::uzlset("labelyl",false)
DCL::uwsgxa(bar[true,0])
DCL::uwsgya([0,1])
end
type = 1
if opt["log"] then
type +=1
type +=1 if !portrait
end
DCL::grfig
DCL::grsvpt(vxmin,vxmax,vymin,vymax)
DCL::grswnd(xmin,xmax,ymin,ymax)
DCL::grstrn(type)
DCL::grstrf
DCL::uetone(bar)
end # end of constwidth
# < set ticking and labeling levels >
if opt["labelintv"]
labelintv = opt["labelintv"]
else
ntn = nton
ntn -= 1 if inf0
ntn -= 1 if inf1
if portrait
labelintv = (ntn-1) / 9 + 1
else
labelintv = (ntn-1) / 5 + 1
end
end
tickintv = opt["tickintv"]
tickintv = labelintv if tickintv <= 0
eps = 1e-5
dummy = -9.9e-38
dz = dzp = dzc = dummy
idu = Array.new
(1...levels.length).each do |i|
dzc = (levels[i] - levels[i-1]).abs
if (dzc-dzp).abs <= eps * [dzc.abs,dzp.abs].max
dz = dzc # set dz if two consecutive inrements are the same
idu.push( i-1 )
end
dzp = (levels[i] - levels[i-1]).abs
end
if idu.length > 0
idumin = idu.min - 1
idumax = idu.max + 1
else
idumin = 0
idumax = levels.length-1
end
if dz != dummy
# if idumin == 1 and levels[0] != miss
# # to correct non-uniform intv at the beginning
# levels[0] = levels[1] - dz
# idumin = 0
# min = levels[0]
# end
# if idumax == levels.length-2 and levels[-1] != miss
# # to correct non-uniform intv at the end
# levels[-1] = levels[-2] + dz
# idumax = levels.length-1
# max = levels[-1]
# end
# use the algorithm used in DCL.udgcla
offs_tick = ( (-levels[idumin]/dz).round % tickintv + idumin ) % tickintv
offs_label = ( (-levels[idumin]/dz).round % labelintv + idumin ) % labelintv
else
md = 0
if ( (idx=levels.eq(0.0).where).length > 0 )
md = idx[0] % labelintv
else
a = levels[0...([labelintv,levels.length].min)]
b = a * 10**( -NMath.log10(a.abs).floor.min )
(0...b.length).each{|i| md=i if (b[i].round-b[i]).abs < 1e-5 }
end
offs_tick = (md % tickintv)
offs_label = md
end
if levels.length >= 4
lvmx = levels[1..-2].max
lvmn = levels[1..-2].min
dlv = (lvmx-lvmn) / (levels.length-3)
elsif levels.length == 3 or levels.length == 2
lvmn = lvmx = dlv = levels[1]
else
lvmn = lvmx = dlv = levels[0]
end
if opt["constwidth"]
charfact = opt["charfact"]
rsizel = DCL::uzrget("rsizel1")
if portrait then
if voff > 0
cent = -1
vxlabel = vxmax+0.01
else
cent = 1
vxlabel = vxmin-0.01
end
for i in 0..nlev-1
if levels[i] != miss
if (i % labelintv) == offs_label
begin
if(opt['chval_fmt'])
char = DCL::chval(opt['chval_fmt'],levels[i])
else
char = sprintf_level(levels[i],lvmx,lvmn,dlv)
end
DCL::sgtxzr(vxlabel,vy[i],char,charfact*rsizel,0,cent,2)
rescue
DCL::sgtxzr(vxlabel,vy[i],levels[i].to_s,charfact*rsizel,0,cent,2)
end
end
if (i % tickintv) == offs_tick
DCL::sgplzv([vxmin,vxmax],[vy[i],vy[i]],1,index)
end
end
end
else
if voff > 0
vylabel = vymax+0.015
else
vylabel = vymin-0.015
end
for i in 0..nlev-1
if levels[i] != miss
if (i % labelintv) == offs_label
begin
if(opt['chval_fmt'])
char = DCL::chval(opt['chval_fmt'],levels[i])
else
char = sprintf_level(levels[i],lvmx,lvmn,dlv)
end
DCL::sgtxzr(vx[i],vylabel,char,charfact*rsizel,0,0,2)
rescue
DCL::sgtxzr(vx[i],vylabel,levels[i].to_s,charfact*rsizel,0,0,2)
end
end
if (i % tickintv) == offs_tick
DCL::sgplzv([vx[i],vx[i]],[vymin,vymax],1,index)
end
end
end
end
else
tick1 = Array.new
tick2 = Array.new
for i in 0..levels.length-1
if i>=idumin && i<=idumax && levels[i]!=rmiss
tick1.push(levels[i]) if (i % tickintv) == offs_tick
tick2.push(levels[i]) if (i % labelintv) == offs_label
end
end
charfact = opt["charfact"]
rsizel = DCL::uzrget("rsizel1")
DCL::uzrset("rsizel1",charfact*rsizel)
rsizet = DCL::uzrget("rsizet1")
if portrait then
if voff > 0
before = uz_set_params( {'labelyl'=>false, 'labelyr'=>true,
'icentyr'=>-1.0} )
else
before = uz_set_params( {'labelyl'=>true, 'labelyr'=>false,
'icentyl'=>1.0} )
end
DCL::uzrset("rsizet1",vwidth)
DCL::uxaxdv("t",1,1)
DCL::uxaxdv("b",1,1)
cfmt_save = DCL::uyqfmt
if opt["log"]
fmt = opt['chval_fmt'] || "b"
else
fmt = opt['chval_fmt'] || level_chval_fmt(lvmx,lvmn,dlv)
end
DCL::uysfmt( fmt )
DCL::uyaxnm("l",tick1,tick2)
DCL::uyaxnm("r",tick1,tick2)
DCL::uysfmt( cfmt_save )
uz_set_params(before)
if inf1
vy3 = [vymax, vymax+vwidth*2.25, vymax]
vx3 = [vxmax, (vxmax+vxmin)/2, vxmin]
DCL.sgtnzv(vx3,vy3,ipat1)
DCL.sgplzv(vx3,vy3,1,3)
end
if inf0
vy3 = [vymin, vymin-vwidth*2.25, vymin]
vx3 = [vxmax, (vxmax+vxmin)/2, vxmin]
DCL.sgtnzv(vx3,vy3,ipat0)
DCL.sgplzv(vx3,vy3,1,3)
end
else
if voff > 0
before = uz_set_params( {'labelxt'=>true, 'labelxb'=>false} )
else
before = uz_set_params( {'labelxt'=>false, 'labelxb'=>true} )
end
DCL::uzrset("rsizet1",vwidth)
cfmt_save = DCL::uxqfmt
if opt["log"]
fmt = opt['chval_fmt'] || "b"
else
fmt = opt['chval_fmt'] || level_chval_fmt(lvmx,lvmn,dlv)
end
DCL::uxsfmt( fmt )
DCL::uxaxnm("t",tick1,tick2)
DCL::uxaxnm("b",tick1,tick2)
DCL::uxsfmt( cfmt_save )
DCL::uyaxdv("l",1,1)
DCL::uyaxdv("r",1,1)
uz_set_params(before)
if inf0
vx3 = [vxmin, vxmin-vwidth*2.25, vxmin]
vy3 = [vymax, (vymax+vymin)/2, vymin]
DCL.sgtnzv(vx3,vy3,ipat0)
DCL.sgplzv(vx3,vy3,1,3)
end
if inf1
vx3 = [vxmax, vxmax+vwidth*2.25, vxmax]
vy3 = [vymax, (vymax+vymin)/2, vymin]
DCL.sgtnzv(vx3,vy3,ipat1)
DCL.sgplzv(vx3,vy3,1,3)
end
end
DCL::uzrset("rsizel1",rsizel)
DCL::uzrset("rsizet1",rsizet)
DCL::uzlset("labelxb",xb)
DCL::uzlset("labelyl",yl)
if !opt["constwidth"]
DCL::grsvpt(vx1,vx2,vy1,vy2)
if itrsv <= 4
DCL::grswnd(ux1sv, ux2sv, uy1sv, uy2sv)
DCL::grstrn(itrsv)
else
DCL.sgssim(simfacsv,vxoffsv,vyoffsv)
DCL.sgsmpl(plxsv,plysv,plrotsv)
end
DCL::grstrf
end
end
DCL::sgpset("lclip", true) if lclip
nil
end
# Annotates line/mark type and index (and size if mark).
# By defualt it is shown in the right margin of the viewport.
#
# * str is a String to show
# * line: true->line ; false->mark
# * vx: vx of the left-hand point of legend line (or mark position).
# * nil : internally determined
# * Float && > 0 : set explicitly
# * Float && < 0 : move it relatively to the left from the defualt
# * dx: length of the legend line (not used if mark).
# * nil : internally determined
# * Float && > 0 : set explicitly
# * vy: vy of the legend (not used if !first -- see below).
# * nil : internally determined
# * Float && > 0 : set explicitly
# * Float && < 0 : move it relatively lower from the defualt
# * first : if false, vy is moved lower relatively from the previous vy.
# * mark_size : size of the mark. if nil, size is used.
def legend(str, type, index, line=false, size=nil,
vx=nil, dx=nil, vy=nil, first=true, mark_size=nil)
size = DCL::uzrget("rsizel1")*0.95 if !size
mark_size = size if !mark_size
vpx1,vpx2,vpy1,vpy2 = DCL.sgqvpt
if first
if !vy
vy = vpy2 - 0.04
elsif vy < 0
vy = ( vpy2 - 0.04 ) + vy
end
@vy = vy
else
vy = @vy - 1.5*size
end
if !vx
vx = vpx2 + 0.015
elsif vx < 0
vx = (vpx2 + 0.015) + vx
end
if line
dx=0.06 if !dx
vx2 = vx + dx
DCL::sgplzv([vx,vx2],[vy,vy],type,index)
DCL.sgtxzv(vx2+0.01,vy,str,size,0,-1,3)
else # --> mark
DCL::sgpmzv([vx],[vy],type,index,mark_size)
DCL.sgtxzv(vx+0.015+mark_size*0.5,vy,str,size,0,-1,3)
end
nil
end
# Driver of quasi_log_levels with data values
def quasi_log_levels_z(vals, nlev=nil, max=nil, min=nil, cycle=1)
if max && min
quasi_log_levels(max.to_f, min.to_f, cycle)
else
if nlev
eps = 0.1
norder = (nlev-1.0+eps)/cycle
else
norder = 3
end
mx1 = vals.max
mx2 = vals.min
if min && min < 0
max = min
min = nil
elsif max && max < 0
min = max
max = nil
end
maxsv = max
minsv = min
if !max
max = [ mx1.abs, mx2.abs ].max.to_f
max = -max if mx1<0
end
if !min
min = max/10**norder
else
max = min*10**norder if nlev
end
if !(minsv && minsv>0) && !(maxsv && maxsv <0) && ( mx2<0 && mx1>0 )
min = -min
end
quasi_log_levels(max, min, cycle)
end
end
# Returns approximately log-scaled contour/tone levels as well as
# major/minor flags for contours. No DCL call is made in here.
#
# * cycle (Integer; 1, or 2 or 3) : number of level in one-order.
# e.g. 1,10,100,.. for cycle==1; 1,3,10,30,.. for cycle==2;
# 1,2,5,10,20,50,.. for cycle==3
# * lev0, lev1 (Float) : levels are set between this two params
# * if lev0 & lev1 > 0 : positive only
# * if lev0 & lev1 < 0 : negative only
# * if lev0 * lev1 < 0 : both positive and negative
# such as over -lev0..-lev1, lev1..lev2
# RETURN VALUE:
# * [ levels, mjmn ]
def quasi_log_levels(lev0, lev1, cycle=1)
raise(ArgumentError, "lev0 is zero (non-zero required)") if lev0 == 0.0
raise(ArgumentError, "lev1 is zero (non-zero required)") if lev1 == 0.0
case cycle
when 1
cycl_levs = [1.0]
when 2
cycl_levs = [1.0, 3.0]
when 3
cycl_levs = [1.0, 2.0, 5.0]
else
raise(ArgumentError, "cycle must be 1,2,or 3, which is now #{cycle}")
end
if lev0 > 0 and lev1 > 0
positive = true
negative = false
elsif lev0 < 0 and lev1 < 0
positive = false
negative = true
else
positive = true
negative = true
end
sml, big = [lev0.abs,lev1.abs].sort
expsml = Math::log10(sml).floor
expbig = Math::log10(big).ceil
levels = Array.new
mjmn = Array.new
for i in expsml..expbig-1
for k in 0..cycle-1
lev = cycl_levs[k] * 10**i
if lev >= sml && lev <= big
levels.push( lev )
mjmn.push( k==0 ? 1 : 0 )
end
end
end
lev = 10**expbig
if lev == big
levels.push( lev )
mjmn.push( 1 )
end
if negative && !positive
levels = levels.reverse.collect{|x| -x}
mjmn = mjmn.reverse
elsif negative && positive
levels.dup.each{|x| levels.unshift(-x)}
mjmn.dup.each{|x| mjmn.unshift(x)}
end
[ levels, mjmn ]
end
end
####################################################################
####################################################################
####################################################################
module GGraph
class << self
## private methods in the module
def __shorten_path(str,maxlen)
return str if str.length <= maxlen
astr = str.split(/\//)
while(str.length > maxlen)
astr.length!=2 ? at = (astr.length)/2 : at = 0
astr.delete_at( at )
(a = astr.dup)[at, 0] = '...' # insert(at,'...') if Ruby>=1.8
str = a.join('/')
end
str
end
private :__shorten_path
end
module_function
def gropn_1_if_not_yet
begin
DCL.stqwrc
rescue
DCL.gropn(1)
end
end
def margin_info(program=nil, data_source=nil, char_height=nil, date=nil,
xl=0.0, xr=0.0, yb=nil, yt=0.0)
program = File.expand_path($0) if !program
if date
program = __shorten_path(program,77) + ' ' + Date.today.to_s
else
program = __shorten_path(program,99)
if date.nil?
program = program + ' ' + Date.today.to_s if program.length < 77
end
end
if !data_source
data_source = Dir.pwd
data_source = '' if data_source == program.sub(/\/[^\/]+$/,'')
end
data_source = __shorten_path(data_source,99)
sz = 1.0/( program.length + data_source.length )
char_height = [0.008, sz].min if !char_height
yb = 2.0 * char_height if !yb
DCL.slmgn(xl, xr, yb, yt)
DCL.slsttl(program, 'b', -1.0, -1.0, char_height, 1)
DCL.slsttl(data_source, 'b', 1.0, -1.0, char_height, 2)
nil
end
def color_bar(*args)
DCLExt.color_bar(*args)
end
def title(string)
if string
if map_trn? || itr_is?(5)
v = DCL::sgqvpt
txhgt = DCL.uzpget('rsizec2') # rsizec2: larger text
vx = (v[0]+v[1])/2
vy = v[3] + (0.5 + DCL.uzpget('pad1')) * txhgt
DCL::sgtxzr(vx , vy, string, txhgt, 0, 0, 3)
else
DCL.uxmttl('t',string,0.0)
end
end
nil
end
def annotate(str_ary)
charsize = 0.7 * DCL.uzpget('rsizec1')
vxmin,vxmax,vymin,vymax = DCL.sgqvpt
vx = vxmax + 0.01
vy = vymax - charsize/2
annotate_at(str_ary,vx,vy,charsize)
nil
end
def annotate_at(str_ary,vx,vy,charsize=nil, align=-1.0, dvyfact=-1.5)
raise TypeError,"Array expected" if ! str_ary.is_a?(Array)
charsize = 0.7 * DCL.uzpget('rsizec1') unless(charsize)
dvy = charsize*dvyfact
str_ary.each{|str|
DCL::sgtxzr(vx,vy,str,charsize,0,align,1)
vy += dvy
}
nil
end
@@fig = Misc::KeywordOptAutoHelp.new(
['new_frame',true, 'whether to define a new frame by DCL.grfrm (otherwise, DCL.grfig is called)'],
['no_new_fig',false, 'If true, neither DCL.grfrm nor DCL.grfig is called (overrides new_frame) -- Then, you need to call one of them in advance. Convenient to set DCL parameters that are reset by grfrm or grfig.'],
['itr', 1, 'coordinate transformation number'],
['viewport',[0.2,0.8,0.2,0.8], '[vxmin, vxmax, vymin, vymax]'],
['window', nil, '(for itr<10,>50) [uxmin, uxmax, uymin, uymax]. each element allowd nil (only for itr<5,>50)'],
['xreverse','positive:down,units:hPa', '(for itr<10,>50) Assign max value to UXMIN and min value to UXMAX if condition is satisfied (nil:never, true:always, String: when an attibute has the value specified ("key:value,key:value,..")'],
['yreverse','positive:down,units:hPa', '(for itr<10,>50) Assign max value to UYMIN and min value to UYMAX if condition is satisfied (nil:never, true:always, String: when an attibute has the value specified ("key:value,key:value,..")'],
# for 5<=itr<=7 (Rectangular Curvilinear Coordinates)
['similar', nil, '3-element float array for similar transformation in a rectangular curvilinear coordinate, which is fed in DCL:grssim:[simfac,vxoff,vyoff], where simfac and [vxoff,vyoff] represent scaling factor and origin shift, respectively.'],
# for 10<=itr<=50 (map projection):
['map_axis', nil, '(for all map projections) 3-element float array to be fed in DCL::umscnt: [uxc, uxy, rot], where [uxc, uyc] represents the tangential point (or the pole at top side for cylindrical projections), and rot represents the rotation angle. If nil, internally determined. (units: degrees)'],
['map_radius', nil, '(for itr>=20: conical/azimuhal map projections) raidus around the tangential point. (units: degrees)'],
['map_fit',nil,'(Only for itr=10(cylindrical) and 11 (Mercator)) true: fit the plot to the data window (overrides map_window and map_axis); false: do not fit (then map_window and map_axis are used); nil: true if itr==10, false if itr==11'],
['map_window', [-180,180,-75,75], '(for itr<20: cylindrical map projections) lon-lat window [lon_min, lon_max, lat_min, lat_max ] to draw the map (units: degres)']
)
def set_fig(options)
@@fig.set(options)
end
@@next_fig = nil
def next_fig(options)
if options.is_a?(Hash)
@@next_fig = options
else
raise TypeError,"Hash expected"
end
nil
end
def map_trn?( fig_yet_to_be_called=false )
if fig_yet_to_be_called
itr = ( @@next_fig && @@next_fig['itr'] ) || @@fig['itr']
else
itr = DCL.sgqtrn
end
case itr
when 1..9,51..99
false
else
true
end
end
def itr_is?( itr, fig_yet_to_be_called=false )
if fig_yet_to_be_called
current_itr = ( @@next_fig && @@next_fig['itr'] ) || @@fig['itr']
else
current_itr = DCL.sgqtrn
end
current_itr == itr
end
def sim_trn?
itr = DCL.sgqtrn
case itr
when 5..7
true
else
false
end
end
def fig(xax=nil, yax=nil, options=nil)
# xax and yax are needed (i.e. Axis objects) if not map projection
if @@next_fig
options = ( options ? @@next_fig.update(options) : @@next_fig )
@@next_fig = nil
end
opts = @@fig.interpret(options)
if opts['no_new_fig']
# do nothing
elsif opts['new_frame']
DCL.grfrm
else
DCL.grfig
end
raise "viewport's length must be 4" if opts['viewport'].length != 4
DCL.grsvpt(*opts['viewport'])
if opts['window']
if !opts['window'].is_a?(Array) || opts['window'].length!=4
raise "Option 'window' must be an Array of length==4"
end
end
itr = opts['itr']
DCL.grstrn(itr)
map_fit = ( (itr==10 and opts['map_fit']!=false) or
(itr==11 and opts['map_fit']==true) )
if ( (1<=itr and itr<=4) or (51<=itr and itr<=99) or map_fit )
window = opts['window']
window = ( window ? window.dup : [nil, nil, nil, nil])
if window.include?(nil)
raise(ArgumentError, "xax and yax must be provided") if !xax or !yax
if (xreverse=opts['xreverse']).is_a?(String)
atts = opts['xreverse'].split(',').collect{|v| v.split(':')}
xreverse = false
atts.each{|key,val|
xreverse = ( xax.get_att(key) == val )
break if xreverse
}
end
if (yreverse=opts['yreverse']).is_a?(String)
atts = opts['yreverse'].split(',').collect{|v| v.split(':')}
yreverse = false
atts.each{|key,val|
yreverse = ( yax.get_att(key) == val )
break if yreverse
}
end
if xreverse
xrange = [ xax.max, xax.min ]
else
xrange = [ xax.min, xax.max ]
end
if yreverse
yrange = [ yax.max, yax.min ]
else
yrange = [ yax.min, yax.max ]
end
default_window=[xrange[0], xrange[1], yrange[0], yrange[1]]
if window.nitems == 0 # if all elements is nil
window = default_window
else
window.each_index do |i|
window[i] = default_window[i] if window[i] == nil
end
end
end
end
case itr
when 1..4,51..99
# all but for map projections and curvilinear coordinates
DCL.grswnd(*window)
when 5,6
if opts['similar']
similar=opts['similar']
DCL.grssim(*similar)
elsif opts['window']
if defined?(DCL::DCLVERSION) && DCL::DCLVERSION >= '5.3'
DCL.sgscwd(*opts['window'])
else
raise "You need DCL 5.3 or later to use the 'window' parameter in this transform (#{itr}). Use 'similar' instead."
end
else
case itr
when 5
vxmin,vxmax,vymin,vymax=DCL.sgqvpt
raise(ArgumentError, "xax must be provided") if !xax
simfac = (vymax-vymin)/(xax.max*2) # only xax is used
similar = [simfac,0.0,0.0]
DCL.grssim(*similar)
else
raise NotImplementedError, "Sorry, automatic window setting is yet to be available for the transform #{itr}. Please specify the 'similar' or 'window' parameter"
end
end
when 10..15
if !map_fit
map_axis = opts['map_axis'] || [180.0, 0.0, 0.0]
DCL::umscnt( *map_axis )
map_window = opts['map_window']
raise "map_window's length must be 4" if map_window.length != 4
map_lat_range = [ map_window[2], map_window[3] ]
if map_lat_range.is_a?(Range)
map_lat_range = [map_lat_range.first, map_lat_range.end]
end
case ( map_axis[2] - map_axis[1] ) % 360
when 0
tyrange = map_lat_range
when 180
tyrange = [ -map_lat_range[1], -map_lat_range[0] ]
else
tyrange = [ -75, 75 ] # latange is ignored
end
DCL::grstxy(map_window[0], map_window[1], tyrange[0], tyrange[1])
else
lon_cent =( window[0] + window[1] ) / 2.0
dlon2 = ( window[1] - window[0] ) / 2.0
map_axis = [ lon_cent, 0.0, 0.0 ]
DCL::sgswnd(*window)
DCL::umscnt( *map_axis )
DCL::grstxy( -dlon2, dlon2, window[2], window[3] )
end
sv = DCL.umpget('lglobe')
DCL.umpset('lglobe', true)
DCL::umpfit
when 20..33
map_axis = opts['map_axis'] || [180.0, 90.0, 0.0]
map_radius = opts['map_radius'] || 70.0
DCL::umscnt( *map_axis )
case itr
when 31
v = opts['viewport']
vptsize = [ v[1]-v[0], v[3]-v[2] ].min
DCL::grssim( vptsize*0.25/Math::tan(0.5*Math::PI*map_radius/180.0), 0.0, 0.0 )
when 22
v = opts['viewport']
vptsize = [ v[1]-v[0], v[3]-v[2] ].min
DCL::grssim( vptsize*0.35*(90.0/map_radius), 0.0, 0.0 )
DCL::grstxy(-180.0, 180.0, 90.0-map_radius, 90.0)
else
DCL::grstxy(-180.0, 180.0, 90.0-map_radius, 90.0)
end
sv = DCL.umpget('lglobe')
DCL.umpset('lglobe', true)
DCL::umpfit
DCL.umpset('lglobe', sv)
else
raise "unsupported transformation number: #{itr}"
end
DCL.grstrf
DCL.umpset('lglobe', sv)
nil
end
@@axes = Misc::KeywordOptAutoHelp.new(
['xside', 'tb', 'Where to draw xaxes (combination of t, b and u)'],
['yside', 'lr', 'Where to draw yaxes (combination of l, r and u)'],
['xtitle', nil, 'Title of x axis (if nil, internally determined)'],
['ytitle', nil, 'Title of y axis (if nil, internally determined)'],
['xunits', nil, 'Units of x axis (if nil, internally determined)'],
['yunits', nil, 'Units of y axis (if nil, internally determined)'],
['xtickint', nil,
'Interval of x axis tickmark (if nil, internally determined)'],
['ytickint', nil,
'Interval of y axis tickmark (if nil, internally determined)'],
['xlabelint', nil,
'Interval of x axis label (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.'],
['time_ax', nil, 'Type of calendar-type time axis: nil (=> auto slection), false (do not use the time axis even if the units of the axis is a time one with since field), "h" (=> like nil, but always use the hour-resolving datetime_ax method in dclext_datetime_ax.rb), or "ymd" (=> like "h" but for y-m-d type using DCL.uc[xy]acl)']
)
def set_axes(options)
@@axes.set(options)
end
@@next_axes = nil
def next_axes(options)
if options.is_a?(Hash)
@@next_axes = options
else
raise TypeError,"Hash expected"
end
nil
end
# axtype: nil (-->auto), 'h' (to resolve hours), or 'ymd'
def __calendar_ax(axtype, xax, side, sunits, ttl, \
tickint=nil, labelint=nil)
window = DCL.sgqwnd
viewport = DCL.sgqvpt
/(.*) *since *(.*)/ =~ sunits
if (!$1 or !$2)
raise("Units mismatch. Requires time units that includes 'since'")
end
tun = Units[$1]
dayun = Units['days']
since = DateTime.parse($2)
if xax
t0 = window[0]
t1 = window[1]
else
t0 = window[2]
t1 = window[3]
end
tstr = since + tun.convert( t0, dayun )
jd0 = tstr.strftime('%Y%m%d').to_i
tlen = tun.convert( t1-t0, dayun )
if !axtype
if tlen < 5
axtype = 'h'
else
axtype = 'ymd'
end
end
if xax
DCL.grswnd(0.0, tlen, window[2], window[3] )
DCL.grstrf
if axtype == 'h'
opts = {'cside'=>side}
opts['dtick1'] = tickint if tickint
opts['dtick2'] = labelint if labelint
DCLExt.datetime_ax(tstr, tstr+tlen, opts )
else
DCL.ucxacl(side,jd0,tlen)
end
DCL.grswnd(*window)
DCL.grstrf
else
DCL.grswnd(window[0], window[1], 0.0, tlen)
DCL.grstrf
if axtype == 'h'
opts = {'yax'=>true, 'cside'=>side}
opts['dtick1'] = tickint if tickint
opts['dtick2'] = labelint if labelint
DCLExt.datetime_ax(tstr, tstr+tlen, opts )
else
DCL.ucyacl(side,jd0,tlen)
end
DCL.grswnd(*window)
DCL.grstrf
end
end
private :__calendar_ax
def axes(xax=nil, yax=nil, options=nil)
if @@next_axes
options = ( options ? @@next_axes.update(options) : @@next_axes )
@@next_axes = nil
end
opts = @@axes.interpret(options)
if opts['xside'].length > 0
xai = _get_axinfo(xax)
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
sunits = opts['xunits'] || xai['units']
units = Units[sunits]
if opts['time_ax'] != false && \
/since/ =~ sunits && units =~ Units['days since 0001-01-01']
opts['xside'].split('').each do |s| # scan('.') also works
ttl = opts['xtitle'] || xai['title']
__calendar_ax(opts['time_ax'], true, s, sunits, ttl,
opts['xtickint'], opts['xlabelint'])
end
else
DCL.uscset('cxttl', (opts['xtitle'] || xai['title']) )
DCL.uscset('cxunit', sunits)
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
end
if opts['yside'].length > 0
yai = _get_axinfo(yax)
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
sunits=(opts['yunits'] || yai['units'])
units = Units[sunits]
if opts['time_ax'] != false && \
/since/ =~ sunits && units =~ Units['days since 0001-01-01']
opts['yside'].split('').each do |s| # scan('.') also works
ttl = opts['ytitle'] || yai['title']
__calendar_ax(opts['time_ax'], false, s, sunits, ttl,
opts['ytickint'], opts['ylabelint'])
end
else
DCL.uscset('cyttl', (opts['ytitle'] || yai['title']) )
DCL.uscset('cyunit', sunits )
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' && sunits && sunits != ''
DCL.uzpset('roffxt', DCL.uzpget('rsizec1')*1.5 )
end
}
end
end
end
nil
end
def _get_axinfo(vary)
if vary.nil?
hash = {
'title'=>'',
'units'=>''
}
else
raise "Not 1D" if vary.rank!=1
hash = {
'title'=>(vary.get_att('long_name') || vary.name), #.gsub('_','' )
'units'=>(vary.get_att('units') || '') #.gsub('_',' ')
}
end
hash
end
def polar_coordinate_boundaries(xax=nil,yax=nil)
slln=DCL.sgpget('LLNINT') ; slgc=DCL.sgpget('LGCINT')
DCL.sgpset('LLNINT',true) ; DCL.sgpset('LGCINT',true)
xmin=xax.min ; xmax=xax.max ; ymin=yax.min ; ymax=yax.max
azimuth_len = ymax-ymin
azimuth_len = azimuth_len.val if azimuth_len.is_a?(UNumeric)
unless( (azimuth_len - 360.0).abs < 1e-2 )
# not a full circle
DCL.sgplzu([xmin,xmax],[ymin,ymin],1,5)
DCL.sgplzu([xmin,xmax],[ymax,ymax],1,5)
end
DCL.sgplzu([xmin,xmin],[ymin,ymax],1,5)
DCL.sgplzu([xmax,xmax],[ymin,ymax],1,5)
DCL.sgpset('LLNINT',slln) ; DCL.sgpset('LGCINT',slgc)
nil
end
@@map = Misc::KeywordOptAutoHelp.new(
['lim', true, 'draw map lim (t or f)'],
['grid', true, 'draw map grid (t or f)'],
['vpt_boundary', false, 'draw viewport boundaries (f, t or 1,2,3.., representing the line width)'],
['wwd_boundary', false, 'draw worksation window boundaries (f, t or 1,2,3.., representing the line width)'],
['fill', false, 'fill the map if coast_world or coast_japan is true (t or f)'],
['coast_world', false, 'draw world coast lines (t or f)'],
['border_world', false, 'draw nation borders (t or f)'],
['plate_world', false, 'draw plate boundaries (t or f)'],
['state_usa', false, 'draw state boundaries of US (t or f)'],
['coast_japan', false, 'draw japanese coast lines (t or f)'],
['pref_japan', false, 'draw japanese prefecture boundaries (t or f)'],
['dgridmj', nil, 'the interval between the major lines of latitudes and longitudes. If nil, internally determined. (units: degrees) (this is a UMPACK parameter, which is nullified when uminit or grfrm is called)'],
['dgridmn', nil, 'the interval between the minor lines of latitudes and longitudes. If nil, internally determined. (units: degrees) (this is a UMPACK parameter, which is nullified when uminit or grfrm is called)']
)
def set_map(options)
@@map.set(options)
end
@@next_map = nil
def next_map(options)
if options.is_a?(Hash)
@@next_map = options
else
raise TypeError,"Hash expected"
end
nil
end
def map(options=nil)
if @@next_map
options = ( options ? @@next_map.update(options) : @@next_map )
@@next_map = nil
end
opts = @@map.interpret(options)
DCL.umplim if opts['lim']
DCL.umpset('dgridmj',opts['dgridmj']) if opts['dgridmj']
DCL.umpset('dgridmn',opts['dgridmn']) if opts['dgridmn']
DCL.umpgrd if opts['grid']
if opts['vpt_boundary']
if opts['vpt_boundary'].is_a?(Integer)
idx = opts['vpt_boundary']
else
idx = 1
end
DCL.slpvpr( idx )
end
if opts['wwd_boundary']
if opts['wwd_boundary'].is_a?(Integer)
idx = opts['wwd_boundary']
else
idx = 1
end
DCL.slpwwr( idx )
end
DCL.umpmap('coast_world') if opts['coast_world']
DCL.umpmap('coast_japan') if opts['coast_japan']
if opts['fill']
DCL.umfmap('coast_world') if opts['coast_world']
DCL.umfmap('coast_japan') if opts['coast_japan']
end
DCL.umpmap('border_world') if opts['border_world']
DCL.umpmap('plate_world') if opts['plate_world']
DCL.umpmap('state_usa') if opts['state_usa']
DCL.umpmap('pref_japan') if opts['pref_japan']
nil
end
def line(gphys, newframe=true, options=nil)
gropn_1_if_not_yet
if newframe!=true && newframe!=false
raise ArgumentError, "2nd arg (newframe) must be true or false"
end
if ! defined?(@@line_options)
@@line_options = Misc::KeywordOptAutoHelp.new(
['title', nil, 'Title of the figure(if nil, internally determined)'],
['annotate', true, 'if false, do not put texts on the right margin even when newframe==true'],
['exchange', false, 'whether to exchange x and y axes'],
['index', 1, 'line/mark index'],
['type', 1, 'line type'],
['label', nil, 'if a String is given, it is shown as the label'],
['max', nil, 'maximam data value'],
['min', nil, 'minimam data value'],
['legend', nil, 'legend to annotate the line type and index. nil (defalut -- do not show); a String as the legend; true to use the name of the GPhys as the legend'],
['legend_vx', nil, '(effective if legend) viewport x values of the lhs of the legend line (positive float); or nil for automatic settting (shown to the right of vpt); or move it to the left relatively (negtive float)'],
['legend_dx', nil, '(effective if legend) length of the legend line'],
['legend_vy', nil, '(effective if legend) viewport y value of the legend (Float; or nil for automatic settting)'],
['legend_size', nil, '(effective if legend) character size of the legend']
)
end
opts = @@line_options.interpret(options)
gp = gphys.first1D
window = ( @@next_fig['window'] if @@next_fig ) || @@fig['window']
window = ( window ? window.dup : [nil, nil, nil, nil])
max = opts['max']; min = opts['min']
if !opts['exchange']
x = gp.coord(0)
y = gp.data
window[2] = min if min
window[3] = max if max
else
y = gp.coord(0)
x = gp.data
window[0] = min if min
window[1] = max if max
end
if newframe
fig(x, y, {'window'=>window})
axes(x, y)
title( (opts['title'] || gp.data.get_att('long_name')) )
annotate(gp.lost_axes) if opts['annotate']
end
if opts['label']
lcharbk = DCL.sgpget('lchar')
DCL.sgpset('lchar',true)
DCL.sgsplc(opts['label'])
end
DCL.uulinz(x.val, y.val, opts['type'], opts['index'])
DCL.sgpset('lchar',lcharbk) if opts['label']
legend = opts['legend']
if legend
legend = gp.name if legend==true
DCLExt::legend(legend,opts['type'],opts['index'],true,
opts['legend_size'],opts['legend_vx'],opts['legend_dx'],
opts['legend_vy'],newframe)
end
nil
end
def mark(gphys, newframe=true, options=nil)
gropn_1_if_not_yet
if newframe!=true && newframe!=false
raise ArgumentError, "2nd arg (newframe) must be true or false"
end
if ! defined?(@@mark_options)
@@mark_options = Misc::KeywordOptAutoHelp.new(
['title', nil, 'Title of the figure(if nil, internally determined)'],
['annotate', true, 'if false, do not put texts on the right margin even when newframe==true'],
['exchange', false, 'whether to exchange x and y axes'],
['index', 1, 'mark index'],
['type', 2, 'mark type'],
['size', 0.01, 'marks size'],
['max', nil, 'maximam data value'],
['min', nil, 'minimam data value'],
['legend', nil, 'legend to annotate the mark type, index, and size. nil (defalut -- do not to show); a String as the legend; true to use the name of the GPhys as the legend'],
['legend_vx', nil, '(effective if legend) viewport x values of the lhs of the legend line (positive float); or nil for automatic settting (shown to the right of vpt); or move it to the left relatively (negtive float)'],
['legend_vy', nil, '(effective if legend) viewport y value of the legend (Float; or nil for automatic settting)'],
['legend_size', nil, '(effective if legend) character size of the legend']
)
end
opts = @@mark_options.interpret(options)
gp = gphys.first1D
window = ( @@next_fig['window'] if @@next_fig ) || @@fig['window']
window = ( window ? window.dup : [nil, nil, nil, nil])
max = opts['max']; min = opts['min']
if !opts['exchange']
x = gp.coord(0)
y = gp.data
window[2] = min if min
window[3] = max if max
else
y = gp.coord(0)
x = gp.data
window[0] = min if min
window[1] = max if max
end
if newframe
fig(x, y, {'window'=>window})
axes(x, y)
title( (opts['title'] || gp.data.get_att('long_name')) )
annotate(gp.lost_axes) if opts['annotate']
end
DCL.uumrkz(x.val, y.val, opts['type'], opts['index'], opts['size'])
legend = opts['legend']
if legend
legend = gp.name if legend==true
DCLExt::legend(legend,opts['type'],opts['index'],false,
opts['legend_size'],opts['legend_vx'],nil,
opts['legend_vy'],newframe,opts['size'])
end
nil
end
@@linear_contour_options = Misc::KeywordOptAutoHelp.new(
['min', nil, 'minimum contour level'],
['max', nil, 'maximum contour level'],
['nlev', nil, 'number of levels'],
['interval', nil, 'contour interval'],
['nozero', nil, 'delete zero contour'],
['coloring', false, 'set color contours with ud_coloring'],
['clr_min', 13, '(if coloring) minimum color number for the minimum data values'],
['clr_max', 99, '(if coloring) maximum color number for the maximum data values']
)
def set_linear_contour_options(options)
@@linear_contour_options.set(options)
end
@@next_linear_contour_options = nil
def next_linear_contour_options(options)
if options.is_a?(Hash)
@@next_linear_contour_options = options
else
raise TypeError,"Hash expected"
end
nil
end
def tone_and_contour(gphys, newframe=true, options=nil)
options ? topt=@@contour_options.select_existent(options) : topt=nil
options ? copt=@@tone_options.select_existent(options) : copt=nil
tone(gphys, newframe, topt)
contour(gphys, false, copt)
end
@@contour_levels = Misc::KeywordOptAutoHelp.new(
['log', nil, 'approximately log-scaled levels (by using DCLExt::quasi_log_levels)'],
['log_cycle', 3, '(if log) number of levels in one-order (1 or 2 or 3)'],
['levels', nil, 'contour levels (Array/NArray of Numeric)'],
['index', nil, '(if levels) line index(es) (Array/NArray of integers, Integer, or nil)'],
['line_type',nil, '(if levels) line type(s) (Array/NArray of integers, Integer, or nil)'],
['label', nil, '(if levels) contour label(s) (Array/NArray of String, String, true, false, nil). nil is recommended.'],
['label_height',nil,'(if levels) label height(s) (Array/NArray of Numeric, Numeric, or nil). nil is recommended.']
)
@@set_contour_levels=false
def set_contour_levels(options)
opts = @@contour_levels.interpret(options)
_set_contour_levels_(opts)
end
def _set_contour_levels_(opts)
raise ArgumentError, "'levels' must be explicitly set" if !opts['levels']
DCLExt.ud_set_contour(opts['levels'],opts['index'],opts['line_type'],
opts['label'],opts['label_height'])
@@set_contour_levels=true
nil
end
def clear_contour_levels
@@set_contour_levels=false
DCL.udiclv # this may not be needed
nil
end
def set_contour(options)
@@contour_options.set(options)
end
@@next_contour = nil
def next_contour(options)
if options.is_a?(Hash)
@@next_contour = options
else
raise TypeError,"Hash expected"
end
nil
end
@@contour_options = Misc::KeywordOptAutoHelp.new(
['title', nil, 'Title of the figure(if nil, internally determined)'],
['annotate', true, 'if false, do not put texts on the right margin even when newframe==true'],
['transpose', false, 'if true, exchange x and y axes'],
['exchange', false, 'same as the option transpose'],
['map_axes', false, '[USE IT ONLY WHEN itr=10 (cylindrical)] If true, draws axes by temprarilly switching to itr=1 and calling GGraph::axes.'],
['keep', false, 'Use the contour levels used previously'],
@@linear_contour_options,
@@contour_levels
)
def contour(gphys, newframe=true, options=nil)
gropn_1_if_not_yet
if newframe!=true && newframe!=false
raise ArgumentError, "2nd arg (newframe) must be true or false"
end
if @@next_contour
options = ( options ? @@next_contour.update(options) : @@next_contour )
@@next_contour = nil
end
if @@next_linear_contour_options
options = ( options ? @@next_linear_contour_options.update(options) :
@@next_linear_contour_options )
@@next_linear_contour_options = nil
end
opts = @@contour_options.interpret(options)
gp = gphys.first2D
gp = gp.transpose(1,0) if opts['transpose'] || opts['exchange']
xax = gp.coord(0)
yax = gp.coord(1)
if map_trn?(newframe)
# /// convert to the anti-clockwise coordinate in case for map filling
# (Because of a bug in UMFMAP in DCL 5.3) -->
if ( (xax[-1].val-xax[0].val)*(yax[-1].val-yax[0].val) < 0 )
gp = gp.copy[true,-1..0]
yax = gp.coord(1)
end
# <-- ///
gp = gp.cyclic_ext(0, 360.0) #cyclic extention with lon if appropriate
xax = gp.coord(0)
elsif itr_is?(5, newframe)
gp = gp.cyclic_ext(1, 360.0) # cyclic extention along azimuth
yax = gp.coord(1)
end
if newframe
fig(xax, yax)
end
if newframe
ttl = (opts['title'] || gp.data.get_att('long_name'))
if map_trn?
map
if opts['map_axes'] && itr_is?(10)
vpt = DCL.sgqvpt
wnd = DCL.sgqwnd
if wnd.include?(DCL.glrget('rundef'))
map_fit = false
wnd = DCL.sgqtxy
cnt = DCL.umqcnt
else
map_fit = true
end
vrat = ( (vpt[3]-vpt[2]) / (vpt[1]-vpt[0]) ).abs
wrat = ( (wnd[3]-wnd[2]) / (wnd[1]-wnd[0]) ).abs
if wrat < vrat
vyoff = (vpt[3]+vpt[2])/2
dvy2 = (vpt[1]-vpt[0])*wrat/2
vpt[2] = vyoff - dvy2
vpt[3] = vyoff + dvy2
else
vxoff = (vpt[1]+vpt[0])/2
dvx2 = (vpt[3]-vpt[2])/wrat/2
vpt[0] = vxoff - dvx2
vpt[1] = vxoff + dvx2
end
trn = DCL.sgqtrn
if map_fit
fig(xax,yax, {'itr'=>1, 'new_frame'=>false, 'viewport'=>vpt})
axes(xax, yax)
title( ttl )
DCL.sgstrn(trn)
else
xax_map = xax[0..1].copy
xax_map[0] = cnt[0] + wnd[0]
xax_map[1] = cnt[0] + wnd[1]
yax_map = yax[0..1].copy
yax_map[0] = wnd[2]
yax_map[1] = wnd[3]
fig(xax_map,yax_map,{'itr'=>1, 'new_frame'=>false, 'viewport'=>vpt})
axes(xax_map,yax_map)
title( ttl )
fig(xax_map,yax_map,{'itr'=>trn, 'new_frame'=>false, 'viewport'=>vpt, 'map_fit'=>false, 'map_axis'=>cnt, 'map_window'=>wnd})
end
else
title( ttl )
end
elsif itr_is?(5)
polar_coordinate_boundaries(xax,yax)
title( ttl )
else
axes(xax, yax)
title( ttl )
end
annotate(gp.lost_axes) if opts['annotate']
end
if !opts['keep'] or DCL.udqcln==0
if !opts['levels'] && opts['log']
levels, mjmn = DCLExt.quasi_log_levels_z(gp.data.val, opts['nlev'],
opts['max'], opts['min'], opts['log_cycle'])
opts['levels'] = levels
opts['index'] = NArray.to_na(mjmn)*2 + 1 if !opts['index']
opts['label'] = true if opts['label'].nil?
end
if (opts['levels'])
backup = @@set_contour_levels
_set_contour_levels_(opts)
@@set_contour_levels = backup
elsif !@@set_contour_levels
DCLExt.ud_set_linear_levs(gp.data.val, opts)
end
end
saved_udparams = nil
if DCL.udqcln >= 3
lv1, = DCL.udqclv(1)
lv2, = DCL.udqclv(2)
lv3, = DCL.udqclv(3)
if lv2-lv1 != lv3-lv2
saved_udparams = DCLExt.ud_set_params({'lmsg'=>false})
end
end
DCL.uwsgxa(xax.val)
DCL.uwsgya(yax.val)
DCL.udcntz(gp.data.val)
DCLExt.ud_set_params(saved_udparams) if saved_udparams
nil
end
@@linear_tone_options = Misc::KeywordOptAutoHelp.new(
['min', nil, 'minimum tone level'],
['max', nil, 'maximum tone level'],
['nlev', nil, 'number of levels'],
['interval', nil, 'contour interval']
)
def set_linear_tone_options(options)
@@linear_tone_options.set(options)
end
@@next_linear_tone_options = nil
def next_linear_tone_options(options)
if options.is_a?(Hash)
@@next_linear_tone_options = options
else
raise TypeError,"Hash expected"
end
nil
end
@@tone_levels = Misc::KeywordOptAutoHelp.new(
['log', nil, 'approximately log-scaled levels (by using DCLExt::quasi_log_levels)'],
['log_cycle', 3, '(if log) number of levels in one-order (1 or 2 or 3)'],
['levels', nil, 'tone levels (Array/NArray of Numeric). Works together with patterns'],
['patterns', nil, 'tone patters (Array/NArray of Numeric). Works together with levels']
)
@@set_tone_levels=false
def set_tone_levels(options)
opts = @@tone_levels.interpret(options)
_set_tone_levels_(opts)
end
def _set_tone_levels_(opts)
if !opts['levels'] && !opts['patterns']
end
if opts['levels']
levels = opts['levels']
else
raise ArgumentError,"'levels' must be explicitly set"
end
if opts['patterns']
patterns = opts['patterns']
else
nlev = levels.length - 1
itpat = DCL.ueiget('itpat')
iclr1 = DCL.ueiget('icolor1')
iclr2 = DCL.ueiget('icolor2')
patterns = (0...nlev).collect{|i|
(((iclr2-iclr1)/(nlev-1.0)*i+iclr1).round) * 1000 + itpat
}
end
DCLExt.ue_set_tone(levels,patterns)
@@set_tone_levels=true
nil
end
def clear_tone_levels
@@set_tone_levels=false
nil
end
def set_tone(options)
@@tone_options.set(options)
end
@@next_tone = nil
def next_tone(options)
if options.is_a?(Hash)
@@next_tone = options
else
raise TypeError,"Hash expected"
end
nil
end
@@tone_options = Misc::KeywordOptAutoHelp.new(
['title', nil, 'Title of the figure(if nil, internally determined)'],
['annotate', true, 'if false, do not put texts on the right margin even when newframe==true'],
['ltone', true, 'Same as udpack parameter ltone'],
['tonf', false, 'Use DCL.uetonf instead of DCL.uetone'],
['tonc', false, 'Use DCL.uetonc instead of DCL.uetone'],
['clr_min', nil, 'if an integer (in 10..99) is specified, used as the color number for the minimum data values. (the same can be done by setting the uepack parameter "icolor1")'],
['clr_max', nil, 'if an integer (in 10..99) is specified, used as the color number for the maximum data values. (the same can be done by setting the uepack parameter "icolor2")'],
['transpose', false, 'if true, exchange x and y axes'],
['exchange', false, 'same as the option transpose'],
['map_axes', false, '[USE IT ONLY WHEN itr=10 (cylindrical)] If true, draws axes by temprarilly switching to itr=1 and calling GGraph::axes.'],
['keep', false, 'Use the tone levels and patterns used previously'],
@@linear_tone_options,
@@tone_levels
)
def tone(gphys, newframe=true, options=nil)
gropn_1_if_not_yet
if newframe!=true && newframe!=false
raise ArgumentError, "2nd arg (newframe) must be true or false"
end
if @@next_tone
options = ( options ? @@next_tone.update(options) : @@next_tone )
@@next_tone = nil
end
if @@next_linear_tone_options
options = ( options ? @@next_linear_tone_options.update(options) :
@@next_linear_tone_options )
@@next_linear_tone_options = nil
end
opts = @@tone_options.interpret(options)
if opts['clr_min']
icolor1_bak = DCL.uepget('icolor1')
DCL.uepset('icolor1', opts['clr_min'])
end
if opts['clr_max']
icolor2_bak = DCL.uepget('icolor2')
DCL.uepset('icolor2', opts['clr_max'])
end
gp = gphys.first2D
gp = gp.transpose(1,0) if opts['transpose'] || opts['exchange']
xax = gp.coord(0)
yax = gp.coord(1)
if map_trn?(newframe)
# /// convert to the anti-clockwise coordinate in case for map filling
# (Because of a bug in UMFMAP in DCL 5.3) -->
if ( (xax[-1].val-xax[0].val)*(yax[-1].val-yax[0].val) < 0 )
gp = gp.copy[true,-1..0]
yax = gp.coord(1)
end
# <-- ///
gp = gp.cyclic_ext(0, 360.0) #cyclic extention with lon if appropriate
xax = gp.coord(0)
elsif itr_is?(5, newframe) # polar coordinate
gp = gp.cyclic_ext(1, 360.0) # cyclic extention along azimuth
yax = gp.coord(1)
end
if newframe
fig(xax, yax)
end
DCL.uwsgxa(xax.val)
DCL.uwsgya(yax.val)
if !opts['keep'] or DCL.ueqntl==0
if !opts['levels'] && opts['log']
levels, = DCLExt.quasi_log_levels_z(gp.data.val, opts['nlev'],
opts['max'], opts['min'], opts['log_cycle'])
rmiss = DCL.glrget('rmiss')
levels.unshift(rmiss) if !opts['max'] && levels[0]<0
levels.push(rmiss) if !opts['max'] && levels[-1]>0
opts['levels'] = levels
end
if opts['levels']
backup = @@set_tone_levels
_set_tone_levels_(opts)
@@set_tone_levels = backup
elsif opts['patterns']
raise "option 'patterns' is not effective unless 'levels' is specified"
elsif !@@set_tone_levels && opts['ltone']
DCL.ueitlv
DCLExt.ue_set_linear_levs(gp.data.val, opts)
else
DCL.ueitlv if !@@set_tone_levels
end
end
if opts['tonf'] && opts['ltone']
DCL.uetonf(gp.data.val)
elsif opts['tonc'] && opts['ltone']
DCL.uetonc(gp.data.val)
else
DCL.uetone(gp.data.val)
end
if newframe
ttl = (opts['title'] || gp.data.get_att('long_name'))
if map_trn?
map
if opts['map_axes'] && itr_is?(10)
vpt = DCL.sgqvpt
wnd = DCL.sgqwnd
if wnd.include?(DCL.glrget('rundef'))
map_fit = false
wnd = DCL.sgqtxy
cnt = DCL.umqcnt
else
map_fit = true
end
vrat = ( (vpt[3]-vpt[2]) / (vpt[1]-vpt[0]) ).abs
wrat = ( (wnd[3]-wnd[2]) / (wnd[1]-wnd[0]) ).abs
if wrat < vrat
vyoff = (vpt[3]+vpt[2])/2
dvy2 = (vpt[1]-vpt[0])*wrat/2
vpt[2] = vyoff - dvy2
vpt[3] = vyoff + dvy2
else
vxoff = (vpt[1]+vpt[0])/2
dvx2 = (vpt[3]-vpt[2])/wrat/2
vpt[0] = vxoff - dvx2
vpt[1] = vxoff + dvx2
end
trn = DCL.sgqtrn
if map_fit
fig(xax,yax, {'itr'=>1, 'new_frame'=>false, 'viewport'=>vpt})
axes(xax, yax)
title( ttl )
DCL.sgstrn(trn)
else
xax_map = xax[0..1].copy
xax_map[0] = cnt[0] + wnd[0]
xax_map[1] = cnt[0] + wnd[1]
yax_map = yax[0..1].copy
yax_map[0] = wnd[2]
yax_map[1] = wnd[3]
fig(xax_map,yax_map,{'itr'=>1, 'new_frame'=>false, 'viewport'=>vpt})
axes(xax_map,yax_map)
title( ttl )
fig(xax_map,yax_map,{'itr'=>trn, 'new_frame'=>false, 'viewport'=>vpt, 'map_fit'=>false, 'map_axis'=>cnt, 'map_window'=>wnd})
end
else
title( ttl )
end
elsif itr_is?(5)
polar_coordinate_boundaries(xax,yax)
title( ttl )
else
axes(xax, yax)
title( ttl )
end
annotate(gp.lost_axes) if opts['annotate']
end
DCL.uepset('icolor1', icolor1_bak) if opts['clr_min']
DCL.uepset('icolor2', icolor2_bak) if opts['clr_max']
nil
end
# < vector >
def set_unit_vect_options(options)
DCLExt.set_unit_vect_options(options)
end
def next_unit_vect_options(options)
DCLExt.next_unit_vect_options(options)
end
@@vxfxratio=nil
@@vyfyratio=nil
def vector(fx, fy, newframe=true, options=nil)
gropn_1_if_not_yet
if newframe!=true && newframe!=false
raise ArgumentError, "2nd arg (newframe) must be true or false"
end
if ! defined?(@@vector_options)
@@vector_options = Misc::KeywordOptAutoHelp.new(
['title', nil, 'Title of the figure(if nil, internally determined)'],
['annotate', true, 'if false, do not put texts on the right margin even when newframe==true'],
['transpose', false, 'if true, exchange x and y axes'],
['exchange', false, 'same as the option transpose'],
['map_axes', false, '[USE IT ONLY WHEN itr=10 (cylindrical)] If true, draws axes by temprarilly switching to itr=1 and calling GGraph::axes.'],
['flow_vect', true, 'If true, use DCLExt::flow_vect to draw vectors; otherwise, DCL::ugvect is used.'],
['keep', false, 'Use the same vector scaling as in the previous call. -- Currently, works only when "flow_vect" is true'],
['xintv', 1, '(Effective only if flow_vect) interval of data sampling in x'],
['yintv', 1, '(Effective only if flow_vect) interval of data sampling in y'],
['factor', 1.0, '(Effective only if flow_vect) scaling factor to strech/reduce the arrow lengths'],
['unit_vect', false, 'Show the unit vector'],
['max_unit_vect', false, '(Effective only if flow_vect && unit_vect) If true, use the maximum arrows to scale the unit vector; otherwise, normalize in V coordinate.'],
['flow_itr5', false, 'If true, use DclExt::flow_itr5 to draw vectors on 2-dim polar coordinate. Should be set DCL.sgstrn(5)']
)
end
opts = @@vector_options.interpret(options)
fx = fx.first2D.copy
fy = fy.first2D.copy
fx = fx.transpose(1,0) if opts['transpose'] || opts['exchange']
fy = fy.transpose(1,0) if opts['transpose'] || opts['exchange']
sh = fx.shape
if sh != fy.shape
raise ArgumentError, "shapes of fx and fy do not agree with each other"
end
if ((xi=opts['xintv']) >= 2)
idx = NArray.int((sh[0]/xi.to_f).ceil).indgen!*xi # [0,xi,2*xi,..]
fx = fx[idx, true]
fy = fy[idx, true]
end
if ((yi=opts['yintv']) >= 2)
idx = NArray.int((sh[1]/yi.to_f).ceil).indgen!*yi # [0,yi,2*yi,..]
fx = fx[true, idx]
fy = fy[true, idx]
end
xax = fx.coord(0)
yax = fy.coord(1)
if map_trn?(newframe)
# /// convert to the anti-clockwise coordinate in case for map filling
# (Because of a bug in UMFMAP in DCL 5.3) -->
if ( (xax[-1].val-xax[0].val)*(yax[-1].val-yax[0].val) < 0 )
fx = fx.copy[true,-1..0]
fy = fy.copy[true,-1..0]
yax = fx.coord(1)
end
# <-- ///
fx = fx.cyclic_ext(0, 360.0) #cyclic extention with lon if appropriate
fy = fy.cyclic_ext(0, 360.0) #cyclic extention with lon if appropriate
xax = fx.coord(0)
elsif itr_is?(5, newframe)
fx = fx.cyclic_ext(1, 360.0) #cyclic extention along azimuth
fy = fy.cyclic_ext(1, 360.0) #cyclic extention along azimuth
yax = fx.coord(1)
end
if newframe
fig(xax, yax)
end
if newframe
if opts['title']
ttl = opts['title']
else
fxnm = fx.data.get_att('long_name') || fx.name
fynm = fy.data.get_att('long_name') || fy.name
ttl = '('+fxnm+','+fynm+')'
end
if map_trn?
map
if opts['map_axes'] && itr_is?(10)
vpt = DCL.sgqvpt
wnd = DCL.sgqwnd
if wnd.include?(DCL.glrget('rundef'))
map_fit = false
wnd = DCL.sgqtxy
cnt = DCL.umqcnt
else
map_fit = true
end
vrat = ( (vpt[3]-vpt[2]) / (vpt[1]-vpt[0]) ).abs
wrat = ( (wnd[3]-wnd[2]) / (wnd[1]-wnd[0]) ).abs
if wrat < vrat
vyoff = (vpt[3]+vpt[2])/2
dvy2 = (vpt[1]-vpt[0])*wrat/2
vpt[2] = vyoff - dvy2
vpt[3] = vyoff + dvy2
else
vxoff = (vpt[1]+vpt[0])/2
dvx2 = (vpt[3]-vpt[2])/wrat/2
vpt[0] = vxoff - dvx2
vpt[1] = vxoff + dvx2
end
trn = DCL.sgqtrn
if map_fit
fig(xax,yax,{'itr'=>1, 'new_frame'=>false, 'viewport'=>vpt})
axes(xax, yax)
title( ttl )
DCL.sgstrn(trn)
else
xax_map = xax[0..1].copy
xax_map[0] = cnt[0] + wnd[0]
xax_map[1] = cnt[0] + wnd[1]
yax_map = yax[0..1].copy
yax_map[0] = wnd[2]
yax_map[1] = wnd[3]
fig(xax_map,yax_map,{'itr'=>1, 'new_frame'=>false, 'viewport'=>vpt})
axes(xax_map,yax_map)
title( ttl )
fig(xax_map,yax_map,{'itr'=>trn, 'new_frame'=>false, 'viewport'=>vpt, 'map_fit'=>false, 'map_axis'=>cnt, 'map_window'=>wnd})
end
else
title( ttl )
end
elsif itr_is?(5)
polar_coordinate_boundaries(xax,yax)
title(ttl)
else
axes(xax, yax)
title(ttl)
end
annotate(fx.lost_axes) if opts['annotate']
end
DCL.uwsgxa(xax.val)
DCL.uwsgya(yax.val)
if opts['flow_itr5']
if itr_is?(5)
DCLExt.flow_itr5( fx, fy, opts['factor'], opts['unit_vect'] )
else
raise "flow_itr5 option should use with itr=5."
end
elsif opts['flow_vect']
uninfo = DCLExt.flow_vect(fx.val, fy.val, opts['factor'], 1, 1,
(opts['keep']&& @@vxfxratio), (opts['keep'] && @@vyfyratio) )
@@vxfxratio, @@vyfyratio, = uninfo
if opts['unit_vect']
if opts['max_unit_vect']
DCLExt.unit_vect(*uninfo)
else
DCLExt.unit_vect(*uninfo[0..1])
end
end
else
before=DCLExt.ug_set_params({'lunit'=>true}) if opts['unit_vect']
DCL.ugvect(fx.val, fy.val)
DCLExt.ug_set_params(before) if opts['unit_vect']
end
nil
end
end
end
if $0 == __FILE__
include NumRu
# < read command line option if any >
if ARGV.length == 1
iws = ARGV[0].to_i
else
iws = 1
end
#< graphic initialization >
DCL.gropn(iws)
DCL.sldiv('y',2,2)
DCL.sgpset('lcntl', false)
DCL.sgpset('lfull',true)
DCL.sgpset('lfprop',true)
DCL.uzfact(0.9)
# < show default parameters >
xdummy = ydummy = nil
begin
print "** GGraph::fig options **\n"
GGraph.fig(xdummy, ydummy, 'help'=>true)
rescue
end
begin
print "** GGraph::axes options **\n"
GGraph.axes(xdummy, ydummy, 'help'=>true)
rescue
end
gp_dummy = nil
begin
print "** GGraph::line options **\n"
GGraph.line(gp_dummy,true,'help'=>true)
rescue
end
begin
print "** GGraph::mark options **\n"
GGraph.mark(gp_dummy,true,'help'=>true)
rescue
end
begin
print "** GGraph::contour options **\n"
GGraph.contour(gp_dummy,true,'help'=>true)
rescue
end
begin
print "** GGraph::tone options **\n"
GGraph.tone(gp_dummy,true,'help'=>true)
rescue
end
begin
print "** GGraph::map options **\n"
GGraph.map('help'=>true)
rescue
end
#< graphic test / demonstration >
file = '../../testdata/T.jan.nc'
gphys = GPhys::NetCDF_IO.open(file, 'T')
#/ graph 1 /
GGraph.set_fig('viewport'=>[0.25,0.75,0.12,0.62])
GGraph.line(gphys.cut(true,35,true).average(0), true)
#/ graph 2 /
GGraph.next_fig('itr'=>2)
GGraph.next_axes('yunits'=>'','xunits'=>'')
GGraph.line(gphys.cut(true,35,true).average(0), true,
'exchange'=>true, 'index'=>3, 'title'=>'TEMPERATURE', 'annotate'=>false, 'min'=>-100, 'max'=>20)
GGraph.mark(gphys.cut(true,35,true).average(0), false,
'exchange'=>true, 'type'=>3)
#/ graph 3 /
GGraph.set_fig('window'=>[nil, 0.1, -70, 20])
GGraph.mark(gphys.cut(true,35,true).average(0))
#/ graph 4 /
GGraph.next_fig('window'=>[nil, nil, -80, 30])
GGraph.mark(gphys.cut(true,35,true).average(0), true, 'max'=>25)
GGraph.line(gphys.cut(true,35,true).average(0), false)
GGraph.set_fig('window'=>nil)
#/ graph 5 /
GGraph.contour(gphys)
#/ graph 6 /
GGraph.next_fig('itr'=>2)
GGraph.contour(gphys.cut(135,true,true))
#/ graph 7 /
GGraph.set_axes('xunits'=>'', 'yunits'=>'')
GGraph.contour(gphys,true, 'min'=>0, 'coloring'=>true)
#/ graph 8 /
GGraph.set_fig('viewport'=>[0.2,0.8,0.15,0.55])
GGraph.contour(gphys,true, 'nozero'=>true)
#/ graph 9 /
GGraph.contour(gphys,true, 'min'=>10, 'int'=>3)
DCL.udpset('lmsg',false)
GGraph.contour(gphys,false, 'max'=>-10, 'int'=>3)
DCL.udpset('lmsg',true)
#/ graph 10 /
GGraph.set_contour_levels('levels'=>[-10,-5,0,5,10],'index'=>[3,1],
'line_type'=>2)
GGraph.contour(gphys)
GGraph.clear_contour_levels
#/ graph 11 /
GGraph.contour(gphys, true, 'levels'=>[0,10,20], 'index'=>3)
#/ graph 12 /
GGraph.set_linear_contour_options('nlev'=>24)
GGraph.next_linear_contour_options('coloring'=>true)
GGraph.contour(gphys)
#/ graph 13 /
GGraph.tone(gphys, true, 'min'=>0)
sv = DCLExt.ud_set_params('indxmj'=>1,'indxmn'=>1)
GGraph.contour(gphys, false)
DCLExt.ud_set_params(sv)
GGraph.color_bar
#/ graph 14 /
GGraph.tone(gphys, true, 'ltone'=>false)
GGraph.contour(gphys, false)
#/ graph 15 /
GGraph.next_fig('itr'=>3)
GGraph.contour(gphys[1..-1,true,true])
#/ graph 16 /
GGraph.tone(gphys, true, 'levels'=>[-20,-10,0,10,20],'patterns'=>[12999,30999,45999,65999,75999,85999])
GGraph.color_bar('vlength'=>0.25,'landscape'=>true)
#/ graph 17 /
GGraph.tone(gphys, true, 'levels'=>[-20,-10,0,10,20],'patterns'=>[30999,45999,65999,75999,85999])
DCLExt.color_bar('vlength'=>0.25, 'left'=>true)
#/ graph 18 /
GGraph.tone(gphys, true, 'levels'=>[-20,-10,0,10,20],'patterns'=>[30999,45999,65999,75999])
#DCLExt.color_bar('vlength'=>0.25, 'left'=>true)
DCLExt.color_bar('vlength'=>0.25, 'levels'=>[-20,-10,0,10,20],'patterns'=>[30999,45999,65999,75999])
#/ graph 19 /
GGraph.set_fig('viewport'=>[0.3,0.7,0.1,0.6])
GGraph.contour(gphys,true, 'min'=>0, 'coloring'=>true, 'transpose'=>true)
GGraph.tone(gphys, false, 'levels'=>[10,20], 'patterns'=>[80999], 'transpose'=>true)
#/ graph 20 /
GGraph.set_fig('viewport'=>[0.25,0.75,0.15,0.6])
GGraph.vector(gphys+10,gphys+10,true,
{'unit_vect'=>true, 'xintv'=>2, 'yintv'=>2})
#/ graph 21 /
GGraph.next_unit_vect_options({'inplace'=>false,'vxuloc'=>0.17,'vyuloc'=>0.07})
GGraph.vector(gphys+10,gphys-10,true,
{'unit_vect'=>true, 'max_unit_vect'=>true, 'xintv'=>2, 'yintv'=>2})
#/ graph 22 /
GGraph.vector(gphys+10,gphys+10,true,
{'unit_vect'=>true, 'flow_vect'=>false, 'xintv'=>2, 'yintv'=>2})
#GGraph.color_bar('help'=>true)
#/ graph 23 /
GGraph.set_fig('viewport'=>[0.2,0.8,0.15,0.55])
GGraph.tone(gphys, true, 'levels'=>[-16,-4,-1,0,1,4,16],'patterns'=>[12999,21999,30999,45999,65999,75999,85999,95999])
GGraph.color_bar('constwidth'=>true,'vlength'=>0.6,'landscape'=>true,'labelintv'=>1)
GGraph.color_bar('constwidth'=>true,'vlength'=>0.35,'index'=>1)
#/ graph 24 /
GGraph.set_map('coast_world'=>true)
# -- mercator --
GGraph.next_fig('itr'=>11)
GGraph.next_map('fill'=>true)
GGraph.tone(gphys, true)
GGraph.color_bar
#/ graph 25 /
# -- orthographic --
GGraph.set_fig('viewport'=>[0.25,0.75,0.1,0.6])
GGraph.next_fig('itr'=>30,'map_axis'=>[135,60,0],'map_radius'=>60)
GGraph.tone(gphys, true)
sv = DCLExt.ud_set_params('indxmj'=>991,'indxmn'=>991)
GGraph.contour(gphys, false)
DCLExt.ud_set_params(sv)
GGraph.color_bar('landscape'=>true) # ,'vlength'=>0.6
#/ graph 26 /
# -- polar stero --
GGraph.next_fig('itr'=>31)
DCL.sgpset('lclip',true)
GGraph.next_map('vpt_boundary'=>3,'dgridmj'=>20,'dgridmn'=>10)
GGraph.tone(gphys, true)
GGraph.color_bar
#/ graph 27 /
# axes for itr=10 (lon-lat projection) -- map_fit=T, map_axes=F (default)
GGraph.next_fig('itr'=>10)
GGraph.contour(gphys,true,'title'=>'map_fit=T, map_axes=F (default)')
#/ graph 28 /
# axes for itr=10 (lon-lat projection) -- map_fit=T, map_axes=T
GGraph.next_fig('itr'=>10)
GGraph.contour(gphys, true,'map_axes'=>true,'title'=>'map_fit=T map_axes=T')
DCL::sgtxzr(0.5,0.64,'Try GPHYSDIR/sample/ggraph_mapfit-axes_dr002687.rb',0.022,0,0.0,22)
DCL::sgtxzr(0.5,0.6,'for more examples',0.022,0,0.0,22)
#/ graph 29 /
# [xy]xmaplabel options for itr=10 -- when it is off (default)
GGraph.next_fig('itr'=>10)
GGraph.tone(gphys, true,'map_axes'=>true,'title'=>'default axes')
#/ graph 30 /
# [xy]xmaplabel options for itr=10 -- label as 90E, 90W, 30N, 30S etc
# sample 1
GGraph.next_fig('itr'=>10)
GGraph.next_axes('xmaplabel'=>'lon','ymaplabel'=>'lat')
GGraph.tone(gphys, true,'map_axes'=>true,'title'=>'lon/lat axes')
DCL::sgtxzr(0.5,0.64,'Try GPHYSDIR/sample/ggraph_latlon_labelling_dr002690.rb',0.022,0,0.0,22)
DCL::sgtxzr(0.5,0.6,'for more options',0.022,0,0.0,22)
#/ graph 31 /
# log-level tone/contour (1)
GGraph.set_fig('itr'=>1,'viewport'=>[0.2,0.85,0.22,0.58])
GGraph.tone(gphys,true,'log'=>true, 'nlev'=>5, 'log_cycle'=>3 )
GGraph.contour(gphys,false,'log'=>true, 'nlev'=>5, 'log_cycle'=>3)
GGraph.color_bar('log'=>true, 'landscape'=>true, 'vlength'=>0.35)
DCL::sgtxzr(0.5,0.68,"With 'log' option",0.022,0,0.0,22)
#/ graph 32 /
# log-level tone/contour (2)
GGraph.set_fig('itr'=>1,'viewport'=>[0.2,0.85,0.22,0.58])
GGraph.tone(gphys,true,'log'=>true, 'nlev'=>5, 'min'=>0.03, 'log_cycle'=>2 )
GGraph.contour(gphys,false,'log'=>true, 'nlev'=>5, 'min'=>0.05, 'log_cycle'=>3)
GGraph.color_bar('log'=>true, 'vlength'=>0.25)
DCL::sgtxzr(0.5,0.68,"With 'log' option",0.022,0,0.0,22)
#/ graph 33/
# vector field on the polar coordinate (1)
# -- demo for flow_itr5 option of GGraph.vector
#### create longitude, latitude, radial axes #####
vrad = VArray.new( NArray.float(11).indgen! * 0.06 + 0.4 ).rename("rad")
vlat = VArray.new( NArray.float(21).indgen! * 9 - 90 ).rename("lat")
vlon = VArray.new( NArray.float(41).indgen! * 9 ).rename("lon")
radax = Axis.new().set_pos(vrad)
latax = Axis.new().set_pos(vlat)
lonax = Axis.new().set_pos(vlon)
grid_meridional = Grid.new(radax, latax)
grid_equator = Grid.new(radax, lonax)
#### create vector field in the meridional plane #####
frad = vrad - 0.7
frad = frad.reshape!(vrad.length,1)
flat = (3*vlat/180*Math::PI).cos
flat = flat.reshape!(1,vlat.length)
vellat = frad*flat
vellat.rename!('vellat')
gp_vellat = GPhys.new(grid_meridional, vellat)
frad = (vrad-0.4)*(vrad-1)
frad = frad.reshape!(vrad.length,1)
flat = (3*vlat/180*Math::PI).sin
flat = flat.reshape!(1,vlat.length)
velrad = frad*flat
velrad.rename!('velrad')
gp_velrad = GPhys.new(grid_meridional, velrad)
#### draw vector field in the meridional plane #####
# DCL.gropn(1)
# GGraph.set_fig('viewport'=>[0.25,0.75,0.12,0.62])
GGraph.next_fig('itr'=>5)
GGraph.vector(gp_velrad, gp_vellat, true,
'flow_itr5'=>true,'factor'=>1e-1)
GGraph.next_fig('itr'=>5)
GGraph.tone(gp_velrad,true)
GGraph.vector(gp_velrad, gp_vellat, false,
'flow_itr5'=>true,'factor'=>1e-1)
#/ graph 34/
# vector field on the polar coordinate (2)
# -- demo for flow_itr5 option of GGraph.vector
#### create vector field in the equatorial plane #####
frad = vrad - 0.7
frad = frad.reshape!(vrad.length,1)
flon = (3*vlon/180*Math::PI).cos
flon = flon.reshape!(1,vlon.length)
vellon = frad*flon
vellon.rename!('vellon')
gp_vellon = GPhys.new(grid_equator, vellon)
frad = (vrad-0.4)*(vrad-1)
frad = frad.reshape!(vrad.length,1)
flon = (3*vlon/180*Math::PI).sin
flon = flon.reshape!(1,vlon.length)
velrad = frad*flon
velrad.rename!('velrad')
gp_velrad = GPhys.new(grid_equator, velrad)
#### draw vector field in the equatorial plane #####
GGraph.next_fig('itr'=>5)
GGraph.vector(gp_velrad, gp_vellon, true,
'flow_itr5'=>true,'factor'=>1e-1)
GGraph.next_fig('itr'=>5)
GGraph.tone(gp_velrad,true)
GGraph.vector(gp_velrad, gp_vellon, false,
'flow_itr5'=>true,'factor'=>1e-1)
DCL.grcls
end
syntax highlighted by Code2HTML, v. 0.9.1