我正在使用bokeh(版本号为0.12.2)开发一个交互式应用程序,该程序根据特定的交互来更新绘图。
目前,我使用滑块来改变图中glyph的位置,但实际上我想访问特定图中鼠标的位置。
数据集是一个多维矩阵(张量),包含密集的数据,每个图在特定位置显示一种维度。如果我在一个图中改变标记glyph的位置,则需要更新其他图,这意味着我必须根据更新的位置切片我的数据集。
这是我尝试使用悬停工具在bokeh服务器更新函数中获取鼠标数据的简单示例:
目前,我使用滑块来改变图中glyph的位置,但实际上我想访问特定图中鼠标的位置。
数据集是一个多维矩阵(张量),包含密集的数据,每个图在特定位置显示一种维度。如果我在一个图中改变标记glyph的位置,则需要更新其他图,这意味着我必须根据更新的位置切片我的数据集。
这是我尝试使用悬停工具在bokeh服务器更新函数中获取鼠标数据的简单示例:
from bokeh.plotting import figure, ColumnDataSource
from bokeh.models import CustomJS, HoverTool
from bokeh.io import curdoc
s = ColumnDataSource(data=dict(x=[0, 1], y=[0, 1]))
callback = CustomJS(args=dict(s=s), code="""
var geometry = cb_data['geometry'];
var mouse_x = geometry.x;
var mouse_y = geometry.y;
var x = s.get('data')['x'];
var y = s.get('data')['y'];
x[0] = mouse_x;
y[0] = mouse_y;
s.trigger('change');
""")
hover_tool = HoverTool(callback=callback)
p = figure(x_range=(0, 1), y_range=(0, 1), tools=[hover_tool])
p.circle(x='x', y='y', source=s)
def update():
print s.data
curdoc().add_root(p)
curdoc().add_periodic_callback(update, 1000)
很不幸,服务器只会输出:
{'y': [0, 1], 'x': [0, 1]}
{'y': [0, 1], 'x': [0, 1]}
{'y': [0, 1], 'x': [0, 1]}
{'y': [0, 1], 'x': [0, 1]}
有没有办法访问鼠标位置(在Python代码中)?即使访问字形的位置也足够了(因为我可以使用一些Javascript代码更改字形的位置)。
编辑:最近我发现有这个tool_events.on_change()工具,我可以用它来实现此目的。但对于HoverTool无效,只能用于TapTool、LassoSelectTool和BoxSelectTool:
from bokeh.plotting import figure
from bokeh.io import curdoc
from bokeh.models.tools import BoxSelectTool, TapTool, HoverTool, LassoSelectTool
from bokeh.models.ranges import Range1d
TOOLS = [TapTool(), LassoSelectTool(), BoxSelectTool(), HoverTool()]
p = figure(tools=TOOLS,
x_range=Range1d(start=0.0, end=10.0),
y_range=Range1d(start=0.0, end=10.0))
def tool_events_callback(attr, old, new):
print attr, 'callback', new
p.tool_events.on_change('geometries', tool_events_callback)
curdoc().add_root(p)
根据我在此处找到的答案:如何从与Bokeh的CustomJS函数的本地变量同步的ColumnDataSource对象中获取数据?。这种解决方案的问题是我不能使用pan并触发tool_events回调。我只能单击(TapTool)或者只能拖动并触发一次回调(Lasso/BoxSelectTool)。实际上,我希望在每次鼠标移动时都能触发这样的回调。