本文介绍了使用“散景服务"(散景0.12.0)动态添加/删除地块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题与,但是bokeh服务器的API在0.12.0中已进行了足够的更改,以至于我难以使答案适应新版本.

My question is quite similar to another thread using bokeh 0.7.1, but the API for bokeh servers has changed enough in 0.12.0, that I am struggling to adapt that answer to the new version.

总而言之,我有一个页面,其中包含时间流图的网格,该页面从不断更新的文件中提取数据.该页面具有一个MultiSelect菜单,该菜单列出了我文件中的所有变量.我希望能够在菜单中选择不同的变量,按一个按钮,然后使现有变量的图消失,并由新的时间流代替,新的时间流中图的数量可能会有所不同.我正在使用bokeh serve --show script.py包装器运行脚本.

To summarize, I have a page with a grid of timestream plots pulling data from a file that is continuously updated. The page has a MultiSelect menu that lists all the variables in my file. I want to be able to select different variables in the menu, press a button, and then have the plots of the existing variable disappear and be replaced by the new timestreams, where the number of plots may be different. I am running my script with the bokeh serve --show script.py wrapper.

在我最初的尝试中,我为按钮分配了一个事件处理程序,该按钮清除了"curdoc",然后为MultiSelect中新选择的变量添加了图形.这会运行,但是地块数量不会更新.显然,我错过了告诉服务器以某种方式刷新页面布局的呼叫.

In my initial attempt at this, I assigned an event handler to a button, which clears 'curdoc' and then adds plots for the newly chosen variables from the MultiSelect. This runs, but the number of plots doesn't update. Clearly I am missing the call that tells the server to somehow refresh the page layout.

import numpy as np

from bokeh.driving import count
from bokeh.plotting import figure, curdoc
from bokeh.layouts import gridplot
from bokeh.models import Slider, Column, Row, ColumnDataSource, MultiSelect, Button
from netCDF4 import Dataset
import datetime

# data
#data = Dataset('/daq/spt3g_software/dfmux/bin/output.nc', 'r', format='NETCDF4')
data = Dataset('20160714_warm_overbiased_noise.nc', 'r', format='NETCDF4')
vars = data.variables.keys()[1:11]

# plots
d = {('y_%s'%name):[] for name in vars}
d['t'] = []
source = ColumnDataSource(data=d)

figs = [figure(x_axis_type="datetime", title=name) for name in vars]
plots = [f.line(x='t', y=('y_%s'%f.title.text), source=source, color="navy", line_width=1) for f in figs]
grid = gridplot(figs, ncols=3, plot_width=500, plot_height=250)

# UI definition
npoints = 2000
slider_npoints = Slider(title="# of points", value=npoints, start=1000, end=10000, step=1000.)
detector_select = MultiSelect(title="Timestreams:", value=[], options=vars)
update_detector_button = Button(label="update detectors", button_type="success")

# UI event handlers
def update_detector_handler():
    global figs, plots, grid, source
    d = {('y_%s'%name):[] for name in detector_select.value}
    d['t'] = []
    source = ColumnDataSource(data=d)

    figs = [figure(x_axis_type="datetime", title=name) for name in detector_select.value]
    plots = [f.line(x='t', y=('y_%s'%f.title.text), source=source, color="navy", line_width=1) for f in figs]
    grid = gridplot(figs, ncols=3, plot_width=500, plot_height=250)
    curdoc().clear()
    curdoc().add_root(Column(Row(slider_npoints, Column(detector_select, update_detector_button)), grid))

update_detector_button.on_click(update_detector_handler)

# callback updater
@count()
def update(t):
    data = Dataset('20160714_warm_overbiased_noise.nc', 'r', format='NETCDF4')
    #data = Dataset('/daq/spt3g_software/dfmux/bin/output.nc', 'r', format='NETCDF4')

    npoints = int(slider_npoints.value)
    new_data = {('y_%s'%f.title.text):data[f.title.text][-npoints:] for f in figs}
    new_data['t'] = data['Time'][-npoints:]*1e3

    source.stream(new_data, npoints)

# define HTML layout and behavior
curdoc().add_root(Column(Row(slider_npoints, Column(detector_select, update_detector_button)), grid))
curdoc().add_periodic_callback(update, 500)

推荐答案

在Bokeh Github页面上回答了类似的问题此处.

A similar problem was answered on the Bokeh Github page here.

从本质上讲,您无需修改​​curdoc(),而可以修改布局对象的子级,例如someLayoutHandle.children.

Essentially, instead of messing with curdoc() you instead modify the children of the layout object e.g. someLayoutHandle.children.

一个简单的示例是使用切换按钮添加和删除图形:

A simple example is using a toggle button to add and remove a graph:

from bokeh.client import push_session
from bokeh.layouts import column, row
from bokeh.models import Toggle
from bokeh.plotting import figure, curdoc
import numpy as np
# Create an arbitrary figure
p1 = figure(name = 'plot1')

# Create sin and cos data
x = np.linspace(0, 4*np.pi, 100)
y1 = np.sin(x)
y2 = np.cos(x)

# Create two plots
r1 = p1.circle(x,y1)

# Create the toggle button
toggle = Toggle(label = 'Add Graph',active=False)

mainLayout = column(row(toggle,name='Widgets'),p1,name='mainLayout')
curdoc().add_root(mainLayout)
session = push_session(curdoc())
# Callback which either adds or removes a plot depending on whether the toggle is active
def toggleCallback(attr):
    # Get the layout object added to the documents root
    rootLayout = curdoc().get_model_by_name('mainLayout')
    listOfSubLayouts = rootLayout.children

    # Either add or remove the second graph
    if  toggle.active == False:
        plotToRemove = curdoc().get_model_by_name('plot2')
        listOfSubLayouts.remove(plotToRemove)

    if toggle.active == True:
        if not curdoc().get_model_by_name('plot2'):
            p2 = figure(name='plot2')
            plotToAdd = p2
            p2.line(x,y2)
            # print('Remade plot 2')
        else:
            plotToAdd = curdoc().get_model_by_name('plot2')
        listOfSubLayouts.append(plotToAdd)

# Set the callback for the toggle button
toggle.on_click(toggleCallback)

session.show()
session.loop_until_closed()

给我最大麻烦的部分是要确保我要添加的绘图是curdoc()的一部分,这就是为什么在回调函数中定义的原因.如果它不在回调中,则每次删除plot2时,bokeh后端都找不到它.要检查是否是这种情况,请在回调函数中取消注释print语句.

The part which gave me the most trouble was making sure that the plot I wanted to add was part of curdoc(), which is why the definition is in the callback function. If it is not within the callback, each time plot2 is removed it cannot be found by the bokeh backend. To check that this is the case, uncomment the print statement in the callback function.

我希望这会有所帮助!

这篇关于使用“散景服务"(散景0.12.0)动态添加/删除地块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-06 22:20