You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Bokeh图表X轴高效高亮多段不同透明度的区域?

解决Bokeh中大量时序高亮区域的伪影与性能问题

你遇到的这个问题在处理大量时序高亮区域时特别常见——用成百上千个BoxAnnotation不仅渲染慢,还会因为独立元素的渲染精度问题在缩小时出现线条伪影。下面给你两个高效的解决方案,既能消除伪影,又能让图表交互流畅:

方案一:用quad Glyph批量渲染高亮区域

这是最推荐的方案,因为它把所有高亮区域作为单个矢量图形元素渲染,既解决性能问题,又彻底消除伪影。

实现步骤:

  1. 准备高亮区域的批量数据:每个时段的左右边界(对应你的time列相邻值)、上下边界(覆盖整个Y轴范围),以及对应的透明度。
  2. 用quad glyph一次性绘制所有矩形,替代循环添加BoxAnnotation。

修改后的代码:

import pandas as pd
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource

# 假设你的data_frame已经包含time, intensity, prediction列
# data_frame = pd.read_csv("your_data.csv")

# 计算Y轴的范围(如果是静态数据可以提前算,动态的话看后面的回调方案)
y_min = data_frame['intensity'].min()
y_max = data_frame['intensity'].max()

# 构建高亮区域的数据源
highlight_data = {
    "left": data_frame['time'].values[:-1],
    "right": data_frame['time'].values[1:],
    "bottom": [y_min] * (len(data_frame)-1),
    "top": [y_max] * (len(data_frame)-1),
    "fill_alpha": data_frame['prediction'].values[:-1],
    "fill_color": ["red"] * (len(data_frame)-1)
}
highlight_source = ColumnDataSource(highlight_data)

# 创建图表
figure_ = figure(x_axis_label='Time', y_axis_label='Intensity')

# 先绘制高亮区域(确保散点在上方)
figure_.quad(
    source=highlight_source,
    left='left', right='right', bottom='bottom', top='top',
    fill_alpha='fill_alpha', fill_color='fill_color',
    line_alpha=0  # 完全隐藏线条,避免任何边界问题
)

# 再绘制散点数据
figure_.circle(x='time', y='intensity', source=ColumnDataSource(data_frame))

show(figure_)

为什么这个方案有效?

  • 性能提升:单个quad glyph对应一个渲染器,Bokeh会批量处理所有矩形,比数千个独立的BoxAnnotation快得多,交互缩放、平移时不会卡顿。
  • 消除伪影:所有矩形属于同一组矢量图形,渲染时不会出现独立元素的重叠/缝隙问题,缩放时始终保持平滑的拼接效果。

动态Y轴范围的适配

如果用户需要缩放Y轴,让高亮区域自动铺满当前Y轴范围,可以添加一个JS回调:

from bokeh.models import CustomJS

# 绑定Y轴范围变化的回调
callback = CustomJS(
    args=dict(source=highlight_source, y_range=figure_.y_range),
    code="""
        const data = source.data;
        const n = data.left.length;
        data.bottom = Array(n).fill(y_range.start);
        data.top = Array(n).fill(y_range.end);
        source.change.emit();
    """
)

figure_.y_range.js_on_change('start', callback)
figure_.y_range.js_on_change('end', callback)

方案二:用ImageRGBA渲染位图背景(超大数据量场景)

如果你的数据集达到十万甚至百万级,quad可能也会有性能瓶颈,这时可以把预测概率转换成一张位图作为背景渲染,性能会更好,但代价是放大后会有像素化(因为是位图)。

核心思路:

  1. 将时间轴离散化为像素,把每个时段的概率值转换成RGBA颜色(红色通道对应概率,alpha通道对应透明度)。
  2. 用ImageRGBA把生成的位图作为背景添加到图表中。

这个方案适合追求极致性能且不需要矢量清晰度的场景,实现起来稍复杂,如果你需要可以再深入探讨。


内容的提问来源于stack exchange,提问作者golmschenk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:09:10