Skip to content

Commit

Permalink
Start sketching the object-oriented wrappers.
Browse files Browse the repository at this point in the history
  • Loading branch information
LaurentMazare committed May 12, 2019
1 parent ccef606 commit f98dcb6
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 17 deletions.
2 changes: 1 addition & 1 deletion examples/dune
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
(executables
(names pyplot)
(names fig pyplot)
(libraries base stdio matplotlib))
18 changes: 18 additions & 0 deletions examples/fig.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
(* Example using the object oriented api. *)
open Base
open Matplotlib

let () =
let xs = List.init 120 ~f:Float.of_int in
let ys1 = List.map xs ~f:(fun i -> Float.sin (i /. 20.)) in
let ys2 = List.map xs ~f:(fun i -> Float.cos (i /. 12.)) in
let xs = Array.of_list xs in
let ys1 = Array.of_list ys1 in
let ys2 = Array.of_list ys2 in
let _fig, ax = Fig.create_with_ax () in
Ax.set_xlabel ax "x label";
Ax.set_ylabel ax "sin(x)";
Ax.grid ax true;
Ax.plot ax ~color:Red ~xs ys1;
Ax.plot ax ~color:Green ~linestyle:Dotted ~linewidth:2. ~xs ys2;
Mpl.show ()
73 changes: 73 additions & 0 deletions src/matplotlib/fig_ax.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
open Base
open Pyops

module Ax = struct
type t = Py.Object.t

let set_title t title =
ignore (t.&("set_title")[| Py.String.of_string title |])

let set_xlabel t label =
ignore (t.&("set_xlabel")[| Py.String.of_string label |])

let set_ylabel t label =
ignore (t.&("set_ylabel")[| Py.String.of_string label |])

let grid t ?which ?axis b =
let keywords =
let b = Some ("b", Py.Bool.of_bool b) in
let which =
Option.map which ~f:(fun which ->
let which =
match which with
| `major -> "major"
| `minor -> "minor"
| `both -> "both"
in
"which", Py.String.of_string which)
in
let axis =
Option.map axis ~f:(fun axis ->
let axis =
match axis with
| `both -> "both"
| `x -> "x"
| `y -> "y"
in
"axis", Py.String.of_string axis)
in
List.filter_opt [ b; which; axis ]
in
ignore (Py.Module.get_function_with_keywords t "grid" [||] keywords)

let plot t ?color ?linewidth ?linestyle ?xs ys =
Mpl.plot t ?color ?linewidth ?linestyle ?xs ys
end

module Fig = struct
type t = Py.Object.t

let create ?figsize () =
let p = Mpl.pyplot_module () in
let keywords =
let figsize =
Option.map figsize ~f:(fun (w, h) ->
"figsize", Py.Tuple.of_pair Py.Float.(of_float w, of_float h))
in
List.filter_opt [ figsize ]
in
Py.Module.get_function_with_keywords p "figure" [||] keywords

let add_subplot t ~nrows ~ncols ~index =
let keywords = [] in
let args = [| nrows; ncols; index |] |> Array.map ~f:Py.Int.of_int in
Py.Module.get_function_with_keywords t "add_subplot" args keywords

let create_with_ax ?figsize () =
let t = create ?figsize () in
let ax = add_subplot t ~nrows:1 ~ncols:1 ~index:1 in
t, ax

let suptitle t title =
ignore (t.&("suptitle")[| Py.String.of_string title |])
end
34 changes: 34 additions & 0 deletions src/matplotlib/fig_ax.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module Ax : sig
type t

val set_title : t -> string -> unit
val set_xlabel : t -> string -> unit
val set_ylabel : t -> string -> unit
val grid : t -> ?which:[`major|`minor|`both] -> ?axis:[`both|`x|`y] -> bool -> unit

val plot
: t
-> ?color:Mpl.Color.t
-> ?linewidth:float
-> ?linestyle:Mpl.Linestyle.t
-> ?xs:float array
-> float array
-> unit
end

module Fig : sig
type t

val create : ?figsize:(float * float) -> unit -> t

(* Use the same api as the python library even if it seems a
bit odd.
Note that the index starts at 1 in the upper left corner and
increases to the right.
*)
val add_subplot : t -> nrows:int -> ncols:int -> index:int -> Ax.t

val create_with_ax : ?figsize:(float * float) -> unit -> t * Ax.t

val suptitle : t -> string -> unit
end
2 changes: 2 additions & 0 deletions src/matplotlib/matplotlib.ml
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
module Ax = Fig_ax.Ax
module Fig = Fig_ax.Fig
module Mpl = Mpl.Public
module Pyplot = Pyplot
18 changes: 18 additions & 0 deletions src/matplotlib/mpl.ml
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,21 @@ module Public = struct
let savefig = savefig
let plot_data = plot_data
end

let float_array_to_python xs =
Py.List.of_array_map Py.Float.of_float xs

let plot p ?color ?linewidth ?linestyle ?xs ys =
let keywords =
List.filter_opt
[ Option.map color ~f:(fun color -> "color", Color.to_pyobject color)
; Option.map linewidth ~f:(fun lw -> "linewidth", Py.Float.of_float lw)
; Option.map linestyle ~f:(fun ls -> "linestyle", Linestyle.to_pyobject ls)
]
in
let args =
match xs with
| Some xs -> [| float_array_to_python xs; float_array_to_python ys |]
| None -> [| float_array_to_python ys |]
in
ignore (Py.Module.get_function_with_keywords p "plot" args keywords)
10 changes: 10 additions & 0 deletions src/matplotlib/mpl.mli
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,13 @@ module Public : sig
val savefig : string -> unit
val plot_data : [`png | `jpg] -> string
end

(* Only internal functions below. *)
val plot
: Py.Object.t
-> ?color:Color.t
-> ?linewidth:float
-> ?linestyle:Linestyle.t
-> ?xs:float array
-> float array
-> unit
17 changes: 1 addition & 16 deletions src/matplotlib/pyplot.ml
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
open Base
open Pyops

let float_array_to_python xs =
Py.List.of_array_map Py.Float.of_float xs

let xlabel label =
let p = Mpl.pyplot_module () in
ignore (p.&("xlabel")[| Py.String.of_string label |])
Expand All @@ -22,16 +19,4 @@ let grid b =

let plot ?color ?linewidth ?linestyle ?xs ys =
let p = Mpl.pyplot_module () in
let keywords =
List.filter_opt
[ Option.map color ~f:(fun color -> "color", Mpl.Color.to_pyobject color)
; Option.map linewidth ~f:(fun lw -> "linewidth", Py.Float.of_float lw)
; Option.map linestyle ~f:(fun ls -> "linestyle", Mpl.Linestyle.to_pyobject ls)
]
in
let args =
match xs with
| Some xs -> [| float_array_to_python xs; float_array_to_python ys |]
| None -> [| float_array_to_python ys |]
in
ignore (Py.Module.get_function_with_keywords p "plot" args keywords)
Mpl.plot p ?color ?linewidth ?linestyle ?xs ys

0 comments on commit f98dcb6

Please sign in to comment.