Bokeh图像绘图中选区数据求和及RangeTool报错解决咨询
解决Bokeh RangeTool与Image glyph的范围类型不匹配问题
错误原因
你遇到的报错核心是RangeTool的y_range参数仅支持Range1d类型,但Bokeh绘制Image时会自动生成DataRange1d作为轴范围,两者类型不匹配导致验证失败,并非RangeTool和Image glyph本身不兼容。
解决步骤
手动创建
Range1d替代默认范围
根据你的2D数组的y轴维度(比如数组的行数)手动定义Range1d实例,将其绑定到主绘图的y_range上,替换自动生成的DataRange1d。关联RangeTool与自定义Range1d
创建RangeTool时,将刚才定义的Range1d实例传入y_range参数即可。添加选中区域求和的回调逻辑
通过CustomJS回调监听RangeTool的范围变化,实时计算选中y轴区域内的数据和。
示例代码
from bokeh.plotting import figure, show from bokeh.models import RangeTool, CustomJS, ColumnDataSource from bokeh.layouts import column import numpy as np # 生成示例2D数组数据 data = np.random.rand(50, 50) # 50行50列的随机数组 x, y = np.meshgrid(np.linspace(0, 10, 50), np.linspace(0, 10, 50)) # 1. 手动创建Range1d,y范围对应数组的行索引(0到49) y_range = Range1d(start=0, end=data.shape[0]-1) # 主绘图,指定y_range为自定义的Range1d p = figure(y_range=y_range, width=800, height=400) image = p.image(image=[data], x=0, y=0, dw=10, dh=10, palette="Viridis256") # 2. 创建RangeTool,关联自定义的y_range range_tool = RangeTool(y_range=y_range) range_tool.overlay.fill_color = "navy" range_tool.overlay.fill_alpha = 0.2 # 创建小图用于显示RangeTool的控制条 select = figure(title="拖动选择Y轴区域", width=800, height=100, y_range=y_range) select.image(image=[data], x=0, y=0, dw=10, dh=10, palette="Viridis256") select.yaxis.visible = False select.add_tools(range_tool) # 3. 添加求和回调:监听RangeTool的y_range变化,计算选中区域的和 source = ColumnDataSource(data=dict(sum_val=[0])) callback = CustomJS(args=dict(data=data, y_range=y_range, source=source), code=""" const start = Math.floor(y_range.start); const end = Math.ceil(y_range.end); let total = 0; // 遍历选中的y轴行,求和 for (let i = start; i <= end; i++) { for (let j = 0; j < data[i].length; j++) { total += data[i][j]; } } source.data.sum_val[0] = total.toFixed(2); source.change.emit(); """) y_range.js_on_change('start', callback) y_range.js_on_change('end', callback) # 添加显示求和结果的文本 p.text(x=1, y=9, text="选中区域总和: ", text_font_size="16pt") p.text(x=3, y=9, text=source.data['sum_val'], text_font_size="16pt", source=source) # 布局并显示 show(column(p, select))
关键说明
- 手动指定
Range1d时,要确保范围和你的数据y轴实际范围匹配(比如如果你的Image的y坐标是从0到数组行数,就设置start=0, end=data.shape[0]-1)。 - 求和逻辑通过
CustomJS实现,直接在前端计算,避免后端交互;如果需要后端处理,可以用Bokeh的Server回调。
内容的提问来源于stack exchange,提问作者Delosari
相关产品推荐
相关产品推荐

