Two-dimensional interactive contour plot using Python and Bokeh


The result is:

Two-dimensional interactive contour plot using Python and Bokeh

Bokeh is powerful plotting tools using nodejs. Although this code doesn't use matplotlib, I want to introduce how to generate 2D interactive contour plot using Bokeh.

See also:

Python Matplotlib Tips: Interactive plot using Bokeh - first step -

I firstly thought that Bokeh uses matplotlib. We generate figure using matplotlib then convert the figure to the Bokeh compatible. However, it seems Bokeh works stand alone without matplotlib (is it true?) Anyway, let's check whether Bokeh works in my environment or not.


In [1]:
import platform
print('python: '+platform.python_version())
import numpy as np
print('numpy: '+np.__version__)
python: 3.6.3
numpy: 1.15.4

Load Bokeh

In [2]:
from bokeh.plotting import figure, show, output_file
from bokeh.io import output_notebook
import bokeh
print('bokeh: '+bokeh.__version__)
output_notebook()
bokeh: 1.0.1
Loading BokehJS ...

Define function

In [3]:
def bivariate_normal(X, Y, sigmax=1.0, sigmay=1.0,
                     mux=0.0, muy=0.0, sigmaxy=0.0):
    """
    Bivariate Gaussian distribution for equal shape *X*, *Y*.
    See `bivariate normal
    <http://mathworld.wolfram.com/BivariateNormalDistribution.html>`_
    at mathworld.
    """
    Xmu = X-mux
    Ymu = Y-muy

    rho = sigmaxy/(sigmax*sigmay)
    z = Xmu**2/sigmax**2 + Ymu**2/sigmay**2 - 2*rho*Xmu*Ymu/(sigmax*sigmay)
    denom = 2*np.pi*sigmax*sigmay*np.sqrt(1-rho**2)
    return np.exp(-z/(2*(1-rho**2))) / denom

Calculate data

In [4]:
delta = 0.02
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
# difference of Gaussians
Z = 10.0 * (Z2 - Z1)

Plot data using Bokeh

In [5]:
p = figure(x_range=(-3, 3), y_range=(-2, 2),
           tooltips=[("x", "$x"), ("y", "$y"), ("value", "@image")])

# must give a vector of image data for image parameter
p.image(image=[Z], x=-3, y=-2, dw=6, dh=4, palette="RdBu11")

show(p)