This question is somewhat similar to:
Consider the example below:
import bokeh.plotting
import bokeh.io
import bokeh.layouts
from bokeh.models import HoverTool
from bokeh.models import ColumnDataSource
# Data for plot
data = {'xl':[[3,4,5],[6,7,8]]
,'yl':[[1,3,2],[4,5,6]]
,'xp':[1,2]
,'yp':[3,4]
,'c':['blue','red']}
s1 = ColumnDataSource(data)
# make plots
p1 = bokeh.plotting.figure()
r1 = p1.multi_line(xs='xl', ys='yl', width=2, line_color='c',hover_color='green',source=s1)
p2 = bokeh.plotting.figure()
r2 = p2.scatter(x='xp', y='yp', size=20,fill_color='c',hover_color='green',source=s1)
# Add hovers
h1 = HoverTool(renderers=[r1])
h1.tooltips = ([('xl', '@xl}'), ('yl', '@yl')])
p1.add_tools(h1)
h2 = HoverTool(renderers=[r2])
h2.tooltips = ([('xp', '@xp}'), ('yp', '@yp')])
p2.add_tools(h2)
# Plot
layout = bokeh.layouts.layout([p1,p2])
bokeh.io.show(layout)
Here, I’m creating two plots, one with a multiline glyph and another with a scatter glyph. Both use the same source but use different fields in the datasource to drive their respective glyphs. This is amazing - hover over one line highlights its equivalent point on the other plot, and hover over a point highlights its corresponding line in the other plot. I cannot stress how amazing this is for my field of hydrogeology where we look at water level over time on one plot (lines) and want to see its corresponding location in plan view (pts).
I’ve run into a situation where instead of lines on p1, I want points. Essentially I want each line vertice to be a scatter point, and I want the hover behaviour to remain the same (i.e. hover over a point in p2, all corresponding points trigger hover on p1). My current workaround/partial solution is pretty dirty - I’m just flattening everything prior to passing it to the datasource:
import bokeh.plotting
import bokeh.io
import bokeh.layouts
from bokeh.models import HoverTool
from bokeh.models import ColumnDataSource
import numpy as np
data = {'xl':np.array([[3,4,5],[6,7,8]]).flatten()
,'yl':np.array([[1,3,2],[4,5,6]]).flatten()
,'xp':[1,1,1,2,2,2]
,'yp':[3,3,3,4,4,4]
,'c':['blue','blue','blue','red','red','red']}
s1 = ColumnDataSource(data)
# make plots
p1 = bokeh.plotting.figure()
r1 = p1.scatter(x='xl', y='yl', size=10, fill_color='c',hover_color='green',source=s1)
p2 = bokeh.plotting.figure()
r2 = p2.scatter(x='xp', y='yp', size=20,fill_color='c',hover_color='green',source=s1)
# Add hovers
h1 = HoverTool(renderers=[r1])
h1.tooltips = ([('xl', '@xl}'), ('yl', '@yl')])
p1.add_tools(h1)
h2 = HoverTool(renderers=[r2])
h2.tooltips = ([('xp', '@xp}'), ('yp', '@yp')])
p2.add_tools(h2)
# Plot
layout = bokeh.layouts.layout([p1,p2])
bokeh.io.show(layout)
This “kinda” works - on p2 (the right plot), I’m just stacking multiple points on top of each other. The hover on p2 gets pretty ugly as a result, and of course this is not very efficient.
I’m wondering if there are any suggestions to improving my workaround. I essentially need a one to many hover relationship between two renderers, which are both ideally built from the same datasource… OR i need a “MultiScatter” type model that works the same way as MultiLine. Any input much appreciated! Thanks!