☰Read-only archive⌕
Looking for help with Bokeh?

This is a read-only archive. Ask questions and join the conversation on GitHub.

Visit Community Support on GitHub →
Archived discussions · Captured October 28, 2026

Calling Python function when clicking on a glyph

Community Support
dekrion
dekrion

I know the only way the BokehJS can interact with Python code is though Bokeh server.
I can easily invoke a Python function when clicking e.g. on a Button widget.

Is there any way to call Python code when clicking on a glyph e.g. a circle?

⌁   Link to post
dekrion
dekrion

from functools import partial
from bokeh.plotting import curdoc, show, figure
from bokeh.models.widgets import Button, Paragraph
from bokeh.models import CustomJS, ColumnDataSource, TapTool
from bokeh.layouts import widgetbox, column
from bokeh.client import push_session

plot = figure(width = 400, height = 400, tools = “tap”)
circles = plot.circle(x = [2, 5, 8], y = [5, 8, 5], size = 30)

minus = Button(label = ‘-’)
plus = Button(label = ‘+’)
text = Paragraph(text = ‘.’)

def function_plus():
text.text = ‘Python function “function_plus” called’

def function_minus():
text.text = ‘Python function “function_minus” called’

def click_handler(foo = None):
foo()

minus.on_click(partial(click_handler, foo = function_minus))
plus.on_click(partial(click_handler, foo = function_plus))

tool = plot.select_one(TapTool)
tool.renderers = [circles]
tool.callback = CustomJS.from_py_func(click_handler) # how to pass “function_minus” or “function_plus” here?

layout = column(widgetbox(minus, plus, text), plot)

session = push_session(document = curdoc())
curdoc().add_root(layout)
session.show(layout)
session.loop_until_closed()

``

···

On Wednesday, July 26, 2017 at 11:47:46 AM UTC+2, Tony Halik wrote:

I know the only way the BokehJS can interact with Python code is though Bokeh server.
I can easily invoke a Python function when clicking e.g. on a Button widget.

Is there any way to call Python code when clicking on a glyph e.g. a circle?

⌁   Link to post
Sebastien_Roche
Sebastien_Roche

I am not really familiar with partial but to answer:

“Is there any way to call Python code when clicking on a glyph e.g. a circle?”

from bokeh.plotting import curdoc, show, figure

from bokeh.models.widgets import Button, Paragraph

from bokeh.models import CustomJS, ColumnDataSource, TapTool

from bokeh.layouts import widgetbox, column

from bokeh.client import push_session

from bokeh.events import Tap

from datetime import datetime

plot = figure(width = 400, height = 400, tools = “tap”)

source = ColumnDataSource(data={‘x’:[2, 5, 8],‘y’:[5, 8, 5]})

circles = plot.circle(x =‘x’, y = ‘y’, size = 30, source = source)

minus = Button(label = ‘-’)

plus = Button(label = ‘+’)

text = Paragraph(text = ‘.’,width=500)

def function_plus():

text.text = 'Python function “function_plus” called with button at '+str(datetime.now())

def function_minus():

text.text = 'Python function “function_minus” called with button at '+str(datetime.now())

def function_source(attr,old,new):

if 'function_plus' in text.text:

	function_plus()

else:

	function_minus()

text.text = text.text.replace('button','source')

source.selected.update({"0d":{"glyph":None,"indices":[]},"1d":{"indices":[]},"2d":{"indices":{}}})

source.on_change(‘selected’,function_source)

minus.on_click(function_minus)

plus.on_click(function_plus)

layout = column(widgetbox(minus, plus, text), plot)

session = push_session(document = curdoc())

curdoc().add_root(layout)

session.show(layout)

session.loop_until_closed()

``

Here i reset the selected attribute of the source after a circle is clicked so that you can clikc the same circle several time in a row and still trigger the “selected” event.

I thought it might start an infinite loop but apparently doing source.selected.update doesn’t trigger the source.on_change(‘selected’) so it works.

⌁   Link to post
dekrion
dekrion

Cool! This is what I was after.
Thanks a lot!

