Tap event latency

Hello all,

I’m using the bokeh.events.Tap to trigger callbacks but this latter triggers half a second latter than when I click. Is this normal ?

Here some minimal code to see this unwanted latency using bokeh 1.02 :

‘’’

import numpy as np

from bokeh.plotting import figure, curdoc

from bokeh.models.widgets import Div

from bokeh.events import Tap

img = np.random.randint(0, 255, (3, 3, 4), ‘uint8’)

p = figure(x_range=(0, 1), y_range=(0, 1))

p.image_rgba(image=[img], x=[0], y=[0], dw=[1], dh=[1])

div = Div(text=‘waiting for tap…’)

def callback(event):

div.text = ‘tap at x={:.2f}, y={:.2f}’.format(event.x, event.y)

p.on_event(Tap, callback)

curdoc().add_root(p)

curdoc().add_root(div)

‘’’

Hi,

It does not seem to take that long for me locally, but several things could affect things: your network performance if the server is running remotely, how many current user sessions there are vs any actions taken to scale the app (e.g. num-threads or a load balancer), possibly other things.

It's worth saying that what you have below sends and event to the bokeh server, runs the python code in callback, sends a model change message back to the client, which then updates the display as a result. If the code below is truly representative of what you need to do, then there is no need for all that. You could do the same thing with a CustomJS callback and .js_on_event, which would execute entirely in the browser without any round trip to the server.

Thanks,

Bryan

···

On Dec 13, 2018, at 10:09, [email protected] wrote:

Hello all,

I'm using the bokeh.events.Tap to trigger callbacks but this latter triggers half a second latter than when I click. Is this normal ?

Here some minimal code to see this unwanted latency using bokeh 1.02 :

'''
import numpy as np
from bokeh.plotting import figure, curdoc
from bokeh.models.widgets import Div
from bokeh.events import Tap

img = np.random.randint(0, 255, (3, 3, 4), 'uint8')

p = figure(x_range=(0, 1), y_range=(0, 1))
p.image_rgba(image=[img], x=[0], y=[0], dw=[1], dh=[1])

div = Div(text='waiting for tap...')

def callback(event):
    div.text = 'tap at x={:.2f}, y={:.2f}'.format(event.x, event.y)

p.on_event(Tap, callback)

curdoc().add_root(p)
curdoc().add_root(div)

'''

--
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/20cb992b-f861-421f-83f2-2975decef160%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

Hi,

Thanks so much for the reply !

Actually I run my code locally with nothing else running in parallel. I confirm I have almost half a second of latency between the moment I click and the moment the callback kicks in. Strangely this is only the case with the Tap event and not for instance the MouseMove event which is much more reactive. I tried on different browsers, nothing changes.

Let me be more specific on what I’m achieving to perform. I want to fit curves on a background image. For that purpose I plan to:

  1. use the MouseMove position to update on real time some (quite complex) curve which pass where the mouse is. For this I use python functions to compute new curve data. CustomJS would be the best but I’m no expert on JS and using numpy/scipy for that purpose simplify things a lot (especially when working on a POC).

  2. use the Tap event to freeze/unfreeze the curve so to stop updating the curve shape when at the right location.

Actually some small latency is not problematic at this stage (as it is a prototype) but half a second makes the app really frustrating to use. When I click at the wanted curve position I need to stay still a bit if not the curve continue to moves with the mouse during half a second. This is really strange as I would expect that the Tap event would at least occur before the next MouseMove Event. As if a small timeout was set on the Tap event.

For now I use the Press event as it requires to click long enough to actually perform a click which takes in place immediately so either I don’t click during enough time and the curve don’t freeze, either it freeze at the right location.

I think it is working well enough for my scenario case but a wanted to share with everybody this strange behaviour and hopefully increase my understanding on how bokeh works or on how to better use it :slight_smile:

Here some more elaborate minimal code illustrating what I want to achieve.

‘’’

import numpy as np

from bokeh.plotting import figure, curdoc

from bokeh.models import Span

from bokeh.models.widgets import Div

from bokeh.events import Tap, MouseMove

controls if mouse positions update shape property

active = False

p = figure(x_range=(0, 1), y_range=(0, 1))

any background image

img = np.random.randint(0, 255, (3, 3, 4), ‘uint8’)

p.image_rgba(image=[img], x=[0], y=[0], dw=[1], dh=[1])

