实时 multi_line 图形更新,性能不错
Realtime multi_line graph updates at decent performance
我目前正在使用 Bokeh 来呈现一个 multi_line
图,其中有几条静态线和一条实时更新的线。这只需要几行就可以正常运行,但是,根据行的分辨率(通常每行 2000-4000 点),当绘图中有 50 多行时,刷新率会显着下降。 CPU 那个时候浏览器的使用率相当高。
这是初始化剧情和触发实时更新的方式:
figure_opts = dict(plot_width=750,
plot_height=750,
x_range=(0, dset_size),
y_range=(0, np.iinfo(dtype).max),
tools='pan,wheel_zoom')
line_opts = dict(
line_width=5, line_color='color', line_alpha=0.6,
hover_line_color='color', hover_line_alpha=1.0,
source=profile_lines
)
profile_plot = figure(**figure_opts)
profile_plot.toolbar.logo = None
multi_line_plot = profile_plot.multi_line(xs='x', ys='y', **line_opts)
profile_plot.xaxis.axis_label = "x"
profile_plot.yaxis.axis_label = "y"
ds = multi_line_plot.data_source
def update_live_plot():
random_arr = np.random.random_integers(65535 * (i % 100) / (100 + 100 / 4), 65535 * (i % 100 + 1) / 100, (2048))
profile = random_arr.astype(np.uint16)
if profile is not None:
profile_lines["x"][i] = x
profile_lines["y"][i] = profile
profile_lines["color"][i] = Category20_20[0]
ds.data = profile_lines
doc.add_periodic_callback(update_live_plot, 100)
有没有什么办法可以让它表现得更好?
例如,是否可以只更新需要更新的一行,而不是 ds.data = profile_lines
?
编辑: 需要更新的一行必须完整更新。 IE。我不是在一端流式传输数据,而是我有一组全新的 2000-4000 值并且想要显示这些值,而不是旧的 live 行。
当前 live 行是 profile_lines
字典数组中 i
处的元素。
您很幸运,使用 CDS patch
方法可以在保持相同长度 的同时使用所有新元素更新一行 。 (流式传输在这里无济于事,因为流式传输到 multi_line
的 CDS 末尾意味着添加一个完整的新行,而流式传输到每个子行末尾的另一种情况没有很好的解决方案全部。)
存储库中有一个 patch_app.py
example 显示如何使用 patch
更新 multi_line
的一行。该示例仅更新线中的一个点,但可以使用切片一次更新整条线:
source.patch({ 'ys' : [([i, slice(None)], new_y)]})
这将更新 source.data['ys']
中的第 i 行,只要 new_y
与旧行的长度相同。
我目前正在使用 Bokeh 来呈现一个 multi_line
图,其中有几条静态线和一条实时更新的线。这只需要几行就可以正常运行,但是,根据行的分辨率(通常每行 2000-4000 点),当绘图中有 50 多行时,刷新率会显着下降。 CPU 那个时候浏览器的使用率相当高。
这是初始化剧情和触发实时更新的方式:
figure_opts = dict(plot_width=750,
plot_height=750,
x_range=(0, dset_size),
y_range=(0, np.iinfo(dtype).max),
tools='pan,wheel_zoom')
line_opts = dict(
line_width=5, line_color='color', line_alpha=0.6,
hover_line_color='color', hover_line_alpha=1.0,
source=profile_lines
)
profile_plot = figure(**figure_opts)
profile_plot.toolbar.logo = None
multi_line_plot = profile_plot.multi_line(xs='x', ys='y', **line_opts)
profile_plot.xaxis.axis_label = "x"
profile_plot.yaxis.axis_label = "y"
ds = multi_line_plot.data_source
def update_live_plot():
random_arr = np.random.random_integers(65535 * (i % 100) / (100 + 100 / 4), 65535 * (i % 100 + 1) / 100, (2048))
profile = random_arr.astype(np.uint16)
if profile is not None:
profile_lines["x"][i] = x
profile_lines["y"][i] = profile
profile_lines["color"][i] = Category20_20[0]
ds.data = profile_lines
doc.add_periodic_callback(update_live_plot, 100)
有没有什么办法可以让它表现得更好?
例如,是否可以只更新需要更新的一行,而不是 ds.data = profile_lines
?
编辑: 需要更新的一行必须完整更新。 IE。我不是在一端流式传输数据,而是我有一组全新的 2000-4000 值并且想要显示这些值,而不是旧的 live 行。
当前 live 行是 profile_lines
字典数组中 i
处的元素。
您很幸运,使用 CDS patch
方法可以在保持相同长度 的同时使用所有新元素更新一行 。 (流式传输在这里无济于事,因为流式传输到 multi_line
的 CDS 末尾意味着添加一个完整的新行,而流式传输到每个子行末尾的另一种情况没有很好的解决方案全部。)
存储库中有一个 patch_app.py
example 显示如何使用 patch
更新 multi_line
的一行。该示例仅更新线中的一个点,但可以使用切片一次更新整条线:
source.patch({ 'ys' : [([i, slice(None)], new_y)]})
这将更新 source.data['ys']
中的第 i 行,只要 new_y
与旧行的长度相同。