from bokeh.plotting import curdoc, show, figure

from bokeh.models import ColumnDataSource

from bokeh.client import push_session

source = ColumnDataSource(data = {‘x’:[2, 5, 8], ‘y’:[5, 8, 5]})
plot = figure(tools = “tap”, title = ‘Plot’)

circles = plot.circle(x = ‘x’, y = ‘y’, size = 30, source = source)

def function_source(attr, old, new):

plot.title.text = ‘Circle index: %s’ % source.selected[“1d”][“indices”][0]

source.on_change(‘selected’, function_source)

session = push_session(document = curdoc())

curdoc().add_root(plot)

session.show()

session.loop_until_closed()

``

···

On Wednesday, July 26, 2017 at 4:27:15 PM UTC+2, Sébastien Roche wrote:

I am not really familiar with partial but to answer:

“Is there any way to call Python code when clicking on a glyph e.g. a circle?”

from bokeh.plotting import curdoc, show, figure

from bokeh.models.widgets import Button, Paragraph

from bokeh.models import CustomJS, ColumnDataSource, TapTool

from bokeh.layouts import widgetbox, column

from bokeh.client import push_session

from bokeh.events import Tap

from datetime import datetime

plot = figure(width = 400, height = 400, tools = “tap”)

source = ColumnDataSource(data={‘x’:[2, 5, 8],‘y’:[5, 8, 5]})

circles = plot.circle(x =‘x’, y = ‘y’, size = 30, source = source)

minus = Button(label = ‘-’)

plus = Button(label = ‘+’)

text = Paragraph(text = ‘.’,width=500)

def function_plus():

text.text = 'Python function “function_plus” called with button at '+str(datetime.now())

def function_minus():

text.text = 'Python function “function_minus” called with button at '+str(datetime.now())

def function_source(attr,old,new):

if ‘function_plus’ in text.text:

  function_plus()

else:

  function_minus()

text.text = text.text.replace(‘button’,‘source’)

source.selected.update({“0d”:{“glyph”:None,“indices”:},“1d”:{“indices”:},“2d”:{“indices”:{}}})

source.on_change(‘selected’,function_source)

minus.on_click(function_minus)

plus.on_click(function_plus)

layout = column(widgetbox(minus, plus, text), plot)

session = push_session(document = curdoc())

curdoc().add_root(layout)

session.show(layout)

session.loop_until_closed()

``

Here i reset the selected attribute of the source after a circle is clicked so that you can clikc the same circle several time in a row and still trigger the “selected” event.

I thought it might start an infinite loop but apparently doing source.selected.update doesn’t trigger the source.on_change(‘selected’) so it works.

⌁   Link to post
Sebastien_Roche
Sebastien_Roche

You can add this to not get an error when you click on something else than a circle

def function_source(attr, old, new):
try:
plot.title.text = ‘Circle index: %s’ % source.selected[“1d”][“indices”][0]
except IndexError:
plot.title.text = ‘Plot’

``

⌁   Link to post
dekrion
dekrion

Thank you for your great support!

···

On Wednesday, July 26, 2017 at 7:42:07 PM UTC+2, Sébastien Roche wrote:

You can add this to not get an error when you click on something else than a circle

def function_source(attr, old, new):
try:
plot.title.text = ‘Circle index: %s’ % source.selected[“1d”][“indices”][0]
except IndexError:
plot.title.text = ‘Plot’

``

⌁   Link to post
stasashdod
stasashdod

Hi Sébastien,

I would like to replicate this exact code in Jupyter Notebook. However, when I use Tap or on_click events do no appear to work. Could you please let me know what have I done wrong in the following Jupyter Code snippet?

I’m highly interested in the ability to use a Tap tool in order to tap on a single point and exectue a Python function within a running Jupyter notebook.

from bokeh.plotting import figure, show
from bokeh.io import output_notebook,push_notebook,reset_output

output_notebook()

from bokeh.models.widgets import Button, Paragraph
from bokeh.models import CustomJS, ColumnDataSource, TapTool
from bokeh.layouts import widgetbox, column
#from bokeh.client import push_session
from bokeh.events import Tap
from datetime import datetime

