I am trying to create a plot using bokeh to visualize my data on IPython Notebook. I want to add some widgets to make it more interactive. Below is an example of the codes.
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.plotting import Figure, output_notebook, show
from bokeh.models.widgets import Select
from bokeh.layouts import column
output_notebook()
x = [x*0.005 for x in range(0, 200)]
y = x
z = ['A' if i>50 else 'B' for i in range(len(x))]
source = ColumnDataSource(data=dict(x=x, y=y, z=z))
plot = Figure(plot_width=400, plot_height=400)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)
def callback(source=source):
data=source.get('data')
f = cb_obj.get('value')
x, y, z = data['x'], data['y'], data['z']
x = [x[i] for i in range(len(x)) if z[i] == f]
y = [y[i] for i in range(len(y)) if z[i] == f]
z = [z[i] for i in range(len(z)) if z[i] == f]
source.trigger('change')
slides = Select(title="Option:", value = 'A', options=['A', 'B'],
callback=CustomJS.from_py_func(callback))
layout = column(slider,plot)
show(layout)
I want to make it such that if I choose other option, the plot will change accordingly based on the criteria I specify in the callback function. Any suggestion on why the codes do not work?
P.S. I used the codes from here, but I change the widgets because the problem I am facing is similar to the above http://docs.bokeh.org/en/0.11.1/docs/user_guide/interaction.html#customjs-with-a-python-function
The issue is you are not actually changing the contents of data['x'], data['y'] or data['z'].
Second issue is, if you change the source data, then you cant change it back as it no longer contains the full data you begun with. Work around is passing in the original data to the callback, and assigning the filtered data to the ColumnDataSource, without changing the original data.
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.plotting import Figure, output_notebook, show
from bokeh.models.widgets import Select
from bokeh.layouts import column
output_notebook()
x = [x*0.005 for x in range(0, 200)]
y = x
z = ['A' if i>50 else 'B' for i in range(len(x))]
original_source = ColumnDataSource(data=dict(x=x, y=y, z=z))
source = ColumnDataSource(data=dict(x=x, y=y, z=z))
plot = Figure(plot_width=400, plot_height=400)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)
def callback(source=source, original_source = original_source):
data=original_source.data
s_data = source.data
f = cb_obj.value
x, y, z = data['x'], data['y'], data['z']
x = [x[i] for i in range(len(x)) if z[i] == f]
y = [y[i] for i in range(len(y)) if z[i] == f]
z = [z[i] for i in range(len(z)) if z[i] == f]
s_data['x'] = x
s_data['y'] = y
s_data['z'] = z
source.trigger('change')
slides = Select(title="Option:", value = 'A', options=['A', 'B'],
callback=CustomJS.from_py_func(callback))
layout = column(slides,plot)
show(layout)