Reputation: 441
I am using this code to create a simple plot:
from ipywidgets import interact
import numpy as np
from bokeh.io import push_notebook, show, output_notebook
from bokeh.plotting import figure
output_notebook()
x = np.linspace(0, 2*np.pi, 2000)
y = np.sin(x)
p = figure(title="simple line example", plot_height=300, plot_width=600, y_range=(-5,5),
background_fill_color='#efefef')
show(p)
By running this code a plot with multiple line will be created succesfully as expected.
My goal was to bring the interactivity of bokeh to this plot by using this code:
r1=p.line(x, y)
def update(f, w=1, A=1, phi=0):
if f == "sin": func = np.sin
elif f == "cos": func = np.cos
for k in range(1,4):
r1=p.line(x, y)
r1.data_source.data['y'] = A * func(w * k*x + phi)
push_notebook()
And show and update the plot using this code:
show(p, notebook_handle=True)
interact(update, f=["sin", "cos"], w=(0,50), A=(1,10), phi=(0, 20, 0.1))
Once I run the code above I get this reult:
I was expecting by changing the variables like phi, A etc the whole plot including 4 lines would be updated. But what I get when I for e.g. change sin to cos, looks like this:
This means the plot dioesnt really "update" but overdraw the new data on the old plot. What am I missing here? And I want stay with the loop.
Upvotes: 0
Views: 1211
Reputation: 34568
What am I missing here?
Two things:
push_notebook
is specifically for making incremental updates to an existing plot, without replacing anything that is there
every call to p.line
adds a new line to a plot.
If you want to have just a fixed set of lines that update in response to widgets, then your callback should not call p.line
at all. You should set up the lines you want, once, up front. Then in the callback, only update the data sources for those lines, before calling push_notebook
to update the JavaScript side.
Also BTW the best practice for updating a data source is assigning to the .data
property to update everything all at once, e.g.
source.data = new_data_dict
Upvotes: 1