plot = figure(width = 400, height = 400, tools = “tap”)

source = ColumnDataSource(data={‘x’:[2, 5, 8],‘y’:[5, 8, 5]})
circles = plot.circle(x =‘x’, y = ‘y’, size = 30, source = source)

minus = Button(label = ‘-’)
plus = Button(label = ‘+’)
text = Paragraph(text = ‘.’,width=500)

def function_plus():
text.text = 'Python function “function_plus” called with button at '+str(datetime.now())

push_notebook(handle=handler)

def function_minus():
text.text = 'Python function “function_minus” called with button at '+str(datetime.now())

def function_source(attr,old,new):
if ‘function_plus’ in text.text:
function_plus()
else:
function_minus()

#text.text = text.text.replace('button','source')
text.text = text.text.replace('.','source')
source.selected.update({"0d":{"glyph":None,"indices":[]},"1d":{"indices":[]},"2d":{"indices":{}}})

push_notebook(handle=handler)

source.on_change(‘selected’,function_source)

minus.on_click(function_minus)
plus.on_click(function_plus)

layout = column(widgetbox(minus, plus, text), plot)
handler = show(layout,notebook_handle=True)

``

···

On Wednesday, July 26, 2017 at 10:27:15 AM UTC-4, Sébastien Roche wrote:

I am not really familiar with partial but to answer:

“Is there any way to call Python code when clicking on a glyph e.g. a circle?”

from bokeh.plotting import curdoc, show, figure

from bokeh.models.widgets import Button, Paragraph

from bokeh.models import CustomJS, ColumnDataSource, TapTool

from bokeh.layouts import widgetbox, column

from bokeh.client import push_session

from bokeh.events import Tap

from datetime import datetime

plot = figure(width = 400, height = 400, tools = “tap”)

source = ColumnDataSource(data={‘x’:[2, 5, 8],‘y’:[5, 8, 5]})

circles = plot.circle(x =‘x’, y = ‘y’, size = 30, source = source)

minus = Button(label = ‘-’)

plus = Button(label = ‘+’)

text = Paragraph(text = ‘.’,width=500)

def function_plus():

text.text = 'Python function “function_plus” called with button at '+str(datetime.now())

def function_minus():

text.text = 'Python function “function_minus” called with button at '+str(datetime.now())

def function_source(attr,old,new):

if ‘function_plus’ in text.text:

  function_plus()

else:

  function_minus()

text.text = text.text.replace(‘button’,‘source’)

source.selected.update({“0d”:{“glyph”:None,“indices”:},“1d”:{“indices”:},“2d”:{“indices”:{}}})

source.on_change(‘selected’,function_source)

minus.on_click(function_minus)

plus.on_click(function_plus)

layout = column(widgetbox(minus, plus, text), plot)

session = push_session(document = curdoc())

curdoc().add_root(layout)

session.show(layout)

session.loop_until_closed()

``

Here i reset the selected attribute of the source after a circle is clicked so that you can clikc the same circle several time in a row and still trigger the “selected” event.

I thought it might start an infinite loop but apparently doing source.selected.update doesn’t trigger the source.on_change(‘selected’) so it works.

⌁   Link to post
Bryan
Bryan

Hi,

on_change, on_event, etc. require using a Bokeh server (the Bokeh server *is the thing* that actually handles getting events to and from JS and python, and calls the python callbacks). You can see an example of embedding a Bokeh server app in a notebook here:

  https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/notebook_embed.ipynb

Thanks,

Bryan

···

On Aug 29, 2017, at 09:54, stasashdod@gmail.com wrote:

Hi Sébastien,

I would like to replicate this exact code in Jupyter Notebook. However, when I use Tap or on_click events do no appear to work. Could you please let me know what have I done wrong in the following Jupyter Code snippet?
I'm highly interested in the ability to use a Tap tool in order to tap on a single point and exectue a Python function within a running Jupyter notebook.

