callback on renderer visibility (using Legend with click_policy)

Hello,
is there a way to attach a callback when clicking on a legend item ?

A single renderer is attached to the LegendItem and the click policy is changing the attribute :

renderer.visible

from False to True or vice-versa.

I am thinking of

renderer.on_change(‘visible’,cb)

But cb is never called.

Maybe this could be implemented through bokeh.events ???

Feature request on GitHub ?

thx

This does actually call a javascript callback on clicking a LegendItem with renderer r :

r.js_on_change(‘change:visible’,CustomJS(code=""“console.log(‘renderer callback’,cb_obj);”"")

But yes, no call to a python callback

Just to be clear, you tried the python callback in a bokeh server app? python callback only function in the context of a running bokeh server.

Thanks,

Bryan

···

On Apr 21, 2017, at 03:48, chupach <[email protected]> wrote:

This does actually call a javascript callback on clicking a LegendItem with renderer r :

r.js_on_change('change:visible',CustomJS(code="""console.log('renderer callback',cb_obj);""")

But yes, no call to a python callback

--
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/b7d84caa-e57d-4b9d-89f8-89175e9de505%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

yes exactly. The bokeh server app often provides the functionality "on_change" on the python side, but seemingly not so for glyphrenderer.
JS code (js_on_change) works well though

Thx,

···

On 22 Apr 2017, at 23:32, Bryan Van de ven <[email protected]> wrote:

Just to be clear, you tried the python callback in a bokeh server app? python callback only function in the context of a running bokeh server.

Thanks,

Bryan

On Apr 21, 2017, at 03:48, chupach <[email protected]> wrote:

This does actually call a javascript callback on clicking a LegendItem with renderer r :

r.js_on_change('change:visible',CustomJS(code="""console.log('renderer callback',cb_obj);""")

But yes, no call to a python callback

--
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/b7d84caa-e57d-4b9d-89f8-89175e9de505%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/8B4DDF96-0DEE-4213-937A-2A8440B7423B%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

Offhand I can't think o any reason that should be. Can you provide a complete example to reproduce the problem for me to check out?

Thanks,

Bryan

···

On Apr 22, 2017, at 16:51, m r <[email protected]> wrote:

yes exactly. The bokeh server app often provides the functionality "on_change" on the python side, but seemingly not so for glyphrenderer.
JS code (js_on_change) works well though

Thx,

On 22 Apr 2017, at 23:32, Bryan Van de ven <[email protected]> wrote:

Just to be clear, you tried the python callback in a bokeh server app? python callback only function in the context of a running bokeh server.

Thanks,

Bryan

On Apr 21, 2017, at 03:48, chupach <[email protected]> wrote:

This does actually call a javascript callback on clicking a LegendItem with renderer r :

r.js_on_change('change:visible',CustomJS(code="""console.log('renderer callback',cb_obj);""")

But yes, no call to a python callback

--
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/b7d84caa-e57d-4b9d-89f8-89175e9de505%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/8B4DDF96-0DEE-4213-937A-2A8440B7423B%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/C5FC72E8-6D12-4F7D-95CD-2020780EB118%40gmail.com\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

thanks Bryan,
seems it is always a good idea to make a simple example as below.

Force is to admit that the python callback works properly in this simple case.

Which does not solve my problem then, as it does not work in our larger framework and likely not that simple to track down.

Maybe at the origin of the problem, the fact that LegendItem’s are dynamically added/removed from Legend on user choice (but that would be weird).

Further investigation needed.

Thx.

from bokeh.io import curdoc

from bokeh.models import CustomJS

from bokeh.plotting import figure

from bokeh.models import Legend,LegendItem

p = figure(plot_width=800, plot_height=250)

s=p.line([1,2,3],[3,2,1],legend=‘down’,name=‘gr_s’)

leg = p.legend[0]

leg.click_policy=“hide”

item = leg.items[0]

js_callback_gr = CustomJS(code=“”“console.log(‘callback gr’,cb_obj);”“”)

s.js_on_change(‘visible’,js_callback_gr)

def callback_gr(attr,old,new):

print(‘renderer changed’,attr,old,new)

s.on_change(‘visible’,callback_gr)

curdoc().add_root(p)

···

On 22 Apr 2017, at 23:53, Bryan Van de ven [email protected] wrote:

Offhand I can’t think o any reason that should be. Can you provide a complete example to reproduce the problem for me to check out?

Thanks,

Bryan

On Apr 22, 2017, at 16:51, m r [email protected] wrote:

yes exactly. The bokeh server app often provides the functionality “on_change” on the python side, but seemingly not so for glyphrenderer.
JS code (js_on_change) works well though

Thx,

On 22 Apr 2017, at 23:32, Bryan Van de ven [email protected] wrote:

Just to be clear, you tried the python callback in a bokeh server app? python callback only function in the context of a running bokeh server.

Thanks,

Bryan

On Apr 21, 2017, at 03:48, chupach [email protected] wrote:

This does actually call a javascript callback on clicking a LegendItem with renderer r :

r.js_on_change(‘change:visible’,CustomJS(code=“”“console.log(‘renderer callback’,cb_obj);”“”)

But yes, no call to a python callback


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/b7d84caa-e57d-4b9d-89f8-89175e9de505%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/8B4DDF96-0DEE-4213-937A-2A8440B7423B%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/C5FC72E8-6D12-4F7D-95CD-2020780EB118%40gmail.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/CD3381ED-1FA6-4F43-AA4F-7230EB9B7EF4%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Hello,

here below is a simple app illustrating several problems we’re facing with dynamic legend items.

A figure with a plot and an empty Legend. A LegendItem can be added dynamically and clicked with hide policy, or removed (Toggle widget).

At first (sometimes), everything works well, sometimes for several rounds of toggling on/off the LegendItem and clicking on it, until it does not anymore:

  • when toggling on (the line is visible), the LegendItem is faded : It is disconnected from the line. Sometime toggling off and back on when line is disconnected revives the app.

  • sometimes, clicking the LegendItem stops acting on the line visibility

  • sometimes, the line gets lost (clicking on LegendItem and then removing the LegendItem), no way to recover.

  • In above cases, renderer callbacks are not working anymore.

Moreover, as a constant, when toggling, the plot does not refresh automatically in order to show the Legend.

Any help would be really appreciated, not sure what the issue is, maybe legends are not yet fully mature and a bit buggy, or we are misusing them. But this instable behaviour somehow means that it should be in principle possible to reliably implement this app.

code below

Thx

from bokeh.io import curdoc

from bokeh.models import CustomJS,ColumnDataSource

from bokeh.layouts import layout,row,column

from bokeh.plotting import figure

from bokeh.models import Legend,LegendItem

from bokeh.models.widgets import Toggle

b = Toggle(label=‘add/remove leg’)

source = ColumnDataSource(dict(index=[0,1,2],x=[1,2,3],dn=[3,2,1]))

p = figure(plot_width=800, plot_height=250)

r_dn = p.line(x=‘x’,y=‘dn’,legend=‘down’,name=‘gr_dn’,source=source)

leg = p.legend[0]

leg.items.pop()

leg.location = ‘top_right’

leg.click_policy=“hide”

leg.inactive_fill_alpha={‘value’: 0.8}

leg.inactive_fill_color={‘value’: ‘white’}

def b_cb(x):

print(‘toggle’,x)

if x:

li = LegendItem(label=‘down’,renderers=[r_dn])

p.legend[0].items.append(li)

else:

p.legend[0].items.pop()

b.on_click(lambda x: b_cb(x))

js_callback_gr = CustomJS(code=“”“console.log(‘callback gr’,cb_obj);”“”)

r_dn.js_on_change(‘visible’,js_callback_gr)

def callback_gr(attr,old,new):

print(‘renderer changed’,attr,old,new)

r_dn.on_change(‘visible’,callback_gr)

curdoc().add_root(column(b,p))

···

On Sunday, April 23, 2017 at 1:17:32 AM UTC+2, chupach wrote:

thanks Bryan,
seems it is always a good idea to make a simple example as below.

Force is to admit that the python callback works properly in this simple case.

Which does not solve my problem then, as it does not work in our larger framework and likely not that simple to track down.

Maybe at the origin of the problem, the fact that LegendItem’s are dynamically added/removed from Legend on user choice (but that would be weird).

Further investigation needed.

Thx.

from bokeh.io import curdoc

from bokeh.models import CustomJS

from bokeh.plotting import figure

from bokeh.models import Legend,LegendItem

p = figure(plot_width=800, plot_height=250)

s=p.line([1,2,3],[3,2,1],legend=‘down’,name=‘gr_s’)

leg = p.legend[0]

leg.click_policy=“hide”

item = leg.items[0]

js_callback_gr = CustomJS(code=“”“console.log(‘callback gr’,cb_obj);”“”)

s.js_on_change(‘visible’,js_callback_gr)

def callback_gr(attr,old,new):

print(‘renderer changed’,attr,old,new)

s.on_change(‘visible’,callback_gr)

curdoc().add_root(p)

On 22 Apr 2017, at 23:53, Bryan Van de ven [email protected] wrote:

Offhand I can’t think o any reason that should be. Can you provide a complete example to reproduce the problem for me to check out?

Thanks,

Bryan

On Apr 22, 2017, at 16:51, m r [email protected] wrote:

yes exactly. The bokeh server app often provides the functionality “on_change” on the python side, but seemingly not so for glyphrenderer.
JS code (js_on_change) works well though

Thx,

On 22 Apr 2017, at 23:32, Bryan Van de ven [email protected] wrote:

Just to be clear, you tried the python callback in a bokeh server app? python callback only function in the context of a running bokeh server.

Thanks,

Bryan

On Apr 21, 2017, at 03:48, chupach [email protected] wrote:

This does actually call a javascript callback on clicking a LegendItem with renderer r :

r.js_on_change(‘change:visible’,CustomJS(code=“”“console.log(‘renderer callback’,cb_obj);”“”)

But yes, no call to a python callback


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/b7d84caa-e57d-4b9d-89f8-89175e9de505%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/8B4DDF96-0DEE-4213-937A-2A8440B7423B%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/C5FC72E8-6D12-4F7D-95CD-2020780EB118%40gmail.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/CD3381ED-1FA6-4F43-AA4F-7230EB9B7EF4%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Digging further and tracking down this faulty behaviour issue (disconnected LegendItem from renderer when dynamically added), I looked at the Legend object in the js console after we add to it a LegendItem object.

It appears that:

Legend.changed.items[0].renderers[0] = {type: “GlyphRenderer”, id: “c18880eb-1602-4710-b207-29573a9c7c32”, visible: false}

i.e. it is somehow corrupted: a dict instead of a renderer object.

On the other hand, when the LegendItem is properly connected to the renderer, we have:

Legend.changed.items[0].renderers[0] = [e]

where e is a renderer object as expected.

···

On Sunday, April 23, 2017 at 2:58:24 PM UTC+2, chupach wrote:

Hello,

here below is a simple app illustrating several problems we’re facing with dynamic legend items.

A figure with a plot and an empty Legend. A LegendItem can be added dynamically and clicked with hide policy, or removed (Toggle widget).

At first (sometimes), everything works well, sometimes for several rounds of toggling on/off the LegendItem and clicking on it, until it does not anymore:

  • when toggling on (the line is visible), the LegendItem is faded : It is disconnected from the line. Sometime toggling off and back on when line is disconnected revives the app.
  • sometimes, clicking the LegendItem stops acting on the line visibility
  • sometimes, the line gets lost (clicking on LegendItem and then removing the LegendItem), no way to recover.
  • In above cases, renderer callbacks are not working anymore.

Moreover, as a constant, when toggling, the plot does not refresh automatically in order to show the Legend.

Any help would be really appreciated, not sure what the issue is, maybe legends are not yet fully mature and a bit buggy, or we are misusing them. But this instable behaviour somehow means that it should be in principle possible to reliably implement this app.

code below

Thx

from bokeh.io import curdoc

from bokeh.models import CustomJS,ColumnDataSource

from bokeh.layouts import layout,row,column

from bokeh.plotting import figure

from bokeh.models import Legend,LegendItem

from bokeh.models.widgets import Toggle

b = Toggle(label=‘add/remove leg’)

source = ColumnDataSource(dict(index=[0,1,2],x=[1,2,3],dn=[3,2,1]))

p = figure(plot_width=800, plot_height=250)

r_dn = p.line(x=‘x’,y=‘dn’,legend=‘down’,name=‘gr_dn’,source=source)

leg = p.legend[0]

leg.items.pop()

leg.location = ‘top_right’

leg.click_policy=“hide”

leg.inactive_fill_alpha={‘value’: 0.8}

leg.inactive_fill_color={‘value’: ‘white’}

def b_cb(x):

print(‘toggle’,x)

if x:

li = LegendItem(label=‘down’,renderers=[r_dn])

p.legend[0].items.append(li)

else:

p.legend[0].items.pop()

b.on_click(lambda x: b_cb(x))

js_callback_gr = CustomJS(code=“”“console.log(‘callback gr’,cb_obj);”“”)

r_dn.js_on_change(‘visible’,js_callback_gr)

def callback_gr(attr,old,new):

print(‘renderer changed’,attr,old,new)

r_dn.on_change(‘visible’,callback_gr)

curdoc().add_root(column(b,p))

On Sunday, April 23, 2017 at 1:17:32 AM UTC+2, chupach wrote:

thanks Bryan,
seems it is always a good idea to make a simple example as below.

Force is to admit that the python callback works properly in this simple case.

Which does not solve my problem then, as it does not work in our larger framework and likely not that simple to track down.

Maybe at the origin of the problem, the fact that LegendItem’s are dynamically added/removed from Legend on user choice (but that would be weird).

Further investigation needed.

Thx.

from bokeh.io import curdoc

from bokeh.models import CustomJS

from bokeh.plotting import figure

from bokeh.models import Legend,LegendItem

p = figure(plot_width=800, plot_height=250)

s=p.line([1,2,3],[3,2,1],legend=‘down’,name=‘gr_s’)

leg = p.legend[0]

leg.click_policy=“hide”

item = leg.items[0]

js_callback_gr = CustomJS(code=“”“console.log(‘callback gr’,cb_obj);”“”)

s.js_on_change(‘visible’,js_callback_gr)

def callback_gr(attr,old,new):

print(‘renderer changed’,attr,old,new)

s.on_change(‘visible’,callback_gr)

curdoc().add_root(p)

On 22 Apr 2017, at 23:53, Bryan Van de ven [email protected] wrote:

Offhand I can’t think o any reason that should be. Can you provide a complete example to reproduce the problem for me to check out?

Thanks,

Bryan

On Apr 22, 2017, at 16:51, m r [email protected] wrote:

yes exactly. The bokeh server app often provides the functionality “on_change” on the python side, but seemingly not so for glyphrenderer.
JS code (js_on_change) works well though

Thx,

On 22 Apr 2017, at 23:32, Bryan Van de ven [email protected] wrote:

Just to be clear, you tried the python callback in a bokeh server app? python callback only function in the context of a running bokeh server.

Thanks,

Bryan

On Apr 21, 2017, at 03:48, chupach [email protected] wrote:

This does actually call a javascript callback on clicking a LegendItem with renderer r :

r.js_on_change(‘change:visible’,CustomJS(code=“”“console.log(‘renderer callback’,cb_obj);”“”)

But yes, no call to a python callback


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/b7d84caa-e57d-4b9d-89f8-89175e9de505%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/8B4DDF96-0DEE-4213-937A-2A8440B7423B%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/C5FC72E8-6D12-4F7D-95CD-2020780EB118%40gmail.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/CD3381ED-1FA6-4F43-AA4F-7230EB9B7EF4%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

and an inelegant way to cure it might be to explicitly set again the renderer array of LegendItem after declaring it.

···

On Monday, April 24, 2017 at 8:03:45 PM UTC+2, chupach wrote:

Digging further and tracking down this faulty behaviour issue (disconnected LegendItem from renderer when dynamically added), I looked at the Legend object in the js console after we add to it a LegendItem object.

It appears that:

Legend.changed.items[0].renderers[0] = {type: “GlyphRenderer”, id: “c18880eb-1602-4710-b207-29573a9c7c32”, visible: false}

i.e. it is somehow corrupted: a dict instead of a renderer object.

On the other hand, when the LegendItem is properly connected to the renderer, we have:

Legend.changed.items[0].renderers[0] = [e]

where e is a renderer object as expected.

On Sunday, April 23, 2017 at 2:58:24 PM UTC+2, chupach wrote:

Hello,

here below is a simple app illustrating several problems we’re facing with dynamic legend items.

A figure with a plot and an empty Legend. A LegendItem can be added dynamically and clicked with hide policy, or removed (Toggle widget).

At first (sometimes), everything works well, sometimes for several rounds of toggling on/off the LegendItem and clicking on it, until it does not anymore:

  • when toggling on (the line is visible), the LegendItem is faded : It is disconnected from the line. Sometime toggling off and back on when line is disconnected revives the app.
  • sometimes, clicking the LegendItem stops acting on the line visibility
  • sometimes, the line gets lost (clicking on LegendItem and then removing the LegendItem), no way to recover.
  • In above cases, renderer callbacks are not working anymore.

Moreover, as a constant, when toggling, the plot does not refresh automatically in order to show the Legend.

Any help would be really appreciated, not sure what the issue is, maybe legends are not yet fully mature and a bit buggy, or we are misusing them. But this instable behaviour somehow means that it should be in principle possible to reliably implement this app.

code below

Thx

from bokeh.io import curdoc

from bokeh.models import CustomJS,ColumnDataSource

from bokeh.layouts import layout,row,column

from bokeh.plotting import figure

from bokeh.models import Legend,LegendItem

from bokeh.models.widgets import Toggle

b = Toggle(label=‘add/remove leg’)

source = ColumnDataSource(dict(index=[0,1,2],x=[1,2,3],dn=[3,2,1]))

p = figure(plot_width=800, plot_height=250)

r_dn = p.line(x=‘x’,y=‘dn’,legend=‘down’,name=‘gr_dn’,source=source)

leg = p.legend[0]

leg.items.pop()

leg.location = ‘top_right’

leg.click_policy=“hide”

leg.inactive_fill_alpha={‘value’: 0.8}

leg.inactive_fill_color={‘value’: ‘white’}

def b_cb(x):

print(‘toggle’,x)

if x:

li = LegendItem(label=‘down’,renderers=[r_dn])

p.legend[0].items.append(li)

else:

p.legend[0].items.pop()

b.on_click(lambda x: b_cb(x))

js_callback_gr = CustomJS(code=“”“console.log(‘callback gr’,cb_obj);”“”)

r_dn.js_on_change(‘visible’,js_callback_gr)

def callback_gr(attr,old,new):

print(‘renderer changed’,attr,old,new)

r_dn.on_change(‘visible’,callback_gr)

curdoc().add_root(column(b,p))

On Sunday, April 23, 2017 at 1:17:32 AM UTC+2, chupach wrote:

thanks Bryan,
seems it is always a good idea to make a simple example as below.

Force is to admit that the python callback works properly in this simple case.

Which does not solve my problem then, as it does not work in our larger framework and likely not that simple to track down.

Maybe at the origin of the problem, the fact that LegendItem’s are dynamically added/removed from Legend on user choice (but that would be weird).

Further investigation needed.

Thx.

from bokeh.io import curdoc

from bokeh.models import CustomJS

from bokeh.plotting import figure

from bokeh.models import Legend,LegendItem

p = figure(plot_width=800, plot_height=250)

s=p.line([1,2,3],[3,2,1],legend=‘down’,name=‘gr_s’)

leg = p.legend[0]

leg.click_policy=“hide”

item = leg.items[0]

js_callback_gr = CustomJS(code=“”“console.log(‘callback gr’,cb_obj);”“”)

s.js_on_change(‘visible’,js_callback_gr)

def callback_gr(attr,old,new):

print(‘renderer changed’,attr,old,new)

s.on_change(‘visible’,callback_gr)

curdoc().add_root(p)

On 22 Apr 2017, at 23:53, Bryan Van de ven [email protected] wrote:

Offhand I can’t think o any reason that should be. Can you provide a complete example to reproduce the problem for me to check out?

Thanks,

Bryan

On Apr 22, 2017, at 16:51, m r [email protected] wrote:

yes exactly. The bokeh server app often provides the functionality “on_change” on the python side, but seemingly not so for glyphrenderer.
JS code (js_on_change) works well though

Thx,

On 22 Apr 2017, at 23:32, Bryan Van de ven [email protected] wrote:

Just to be clear, you tried the python callback in a bokeh server app? python callback only function in the context of a running bokeh server.

Thanks,

Bryan

On Apr 21, 2017, at 03:48, chupach [email protected] wrote:

This does actually call a javascript callback on clicking a LegendItem with renderer r :

r.js_on_change(‘change:visible’,CustomJS(code=“”“console.log(‘renderer callback’,cb_obj);”“”)

But yes, no call to a python callback


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/b7d84caa-e57d-4b9d-89f8-89175e9de505%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/8B4DDF96-0DEE-4213-937A-2A8440B7423B%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/C5FC72E8-6D12-4F7D-95CD-2020780EB118%40gmail.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/CD3381ED-1FA6-4F43-AA4F-7230EB9B7EF4%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

It seems like it might be a bug then, I'd suggest at this point a GH issue would be the best place to collect and track this information.

Thanks,

Bryan

···

On Apr 24, 2017, at 13:06, chupach <[email protected]> wrote:

and an inelegant way to cure it might be to explicitly set again the renderer array of LegendItem after declaring it.

On Monday, April 24, 2017 at 8:03:45 PM UTC+2, chupach wrote:
Digging further and tracking down this faulty behaviour issue (disconnected LegendItem from renderer when dynamically added), I looked at the Legend object in the js console after we add to it a LegendItem object.
It appears that:

Legend.changed.items[0].renderers[0] = {type: "GlyphRenderer", id: "c18880eb-1602-4710-b207-29573a9c7c32", visible: false}

i.e. it is somehow corrupted: a dict instead of a renderer object.

On the other hand, when the LegendItem is properly connected to the renderer, we have:

Legend.changed.items[0].renderers[0] = [e]

where e is a renderer object as expected.

On Sunday, April 23, 2017 at 2:58:24 PM UTC+2, chupach wrote:
Hello,

here below is a simple app illustrating several problems we're facing with dynamic legend items.

A figure with a plot and an empty Legend. A LegendItem can be added dynamically and clicked with hide policy, or removed (Toggle widget).

At first (sometimes), everything works well, sometimes for several rounds of toggling on/off the LegendItem and clicking on it, until it does not anymore:
- when toggling on (the line is visible), the LegendItem is faded : It is disconnected from the line. Sometime toggling off and back on when line is disconnected revives the app.
- sometimes, clicking the LegendItem stops acting on the line visibility
- sometimes, the line gets lost (clicking on LegendItem and then removing the LegendItem), no way to recover.
- In above cases, renderer callbacks are not working anymore.

Moreover, as a constant, when toggling, the plot does not refresh automatically in order to show the Legend.

Any help would be really appreciated, not sure what the issue is, maybe legends are not yet fully mature and a bit buggy, or we are misusing them. But this instable behaviour somehow means that it should be in principle possible to reliably implement this app.

code below

Thx

from bokeh.io import curdoc
from bokeh.models import CustomJS,ColumnDataSource
from bokeh.layouts import layout,row,column
from bokeh.plotting import figure
from bokeh.models import Legend,LegendItem
from bokeh.models.widgets import Toggle

b = Toggle(label='add/remove leg')

source = ColumnDataSource(dict(index=[0,1,2],x=[1,2,3],dn=[3,2,1]))
p = figure(plot_width=800, plot_height=250)
r_dn = p.line(x='x',y='dn',legend='down',name='gr_dn',source=source)

leg = p.legend[0]
leg.items.pop()
leg.location = 'top_right'
leg.click_policy="hide"
leg.inactive_fill_alpha={'value': 0.8}
leg.inactive_fill_color={'value': 'white'}

def b_cb(x):
    print('toggle',x)
    if x:
        li = LegendItem(label='down',renderers=[r_dn])
        p.legend[0].items.append(li)
    else:
        p.legend[0].items.pop()

b.on_click(lambda x: b_cb(x))

js_callback_gr = CustomJS(code="""console.log('callback gr',cb_obj);""")
r_dn.js_on_change('visible',js_callback_gr)

def callback_gr(attr,old,new):
     print('renderer changed',attr,old,new)
r_dn.on_change('visible',callback_gr)

curdoc().add_root(column(b,p))

On Sunday, April 23, 2017 at 1:17:32 AM UTC+2, chupach wrote:
thanks Bryan,
seems it is always a good idea to make a simple example as below.
Force is to admit that the python callback works properly in this simple case.

Which does not solve my problem then, as it does not work in our larger framework and likely not that simple to track down.
Maybe at the origin of the problem, the fact that LegendItem's are dynamically added/removed from Legend on user choice (but that would be weird).
Further investigation needed.

Thx.

from bokeh.io import curdoc
from bokeh.models import CustomJS
from bokeh.plotting import figure
from bokeh.models import Legend,LegendItem

p = figure(plot_width=800, plot_height=250)
s=p.line([1,2,3],[3,2,1],legend='down',name='gr_s')

leg = p.legend[0]
leg.click_policy="hide"

item = leg.items[0]

js_callback_gr = CustomJS(code="""console.log('callback gr',cb_obj);""")
s.js_on_change('visible',js_callback_gr)

def callback_gr(attr,old,new):
     print('renderer changed',attr,old,new)
s.on_change('visible',callback_gr)

curdoc().add_root(p)

On 22 Apr 2017, at 23:53, Bryan Van de ven <[email protected]> wrote:

Offhand I can't think o any reason that should be. Can you provide a complete example to reproduce the problem for me to check out?

Thanks,

Bryan

On Apr 22, 2017, at 16:51, m r <[email protected]> wrote:

yes exactly. The bokeh server app often provides the functionality "on_change" on the python side, but seemingly not so for glyphrenderer.
JS code (js_on_change) works well though

Thx,

On 22 Apr 2017, at 23:32, Bryan Van de ven <[email protected]> wrote:

Just to be clear, you tried the python callback in a bokeh server app? python callback only function in the context of a running bokeh server.

Thanks,

Bryan

On Apr 21, 2017, at 03:48, chupach <[email protected]> wrote:

This does actually call a javascript callback on clicking a LegendItem with renderer r :

r.js_on_change('change:visible',CustomJS(code="""console.log('renderer callback',cb_obj);""")

But yes, no call to a python callback

--
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/b7d84caa-e57d-4b9d-89f8-89175e9de505%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/8B4DDF96-0DEE-4213-937A-2A8440B7423B%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/C5FC72E8-6D12-4F7D-95CD-2020780EB118%40gmail.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/CD3381ED-1FA6-4F43-AA4F-7230EB9B7EF4%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/1b8dcde3-b2ae-4e12-8760-abd073a8bc86%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.