Hovertool Support for Live Streamed Data Plotting

Hi, I have a plot with multiple step glyphs where the data is live streamed. I am hoping to add multiple hover tools to see all values for each step, similar to what is implemented here: python - Multiple HoverTools for different lines (bokeh) - Stack Overflow

However, it seems that hover tools aren’t supported for steps as of Jan 2022, according to Glyph Hit Testing Census · bokeh/bokeh Wiki · GitHub.

I attempted to use lines instead of steps, and the hover tools worked great. However, the lines only sporadically plotted, which I am not certain why.

So my question here is is there any way to have hover tools for this situation? Either a better way to handle the live data to plot the lines consistently, or are there plans to support step hit testing?

I would appreciate any help or insight, thanks!

Here’s a picture of what the data looks like with step:

here’s what it looks like with line (not the same data as above, and also hovers not implemented here)

the flat dashed line is a constant and seems to always show, while the changing data has a hard time consistently plotting (only blue visible here)

Hi @alex-yang21 It’s not really possible to speculate or offer concrete suggestions without a complete Minimal Reproducible Example.

1 Like

Hi Bryan, thanks for getting back to me. Sorry for the lack of a proper example, and I’ve been trying to create a minimal reproducible example but haven’t been able to. I created an example that very closely mimics my plots behavior. The example however, works with both steps and lines, while the actual plot doesn’t…

This is the example:

from random import randint, uniform

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

ds1 = ColumnDataSource({"timestamp": [], "value1": []})
ds2 = ColumnDataSource({"timestamp": [], "value2": []})
ds3 = ColumnDataSource({"timestamp": [], "value3": []})

plot = figure(x_axis_type='linear',plot_width=1000, plot_height=600)

plot1 = plot.line(x='timestamp', y= 'value1', source=ds1, color='blue')
plot.add_tools(HoverTool(renderers=[plot1], tooltips=[('value1',"@value1")],mode='vline'))

plot2 = plot.line(x='timestamp', y= 'value2', source=ds2, color='red')
plot.add_tools(HoverTool(renderers=[plot2], tooltips=[("value2","@value2")],mode='vline'))

plot3 = plot.line(x='timestamp', y= 'value3', source=ds3, color='green')
plot.add_tools(HoverTool(renderers=[plot3], tooltips=[("value3","@value3")],mode='vline'))

now = 0
def callback():
    global now
    now = now + 1
    new_data1 = {"timestamp": [], "value1": []}
    new_data2 = {"timestamp": [], "value2": []}
    new_data3 = {"timestamp": [], "value3": []}

    choice = randint(0, 3)
    if choice == 0:
        new_data1["timestamp"].append(now)
        new_data1["value1"].append(uniform(0, 5))
        ds1.stream(new_data1, rollover=5)

        new_data2["timestamp"].append(now)
        new_data2["value2"].append(uniform(0, 5))
        ds2.stream(new_data2, rollover=5)

        new_data3["timestamp"].append(now)
        new_data3["value3"].append(3)
        ds3.stream(new_data3, rollover=5)
    elif choice == 1:
        new_data1["timestamp"].append(now)
        new_data1["value1"].append(uniform(0, 5))
        ds1.stream(new_data1, rollover=5)
    elif choice == 2:
        new_data2["timestamp"].append(now)
        new_data2["value2"].append(uniform(0, 5))
        ds2.stream(new_data2, rollover=5)
    elif choice == 3:
        new_data3["timestamp"].append(now)
        new_data3["value3"].append(3)
        ds3.stream(new_data3, rollover=5)

curdoc().add_root(column(plot))

update_interval_s = 2
curdoc().add_periodic_callback(callback, update_interval_s * 1000)

In this example, the lines pretty much work the same as the steps, and I’ve been trying to figure out why a line wouldn’t work when a step does in my actual plot. Will continue looking, thanks

Eventually found the issue. We were using a single ColumnDataSource and filtering it to produce the Line/Step we wanted (in our code, not the MRE above). Using a CDSView to filter out a ColumnDataSource does not work:
CDSView filters are not compatible with glyphs with connected topology such as Line or Patch

So a fix would be to use individual ColumnDataSources for each Line as I did in the example above

Also note we are using bokeh-2.4.2

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.