from bokeh.plotting import figure, show
from bokeh.io import output_notebook,push_notebook,reset_output

output_notebook()

from bokeh.models.widgets import Button, Paragraph
from bokeh.models import CustomJS, ColumnDataSource, TapTool
from bokeh.layouts import widgetbox, column
#from bokeh.client import push_session
from bokeh.events import Tap
from datetime import datetime

plot = figure(width = 400, height = 400, tools = "tap")

source = ColumnDataSource(data={'x':[2, 5, 8],'y':[5, 8, 5]})
circles = plot.circle(x ='x', y = 'y', size = 30, source = source)

minus = Button(label = '-')
plus = Button(label = '+')
text = Paragraph(text = '.',width=500)

def function_plus():
    text.text = 'Python function "function_plus" called with button at '+str(datetime.now())
    
    push_notebook(handle=handler)
    
def function_minus():
    text.text = 'Python function "function_minus" called with button at '+str(datetime.now())
  
def function_source(attr,old,new):
    if 'function_plus' in text.text:
        function_plus()
    else:
        function_minus()
    
    #text.text = text.text.replace('button','source')
    text.text = text.text.replace('.','source')
    source.selected.update({"0d":{"glyph":None,"indices":},"1d":{"indices":},"2d":{"indices":{}}})
    
    push_notebook(handle=handler)

source.on_change('selected',function_source)

minus.on_click(function_minus)
plus.on_click(function_plus)

layout = column(widgetbox(minus, plus, text), plot)
handler = show(layout,notebook_handle=True)

On Wednesday, July 26, 2017 at 10:27:15 AM UTC-4, Sébastien Roche wrote:
I am not really familiar with partial but to answer:

"Is there any way to call Python code when clicking on a glyph e.g. a circle?"

from bokeh.plotting import curdoc, show, figure
from bokeh.models.widgets import Button, Paragraph
from bokeh.models import CustomJS, ColumnDataSource, TapTool
from bokeh.layouts import widgetbox, column
from bokeh.client import push_session
from bokeh.events import Tap
from datetime import datetime

plot = figure(width = 400, height = 400, tools = "tap")

source = ColumnDataSource(data={'x':[2, 5, 8],'y':[5, 8, 5]})
circles = plot.circle(x ='x', y = 'y', size = 30, source = source)

minus = Button(label = '-')
plus = Button(label = '+')
text = Paragraph(text = '.',width=500)

def function_plus():
    text.text = 'Python function "function_plus" called with button at '+str(datetime.now())
    
def function_minus():
    text.text = 'Python function "function_minus" called with button at '+str(datetime.now())

def function_source(attr,old,new):
  if 'function_plus' in text.text:
    function_plus()
  else:
    function_minus()

  text.text = text.text.replace('button','source')
  source.selected.update({"0d":{"glyph":None,"indices":},"1d":{"indices":},"2d":{"indices":{}}})

source.on_change('selected',function_source)

minus.on_click(function_minus)
plus.on_click(function_plus)

layout = column(widgetbox(minus, plus, text), plot)

session = push_session(document = curdoc())
curdoc().add_root(layout)
session.show(layout)
session.loop_until_closed()

Here i reset the selected attribute of the source after a circle is clicked so that you can clikc the same circle several time in a row and still trigger the "selected" event.
I thought it might start an infinite loop but apparently doing source.selected.update doesn't trigger the source.on_change('selected') so it works.

--
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 bokeh+unsubscribe@continuum.io.
To post to this group, send email to bokeh@continuum.io.
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/3f218af3-663f-4b56-baf3-ced1c52a586a%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

⌁   Link to post
Jon_Mease
Jon_Mease

FWIW I’ve found it handy to keep a show_app function like this around (code extracted from the example notebook that Bryan linked above).

def show_app(layout):

from bokeh.application import Application

from bokeh.application.handlers import FunctionHandler
from bokeh.io import show

def modify_doc(doc):

doc.add_root(layout)

handler = FunctionHandler(modify_doc)

app = Application(handler)

return show(app)

``

