0
votes

I've modified the multi_line plot example provided on the official bokeh usage guide pages to add a HoverTool with tooltips. (Usage guide example)

from bokeh.plotting import figure, output_file, show
from bokeh.models import ColumnDataSource, HoverTool

output_file("patch.html")

plot_data=dict(
        xs=[[1, 3, 2], [3, 4, 6, 6]],
        ys=[[2, 1, 4], [4, 7, 8, 5]],
        colors=["firebrick", "navy"],
        alphas=[0.8, 0.3])

hover=HoverTool(tooltips=[
        ('X-Coordinate','@xs'),
        ('Y-Coordinate','@ys')])

dsource = ColumnDataSource(plot_data)
p = figure(plot_width=400, plot_height=400, tools=[hover, 'wheel_zoom', ])
p.multi_line('xs', 'ys', color='colors', alpha='alphas', line_width=4, 
source=dsource)

show(p)

I would expect the tooltip to show the x and y coordinates of the point over which (near to) i hover the pointer. However, the tooltip contains the x and y co-ordinates of all the line points over which the pointer hovers.

Is there a way/option buried somewhere (i tried to hard to find it) to make HoverTool-tool to display the co-ordinates of a single point?

P.S. - I know that $x, $y and $sx, $sy can be used to display the screen and canvas x, y co-ordinates respectively but in my case x axis could be a datetime axis as well in which case i would want one single date in the tooltip instead of all the dates.

enter image description hereenter image description here

2
This is something that should be made better at the Bokeh level: github.com/bokeh/bokeh/issues/7969bigreddot
Glad you guys are taking it up.Parikshit Bhinde

2 Answers

1
votes

Make an invisible line, and set it into the hover.renderers:

import numpy as np
from itertools import chain
nan = itertools.repeat([np.nan])
xs, ys = (np.concatenate(list(chain(*zip(plot_data[name], nan)))) for name in ["xs", "ys"])
dsource2 = ColumnDataSource(dict(xs=xs, ys=ys))
line = p.line('xs', 'ys', source=dsource2, alpha=0)
hover.renderers = [line]
0
votes

Posting the answer with full code including the solution provided by HYRY :

from bokeh.plotting import figure, output_file, show
from bokeh.models import ColumnDataSource, HoverTool

import numpy as np
import itertools
from itertools import chain

output_file("patch.html")

plot_data=dict(
        xs=[[1, 3, 2], [3, 4, 6, 6]],
        ys=[[2, 1, 4], [4, 7, 8, 5]],
        colors=["firebrick", "navy"],
        alphas=[0.8, 0.3])

hover=HoverTool()

dsource = ColumnDataSource(plot_data)
p = figure(plot_width=400, plot_height=400, tools=[hover, 'wheel_zoom', ])
p.multi_line('xs', 'ys', color='colors', alpha='alphas', line_width=4, source=dsource)


nan = itertools.repeat([np.nan])
xs, ys = (np.concatenate(list(chain(*zip(plot_data[name], nan)))) for name in ["xs", "ys"])
dsource2 = ColumnDataSource(dict(xs=xs, ys=ys))
line = p.line('xs', 'ys', source=dsource2, color='white', line_width=1, alpha=1)
hover.renderers = [line]

show(p)

I have modified the properties of the 'invisible' line to indicate how it's drawn over the existing lines and hence provide the coordinates. The output now looks like:enter image description here