Introduction to Bokeh

Agenda

  • Make a few plots
  • Play with vectorized attributes
  • See how to use toolbars
  • Linked Brushing
  • Interactivity
  • Show example of static plot to html

Setup

First let's import things and make a few arrays


In [ ]:
import numpy as np
from bokeh.plotting import *
N = 102
lin_arr = np.linspace(0, 4*np.pi, N)
sin_arr = np.sin(lin_arr)
cos_arr = np.cos(lin_arr)

Output

Bokeh can output to html, a notebook, or just fragments for embedding in a web application.

To start playing, we'll use the notebook. Later we will see the other types of output.


In [ ]:
output_notebook()

Scatter Plots

To begin with let's make a scatter plot.


In [ ]:
p1 = figure()
p1.scatter(lin_arr, sin_arr, color="#FF00FF")
p1.scatter(lin_arr, cos_arr, color="green")
show(p1)

Exercise

Play with plotting arrays, try editting

  • color,
  • markers,
  • alpha (value between 0-1), and
  • size (int of pixels)

In [ ]:
p2 = figure()
p2.scatter(..., color="red")
show(p2)

In [ ]:
p3 = figure()
p3.scatter(... , marker="square", color="green")
show(p3)

See also

For some fun with different glyphs see the glyphs notebook.

Everything is vectorized

While we have only been passing vectors for locations, we can do so for almost any parameter.

Let's use the cos_arr to size the circles


In [ ]:
p4 = figure()
p4.scatter(x=lin_arr, y=sin_arr, size=cos_arr**2*10)
show(p4)

In [ ]:
from bokeh.palettes import brewer

In [ ]:
print brewer.keys()
print brewer["Greys"].keys()

In [ ]:
#palette = brewer["Spectral"][10]
palette = brewer["Greys"][9] + list(reversed(brewer["Greys"][9]))
colors = palette * (len(lin_arr) / len(palette)) + palette[0:len(lin_arr) % len(palette)]

In [ ]:
p5 = figure()
p5.scatter(x=lin_arr, y=sin_arr, size=cos_arr**2*10 + 5, fill_color=colors)
show(p5)

In [ ]:
p5 = figure()
p5.scatter(x=lin_arr, y=sin_arr, size=cos_arr**2*10, fill_color=colors, fill_alpha=lin_arr/(4*np.pi))
show(p5)

Tools

If you notice the bar at the top of the you see several places to interact with the plot.

These are tools and there a many different tools built into the Bokeh.

Let's take a look at HoverTools


In [ ]:
source = ColumnDataSource(
    data=dict(
        x=lin_arr,
        y=sin_arr,
        size=cos_arr**2*10 + 5,
        colors=colors
    )
)

In [ ]:
from bokeh.models import HoverTool
from collections import OrderedDict

TOOLS="crosshair,pan,wheel_zoom,box_zoom,reset,hover,previewsave"
p6 = figure(title="Hoverful Scatter", tools=TOOLS)
p6.circle(x="x", y="y", size="size", source=source,
    fill_color="colors", fill_alpha=0.6, line_color=None)

hover = p6.select(dict(type=HoverTool))
hover.tooltips = OrderedDict([
    ("index", "$index"),
    ("(x,y)", "(@x, @y)"),
    ("size", "@size"),
    ("fill color", "$color[hex, swatch]:fill_color"),
])
show(p6)

Linking two plots

One of the best aspects of Bokeh is linked brushing.


In [ ]:
N = 300
x = np.linspace(0, 4*np.pi, N)
y1 = np.sin(x)
y2 = np.cos(x)

source = ColumnDataSource()
source.add(data=x, name='x')
source.add(data=y1, name='y1')
source.add(data=y2, name='y2')

TOOLS = "pan,wheel_zoom,box_zoom,reset,save,box_select,lasso_select"

s1 = figure(tools=TOOLS, plot_width=350, plot_height=350)
s1.scatter('x', 'y1', source=source)

# Linked brushing in Bokeh is expressed by sharing data sources between
# renderers. Note below that s2.scatter is called with the `source`
# keyword argument, and supplied with the same data source from s1.scatter
s2 = figure(tools=TOOLS, plot_width=350, plot_height=350)
s2.scatter('x', 'y2', source=source)

p = gridplot([[s1,s2]])
show(p)

Basic interactivity

Bokeh lets you use a Python update function to update your plots.

In IPython notebook we can use the interactive widgets provided by the notebook. We'll see how to make a interactive page outsite the notebook in a minute.


In [ ]:
x = np.linspace(0, 2*np.pi, 2000)
y = np.sin(x)

source = ColumnDataSource(data=dict(x=x, y=y))

p = figure(title="simple line example", plot_height=300, plot_width=600)
p.line(x, y, color="#2222aa", line_width=3, source=source, name="foo")

In [ ]:
def update(f, w=1, A=1, phi=0):
    if   f == "sin": func = np.sin
    elif f == "cos": func = np.cos
    elif f == "tan": func = np.tan
    source.data['y'] = A * func(w * x + phi)
    source.push_notebook()

In [ ]:
from IPython.html.widgets import interact
interact(update, f=["sin", "cos", "tan"], w=(0,100), A=(1,10), phi=(0, 10, 0.1))

In [ ]:
show(p)

In [ ]: