Bokeh:为什么我需要调用 source.change.emit() 来更新 Span 的位置?

Bokeh: Why do I need to call the source.change.emit() to update the location of a Span?

我想突出显示我悬停的样本。我确实设法通过自定义 JSCallback 解决了这个问题。请参阅下面的最小工作示例。
我的问题是,为什么我需要调用 source.change.emit() 来更新我的 Span 的位置?如果我在回调中删除 source.change.emit() ,则水平线的位置根本不会改变(视觉上)。到目前为止,我认为,如果我实际更改源对象中的数据(如 source.data['Value1'] = <new_value>.

,我只需要调用此命令
import pandas as pd
from bokeh.plotting import figure, curdoc
from bokeh.models import ColumnDataSource, HoverTool, CustomJS, Span
from bokeh.layouts import layout

plot1 = figure(plot_width=1000, plot_height=250)

df = pd.DataFrame({"ID":[0, 1, 2, 3, 4, 5, 6, 7], 
                   "Value1":[0, 100, 200, 300, 400, 500, 600, 700], 
                   "Value2":[0, 1, 2, 4,8 , 16, 32, 64]})
source = ColumnDataSource(df)

line = plot1.line(x='ID', y='Value1', source=source)
circle = plot1.circle(x='ID', y='Value1', source=source)

v_line = Span(location=2,  dimension='height', line_color='green',
                              line_dash='dashed', line_width=3)
plot1.add_layout(v_line)

callback = CustomJS(args=dict(source=source, v_line=v_line), 
                        code="""
                        v_line.location = cb_data['index'].line_indices[0];
                        source.change.emit();
                        """)

hover_tool_plot = HoverTool(mode='vline', line_policy='nearest', callback=callback, renderers=[line])

plot1.add_tools(hover_tool_plot)

layout_ = layout([[plot1]])
curdoc().add_root(layout_)

在我的应用程序中,我处理具有相同源对象的多个绘图中的大量数据。因此,当我在回调中包含 source.change.emit() 部分时,Span 位置会发生变化,但视觉悬停注释会明显变慢,并且由于这种不平滑性还会跳过一些样本。有没有办法在不调用 source.change.emit() 的情况下更新 Span 的位置?
提前致谢。

编辑:
我 运行 使用 Bokeh 2.3.0。

如果移到行的begin/end之外,location然后line_indices为空,line_indices[0]的设置未定义。在这种情况下,事情会停止更新,因为 undefined 不是设置 location 的有效对象。也许这就是您所看到的?

此版本的代码更新并保持工具提示和跨度同步,无需 emit 调用 Bokeh 2.3(注意:请始终,始终 指定相关软件每个个问题中的版本)

callback = CustomJS(args=dict(source=source, v_line=v_line),
                        code="""
                        const loc = cb_data['index'].line_indices[0]
                        if (loc === undefined) {
                             v_line.visible = false
                        } else {
                            v_line.visible = true
                            v_line.location = loc;
                        }
                        """)

hover_tool_plot = HoverTool(mode='vline', line_policy='prev', 
                            callback=callback, renderers=[line])

请注意,我还将 line_policy 更改为 prev,因为我相信 line_indices 无论如何都会报告。这可能会变得更加灵活,但以前没有人问过这个问题。欢迎提出功能请求 on github.