【问题标题】:Bokeh: Why do I need to call the source.change.emit() to update the location of a Span?Bokeh:为什么我需要调用 source.change.emit() 来更新 Span 的位置?
【发布时间】:2021-03-22 08:37:03
【问题描述】:

我想突出显示我悬停的样本。我确实设法通过自定义 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 上运行。

【问题讨论】:

    标签: python bokeh


    【解决方案1】:

    如果您移到行的开头/结尾之外,location 然后line_indices 为空,并且来自line_indices[0] 的设置未定义。在这种情况下,事情会停止更新,因为undefined 不是将location 设置为有效的事情。也许这就是您所看到的?

    此版本的代码更新并保持工具提示和跨度同步,无需使用 Bokeh 2.3 调用 emit(注意:请始终,始终every 问题)

    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

    【讨论】:

    • 非常感谢!我不知道,一旦属性设置为undefined,它就会完全停止更新。在我看来,这是一件非常重要的事情。另外我发现,当尝试将Infinity 的值设置为.location 时,情况似乎也是如此(在我的情况下,有时在回调中使用cb_data['geometry'].x 时会发生这种情况)。
    • 嗯,几乎可以肯定,设置 undefined 是否是可恢复的错误取决于特定属性。但无论如何它都属于“未定义的行为”,因此应该避免。一般来说,Bokeh 模型属性都是严格类型的(参考指南中记录的类型),只有这些类型的值才有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-12
    • 2021-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多