Can we use the bokeh
library to make an interactive image plot? All we need is to be able to capture an (x,y) pixel position on an image, so we can use it in our lens model. Let's start by following this tutorial and see how far we get.
In [ ]:
# !conda install bokeh
In [28]:
import numpy
import bokeh.plotting
import bokeh.models
In [2]:
# Set the output to 'notebook' mode
bokeh.plotting.output_notebook()
In [3]:
# Simple numpy calculation of a sine wave:
x = numpy.arange(0.0, 100.0, 0.1)
y = numpy.sin(x)
In [4]:
# Make a basic interactive plot with bokeh:
p = bokeh.plotting.figure(title="Sin(x)", plot_width=300, plot_height=300)
p.line(x,y, line_width=3.0)
bokeh.plotting.show(p)
Out[4]:
Bokeh provides a HoverTool
that keeps track of where the cursor is, and a TapTool
to enable actions on mouse clicks (see the API reference guide for more details about the available tools). We can use both in concert to enable positions to be recorded in the notebook when a click is made.
In [32]:
# Make a data point (a "source") to move around:
s = bokeh.plotting.ColumnDataSource(data = dict(x=[0],y=[0])) # initialize source at the origin (although this doesn't matter)
# Set up a TapTool to listen for mouse clicks, extract the source position, and reset the notebook x, y variables:
tcallback = bokeh.models.CustomJS(args=dict(s=s), code="""
var x = s.get('data')['x']; // pointer to source x position
var y = s.get('data')['y']; // pointer to source y position
var kernel = IPython.notebook.kernel; // not sure why this needs to be declared?
IPython.notebook.kernel.execute("x = " + x);
IPython.notebook.kernel.execute("y = " + y);
""")
tap_tool = bokeh.models.TapTool(callback=tcallback)
# Set up a HoverTool that continuously changes the source position, ready for it to be read by the TapTool:
hcallback = bokeh.models.CustomJS(args=dict(s=s), code="""
var geometry = cb_data['geometry'];
var x_data = geometry.x; // current mouse x position in plot coordinates (set by x_range)
var y_data = geometry.y; // current mouse y position in plot coordinates (set by y_range)
var x = s.get('data')['x']; // pointer to source x position
var y = s.get('data')['y']; // pointer to source y position
console.log("(x,y)=" + x_data+","+y_data); // enable monitoring of values in Javascript console
x[0] = x_data; // update source x position
y[0] = y_data; // update source y position
s.trigger('change');
""")
hover_tool = bokeh.models.HoverTool(callback=hcallback,tooltips=None)
# "Plot" the point in the figure, with very small size so we only see the cursor in practice:
p = bokeh.plotting.figure(x_range=(0,100), y_range=(0,100), tools=[hover_tool,tap_tool])
p.scatter(x='x',y='y',size=0.001,source=s)
bokeh.plotting.show(p)
Out[32]:
The x
and y
variables now contain the position of the last click!
In [31]:
print x, y
In [ ]: