Search code examples
pythonbokeh

Bokeh: How to access Index with custom callback in HoverTool for a line?


I try to make a JSCallback for a line and access the index of it.
For the circle() glyph, this works if I precisely hover over the dot. In this case, the Hover annotation works and the cb_data['index'].indices holds the same value as the hover annotation shows. However, for the line() with mode='vline', this does not work. Even when the internal hover annotation shows an index, the cb_data['index'].indices is empty.
Below is a minimal working example that shows this case in the console log of the browser:

import pandas as pd

from bokeh.plotting import figure, curdoc
from bokeh.models import ColumnDataSource, HoverTool, CustomJS
from bokeh.layouts import layout

plot1 = figure(plot_width=1000, plot_height=250)
plot2 = figure(plot_width=1000, plot_height=250)

df = pd.DataFrame({"ID":[0, 1, 2, 3, 4, 5, 6, 7], 
                   "Value1":[0, 100, 200, 300, 400, 500, 600, 700], 
                   "Value2":[0, 1, 2, 4,8 , 16, 32, 64]})
source = ColumnDataSource(df)

line = plot1.line(x='ID', y='Value1', source=source)
circle = plot2.circle(x='ID', y='Value2', source=source)

callback = CustomJS(args=dict(source=source), 
                        code="""
                        console.log("Indices: "+ cb_data['index'].indices);
                        console.log("Mouse X: "+ cb_data['geometry'].x);
                        console.log("Mouse Y: "+ cb_data['geometry'].y);
                        """)

hover_tool_plot = HoverTool(mode='vline', callback=callback)

plot1.add_tools(hover_tool_plot)
plot2.add_tools(hover_tool_plot)

layout_ = layout([[plot1],[plot2]])
curdoc().add_root(layout_)

enter image description here When I hover between the two points 5 and 6, the hover annotation snaps to the index 6. However, the output looks as follows, which means there is no index selected:

Indices: 
VM612:6 Mouse X: 5.642537313432836
VM612:7 Mouse Y: 469.12556053811653

For the circle case, this does work (But as I said, only if I hover exactly over the point). enter image description here The output of the log indeed gives me the index 6.

Indices: 6
VM746:6 Mouse X: 5.995974576271187
VM746:7 Mouse Y: 32.473542600896856

Is there any way to get the correct index when hovering over the line using the mode='vline'?
I do need the index in the callback to set a line in another plot for my application.
PS: I´m running Bokeh as a server application.


Solution

  • For a line glyph, you want to look at .line_indices, not .indices.

    Note that there is no one "correct" answer about which index (previous? next? nearest?) should be returned. The hover tool has a line_policy setting that you can customize you your needs.