any (complicated) shape

shape = Span(location=0, dimension=‘height’)

p.renderers.extend([shape])

freeze/unfreeze shape

def tap_callback(event):

global active

active = not active

def shape_callback(event):

if active:

any (complicated) shape update

shape.location = event.x

p.on_event(Tap, tap_callback, shape_callback)

p.on_event(MouseMove, shape_callback)

curdoc().add_root(p)

curdoc().add_root(div)

‘‘’

···

Le 13 déc. 2018 à 23:12, Bryan Van de ven [email protected] a écrit :

Hi,

It does not seem to take that long for me locally, but several things could affect things: your network performance if the server is running remotely, how many current user sessions there are vs any actions taken to scale the app (e.g. num-threads or a load balancer), possibly other things.

It’s worth saying that what you have below sends and event to the bokeh server, runs the python code in callback, sends a model change message back to the client, which then updates the display as a result. If the code below is truly representative of what you need to do, then there is no need for all that. You could do the same thing with a CustomJS callback and .js_on_event, which would execute entirely in the browser without any round trip to the server.

Thanks,

Bryan

On Dec 13, 2018, at 10:09, [email protected] wrote:

Hello all,

I’m using the bokeh.events.Tap to trigger callbacks but this latter triggers half a second latter than when I click. Is this normal ?

Here some minimal code to see this unwanted latency using bokeh 1.02 :

‘’’
import numpy as np
from bokeh.plotting import figure, curdoc
from bokeh.models.widgets import Div
from bokeh.events import Tap

img = np.random.randint(0, 255, (3, 3, 4), ‘uint8’)

p = figure(x_range=(0, 1), y_range=(0, 1))
p.image_rgba(image=[img], x=[0], y=[0], dw=[1], dh=[1])

div = Div(text=‘waiting for tap…’)

def callback(event):
div.text = ‘tap at x={:.2f}, y={:.2f}’.format(event.x, event.y)

p.on_event(Tap, callback)

curdoc().add_root(p)
curdoc().add_root(div)

‘’’


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/20cb992b-f861-421f-83f2-2975decef160%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.


You received this message because you are subscribed to a topic in the Google Groups “Bokeh Discussion - Public” group.
To unsubscribe from this topic, visit https://groups.google.com/a/continuum.io/d/topic/bokeh/WyvNzjBBq2g/unsubscribe.
To unsubscribe from this group and all its topics, 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/78CFD603-F88C-4BC0-BD3A-80B0918C3C01%40anaconda.com.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Hi,

It occurs to me that there may be another reason, namely they the underlying gesture event library we use probably has to delay recognition of single tap events long enough to determine that the tap is not actually just the start of a double tap. There’s not much to do about that in any released version of Bokeh. We could investigate whether the timeout is configurable in the underlying library, and if so, expose that configuration for users that need something different. A GitHub issue would be the next appropriate step.

Thanks,

Bryan

···

On Dec 14, 2018, at 12:12, Alister Trabattoni [email protected] wrote:

Hi,

Thanks so much for the reply !

Actually I run my code locally with nothing else running in parallel. I confirm I have almost half a second of latency between the moment I click and the moment the callback kicks in. Strangely this is only the case with the Tap event and not for instance the MouseMove event which is much more reactive. I tried on different browsers, nothing changes.

Let me be more specific on what I’m achieving to perform. I want to fit curves on a background image. For that purpose I plan to:

  1. use the MouseMove position to update on real time some (quite complex) curve which pass where the mouse is. For this I use python functions to compute new curve data. CustomJS would be the best but I’m no expert on JS and using numpy/scipy for that purpose simplify things a lot (especially when working on a POC).
  1. use the Tap event to freeze/unfreeze the curve so to stop updating the curve shape when at the right location.

Actually some small latency is not problematic at this stage (as it is a prototype) but half a second makes the app really frustrating to use. When I click at the wanted curve position I need to stay still a bit if not the curve continue to moves with the mouse during half a second. This is really strange as I would expect that the Tap event would at least occur before the next MouseMove Event. As if a small timeout was set on the Tap event.

For now I use the Press event as it requires to click long enough to actually perform a click which takes in place immediately so either I don’t click during enough time and the curve don’t freeze, either it freeze at the right location.

I think it is working well enough for my scenario case but a wanted to share with everybody this strange behaviour and hopefully increase my understanding on how bokeh works or on how to better use it :slight_smile:

