散景从CustomJS获取值(更改数据源中的值)

时间:2019-04-17 14:10:22

标签: javascript python bokeh

我修改了this example。 我最终想要的是一种获取图中选择的数据点并在python代码中修改它们的方法。因此,我在这里添加了一个函数,该函数应该从第二张图返回值(这就是按钮的作用)。但是,如果选择这些点,它们将正确绘制,但是数据源不会更改(单击按钮会提供{'X':[],'Y':[]}。如何从JS写回python bokeh数据源吗?应该不是s2.change.emit()或s2.trigger('change')做这个吗?我也尝试了后者,但没有用。

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 个答案:

答案 0 :(得分:1)

当单击按钮时,此代码将显示第二个绘图中更新的源数据。使用以下命令运行它: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))

您的示例中未更新源数据,因为JS中没有检测推送变化的机制。只能检测到将新对象分配给source.data。一旦检测到更改,就可以同步BokehJS和Python模型之间的数据。