Bokeh получить значения из CustomJS (изменить значения в источнике данных) - PullRequest
0 голосов
/ 17 апреля 2019

Я изменил этот пример . То, что я хочу - в конечном итоге - это способ выбрать точки данных, выбранные на графике, и изменить их в коде 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 Ответ

1 голос
/ 18 апреля 2019

Этот код будет отображать обновленные исходные данные со второго графика при нажатии кнопки. Запустите его с: 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 нет механизма для обнаружения push-изменений. Обнаружить можно только присвоение нового объекта source.data. Как только изменение обнаружено, данные между моделями BokehJS и Python могут быть синхронизированы.

...