Here some more elaborate minimal code illustrating what I want to achieve.

‘’’

import numpy as np

from bokeh.plotting import figure, curdoc

from bokeh.models import Span

from bokeh.models.widgets import Div

from bokeh.events import Tap, MouseMove

controls if mouse positions update shape property

active = False

p = figure(x_range=(0, 1), y_range=(0, 1))

any background image

img = np.random.randint(0, 255, (3, 3, 4), ‘uint8’)

p.image_rgba(image=[img], x=[0], y=[0], dw=[1], dh=[1])

any (complicated) shape

shape = Span(location=0, dimension=‘height’)

p.renderers.extend([shape])

freeze/unfreeze shape

def tap_callback(event):

global active

active = not active

def shape_callback(event):

if active:

any (complicated) shape update

shape.location = event.x

p.on_event(Tap, tap_callback, shape_callback)

p.on_event(MouseMove, shape_callback)

curdoc().add_root(p)

curdoc().add_root(div)

‘‘’

Le 13 déc. 2018 à 23:12, Bryan Van de ven [email protected] a écrit :

Hi,

It does not seem to take that long for me locally, but several things could affect things: your network performance if the server is running remotely, how many current user sessions there are vs any actions taken to scale the app (e.g. num-threads or a load balancer), possibly other things.

It’s worth saying that what you have below sends and event to the bokeh server, runs the python code in callback, sends a model change message back to the client, which then updates the display as a result. If the code below is truly representative of what you need to do, then there is no need for all that. You could do the same thing with a CustomJS callback and .js_on_event, which would execute entirely in the browser without any round trip to the server.

Thanks,

Bryan

On Dec 13, 2018, at 10:09, [email protected] wrote:

Hello all,

I’m using the bokeh.events.Tap to trigger callbacks but this latter triggers half a second latter than when I click. Is this normal ?

Here some minimal code to see this unwanted latency using bokeh 1.02 :

‘’’
import numpy as np
from bokeh.plotting import figure, curdoc
from bokeh.models.widgets import Div
from bokeh.events import Tap

img = np.random.randint(0, 255, (3, 3, 4), ‘uint8’)

p = figure(x_range=(0, 1), y_range=(0, 1))
p.image_rgba(image=[img], x=[0], y=[0], dw=[1], dh=[1])

div = Div(text=‘waiting for tap…’)

def callback(event):
div.text = ‘tap at x={:.2f}, y={:.2f}’.format(event.x, event.y)

p.on_event(Tap, callback)

curdoc().add_root(p)
curdoc().add_root(div)

‘’’


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/20cb992b-f861-421f-83f2-2975decef160%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.


You received this message because you are subscribed to a topic in the Google Groups “Bokeh Discussion - Public” group.
To unsubscribe from this topic, visit https://groups.google.com/a/continuum.io/d/topic/bokeh/WyvNzjBBq2g/unsubscribe.
To unsubscribe from this group and all its topics, 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/78CFD603-F88C-4BC0-BD3A-80B0918C3C01%40anaconda.com.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

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/62C55C5B-4D99-4897-BFB9-EFB7FC7DA6B3%40gmail.com.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

It’s done !

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

···

Le 14 déc. 2018 à 20:56, Bryan Van de ven [email protected] a écrit :

Hi,

It occurs to me that there may be another reason, namely they the underlying gesture event library we use probably has to delay recognition of single tap events long enough to determine that the tap is not actually just the start of a double tap. There’s not much to do about that in any released version of Bokeh. We could investigate whether the timeout is configurable in the underlying library, and if so, expose that configuration for users that need something different. A GitHub issue would be the next appropriate step.

Thanks,

Bryan

On Dec 14, 2018, at 12:12, Alister Trabattoni [email protected] wrote:

Hi,

Thanks so much for the reply !

Actually I run my code locally with nothing else running in parallel. I confirm I have almost half a second of latency between the moment I click and the moment the callback kicks in. Strangely this is only the case with the Tap event and not for instance the MouseMove event which is much more reactive. I tried on different browsers, nothing changes.

Let me be more specific on what I’m achieving to perform. I want to fit curves on a background image. For that purpose I plan to:

  1. use the MouseMove position to update on real time some (quite complex) curve which pass where the mouse is. For this I use python functions to compute new curve data. CustomJS would be the best but I’m no expert on JS and using numpy/scipy for that purpose simplify things a lot (especially when working on a POC).
  1. use the Tap event to freeze/unfreeze the curve so to stop updating the curve shape when at the right location.

