Effective updating of graphic images in Bokeh for interactive visualization

I am trying to create a smooth interactive visualization of various fragments of a multidimensional array using Bokeh. Sliced ​​data is modified according to user interaction and therefore must be updated several times per second. I wrote a Bokeh application with several small graphic images (64x64 values) to show the contents of fragments, and a callback to update ColumnDataSources when the user interacts with the application. Everything works as expected, but I cannot get more than 2 or 3 frames per second, and I would like to get at least 10 frames.

Here is a simplified sample of my code using 16 images with a periodic callback every 100 ms to simulate user interaction. Using Bokeh 0.12.3 and Python 2.7 on Mac and Linux, I get almost the same timings (~ 300 ms per frame) on both machines.

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) 

I tried to use only one data source with different fields for each graph, and also update the data using the stream () method (although this does not make sense, since the whole image is replaced), and I don’t know, t have achieved any kind of performance improvement. Does anyone know what I can do to improve the interactivity of this visualization? Am I doing something wrong to update image data?

I assume that the bottleneck is the overhead caused by JSON encoding / decoding of image data, which may improve in the future, as it seems that Bokeh developers are aware of this problem and are trying to solve it. Unfortunately, it seems that the fix will not appear soon.

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

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

Any other suggestions?

+5
source share
1 answer

As others noted, an efficient binary array protocol was implemented. So the answer is to upgrade to the latest versions.

For completeness, here is a comparison of the results.

From 0.12.3 (version from the original message: be sure to use a tornado <4.5):

---- Total update time (seconds): 0.14389 + Sources of time updates (seconds): ['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) ^

As of 0.12.13 (the latest version since that time):

---- Total update time (sec.): 0.01999 + Sources of update time (sec.): [0.00367, 0.00113 ',' 0.00118 ',' 0,00099 ',' 0,00099 ',' 0.00104 ',' 0.00104 ']

Perhaps there is an even more minor improvement if all the images are stored in different (length 1) columns of the same ColumnDataSource and are updated immediately, rather than iterating over several different data sources.

0
source

Source: https://habr.com/ru/post/1260636/


All Articles