☰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

Correct way to add callbacks to an unknown number of plots.

Community Support
Robert
Robert

Hi folks!

I’m wondering what the correct way to add interactions with callbacks to a set of different plots?

So in my specific example I have a set of plots in a tab as such

for file in files:

tabs = Tabs(tabs = list_of_plots)

radio_group = RadioGroup(labels = list_of_names, title = “title” )

text_input = = TextInput(value = “default”, title="RSF for selected element: ")

       text_input.on_change("value", ??????)

which makes len(files) set of tabs which have individual radio groups and text inputs. I store the widgets with unique id’s in a class as attributes. The plots are configured with sources as attributes of of the class aswell

My question is then, how do I set up the callbacks as denoted by the ???. I’ve thought about generating an individual function for each set in Tabs, but I’m not sure if that’s all that great an idea.

Thanks for any feedback, and I’d be happy to supply a little more detailed code to elaborate.

-Robert

⌁   Link to post
Havoc_Pennington
Havoc_Pennington

One option is to capture context with lambdas like:

def on_input_change(text_input, new):

pass

model.on_change(“foo”, lambda attr, old, new: on_input_change(input, new))

Another option is to use Document.on_change to get all changes to anything, then filter by model and attr.

Havoc

···

On Jan 28, 2016, at 3:14 PM, Robert solli.robert@gmail.com wrote:

Hi folks!

I’m wondering what the correct way to add interactions with callbacks to a set of different plots?

So in my specific example I have a set of plots in a tab as such

for file in files:

tabs = Tabs(tabs = list_of_plots)

radio_group = RadioGroup(labels = list_of_names, title = “title” )

text_input = = TextInput(value = “default”, title="RSF for selected element: ")

     text_input.on_change("value", ??????)

which makes len(files) set of tabs which have individual radio groups and text inputs. I store the widgets with unique id’s in a class as attributes. The plots are configured with sources as attributes of of the class aswell

My question is then, how do I set up the callbacks as denoted by the ???. I’ve thought about generating an individual function for each set in Tabs, but I’m not sure if that’s all that great an idea.

Thanks for any feedback, and I’d be happy to supply a little more detailed code to elaborate.

-Robert

–

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/b6883fd5-b121-43d5-9116-711bc0a9d5b1%40continuum.io.

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

⌁   Link to post
Robert
Robert

I’m trying to set up context with lambdas. However it seems like I keep overwriting the lambda functions in the for loop. The relevant code is as follows:

for attr_ind in attribute_ids:

…

		setattr(self, attr_id + "_radio_group", RadioGroup(labels = list_of_elements, active=0))

		setattr(self, attr_id + "_text_input", TextInput(value = "default", title="RSF for selected element: "))

		a = getattr(self, attr_id + "_text_input")

		a.on_change("value", lambda attr, old, new: self.update_data(attr_id, new))

		b = getattr(self, attr_id + "_radio_group")

and the function update_data looks like this

def update_data(self, attrname, new):

	radio = getattr(self, attrname + "_radio_group")

	figure = getattr(self, attrname +"_figure_obj")

	figure.title = new

fredag 29. januar 2016 02.52.43 UTC+1 skrev Havoc Pennington følgende:

···

One option is to capture context with lambdas like:

def on_input_change(text_input, new):

pass

model.on_change(“foo”, lambda attr, old, new: on_input_change(input, new))

Another option is to use Document.on_change to get all changes to anything, then filter by model and attr.

Havoc

On Jan 28, 2016, at 3:14 PM, Robert solli....@gmail.com wrote:

Hi folks!

I’m wondering what the correct way to add interactions with callbacks to a set of different plots?

So in my specific example I have a set of plots in a tab as such

for file in files:

tabs = Tabs(tabs = list_of_plots)

radio_group = RadioGroup(labels = list_of_names, title = “title” )

text_input = = TextInput(value = “default”, title="RSF for selected element: ")

     text_input.on_change("value", ??????)

which makes len(files) set of tabs which have individual radio groups and text inputs. I store the widgets with unique id’s in a class as attributes. The plots are configured with sources as attributes of of the class aswell

My question is then, how do I set up the callbacks as denoted by the ???. I’ve thought about generating an individual function for each set in Tabs, but I’m not sure if that’s all that great an idea.

Thanks for any feedback, and I’d be happy to supply a little more detailed code to elaborate.

-Robert

–

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/b6883fd5-b121-43d5-9116-711bc0a9d5b1%40continuum.io.

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

⌁   Link to post
Robert
Robert

I sent the above message a little too quick. The figure elements are stored in the class as such:

		figure_obj = figure(plot_width = 1000, plot_height = 800, y_axis_type = "log", title = "this is a thing")

		setattr(self, attr_id + "_figure_obj" ,figure_obj)

Lastly. Thank you for all help, it is very much appreciated.

fredag 29. januar 2016 16.56.11 UTC+1 skrev Robert følgende:

···

