散景:从服务器回调中添加 annotations/glyphs

Bokeh: Add annotations/glyphs from server callback

我正在尝试从服务器回调中添加注释。回调应该在其两侧“包裹”一个带有区域的点击点。

我的代码如下所示:

import numpy as np
from bokeh.models import BoxAnnotation
from bokeh.server.server import Server
from bokeh.plotting import figure


def _app(doc):
    p = figure(tools=['tap'])

    x = np.random.random(size=1000) - .5
    x_cum = np.cumsum(x)
    t = np.arange(len(x))

    s = p.scatter(t, x_cum)

    def handler(attr, old, new):
        print('attr: {} old: {} new: {}'.format(attr, old, new))

        new_layout = []

        for t in new:
            new_layout.append(BoxAnnotation(left=t - 5, right=t + 5, fill_color='green', fill_alpha=.3, level='underlay'))

        p.center = new_layout


    s.data_source.selected.on_change('indices', handler)

    doc.add_root(p)


server = Server({'/': _app}, num_procs=1)
server.start()

if __name__ == '__main__':
    server.io_loop.add_callback(server.show, "/")
    server.io_loop.start()

我也试过 p.add_layout 而不是设置 p.center 但没有。我看到对于 Jupyter notebooks 有一个 push_notebook() 函数可能在这里起作用,所以也许类似的东西可以用于服务器?

您的代码甚至在有机会设置该回调之前就因异常而失败。您应该已经收到 RuntimeError: Columns need to be 1D (y is not) 错误。要修复它,请替换

x = np.random.random(size=(1, 1000)) - .5
x_cum = np.cumsum(x, axis=1)

x = np.random.random(size=(1000,)) - .5
x_cum = np.cumsum(x)

并且一定要使用 add_layout 而不是覆盖整个 center 属性 因为后者会删除那里的其他东西,比如网格线。 请注意,只是一遍又一遍地调用 add_layout 只会添加新注释而不会删除旧注释。如果你想去掉它们,那么你可以直接设置 center 属性,但使用旧值过滤排除所有 BoxAnnotation 个实例。