与段字形关联时,悬停工具不显示工具提示
Hover tool does not display tooltip when associated with segment glyphs
我检查了很多类似问题的答案,但 none 是相关的。对我来说,悬停工具已启用,但无论我放大多远以将项目与所有其他项目隔离(无重叠),工具提示都不会显示。现在我在另一个使用段字形但 line_width=12 (x) 的应用程序上工作,并且随着段的高度放大 (y) 并最终显示工具提示。在它不起作用的地方,line_width=1(大量数据),该线段是一条水平线(y0、y1 的 y 值相同)。我认为这可能与 line_width 太小有关。但即使它的值设置得非常大 (20) 并放大并消除所有重叠,也不会显示任何工具提示。
这是我的测试代码:
from bokeh.io import output_file
from bokeh.models.ranges import Range1d
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure, show
from bokeh.models.tools import HoverTool
import random
def build_test_data(dataSeries2gen, count2gen, series2gen):
# test data
vectorSeries = []
if dataSeries2gen == "horizontal":
# gen random seed numbers for X and Y but always use same Y
for nSeries in range(0, series2gen):
sameY = [random.randint(1, 4000) for y in range(4000)]
randX1 = [random.randint(1, 51200) for x in range(51200)]
randX2 = [random.randint(1, 51200) for x in range(51200)]
nextSeries = []
for nextSeed in range(1, count2gen):
yIdx = random.randint(1, 3999)
xIdx = random.randint(1, 51999)
nextSegment = [randX1[xIdx], sameY[yIdx],\
randX2[xIdx], sameY[yIdx]]
nextSeries.append(nextSegment)
vectorSeries.append(nextSeries)
else:
for nSeries in range(0, series2gen):
randY1 = [random.randint(1, 4000) for y in range(4000)]
randY2 = [random.randint(1, 4000) for y in range(4000)]
randX1 = [random.randint(1, 51200) for x in range(51200)]
randX2 = [random.randint(1, 51200) for x in range(51200)]
nextSeries = []
for nextSeed in range(1, count2gen):
nextSegment = [randX1[nextSeed], randY1[nextSeed],\
[randX2[nextSeed], randY2[nextSeed]]
nextSeries.append(nextSegment)
vectorSeries.append(nextSeries)
plot_segments_withSource(vectorSeries)
def plot_segments_withSource(theData):
colorPalette = ["red", "green", "blue", "yellow", "orange"]
output_file("test.html", mode='inline')
xRange = Range1d(1, 51200)
yRange = Range1d(1, 4000)
p = figure(plot_width=700, plot_height=750, x_range=xRange,\
y_range=yRange, output_backend="webgl")
colorIdx = -1
for nSeries in theData:
colorIdx += 1
color2use = colorPalette[colorIdx]
x0 = []
y0 = []
x1 = []
y1 = []
for vPoints in nSeries:
x0.append(vPoints[0])
y0.append(vPoints[1])
x1.append(vPoints[2])
y1.append(vPoints[3])
source = ColumnDataSource(dict(
x0 = x0,
y0 = y0,
x1 = x1,
y1 = y1
)
)
p.segment(x0="01", y0="y0", x1="x1", y1="y1",\
line_color=color2use, source=source, line_width=1)
# invert yAxis where 0 is at the top
p.y_range = Range1d(4000, 0)
hover = HoverTool()
hover.tooltips = [("x0,y0", "$x0,$y0"),
("x1,y1", "$x1,$y1")]
hover.point_policy = "snap_to_data"
hover.line_policy = "nearest"
p.add_tools(hover)
p.title.text = "This is a test"
p.legend.location = "top_right"
p.xaxis.axis_label = "Occurrences"
p.yaxis.axis_label = "Time"
show(p)
if __name__ == "__main__":
dataSeries2gen = "horizontal"
count2gen = 100000
series2gen = 2
build_test_data(dataSeries2gen, count2gen, series2gen)
我需要它来处理数据的显示和设置自定义 JavaScript(鼠标单击事件)以执行其他操作。但是,如果悬停工具无法识别项目是什么,则点击事件也不会触发。
谢谢
我在您的代码中发现了 2 个问题:
1) 分段悬停在倒轴(本例中为 Y 轴)上不起作用肯定存在问题。这可能是散景问题(请 check/submit 提出问题)
2) 工具提示语法不正确。根据 Bokeh 文档,仅允许使用以下语法
:$index: index of hovered point in the data source
:$name: value of the ``name`` property of the hovered glyph renderer
:$x: x-coordinate under the cursor in data space
:$y: y-coordinate under the cursor in data space
:$sx: x-coordinate under the cursor in screen (canvas) space
:$sy: y-coordinate under the cursor in screen (canvas) space
:$color: color data from data source
因此 $x0,$x1,$y0,$y1
无法被 HoverTool 理解,无法使用。我将它们替换为 @x0,@y0,@x1,@y1
,这相当于 $x,$y
,以防您的光标指向段的开头或结尾。我还添加了 ("x,y", "$sx,$sy")
以显示光标下的屏幕坐标。
为了正确显示悬停工具提示,我通过隐藏原始 y 轴并插入一个额外的倒置轴来实现一个技巧。这行得通,但实际上没有意义,因为轴是倒置的,但 y 范围不是。总之,希望对你有所帮助。
from bokeh.io import output_file
from bokeh.models.ranges import Range1d
from bokeh.models import ColumnDataSource, LinearAxis
from bokeh.plotting import figure, show
from bokeh.models.tools import HoverTool
import random
def build_test_data(dataSeries2gen, count2gen, series2gen):
# test data
vectorSeries = []
if dataSeries2gen == "horizontal":
# gen random seed numbers for X and Y but always use same Y
for nSeries in range(0, series2gen):
sameY = [random.randint(1, 4000) for y in range(4000)]
randX1 = [random.randint(1, 51200) for x in range(51200)]
randX2 = [random.randint(1, 51200) for x in range(51200)]
nextSeries = []
for nextSeed in range(1, count2gen):
yIdx = random.randint(1, 3999)
xIdx = random.randint(1, 51199)
nextSegment = [randX1[xIdx], sameY[yIdx], randX2[xIdx], sameY[yIdx]]
nextSeries.append(nextSegment)
vectorSeries.append(nextSeries)
else:
for nSeries in range(0, series2gen):
randY1 = [random.randint(1, 4000) for y in range(4000)]
randY2 = [random.randint(1, 4000) for y in range(4000)]
randX1 = [random.randint(1, 51200) for x in range(51200)]
randX2 = [random.randint(1, 51200) for x in range(51200)]
nextSeries = []
for nextSeed in range(1, count2gen):
nextSegment = [randX1[nextSeed], randY1[nextSeed], randX2[nextSeed], randY2[nextSeed]]
nextSeries.append(nextSegment)
vectorSeries.append(nextSeries)
plot_segments_withSource(vectorSeries)
def plot_segments_withSource(theData):
colorPalette = ["red", "green", "blue", "yellow", "orange"]
output_file("test.html", mode = 'inline')
p = figure(plot_width = 700, plot_height = 750, output_backend = "webgl", y_axis_location = None)
colorIdx = -1
for nSeries in theData:
colorIdx += 1
color2use = colorPalette[colorIdx]
x0, y0, x1, y1 = [], [], [], []
for vPoints in nSeries:
x0.append(vPoints[0])
y0.append(vPoints[1])
x1.append(vPoints[2])
y1.append(vPoints[3])
source = ColumnDataSource(dict(x0 = x0,y0 = y0,x1 = x1,y1 = y1))
p.segment(x0 = "x0", y0 = "y0", x1 = "x1", y1 = "y1", line_color = color2use, source = source, line_width = 1)
# insert inverted extra yAxis where 0 is at the top
p.extra_y_ranges = {"Time Extra Axis": Range1d(start = 4000, end = 0) }
p.add_layout(LinearAxis(y_range_name = "Time Extra Axis", axis_label = 'Time'), 'left')
hover = HoverTool()
hover.tooltips = [("x0,y0", "@x0,@y0"), ("x1,y1", "@x1,@y1"), ("x,y", "$sx,$sy")]
hover.point_policy = "snap_to_data"
hover.line_policy = "nearest"
p.add_tools(hover)
p.title.text = "This is a test"
p.xaxis.axis_label = "Occurrences"
p.yaxis.axis_label = "Time"
show(p)
if __name__ == "__main__":
dataSeries2gen = "horizontal"
count2gen = 10
series2gen = 2
build_test_data(dataSeries2gen, count2gen, series2gen)
结果:
我检查了很多类似问题的答案,但 none 是相关的。对我来说,悬停工具已启用,但无论我放大多远以将项目与所有其他项目隔离(无重叠),工具提示都不会显示。现在我在另一个使用段字形但 line_width=12 (x) 的应用程序上工作,并且随着段的高度放大 (y) 并最终显示工具提示。在它不起作用的地方,line_width=1(大量数据),该线段是一条水平线(y0、y1 的 y 值相同)。我认为这可能与 line_width 太小有关。但即使它的值设置得非常大 (20) 并放大并消除所有重叠,也不会显示任何工具提示。 这是我的测试代码:
from bokeh.io import output_file
from bokeh.models.ranges import Range1d
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure, show
from bokeh.models.tools import HoverTool
import random
def build_test_data(dataSeries2gen, count2gen, series2gen):
# test data
vectorSeries = []
if dataSeries2gen == "horizontal":
# gen random seed numbers for X and Y but always use same Y
for nSeries in range(0, series2gen):
sameY = [random.randint(1, 4000) for y in range(4000)]
randX1 = [random.randint(1, 51200) for x in range(51200)]
randX2 = [random.randint(1, 51200) for x in range(51200)]
nextSeries = []
for nextSeed in range(1, count2gen):
yIdx = random.randint(1, 3999)
xIdx = random.randint(1, 51999)
nextSegment = [randX1[xIdx], sameY[yIdx],\
randX2[xIdx], sameY[yIdx]]
nextSeries.append(nextSegment)
vectorSeries.append(nextSeries)
else:
for nSeries in range(0, series2gen):
randY1 = [random.randint(1, 4000) for y in range(4000)]
randY2 = [random.randint(1, 4000) for y in range(4000)]
randX1 = [random.randint(1, 51200) for x in range(51200)]
randX2 = [random.randint(1, 51200) for x in range(51200)]
nextSeries = []
for nextSeed in range(1, count2gen):
nextSegment = [randX1[nextSeed], randY1[nextSeed],\
[randX2[nextSeed], randY2[nextSeed]]
nextSeries.append(nextSegment)
vectorSeries.append(nextSeries)
plot_segments_withSource(vectorSeries)
def plot_segments_withSource(theData):
colorPalette = ["red", "green", "blue", "yellow", "orange"]
output_file("test.html", mode='inline')
xRange = Range1d(1, 51200)
yRange = Range1d(1, 4000)
p = figure(plot_width=700, plot_height=750, x_range=xRange,\
y_range=yRange, output_backend="webgl")
colorIdx = -1
for nSeries in theData:
colorIdx += 1
color2use = colorPalette[colorIdx]
x0 = []
y0 = []
x1 = []
y1 = []
for vPoints in nSeries:
x0.append(vPoints[0])
y0.append(vPoints[1])
x1.append(vPoints[2])
y1.append(vPoints[3])
source = ColumnDataSource(dict(
x0 = x0,
y0 = y0,
x1 = x1,
y1 = y1
)
)
p.segment(x0="01", y0="y0", x1="x1", y1="y1",\
line_color=color2use, source=source, line_width=1)
# invert yAxis where 0 is at the top
p.y_range = Range1d(4000, 0)
hover = HoverTool()
hover.tooltips = [("x0,y0", "$x0,$y0"),
("x1,y1", "$x1,$y1")]
hover.point_policy = "snap_to_data"
hover.line_policy = "nearest"
p.add_tools(hover)
p.title.text = "This is a test"
p.legend.location = "top_right"
p.xaxis.axis_label = "Occurrences"
p.yaxis.axis_label = "Time"
show(p)
if __name__ == "__main__":
dataSeries2gen = "horizontal"
count2gen = 100000
series2gen = 2
build_test_data(dataSeries2gen, count2gen, series2gen)
我需要它来处理数据的显示和设置自定义 JavaScript(鼠标单击事件)以执行其他操作。但是,如果悬停工具无法识别项目是什么,则点击事件也不会触发。
谢谢
我在您的代码中发现了 2 个问题:
1) 分段悬停在倒轴(本例中为 Y 轴)上不起作用肯定存在问题。这可能是散景问题(请 check/submit 提出问题)
2) 工具提示语法不正确。根据 Bokeh 文档,仅允许使用以下语法
:$index: index of hovered point in the data source
:$name: value of the ``name`` property of the hovered glyph renderer
:$x: x-coordinate under the cursor in data space
:$y: y-coordinate under the cursor in data space
:$sx: x-coordinate under the cursor in screen (canvas) space
:$sy: y-coordinate under the cursor in screen (canvas) space
:$color: color data from data source
因此 $x0,$x1,$y0,$y1
无法被 HoverTool 理解,无法使用。我将它们替换为 @x0,@y0,@x1,@y1
,这相当于 $x,$y
,以防您的光标指向段的开头或结尾。我还添加了 ("x,y", "$sx,$sy")
以显示光标下的屏幕坐标。
为了正确显示悬停工具提示,我通过隐藏原始 y 轴并插入一个额外的倒置轴来实现一个技巧。这行得通,但实际上没有意义,因为轴是倒置的,但 y 范围不是。总之,希望对你有所帮助。
from bokeh.io import output_file
from bokeh.models.ranges import Range1d
from bokeh.models import ColumnDataSource, LinearAxis
from bokeh.plotting import figure, show
from bokeh.models.tools import HoverTool
import random
def build_test_data(dataSeries2gen, count2gen, series2gen):
# test data
vectorSeries = []
if dataSeries2gen == "horizontal":
# gen random seed numbers for X and Y but always use same Y
for nSeries in range(0, series2gen):
sameY = [random.randint(1, 4000) for y in range(4000)]
randX1 = [random.randint(1, 51200) for x in range(51200)]
randX2 = [random.randint(1, 51200) for x in range(51200)]
nextSeries = []
for nextSeed in range(1, count2gen):
yIdx = random.randint(1, 3999)
xIdx = random.randint(1, 51199)
nextSegment = [randX1[xIdx], sameY[yIdx], randX2[xIdx], sameY[yIdx]]
nextSeries.append(nextSegment)
vectorSeries.append(nextSeries)
else:
for nSeries in range(0, series2gen):
randY1 = [random.randint(1, 4000) for y in range(4000)]
randY2 = [random.randint(1, 4000) for y in range(4000)]
randX1 = [random.randint(1, 51200) for x in range(51200)]
randX2 = [random.randint(1, 51200) for x in range(51200)]
nextSeries = []
for nextSeed in range(1, count2gen):
nextSegment = [randX1[nextSeed], randY1[nextSeed], randX2[nextSeed], randY2[nextSeed]]
nextSeries.append(nextSegment)
vectorSeries.append(nextSeries)
plot_segments_withSource(vectorSeries)
def plot_segments_withSource(theData):
colorPalette = ["red", "green", "blue", "yellow", "orange"]
output_file("test.html", mode = 'inline')
p = figure(plot_width = 700, plot_height = 750, output_backend = "webgl", y_axis_location = None)
colorIdx = -1
for nSeries in theData:
colorIdx += 1
color2use = colorPalette[colorIdx]
x0, y0, x1, y1 = [], [], [], []
for vPoints in nSeries:
x0.append(vPoints[0])
y0.append(vPoints[1])
x1.append(vPoints[2])
y1.append(vPoints[3])
source = ColumnDataSource(dict(x0 = x0,y0 = y0,x1 = x1,y1 = y1))
p.segment(x0 = "x0", y0 = "y0", x1 = "x1", y1 = "y1", line_color = color2use, source = source, line_width = 1)
# insert inverted extra yAxis where 0 is at the top
p.extra_y_ranges = {"Time Extra Axis": Range1d(start = 4000, end = 0) }
p.add_layout(LinearAxis(y_range_name = "Time Extra Axis", axis_label = 'Time'), 'left')
hover = HoverTool()
hover.tooltips = [("x0,y0", "@x0,@y0"), ("x1,y1", "@x1,@y1"), ("x,y", "$sx,$sy")]
hover.point_policy = "snap_to_data"
hover.line_policy = "nearest"
p.add_tools(hover)
p.title.text = "This is a test"
p.xaxis.axis_label = "Occurrences"
p.yaxis.axis_label = "Time"
show(p)
if __name__ == "__main__":
dataSeries2gen = "horizontal"
count2gen = 10
series2gen = 2
build_test_data(dataSeries2gen, count2gen, series2gen)
结果: