Есть ли способ использовать MultiSelect в Bokeh для выбора канала потоковой передачи данных? - PullRequest
1 голос
/ 12 апреля 2019

Я собираю сервер Bokeh для сбора нескольких потоков данных и предоставляю прямую диаграмму любого канала, который пользователь выбирает в меню MultiSelect. У меня работает потоковый бит, но я не уверен, как выбрать, какой поток будет отображаться на рисунке, который я добавил в макет.

Я пытался использовать curdoc (). Remove_root (), чтобы удалить текущий макет, а затем добавить новый, но это просто убивает приложение, и новый макет не отображается. Я также пытался просто обновить фигуру, но это также просто убивает приложение.

from bokeh.layouts import column
from bokeh.plotting import figure,curdoc
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import MultiSelect

def change_plot(attr,old,new):
    global model,selector,p,source
    curdoc().remove_root(mode)
    p = figure()
    p.circle(x=new+'_x',y=new+'_y',source=source)
    model = column(selector,p)
    curdoc().add_root(model)

def update_plot():
    newdata = {}
    for i in range(10):
        # the following two lines would nominally provide real data
        newdata[str(i)+'_x'] = 1
        newdata[str(i)+'_y'] = 1
    source.stream(newdata,100)

selector = MultiSelect(title='Options',value=[str(i) for i in range(10)])
selector.on_change('value',change_plot)

data = {}
for i in range(10):
    data[str(i)+'_x'] = 0
    data[str(i)+'_y'] = 0
source = ColumnDataSource(data=data)

p = figure()
p.circle(x='0_x',y='0_y',source=source)
curdoc().add_root(model)
curdoc().add_periodic_callback(update_plot,100)

Я запускаю этот код, используя bokeh serve --show app.py, и я ожидал, что он будет создавать новый график каждый раз при обновлении MultiSelect, но вместо этого он просто падает где-то в обратном вызове change_plot.

1 Ответ

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

В этом коде выбор строки в MultiSelect добавляет новую строку, если ее нет на холсте, и начинает потоковую передачу или просто переключает потоковую передачу, если строка уже была на холсте.Код работает для Bokeh v1.0.4.Запуск с bokeh serve --show app.py

from bokeh.models import ColumnDataSource, MultiSelect, Column
from bokeh.plotting import figure, curdoc
from datetime import datetime
from random import randint
from bokeh.palettes import Category10

lines = ['line_{}'.format(i) for i in range(10)]
data = [{'time':[], item:[]} for item in lines]
sources = [ColumnDataSource(item) for item in data]

plot = figure(plot_width = 1200, x_axis_type = 'datetime')

def add_line(attr, old, new):
    for line in new:
        if not plot.select_one({"name": line}):
            index = lines.index(line)
            plot.line(x = 'time', y = line, color = Category10[10][index], name = line, source = sources[index])

multiselect = MultiSelect(title = 'Options', options = [(i, i) for i in lines], value = [''])
multiselect.on_change('value', add_line)

def update():
    for line in lines:
        if line in multiselect.value:
            if plot.select({"name": line}):
                sources[lines.index(line)].stream(eval('dict(time = [datetime.now()], ' + line + ' = [randint(5, 10)])'))

curdoc().add_root(Column(plot, multiselect))
curdoc().add_periodic_callback(update, 1000)

Результат:

enter image description here

...