1

I'd like to use multiple Hovertools in one plot together with Hovertool's names attribute to selectivly apply each tool. Take for instance

hover1 = HoverTool(tooltips=[("group", "1")], names = ['line1'])
hover2 = HoverTool(tooltips=[("group", "2")], names = ['lines2'])

and the two data sources:

source1 = ColumnDataSource(data=dict(
xs=[[1, 3, 2], [3, 4, 6, 6]],
ys=[[2, 1, 4], [4, 7, 8, 5]], 
))

source2 = ColumnDataSource(data=dict(
xs=[[1, 3, 2], [6, 7, 9, 8]],
ys=[[-1, 0, 1], [1, 1, 2, 1]]
))

I'd though the following (using the bokeh.models API) should do what I want

p = figure(plot_width=400, plot_height=400)
l1 = MultiLine(xs='xs', ys='ys', name='lines1')
l2 = MultiLine(xs='xs', ys='ys', name='lines2')
p.add_tools(hover)
p.add_tools(hover2)
p.add_glyph(source1, l1)
p.add_glyph(source2, l2)
show(p)

Alas the Hovertools in the resulting plot do not work (i.e. no tooltips are shown). Using the bokeh.plotting API as follows and everything works as expected:

p = figure(plot_width=400, plot_height=400, tools=[hover, hover2])
p.multi_line(xs='xs', ys='ys', source=source1, name='lines1')
p.multi_line(xs='xs', ys='ys', source=source2, name='lines2')
show(p)

Question: How does one replicate the result of the bokeh.plotting API with the bokeh.models API?

ChesuCR
  • 9,352
  • 5
  • 51
  • 114
Sascha
  • 219
  • 4
  • 12
  • You can have more than one renderer on one `Hovertool`. But you can´t use more than one `Hovertool` on the same plot, as far as I know. You can customise you hover tooltips with a callback called `CustomJSHover`. Check the documentation – ChesuCR Jun 13 '18 at 11:43
  • @ChesuCR When using the plotting API there is a warning about duplicate tools but using multiple `HoverTool`s otherwise seems to work all right (there is even an individual icon in the toolbar for each `HoverTool` that allows enabling/disabling it individually). – Sascha Jun 13 '18 at 11:53
  • See [this Q&A](https://stackoverflow.com/a/34534995/9629533) for the use of multiple hover tools as well. – Sascha Jun 13 '18 at 11:58
  • Ah!! Good to know. I have tried to make that work time ago and it didn´t work, maybe I had used a different tool. Anyway check if my answer that I have written is useful for you – ChesuCR Jun 13 '18 at 22:13

1 Answers1

5

The names attribute of the HoverTool model in the Bokeh Documentation:

names: property type: List ( String )

A list of names to query for. If set, only renderers that have a matching value for their name attribute will be used.

With this

l1 = MultiLine(xs='xs', ys='ys', name='lines1')

You are assigning the name to the Multiline object and that is a glyph, not a renderer. So try this instead

from bokeh.io import output_notebook, show
output_notebook()

import numpy as np
from bokeh.plotting import figure
from bokeh.models.sources import ColumnDataSource
from bokeh.models.glyphs import MultiLine
from bokeh.layouts import row
from bokeh.models.tools import HoverTool

source = ColumnDataSource(data=dict(
        xs1=[[1, 2, 3], [5, 6, 7]],
        ys1=[[1, 2, 3], [6, 5, 7]],
        xs2=[[7, 8, 9], [1, 2, 3]],
        ys2=[[4, 5, 7], [6, 7, 2]],
    )
)

hover1 = HoverTool(tooltips=[("group", "1")], names = ['lines1'])
hover2 = HoverTool(tooltips=[("group", "2")], names = ['lines2'])

p = figure(plot_width=400, plot_height=400)
l1 = MultiLine(xs='xs1', ys='ys1')
l2 = MultiLine(xs='xs2', ys='ys2')
r1 = p.add_glyph(source, l1, name='lines1')  # the name is assigned to the renderer
r2 = p.add_glyph(source, l2, name='lines2')
# r1.name = 'lines1'  # or you could assign the name like this as well
# r2.name = 'lines2'

p.add_tools(hover1)
p.add_tools(hover2)

# p = figure(plot_width=400, plot_height=400, tools=[hover1, hover2])
# p.multi_line(xs='xs1', ys='ys1', source=source, name='lines1')
# p.multi_line(xs='xs2', ys='ys2', source=source, name='lines2')


show(p)
ChesuCR
  • 9,352
  • 5
  • 51
  • 114
  • Works like a charm! Thanks a lot not only for taking time to find a solution but also explaining the solution :) – Sascha Jun 14 '18 at 06:35
  • Nice!! Mark the post as the correct answer if it works. Thank you – ChesuCR Jun 14 '18 at 08:34
  • @ChesuCR I am getting the following error. It doesn't seem to be accepting a list. Tried with plain string but it didn't work. It's been a while since you posted this so I am assuming things have changed in Bokeh 3.2.1 Error: ValueError: failed to validate HoverTool(id='p1010', ...).name: expected either None or a value of type String, got ['line1'] – Gopinath S Aug 03 '23 at 01:55
  • Ah you are right, they should have changed that at some point. I may update the answer in the future. Thanks – ChesuCR Aug 08 '23 at 06:23