1

I have a graph with multiple lines. I want to make a line in bold when hovered. Other lines should be untouched.

In the example below, the tooltip works fine, but the hover_glyph doesn't. If I hover one line then both lines are getting wider. If I hover the second line, nothing happens to both lines. How to make it working?

x = np.linspace(0, 4 * np.pi, 100)
y1 = np.sin(x)
y2 = np.cos(x)

output_notebook()

source = ColumnDataSource(pd.DataFrame(data={'L1': y1, 'L2': y2}, index=x))
f = figure(tools='xwheel_zoom, wheel_zoom, pan', active_scroll='xwheel_zoom', active_drag='pan')

g1 = f.line(x='index', y='L1', source=source, color=Spectral11[1], legend_label='L1', name='L1') 
gg1 = g1.hover_glyph = Line(line_color=Spectral11[1], line_width=5)

g2 = f.line(x='index', y='L2', source=source, color=Spectral11[3], legend_label='L2', name='L2') 
gg2 = g2.hover_glyph = Line(line_color=Spectral11[3], line_width=4)

hover = HoverTool(renderers=[g2])
hover.tooltips=[
            ('both fields', '@L1'+':'+'@L2'),
            ('name', '$y'),
            ('Number', '$name')
        ]
f.add_tools(hover)

hover2 = HoverTool(renderers=[g1])
hover2.tooltips=[
            ('name', '$y'),
            ('Number', '$name')
        ]
f.add_tools(hover2)

show(f)
hopeman
  • 153
  • 1
  • 9
  • You could maybe make it a little easier for somebody to help if you edited the post to include the necessary imports. – TMBailey Feb 24 '23 at 08:19
  • 1
    This looks like a bug to me and I opend [issues #128459](https://github.com/bokeh/bokeh/issues/12845) because of this. – mosc9575 Feb 24 '23 at 10:11
  • Thank you for the ticket in bokeh github. There is good answer for this from mattpap: https://github.com/bokeh/bokeh/issues/12845#issuecomment-1443921178 – hopeman Feb 26 '23 at 12:19

2 Answers2

1

A possible work-around might be to use multi_line.

For completeness, here is a slightly simpler, self-contained, working demo of the issue. This snippet should highlight L1 but not L2 when L1 is hovered. Instead, both lines are highlighted when L1 is hovered.

from bokeh.io import output_notebook, show
from bokeh.models import HoverTool
from bokeh.palettes import Spectral11
from bokeh.plotting import figure, ColumnDataSource

import numpy as np

output_notebook()

x = np.linspace(0, 4 * np.pi, 100)
y1 = np.sin(x)
y2 = np.cos(x)
source = ColumnDataSource({'L1': y1, 'L2': y2, 'index': x})

f = figure(tools='')
g1 = f.line(x='index', y='L1', source=source, color=Spectral11[1], legend_label='L1', name='L1',
            hover_line_width=4)
g2 = f.line(x='index', y='L2', source=source, color=Spectral11[3], legend_label='L2', name='L2',
           hover_line_width=4)

hover = HoverTool(renderers=[g1])  # Activate hover only for L1.
f.add_tools(hover)

show(f)

EDIT: ADDED POSSIBLE WORK-AROUND

If you are happy to work with multi-lines, the line highlighting feature seems to work for them so that might be a work-around. I haven't tried to reproduce the tooltips shown in the original question, though.

from bokeh.io import output_notebook, show
from bokeh.models import HoverTool
from bokeh.palettes import Spectral11
from bokeh.plotting import figure, ColumnDataSource

import numpy as np

output_notebook()

x = np.linspace(0, 4 * np.pi, 100)
y1 = np.sin(x)
y2 = np.cos(x)

source = ColumnDataSource({
    "index": [x, x],
    "y": [y1, y2],
    "color": [Spectral11[1], Spectral11[3]],
    "label": ["L1", "L2"]
})

f = figure(tools='')
g = f.multi_line(xs="index", ys="y", source=source, color="color", legend_group="label",
                 hover_line_width=4)

hover = HoverTool(renderers=[g],
                  tooltips="@label: $data_x, $data_y")
f.add_tools(hover)

show(f)
TMBailey
  • 557
  • 3
  • 14
  • This is not an answer. If you want to improve the question, you can request or apply some changes by [editing](https://stackoverflow.com/posts/75512155/edit) the question. – mosc9575 Feb 24 '23 at 10:12
  • I guess there is some risk that actual answers might never emerge if people overlook this question because it seems to already have an answer--that would be a shame. – TMBailey Feb 24 '23 at 13:22
  • @TMBaily: Your multipline workaround is very good. I want to mention that I had to set `hover = HoverTool(renderers=[g],tooltips=None)` to make it work in bokeh 3.0.3. Before there was an error in the browser console. – mosc9575 Feb 24 '23 at 16:28
  • @mosc9575: Thanks. I don't see that error, but I've got bokeh 2.3.2. – TMBailey Feb 25 '23 at 08:36
1

The two renderer are connected because they share the same source.

If you want to split the hover action, you have to split the source into two sources.

import numpy as np
from bokeh.plotting import figure, show, output_notebook
from bokeh.models import ColumnDataSource, HoverTool
from bokeh.palettes import Spectral11
output_notebook()

x = np.linspace(0, 4 * np.pi, 100)
y1 = np.sin(x)
y2 = np.cos(x)

source1 = ColumnDataSource({'L1': y1, "index":x})
source2 = ColumnDataSource({'L1': y1,'L2': y2, "index":x})

p = figure(tools='xwheel_zoom, wheel_zoom, pan', active_scroll='xwheel_zoom', active_drag='pan')

g1 = p.line(x='index', y='L1', source=source1, color=Spectral11[1], legend_label='L1', name='L1',
            hover_line_color=Spectral11[1], hover_line_width=5)

# workaround for the hover information "both fields"
p.line(x='index', y='L1', source=source2, color=Spectral11[1], legend_label='L1', name='L2', line_width=0)

g2 = p.line(x='index', y='L2', source=source2, color=Spectral11[3], legend_label='L2', name='L2',
            hover_line_color=Spectral11[3], hover_line_width=4)

hover = HoverTool(renderers=[g2])
hover.tooltips=[
            ('both fields', '@L1:@L2'),
            ('name', '$y'),
            ('Number', '$name')
        ]
p.add_tools(hover)

hover2 = HoverTool(renderers=[g1])
hover2.tooltips=[
            ('name', '$y'),
            ('Number', '$name')
        ]
p.add_tools(hover2)

show(p)

Comment: You one hover tool information was a bit tricky. The workaround might be ok, but is far from perfect.

mosc9575
  • 5,618
  • 2
  • 9
  • 32
  • Nice. I guess this is a case of "linked hover" behavior. I'm guessing the whole row of the source is hovered together, but I have not found that in the docs. I've only found one sorta relevant reference to shared "selections and hovered inspections" buried under a section on linked selection with filtered data, and that is about linking between different plots. – TMBailey Feb 25 '23 at 09:00
  • Exactly, the same answer gave mattpap on github: https://github.com/bokeh/bokeh/issues/12845#issuecomment-1443921178 . It solved the issue. – hopeman Feb 26 '23 at 12:20