Commit b8d06ba6 authored by Erwan Jahier's avatar Erwan Jahier
Browse files

Enhance the gnuplot-rif visualiser

parent 819bb7c5
......@@ -18,6 +18,7 @@
open Genlex
let usage =
" gnuplot-rif [-x11|-ps|-cps|-eps|-latex] <f>.rif
......@@ -61,8 +62,7 @@ let (readfile: string -> string) =
if str = "" then
(
output_string stderr ("*** File " ^ name ^ " is empty!\n");
flush stderr;
exit 2
""
)
else
(
......@@ -76,6 +76,10 @@ type tok = token Stream.t
let debug_parsing = false
let debug_msg msg =
if debug_parsing then
( output_string stdout msg; flush stdout )
let (print_debug : string -> tok -> unit) =
fun msg tok ->
if debug_parsing then
......@@ -86,6 +90,107 @@ let (print_debug : string -> tok -> unit) =
else
()
(********************************************************************************)
(* get var type in the rif file *)
type vtypes_tbl = (string * string) list
let (get_var_types : string -> vtypes_tbl) =
fun rif_file ->
let _ = debug_msg "get_var_types \n" in
let tbl = ref [] in
let rec aux s =
let _ = debug_msg ("aux "^(string_of_int (Stream.count s))^" \n") in
match s with parser
| [< 'String(_,id) >] -> aux2 id s
| [< 'Ident(_,_) >] -> aux s
| [< 'Int(_,_) >] -> aux s
| [< 'Float(_,_) >] -> aux s
| [< 'Kwd(_,_) >] -> aux s
| [< 'Char(_,_) >] -> aux s
and aux2 id s =
let _ = debug_msg ("aux2 "^(string_of_int (Stream.count s))^"\n") in
match s with parser
| [< 'Kwd(_, ":"); >] -> aux3 id s
| [< 'Ident(_,_) >] -> aux s
| [< 'Int(_,_) >] -> aux s
| [< 'Float(_,_) >] -> aux s
| [< 'Kwd(_,_) >] -> aux s
| [< 'Char(_,_) >] -> aux s
and aux3 id s =
let _ = debug_msg ("aux3 "^(string_of_int (Stream.count s))^"\n") in
match s with parser
| [< 'Ident(_,t)>] -> tbl:=(id, t)::!tbl; aux s
| [< 'Kwd(_,_) >] -> aux s
| [< 'Int(_,_) >] -> aux s
| [< 'Float(_,_) >] -> aux s
| [< 'String(_,_) >] -> aux s
| [< 'Char(_,_) >] -> aux s
in
try
aux (lexer (Stream.of_string rif_file))
with _ ->
List.rev !tbl
let (get_range : string list -> int * int) =
fun l ->
let get_min_max (min, max) str =
(* print_string ("val = " ^ str ^ "\n "); *)
(* flush stdout; *)
let i = try int_of_string str with _ ->
try truncate (float_of_string str) with _ -> 0
in
if i < min then (i,max) else
if i > max then (min,i) else (min,max)
in
List.fold_left get_min_max (0,0) l
let debut = ref 0
let delta = ref 0
let step_nb = ref 0
let is_num str =
try
ignore(int_of_string str);
true
with _ ->
try
ignore(float_of_string str);
true
with _ ->
str = "T" || str = "F" ||
str = "t" || str = "f"
let (get_delta : string -> vtypes_tbl -> unit) =
fun rif_file tbl ->
let lines = Str.split (Str.regexp "\n") rif_file in
let _ = step_nb := List.length lines in
let lines = List.map (fun line -> Str.split (Str.regexp "[ \t]+") line) lines in
let lines = List.filter (fun line -> line <> []) lines in
let lines = List.filter (fun line -> is_num (List.hd line)) lines in
let all_values = List.flatten lines in
let vmin,vmax = get_range all_values in
let nb_vars = List.fold_left (fun cpt (_, t) -> if t="bool" then cpt+1 else cpt) 0 tbl in
let delta' = (vmax - vmin) / (nb_vars) in
let cdelta = max 1 delta' in
let cdebut = vmin + (-vmin mod (1+cdelta)) in
print_string ("delta = " ^ (string_of_int cdelta) ^ "\n ");
print_string ("vmin = " ^ (string_of_int vmin) ^ "\n ");
print_string ("vmax = " ^ (string_of_int vmax) ^
"\n ");
print_string ("debut = " ^ (string_of_int cdebut) ^ "\n ");
flush stdout;
debut := cdebut;
delta := cdelta
(********************************************************************************)
let rec (get_names_in_gp : tok -> string list) =
......@@ -139,96 +244,158 @@ let terminal_kind_to_string tk file =
| X11 -> ""
| NoDisplay -> ""
let gen_plot_file vars file tk =
let gen_plot_file rif_file vars to_hide ttbl file tk =
let file_name = (Filename.chop_extension file) ^ ".plot" in
let oc = open_out file_name in
let put str = output_string oc str in
(* let flip = ref true in *)
let put_one_var (var:string) (i:int) =
let is_num = try List.assoc var ttbl <> "bool" with _ -> false in (* don't crash for that... *)
put ("\"" ^ file ^ "\" us 1:" ^ (string_of_int i) ^
" ti \"" ^ var ^ "\" ")
(if is_num then (" title \"" ^ var ^ "\" ") else " notitle ") ^
(* (if not is_num then *)
(* if !flip then (flip:=false;" lc rgbcolor \"red\" ") *)
(* else (flip:=true;" lc rgbcolor \"blue\" ") *)
(* else "") ^ *)
(if is_num then " with linespoints" else "" ))
in
let xtics =
let log_step_nb = truncate (log (float_of_int !step_nb) ) in
string_of_int (max 1 ((!step_nb / (log_step_nb * 100))*10))
in
let cpt = ref (!debut + (!delta/2)) in
output_string stderr ("Generating "^ file_name ^ " file...\n");
flush stderr;
put "
put ("
# defaults
set data style linespoints
set pointsize 0.1
set data style steps
set pointsize 0.2
set grid back
set xtics "^xtics^" mirror
set ytics "^ (string_of_int (1+ !delta))^"
unset grid
set mouse
";
set key right top title \"Numeric variables\" box 3
#set origin 0.1,0
#set size 0.9,1
");
List.iter
(fun (id, t) ->
if (to_hide id) then output_string stderr ("Hidding " ^ id ^ "\n");
if t = "bool" then (
cpt:= !cpt+1+ !delta ;
if (to_hide id) then
()
else
put ("set label \""^ id ^ "\" at 1, "^(string_of_int !cpt) ^"\n")
) ;
)
ttbl;
flush stderr;
if (tk <> X11 && tk <> NoDisplay) then put "set size 1.3,1\n";
put "# options
set xlabel \"steps\"
";
put (terminal_kind_to_string tk file);
put "\n plot ";
put_one_var (List.hd vars) 2;
ignore
(List.fold_left
(fun i var ->
put ",";
put_one_var var i;
(i+1)
(fun (i,sep) var ->
if to_hide var then (i+1,sep) else (
put sep;
put_one_var var i;
(i+1,",")
)
)
3
(List.tl vars)
(2,"")
vars
);
if tk = X11 then put "\npause -1 \n";
close_out oc;
file_name
(********************************************************************************)
(* shift booleans so that they are mode visible. *)
let (scale_bool : string list -> string list) =
fun l ->
let _ = debug_msg "scale_bool \n" in
let cpt = ref (!debut) in
List.map
(fun str ->
match str with
| "f" -> cpt:= !cpt+1+ !delta ; string_of_int (!cpt)
| "t" -> cpt:= !cpt+1+ !delta ; string_of_int (!cpt+ !delta)
| e -> e
)
l
(*
Takes a ".rif" file name and generates a ".gp" file that contains
the same info in a format suitable for gnuplot
*)
let (rif_to_gp : string -> string) =
fun rif_file ->
let (transform_bools : vtypes_tbl -> string -> string) =
fun tbl str ->
let lines = Str.split (Str.regexp "\n") str in
let lines = List.map (fun line -> Str.split (Str.regexp "[ \t]+") line) lines in
let lines = List.filter (fun line -> line <> []) lines in
let lines = List.map scale_bool lines in
let lines = List.map (String.concat " ") lines in
String.concat "\n" lines
(*
Takes a ".rif" file name and generates a ".gp" file that contains
the same info in a format suitable for gnuplot
*)
let (rif_to_gp : vtypes_tbl -> string -> string) =
fun tbl rif_file ->
let gp_file = ((Filename.chop_extension rif_file) ^ ".gp") in
let oc = open_out gp_file in
let put str = output_string oc str in
let rif_file_content = readfile rif_file in
let subst =
[
(Str.regexp_string ":bool"), " | " ;
(Str.regexp_string ":int"), " | " ;
(Str.regexp_string ":real"), " | " ;
(Str.regexp_string "#step"), "#";
(Str.regexp_string"# This is "), "@ This is ";
(Str.regexp_string"# seed = "), "@ seed = ";
(Str.regexp_string"# step"), "#";
(Str.regexp_string"@#"), "";
(Str.regexp_string"#program"), "#@program";
(Str.regexp_string"#inputs"), "#@ columns : steps | ";
(Str.regexp_string"#@inputs"), "#@ columns : steps | ";
(Str.regexp_string"#@outputs"), "";
(Str.regexp_string"#outputs"), "";
(Str.regexp_string"#@locals"), "";
(Str.regexp_string"#outs"), " ";
(Str.regexp_string"#locals"), " ";
(Str.regexp_string"#locs"), " ";
(Str.regexp_string"bye!"), "";
(Str.regexp_string "\n"), " " ;
(Str.regexp_string" t "), " 1 ";
(Str.regexp_string" true "), " 1 ";
(Str.regexp_string" false "), " 0 ";
(Str.regexp_string" True "), " 1 ";
(Str.regexp_string" False "), " 0 ";
(Str.regexp_string" f "), " 0 ";
(Str.regexp_string" T "), " 1 ";
(Str.regexp_string" F "), " 0 ";
(Str.regexp_string" t "), " 1 ";
(Str.regexp_string" f "), " 0 ";
(Str.regexp_string" T "), " 1 ";
(Str.regexp_string" F "), " 0 ";
(Str.regexp_string "#"), "\n" ;
(Str.regexp_string "@"), "#"
]
(Str.regexp_string ":bool"), " | " ;
(Str.regexp_string ":int"), " | " ;
(Str.regexp_string ":real"), " | " ;
(Str.regexp_string "#step"), "#";
(Str.regexp_string"# This is "), "@ This is "; (* @ are used to be able to restore # afterwards *)
(Str.regexp_string"# seed = "), "@ seed = ";
(Str.regexp_string"# step"), "#";
(Str.regexp_string"@#"), "";
(Str.regexp_string"#program"), "#@program";
(Str.regexp_string"#inputs"), "#@ columns : steps | ";
(Str.regexp_string"#@inputs"), "#@ columns : steps | ";
(Str.regexp_string"#@outputs"), "";
(Str.regexp_string"#outputs"), "";
(Str.regexp_string"#@locals"), "";
(Str.regexp_string"#outs"), " ";
(Str.regexp_string"#The random engine"), "@The random engine";
(Str.regexp_string"#locals"), " ";
(Str.regexp_string"#oracle_outputs"), "@oracle_outputs";
(Str.regexp_string"#locs"), " ";
(Str.regexp_string"#*** An assertion"), "@*** An assertion";
(Str.regexp_string"bye!"), "";
(Str.regexp_string "\n"), " " ;
(Str.regexp_string" t "), " t ";
(Str.regexp_string" true "), " t ";
(Str.regexp_string" false "), " f ";
(Str.regexp_string" True "), " t ";
(Str.regexp_string" False "), " f ";
(Str.regexp_string" f "), " f ";
(Str.regexp_string" T "), " t ";
(Str.regexp_string" F "), " f ";
(Str.regexp_string" t "), " t ";
(Str.regexp_string" f "), " f ";
(Str.regexp_string" T "), " t ";
(Str.regexp_string" F "), " f ";
(Str.regexp_string "#"), "\n" ;
(Str.regexp_string "@"), "#"
]
in
let gp_file_content =
try
......@@ -236,7 +403,7 @@ let (rif_to_gp : string -> string) =
(fun str (regexp, temp) -> Str.global_replace regexp temp str)
rif_file_content
subst
(* replaces "," by "." ins floats *)
(* Str.string_match (Str.regexp "\([0-9]*\)\(,\)\([0-9]*\)") s 0; *)
(* Str.replace_matched "\1.\3" s *)
......@@ -247,6 +414,7 @@ let (rif_to_gp : string -> string) =
flush stdout;
exit 2
in
let gp_file_content = transform_bools tbl gp_file_content in
output_string stdout ("Generating "^ gp_file ^ " file...\n");
flush stdout;
put gp_file_content;
......@@ -337,6 +505,7 @@ let terminal = ref NoDisplay
let rif_file = ref ""
let plot_file = ref ""
(* XXX rajouter un --hide-var *)
let rec speclist =
[
......@@ -364,6 +533,22 @@ let rec speclist =
]
(* Returns the list of var names to hide *)
let (read_ressource_file : string -> string list) =
fun file ->
try
let str = if Sys.file_exists file then readfile file else "" in
let strl = Str.split (Str.regexp "\n") str in
let strll = List.map (Str.split (Str.regexp "[ \t]+")) strl in
let hide_strll =
List.filter (fun l -> if l = [] then false else List.hd l = "hide")
strll
in
List.flatten (List.map List.tl hide_strll)
with _ ->
print_string "No valid .gnuplot-rif file has been found.\n";
[]
let main () =
if
(Array.length Sys.argv) <= 1
......@@ -381,7 +566,11 @@ let main () =
flush stdout; flush stderr; exit 2
);
let gp_file = rif_to_gp !rif_file in
let rif_file_content = readfile !rif_file in
let ttbl = get_var_types rif_file_content in
let _ = get_delta rif_file_content ttbl in
let gp_file = rif_to_gp ttbl !rif_file in
let gp_s =
if not (Sys.file_exists gp_file) then
(
......@@ -393,13 +582,22 @@ let main () =
lexer (Stream.of_string (readfile gp_file))
in
let vars = List.rev (get_names_in_gp gp_s) in
let vars_to_hide = read_ressource_file ".gnuplot-rif" in
let to_hide v =
List.exists
(fun patt ->
let patt = Str.global_replace (Str.regexp_string "*") ".*" patt in
Str.string_match (Str.regexp patt) v 0)
vars_to_hide
in
let _ = plot_file := gen_plot_file rif_file_content vars to_hide ttbl gp_file !terminal in
if debug_parsing then
(
output_string stderr "\nvar names are :\n";
List.iter (fun x -> print_string (x ^ "\n")) vars;
flush stderr
);
let _ = plot_file := gen_plot_file vars gp_file !terminal in
if !terminal <> NoDisplay then
let pid =
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment