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

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

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

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

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

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

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

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

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)[[email protected] 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)[[email protected] 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)[[email protected] 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)[[email protected] 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 [email protected] 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 [email protected] 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 [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/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 [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/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

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)[[email protected] 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)[[email protected] 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)[[email protected] 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)[[email protected] 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 [email protected] 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 [email protected] 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 [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/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 [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/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