Skip to content
This repository was archived by the owner on Oct 11, 2023. It is now read-only.

Commit 1a5ed28

Browse files
committed
Add initial plotting API
1 parent 430afbf commit 1a5ed28

File tree

2 files changed

+290
-0
lines changed

2 files changed

+290
-0
lines changed
Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
package io.continuum.bokeh
2+
3+
import Json.Writer
4+
5+
object Figure {
6+
def apply(): Figure = {
7+
val fig = new Figure()
8+
9+
val xaxis = new LinearAxis()
10+
val yaxis = new LinearAxis()
11+
val xgrid = new Grid().axis(xaxis).dimension(0)
12+
val ygrid = new Grid().axis(yaxis).dimension(1)
13+
14+
fig.addLayout(xaxis, Place.Below)
15+
fig.addLayout(yaxis, Place.Left)
16+
17+
fig.addLayout(xgrid, Place.Center)
18+
fig.addLayout(ygrid, Place.Center)
19+
20+
fig
21+
}
22+
23+
def apply(width: Int, height: Int): Figure = apply().width(width).height(height)
24+
def apply(title: String, width: Int, height: Int): Figure = apply(width, height).title(title)
25+
}
26+
27+
@model class Figure extends Plot { plot =>
28+
final override val typeName = "Plot"
29+
30+
type Cols = ColumnDataSource
31+
32+
protected def _addGlyph[X, Y, T[X, Y] <: Glyph[X, Y]](source: ColumnDataSource, glyph: T[X, Y]): T[X, Y] = {
33+
plot.addGlyph(source, glyph)
34+
glyph
35+
}
36+
37+
// annular_wedge(x, y, inner_radius, outer_radius, start_angle, end_angle)
38+
39+
def annular_wedge[X, Y](x: Seq[X], y: Seq[Y]): AnnularWedge[X, Y] = ???
40+
41+
// annulus(x, y, inner_radius, outer_radius)
42+
43+
def annulus[X, Y](x: Seq[X], y: Seq[Y]): Annulus[X, Y] = ???
44+
45+
// arc(x, y, radius, start_angle, end_angle)
46+
47+
def arc[X, Y](x: Seq[X], y: Seq[Y]): Arc[X, Y] = ???
48+
49+
// bezier(x0, y0, x1, y1, cx0, cy0, cx1, cy1)
50+
51+
def bezier[X, Y](x0: Seq[X], y0: Seq[Y], x1: Seq[X], y1: Seq[Y], cx0: Seq[X], cy0: Seq[Y], cx1: Seq[X], cy1: Seq[Y]): Bezier[X, Y] = ???
52+
53+
// image(image, x, y, dw, dh)
54+
55+
def image[X, Y](/* image: Seq[???], */ x: Seq[X], y: Seq[Y]): Image[X, Y] = ???
56+
57+
// image_rgba(image, x, y, dw, dh)
58+
59+
def image_rgba[X, Y](/* image: Seq[???], */ x: Seq[X], y: Seq[Y]): ImageRGBA[X, Y] = ???
60+
61+
// image_url(url, x, y)
62+
63+
def image_url[X, Y](url: Seq[String], x: Seq[X], y: Seq[Y]): ImageURL[X, Y] = ???
64+
65+
// line(x, y)
66+
67+
def line[Y:Scalar:Default:Writer](y: Seq[Y]): Line[Int, Y] = {
68+
line(0 until y.length, y)
69+
}
70+
71+
def line[X:Scalar:Default:Writer, Y:Scalar:Default:Writer](x: X, y: Y): Line[X, Y] = {
72+
new Line[X, Y].x(x).y(y)
73+
}
74+
75+
def line[X:Scalar:Default:Writer, Y:Scalar:Default:Writer](x: Seq[X], y: Y): Line[X, Y] = {
76+
val outer_x = x
77+
object source extends ColumnDataSource {
78+
val x = new Column('x, outer_x)
79+
}
80+
_addGlyph(source, new Line[X, Y].x(source.x).y(y))
81+
}
82+
83+
def line[X:Scalar:Default:Writer, Y:Scalar:Default:Writer](x: X, y: Seq[Y]): Line[X, Y] = {
84+
val outer_y = y
85+
object source extends ColumnDataSource {
86+
val y = new Column('y, outer_y)
87+
}
88+
_addGlyph(source, new Line[X, Y].x(x).y(source.y))
89+
}
90+
91+
def line[X:Scalar:Default:Writer, Y:Scalar:Default:Writer](x: Seq[X], y: Seq[Y]): Line[X, Y] = {
92+
val (outer_x, outer_y) = (x, y)
93+
object source extends ColumnDataSource {
94+
val x = new Column('x, outer_x)
95+
val y = new Column('y, outer_y)
96+
}
97+
_addGlyph(source, new Line[X, Y].x(source.x).y(source.y))
98+
}
99+
100+
def line[X:Scalar:Default:Writer, Y:Scalar:Default:Writer](xy: Seq[(X, Y)]): Line[X, Y] = {
101+
line(xy.map(_._1), xy.map(_._2))
102+
}
103+
104+
def line[S <: Cols, M[_]: ArrayLike, N[_]: ArrayLike, X:Scalar:Default:Writer, Y:Scalar:Default:Writer]
105+
(x: S#Column[M, X], y: S#Column[N, Y])(implicit ev: x.parent.type =:= y.parent.type): Line[X, Y] = {
106+
_addGlyph(x.parent, new Line[X, Y].x(x).y(y))
107+
}
108+
109+
def line[S <: Cols, M[_]: ArrayLike, N[_]: ArrayLike, X:Scalar:Default:Writer, Y:Scalar:Default:Writer]
110+
(source: S)(x: source.type => source.Column[M, X], y: source.type => source.Column[N, Y]): Line[X, Y] = {
111+
_addGlyph(source, new Line[X, Y].x(x(source)).y(y(source)))
112+
}
113+
114+
// multi_line(xs, ys)
115+
116+
def multi_line[X, Y](x: Seq[Seq[X]], y: Seq[Seq[Y]]): Patches[X, Y] = ???
117+
118+
// oval(x, y, width, height)
119+
120+
def oval[X, Y](x: Seq[X], y: Seq[Y], width: Seq[X], height: Seq[Y]): Oval[X, Y] = ???
121+
122+
// patch(x, y)
123+
124+
def patch[X, Y](x: Seq[X], y: Seq[Y]): Patch[X, Y] = ???
125+
126+
// patches(xs, ys)
127+
128+
def patches[X, Y](x: Seq[Seq[X]], y: Seq[Seq[Y]]): Patches[X, Y] = ???
129+
130+
// quad(left, right, top, bottom)
131+
132+
def quad[X, Y](left: Seq[X], right: Seq[X], bottom: Seq[Y], top: Seq[Y]): Patch[X, Y] = ???
133+
134+
// quadratic(x0, y0, x1, y1, cx, cy)
135+
136+
def quadratic[X, Y](x0: Seq[X], y0: Seq[Y], x1: Seq[X], y1: Seq[Y], cx: Seq[X], cy: Seq[Y]): Quadratic[X, Y] = ???
137+
138+
// ray(x, y, length, angle)
139+
140+
def ray[X, Y](x: Seq[X], y: Seq[Y], length: Seq[Double], angle: Seq[Double]): Ray[X, Y] = ???
141+
142+
// rect(x, y, width, height)
143+
144+
def rect[X, Y](x: Seq[X], y: Seq[Y], width: Seq[X], height: Seq[Y]): Rect[X, Y] = ???
145+
146+
// segment(x0, y0, x1, y1)
147+
148+
def segment[X, Y](x0: Seq[X], y0: Seq[Y], x1: Seq[X], y1: Seq[Y]): Rect[X, Y] = ???
149+
150+
// text(x, y, text)
151+
152+
def text[X, Y](x: Seq[X], y: Seq[Y], text: Seq[String]): Text[X, Y] = ???
153+
154+
// wedge(x, y, radius, start_angle, end_angle)
155+
156+
def wedge[X, Y](x: Seq[X], y: Seq[Y]): Wedge[X, Y] = ???
157+
158+
trait MarkerApi {
159+
type MarkerType[X, Y] <: Marker[X, Y]
160+
161+
protected def newMarker[X:Scalar:Default:Writer, Y:Scalar:Default:Writer]: MarkerType[X, Y]
162+
163+
def apply[Y:Scalar:Default:Writer](y: Seq[Y]): MarkerType[Int, Y] = {
164+
apply(0 until y.length, y)
165+
}
166+
167+
def apply[X:Scalar:Default:Writer, Y:Scalar:Default:Writer](x: X, y: Y): MarkerType[X, Y] = {
168+
newMarker[X, Y].x(x).y(y)
169+
}
170+
171+
def apply[X:Scalar:Default:Writer, Y:Scalar:Default:Writer](x: Seq[X], y: Y): MarkerType[X, Y] = {
172+
val outer_x = x
173+
object source extends ColumnDataSource {
174+
val x = new Column('x, outer_x)
175+
}
176+
_addGlyph(source, newMarker[X, Y].x(source.x).y(y))
177+
}
178+
def apply[X:Scalar:Default:Writer, Y:Scalar:Default:Writer](x: X, y: Seq[Y]): MarkerType[X, Y] = {
179+
val outer_y = y
180+
object source extends ColumnDataSource {
181+
val y = new Column('y, outer_y)
182+
}
183+
_addGlyph(source, newMarker[X, Y].x(x).y(source.y))
184+
}
185+
186+
def apply[X:Scalar:Default:Writer, Y:Scalar:Default:Writer](x: Seq[X], y: Seq[Y]): MarkerType[X, Y] = {
187+
val (outer_x, outer_y) = (x, y)
188+
object source extends ColumnDataSource {
189+
val x = new Column('x, outer_x)
190+
val y = new Column('y, outer_y)
191+
}
192+
_addGlyph(source, newMarker[X, Y].x(source.x).y(source.y))
193+
}
194+
195+
def apply[X:Scalar:Default:Writer, Y:Scalar:Default:Writer](xy: Seq[(X, Y)]): MarkerType[X, Y] = {
196+
apply(xy.map(_._1), xy.map(_._2))
197+
}
198+
199+
def apply[S <: Cols, M[_]: ArrayLike, N[_]: ArrayLike, X:Scalar:Default:Writer, Y:Scalar:Default:Writer]
200+
(x: S#Column[M, X], y: S#Column[N, Y])(implicit ev: x.parent.type =:= y.parent.type): MarkerType[X, Y] = {
201+
_addGlyph(x.parent, newMarker[X, Y].x(x).y(y))
202+
}
203+
204+
def apply[S <: Cols, M[_]: ArrayLike, N[_]: ArrayLike, X:Scalar:Default:Writer, Y:Scalar:Default:Writer]
205+
(source: S)(x: source.type => source.Column[M, X], y: source.type => source.Column[N, Y]): MarkerType[X, Y] = {
206+
_addGlyph(source, newMarker[X, Y].x(x(source)).y(y(source)))
207+
}
208+
}
209+
210+
object asterisk extends MarkerApi {
211+
type MarkerType[X, Y] = Asterisk[X, Y]
212+
def newMarker[X:Scalar:Default:Writer, Y:Scalar:Default:Writer] = new Asterisk[X, Y]()
213+
}
214+
object circle extends MarkerApi {
215+
type MarkerType[X, Y] = Circle[X, Y]
216+
def newMarker[X:Scalar:Default:Writer, Y:Scalar:Default:Writer] = new Circle()
217+
}
218+
object circle_cross extends MarkerApi {
219+
type MarkerType[X, Y] = CircleCross[X, Y]
220+
def newMarker[X:Scalar:Default:Writer, Y:Scalar:Default:Writer] = new CircleCross()
221+
}
222+
object circle_x extends MarkerApi {
223+
type MarkerType[X, Y] = CircleX[X, Y]
224+
def newMarker[X:Scalar:Default:Writer, Y:Scalar:Default:Writer] = new CircleX()
225+
}
226+
object cross extends MarkerApi {
227+
type MarkerType[X, Y] = Cross[X, Y]
228+
def newMarker[X:Scalar:Default:Writer, Y:Scalar:Default:Writer] = new Cross()
229+
}
230+
object diamond extends MarkerApi {
231+
type MarkerType[X, Y] = Diamond[X, Y]
232+
def newMarker[X:Scalar:Default:Writer, Y:Scalar:Default:Writer] = new Diamond()
233+
}
234+
object diamond_cross extends MarkerApi {
235+
type MarkerType[X, Y] = DiamondCross[X, Y]
236+
def newMarker[X:Scalar:Default:Writer, Y:Scalar:Default:Writer] = new DiamondCross()
237+
}
238+
object inverted_triangle extends MarkerApi {
239+
type MarkerType[X, Y] = InvertedTriangle[X, Y]
240+
def newMarker[X:Scalar:Default:Writer, Y:Scalar:Default:Writer] = new InvertedTriangle()
241+
}
242+
object square extends MarkerApi {
243+
type MarkerType[X, Y] = Square[X, Y]
244+
def newMarker[X:Scalar:Default:Writer, Y:Scalar:Default:Writer] = new Square()
245+
}
246+
object square_cross extends MarkerApi {
247+
type MarkerType[X, Y] = SquareCross[X, Y]
248+
def newMarker[X:Scalar:Default:Writer, Y:Scalar:Default:Writer] = new SquareCross()
249+
}
250+
object square_x extends MarkerApi {
251+
type MarkerType[X, Y] = SquareX[X, Y]
252+
def newMarker[X:Scalar:Default:Writer, Y:Scalar:Default:Writer] = new SquareX()
253+
}
254+
object triangle extends MarkerApi {
255+
type MarkerType[X, Y] = Triangle[X, Y]
256+
def newMarker[X:Scalar:Default:Writer, Y:Scalar:Default:Writer] = new Triangle()
257+
}
258+
object plain_x extends MarkerApi {
259+
type MarkerType[X, Y] = PlainX[X, Y]
260+
def newMarker[X:Scalar:Default:Writer, Y:Scalar:Default:Writer] = new PlainX()
261+
}
262+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.continuum.bokeh
2+
package tests
3+
4+
import org.specs2.mutable._
5+
6+
class PlottingSpec extends Specification {
7+
"bokeh.plotting API" should {
8+
"support markers" in {
9+
val fig = new Figure()
10+
11+
object source extends ColumnDataSource {
12+
val x = column(List(1.0, 2.0, 3.0))
13+
val y = column(List(2.0, 3.0, 4.0))
14+
}
15+
16+
fig.circle(List(2.0, 3.0, 4.0)).size(5.0)
17+
fig.circle(1.0, 2.0).size(5.0)
18+
fig.circle(List(1.0, 2.0, 3.0), 2.0).size(5.0)
19+
fig.circle(1.0, List(2.0, 3.0, 4.0)).size(5.0)
20+
fig.circle(List(1.0, 2.0, 3.0), List(2.0, 3.0, 4.0)).size(5.0)
21+
fig.circle(List((1.0, 2.0), (2.0, 3.0), (3.0, 4.0))).size(5.0)
22+
fig.circle(source.x, source.y)
23+
fig.circle(source)(_.x, _.y)
24+
25+
1 === 1 // TODO: write actuall tests
26+
}
27+
}
28+
}

0 commit comments

Comments
 (0)