I’m trying to set up context with lambdas. However it seems like I keep overwriting the lambda functions in the for loop. The relevant code is as follows:

for attr_ind in attribute_ids:

…

  	setattr(self, attr_id + "_radio_group", RadioGroup(labels = list_of_elements, active=0))
  	setattr(self, attr_id + "_text_input", TextInput(value = "default", title="RSF for selected element: "))
  	a = getattr(self, attr_id + "_text_input")
  	a.on_change("value", lambda attr, old, new: self.update_data(attr_id, new))
  	b = getattr(self, attr_id + "_radio_group")

and the function update_data looks like this

def update_data(self, attrname, new):

  radio = getattr(self, attrname + "_radio_group")
  figure = getattr(self, attrname +"_figure_obj")
  figure.title = new

fredag 29. januar 2016 02.52.43 UTC+1 skrev Havoc Pennington følgende:

One option is to capture context with lambdas like:

def on_input_change(text_input, new):

pass

model.on_change(“foo”, lambda attr, old, new: on_input_change(input, new))

Another option is to use Document.on_change to get all changes to anything, then filter by model and attr.

Havoc

On Jan 28, 2016, at 3:14 PM, Robert solli....@gmail.com wrote:

Hi folks!

I’m wondering what the correct way to add interactions with callbacks to a set of different plots?

So in my specific example I have a set of plots in a tab as such

for file in files:

tabs = Tabs(tabs = list_of_plots)

radio_group = RadioGroup(labels = list_of_names, title = “title” )

text_input = = TextInput(value = “default”, title="RSF for selected element: ")

     text_input.on_change("value", ??????)

which makes len(files) set of tabs which have individual radio groups and text inputs. I store the widgets with unique id’s in a class as attributes. The plots are configured with sources as attributes of of the class aswell

My question is then, how do I set up the callbacks as denoted by the ???. I’ve thought about generating an individual function for each set in Tabs, but I’m not sure if that’s all that great an idea.

Thanks for any feedback, and I’d be happy to supply a little more detailed code to elaborate.

-Robert

–

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/b6883fd5-b121-43d5-9116-711bc0a9d5b1%40continuum.io.

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

⌁   Link to post
Havoc_Pennington
Havoc_Pennington

Hi,

I’m not sure what’s going wrong … (do you need to store everything as an attribute like that? it maybe makes things more complex)

but anyway, this works afaik:

(py3)[hp@localhost tmp]$ cat /tmp/foo.py
from future import print_function

def callback(n):
print(n)

def call_callback(cb):
cb()

for i in [1,2,3,4,5]:
call_callback(lambda: callback(i))

(py3)[hp@localhost tmp]$ python foo.py
1
2
3
4
5

So that was my suggestion more or less, with bokeh models instead of integers of course.

Even simpler option, possibly slightly less memory-efficient but maybe not, depends on how python is implemented:

(py3)[hp@localhost tmp]$ cat /tmp/bar.py
from future import print_function

def call_callback(cb):
cb()

for i in [1,2,3,4,5]:
def callback():
print(i)
call_callback(callback)

(py3)[hp@localhost tmp]$ python bar.py
1
2
3
4
5

Maybe I’m missing something about what you’re asking?

Havoc

···

On Fri, Jan 29, 2016 at 10:56 AM, Robert solli.robert@gmail.com wrote:

I’m trying to set up context with lambdas. However it seems like I keep overwriting the lambda functions in the for loop. The relevant code is as follows:

for attr_ind in attribute_ids:

…

  	setattr(self, attr_id + "_radio_group", RadioGroup(labels = list_of_elements, active=0))
  	setattr(self, attr_id + "_text_input", TextInput(value = "default", title="RSF for selected element: "))
  	a = getattr(self, attr_id + "_text_input")
  	a.on_change("value", lambda attr, old, new: self.update_data(attr_id, new))
  	b = getattr(self, attr_id + "_radio_group")

and the function update_data looks like this

def update_data(self, attrname, new):

  radio = getattr(self, attrname + "_radio_group")
  figure = getattr(self, attrname +"_figure_obj")
  figure.title = new

fredag 29. januar 2016 02.52.43 UTC+1 skrev Havoc Pennington følgende:

One option is to capture context with lambdas like:

def on_input_change(text_input, new):

pass

model.on_change(“foo”, lambda attr, old, new: on_input_change(input, new))

Another option is to use Document.on_change to get all changes to anything, then filter by model and attr.

Havoc

On Jan 28, 2016, at 3:14 PM, Robert solli....@gmail.com wrote:

Hi folks!

I’m wondering what the correct way to add interactions with callbacks to a set of different plots?

So in my specific example I have a set of plots in a tab as such

for file in files:

tabs = Tabs(tabs = list_of_plots)

radio_group = RadioGroup(labels = list_of_names, title = “title” )

text_input = = TextInput(value = “default”, title="RSF for selected element: ")

     text_input.on_change("value", ??????)

