Discarding triggered but not completed on_change events from animation

I added a “movie” of frames of image data to my Bokeh app, following the Holoviews player.py example (http://holoviews.org/reference/apps/bokeh/player.html) (though I don’t use Holoview, just update ColumnDataSource of the p.image with the new frame).

When playing, it works fine. However, when I try to hit the “Pause”, the movie takes a long time to stop. Is there a way to force discarding of callbacks that have been triggered, but haven’t completed? Right now, when the Pause button is hit, it simply calls curdoc().remove_periodic_callback(animate_update)

Here’s a minimum working example. It’s only a problem with the large image sizes (400x400), the normal player.py size of (10x10) doesn’t have the issue. So it must be the time lag due to image rendering. Any suggestions to make this smooth and responsive are appreciated.

-- coding: utf-8 --

“”"

An example of a simple player widget animating an Image demonstrating

how to connnect a simple HoloViews plot with custom widgets and

combine them into a bokeh layout.

The app can be served using:

bokeh serve --show player.py

“”"

import numpy as np

from bokeh.io import curdoc

from bokeh.layouts import layout

from bokeh.models import Slider, Button

from bokeh.plotting import figure, ColumnDataSource

create image data

start = 0

end = 10

images = np.random.rand(400,400,end-start+1)

#create CDS and figure

simg = ColumnDataSource({‘images’:[images],‘image’:[images[…,0]],

‘x’:[0],‘y’:[0],‘dw’:[images.shape[1]],‘dh’:[images.shape[0]]})

p = figure(plot_width=512,plot_height=512,sizing_mode=‘scale_both’,

x_range=(0,images.shape[1]),y_range=(0,images.shape[0]))

p.image(source=simg,image=‘image’,x=‘x’,y=‘y’,dw=‘dw’,dh=‘dh’)

def animate_update():

year = slider.value + 1

if year > end:

year = start

slider.value = year

def slider_update(attrname, old, new):

print slider.value

tmp = simg.data[‘images’][0][…,slider.value]

print tmp.shape

simg.data[‘image’] = [tmp]

slider = Slider(start=start, end=end, value=0, step=1, title=“Year”)

slider.on_change(‘value’, slider_update)

def animate():

if button.label == ‘► Play’:

button.label = ‘❚❚ Pause’

curdoc().add_periodic_callback(animate_update, 200)

else:

button.label = ‘► Play’

curdoc().remove_periodic_callback(animate_update)

button = Button(label=‘► Play’, width=60)

button.on_click(animate)

layout = layout([

[p],

[slider, button],

], sizing_mode=‘fixed’)

curdoc().add_root(layout)

``

···

On Tuesday, August 29, 2017 at 3:05:48 PM UTC-4, [email protected] wrote:

I added a “movie” of frames of image data to my Bokeh app, following the Holoviews player.py example (http://holoviews.org/reference/apps/bokeh/player.html) (though I don’t use Holoview, just update ColumnDataSource of the p.image with the new frame).

When playing, it works fine. However, when I try to hit the “Pause”, the movie takes a long time to stop. Is there a way to force discarding of callbacks that have been triggered, but haven’t completed? Right now, when the Pause button is hit, it simply calls curdoc().remove_periodic_callback(animate_update)

My guess is it is not the image *rendering* but rather the time it takes to *send* the image data. There was a round of work last year to switch to a Base64 encoding that make dramatic improvements for sending image data. But there is potentially even more dramatic improvements that can be made (for Bokeh server usage) by adopting a pure binary protocol. There is an open issue for this that you can follow:

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

I hope to have something in the next month or two. Unfortunately offhand I don't have any good workarounds to suggest for your particular situation in the mean time.

Thanks,

Bryan

···

On Aug 29, 2017, at 14:31, [email protected] wrote:

Here's a minimum working example. It's only a problem with the large image sizes (400x400), the normal player.py size of (10x10) doesn't have the issue. So it must be the time lag due to image rendering. Any suggestions to make this smooth and responsive are appreciated.
# -*- coding: utf-8 -*-
"""
An example of a simple player widget animating an Image demonstrating
how to connnect a simple HoloViews plot with custom widgets and
combine them into a bokeh layout.

The app can be served using:

    bokeh serve --show player.py

"""
import numpy as np

from bokeh.io import curdoc
from bokeh.layouts import layout
from bokeh.models import Slider, Button
from bokeh.plotting import figure, ColumnDataSource

# create image data
start = 0
end = 10
images = np.random.rand(400,400,end-start+1)

#create CDS and figure
simg = ColumnDataSource({'images':[images],'image':[images[...,0]],
                        'x':[0],'y':[0],'dw':[images.shape[1]],'dh':[images.shape[0]]})
p = figure(plot_width=512,plot_height=512,sizing_mode='scale_both',
           x_range=(0,images.shape[1]),y_range=(0,images.shape[0]))
p.image(source=simg,image='image',x='x',y='y',dw='dw',dh='dh')

def animate_update():
    year = slider.value + 1
    if year > end:
        year = start
    slider.value = year

def slider_update(attrname, old, new):
    print slider.value
    tmp = simg.data['images'][0][...,slider.value]
    print tmp.shape
    simg.data['image'] = [tmp]

slider = Slider(start=start, end=end, value=0, step=1, title="Year")
slider.on_change('value', slider_update)

def animate():
    if button.label == '► Play':
        button.label = '❚❚ Pause'
        curdoc().add_periodic_callback(animate_update, 200)
    else:
        button.label = '► Play'
        curdoc().remove_periodic_callback(animate_update)

button = Button(label='► Play', width=60)
button.on_click(animate)

layout = layout([
    [p],
    [slider, button],
], sizing_mode='fixed')

curdoc().add_root(layout)

On Tuesday, August 29, 2017 at 3:05:48 PM UTC-4, [email protected] wrote:
I added a "movie" of frames of image data to my Bokeh app, following the Holoviews player.py example (http://holoviews.org/reference/apps/bokeh/player.html) (though I don't use Holoview, just update ColumnDataSource of the p.image with the new frame).

When playing, it works fine. However, when I try to hit the "Pause", the movie takes a long time to stop. Is there a way to force discarding of callbacks that have been triggered, but haven't completed? Right now, when the Pause button is hit, it simply calls curdoc().remove_periodic_callback(animate_update)

--
You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/b1a2ae5a-99d7-472c-b7d1-3268d36863ab%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.