Amir
Amir

Reputation: 441

creating interactive bokeh plot + using for loop to multiple line plot

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. enter image description here

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:

enter image description here

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: enter image description here

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

Answers (1)

bigreddot
bigreddot

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

Related Questions