You can basically swap in show_app for the standard bokeh.io.show and then the on_change, on_event, etc. callbacks will work in the notebook. If you show a layout that includes bokeh widgets then the widget callbacks will also work.

Caveats:

  • You have to be careful not to call show_app on the same figure handle more than once because it won’t show up after the first call.
  • Because the app is running in a separate thread than the main notebook kernel you can’t directly update figure properties after calling show_app (Accessing properties works fine though). You have to use the Document.add_next_tick_callback command (see http://bokeh.pydata.org/en/latest/docs/reference/document.html). I’ve wrapped this logic in a helper function called setattr_app:

def setattr_app(model, prop, val):
import functools

doc = model.document

doc.add_next_tick_callback(functools.partial(setattr, model, prop, val))

``

Example usage: setattr_app(my_line_glyph, ‘line_color’, ‘red’)

Once you have these helper functions this is a pretty nice notebook workflow. You get Python callbacks working for figures and widgets and you don’t have to keep track of figure handles or call push_notebook() when updating properties of existing figures.

Side note: Bryan, do you have any concerns with people using this approach and ending up with a few dozen app instances in a single notebook?

-Jon

···

On Thursday, August 31, 2017 at 12:31:20 PM UTC-4, Bryan Van de ven wrote:

Hi,

on_change, on_event, etc. require using a Bokeh server (the Bokeh server is the thing that actually handles getting events to and from JS and python, and calls the python callbacks). You can see an example of embedding a Bokeh server app in a notebook here:

    [https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/notebook_embed.ipynb](https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/notebook_embed.ipynb)

Thanks,

Bryan

On Aug 29, 2017, at 09:54, stasa...@gmail.com wrote:

Hi Sébastien,

I would like to replicate this exact code in Jupyter Notebook. However, when I use Tap or on_click events do no appear to work. Could you please let me know what have I done wrong in the following Jupyter Code snippet?

I’m highly interested in the ability to use a Tap tool in order to tap on a single point and exectue a Python function within a running Jupyter notebook.

from bokeh.plotting import figure, show

from bokeh.io import output_notebook,push_notebook,reset_output

output_notebook()

from bokeh.models.widgets import Button, Paragraph
from bokeh.models import CustomJS, ColumnDataSource, TapTool
from bokeh.layouts import widgetbox, column
#from bokeh.client import push_session

from bokeh.events import Tap

from datetime import datetime

plot = figure(width = 400, height = 400, tools = “tap”)

source = ColumnDataSource(data={‘x’:[2, 5, 8],‘y’:[5, 8, 5]})

circles = plot.circle(x =‘x’, y = ‘y’, size = 30, source = source)

minus = Button(label = ‘-’)
plus = Button(label = ‘+’)
text = Paragraph(text = ‘.’,width=500)

def function_plus():
text.text = 'Python function “function_plus” called with button at '+str(datetime.now())

push_notebook(handle=handler)

def function_minus():
text.text = 'Python function “function_minus” called with button at '+str(datetime.now())

def function_source(attr,old,new):

if 'function_plus' in text.text:
    function_plus()
else:
    function_minus()
#text.text = text.text.replace('button','source')
text.text = text.text.replace('.','source')
source.selected.update({"0d":{"glyph":None,"indices":[]},"1d":{"indices":[]},"2d":{"indices":{}}})
push_notebook(handle=handler)

source.on_change(‘selected’,function_source)

minus.on_click(function_minus)

plus.on_click(function_plus)

layout = column(widgetbox(minus, plus, text), plot)
handler = show(layout,notebook_handle=True)

On Wednesday, July 26, 2017 at 10:27:15 AM UTC-4, Sébastien Roche wrote:

I am not really familiar with partial but to answer:

“Is there any way to call Python code when clicking on a glyph e.g. a circle?”

from bokeh.plotting import curdoc, show, figure
from bokeh.models.widgets import Button, Paragraph
from bokeh.models import CustomJS, ColumnDataSource, TapTool
from bokeh.layouts import widgetbox, column
from bokeh.client import push_session

from bokeh.events import Tap

from datetime import datetime

plot = figure(width = 400, height = 400, tools = “tap”)

source = ColumnDataSource(data={‘x’:[2, 5, 8],‘y’:[5, 8, 5]})

circles = plot.circle(x =‘x’, y = ‘y’, size = 30, source = source)

minus = Button(label = ‘-’)
plus = Button(label = ‘+’)
text = Paragraph(text = ‘.’,width=500)

def function_plus():
text.text = 'Python function “function_plus” called with button at '+str(datetime.now())

def function_minus():
text.text = 'Python function “function_minus” called with button at '+str(datetime.now())

def function_source(attr,old,new):

    if 'function_plus' in text.text:
            function_plus()
    else:
            function_minus()
    text.text = text.text.replace('button','source')
    source.selected.update({"0d":{"glyph":None,"indices":[]},"1d":{"indices":[]},"2d":{"indices":{}}})

source.on_change(‘selected’,function_source)

minus.on_click(function_minus)

plus.on_click(function_plus)

layout = column(widgetbox(minus, plus, text), plot)

session = push_session(document = curdoc())
curdoc().add_root(layout)
session.show(layout)
session.loop_until_closed()

Here i reset the selected attribute of the source after a circle is clicked so that you can clikc the same circle several time in a row and still trigger the “selected” event.

I thought it might start an infinite loop but apparently doing source.selected.update doesn’t trigger the source.on_change(‘selected’) so it works.

–
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 bokeh+un...@continuum.io.

To post to this group, send email to bo...@continuum.io.

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/3f218af3-663f-4b56-baf3-ced1c52a586a%40continuum.io.

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

⌁   Link to post
Jorge_Eliecer_Valenc
Jorge_Eliecer_Valenc

I have the same problem but with the latest version 1.0.2, anyone knows how to make this in that version?

···

El miércoles, 26 de julio de 2017, 10:20:42 (UTC-5), Tony Halik escribió:

Cool! This is what I was after.
Thanks a lot!

from bokeh.plotting import curdoc, show, figure

from bokeh.models import ColumnDataSource

from bokeh.client import push_session

source = ColumnDataSource(data = {‘x’:[2, 5, 8], ‘y’:[5, 8, 5]})
plot = figure(tools = “tap”, title = ‘Plot’)

circles = plot.circle(x = ‘x’, y = ‘y’, size = 30, source = source)

def function_source(attr, old, new):

plot.title.text = ‘Circle index: %s’ % source.selected[“1d”][“indices”][0]

source.on_change(‘selected’, function_source)

session = push_session(document = curdoc())

curdoc().add_root(plot)

session.show()

session.loop_until_closed()

``

On Wednesday, July 26, 2017 at 4:27:15 PM UTC+2, Sébastien Roche wrote:

I am not really familiar with partial but to answer:

“Is there any way to call Python code when clicking on a glyph e.g. a circle?”

from bokeh.plotting import curdoc, show, figure

from bokeh.models.widgets import Button, Paragraph

from bokeh.models import CustomJS, ColumnDataSource, TapTool

from bokeh.layouts import widgetbox, column

from bokeh.client import push_session

from bokeh.events import Tap

from datetime import datetime

plot = figure(width = 400, height = 400, tools = “tap”)

source = ColumnDataSource(data={‘x’:[2, 5, 8],‘y’:[5, 8, 5]})

circles = plot.circle(x =‘x’, y = ‘y’, size = 30, source = source)

minus = Button(label = ‘-’)

plus = Button(label = ‘+’)

text = Paragraph(text = ‘.’,width=500)

def function_plus():

text.text = 'Python function “function_plus” called with button at '+str(datetime.now())

def function_minus():

text.text = 'Python function “function_minus” called with button at '+str(datetime.now())

def function_source(attr,old,new):

if 'function_plus' in text.text:
  function_plus()
else:
  function_minus()
text.text = text.text.replace('button','source')
source.selected.update({"0d":{"glyph":None,"indices":[]},"1d":{"indices":[]},"2d":{"indices":{}}})

source.on_change(‘selected’,function_source)

minus.on_click(function_minus)

plus.on_click(function_plus)

layout = column(widgetbox(minus, plus, text), plot)

session = push_session(document = curdoc())

curdoc().add_root(layout)

session.show(layout)

session.loop_until_closed()

``

Here i reset the selected attribute of the source after a circle is clicked so that you can clikc the same circle several time in a row and still trigger the “selected” event.

I thought it might start an infinite loop but apparently doing source.selected.update doesn’t trigger the source.on_change(‘selected’) so it works.

⌁   Link to post
Bryan
Bryan

There was some confusion and regressions around selections leading up to 1.0. For most use case you would want to use:

  source.selected.on_change('indices', function_source)

This kind of usage is now continuously maintained under integration tests.

On a tangent, please note that using "session.loop_until_closed()" is highly discouraged (I would go so far as to say it is not supported for anything except supporting testing use cases) and has been for quite a long time. It should be printing a giant multi-line warning explaining why when you call it.

Thanks,

Bryan

···

On Dec 11, 2018, at 17:06, jeliecerv@gmail.com wrote:

I have the same problem but with the latest version 1.0.2, anyone knows how to make this in that version?

El miércoles, 26 de julio de 2017, 10:20:42 (UTC-5), Tony Halik escribió:
Cool! This is what I was after.
Thanks a lot!

from bokeh.plotting import curdoc, show, figure

from bokeh.models import ColumnDataSource

from bokeh.client import push_session

source = ColumnDataSource(data = {'x':[2, 5, 8], 'y':[5, 8, 5]})
plot = figure(tools = "tap", title = 'Plot')

circles = plot.circle(x = 'x', y = 'y', size = 30, source = source)

def function_source(attr, old, new):

  plot.title.text = 'Circle index: %s' % source.selected["1d"]["indices"][0]

source.on_change('selected', function_source)

session = push_session(document = curdoc())

curdoc().add_root(plot)

session.show()

session.loop_until_closed()

On Wednesday, July 26, 2017 at 4:27:15 PM UTC+2, Sébastien Roche wrote:
I am not really familiar with partial but to answer:

"Is there any way to call Python code when clicking on a glyph e.g. a circle?"

from bokeh.plotting import curdoc, show, figure
from bokeh.models.widgets import Button, Paragraph
from bokeh.models import CustomJS, ColumnDataSource, TapTool
from bokeh.layouts import widgetbox, column
from bokeh.client import push_session
from bokeh.events import Tap
from datetime import datetime

plot = figure(width = 400, height = 400, tools = "tap")

source = ColumnDataSource(data={'x':[2, 5, 8],'y':[5, 8, 5]})
circles = plot.circle(x ='x', y = 'y', size = 30, source = source)

minus = Button(label = '-')
plus = Button(label = '+')
text = Paragraph(text = '.',width=500)

def function_plus():
    text.text = 'Python function "function_plus" called with button at '+str(datetime.now())
    
def function_minus():
    text.text = 'Python function "function_minus" called with button at '+str(datetime.now())

def function_source(attr,old,new):
  if 'function_plus' in text.text:
    function_plus()
  else:
    function_minus()

  text.text = text.text.replace('button','source')
  source.selected.update({"0d":{"glyph":None,"indices":},"1d":{"indices":},"2d":{"indices":{}}})

source.on_change('selected',function_source)

minus.on_click(function_minus)
plus.on_click(function_plus)

layout = column(widgetbox(minus, plus, text), plot)

session = push_session(document = curdoc())
curdoc().add_root(layout)
session.show(layout)
session.loop_until_closed()

Here i reset the selected attribute of the source after a circle is clicked so that you can clikc the same circle several time in a row and still trigger the "selected" event.
I thought it might start an infinite loop but apparently doing source.selected.update doesn't trigger the source.on_change('selected') so it works.

--
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 bokeh+unsubscribe@continuum.io.
To post to this group, send email to bokeh@continuum.io.
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/dc715efe-b607-4cfe-84a3-186aa8f8b33e%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

⌁   Link to post

End of archived discussion · Replies are disabled