我正在将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回调中。
答案 0 :(得分:1)
在此代码中,如果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)
结果: