require "numru/gphys" require "numru/dcl" require "numru/misc" require "date" ############################################################ =begin =module NumRu::GGraph and others in ggraph.rb ==Index * (()) * (()) Sets the strings to appear in the bottom margin. * (()) 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_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. * ((<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. * ((<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) "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] "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_lat_range" nil # (for itr<20: cylindrical map projections) # latitudinal range to draw the map. By default # (nil), the map is drawn between 75E and 75S. # (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) "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,yax_cyclic=nil) Draw boundaries in a polar coordinate. ARGUMENTS * xax (VArray): Grid points of the radial coordinate. * yax (VArray): Grid points of the azimuthal coordinate. * yax_cyclic : Should give true value when the azimuthal coordinate is cyclic. 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) "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) "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 "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 "help" false # show help message if true RETURN VALUE * nil ---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 "min" nil # minimum contour value "max" nil # maximum contour value "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 id "clr_max" 100 # (if coloring) maximum color id "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 minimum color number. (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 maximum color number. (the same can be done # by setting the uepack parameter "icolor2") "transpose" false # if true, exchange x and y axes "min" nil # minimum contour value "max" nil # maximum contour value "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 "flow_vect" true # If true, use DCLExt::flow_vect to draw # vectors; otherwise, DCL::ugvect is used. "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' 100 (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: ===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. ===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=100) # 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 id (Integer) # 'clr_max' 100 (if coloring) maximum color id (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'] || 100 ) 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 > 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 > 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 > 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 > 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 ############################################################ # <<< 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) 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 ux0,ux1,uy0,uy1 = DCL.sgqwnd 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 vyfyratio = factor*cn*ay 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 ###################################### # <<< 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) "] ) def set_color_bar_options(options) @@color_bar_options.set(options) 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 set at same time\n" end landscape = opt["landscape"] || !opt["portrait"] portrait = ! landscape miss = DCL::glrget("rmiss") if !levels.nil? then nlevel = levels.length levels = NArray.to_na(levels) if levels.class==Array if patterns.length != (nlevel-1) then raise "patterns.length must be equal levels.length - 1\n" end DCL::ueitlv DCL::uestln(levels,patterns) nton = patterns.length else nton = DCL::ueqntl if nton==0 then raise "no tone patern was set\n" end lev1 = Array.new lev2 = Array.new patterns = Array.new for n in 0..nton-1 tlev1,tlev2,ipat = DCL::ueqtlv(n+1) lev1.push(tlev1) lev2.push(tlev2) patterns.push(ipat) 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]) levels = NArray.to_na(levels) patterns = NArray.to_na(patterns) end vx1, vx2, vy1, vy2 = DCL.sgqvpt 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 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 char = DCL::chval(DCL::uyqfmt,levels[i]) 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 char = DCL::chval(DCL::uxqfmt,levels[i]) 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 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) DCL::uyaxnm("l",tick1,tick2) DCL::uyaxnm("r",tick1,tick2) 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) DCL::uxaxnm("t",tick1,tick2) DCL::uxaxnm("b",tick1,tick2) 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) DCL::grsvpt(vx1,vx2,vy1,vy2) end DCL::sgpset("lclip", true) if lclip 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 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? 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') dvx = 0.01 dvy = charsize*1.5 raise TypeError,"Array expected" if ! str_ary.is_a?(Array) vxmin,vxmax,vymin,vymax = DCL.sgqvpt vx = vxmax + dvx vy = vymax - charsize/2 str_ary.each{|str| DCL::sgtxzr(vx,vy,str,charsize,0,-1,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)'], ['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]'], ['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_lat_range', nil, '(for itr<20: cylindrical map projections) latitudinal range to draw the map. By default (nil), the map is drawn between 75E and 75S. (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? itr = DCL.sgqtrn case itr when 1..9,51..99 false else true end 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['new_frame'] DCL.grfrm else DCL.grfig end DCL.grsvpt(*opts['viewport']) DCL.grstrn(opts['itr']) case opts['itr'] when 1..9,51..99 # all but for map projection raise(ArgumentError, "xax and yax must be provided") if !xax or !yax if !opts['window'] 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 window=[xrange[0], xrange[1], yrange[0], yrange[1]] else window=opts['window'] end unless opts['itr']==5 then DCL.grswnd(*window) else if ! opts['similar'] vxmin,vxmax,vymin,vymax=DCL.sgqvpt simfac = (vymax-vymin)/(xrange[1]*2) similar = [simfac,0.0,0.0] else similar=opts['similar'] end DCL.grssim(*similar) end when 10..15 map_axis = opts['map_axis'] || [180.0, 0.0, 0.0] map_lat_range = opts['map_lat_range'] || [-75,75] if map_lat_range.is_a?(Range) map_lat_range = [map_lat_range.first, map_lat_range.end] end DCL::umscnt( *map_axis ) 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(-180.0,180.0,tyrange[0],tyrange[1]) sv = DCL.umpget('lglobe') DCL.umpset('lglobe', true) DCL::umpfit DCL.umpset('lglobe', sv) 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 opts['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: #{opts['itr']}" end DCL.grstrf 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)'] ) 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 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) DCL.uscset('cxttl', (opts['xtitle'] || xai['title']) ) DCL.uscset('cxunit',(opts['xunits'] || xai['units']) ) DCL.uspset('dxt', opts['xtickint']) if(opts['xtickint']) DCL.uspset('dxl', opts['xlabelint']) if(opts['xlabelint']) opts['xside'].split('').each{|s| # scan('.') also works DCL.usxaxs(s) } end if opts['yside'].length > 0 yai = _get_axinfo(yax) DCL.uscset('cyttl', (opts['ytitle'] || yai['title']) ) DCL.uscset('cyunit', (un=(opts['yunits'] || yai['units'])) ) DCL.uspset('dxt', opts['ytickint']) if(opts['ytickint']) DCL.uspset('dxl', opts['ylabelint']) if(opts['ylabelint']) opts['yside'].split('').each{|s| # scan('.') also works DCL.usyaxs(s) if s=='l' && un && un != '' DCL.uzpset('roffxt', DCL.uzpget('rsizec1')*1.5 ) end } end 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,yax_cyclic=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 unless yax_cyclic 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)'], ['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)'] ) 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.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('border_world') if opts['border_world'] DCL.umpmap('plate_world') if opts['plate_world'] DCL.umpmap('state_usa') if opts['state_usa'] DCL.umpmap('coast_japan') if opts['coast_japan'] DCL.umpmap('pref_japan') if opts['pref_japan'] nil end def line(gphys, newframe=true, options=nil) 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'] ) end opts = @@line_options.interpret(options) gp = gphys.first1D if !opts['exchange'] x = gp.coord(0) y = gp.data else y = gp.coord(0) x = gp.data end if newframe fig(x, y) 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'] nil end def mark(gphys, newframe=true, options=nil) 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'] ) end opts = @@mark_options.interpret(options) gp = gphys.first1D if !opts['exchange'] x = gp.coord(0) y = gp.data else y = gp.coord(0) x = gp.data end if newframe fig(x, y, opts['fig_params']) 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']) nil end @@linear_contour_options = Misc::KeywordOptAutoHelp.new( ['min', nil, 'minimum contour value'], ['max', nil, 'maximum contour value'], ['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 id'], ['clr_max', 100, '(if coloring) maximum color id'] ) 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 @@contour_levels = Misc::KeywordOptAutoHelp.new( ['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 contour(gphys, newframe=true, options=nil) if newframe!=true && newframe!=false raise ArgumentError, "2nd arg (newframe) must be true or false" end if ! defined?(@@contour_options) @@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'], @@linear_contour_options, @@contour_levels ) 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'] xax = gp.coord(0) yax = gp.coord(1) if newframe fig(xax, yax) end if sim_trn? \ && gp.coord(1).get_att('topology') == "circular" \ && modulo=gp.coord(1).get_att('modulo') gp = gp.cyclic_ext(1, modulo) # cyclic extention with 2nd dim. yax = gp.coord(1) yax_cyclic = true else yax_cyclic = false end if map_trn? gp = gp.cyclic_ext(0, 360.0) #cyclic extention with lon if appropriate xax = gp.coord(0) end if newframe if map_trn? map elsif sim_trn? polar_coordinate_boundaries(xax,yax,yax_cyclic) else axes(xax, yax) end title( (opts['title'] || gp.data.get_att('long_name')) ) annotate(gp.lost_axes) if opts['annotate'] 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 DCL.uwsgxa(xax.val) DCL.uwsgya(yax.val) DCL.udcntz(gp.data.val) nil end @@linear_tone_options = Misc::KeywordOptAutoHelp.new( ['min', nil, 'minimum contour value'], ['max', nil, 'maximum contour value'], ['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( ['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 tone(gphys, newframe=true, options=nil) if newframe!=true && newframe!=false raise ArgumentError, "2nd arg (newframe) must be true or false" end if ! defined?(@@tone_options) @@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 mimimum color number. (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 maximum color number. (the same can be done by setting the uepack parameter "icolor2")'], ['transpose', false, 'if true, exchange x and y axes'], @@linear_tone_options, @@tone_levels ) 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'] xax = gp.coord(0) yax = gp.coord(1) if newframe fig(xax, yax) end if sim_trn? \ && gp.coord(1).get_att('topology') == "circular" \ && modulo=gp.coord(1).get_att('modulo') gp = gp.cyclic_ext(1, modulo) # cyclic extention with 2nd dim. yax = gp.coord(1) yax_cyclic = true else yax_cyclic = false end if map_trn? gp = gp.cyclic_ext(0, 360.0) #cyclic extention with lon if appropriate xax = gp.coord(0) end DCL.uwsgxa(xax.val) DCL.uwsgya(yax.val) if opts['levels'] backup = @@set_tone_levels _set_tone_levels_(opts) @@set_tone_levels = backup 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 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) if opts['tonf'] DCL.uetonf(gp.data.val) elsif opts['tonc'] DCL.uetonc(gp.data.val) else DCL.uetone(gp.data.val) end else DCL.ueitlv if !@@set_tone_levels 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 end if newframe # axes should be drawn after uetone if map_trn? map elsif sim_trn? polar_coordinate_boundaries(xax,yax,yax_cyclic) else axes(xax, yax) end title( (opts['title'] || gp.data.get_att('long_name')) ) 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 def vector(fx, fy, newframe=true, options=nil) 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'], ['flow_vect', true, 'If true, use DCLExt::flow_vect to draw vectors; otherwise, DCL::ugvect is used.'], ['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.'] ) end opts = @@vector_options.interpret(options) fx = fx.first2D.copy fy = fy.first2D.copy sh = fx.shape if sh != fy.shape raise ArgumentError, "shapes of fx and fy do not agree with each other" end fx = fx.transpose(1,0) if opts['transpose'] fy = fy.transpose(1,0) if opts['transpose'] if ((xi=opts['xintv']) >= 2) idx = NArray.int(sh[0]/xi).indgen!*xi # [0,xi,2*xi,..] fx = fx[idx, true] fy = fy[idx, true] end if ((yi=opts['xintv']) >= 2) idx = NArray.int(sh[1]/yi).indgen!*yi # [0,yi,2*yi,..] fx = fx[true, idx] fy = fy[true, idx] end xax = fx.coord(0) yax = fy.coord(1) if newframe fig(xax, yax) end if map_trn? 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) 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 else axes(xax, yax) end title(ttl) annotate(fx.lost_axes) if opts['annotate'] end DCL.uwsgxa(xax.val) DCL.uwsgya(yax.val) if opts['flow_vect'] uninfo = DCLExt.flow_vect(fx.val, fy.val, opts['factor'] ) 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 # < 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 #< graphic test / demonstration > file = '../../testdata/T.jan.nc' gphys = GPhys::NetCDF_IO.open(file, 'T') DCL.gropn(iws) DCL.sldiv('y',2,2) DCL.sgpset('lcntl', false) DCL.sgpset('lfull',true) DCL.sgpset('lfprop',true) DCL.uzfact(0.9) #/ 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'=>'TEMERATURE', 'annotate'=>false) GGraph.mark(gphys.cut(true,35,true).average(0), false, 'exchange'=>true, 'type'=>3) #/ graph 3 / GGraph.contour(gphys) #/ graph 4 / GGraph.next_fig('itr'=>2) GGraph.contour(gphys.cut(135,true,true)) #/ graph 5 / GGraph.set_axes('xunits'=>'', 'yunits'=>'') GGraph.contour(gphys,true, 'min'=>0, 'coloring'=>true) #/ graph 6 / GGraph.set_fig('viewport'=>[0.2,0.8,0.15,0.55]) GGraph.contour(gphys,true, 'nozero'=>true) #/ graph 7 / 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 8 / GGraph.set_contour_levels('levels'=>[-10,-5,0,5,10],'index'=>[3,1], 'line_type'=>2) GGraph.contour(gphys) GGraph.clear_contour_levels #/ graph 9 / GGraph.contour(gphys, true, 'levels'=>[0,10,20], 'index'=>3) #/ graph 10 / GGraph.set_linear_contour_options('nlev'=>24) GGraph.next_linear_contour_options('coloring'=>true) GGraph.contour(gphys) #/ graph 11 / 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 12 / GGraph.tone(gphys, true, 'ltone'=>false) GGraph.contour(gphys, false) #/ graph 13 / GGraph.next_fig('itr'=>3) GGraph.contour(gphys[1..-1,true,true]) #/ graph 14 / 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 15 / 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 16 / 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 17 / 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 18 / 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 19 / 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 20 / GGraph.vector(gphys+10,gphys+10,true, {'unit_vect'=>true, 'flow_vect'=>false, 'xintv'=>2, 'yintv'=>2}) #GGraph.color_bar('help'=>true) #/ graph 21 / 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 22 / # -- mercator -- GGraph.next_fig('itr'=>11) GGraph.set_map('coast_world'=>true) GGraph.tone(gphys, true) GGraph.color_bar #/ graph 23 / # -- 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 24 / # -- polar stero -- GGraph.next_fig('itr'=>31) DCL.sgpset('lclip',true) GGraph.next_map('vpt_boundary'=>3) GGraph.tone(gphys, true) GGraph.color_bar DCL.grcls end