草庐IT

javascript - Bokeh 服务器获取鼠标位置

coder 2025-04-01 原文

我正在开发一个带有 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() 来达到这个目的。不幸的是,它只适用于 TapToolLassoSelectToolBoxSelectTool,不适用于 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/

有关javascript - Bokeh 服务器获取鼠标位置的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用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请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的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

  4. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在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

  5. ruby - 简单获取法拉第超时 - 2

    有没有办法在这个简单的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

  6. ruby - 从 Ruby 中的主机名获取 IP 地址 - 2

    我有一个存储主机名的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

  7. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值: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

  8. ruby-on-rails - 获取 inf-ruby 以使用 ruby​​ 版本管理器 (rvm) - 2

    我安装了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

  9. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  10. Ruby 从大范围中获取第 n 个项目 - 2

    假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit

随机推荐