which makes len(files) set of tabs which have individual radio groups and text inputs. I store the widgets with unique id’s in a class as attributes. The plots are configured with sources as attributes of of the class aswell

My question is then, how do I set up the callbacks as denoted by the ???. I’ve thought about generating an individual function for each set in Tabs, but I’m not sure if that’s all that great an idea.

Thanks for any feedback, and I’d be happy to supply a little more detailed code to elaborate.

-Robert

–

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/b6883fd5-b121-43d5-9116-711bc0a9d5b1%40continuum.io.

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 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/08cc06ec-aa3f-40b5-b9c2-353e8c3ce6e7%40continuum.io.

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

–

Havoc Pennington

Senior Software Architect

[External image unavailable in archive]

⌁   Link to post
Robert
Robert

Probably correct on the attributes, it was the best idea I had at the moment.

The problem I think arises is one of scope. As in your example you call the function for each iteration in the loop. However in mine I’m running the entire loop - then pushing to the server. Which means that probably the lambda looks to the parent scope of when it’s executed - i.e the last iteration. And not the one in which it is defined.

To reiterate, my code doesn’t work because I think(?) the callback isn’t executed before after the last loop. I think the problem can be circumvented by assigning the value as a keyword argument, but I’m not sure how to implement that with Bokeh callbacks.

Thanks again for your time

-Robert

lørdag 30. januar 2016 17.09.43 UTC+1 skrev Havoc Pennington følgende:

···

Hi,

I’m not sure what’s going wrong … (do you need to store everything as an attribute like that? it maybe makes things more complex)

but anyway, this works afaik:

(py3)[hp@localhost tmp]$ cat /tmp/foo.py
from future import print_function

def callback(n):
print(n)

def call_callback(cb):
cb()

for i in [1,2,3,4,5]:
call_callback(lambda: callback(i))

(py3)[hp@localhost tmp]$ python foo.py
1
2
3
4
5

So that was my suggestion more or less, with bokeh models instead of integers of course.

Even simpler option, possibly slightly less memory-efficient but maybe not, depends on how python is implemented:

(py3)[hp@localhost tmp]$ cat /tmp/bar.py
from future import print_function

def call_callback(cb):
cb()

for i in [1,2,3,4,5]:
def callback():
print(i)
call_callback(callback)

(py3)[hp@localhost tmp]$ python bar.py
1
2
3
4
5

Maybe I’m missing something about what you’re asking?

Havoc

On Fri, Jan 29, 2016 at 10:56 AM, Robert solli....@gmail.com wrote:

I’m trying to set up context with lambdas. However it seems like I keep overwriting the lambda functions in the for loop. The relevant code is as follows:

for attr_ind in attribute_ids:

…

  	setattr(self, attr_id + "_radio_group", RadioGroup(labels = list_of_elements, active=0))
  	setattr(self, attr_id + "_text_input", TextInput(value = "default", title="RSF for selected element: "))
  	a = getattr(self, attr_id + "_text_input")
  	a.on_change("value", lambda attr, old, new: self.update_data(attr_id, new))
  	b = getattr(self, attr_id + "_radio_group")

and the function update_data looks like this

def update_data(self, attrname, new):
  radio = getattr(self, attrname + "_radio_group")
  figure = getattr(self, attrname +"_figure_obj")
  figure.title = new

fredag 29. januar 2016 02.52.43 UTC+1 skrev Havoc Pennington følgende:

One option is to capture context with lambdas like:

def on_input_change(text_input, new):

pass

model.on_change(“foo”, lambda attr, old, new: on_input_change(input, new))

Another option is to use Document.on_change to get all changes to anything, then filter by model and attr.

Havoc

On Jan 28, 2016, at 3:14 PM, Robert solli....@gmail.com wrote:

Hi folks!

I’m wondering what the correct way to add interactions with callbacks to a set of different plots?

So in my specific example I have a set of plots in a tab as such

for file in files:

tabs = Tabs(tabs = list_of_plots)

radio_group = RadioGroup(labels = list_of_names, title = “title” )

text_input = = TextInput(value = “default”, title="RSF for selected element: ")

     text_input.on_change("value", ??????)

which makes len(files) set of tabs which have individual radio groups and text inputs. I store the widgets with unique id’s in a class as attributes. The plots are configured with sources as attributes of of the class aswell

My question is then, how do I set up the callbacks as denoted by the ???. I’ve thought about generating an individual function for each set in Tabs, but I’m not sure if that’s all that great an idea.

Thanks for any feedback, and I’d be happy to supply a little more detailed code to elaborate.

-Robert

–

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/b6883fd5-b121-43d5-9116-711bc0a9d5b1%40continuum.io.

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 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/08cc06ec-aa3f-40b5-b9c2-353e8c3ce6e7%40continuum.io.

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

–
Havoc Pennington

Senior Software Architect

⌁   Link to post

End of archived discussion · Replies are disabled