在bokeh应用程序中,我想重用HoverTool创建的工具提示的呈现。
尤其是,我想通过某种方式在数据源中选择一个数据点,然后显示该点的更多信息。例如,可以从滑块进行选择。 我可以添加一个自制标签(请参见代码示例),但是如果可以显示由HoverTool生成的工具提示,那将更好,因为它们已经被很好地格式化了。
示例代码显示了一个滑块,该滑块选择一个数据点并设置一个自定义标签。我想避免使用自定义标签,而是以某种方式触发悬停工具提示。
from bokeh.io import show
from bokeh.layouts import column
from bokeh.models import HoverTool, ColumnDataSource, Slider, CustomJS, LabelSet
from bokeh.plotting import figure
import numpy as np
x = np.linspace(0,1)
y = np.linspace(0,2)
ds = ColumnDataSource(data=dict(x=x,y=y))
fig = figure()
fig.scatter(x='x', y='y', source=ds)
# a datasource to show labels at a x/y position, set in the JS callback
labels = ColumnDataSource(data=dict(x=[], y=[], t=[], ind=[]))
fig.add_layout(LabelSet(x='x', y='y', text='t', source=labels))
# slider that selects a datapoint and creates the label for the point
slider = Slider(start=0, end=len(x), value=0, step=1)
code = """
labels.data = {'x':[],'y':[],'t':[]}
source.selected.indices = [slider.value]
labels.data = {'ind':[slider.value],
'x':[source.data.x[slider.value]],
'y':[source.data.y[slider.value]],
't':[source.data.x[slider.value]]}
labels.change.emit()
source.change.emit()
"""
callback = CustomJS(args=dict(source=ds, slider=slider, labels=labels), code=code)
slider.js_on_change('value', callback)
# hover to show default tooltips, can those be triggered?
hover = HoverTool(mode='vline')
fig.add_tools(hover)
show(column(slider, fig))
答案 0 :(得分:0)
调用HoverToolView._inspect(x, y)
,其中(x,y)是该点的画布坐标。我们需要使用xscale.compute()
和yscale.compute()
将数据坐标转换为画布坐标。
import numpy as np
from bokeh.plotting import figure, show, output_notebook
from bokeh.models import Slider, HoverTool, CustomJS, ColumnDataSource
from bokeh.layouts import column
output_notebook()
N = 100
x = np.random.random(size=N) * 100
y = np.random.random(size=N) * 100
radii = np.random.random(size=N) * 1.5
colors = [
"#%02x%02x%02x" % (int(r), int(g), 150) for r, g in zip(50+2*x, 30+2*y)
]
TOOLS="hover,crosshair,pan,wheel_zoom,zoom_in,zoom_out,box_zoom,undo,redo,reset,tap,save,box_select,poly_select,lasso_select,"
p = figure(tools=TOOLS)
source = ColumnDataSource(dict(x=x, y=y, radius=radii, colors=colors))
renderer = p.scatter("x", "y", radius="radius",
fill_color="colors", fill_alpha=0.6,
line_color=None, source=source)
slider = Slider(start=0, end=len(x), value=0, step=1)
code = """
let ind = slider.value;
let x = source.data.x[ind];
let y = source.data.y[ind];
let fig_view = Bokeh.index["myplot"].child_views[1];
let hover_view = fig_view.tool_views[hovertool.id];
let renderer_view = fig_view.renderer_views[renderer.id];
let xs = renderer_view.xscale.compute(x);
let ys = renderer_view.yscale.compute(y);
hover_view._inspect(xs, ys);
"""
callback = CustomJS(args=dict(
fig=p,
slider=slider,
hovertool=p.select_one(HoverTool),
source=source,
renderer=renderer
), code=code)
slider.js_on_change('value', callback)
show(column(slider, p, id="myplot"))