Hover with 2nd y-axis problem

I am attempting to get hover to work correctly with a graph that has a second y-axis. Currently, hover works fine with just 1 y-axis such as:

p = figure(x_axis_type=“datetime”, x_axis_label=x_axis_label, y_axis_label=y_axis_label, y_range=y_range, sizing_mode=“stretch_width”, output_backend=“webgl”)
p.add_tools(HoverTool(tooltips=[(‘Item’, ‘$name’),
(‘Time’, ‘$x{%Y-%m-%d %H:%M:%S}’),
(‘Voltage’, hov’$y{%1.1f} Volts’),
],
p.line(x, y, color=c, legend_label=‘label’, name=‘name’)

I’m adding data on a second y-axis with something like this:

p.extra_y_ranges = {“y2”: Range1d(start=bottom, end=top)}
p.add_layout(LinearAxis(y_range_name=“y2”, axis_label=‘Percent Disolved Oxygen’), ‘right’)
p.line(data[‘tstamp’], disolved_oxygen, legend=‘Disolved Ocygen %’, color = “cyan”, y_range_name = “y2”)

The hover tool does hovering on both data in the 1st y-axis (correctly), and also the second y-axis (but incorrectly).

Any thoughts on how to do this?

I don’t recall anyone ever asking about this, it’s possible there is just a bug. What it’s really needed is a complete Minimal Reproducible Example to run directly.

Here’s a simple example. I know I’m not doing the hover correctly but not sure how to proceed.

from bokeh.models import ColumnDataSource, HoverTool, Range1d, LinearAxis
from bokeh.plotting import figure, show
from datetime import datetime, timedelta

x = []
y1 = []
y2 = []
for i in range(0, 100):
    x.append(datetime(2022, 5, 25, 12, 0, 0) + timedelta(minutes=i))
    y1.append(i)
    y2.append(-i/10)

p = figure(x_axis_type='datetime', x_axis_label='Voltage')
p.add_tools(HoverTool(tooltips=[('Item', '$name'),
                                ('Time', '$x{%Y-%m-%d  %H:%M:%S}'),
                                ('Voltage', '$y{%1.1f} Volts'),                                     
                                ],
                      formatters={'$x': 'datetime', '$y': 'printf'}
                      ))
p.line(x, y1, name='Voltage')
p.extra_y_ranges = {"y2": Range1d(-10, 0)}
p.add_layout(LinearAxis(y_range_name = "y2", axis_label='Current'), 'right')
p.line(x, y2, color = "cyan", y_range_name = "y2")
show(p)

The $name hover variable refers to the name property on the glyph. You have configured name='Voltage' on the first line, but nothing at all on the second. (edit: worth also stating explicitly that the undesired result does not have anything to do with multiple axes).

Also @Jah gentle request for the future, please also always provide more detailed descriptions than “The hover tool does hovering …but incorrectly”. That is because “incorrectly” could mean any number of things, you need to state what you mean by it, to help save everyone time and effort. In this case, it would have been good to mention that “incorrectly” means “displays ??? instead of the expected data”.

Edit: and in fact, here I am simply assuming that the ??? was what you meant to refer to. But I can imagine other possible things you might have meant (e.g. maybe you don’t want “Volts” to appear for both lines?) So, really, you do need to be more specific about exactly what problem you are trying to solve.

By incorrect, I mean that the hover displays “Item: ???” when going over the plotted data from the y2 axis. Additionally, the hover (3rd piece of information) shows Voltage for the name but does have the correct y value. As I built the hover tool before I even created the y2 axis I would understand that the hover tool isn’t correctly configured for the second y2 axis. (1) I just wasn’t clear how to build the hover tool for the y2 axis and (2) the hover behavior seems odd for the y2 axis given the incomplete way in which I built it.

You mention that I “have configured name=‘Voltage’ on the first line, but nothing at all on the second…”. What do you mean by “line”? I do not follow the idea of first and second lines?

I apologize for not being precise. As I mentioned earlier, I know I’m not setting up the hover tool correctly to handle the y2 axis. I just do not understand how to do it and was asking if somebody had thoughts on how to correctly add a hover tool to the y2 axis. In this case, I would like the y2 hover to have the Item be “Current” and when hovering over a y2 sample the third piece of information in the hover box to read “Current: xx Amps”.

You called the line method twice in your code:

p.line(x, y1, name='Voltage')   # first has name

p.line(x, y2, color = "cyan", y_range_name = "y2") # second does not

To reiterate what I noted above: these issues have nothing at all to do with a second axis

I now understand that my p.line() for the y2 axis did not use the “name” parameter. Thus, I’ve added name=‘Current’ to that call:

p.line(x, y2, name='Current', color = "cyan", y_range_name = "y2")

That now takes care of the “Item: ???” in the hover tool.

It appears to me that I’ll need to make my hover tooltip more generic and instead of having the (‘Voltage’, ‘$y(%1.1f) Volts’) I might have to change it to just something like (‘Value’, ‘$y(%1.1f)’).

p.add_tools(HoverTool(tooltips=[(‘Item’, ‘$name’),
(‘Time’, ‘$x{%Y-%m-%d %H:%M:%S}’),
(‘Value’, ‘$y{%1.1f}’),
],
formatters={’$x’: ‘datetime’, ‘$y’: ‘printf’}
))

My (limited) understanding of the hover tool is that it will apply to all items in the figure, regardless the data in associated with the first or second y axis.

My (limited) understanding of the hover tool is that it will apply to all items in the figure, regardless the data in associated with the first or second y axis.

Yes, by default the hovertool triggers on all renderers. BUT you can control what renderers it triggers on:

#create a pointer to the renderer when you instantiate it
r1 = p.line(.....
#then when you make your hovertool...
p.add_tools(HoverTool(renderers=[r1],tooltips=[(....

This hovertool will now only trigger on r1 and nothing else in the plot.

Thank you @gmerritt123 ! That’s exactly what I was looking for.

1 Like