0
votes

I have this code here which creates a bokeh plot where all plots pan and zoom together. I want to be able to hide the same named line, 'line1', simultaneously on all 3 plots when I click the line1 legend item (or an optional additional widget or checkbox outside the plots) instead of having to click them individually. How do I do that?

Line 1 could be created from a different data source every time, ie the x values for all the lines are the same but the y values could be different between (plot 0, line1) and (plot 1, line1)

Current Output:

plot with all graphs

Wanted Output:

enter image description here

from bokeh.io import output_file, show,save
from bokeh.layouts import column
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource

output_file("panning.html")
data=[]
x = list(range(11))
y0 = x
y1 = [10-xx for xx in x]
y2 = [abs(xx-5) for xx in x]
source = ColumnDataSource(data=dict(x=x, y0=y0, y1=y1,y2=y2))
for i in range(3):
    p = figure(title="Basic Title", plot_width=300, plot_height=300)
    if len(data):
        p.x_range=data[0].x_range
        p.y_range=data[0].y_range

    p.circle('x', 'y0', size=10, color="navy", alpha=0.5,legend_label='line1', source=source)

    p.triangle('x', 'y1', size=10, color="firebrick", alpha=0.5,legend_label='line2', source=source)

    p.square('x', 'y2', size=10, color="olive", alpha=0.5,legend_label='line3', source=source)
    p.legend.location='top_right'
    p.legend.click_policy = "hide"
    data.append(p)
plot_col=column(data)
# show the results
show(plot_col)

save(plot_col)
1
not getting you but have a look here Maybe this will help you. - ellenkis
How to get around this when using save/show: WARNING:bokeh.embed.util: You are generating standalone HTML/JS output, but trying to use real Python callbacks (i.e. with on_change or on_event). This combination cannot work. Only JavaScript callbacks may be used with standalone output. For more information on JavaScript callbacks with Bokeh, see: docs.bokeh.org/en/latest/docs/user_guide/interaction/… Alternatively, to use real Python callbacks, a Bokeh server application may be used. For more information on building and running Bokeh applications, - azazelspeaks
Basically looking for that but with multiple plots and using a customjs I guess from reading that article - azazelspeaks

1 Answers

0
votes

Interactive (clickable) legends are not coordinate-able across multiple plots. You will have to use a dedicated widget as you suggest.

There is an example of exactly this, for a single plot, in the repo:

https://github.com/bokeh/bokeh/blob/master/examples/plotting/file/line_on_off.py

l0 = p.line(x, np.sin(x), color=Viridis3[0], legend_label="Line 0", **props)
l1 = p.line(x, 4 * np.cos(x), color=Viridis3[1], legend_label="Line 1", **props)
l2 = p.line(x, np.tan(x), color=Viridis3[2], legend_label="Line 2", **props)

checkbox = CheckboxGroup(labels=["Line 0", "Line 1", "Line 2"],
                         active=[0, 1, 2], width=100)
checkbox.callback = CustomJS(args=dict(l0=l0, l1=l1, l2=l2, checkbox=checkbox), code="""
l0.visible = 0 in checkbox.active;
l1.visible = 1 in checkbox.active;
l2.visible = 2 in checkbox.active;
""")

To generalize this you would pass in the additional glyph renderers from each other plot and toggle their visibility in the same manner.