More ocaml-flot cleanup, averages, label rotation #8

Merged
merged 5 commits into from Dec 20, 2011
View
@@ -3,27 +3,33 @@ open Buffer
open Printf
open Utils
-type labels = (float, string) Hashtbl.t
-
-type setting =
- | Points of point_setting list
- | X_axis of axis_setting list
- | Y_axis of axis_setting list
-and point_setting =
- | Show of bool
-and axis_setting =
- | Min of float
- | Max of float
- | TickFormatter of labels
- | TickSize of float
-
-type settings = setting list
+type settings = {
+ xaxis : axis_settings;
+ yaxis : axis_settings;
+}
+and axis_settings = {
+ min : float option;
+ max : float option;
+ tickFormatter : labels option;
+ tickSize : float option;
+ labelAngle : int option;
+}
+and labels = (float, string) Hashtbl.t
type point = float * float
type series = {
- label : string;
+ label : string option;
points : point list;
+ color : int option;
+ point_settings : point_settings;
+ line_settings : line_settings;
+}
+and point_settings = {
+ show_points : bool option;
+}
+and line_settings = {
+ show_lines : bool option;
}
type plot = {
@@ -32,64 +38,94 @@ type plot = {
settings : settings;
}
-let default_settings : settings = []
+let rec settings_default = {
+ xaxis = axis_default;
+ yaxis = axis_default;
+}
+and axis_default = {
+ min = None;
+ max = None;
+ tickFormatter = None;
+ tickSize = None;
+ labelAngle = None;
+}
+
+let rec series_default = {
+ label = None;
+ points = [];
+ color = None;
+ point_settings = point_settings_default;
+ line_settings = line_settings_default;
+}
+and point_settings_default = {
+ show_points = Some true;
+}
+and line_settings_default = {
+ show_lines = Some false;
+}
+
+let rec tf_of_settings_to_buffer b {xaxis; yaxis} =
+ tf_of_axis_to_buffer b "x" xaxis;
+ tf_of_axis_to_buffer b "y" yaxis
+and tf_of_axis_to_buffer b axis {tickFormatter} =
+ match tickFormatter with None -> () | Some labels ->
+ let axis_labels = axis ^ "_labels" in
+ bprintf b "var %s = new Object();\n" axis_labels;
+ let map_release ~key:i ~data:l =
+ bprintf b "%s[%f] = '%s';\n" axis_labels i l in
+ Float.Table.iter labels ~f:map_release;
+ bprintf b "var %s_tf = function(val, axis) {" axis_labels;
+ bprintf b "var r = %s[val]; " axis_labels;
+ add_string b "return (typeof r === 'undefined') ? '' : r;}"
-let default_labels : labels = Float.Table.create ()
+let sub_to_buffer b name ~f s =
+ bprintf b "%s: {" name; f s; add_string b "},"
-let string_of_settings name ~f ss =
- let strings = List.map ~f ss in
- let body = String.concat ~sep:", " strings in
- sprintf "%s: {%s}" name body
+let opt_f b opt f =
+ match opt with None -> () | Some v -> f v; add_string b ","
-let rec tick_formatters_of_setting b = function
- | X_axis ss -> List.iter ss ~f:(tick_formatters_of_axis b "x")
- | Y_axis ss -> List.iter ss ~f:(tick_formatters_of_axis b "y")
- | _ -> ()
-and tick_formatters_of_axis b axis = function
- | TickFormatter labels ->
- let axis_labels = axis ^ "_labels" in
- bprintf b "var %s = new Object();\n" axis_labels;
- let map_release ~key:i ~data:l =
- bprintf b " %s[%f] = '%s';\n" axis_labels i l in
- Float.Table.iter labels ~f:map_release;
- bprintf b "var %s_tf = function(val, axis) {" axis_labels;
- bprintf b " var r = %s[val];" axis_labels;
- bprintf b " return (typeof r === 'undefined') ? '' : r;\n }"
- | _ -> ()
+let rec settings_to_buffer b {xaxis; yaxis} =
+ sub_to_buffer b "xaxis" ~f:(axis_to_buffer b "x") xaxis;
+ sub_to_buffer b "yaxis" ~f:(axis_to_buffer b "y") yaxis
+and axis_to_buffer b axis {min; max; tickFormatter; tickSize; labelAngle} =
+ opt_f b min (fun m -> bprintf b "min: %f" m);
+ opt_f b max (fun m -> bprintf b "max: %f" m);
+ opt_f b tickFormatter
+ (fun _ -> bprintf b "tickFormatter: %s_labels_tf" axis);
+ opt_f b tickSize (fun ts -> bprintf b "tickSize: %f" ts);
+ opt_f b labelAngle (fun la -> bprintf b "labelAngle: %d" la)
-let rec string_of_setting = function
- | Points ss -> string_of_settings "points" ~f:string_of_points ss
- | X_axis ss -> string_of_settings "xaxis" ~f:(string_of_axis "x") ss
- | Y_axis ss -> string_of_settings "yaxis" ~f:(string_of_axis "y") ss
-and string_of_points = function
- | Show b -> sprintf "show: %b" b
-and string_of_axis axis = function
- | Min n -> sprintf "min: %f" n
- | Max n -> sprintf "max: %f" n
- | TickFormatter _ -> sprintf "tickFormatter: %s_labels_tf" axis
- | TickSize f -> sprintf "tickSize: %f" f
+let settings_to_buffer b s =
+ add_string b "{\n"; settings_to_buffer b s; add_string b "}"
-let string_of_settings ss =
- let soss = List.map ~f:string_of_setting ss in
- let body = String.concat ~sep:",\n" soss in
- sprintf "{\n%s}" (indent 2 body)
+let line_settings_to_buffer b {show_lines} =
+ add_string b "lines: {";
+ bprintf b "show:%b," (Option.value show_lines ~default:false);
+ add_string b "},"
-let string_of_series {label; points} =
- let pss = List.map points ~f:(fun (x, y) -> sprintf "[%f,%f]" x y) in
- let ps = String.concat ~sep:"," pss in
- "{label:\"" ^ label ^ "\",data:[" ^ ps ^ "]}"
+let rec series_to_buffer b series =
+ add_string b "{";
+ opt_f b series.label (fun l -> bprintf b "label:\"%s\"" l);
+ add_string b "data:[";
+ List.iter series.points ~f:(fun (x, y) -> bprintf b "[%f,%f]," x y);
+ add_string b "],";
+ opt_f b series.color (fun c -> bprintf b "color:%d" c);
+ sub_to_buffer b "points" ~f:(point_settings_to_buffer b) series.point_settings;
+ line_settings_to_buffer b series.line_settings;
+ add_string b "},\n"
+and point_settings_to_buffer b {show_points} =
+ opt_f b show_points (fun s -> bprintf b "show: %b" s)
let string_of_plot (plot : plot) =
- let b = Buffer.create 1000 in
+ let b = Buffer.create 2048 in
let style = "width: 1000px; height: 600px" in
bprintf b "<div id='%s' style='%s'></div>\n" plot.dom_id style;
add_string b "<script type='text/javascript'>\n";
- add_string b " $(function () {\n";
- List.iter plot.settings ~f:(tick_formatters_of_setting b);
- let dss = List.map plot.data ~f:string_of_series in
- let ds = String.concat ~sep:",\n" dss in
- let ss = string_of_settings plot.settings in
- bprintf b "\n$.plot($('#%s'), [\n%s\n], %s);" plot.dom_id ds ss;
- add_string b " });\n";
- add_string b "</script>\n";
- indent 2 (contents b)
+ add_string b "$(function () {\n";
+ tf_of_settings_to_buffer b plot.settings;
+ bprintf b "\n$.plot($('#%s'), [\n" plot.dom_id;
+ List.iter plot.data ~f:(series_to_buffer b);
+ add_string b "], ";
+ settings_to_buffer b plot.settings;
+ add_string b ");\n});\n</script>\n";
+ contents b
View
@@ -85,7 +85,33 @@ let extract_data x_axis_reverse_labels db_result =
Int.Table.change data config_id (update_points (x, y))
in List.iter db_result#get_all_lst (fun row -> extract_entry row);
List.mapi (Int.Table.data data)
- ~f:(fun i s -> {points = s; label = "config_id=" ^ (string_of_int i)})
+ ~f:(fun i s ->
+ {label = Some ("config_id=" ^ (string_of_int i));
+ points = s; color = Some i;
+ point_settings = point_settings_default;
+ line_settings = line_settings_default})
+
+let generate_average series =
+ let sums = Float.Table.create () in
+ let update v count_sum_opt =
+ let count, sum = Option.value count_sum_opt ~default:(0, 0.) in
+ Some (count + 1, sum +. v) in
+ List.iter series.points
+ ~f:(fun (x, y) -> Float.Table.change sums x (update y));
+ let avg_map = Float.Table.map sums
+ ~f:(fun (c, s) -> s /. (float_of_int c)) in
+ let avg_list = Float.Table.to_alist avg_map in
+ let avg_list_sorted =
+ List.sort avg_list ~cmp:(fun (x1,_) (x2,_) -> compare x1 x2) in
+ {series with
+ label = None;
+ points = avg_list_sorted;
+ point_settings = {show_points = Some false};
+ line_settings = {show_lines = Some true}}
+
+let add_averages data =
+ let data_avg = List.map data ~f:generate_average in
+ data @ data_avg
let som_handler ~conn som_id config_ids =
let query = "SELECT tc FROM tbl_som_definitions " ^
@@ -114,11 +140,13 @@ let som_handler ~conn som_id config_ids =
let builds_ord = List.flatten v_result#get_all_lst in
let x_axis_labels = natural_map_from_list builds_ord in
let x_axis_reverse_labels = reverse_natural_map x_axis_labels in
- let settings =
- [Points [Show true];
- X_axis [TickFormatter x_axis_labels; TickSize 1.];
- Y_axis [Min 0.]] in
- let data = extract_data x_axis_reverse_labels result in
+ let settings = {
+ xaxis = {axis_default with
+ tickFormatter = Some x_axis_labels; tickSize = Some 1.;
+ labelAngle = Some 285;};
+ yaxis = {axis_default with min = Some 0.}} in
+ let raw_data = extract_data x_axis_reverse_labels result in
+ let data = add_averages raw_data in
let plot = {dom_id = "graph"; data; settings} in
print_string (string_of_plot plot)
(*List.iter builds_ord ~f:(fun b -> printf "%s<br />\n" b);*)