Bokeh get values from CustomJS (change values in data source)

泄露秘密 提交于 2019-12-11 05:56:44

问题


I have modified this example. What I want- eventually- is a way to get the datapoints selected in a graph and modifiy them in the python code. Thus I added a function here that should return the values from the second graph (thats what the button is for). However, if I select the points, they are plotted correctly, but the data source is not changed (the button click provides {'X':[],'Y':[]}. How do I write back from JS to the python bokeh data source? Isn't the s2.change.emit() or a s2.trigger('change') supposed to do this? I also tried the latter but its not working.

from random import random

from bokeh.layouts import row
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.plotting import figure
from bokeh.models.widgets import Button
from bokeh.io import curdoc


x = [random() for x in range(500)]
y = [random() for y in range(500)]

s1 = ColumnDataSource(data=dict(x=x, y=y))
p1 = figure(plot_width=400, plot_height=400, tools="lasso_select", title="Select Here")
p1.circle('x', 'y', source=s1, alpha=0.6)

s2 = ColumnDataSource(data=dict(x=[], y=[]))
p2 = figure(plot_width=400, plot_height=400, x_range=(0, 1), y_range=(0, 1),
            tools="", title="Watch Here")
p2.circle('x', 'y', source=s2, alpha=0.6)

s1.selected.js_on_change('indices', CustomJS(args=dict(s1=s1, s2=s2), code="""
        var inds = cb_obj.indices;
        var d1 = s1.data;
        var d2 = s2.data;
        d2['x'] = []
        d2['y'] = []
        for (var i = 0; i < inds.length; i++) {
            d2['x'].push(d1['x'][inds[i]])
            d2['y'].push(d1['y'][inds[i]])
        }
        s2.change.emit();
    """)
)
def get_values():
    global s2
    print(s2.data)     

button = Button(label="Get selected set")
button.on_click(get_values)


layout = row(p1, p2,button)
curdoc().add_root(layout)
curdoc().title = "my dashboard"

回答1:


This code will display the updated source data from the second plot when the button is clicked. Run it with: bokeh serve --show app.py

from random import random
from bokeh.models import CustomJS, ColumnDataSource, Row
from bokeh.plotting import figure, show, curdoc
from bokeh.models.widgets import Button

x = [random() for x in range(500)]
y = [random() for y in range(500)]

s1 = ColumnDataSource(data = dict(x = x, y = y))
p1 = figure(plot_width = 400, plot_height = 400, tools = "lasso_select", title = "Select Here")
p1.circle('x', 'y', source = s1, alpha = 0.6)

s2 = ColumnDataSource(data = dict(x = [], y = []))
p2 = figure(plot_width = 400, plot_height = 400, x_range = (0, 1), y_range = (0, 1), tools = "", title = "Watch Here")
p2.circle('x', 'y', source = s2, alpha = 0.6)

s1.selected.js_on_change('indices', CustomJS(args = dict(s1 = s1, s2 = s2), code = """
        var inds = cb_obj.indices;
        var d1 = s1.data;
        d2 = {'x': [], 'y': []}
        for (var i = 0; i < inds.length; i++) {
            d2['x'].push(d1['x'][inds[i]])
            d2['y'].push(d1['y'][inds[i]])
        }
        s2.data = d2  """))

def get_values():
    print(s2.data)

button = Button(label = "Get selected set")
button.on_click(get_values)

curdoc().add_root(Row(p1, p2, button))

The source data is not updated in your example because there is no mechanism in JS to detect the push changes. Only assigning a new object to source.data can be detected. Once the change is detected the data between BokehJS and Python models can be synchronised.



来源:https://stackoverflow.com/questions/55729552/bokeh-get-values-from-customjs-change-values-in-data-source

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!