Updating ColumnDataSource for multi_line based on Select on_change

I’m having problems updating the ColumnDataSource using an on_change event with a Select widget. Below is the code. If you click on the image, a random line will be added to the multi_line plot. Once you change the value of the Select widget, it should reset the multi_line ColumnDataSource, erasing the plots. But instead they persist, and if you look at the browser console, the xspsin and yspsin still have the same data (so the sspsin doesn’t update properly). Is the mixing of on_change and CustomJS calls not allowed for ColumnDataSource updates?

from bokeh.models import ColumnDataSource, TapTool
from bokeh.plotting import figure, output_file, show
from bokeh.models import CustomJS, TapTool
from bokeh.models.widgets import Select
from bokeh.layouts import row,column
from bokeh.plotting import curdoc
import numpy as np

#output_file(“test_tap_example.html”)

#create data
xsize=ysize=100
x = np.arange(xsize); y= np.arange(ysize)
image_data = np.random.rand(xsize,ysize)
for i in range(ysize): image_data[:,i] *= np.arange(xsize)

#create column data sources
simage = ColumnDataSource(data = dict(psin=,time=[y],image=[image_data.T]))
sspsin = ColumnDataSource(data=dict(xspsin=,yspsin=))

callback = CustomJS(args=dict(sspsin=sspsin),code="""
var xspsin = sspsin.data[‘xspsin’];
var yspsin = sspsin.data[‘yspsin’];
var x = new Array(10);
var y = new Array(10);
for (var iy=0; iy<y.length; iy++){
x[iy] = iy;
y[iy] = Math.random();
}
xspsin.push(x);
yspsin.push(y);
console.log(yspsin);
sspsin.trigger(‘change’);
“”")
taptool = TapTool(callback=callback)

#create tools
p = figure(plot_width=400, plot_height=400,
tools=[taptool,“crosshair”], title=“Click the Dots”,x_range=(0,xsize),y_range=(0,ysize))
p2 = figure(plot_width=400, plot_height=200)

p.image(image=‘image’,source=simage,x=0,y=0,dw=xsize,dh=ysize,palette=‘Spectral9’)
p.rect(x=xsize/2.,y=ysize/2.,width=xsize,height=ysize,alpha=0) #so that taptool responds
p2.multi_line(xs=‘xspsin’,ys=‘yspsin’,source=sspsin)#,color=palette)

for some reason this doesnt update

dropselect = Select(value=“test”,options=[“test”,“test2”])
def dropselect_update(attribute,old,new):
#sspsin.data = dict(xspsin=,yspsin=) #also doesnt work
sspsin.data[‘xspsin’] =
sspsin.data[‘yspsin’] =
print “in dropselect_update”
dropselect.on_change(“value”,dropselect_update)

curdoc().add_root(row(dropselect,p,p2))

``

Some related discussions below I’m coming up with. Seems like the problem is that ColumnDataSource isn’t updated on server and Python-side; I would have to sync before the dropselect_update could work (or just replace with JS callback). If I did try to stay with Python code for dropselect_update, could someone give more details on how this could be done for this case?

https://github.com/bokeh/bokeh/issues/2647

https://groups.google.com/a/continuum.io/forum/#!searchin/bokeh/sync/bokeh/rDixsHESWGc/9zYDwRPcCgAJ

···

On Thursday, February 16, 2017 at 3:29:08 PM UTC-5, [email protected] wrote:

I’m having problems updating the ColumnDataSource using an on_change event with a Select widget. Below is the code. If you click on the image, a random line will be added to the multi_line plot. Once you change the value of the Select widget, it should reset the multi_line ColumnDataSource, erasing the plots. But instead they persist, and if you look at the browser console, the xspsin and yspsin still have the same data (so the sspsin doesn’t update properly). Is the mixing of on_change and CustomJS calls not allowed for ColumnDataSource updates?

from bokeh.models import ColumnDataSource, TapTool
from bokeh.plotting import figure, output_file, show
from bokeh.models import CustomJS, TapTool
from bokeh.models.widgets import Select
from bokeh.layouts import row,column
from bokeh.plotting import curdoc
import numpy as np

#output_file(“test_tap_example.html”)

#create data
xsize=ysize=100
x = np.arange(xsize); y= np.arange(ysize)
image_data = np.random.rand(xsize,ysize)
for i in range(ysize): image_data[:,i] *= np.arange(xsize)

#create column data sources
simage = ColumnDataSource(data = dict(psin=,time=[y],image=[image_data.T]))
sspsin = ColumnDataSource(data=dict(xspsin=,yspsin=))

callback = CustomJS(args=dict(sspsin=sspsin),code="""
var xspsin = sspsin.data[‘xspsin’];
var yspsin = sspsin.data[‘yspsin’];
var x = new Array(10);
var y = new Array(10);
for (var iy=0; iy<y.length; iy++){
x[iy] = iy;
y[iy] = Math.random();
}
xspsin.push(x);
yspsin.push(y);
console.log(yspsin);
sspsin.trigger(‘change’);
“”")
taptool = TapTool(callback=callback)

#create tools
p = figure(plot_width=400, plot_height=400,
tools=[taptool,“crosshair”], title=“Click the Dots”,x_range=(0,xsize),y_range=(0,ysize))
p2 = figure(plot_width=400, plot_height=200)

p.image(image=‘image’,source=simage,x=0,y=0,dw=xsize,dh=ysize,palette=‘Spectral9’)
p.rect(x=xsize/2.,y=ysize/2.,width=xsize,height=ysize,alpha=0) #so that taptool responds
p2.multi_line(xs=‘xspsin’,ys=‘yspsin’,source=sspsin)#,color=palette)

for some reason this doesnt update

dropselect = Select(value=“test”,options=[“test”,“test2”])
def dropselect_update(attribute,old,new):
#sspsin.data = dict(xspsin=,yspsin=) #also doesnt work
sspsin.data[‘xspsin’] =
sspsin.data[‘yspsin’] =
print “in dropselect_update”
dropselect.on_change(“value”,dropselect_update)

curdoc().add_root(row(dropselect,p,p2))

``

Replacing the dropselect_update code with JS callback doesn’t seem to work either:

callbackDrop = CustomJS(args=dict(sspsin=sspsin),code="""
var xspsin = sspsin.data[‘xspsin’];
xspsin = new Array();
var yspsin = sspsin.data[‘yspsin’];
yspsin = new Array();
console.log(yspsin);
sspsin.trigger(‘change’);
“”")
dropselect.js_on_change(‘value’,callbackDrop)

``

···

On Thursday, February 16, 2017 at 4:05:42 PM UTC-5, [email protected] wrote:

Some related discussions below I’m coming up with. Seems like the problem is that ColumnDataSource isn’t updated on server and Python-side; I would have to sync before the dropselect_update could work (or just replace with JS callback). If I did try to stay with Python code for dropselect_update, could someone give more details on how this could be done for this case?

https://github.com/bokeh/bokeh/issues/2647

https://groups.google.com/a/continuum.io/forum/#!searchin/bokeh/sync/bokeh/rDixsHESWGc/9zYDwRPcCgAJ

On Thursday, February 16, 2017 at 3:29:08 PM UTC-5, [email protected] wrote:

I’m having problems updating the ColumnDataSource using an on_change event with a Select widget. Below is the code. If you click on the image, a random line will be added to the multi_line plot. Once you change the value of the Select widget, it should reset the multi_line ColumnDataSource, erasing the plots. But instead they persist, and if you look at the browser console, the xspsin and yspsin still have the same data (so the sspsin doesn’t update properly). Is the mixing of on_change and CustomJS calls not allowed for ColumnDataSource updates?

from bokeh.models import ColumnDataSource, TapTool
from bokeh.plotting import figure, output_file, show
from bokeh.models import CustomJS, TapTool
from bokeh.models.widgets import Select
from bokeh.layouts import row,column
from bokeh.plotting import curdoc
import numpy as np

#output_file(“test_tap_example.html”)

#create data
xsize=ysize=100
x = np.arange(xsize); y= np.arange(ysize)
image_data = np.random.rand(xsize,ysize)
for i in range(ysize): image_data[:,i] *= np.arange(xsize)

#create column data sources
simage = ColumnDataSource(data = dict(psin=,time=[y],image=[image_data.T]))
sspsin = ColumnDataSource(data=dict(xspsin=,yspsin=))

callback = CustomJS(args=dict(sspsin=sspsin),code="""
var xspsin = sspsin.data[‘xspsin’];
var yspsin = sspsin.data[‘yspsin’];
var x = new Array(10);
var y = new Array(10);
for (var iy=0; iy<y.length; iy++){
x[iy] = iy;
y[iy] = Math.random();
}
xspsin.push(x);
yspsin.push(y);
console.log(yspsin);
sspsin.trigger(‘change’);
“”")
taptool = TapTool(callback=callback)

#create tools
p = figure(plot_width=400, plot_height=400,
tools=[taptool,“crosshair”], title=“Click the Dots”,x_range=(0,xsize),y_range=(0,ysize))
p2 = figure(plot_width=400, plot_height=200)

p.image(image=‘image’,source=simage,x=0,y=0,dw=xsize,dh=ysize,palette=‘Spectral9’)
p.rect(x=xsize/2.,y=ysize/2.,width=xsize,height=ysize,alpha=0) #so that taptool responds
p2.multi_line(xs=‘xspsin’,ys=‘yspsin’,source=sspsin)#,color=palette)

for some reason this doesnt update

dropselect = Select(value=“test”,options=[“test”,“test2”])
def dropselect_update(attribute,old,new):
#sspsin.data = dict(xspsin=,yspsin=) #also doesnt work
sspsin.data[‘xspsin’] =
sspsin.data[‘yspsin’] =
print “in dropselect_update”
dropselect.on_change(“value”,dropselect_update)

curdoc().add_root(row(dropselect,p,p2))

``

This works:

dropselect = Select(value=“test”,options=[“test”,“test2”])

dropselect_code = “”"
sspsin.data[‘xspsin’]=;
sspsin.data[‘yspsin’]=;

sspsin.trigger(‘change’)
“”"
dropselect.callback = CustomJS(args=dict(sspsin=sspsin),code=dropselect_code)

``

Excellent! Thanks! From your answer, I thought my issue was not using but instead new Array();. But I tried:
var xspsin = sspsin.data[‘xspsin’];
xspsin = ;
var yspsin = sspsin.data[‘yspsin’];
yspsin = ;
sspsin.trigger(‘change’);

``

And that didn’t work either. Normally this works in other cases. Why does it not work this way?

···

On Saturday, February 18, 2017 at 5:50:34 PM UTC-5, [email protected] wrote:

This works:

dropselect = Select(value=“test”,options=[“test”,“test2”])

dropselect_code = “”"
sspsin.data[‘xspsin’]=;
sspsin.data[‘yspsin’]=;

sspsin.trigger(‘change’)
“”"
dropselect.callback = CustomJS(args=dict(sspsin=sspsin),code=dropselect_code)

``