New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bokeh visualization library by Alex Razoumov #55

Closed
razoumov opened this Issue Dec 7, 2015 · 0 comments

Comments

Projects
None yet
2 participants
@razoumov
Collaborator

razoumov commented Dec 7, 2015

Details

Bokeh is an open-source python library for interactive visualization in a web browser.

Where: Simon Fraser University, Burnaby Campus, Library Research Commons
When: 11:30 am - 12:30 pm, Monday, February 29, 2015

Prerequisite knowledge: Entry level Python
Dependencies: Python 3 (or higher) and Bokeh library

Etherpad: https://etherpad.wikimedia.org/p/2016-02-29-SFU
Video: https://plus.google.com/events/cjr1dpiaf2hmsnkveautq7ft9a8

The Bokeh library provides a nice Python (or R/Julia/Scala) interface for generating JSON objects which
are then consumed by the BokehJS library running in the browser.

Installation method #1 (if installing from scratch)

Install Anaconda python distribution from http://continuum.io/downloads. It should come with all the
dependencies included.

Installation method #2 (if you have conda installed)

conda install pip
conda install numpy
conda install ipython
pip install jupyter
conda install bokeh   # installs the dependencies as well

Optional sample data -- we won't be using it much

import bokeh
bokeh.sampledata.download()   # will download 74M into ~/.bokeh/data

Running bokeh

There are three types of output in bokeh: output_file(), output_notebook(), output_server(). First, let's
try output_file(). Start with a very simple example:

from bokeh.plotting import figure, output_file, show
output_file("output.html")
p = figure()
p.line(x=[1, 2, 3], y=[4, 8, 1])
show(p)   # will save the file and open it automatically in your browser
# save(p)   # will only save the file
from bokeh.plotting import figure, output_file, show, save
from numpy import *
output_file("lines.html", title="simple example")
x = arange(0,2*pi+.01,.1)
p = figure(title="few functions", x_axis_label='x', y_axis_label='y')   # create a new plot
p.line(x, sin(x), legend="sin(x)", line_width=2)   # render a line with these properties
p.line(x, cos(x), legend="cos(x)", line_width=2, line_color="red", line_dash="4 10")
p.circle(x, sqrt(x), legend="sqrt(x)", fill_color="orange", size=6)
show(p)

Take a look at what's inside lines.html: it's a static html, with BokehJS JavaScript/CSS embedded -- no
need to be online to display it.

We can also run bokeh from the command line. Let's save the following script in a file scatter.py:

from bokeh.plotting import figure, show, output_file
from numpy import random, pi, sin
n = 1000
x = random.normal(0, pi, n)
y = sin(x) + random.normal(0, 0.2, n)
output_file("scatter.html", title="simple scatter plot")
p = figure()
p.scatter(x, y, alpha=0.1)
show(p)

Run it from the command line:

$ bokeh html scatter.py
$ open scatter.html

Next, let's take start jupyter notebook with "ipython notebook". In the Python code simply replace
output_file() with output_notebook().

from bokeh.plotting import figure, output_notebook, show
from numpy import *
output_notebook()
x = arange(0,2*pi+.01,.1)
p = figure(title="few functions", x_axis_label='x', y_axis_label='y')   # create a new plot
p.line(x, sin(x), legend="sin(x)", line_width=2)
p.line(x, cos(x), legend="cos(x)", line_width=2, line_color="red", line_dash="4 10")
p.circle(x, sqrt(x), legend="sqrt(x)", fill_color="orange", size=6)
show(p)
help(p.line)   # show help on line() method
help(p.circle)   # show help on circle() method

Now let's do several panels in a single plot:

from bokeh.plotting import figure, output_notebook, show, gridplot
from numpy import *
output_notebook()
x = arange(0,2*pi+.01,.1)
s1 = figure(width=400, height=350, title=None)
s1.line(x, sin(x), legend="sin(x)", line_width=2)
s2 = figure(width=400, height=350, title=None)
s2.line(x, cos(x), legend="cos(x)", line_width=2, line_color="red", line_dash="4 10")
s3 = figure(width=400, height=350, title=None)
s3.circle(x, sqrt(x), legend="sqrt(x)", fill_color="orange", size=6)
p = gridplot([ [s1, s2], [None, s3] ])
show(p)

Now let's add "x_range=s1.x_range" argument to s3 = figure(...) -- this will link s1's and s3's
horizontal axes.

The next example shows "tools" argument to figure(), and how we can set colors continuously:

