I have a Python Bokeh plot containing multiple lines, Is there a way I can interactively switch some of these lines on and off?
p1.line(Time,Temp0,size=12,color=getcolor())
p1.line(Time,Temp1,size=12,color=getcolor())
p1.line(Time,Temp2,size=12,color=getcolor())
p1.line(Time,Temp3,size=12,color=getcolor())
....
show(p1)
I just came across this problem myself in a similar scenario. In my case, I also wanted to do other operations on it.
There are 2 possible approaches:
1.) Client-server approach
2.) Client only approach
1.) Client Server Approach ak Bokeh Server
One way how you can achieve this interactivity is by using the bokeh server which you can read more about here. I will describe this way in more detail since at this point, I am a bit more familiar with it.
Going by your example above, if I were to use the bokeh serve, I would first setup a ColumnDataSource like so:
source = ColumnDataSource(data = dict(
time = Time,
temp0 = [],
temp1 = [],
temp2 = [],
temp3 = [],
)
Next I would setup a widget that allows you to toggle what temperatures to show:
multi_select = MultiSelect(title="Option:", value=["Temp1"],
options=["Temp1", "Temp2", "Temp3"])
# Add an event listener on the python side.
multi_select.on_change('value', lambda attr, old, new: update())
Then I would define the update function like below. The purpose of the update function is to update the ColumnDataSource (which was previously empty) with values you want to populate in the graph now.
def update():
"""This function will syncronize the server data object with
your browser data object. """
# Here I retrieve the value of selected elements from multi-select
selection_options = multi_select.options
selections = multi_select.value
for option in selection_options:
if option not in selections:
source.data[option] = []
else:
# I am assuming your temperatures are in a dataframe.
source.data[option] = df[option]
The last thing to do is to redefine how you plot your glyphs. Instead of drawing from lists, or dataframes, we will draw our data from a ColumnDataSource like so:
p1.line("time","temp0", source=source, size=12,color=getcolor())
p1.line("time","temp1", source=source, size=12,color=getcolor())
p1.line("time","temp2", source=source, size=12,color=getcolor())
p1.line(Time,Temp3, source=source, size=12,color=getcolor())
So basically by controlling the content of the ColumnDataSource which is synchronized with the browser object, I can toggle whether data points are shown or not. You may or may not need to define multiple ColumnDataSources. Try it out this way first.
2.) Client only approach ak Callbacks
The approach above uses a client-server architecture. Another possible approach would be to do this all on the front-end. This link shows how some simple interactions can be done completely on the browser side via various forms of callbacks.
Anyway, I hope this is helpful. Cheers!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With