2016-09-28 15 views
4

私は、特定の相互作用に基づいてプロットを更新するbokeh(0.12.2)を備えた対話型アプリケーションを開発しています。bokehサーバーがマウス位置を取得

今のところ私はスライダを使ってプロット内のグリフの位置を変更しますが、実際には特定のプロット内でマウスの位置にアクセスしたいと考えています。

データセットは多次元マトリックス(テンソル)で密集したデータで、各プロットは特定の場所に1次元を表示します。 1つのプロットでマーカーグリフの位置を変更すると、他のプロットを更新する必要があります。つまり、更新された位置に従ってデータセットをスライスする必要があります。

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コードで変更できるため)。


EDIT:だから私は最近、私は、この目的のために使用することができ、このtool_events.on_change()があることが分かりました。残念ながら、それだけでHoverToolのためではない、BoxSelectToolTapToolLassoSelectToolのために働くん:How can I get data from a ColumnDataSource object which is synchronized with local variables of Bokeh's CustomJS function?

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) 

私はここで見つけるの回答に基づいています。このソリューションの問題点は、パンを使用してtool_eventsコールバックをトリガーできないことです。 (TapTool)をクリックするか、パンしてコールバックを1回だけトリガーすることができます(Lasso/BoxSelectTool)。私は実際にすべてのマウス移動でこのようなコールバックを引き起こしたいと思っています。

答えて

4

私は最近、この目的のためにカスタムモデルを使用できることを知りました。これは、既存のツールを拡張することを意味します。 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を作成します。コーヒー:あなたはmain.pyプログラムで、あなたのツールを使用することができます。その後

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 

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 
関連する問題