from bokeh.plotting import figure, output_notebook, show
from numpy import random
n = 4000
x = random.random(size=n) * 100   # 4000-long array with each element in [0,100]
y = random.random(size=n) * 100
radii = random.random(size=n) * 1.5
colors = ["#%02x%02x%02x" % (int(r), int(g), 150) for r, g in zip(50+2*x, 30+2*y)]   # hexadecimal
output_notebook()
buttons="resize,crosshair,pan,wheel_zoom,box_zoom,reset,box_select,lasso_select"
p = figure(tools=buttons, x_range=(0,100), y_range=(0,100))
p.circle(x,y, radius=radii, fill_color=colors, fill_alpha=0.6, line_color=None)
show(p)

There are many other markers:

  • already saw circle()
  • also asterisk(), circle_cross(), circle_x(), cross(), diamond(), diamond_cross(), inverted_triangle(),
    square(), square_cross(), square_x(), triangle(), x()

Multiple lines

from bokeh.plotting import figure, output_notebook, show
output_notebook()
p = figure(width=400, height=400)
xlist = [ [1,3,2], [3,4,6,6] ]
ylist = [ [2,1,4], [4,7,8,5] ]
p.multi_line(xlist, ylist, color=["red", "navy"], alpha=[0.8, 0.2], line_width=5)
show(p)

Other glyph functions

  • patch() # filled polygon
  • patches() # multiple filled polygons
  • quad() # filled rectangle along major axes
  • rect() # filled rectangle in any direction
from bokeh.plotting import figure, show, output_notebook
output_notebook()
from math import pi
p = figure(width=400, height=400)
p.rect(x=[1, 2, 3], y=[1, 2, 3], width=0.2, height=40, color="orange", angle=pi/3, height_units="screen")
show(p)

Now add "x_range=(0,3)" argument to p = figure(...) call.

  • oval() # filled oval
  • image() # heat map
  • ray() # radial segments
  • arc()
  • wedge()
  • annular_wedge()

Now let's pick up a static example from http://bokeh.pydata.org/en/latest/docs/gallery.html and paste its
source code into our notebook. Don't forget to replace output_file() with output_notebook().

Similar to bokeh.plotting interface, bokeh.charts can make statistical charts
http://bokeh.pydata.org/en/latest/docs/user_guide/charts.html (wait to load). Many of its functions take
a dataframe source.

from bokeh.charts import Scatter, output_notebook, show
from bokeh.sampledata.autompg import autompg as df
p = Scatter(df, x='mpg', y='hp', xlabel="mpg", ylabel="horsepower", color="blue")
output_notebook()
show(p)

Now replace color="blue" with color="cyl", which is another column in the dataframe.

Interactivity through Jupyter notebook widgets (does not work for output_file())

# First, a simple line plot -- nothing unusual here:
from numpy import *
from bokeh.io import push_notebook
from bokeh.plotting import figure, show, output_notebook
from ipywidgets import interact
x = linspace(0,2*pi,1000)
y = sin(x)
output_notebook()
p = figure(title="simple", height=500, width=600, y_range=(-5,5))
r = p.line(x,y,color='blue',line_width=3)
show(p)

# we can access the line points with
print(r.data_source.data['x'])
print(r.data_source.data['y'])

# define a function
def update(f,w=1,A=1,phi=0):
    if f=='sin': fun=sin
    elif f=='cos': fun=cos
    elif f=='tan': fun=tan
    r.data_source.data['y'] = A * fun(w*x + phi)
    push_notebook()   # update the last notebook plot with the new data

# display a widget tied to update()
interact(update,f=['sin','cos','tan'],w=(0,10),A=(1,3,0.2),phi=(0,20,0.1))

Interactivity through Bokeh widgets

Interactivity through JavaScript callbacks

Run power.py inside the ipython notebook.

Bokeh server <--> python script

We can push script's output to a session on a bokeh server. First, start the server:

$ bokeh serve

and then connect to it from a running script:

from bokeh.plotting import figure, show, output_server
p = figure(title="Server Plot")
p.circle([1, 2, 3], [4, 5, 6])
output_server("hover")   # name of the session; any existing session with same name will be overwritten
show(p)    # open a page in the browser pointing to the server

Or we can simply start the script (BOKEH APPLICATION) and attach it to the server in one command (without
using output_server() !):

$ bokeh serve --show dropNumbers.py   # copy dropNumbers.py from etherpad

WebGL

Let's take our file scatter.py (that we wrote before) and set n=100000 (1e5) and use
figure(webgl=False). Then run it from the command line:

$ bokeh html scatter.py
$ open scatter.html   # this is the step that should be accelerated with WebGL

On my laptop I get 5s (webgl=False) vs. 2s (webgl=True) rendering time in the browser. It seems that the
default figure() without arguments does not use WebGL.

Mapping geo data with Google Maps

Can put a glyph on top of google maps -- run gmap.py from the etherpad in the ipython notebook.

@razoumov razoumov added the workshop label Dec 8, 2015

@ttimbers ttimbers changed the title from Bokeh visualization library to Bokeh visualization library by Alex Razoumov Feb 25, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment