Триггерное отображение подсказок HoverTool через CustomJS в боке - PullRequest
0 голосов
/ 09 июня 2019

В приложении 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))

1 Ответ

0 голосов
/ 10 июня 2019

Назовите 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"))
...