我正在开发一个带有 Bokeh (0.12.2) 的交互式应用程序,它可以根据特定的交互更新绘图。
现在我使用 slider 来更改图形中字形的位置,但实际上我想访问我的鼠标在特定图形中的位置。
数据集是一个多维矩阵(张量),密集的数据,每个图在特定位置显示一个维度。如果我更改标记符号在一个图上的位置,则其他图也需要更新,这意味着我必须根据更新后的位置对数据集进行切片。
这是一个简单的示例,我尝试使用悬停工具在我的 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() 来达到这个目的。不幸的是,它只适用于 TapTool、LassoSelectTool 和 BoxSelectTool,不适用于 HoverTool:
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)
基于我在这里找到的答案:How can I get data from a ColumnDataSource object which is synchronized with local variables of Bokeh's CustomJS function? .此解决方案的问题是我无法使用平移并触发 tool_events 回调。我只能单击 (TapTool) 或平移并仅触发一次回调 (Lasso/BoxSelectTool)。我实际上希望在每次鼠标移动时触发这样的回调..
最佳答案
所以我最近发现您可以为此目的使用自定义模型。这意味着,扩展现有工具,例如GestureTool 但实现/覆盖您自己的功能。您需要运行 Bokeh 服务器(显然)。
$ bokeh serve dir_with_mainfile/
我现在使用的是: 创建文件 MouseMoveTool.py:
from bokeh.models import Tool
class MouseMoveTool(Tool):
# assuming your models are saved in subdirectory models/
with open('models/MouseMoveTool.coffee', 'r') as f:
controls = f.read()
__implementation__ = controls
然后创建 MouseMoveTool.coffee:
p = require "core/properties"
GestureTool = require "models/tools/gestures/gesture_tool"
class MouseMoveToolView extends GestureTool.View
### Override the _pan function ###
_pan: (e) ->
frame = @plot_model.frame
canvas = @plot_view.canvas
vx = canvas.sx_to_vx(e.bokeh.sx)
vy = canvas.sy_to_vy(e.bokeh.sy)
if not frame.contains(vx, vy)
return null
# x and y are your mouse coordinates relative to the axes values
x = frame.x_mappers.default.map_from_target(vx)
y = frame.y_mappers.default.map_from_target(vy)
# update the model's geometry attribute. this will trigger
# the tool_events.on_change('geometries', ..) callback
# in your python code.
@plot_model.plot.tool_events.geometries = [{x:x, y:y}]
class MouseMoveTool extends GestureTool.Model
default_view: MouseMoveToolView
type: "MouseMoveTool"
tool_name: "Mouse Move Tool"
icon: "bk-tool-icon-pan"
event_type: "pan"
default_order: 13
module.exports =
Model: MouseMoveTool
View: MouseMoveToolView
之后,您可以在 main.py 程序中使用您的工具:
from models.MouseMoveTool import MouseMoveTool
p = figure(plot_width=300, plot_height=300, tools=[MouseMoveTool()])
p.tool_events.on_change('geometries', on_mouse_move)
def on_mouse_move(attr, old, new):
print new[0] # will print {x:.., y:..} coordinates
关于javascript - Bokeh 服务器获取鼠标位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39744122/
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru
在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo
有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url
我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge
我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c
我安装了ruby版本管理器,并将RVM安装的ruby实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby。有没有办法让emacs像shell一样尊重ruby的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el
我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b
假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit