1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
include Base
module Data = struct
open Attributes
type t = Attribute.t list
let mode = string "mode"
let name = string "name"
let labels = array "labels" Type.String
let values = array "values" Type.Float
let text = array "text" Type.String
let orientation = string "orientation"
let x = array "x" Type.Float
let y = array "y" Type.Float
let z = array "z" Type.Float
let xy xys =
let xs = Array.map fst xys in
let ys = Array.map snd xys in
x xs @ y ys
let xyz xyzs =
let xs = Array.map (fun (x,_,_) -> x) xyzs in
let ys = Array.map (fun (_,y,_) -> y) xyzs in
let zs = Array.map (fun (_,_,z) -> z) xyzs in
x xs @ y ys @ z zs
let data ds = ds
let to_json = Attributes.to_json
let of_json = Attributes.of_json
end
module Layout = struct
open Attributes
type t = Attribute.t list
let title = string "title"
let barmode = string "barmode"
let layout ats = ats
let to_json = Attributes.to_json
let of_json = Attributes.of_json
end
module Graph = struct
type t = { type_ : string; data : Data.t }
let scatter data_list = { type_ = "scatter"; data= List.flatten data_list }
let scatter3d data_list = { type_ = "scatter3d"; data= List.flatten data_list }
let bar data_list = { type_ = "bar"; data= List.flatten data_list }
let pie data_list = { type_ = "pie"; data= List.flatten data_list }
let histogram data_list = { type_ = "histogram"; data= List.flatten data_list }
let graph type_ data_list = { type_; data= List.flatten data_list }
let to_json g =
match Data.to_json g.data with
| `O kvs -> `O (("type", `String g.type_) :: kvs)
| _ -> assert false
let of_json = function
| `O kvs ->
let open Option in
let type_, others =
List.partition (function ("type", _) -> true | _ -> false) kvs
in
(match type_ with
| ["type", `String type_] ->
let+ data = Data.of_json (`O others) in
{ type_; data }
| _ -> None)
| _ -> None
end
module Figure = struct
type t =
{ graphs : Graph.t list;
layout : Layout.t }
let figure graphs layout = { graphs; layout= List.flatten layout }
let to_json g =
let graphs = List.map Graph.to_json g.graphs in
let layout = Layout.to_json g.layout in
`O ["data", `A graphs; "layout", layout]
let of_json j =
let open Option in
match j with
| `O kvs ->
let* graphs = List.assoc_opt "data" kvs in
let* graphs =
match graphs with
| `A graphs -> Option.mapM Graph.of_json graphs
| _ -> None
in
let* layout = List.assoc_opt "layout" kvs in
let+ layout = Layout.of_json layout in
{ graphs; layout }
| _ -> None
end