From: <hez...@us...> - 2010-05-01 19:58:10
|
Revision: 10960 http://plplot.svn.sourceforge.net/plplot/?rev=10960&view=rev Author: hezekiahcarty Date: 2010-05-01 19:58:03 +0000 (Sat, 01 May 2010) Log Message: ----------- (OCaml) Allow colorbars and labeling to be defined as plot elements This change is intended to make building individual plots for use with the Plplot.Plot.plot function a bit easier. Modified Paths: -------------- trunk/bindings/ocaml/plplot.ml trunk/bindings/ocaml/plplot.mli trunk/examples/ocaml/xplot01.ml Modified: trunk/bindings/ocaml/plplot.ml =================================================================== --- trunk/bindings/ocaml/plplot.ml 2010-05-01 16:16:24 UTC (rev 10959) +++ trunk/bindings/ocaml/plplot.ml 2010-05-01 19:58:03 UTC (rev 10960) @@ -1,5 +1,5 @@ (* -Copyright 2009 Hezekiah M. Carty +Copyright 2009, 2010 Hezekiah M. Carty This file is part of PLplot. @@ -185,10 +185,15 @@ | Axes of (color_t * axis_options_t list * axis_options_t list * int * line_style_t * (plplot_axis_type -> float -> string) option) + | Colorbar of + (float plot_side_t option * string plot_side_t option * bool option * + float option * [`image of (float * float) | `shade of (float array)] * + axis_options_t list option) | Contours of (color_t * pltr_t * float array * float array array) | Image of image_t | Image_fr of (image_t * (float * float)) | Join of (color_t * float * float * float * float * int * line_style_t) + | Labels of (color_t * string * string * string) | Lines of (string option * color_t * float array * float array * int * line_style_t) | Map of (color_t * map_t * float * float * float * float) @@ -501,6 +506,14 @@ (** [circle ?fill color x y r] - A special case of [arc]. *) let circle ?fill color x y r = arc ?fill color x y r r 0.0 360.0 + (** Draw a colorbar, optionally log scaled and labeled. *) + let image_colorbar ?custom_axis ?label ?log ?pos ?width data = + Colorbar (pos, label, log, width, `image data, custom_axis) + + (** Draw a shaded colorbar, optionally log scaled and labeled. *) + let shade_colorbar ?custom_axis ?label ?log ?pos ?width data = + Colorbar (pos, label, log, width, `shade data, custom_axis) + (** [contours color pltr contours data] *) let contours color pltr contours data = Contours (color, pltr, contours, data) @@ -516,6 +529,10 @@ let join ?style ?width color (x0, y0) (x1, y1) = Join (color, x0, y0, x1, y1, width |? 1, style |? Solid_line) + (** [label x y title] labels the axes and adds plot title *) + let label ?(color = Black) x y title = + Labels (color, x, y, title) + (** [lines ?label color xs ys] *) let lines ?label ?style ?width color xs ys = Lines (label, color, xs, ys, width |? 1, style |? Solid_line) @@ -727,6 +744,170 @@ (xmin, ymin), (xmax, ymax) in *) + (** [colorbar_base ?label ?log ?pos values] draws a colorbar, using the given + values for the color range. [label] gives the position and text of the + colorbar label; if [log] is true then the scale is taken to be log rather + than linear ; [pos] sets the position of the colorbar itself, both the + side of the plot to put it on and the distance from the edge + (normalized device units); [width] is the width of the colorbar (again in + normalized device units). + NOTE: This potentially wrecks the current viewport and + window settings, among others, so it should be called AFTER the current + plot page is otherwise complete. *) + let colorbar_base ?custom_axis ?label ?log ?(pos = Right 0.07) ?(width = 0.03) + data = + (* Save the state of the current plot window. *) + let dxmin, dxmax, dymin, dymax = plgvpd () in + let wxmin, wxmax, wymin, wymax = plgvpw () in + (*let old_default, old_scale = plgchr () in*) + + let old_color = plg_current_col0 () in + + (* Small font *) + plschr 0.0 0.75; + (* Small ticks on the vertical axis *) + plsmaj 0.0 0.5; + plsmin 0.0 0.5; + + (* Offset from the edge of the plot surface in normalized device units *) + let offset = + match pos with + | Right off + | Top off -> 1.0 -. off + | Left off + | Bottom off -> off -. width + in + (* Put the bar on the proper side, with the proper offsets. *) + (* Unit major-axis, minor-axis scaled to contour values. *) + let width_start = offset in + let width_end = offset +. width in + + (* Set the viewport and window *) + let init_window min_value max_value = + match pos with + | Right _ + | Left _ -> + plvpor width_start width_end 0.15 0.85; + plwind 0.0 1.0 min_value max_value; + | Top _ + | Bottom _ -> + plvpor 0.15 0.85 width_start width_end; + plwind min_value max_value 0.0 1.0; + in + + (* "Rotate" the image if we have a horizontal (Top or Bottom) colorbar. *) + (* Also, double the amount of data because plshades won't work properly + otherwise. *) + let colorbar_data values = + match pos with + | Right off + | Left off -> [|values; values|] + | Top off + | Bottom off -> Array.map (fun x -> [|x; x|]) values + in + + (* Draw the image or shaded data, depending on what was requested *) + let () = + match data with + | `image (min_value, max_value) -> + (* Draw the color bar as an image. *) + (* TODO FIXME XXX: Change "100" to be the number of color palette 1 + colors once the attribute getting + setting functions are in + place. *) + let colorbar_steps = Array_ext.range ~n:100 min_value max_value in + let data = colorbar_data colorbar_steps in + init_window min_value max_value; + (match pos with + | Right _ + | Left _ -> plot [image (0.0, min_value) (1.0, max_value) data] + | Top _ + | Bottom _ -> plot [image (min_value, 0.0) (max_value, 1.0) data]) + | `shade contours -> + let shade_data = colorbar_data contours in + let max_value, min_value = plMinMax2dGrid [|contours|] in + init_window min_value max_value; + (match pos with + | Right _ + | Left _ -> + plot [ + pltr (pltr1 [|0.0; 1.0|] contours); + shades (0.0, min_value) (1.0, max_value) contours shade_data; + clear_pltr; + ] + | Top _ + | Bottom _ -> + plot [ + pltr (pltr1 contours [|0.0; 1.0|]); + shades (min_value, 0.0) (max_value, 1.0) contours shade_data; + clear_pltr; + ]) + in + + (* Draw a box and tick marks around the color bar. *) + set_color Black; + (* Draw ticks and labels on the major axis. Add other options as + appropriate. *) + let major_axis_opt = + List.concat [ + [Frame0; Frame1; Major_ticks]; + (* Log? *) + (match log with + | None -> [] + | Some b -> if b then [Minor_ticks; Log] else []); + (* Which side gets the label *) + (match pos with + | Right _ + | Top _ -> [Unconventional_label] + | Left _ + | Bottom _ -> [Label]); + (* Perpendicular labeling? *) + (match pos with + | Right _ + | Left _ -> [Vertical_label] + | Top _ + | Bottom _ -> []); + (* User-specified axis options? *) + (match custom_axis with + | None -> [] + | Some l -> l); + ] + in + (* Just draw the minor axis sides, no labels or ticks. *) + let minor_axis_opt = [Frame0; Frame1] in + let x_opt, y_opt = + match pos with + | Top _ + | Bottom _ -> major_axis_opt, minor_axis_opt + | Left _ + | Right _ -> minor_axis_opt, major_axis_opt + in + plot_axes x_opt y_opt; + + (* Draw the label *) + Option.may ( + fun l -> + (* Which side to draw the label on and the offset from that side in + units of character height. *) + let label_string, label_pos_string, label_offset = + match l with + | Right s -> s, "r", 4.0 + | Left s -> s, "l", 4.0 + | Top s -> s, "t", 1.5 + | Bottom s -> s, "b", 1.5 + in + plmtex label_pos_string label_offset 0.5 0.5 label_string + ) label; + + (* TODO XXX FIXME - Make sure setting are all properly restored... *) + (* Restore the old plot window settings. *) + plvpor dxmin dxmax dymin dymax; + plwind wxmin wxmax wymin wymax; + plschr 0.0 1.0; + plsmaj 0.0 1.0; + plsmin 0.0 1.0; + set_color (Index_color old_color); + () + in let plot_arc (color, x, y, a, b, angle1, angle2, fill) = set_color_in color ( fun () -> plarc x y a b angle1 angle2 fill; @@ -745,6 +926,9 @@ plwid old_width; ) in + let plot_colorbar (pos, label, log, width, data, custom_axis) = + colorbar_base ?custom_axis ?label ?log ?pos ?width data + in let plot_contours (color, pltr, contours, data) = set_color_in color ( fun () -> @@ -778,6 +962,11 @@ plwid old_width; ) in + let plot_labels (color, x, y, title) = + set_color_in color ( + fun () -> pllab x y title + ) + in let plot_lines (label, color, xs, ys, width, style) = set_color_in color ( fun () -> @@ -866,10 +1055,12 @@ match p with | Arc a -> plot_arc a | Axes ax -> plot_axes ax + | Colorbar cb -> plot_colorbar cb | Contours c -> plot_contours c | Image i -> plot_image i | Image_fr (i, scale) -> plot_imagefr i scale | Join j -> plot_join j + | Labels lab -> plot_labels lab | Lines l -> plot_lines l | Map m -> plot_map m | Points p -> plot_points p @@ -888,174 +1079,6 @@ fun plottable -> with_stream ?stream (fun () -> one_plot plottable) ) plottable_list - (** Label the axes and plot title *) - let label ?stream x y title = - with_stream ?stream (fun () -> pllab x y title) - - (** [colorbar_base ?label ?log ?pos values] draws a colorbar, using the given - values for the color range. [label] gives the position and text of the - colorbar label; if [log] is true then the scale is taken to be log rather - than linear ; [pos] sets the position of the colorbar itself, both the - side of the plot to put it on and the distance from the edge - (normalized device units); [width] is the width of the colorbar (again in - normalized device units). - NOTE: This potentially wrecks the current viewport and - window settings, among others, so it should be called AFTER the current - plot page is otherwise complete. *) - let colorbar_base ?custom_axis ?label ?log ?(pos = Right 0.07) ?(width = 0.03) - data = - (* Save the state of the current plot window. *) - let dxmin, dxmax, dymin, dymax = plgvpd () in - let wxmin, wxmax, wymin, wymax = plgvpw () in - (*let old_default, old_scale = plgchr () in*) - - let old_color = plg_current_col0 () in - - (* Small font *) - plschr 0.0 0.75; - (* Small ticks on the vertical axis *) - plsmaj 0.0 0.5; - plsmin 0.0 0.5; - - (* Offset from the edge of the plot surface in normalized device units *) - let offset = - match pos with - | Right off - | Top off -> 1.0 -. off - | Left off - | Bottom off -> off -. width - in - (* Put the bar on the proper side, with the proper offsets. *) - (* Unit major-axis, minor-axis scaled to contour values. *) - let width_start = offset in - let width_end = offset +. width in - - (* Set the viewport and window *) - let init_window min_value max_value = - match pos with - | Right _ - | Left _ -> - plvpor width_start width_end 0.15 0.85; - plwind 0.0 1.0 min_value max_value; - | Top _ - | Bottom _ -> - plvpor 0.15 0.85 width_start width_end; - plwind min_value max_value 0.0 1.0; - in - - (* "Rotate" the image if we have a horizontal (Top or Bottom) colorbar. *) - (* Also, double the amount of data because plshades won't work properly - otherwise. *) - let colorbar_data values = - match pos with - | Right off - | Left off -> [|values; values|] - | Top off - | Bottom off -> Array.map (fun x -> [|x; x|]) values - in - - (* Draw the image or shaded data, depending on what was requested *) - let () = - match data with - | `image (min_value, max_value) -> - (* Draw the color bar as an image. *) - (* TODO FIXME XXX: Change "100" to be the number of color palette 1 - colors once the attribute getting + setting functions are in - place. *) - let colorbar_steps = Array_ext.range ~n:100 min_value max_value in - let data = colorbar_data colorbar_steps in - init_window min_value max_value; - (match pos with - | Right _ - | Left _ -> plot [image (0.0, min_value) (1.0, max_value) data] - | Top _ - | Bottom _ -> plot [image (min_value, 0.0) (max_value, 1.0) data]) - | `shade contours -> - let shade_data = colorbar_data contours in - let max_value, min_value = plMinMax2dGrid [|contours|] in - init_window min_value max_value; - (match pos with - | Right _ - | Left _ -> - plot [ - pltr (pltr1 [|0.0; 1.0|] contours); - shades (0.0, min_value) (1.0, max_value) contours shade_data; - clear_pltr; - ] - | Top _ - | Bottom _ -> - plot [ - pltr (pltr1 contours [|0.0; 1.0|]); - shades (min_value, 0.0) (max_value, 1.0) contours shade_data; - clear_pltr; - ]) - in - - (* Draw a box and tick marks around the color bar. *) - set_color Black; - (* Draw ticks and labels on the major axis. Add other options as - appropriate. *) - let major_axis_opt = - List.concat [ - [Frame0; Frame1; Major_ticks]; - (* Log? *) - (match log with - | None -> [] - | Some b -> if b then [Minor_ticks; Log] else []); - (* Which side gets the label *) - (match pos with - | Right _ - | Top _ -> [Unconventional_label] - | Left _ - | Bottom _ -> [Label]); - (* Perpendicular labeling? *) - (match pos with - | Right _ - | Left _ -> [Vertical_label] - | Top _ - | Bottom _ -> []); - (* User-specified axis options? *) - (match custom_axis with - | None -> [] - | Some l -> l); - ] - in - (* Just draw the minor axis sides, no labels or ticks. *) - let minor_axis_opt = [Frame0; Frame1] in - let x_opt, y_opt = - match pos with - | Top _ - | Bottom _ -> major_axis_opt, minor_axis_opt - | Left _ - | Right _ -> minor_axis_opt, major_axis_opt - in - plot_axes x_opt y_opt; - - (* Draw the label *) - Option.may ( - fun l -> - (* Which side to draw the label on and the offset from that side in - units of character height. *) - let label_string, label_pos_string, label_offset = - match l with - | Right s -> s, "r", 4.0 - | Left s -> s, "l", 4.0 - | Top s -> s, "t", 1.5 - | Bottom s -> s, "b", 1.5 - in - plmtex label_pos_string label_offset 0.5 0.5 label_string - ) label; - - (* TODO XXX FIXME - Make sure setting are all properly restored... *) - (* Restore the old plot window settings. *) - plvpor dxmin dxmax dymin dymax; - plwind wxmin wxmax wymin wymax; - plschr 0.0 1.0; - plsmaj 0.0 1.0; - plsmin 0.0 1.0; - set_color (Index_color old_color); - () - (** [colorbar_labeler ?log ?min ?max axis n] can be used as a custom axis labeling function when a colorbar is meant to represent values beyond those which are represented. So if the colorbar labeling shows @@ -1091,20 +1114,6 @@ | Some false -> normal_text n | Some true -> log10_text n - (** Draw a colorbar, optionally log scaled and labeled. *) - let colorbar ?stream ?custom_axis ?label ?log ?pos ?width (min, max) = - with_stream ?stream ( - fun () -> - colorbar_base ?custom_axis ?label ?log ?pos ?width (`image (min, max)) - ) - - (** Draw a shaded colorbar, optionally log scaled and labeled. *) - let shadebar ?stream ?custom_axis ?label ?log ?pos ?width values = - with_stream ?stream ( - fun () -> - colorbar_base ?custom_axis ?label ?log ?pos ?width (`shade values) - ) - (** Finish the current page, start a new one (alias for {!start_page}). *) let next_page = start_page @@ -1181,8 +1190,8 @@ plot ~stream [ list plottable_points; axes x_axis y_axis; + Option.map_default (fun (x, y, t) -> label x y t) (list []) labels; ]; - Option.may (fun (x, y, t) -> label ~stream x y t) labels; end_stream ~stream (); () @@ -1205,8 +1214,8 @@ plot ~stream [ list plottable_lines; axes x_axis y_axis; + Option.map_default (fun (x, y, t) -> label x y t) (list []) labels; ]; - Option.may (fun (x, y, t) -> label ~stream x y t) labels; Option.may (fun n -> draw_legend ~stream n (Array.to_list colors)) names; end_stream ~stream (); () @@ -1223,9 +1232,9 @@ plot ~stream [ image (xmin, ymin) (xmax, ymax) m; default_axes; + Option.map_default (fun (x, y, t) -> label x y t) (list []) labels; + image_colorbar ?log ~pos:(Right 0.12) (m_min, m_max); ]; - Option.may (fun (x, y, t) -> label ~stream x y t) labels; - colorbar ~stream ?log ~pos:(Right 0.12) (m_min, m_max); end_stream ~stream (); () @@ -1260,9 +1269,9 @@ plot ~stream [ list plot_content; default_axes; + Option.map_default (fun (x, y, t) -> label x y t) (list []) labels; ]; Option.may (fun n -> draw_legend ~stream n (Array.to_list colors)) names; - Option.may (fun (x, y, t) -> label ~stream x y t) labels; end_stream ~stream (); () @@ -1282,9 +1291,9 @@ plot ~stream [ shades (xmin, ymin) (xmax, ymax) contours m; default_axes; + Option.map_default (fun (x, y, t) -> label x y t) (list []) labels; + shade_colorbar ?log ~pos:(Right 0.12) contours; ]; - Option.may (fun (x, y, t) -> label ~stream x y t) labels; - shadebar ~stream ?log ~pos:(Right 0.12) contours; end_stream ~stream (); () end Modified: trunk/bindings/ocaml/plplot.mli =================================================================== --- trunk/bindings/ocaml/plplot.mli 2010-05-01 16:16:24 UTC (rev 10959) +++ trunk/bindings/ocaml/plplot.mli 2010-05-01 19:58:03 UTC (rev 10960) @@ -282,6 +282,29 @@ (** [circle ?fill color x y r] *) val circle : ?fill:bool -> color_t -> float -> float -> float -> plot_t + (** [image_colorbar ?label ?log ?pos ?width (min, max)] add a + color bar to a plot using the current color scale. This function + should be called after the rest of the plot is complete. *) + val image_colorbar : + ?custom_axis:axis_options_t list -> + ?label:string plot_side_t -> + ?log:bool -> + ?pos:float plot_side_t -> + ?width:float -> + float * float -> plot_t + + (** [shade_colorbar ?label ?log ?pos ?width contours] add a shaded + color bar to a plot using the current color scale. This is similar to + {!image_colorbar} but takes [contours] as rather than a range. This + function should be called after the rest of the plot is complete. *) + val shade_colorbar : + ?custom_axis:axis_options_t list -> + ?label:string plot_side_t -> + ?log:bool -> + ?pos:float plot_side_t -> + ?width:float -> + float array -> plot_t + (** [contours color tranform_func contours data] *) val contours : color_t -> pltr_t -> float array -> float array array -> plot_t @@ -303,6 +326,9 @@ ?width:int -> color_t -> float * float -> float * float -> plot_t + (** [label ?color x_label y_label title] adds axis labels and a title. *) + val label : ?color:color_t -> string -> string -> string -> plot_t + (** [lines ?label ?style color xs ys] *) val lines : ?label:string -> @@ -398,38 +424,9 @@ (** Draw a legend, given a list of titles and colors *) val draw_legend : ?stream:stream_t -> - ?line_length:'a -> + ?line_length:float -> ?x:float -> ?y:float -> string list -> color_t list -> unit - (** [label x_label y_label title] adds axis labels and a title to the given - plot [stream]. *) - val label : ?stream:stream_t -> string -> string -> string -> unit - - (** [colorbar ?stream ?label ?log ?pos ?width (min, max)] add a color bar - to a plot using the current color scale. This function should be - called after the rest of the plot is complete. *) - val colorbar : - ?stream:stream_t -> - ?custom_axis:axis_options_t list -> - ?label:string plot_side_t -> - ?log:bool -> - ?pos:float plot_side_t -> - ?width:float -> - float * float -> unit - - (** [shadebar ?stream ?label ?log ?pos ?width contours] add a shaded color - bar to a plot using the current color scale. This is similar to - {!colorbar} but takes contours as [values]. This function should be - called after the rest of the plot is complete. *) - val shadebar : - ?stream:stream_t -> - ?custom_axis:axis_options_t list -> - ?label:string plot_side_t -> - ?log:bool -> - ?pos:float plot_side_t -> - ?width:float -> - float array -> unit - (** [colorbar_labeler ?log ?min ?max axis n] can be used as a custom axis labeling function when a colorbar is meant to represent values beyond those which are represented. So if the colorbar labeling shows @@ -439,7 +436,7 @@ ?log:bool -> ?min:float -> ?max:float -> - 'a -> float -> string + plplot_axis_type -> float -> string (** Draw the plot axes on the current plot page *) val plot_axes : Modified: trunk/examples/ocaml/xplot01.ml =================================================================== --- trunk/examples/ocaml/xplot01.ml 2010-05-01 16:16:24 UTC (rev 10959) +++ trunk/examples/ocaml/xplot01.ml 2010-05-01 19:58:03 UTC (rev 10960) @@ -91,7 +91,6 @@ let ys = Array.init 6 (fun i -> y.(i * 10 + 3)) in P.set_color ~stream P.Blue; - P.label ~stream "(x)" "(y)" "#frPLplot Example 1 - y=x#u2"; P.plot ~stream [ (* Plot the data points *) @@ -100,6 +99,8 @@ P.lines P.Red x y; (* Show the axes *) P.default_axes; + (* Title and axis labels *) + P.label "(x)" "(y)" "#frPLplot Example 1 - y=x#u2"; ]; (* All done. *) @@ -113,7 +114,6 @@ P.start_page ~stream (-2.0, -0.4) (10.0, 1.2) P.Greedy; P.set_color ~stream P.Blue; - P.label ~stream "(x)" "sin(x)/x" "#frPLplot Example 1 - Sinc Function"; (* Fill up the arrays *) let x = Array.init 100 (fun i -> (float_of_int i -. 19.0) /. 6.0) in @@ -137,6 +137,7 @@ P.plot ~stream [ P.lines ~width:2 P.Red x y; P.axes x_axis y_axis; + P.label "(x)" "sin(x)/x" "#frPLplot Example 1 - Sinc Function"; ]; (* All done. *) @@ -151,8 +152,6 @@ P.start_page ~stream (0.0, -1.2) (360.0, 1.2) P.Greedy; P.set_color ~stream P.Red; - P.label ~stream "Angle (degrees)" "sine" - "#frPLplot Example 1 - Sine function"; let x = Array.init 101 (fun i -> 3.6 *. float_of_int i) in let y = Array.init 101 (fun i -> sin (x.(i) *. pi /. 180.0)) in @@ -178,6 +177,9 @@ P.lines P.Brown x y; (* The normal plot axes *) P.axes x_axis y_axis; + (* Plot title and axis labels *) + P.label "Angle (degrees)" "sine" + "#frPLplot Example 1 - Sine function"; ]; (* All done. *) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |