Мне нужен курсор, который связан между участками в 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)
Вы хотите 'Span', который является строкой, которая всегда охватывает все измерения независимо от диапазона данных. Вы настраиваете его свойство 'dimenions' для установки направления' vertical' или 'horizontal', а затем вы устанавливаете одно числовое значение для' location' (которое вы могли бы обновить, например, из 'CustomJS'). Он также имеет возможность для режима рендеринга CSS, который во многих случаях будет намного более результативным. – bigreddot
Спасибо @bigreddot. Это был намек, который мне нужен. Я опубликовал код функционирования. – mcragun