2016-06-25 1 views
1

Мне нужен курсор, который связан между участками в Bokeh. Поэтому, если я перемещаю курсор на один график, эквивалентная строка появляется на соседнем участке. Я не понял, как это сделать со встроенным инструментом курсора. Поэтому мое текущее решение состоит в том, чтобы нарисовать линию на каждом сюжете, который имеет источник. Затем, когда я наводил курсор на любой сюжет, источник обновляется.Ссылка на пробел или курсор между графиками с Bokeh в Python

У меня есть 2 проблемы с этим методом: 1. Похоже на обходное решение 2. В настоящее время линии имеют конечную длину. Я бы хотел, чтобы линия была бесконечной, поэтому независимо от того, как изменяется размер графика, линия проходит от края. В настоящее время линия, которую я рисую, является конечной. Правильный способ рисования бесконечной горизонтальной линии - аннотация «Span», но мне сложно определить, как передать/обновить местоположение Span через мой обратный вызов. См. Мой код ниже.

from bokeh.io import gridplot, show, output_notebook, output_file 
from bokeh.plotting import figure 
from bokeh.models import HoverTool, ColumnDataSource, CustomJS, Span 


output_notebook() 

x = list(range(11)) 
y1 = x 
y2 = [10 - i for i in x] 


source = ColumnDataSource({'x0': [0], 'y0': [2], 'x1': [10], 'y1': [2]}) 

# create a new plot 
s1 = figure(width=250, plot_height=250, tools="", title=None) 
cr1 = s1.circle(x, y1, size=10, color="navy", alpha=0.5) 
sr1 = s1.segment(x0='x0', y0='y0', x1='x1', y1='y1', color='red', alpha=1, line_width=1, source=source,) 
sp1 = Span(location=source.data['y0'][0], dimension='width', line_color='green') 
s1.renderers.extend([sp1,]) 

# create another one 
s2 = figure(width=250, height=250, title=None) 
cr2 = s2.triangle(x, y1, size=10, color="firebrick", alpha=0.5) 
sr2 = s2.segment(x0='x0', y0='y0', x1='x1', y1='y1', color='red', alpha=1, line_width=1, source=source,) 

# put all the plots in an HBox 
p = gridplot([[s1,s2],[]]) 

code = """ 
var data = {'x0': [], 'y0': [], 'x1': [], 'y1': []}; 
var cdata = circle.get('data'); 
var indices = cb_data.index['1d'].indices; 

for (i=0; i < indices.length; i++) { 
    ind0 = indices[i]; 
     data['x0'].push(0); 
     data['y0'].push(cdata.y[ind0]); 
     data['x1'].push(10); 
     data['y1'].push(cdata.y[ind0]); 

} 
segment.set('data', data); 
""" 


callback1 = CustomJS(args={'circle': cr1.data_source, 'segment': sr2.data_source}, code=code) 
s1.add_tools(HoverTool(tooltips=None, callback=callback1, renderers=[cr1])) 

callback2 = CustomJS(args={'circle': cr2.data_source, 'segment': sr2.data_source}, code=code) 
s2.add_tools(HoverTool(tooltips=None, callback=callback2, renderers=[cr2])) 


# show the results 
show(p) 
+1

Вы хотите 'Span', который является строкой, которая всегда охватывает все измерения независимо от диапазона данных. Вы настраиваете его свойство 'dimenions' для установки направления' vertical' или 'horizontal', а затем вы устанавливаете одно числовое значение для' location' (которое вы могли бы обновить, например, из 'CustomJS'). Он также имеет возможность для режима рендеринга CSS, который во многих случаях будет намного более результативным. – bigreddot

+0

Спасибо @bigreddot. Это был намек, который мне нужен. Я опубликовал код функционирования. – mcragun

ответ

1

Благодаря @bigreddot для его ответа на пролеты. Я попытался и не получил работу, но понял это своими намеками. Рабочий код приведен ниже. Я реализовал диапазон в каждом сюжете, а затем редактировал местоположение каждого.

from bokeh.io import gridplot, show, output_notebook, output_file 
from bokeh.plotting import figure 
from bokeh.models import HoverTool, ColumnDataSource, CustomJS, Span 

output_file('Test.html') 

#output_notebook() 

x = list(range(11)) 
y1 = x 
y2 = [10 - i for i in x] 

# create a new plot 
s1 = figure(width=250, plot_height=250, tools="", title=None) 
cr1 = s1.circle(x, y1, size=10, color="navy", alpha=0.5) 
sp1 = Span(location=source.data['y0'][0], dimension='width', line_color='green', render_mode='css') 
s1.renderers.extend([sp1,]) 

# create another one 
s2 = figure(width=250, height=250, title=None) 
cr2 = s2.triangle(x, y1, size=10, color="firebrick", alpha=0.5) 
sp2 = Span(location=source.data['y0'][0], dimension='width', line_color='green', render_mode='css') 
s2.renderers.extend([sp2,]) 

# put all the plots in an HBox 
p = gridplot([[s1,s2],[]]) 

code = """ 
var cdata = circle.get('data'); 
var indices = cb_data.index['1d'].indices; 

var sum = 0; 

for (i=0; i < indices.length; i++) { 
    sum += cdata.y[indices[i]]; 
} 

var avg = sum/indices.length 
span1.set('location', [avg]) 
span2.set('location', [avg]) 
""" 

callback1 = CustomJS(args={'circle': cr1.data_source, 'span1': sp1, 'span2': sp2}, code=code) 
s1.add_tools(HoverTool(tooltips=None, callback=callback1, renderers=[cr1])) 

callback2 = CustomJS(args={'circle': cr2.data_source, 'span1': sp1, 'span2': sp2}, code=code) 
s2.add_tools(HoverTool(tooltips=None, callback=callback2, renderers=[cr2])) 

# show the results 
show(p)