【问题标题】:Bokeh Taptool return selected indexBokeh Taptool 返回选定的索引
【发布时间】:2018-05-23 00:30:07
【问题描述】:

我需要在散景图中获取选定数据点的索引,这需要作为我的 Web 应用程序中另一个函数的输入。

我正在使用 Bokeh 的 Taptool CustomJS 回调。但是,除了“console.log”之外,我找不到获取所选点的实际索引的方法。有没有办法将此索引返回到 JavaScript 之外?

下面是我的代码。我是 Javascript 和 Bokeh 的新手。感谢您提前提供任何帮助。

codes = """
    var index_selected = source.selected['1d']['indices'][0];
    source.trigger('change');

    console.log(index_selected);
    """
taptool.callback = CustomJS(args=dict(source=source),code = codes)

【问题讨论】:

  • 你想对索引做什么?一般来说,一旦你到达 Bokeh 的 javascript 界面,它就会被设计为停留在那里。如果您需要将值返回给 Python,那么您还需要从运行 Python 的服务器运行 Bokeh。另外,您使用的是什么版本的 Bokeh? source.trigger('change') 已弃用,您应该使用 source.change.emit()
  • 您是在询问将索引返回到 Python 的问题吗?如果是这样,您将必须运行 Bokeh 服务器应用程序。当您制作独立的 Bokeh 输出时,它会生成未连接到任何 Python 进程的静态 HTML 和 JS 代码。
  • 很明显,如果你想在 python 中得到答案,你需要运行一个散景服务器,但这并没有提供任何关于如何做到这一点的线索。

标签: javascript python bokeh


【解决方案1】:

这适用于 multi_line:

selected_src = ColumnDataSource(dict(indices=[])

def handle_selection_change(_attr, # should be 'data'
                            old_indices, 
                            new_indices):
   ...

selected_src.on_change('data', handle_selection_change)

taptool.callback = CustomJS(
    args=dict(source=source, selected=selected_src),
    code = """
       selected.data = { "indices" : source.selected.indices };
    """)

【讨论】:

  • 无法让它工作。不知道handle_selection_change 应该做什么(用pass 填充函数),但selected_src 似乎总是空的。
  • handle_selection_change 会根据行选择的变化做任何你需要的事情。在我的代码中,我使用new_indices['indices'I 根据选定的行更新另一个控件。我看到我的代码实际上有类似{"indices" : source.selected.indices } 的东西,所以我可能已经把它写下来了。看看能不能解决。
  • {"indices" : source.selected.indices } 确实修复了它。
  • 我相应地修改了我的答案。
【解决方案2】:

以下示例绘制了两个三角形。通过点击一个三角形,相应的索引被打印出来。该示例虽然没有使用 CustomJS。

from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.io import curdoc

def my_tap_handler(attr,old,new):
    index = source.selected.indices
    print(index)

source = ColumnDataSource(data=dict(
    x=[[1,2,3],[7,8,8,]],
    y=[[2,1,3],[6,8,7]]
))
p = figure(tools="tap")

renderer = p.patches('x', 'y', source=source)
renderer.data_source.on_change("selected", my_tap_handler)
curdoc().add_root(p)

【讨论】:

  • 这可能适用于补丁(我没有尝试),但它似乎不适用于 multi_line