Actually some small latency is not problematic at this stage (as it is a prototype) but half a second makes the app really frustrating to use. When I click at the wanted curve position I need to stay still a bit if not the curve continue to moves with the mouse during half a second. This is really strange as I would expect that the Tap event would at least occur before the next MouseMove Event. As if a small timeout was set on the Tap event.

For now I use the Press event as it requires to click long enough to actually perform a click which takes in place immediately so either I don’t click during enough time and the curve don’t freeze, either it freeze at the right location.

I think it is working well enough for my scenario case but a wanted to share with everybody this strange behaviour and hopefully increase my understanding on how bokeh works or on how to better use it :slight_smile:

Here some more elaborate minimal code illustrating what I want to achieve.

‘’’

import numpy as np

from bokeh.plotting import figure, curdoc

from bokeh.models import Span

from bokeh.models.widgets import Div

from bokeh.events import Tap, MouseMove

controls if mouse positions update shape property

active = False

p = figure(x_range=(0, 1), y_range=(0, 1))

any background image

img = np.random.randint(0, 255, (3, 3, 4), ‘uint8’)

p.image_rgba(image=[img], x=[0], y=[0], dw=[1], dh=[1])

any (complicated) shape

shape = Span(location=0, dimension=‘height’)

p.renderers.extend([shape])

freeze/unfreeze shape

def tap_callback(event):

global active

active = not active

def shape_callback(event):

if active:

any (complicated) shape update

shape.location = event.x

p.on_event(Tap, tap_callback, shape_callback)

p.on_event(MouseMove, shape_callback)

curdoc().add_root(p)

curdoc().add_root(div)

‘‘’

Le 13 déc. 2018 à 23:12, Bryan Van de ven [email protected] a écrit :

Hi,

It does not seem to take that long for me locally, but several things could affect things: your network performance if the server is running remotely, how many current user sessions there are vs any actions taken to scale the app (e.g. num-threads or a load balancer), possibly other things.

It’s worth saying that what you have below sends and event to the bokeh server, runs the python code in callback, sends a model change message back to the client, which then updates the display as a result. If the code below is truly representative of what you need to do, then there is no need for all that. You could do the same thing with a CustomJS callback and .js_on_event, which would execute entirely in the browser without any round trip to the server.

Thanks,

Bryan

On Dec 13, 2018, at 10:09, [email protected] wrote:

Hello all,

I’m using the bokeh.events.Tap to trigger callbacks but this latter triggers half a second latter than when I click. Is this normal ?

Here some minimal code to see this unwanted latency using bokeh 1.02 :

‘’’
import numpy as np
from bokeh.plotting import figure, curdoc
from bokeh.models.widgets import Div
from bokeh.events import Tap

img = np.random.randint(0, 255, (3, 3, 4), ‘uint8’)

p = figure(x_range=(0, 1), y_range=(0, 1))
p.image_rgba(image=[img], x=[0], y=[0], dw=[1], dh=[1])

div = Div(text=‘waiting for tap…’)

def callback(event):
div.text = ‘tap at x={:.2f}, y={:.2f}’.format(event.x, event.y)

p.on_event(Tap, callback)

curdoc().add_root(p)
curdoc().add_root(div)

‘’’


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/20cb992b-f861-421f-83f2-2975decef160%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.


You received this message because you are subscribed to a topic in the Google Groups “Bokeh Discussion - Public” group.
To unsubscribe from this topic, visit https://groups.google.com/a/continuum.io/d/topic/bokeh/WyvNzjBBq2g/unsubscribe.
To unsubscribe from this group and all its topics, 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/78CFD603-F88C-4BC0-BD3A-80B0918C3C01%40anaconda.com.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

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/62C55C5B-4D99-4897-BFB9-EFB7FC7DA6B3%40gmail.com.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

You received this message because you are subscribed to a topic in the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this topic, visit https://groups.google.com/a/continuum.io/d/topic/bokeh/WyvNzjBBq2g/unsubscribe.

To unsubscribe from this group and all its topics, 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/6BFDFA1A-ACA8-42AA-B547-6683DD895C8D%40anaconda.com.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.