Bokeh中图像图的高效更新,用于交互式可视化

问题描述 投票:6回答:1

我正在尝试使用Bokeh创建一个多维数组的不同切片的平滑交互式可视化。切片中的数据根据​​用户交互而改变,因此必须每秒更新几次。我编写了一个带有几个小图像图(64x64值)的Bokeh应用程序来显示切片的内容,以及当用户与应用程序交互时更新ColumnDataSources的回调。一切都按预期工作,但我不能超过每秒2或3帧,我想得到至少10帧。

这是我的代码的简化示例,使用16个图像,每100ms定期回调一次,以模拟用户交互。在Mac和Linux上使用Bokeh 0.12.3和Python 2.7我在两台机器上获得几乎完全相同的时序(每帧约300毫秒)。

from __future__ import print_function, division
from random import randint
from timeit import default_timer as timer
import numpy as np

from bokeh.io import curdoc
from bokeh.layouts import gridplot
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure

# Set up app and fake data
grid_size = 4
data_size = 64
names = ['d{}'.format(i) for i in range(grid_size)]
plots = [[None for _ in range(grid_size)] for _ in range(grid_size)]
sources = dict()

num_images = 16
image_data = [[np.random.rand(data_size, data_size)] for i in range(num_images)]

# Create plots and datasources
plot_size = 256
for row, row_name in enumerate(names):
    for col, c_name in enumerate(names):
        d_name = row_name + "_" + c_name
        sources[d_name] = ColumnDataSource(
            {'value': image_data[randint(0, num_images - 1)]})
        plots[row][col] = figure(plot_width=plot_size,
                                 plot_height=plot_size,
                                 x_range=(0, data_size),
                                 y_range=(0, data_size))

        plots[row][col].image('value', source=sources[d_name],
                              x=0, y=0, dw=data_size, dh=data_size,
                              palette="Viridis256")


# Updates
def update():
    global sources
    start_update, end_update = [], []
    start_time = timer()
    for row, row_name in enumerate(names):
        for col, c_name in enumerate(names):
            d_name = row_name + "_" + c_name
            new_data = dict()
            new_data['value'] = image_data[randint(0, num_images - 1)]
            start_update.append(timer())  # ----- TIMER ON
            sources[d_name].data = new_data
            end_update.append(timer())    # ----- TIMER OFF

    print("\n---- \tTotal update time (secs): {:07.5f}".format(timer() - start_time))
    print("+ \tSources update times (secs): {}".format(
           ["{:07.5f}".format(end_update[i] - s) for i,s in enumerate(start_update)]))


# Document
grid = gridplot(plots)
curdoc().add_root(grid)
curdoc().add_periodic_callback(update, 100)

我已经尝试过为每个绘图只使用一个具有不同字段的数据源,并且还使用stream()方法更新数据(尽管由于整个图像被替换而没有意义)并且我没有实现任何性能提升。有谁知道我可以做些什么来改善这种可视化的交互性?我是否做错了更新图像数据?

我的猜测是瓶颈是由图像数据的JSON编码/解码引起的开销,这可能在将来有所改善,因为看起来Bokeh开发人员已经意识到这个问题并试图解决它。可悲的是,看起来修复不会很快到来。

https://github.com/bokeh/bokeh/issues/2204

https://github.com/bokeh/bokeh/pull/5429

还有其他建议吗?

python plot updates bokeh
1个回答
0
投票

正如其他人所提到的,已经实现了有效的二进制阵列协议。所以答案是升级到最新版本。

为了完整起见,这里是结果的比较。

使用0.12.3(原始帖子的版本 - 确保使用龙卷风<4.5):

----总更新时间(秒):0.14389 +来源更新时间(秒):['0.00943','0.00962','0.01100','0.00908','0.00004','0.00975','0.00984',' 0.00997','0.00946','0.00926','0.00912','0.00898','0.00900','0.00908','0.00999','0.01014'] ^ C

使用0.12.13(截至目前的最新版本):

----总更新时间(秒):0.01999 +来源更新时间(秒):['0.00157','0.00231','0.00131','0.00143','0.00114','0.00123','0.00109',' 0.00118','0.00116','0.00102','0.00113','0.00118','0.00099','0.00099','0.00104','0.00104']

如果所有图像都存储在单个ColumnDataSource的不同(长度1)列中并且一次更新,而不是迭代几个不同的数据源,则可能有更多的边际改进。

© www.soinside.com 2019 - 2024. All rights reserved.