Better way of deleting annotations?

Hi, sorry for a noob question, but I have not been able to find a clean way of deleting annotations. In the example below, there are two methods, the currently uncommented method works, but is kind of hokey… first looping through the renderers to get the ones you want to delete and then looping through again to delete them. The other commented out method doesn’t work maybe due to internal array indexing issues or something. Anyway, is there a cleaner / better way of deleting a list of annotations from a plot? I have searched and haven’t been able to find anything.

“”"
example derived from:
https://bokeh.pydata.org/en/latest/docs/user_guide/annotations.html#box-annotations

example designed to work on bokeh server.
“”"

from bokeh.plotting import figure, curdoc
from bokeh.layouts import row
from bokeh.plotting import show, output_file
from bokeh.models import BoxAnnotation

TOOLS = “pan,wheel_zoom,box_zoom,reset,save”

x = [0,1,2,3]
y = [-10,220,40,90]

p = figure(x_axis_type=“datetime”, tools=TOOLS)

p.line(x=x, y=y, line_color=“gray”, line_width=1)

low_box = BoxAnnotation(top=80, fill_alpha=0.1, fill_color=‘red’)
mid_box1 = BoxAnnotation(name=‘mid_box’,bottom=80, top=90, fill_alpha=0.1, fill_color=‘green’)
mid_box2 = BoxAnnotation(name=‘mid_box’,bottom=100, top=100, fill_alpha=0.1, fill_color=‘green’)
mid_box3 = BoxAnnotation(name=‘mid_box’,bottom=110, top=120, fill_alpha=0.1, fill_color=‘green’)
mid_box4 = BoxAnnotation(name=‘mid_box’,bottom=120, top=130, fill_alpha=0.1, fill_color=‘green’)
mid_box5 = BoxAnnotation(name=‘mid_box’,bottom=130, top=140, fill_alpha=0.1, fill_color=‘green’)
mid_box6 = BoxAnnotation(name=‘mid_box’,bottom=140, top=150, fill_alpha=0.1, fill_color=‘green’)
mid_box7 = BoxAnnotation(name=‘mid_box’,bottom=150, top=160, fill_alpha=0.1, fill_color=‘green’)
mid_box8 = BoxAnnotation(name=‘mid_box’,bottom=160, top=170, fill_alpha=0.1, fill_color=‘green’)
mid_box9 = BoxAnnotation(name=‘mid_box’,bottom=170, top=180, fill_alpha=0.1, fill_color=‘green’)
high_box = BoxAnnotation(bottom=180, fill_alpha=0.1, fill_color=‘red’)

p.add_layout(low_box)
p.add_layout(mid_box1)
p.add_layout(mid_box2)
p.add_layout(mid_box3)
p.add_layout(mid_box4)
p.add_layout(mid_box5)
p.add_layout(mid_box6)
p.add_layout(mid_box7)
p.add_layout(mid_box8)
p.add_layout(mid_box9)
p.add_layout(high_box)

p.title.text = “Glucose Range”
p.xgrid[0].grid_line_color=None
p.ygrid[0].grid_line_alpha=0.5
p.xaxis.axis_label = ‘Time’
p.yaxis.axis_label = ‘Value’

“”"
“”"

In[0]:

···

#=============================================================================

This works

remove_these =
j = 0

identify the items to delete

for i,r in enumerate(p.renderers):
print(“renderer loop identification phase” + str(type(r)))
if r.name == ‘mid_box’:
j = j+1
remove_these.append(r)

delete them

for j,r in enumerate(remove_these):
print(“renderer loop deleting phase” + str(type(r)))
p.renderers.remove(remove_these[j])
“”"
“”"

In[1]:

#=============================================================================

This doesn’t work

“”"
print(">>> oops, I changed my mind… let’s delete that middle box annotation.")
for i,r in enumerate(p.renderers):
print(“renderer loop” + str(type(r)))
if r.name == ‘mid_box’:
p.renderers.remove(r)
print("<<<dang… didn’t work for all of them")
“”"

In[2]:

layout = row(p)

curdoc().add_root(layout)
curdoc().title = ‘Layout Buttons’

Maybe worth a try:

  p.renderers = [r for r in p.renderers if r.name != 'mid_box']

That said, if you are removing in order hide something, only to possible add it back later, then I'd suggest its easier and more advisable to just make something visible/invisible as needed, but keep it around, instead of adding/deleting instances.

Thanks,

Bryan

···

On Jan 25, 2018, at 13:13, [email protected] wrote:

Hi, sorry for a noob question, but I have not been able to find a clean way of deleting annotations. In the example below, there are two methods, the currently uncommented method works, but is kind of hokey... first looping through the renderers to get the ones you want to delete and then looping through again to delete them. The other commented out method doesn't work maybe due to internal array indexing issues or something. Anyway, is there a cleaner / better way of deleting a list of annotations from a plot? I have searched and haven't been able to find anything.

"""
example derived from:
https://bokeh.pydata.org/en/latest/docs/user_guide/annotations.html#box-annotations

example designed to work on bokeh server.
"""

from bokeh.plotting import figure, curdoc
from bokeh.layouts import row
from bokeh.plotting import show, output_file
from bokeh.models import BoxAnnotation
TOOLS = "pan,wheel_zoom,box_zoom,reset,save"
x = [0,1,2,3]
y = [-10,220,40,90]
p = figure(x_axis_type="datetime", tools=TOOLS)
p.line(x=x, y=y, line_color="gray", line_width=1)
low_box = BoxAnnotation(top=80, fill_alpha=0.1, fill_color='red')
mid_box1 = BoxAnnotation(name='mid_box',bottom=80, top=90, fill_alpha=0.1, fill_color='green')
mid_box2 = BoxAnnotation(name='mid_box',bottom=100, top=100, fill_alpha=0.1, fill_color='green')
mid_box3 = BoxAnnotation(name='mid_box',bottom=110, top=120, fill_alpha=0.1, fill_color='green')
mid_box4 = BoxAnnotation(name='mid_box',bottom=120, top=130, fill_alpha=0.1, fill_color='green')
mid_box5 = BoxAnnotation(name='mid_box',bottom=130, top=140, fill_alpha=0.1, fill_color='green')
mid_box6 = BoxAnnotation(name='mid_box',bottom=140, top=150, fill_alpha=0.1, fill_color='green')
mid_box7 = BoxAnnotation(name='mid_box',bottom=150, top=160, fill_alpha=0.1, fill_color='green')
mid_box8 = BoxAnnotation(name='mid_box',bottom=160, top=170, fill_alpha=0.1, fill_color='green')
mid_box9 = BoxAnnotation(name='mid_box',bottom=170, top=180, fill_alpha=0.1, fill_color='green')
high_box = BoxAnnotation(bottom=180, fill_alpha=0.1, fill_color='red')
p.add_layout(low_box)
p.add_layout(mid_box1)
p.add_layout(mid_box2)
p.add_layout(mid_box3)
p.add_layout(mid_box4)
p.add_layout(mid_box5)
p.add_layout(mid_box6)
p.add_layout(mid_box7)
p.add_layout(mid_box8)
p.add_layout(mid_box9)
p.add_layout(high_box)
p.title.text = "Glucose Range"
p.xgrid[0].grid_line_color=None
p.ygrid[0].grid_line_alpha=0.5
p.xaxis.axis_label = 'Time'
p.yaxis.axis_label = 'Value'
"""
"""
# In[0]:
#=============================================================================
# This works
remove_these =
j = 0
# identify the items to delete
for i,r in enumerate(p.renderers):
    print("renderer loop identification phase" + str(type(r)))
    if r.name == 'mid_box':
        j = j+1
        remove_these.append(r)
# delete them
for j,r in enumerate(remove_these):
    print("renderer loop deleting phase" + str(type(r)))
    p.renderers.remove(remove_these[j])
"""
"""
# In[1]:
#=============================================================================
# This doesn't work
"""
print(">>> oops, I changed my mind... let's delete that middle box annotation.")
for i,r in enumerate(p.renderers):
    print("renderer loop" + str(type(r)))
    if r.name == 'mid_box':
        p.renderers.remove(r)
print("<<<dang... didn't work for all of them")
"""
# In[2]:
layout = row(p)
curdoc().add_root(layout)
curdoc().title = 'Layout Buttons'

--
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/421cdd4e-c890-4c2d-9c10-42dea1e02071%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

Thanks! that works! (and is very pythonic :slight_smile:

My use-case is cycling through sets of data, and I am updating the data in the data source so that I don’t need to recreate the plot and that is working fine. The reason I need (or desire) to delete the annotations is that as I cycle through the plots, some may have 3 annotations, others none, others 50… so it seems that deleting is more appropriate as long as it doesn’t kill performance. If performance becomes an issue, it may make sense to do the visible / not toggling, but then need to manage a queue of annotations.

I have a related issue with what appears to be these renderers hanging around after deletion… but havn’t been able to reduce it to a minimal example yet… If I can do that… I will post a follow-up if it is related to this topic.

Thanks for the quick response! :slight_smile:

···

On Thursday, January 25, 2018 at 2:24:13 PM UTC-5, Bryan Van de ven wrote:

Maybe worth a try:

    p.renderers = [r for r in p.renderers if [r.name](http://r.name) != 'mid_box']

That said, if you are removing in order hide something, only to possible add it back later, then I’d suggest its easier and more advisable to just make something visible/invisible as needed, but keep it around, instead of adding/deleting instances.

Thanks,

Bryan

On Jan 25, 2018, at 13:13, [email protected] wrote:

Hi, sorry for a noob question, but I have not been able to find a clean way of deleting annotations. In the example below, there are two methods, the currently uncommented method works, but is kind of hokey… first looping through the renderers to get the ones you want to delete and then looping through again to delete them. The other commented out method doesn’t work maybe due to internal array indexing issues or something. Anyway, is there a cleaner / better way of deleting a list of annotations from a plot? I have searched and haven’t been able to find anything.

“”"

example derived from:

https://bokeh.pydata.org/en/latest/docs/user_guide/annotations.html#box-annotations

example designed to work on bokeh server.

“”"

from bokeh.plotting import figure, curdoc

from bokeh.layouts import row

from bokeh.plotting import show, output_file

from bokeh.models import BoxAnnotation

TOOLS = “pan,wheel_zoom,box_zoom,reset,save”

x = [0,1,2,3]

y = [-10,220,40,90]

p = figure(x_axis_type=“datetime”, tools=TOOLS)

p.line(x=x, y=y, line_color=“gray”, line_width=1)

low_box = BoxAnnotation(top=80, fill_alpha=0.1, fill_color=‘red’)

mid_box1 = BoxAnnotation(name=‘mid_box’,bottom=80, top=90, fill_alpha=0.1, fill_color=‘green’)

mid_box2 = BoxAnnotation(name=‘mid_box’,bottom=100, top=100, fill_alpha=0.1, fill_color=‘green’)

mid_box3 = BoxAnnotation(name=‘mid_box’,bottom=110, top=120, fill_alpha=0.1, fill_color=‘green’)

mid_box4 = BoxAnnotation(name=‘mid_box’,bottom=120, top=130, fill_alpha=0.1, fill_color=‘green’)

mid_box5 = BoxAnnotation(name=‘mid_box’,bottom=130, top=140, fill_alpha=0.1, fill_color=‘green’)

mid_box6 = BoxAnnotation(name=‘mid_box’,bottom=140, top=150, fill_alpha=0.1, fill_color=‘green’)

mid_box7 = BoxAnnotation(name=‘mid_box’,bottom=150, top=160, fill_alpha=0.1, fill_color=‘green’)

mid_box8 = BoxAnnotation(name=‘mid_box’,bottom=160, top=170, fill_alpha=0.1, fill_color=‘green’)

mid_box9 = BoxAnnotation(name=‘mid_box’,bottom=170, top=180, fill_alpha=0.1, fill_color=‘green’)

high_box = BoxAnnotation(bottom=180, fill_alpha=0.1, fill_color=‘red’)

p.add_layout(low_box)

p.add_layout(mid_box1)

p.add_layout(mid_box2)

p.add_layout(mid_box3)

p.add_layout(mid_box4)

p.add_layout(mid_box5)

p.add_layout(mid_box6)

p.add_layout(mid_box7)

p.add_layout(mid_box8)

p.add_layout(mid_box9)

p.add_layout(high_box)

p.title.text = “Glucose Range”

p.xgrid[0].grid_line_color=None

p.ygrid[0].grid_line_alpha=0.5

p.xaxis.axis_label = ‘Time’

p.yaxis.axis_label = ‘Value’

“”"

“”"

In[0]:

#=============================================================================

This works

remove_these =

j = 0

identify the items to delete

for i,r in enumerate(p.renderers):

print("renderer loop identification phase" + str(type(r)))
if [r.name](http://r.name) == 'mid_box':
    j = j+1
    remove_these.append(r)

delete them

for j,r in enumerate(remove_these):

print("renderer loop deleting phase" + str(type(r)))
p.renderers.remove(remove_these[j])

“”"

“”"

In[1]:

#=============================================================================

This doesn’t work

“”"

print(“>>> oops, I changed my mind… let’s delete that middle box annotation.”)

for i,r in enumerate(p.renderers):

print("renderer loop" + str(type(r)))
if [r.name](http://r.name) == 'mid_box':
    p.renderers.remove(r)

print(“<<<dang… didn’t work for all of them”)

“”"

In[2]:

layout = row(p)

curdoc().add_root(layout)

curdoc().title = ‘Layout Buttons’


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/421cdd4e-c890-4c2d-9c10-42dea1e02071%40continuum.io.

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

Bryan,

Following-up… and pointing to another thread (I thought the other issue was separate, so I opened a new thread)…

Setting renderers works to remove them sometimes, but it looks like the box annotations can sometimes hang around if the box-annotations are removed in this manner… I don’t quite understand the technical details, but it looks like Eugene found some issue related to removing things which are not glyph renderers and opened up an issue report.

https://github.com/bokeh/bokeh/issues/6423#issuecomment-307283106

Note that this issue is documented in:

https://groups.google.com/a/continuum.io/forum/#!mydiscussions/bokeh/wsiTB4r38OM

And I also tried using renderers.remove() per suggestion in https://github.com/bokeh/bokeh/issues/6423#issuecomment-307283106 (that Eugene pointed me to), but that didn’t work to reliably remove the renderers.

I think I will be going the toggle visibility route.

Thanks again for your support!

-james

···

On Thursday, January 25, 2018 at 2:24:13 PM UTC-5, Bryan Van de ven wrote:

Maybe worth a try:

    p.renderers = [r for r in p.renderers if [r.name](http://r.name) != 'mid_box']

That said, if you are removing in order hide something, only to possible add it back later, then I’d suggest its easier and more advisable to just make something visible/invisible as needed, but keep it around, instead of adding/deleting instances.

Thanks,

Bryan

On Jan 25, 2018, at 13:13, [email protected] wrote:

Hi, sorry for a noob question, but I have not been able to find a clean way of deleting annotations. In the example below, there are two methods, the currently uncommented method works, but is kind of hokey… first looping through the renderers to get the ones you want to delete and then looping through again to delete them. The other commented out method doesn’t work maybe due to internal array indexing issues or something. Anyway, is there a cleaner / better way of deleting a list of annotations from a plot? I have searched and haven’t been able to find anything.

“”"

example derived from:

https://bokeh.pydata.org/en/latest/docs/user_guide/annotations.html#box-annotations

example designed to work on bokeh server.

“”"

from bokeh.plotting import figure, curdoc

from bokeh.layouts import row

from bokeh.plotting import show, output_file

from bokeh.models import BoxAnnotation

TOOLS = “pan,wheel_zoom,box_zoom,reset,save”

x = [0,1,2,3]

y = [-10,220,40,90]

p = figure(x_axis_type=“datetime”, tools=TOOLS)

p.line(x=x, y=y, line_color=“gray”, line_width=1)

low_box = BoxAnnotation(top=80, fill_alpha=0.1, fill_color=‘red’)

mid_box1 = BoxAnnotation(name=‘mid_box’,bottom=80, top=90, fill_alpha=0.1, fill_color=‘green’)

mid_box2 = BoxAnnotation(name=‘mid_box’,bottom=100, top=100, fill_alpha=0.1, fill_color=‘green’)

mid_box3 = BoxAnnotation(name=‘mid_box’,bottom=110, top=120, fill_alpha=0.1, fill_color=‘green’)

mid_box4 = BoxAnnotation(name=‘mid_box’,bottom=120, top=130, fill_alpha=0.1, fill_color=‘green’)

mid_box5 = BoxAnnotation(name=‘mid_box’,bottom=130, top=140, fill_alpha=0.1, fill_color=‘green’)

mid_box6 = BoxAnnotation(name=‘mid_box’,bottom=140, top=150, fill_alpha=0.1, fill_color=‘green’)

mid_box7 = BoxAnnotation(name=‘mid_box’,bottom=150, top=160, fill_alpha=0.1, fill_color=‘green’)

mid_box8 = BoxAnnotation(name=‘mid_box’,bottom=160, top=170, fill_alpha=0.1, fill_color=‘green’)

mid_box9 = BoxAnnotation(name=‘mid_box’,bottom=170, top=180, fill_alpha=0.1, fill_color=‘green’)

high_box = BoxAnnotation(bottom=180, fill_alpha=0.1, fill_color=‘red’)

p.add_layout(low_box)

p.add_layout(mid_box1)

p.add_layout(mid_box2)

p.add_layout(mid_box3)

p.add_layout(mid_box4)

p.add_layout(mid_box5)

p.add_layout(mid_box6)

p.add_layout(mid_box7)

p.add_layout(mid_box8)

p.add_layout(mid_box9)

p.add_layout(high_box)

p.title.text = “Glucose Range”

p.xgrid[0].grid_line_color=None

p.ygrid[0].grid_line_alpha=0.5

p.xaxis.axis_label = ‘Time’

p.yaxis.axis_label = ‘Value’

“”"

“”"

In[0]:

#=============================================================================

This works

remove_these =

j = 0

identify the items to delete

for i,r in enumerate(p.renderers):

print("renderer loop identification phase" + str(type(r)))
if [r.name](http://r.name) == 'mid_box':
    j = j+1
    remove_these.append(r)

delete them

for j,r in enumerate(remove_these):

print("renderer loop deleting phase" + str(type(r)))
p.renderers.remove(remove_these[j])

“”"

“”"

In[1]:

#=============================================================================

This doesn’t work

“”"

print(“>>> oops, I changed my mind… let’s delete that middle box annotation.”)

for i,r in enumerate(p.renderers):

print("renderer loop" + str(type(r)))
if [r.name](http://r.name) == 'mid_box':
    p.renderers.remove(r)

print(“<<<dang… didn’t work for all of them”)

“”"

In[2]:

layout = row(p)

curdoc().add_root(layout)

curdoc().title = ‘Layout Buttons’


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/421cdd4e-c890-4c2d-9c10-42dea1e02071%40continuum.io.

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

Another option for a variable number of boxes might be to use rect, quad etc. If you need them to be on top, you can change their render_level. The only other consideration is that by default all glyphs participate in hit-testing, so if you have a hover tool you might need to be more explicit to exclude these pseudo-annotations.

thanks,

Bryan

···

On Jan 30, 2018, at 07:39, James <[email protected]> wrote:

Bryan,

Following-up... and pointing to another thread (I thought the other issue was separate, so I opened a new thread)...

Setting renderers works to remove them sometimes, but it looks like the box annotations can sometimes hang around if the box-annotations are removed in this manner.. I don't quite understand the technical details, but it looks like Eugene found some issue related to removing things which are not glyph renderers and opened up an issue report.

     https://github.com/bokeh/bokeh/issues/6423#issuecomment-307283106

Note that this issue is documented in:

     Redirecting to Google Groups

And I also tried using renderers.remove() per suggestion in https://github.com/bokeh/bokeh/issues/6423#issuecomment-307283106 (that Eugene pointed me to), but that didn't work to reliably remove the renderers.

I think I will be going the toggle visibility route.

Thanks again for your support!

-james

On Thursday, January 25, 2018 at 2:24:13 PM UTC-5, Bryan Van de ven wrote:
Maybe worth a try:

        p.renderers = [r for r in p.renderers if r.name != 'mid_box']

That said, if you are removing in order hide something, only to possible add it back later, then I'd suggest its easier and more advisable to just make something visible/invisible as needed, but keep it around, instead of adding/deleting instances.

Thanks,

Bryan

> On Jan 25, 2018, at 13:13, jamesw...@gmail.com wrote:
>
> Hi, sorry for a noob question, but I have not been able to find a clean way of deleting annotations. In the example below, there are two methods, the currently uncommented method works, but is kind of hokey... first looping through the renderers to get the ones you want to delete and then looping through again to delete them. The other commented out method doesn't work maybe due to internal array indexing issues or something. Anyway, is there a cleaner / better way of deleting a list of annotations from a plot? I have searched and haven't been able to find anything.
>
>
>
> """
> example derived from:
> https://bokeh.pydata.org/en/latest/docs/user_guide/annotations.html#box-annotations
>
> example designed to work on bokeh server.
> """
>
> from bokeh.plotting import figure, curdoc
> from bokeh.layouts import row
> from bokeh.plotting import show, output_file
> from bokeh.models import BoxAnnotation
> TOOLS = "pan,wheel_zoom,box_zoom,reset,save"
> x = [0,1,2,3]
> y = [-10,220,40,90]
> p = figure(x_axis_type="datetime", tools=TOOLS)
> p.line(x=x, y=y, line_color="gray", line_width=1)
> low_box = BoxAnnotation(top=80, fill_alpha=0.1, fill_color='red')
> mid_box1 = BoxAnnotation(name='mid_box',bottom=80, top=90, fill_alpha=0.1, fill_color='green')
> mid_box2 = BoxAnnotation(name='mid_box',bottom=100, top=100, fill_alpha=0.1, fill_color='green')
> mid_box3 = BoxAnnotation(name='mid_box',bottom=110, top=120, fill_alpha=0.1, fill_color='green')
> mid_box4 = BoxAnnotation(name='mid_box',bottom=120, top=130, fill_alpha=0.1, fill_color='green')
> mid_box5 = BoxAnnotation(name='mid_box',bottom=130, top=140, fill_alpha=0.1, fill_color='green')
> mid_box6 = BoxAnnotation(name='mid_box',bottom=140, top=150, fill_alpha=0.1, fill_color='green')
> mid_box7 = BoxAnnotation(name='mid_box',bottom=150, top=160, fill_alpha=0.1, fill_color='green')
> mid_box8 = BoxAnnotation(name='mid_box',bottom=160, top=170, fill_alpha=0.1, fill_color='green')
> mid_box9 = BoxAnnotation(name='mid_box',bottom=170, top=180, fill_alpha=0.1, fill_color='green')
> high_box = BoxAnnotation(bottom=180, fill_alpha=0.1, fill_color='red')
> p.add_layout(low_box)
> p.add_layout(mid_box1)
> p.add_layout(mid_box2)
> p.add_layout(mid_box3)
> p.add_layout(mid_box4)
> p.add_layout(mid_box5)
> p.add_layout(mid_box6)
> p.add_layout(mid_box7)
> p.add_layout(mid_box8)
> p.add_layout(mid_box9)
> p.add_layout(high_box)
> p.title.text = "Glucose Range"
> p.xgrid[0].grid_line_color=None
> p.ygrid[0].grid_line_alpha=0.5
> p.xaxis.axis_label = 'Time'
> p.yaxis.axis_label = 'Value'
> """
> """
> # In[0]:
> #=============================================================================
> # This works
> remove_these =
> j = 0
> # identify the items to delete
> for i,r in enumerate(p.renderers):
> print("renderer loop identification phase" + str(type(r)))
> if r.name == 'mid_box':
> j = j+1
> remove_these.append(r)
> # delete them
> for j,r in enumerate(remove_these):
> print("renderer loop deleting phase" + str(type(r)))
> p.renderers.remove(remove_these[j])
> """
> """
> # In[1]:
> #=============================================================================
> # This doesn't work
> """
> print(">>> oops, I changed my mind... let's delete that middle box annotation.")
> for i,r in enumerate(p.renderers):
> print("renderer loop" + str(type(r)))
> if r.name == 'mid_box':
> p.renderers.remove(r)
> print("<<<dang... didn't work for all of them")
> """
> # In[2]:
> layout = row(p)
> curdoc().add_root(layout)
> curdoc().title = 'Layout Buttons'
>
> --
> 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/421cdd4e-c890-4c2d-9c10-42dea1e02071%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/aeca89b3-b123-4494-8a88-d95c16126e37%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

Rects and quads can’t fill one dimension, can they? So that would be another consideration in case arbitrary panning must be supported.
Yet another issue is DataRange1d usage - such rects and quads will change its boundaries.

  • Eugene
···

On Tuesday, January 30, 2018 at 9:35:14 PM UTC+7, Bryan Van de ven wrote:

Another option for a variable number of boxes might be to use rect, quad etc. If you need them to be on top, you can change their render_level. The only other consideration is that by default all glyphs participate in hit-testing, so if you have a hover tool you might need to be more explicit to exclude these pseudo-annotations.

thanks,

Bryan

On Jan 30, 2018, at 07:39, James [email protected] wrote:

Bryan,

Following-up… and pointing to another thread (I thought the other issue was separate, so I opened a new thread)…

Setting renderers works to remove them sometimes, but it looks like the box annotations can sometimes hang around if the box-annotations are removed in this manner… I don’t quite understand the technical details, but it looks like Eugene found some issue related to removing things which are not glyph renderers and opened up an issue report.

 [https://github.com/bokeh/bokeh/issues/6423#issuecomment-307283106](https://github.com/bokeh/bokeh/issues/6423#issuecomment-307283106)

Note that this issue is documented in:

 [https://groups.google.com/a/continuum.io/forum/#!mydiscussions/bokeh/wsiTB4r38OM](https://groups.google.com/a/continuum.io/forum/#!mydiscussions/bokeh/wsiTB4r38OM)

And I also tried using renderers.remove() per suggestion in https://github.com/bokeh/bokeh/issues/6423#issuecomment-307283106 (that Eugene pointed me to), but that didn’t work to reliably remove the renderers.

I think I will be going the toggle visibility route.

Thanks again for your support!

-james

On Thursday, January 25, 2018 at 2:24:13 PM UTC-5, Bryan Van de ven wrote:

Maybe worth a try:

    p.renderers = [r for r in p.renderers if [r.name](http://r.name) != 'mid_box']

That said, if you are removing in order hide something, only to possible add it back later, then I’d suggest its easier and more advisable to just make something visible/invisible as needed, but keep it around, instead of adding/deleting instances.

Thanks,

Bryan

On Jan 25, 2018, at 13:13, [email protected] wrote:

Hi, sorry for a noob question, but I have not been able to find a clean way of deleting annotations. In the example below, there are two methods, the currently uncommented method works, but is kind of hokey… first looping through the renderers to get the ones you want to delete and then looping through again to delete them. The other commented out method doesn’t work maybe due to internal array indexing issues or something. Anyway, is there a cleaner / better way of deleting a list of annotations from a plot? I have searched and haven’t been able to find anything.

“”"
example derived from:
https://bokeh.pydata.org/en/latest/docs/user_guide/annotations.html#box-annotations

example designed to work on bokeh server.
“”"

from bokeh.plotting import figure, curdoc
from bokeh.layouts import row
from bokeh.plotting import show, output_file
from bokeh.models import BoxAnnotation
TOOLS = “pan,wheel_zoom,box_zoom,reset,save”
x = [0,1,2,3]
y = [-10,220,40,90]
p = figure(x_axis_type=“datetime”, tools=TOOLS)
p.line(x=x, y=y, line_color=“gray”, line_width=1)
low_box = BoxAnnotation(top=80, fill_alpha=0.1, fill_color=‘red’)
mid_box1 = BoxAnnotation(name=‘mid_box’,bottom=80, top=90, fill_alpha=0.1, fill_color=‘green’)
mid_box2 = BoxAnnotation(name=‘mid_box’,bottom=100, top=100, fill_alpha=0.1, fill_color=‘green’)
mid_box3 = BoxAnnotation(name=‘mid_box’,bottom=110, top=120, fill_alpha=0.1, fill_color=‘green’)
mid_box4 = BoxAnnotation(name=‘mid_box’,bottom=120, top=130, fill_alpha=0.1, fill_color=‘green’)
mid_box5 = BoxAnnotation(name=‘mid_box’,bottom=130, top=140, fill_alpha=0.1, fill_color=‘green’)
mid_box6 = BoxAnnotation(name=‘mid_box’,bottom=140, top=150, fill_alpha=0.1, fill_color=‘green’)
mid_box7 = BoxAnnotation(name=‘mid_box’,bottom=150, top=160, fill_alpha=0.1, fill_color=‘green’)
mid_box8 = BoxAnnotation(name=‘mid_box’,bottom=160, top=170, fill_alpha=0.1, fill_color=‘green’)
mid_box9 = BoxAnnotation(name=‘mid_box’,bottom=170, top=180, fill_alpha=0.1, fill_color=‘green’)
high_box = BoxAnnotation(bottom=180, fill_alpha=0.1, fill_color=‘red’)
p.add_layout(low_box)
p.add_layout(mid_box1)
p.add_layout(mid_box2)
p.add_layout(mid_box3)
p.add_layout(mid_box4)
p.add_layout(mid_box5)
p.add_layout(mid_box6)
p.add_layout(mid_box7)
p.add_layout(mid_box8)
p.add_layout(mid_box9)
p.add_layout(high_box)
p.title.text = “Glucose Range”
p.xgrid[0].grid_line_color=None
p.ygrid[0].grid_line_alpha=0.5
p.xaxis.axis_label = ‘Time’
p.yaxis.axis_label = ‘Value’
“”"
“”"

In[0]:

#=============================================================================

This works

remove_these =
j = 0

identify the items to delete

for i,r in enumerate(p.renderers):
print(“renderer loop identification phase” + str(type(r)))
if r.name == ‘mid_box’:
j = j+1
remove_these.append(r)

delete them

for j,r in enumerate(remove_these):
print(“renderer loop deleting phase” + str(type(r)))
p.renderers.remove(remove_these[j])
“”"
“”"

In[1]:

#=============================================================================

This doesn’t work

“”"
print(“>>> oops, I changed my mind… let’s delete that middle box annotation.”)
for i,r in enumerate(p.renderers):
print(“renderer loop” + str(type(r)))
if r.name == ‘mid_box’:
p.renderers.remove(r)
print(“<<<dang… didn’t work for all of them”)
“”"

In[2]:

layout = row(p)
curdoc().add_root(layout)
curdoc().title = ‘Layout Buttons’


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/421cdd4e-c890-4c2d-9c10-42dea1e02071%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/aeca89b3-b123-4494-8a88-d95c16126e37%40continuum.io.

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

DataRange1d can also be explicitly configured as to what glyphs it considers when computing bounds. If you need "full span" box annotations, then yes you'd have to do something hacking like specifying very large bounds along that dimensions. However you can also constrain the range bounds to prevent infinite panning/zooming if that is appropriate.

Thanks,

Bryan

···

On Jan 30, 2018, at 08:49, Eugene Pakhomov <[email protected]> wrote:

Rects and quads can't fill one dimension, can they? So that would be another consideration in case arbitrary panning must be supported.
Yet another issue is DataRange1d usage - such rects and quads will change its boundaries.

- Eugene

On Tuesday, January 30, 2018 at 9:35:14 PM UTC+7, Bryan Van de ven wrote:
Another option for a variable number of boxes might be to use rect, quad etc. If you need them to be on top, you can change their render_level. The only other consideration is that by default all glyphs participate in hit-testing, so if you have a hover tool you might need to be more explicit to exclude these pseudo-annotations.

thanks,

Bryan

> On Jan 30, 2018, at 07:39, James <[email protected]> wrote:
>
> Bryan,
>
> Following-up... and pointing to another thread (I thought the other issue was separate, so I opened a new thread)...
>
> Setting renderers works to remove them sometimes, but it looks like the box annotations can sometimes hang around if the box-annotations are removed in this manner.. I don't quite understand the technical details, but it looks like Eugene found some issue related to removing things which are not glyph renderers and opened up an issue report.
>
> https://github.com/bokeh/bokeh/issues/6423#issuecomment-307283106
>
> Note that this issue is documented in:
>
> Redirecting to Google Groups
>
> And I also tried using renderers.remove() per suggestion in https://github.com/bokeh/bokeh/issues/6423#issuecomment-307283106 (that Eugene pointed me to), but that didn't work to reliably remove the renderers.
>
> I think I will be going the toggle visibility route.
>
> Thanks again for your support!
>
> -james
>
> On Thursday, January 25, 2018 at 2:24:13 PM UTC-5, Bryan Van de ven wrote:
> Maybe worth a try:
>
> p.renderers = [r for r in p.renderers if r.name != 'mid_box']
>
> That said, if you are removing in order hide something, only to possible add it back later, then I'd suggest its easier and more advisable to just make something visible/invisible as needed, but keep it around, instead of adding/deleting instances.
>
> Thanks,
>
> Bryan
>
> > On Jan 25, 2018, at 13:13, jamesw...@gmail.com wrote:
> >
> > Hi, sorry for a noob question, but I have not been able to find a clean way of deleting annotations. In the example below, there are two methods, the currently uncommented method works, but is kind of hokey... first looping through the renderers to get the ones you want to delete and then looping through again to delete them. The other commented out method doesn't work maybe due to internal array indexing issues or something. Anyway, is there a cleaner / better way of deleting a list of annotations from a plot? I have searched and haven't been able to find anything.
> >
> >
> >
> > """
> > example derived from:
> > https://bokeh.pydata.org/en/latest/docs/user_guide/annotations.html#box-annotations
> >
> > example designed to work on bokeh server.
> > """
> >
> > from bokeh.plotting import figure, curdoc
> > from bokeh.layouts import row
> > from bokeh.plotting import show, output_file
> > from bokeh.models import BoxAnnotation
> > TOOLS = "pan,wheel_zoom,box_zoom,reset,save"
> > x = [0,1,2,3]
> > y = [-10,220,40,90]
> > p = figure(x_axis_type="datetime", tools=TOOLS)
> > p.line(x=x, y=y, line_color="gray", line_width=1)
> > low_box = BoxAnnotation(top=80, fill_alpha=0.1, fill_color='red')
> > mid_box1 = BoxAnnotation(name='mid_box',bottom=80, top=90, fill_alpha=0.1, fill_color='green')
> > mid_box2 = BoxAnnotation(name='mid_box',bottom=100, top=100, fill_alpha=0.1, fill_color='green')
> > mid_box3 = BoxAnnotation(name='mid_box',bottom=110, top=120, fill_alpha=0.1, fill_color='green')
> > mid_box4 = BoxAnnotation(name='mid_box',bottom=120, top=130, fill_alpha=0.1, fill_color='green')
> > mid_box5 = BoxAnnotation(name='mid_box',bottom=130, top=140, fill_alpha=0.1, fill_color='green')
> > mid_box6 = BoxAnnotation(name='mid_box',bottom=140, top=150, fill_alpha=0.1, fill_color='green')
> > mid_box7 = BoxAnnotation(name='mid_box',bottom=150, top=160, fill_alpha=0.1, fill_color='green')
> > mid_box8 = BoxAnnotation(name='mid_box',bottom=160, top=170, fill_alpha=0.1, fill_color='green')
> > mid_box9 = BoxAnnotation(name='mid_box',bottom=170, top=180, fill_alpha=0.1, fill_color='green')
> > high_box = BoxAnnotation(bottom=180, fill_alpha=0.1, fill_color='red')
> > p.add_layout(low_box)
> > p.add_layout(mid_box1)
> > p.add_layout(mid_box2)
> > p.add_layout(mid_box3)
> > p.add_layout(mid_box4)
> > p.add_layout(mid_box5)
> > p.add_layout(mid_box6)
> > p.add_layout(mid_box7)
> > p.add_layout(mid_box8)
> > p.add_layout(mid_box9)
> > p.add_layout(high_box)
> > p.title.text = "Glucose Range"
> > p.xgrid[0].grid_line_color=None
> > p.ygrid[0].grid_line_alpha=0.5
> > p.xaxis.axis_label = 'Time'
> > p.yaxis.axis_label = 'Value'
> > """
> > """
> > # In[0]:
> > #=============================================================================
> > # This works
> > remove_these =
> > j = 0
> > # identify the items to delete
> > for i,r in enumerate(p.renderers):
> > print("renderer loop identification phase" + str(type(r)))
> > if r.name == 'mid_box':
> > j = j+1
> > remove_these.append(r)
> > # delete them
> > for j,r in enumerate(remove_these):
> > print("renderer loop deleting phase" + str(type(r)))
> > p.renderers.remove(remove_these[j])
> > """
> > """
> > # In[1]:
> > #=============================================================================
> > # This doesn't work
> > """
> > print(">>> oops, I changed my mind... let's delete that middle box annotation.")
> > for i,r in enumerate(p.renderers):
> > print("renderer loop" + str(type(r)))
> > if r.name == 'mid_box':
> > p.renderers.remove(r)
> > print("<<<dang... didn't work for all of them")
> > """
> > # In[2]:
> > layout = row(p)
> > curdoc().add_root(layout)
> > curdoc().title = 'Layout Buttons'
> >
> > --
> > 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/421cdd4e-c890-4c2d-9c10-42dea1e02071%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/aeca89b3-b123-4494-8a88-d95c16126e37%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/863a9fa8-f703-4f5c-a6f2-4535a829417a%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

Eugene and Bryan,

I just confirmed that toggling visible works for me. Thanks!

-james

···

On Tuesday, January 30, 2018 at 8:39:42 AM UTC-5, James wrote:

Bryan,

Following-up… and pointing to another thread (I thought the other issue was separate, so I opened a new thread)…

Setting renderers works to remove them sometimes, but it looks like the box annotations can sometimes hang around if the box-annotations are removed in this manner… I don’t quite understand the technical details, but it looks like Eugene found some issue related to removing things which are not glyph renderers and opened up an issue report.

https://github.com/bokeh/bokeh/issues/6423#issuecomment-307283106

Note that this issue is documented in:

https://groups.google.com/a/continuum.io/forum/#!mydiscussions/bokeh/wsiTB4r38OM

And I also tried using renderers.remove() per suggestion in https://github.com/bokeh/bokeh/issues/6423#issuecomment-307283106 (that Eugene pointed me to), but that didn’t work to reliably remove the renderers.

I think I will be going the toggle visibility route.

Thanks again for your support!

-james

On Thursday, January 25, 2018 at 2:24:13 PM UTC-5, Bryan Van de ven wrote:

Maybe worth a try:

    p.renderers = [r for r in p.renderers if [r.name](http://r.name) != 'mid_box']

That said, if you are removing in order hide something, only to possible add it back later, then I’d suggest its easier and more advisable to just make something visible/invisible as needed, but keep it around, instead of adding/deleting instances.

Thanks,

Bryan

On Jan 25, 2018, at 13:13, [email protected] wrote:

Hi, sorry for a noob question, but I have not been able to find a clean way of deleting annotations. In the example below, there are two methods, the currently uncommented method works, but is kind of hokey… first looping through the renderers to get the ones you want to delete and then looping through again to delete them. The other commented out method doesn’t work maybe due to internal array indexing issues or something. Anyway, is there a cleaner / better way of deleting a list of annotations from a plot? I have searched and haven’t been able to find anything.

“”"

example derived from:

https://bokeh.pydata.org/en/latest/docs/user_guide/annotations.html#box-annotations

example designed to work on bokeh server.

“”"

from bokeh.plotting import figure, curdoc

from bokeh.layouts import row

from bokeh.plotting import show, output_file

from bokeh.models import BoxAnnotation

TOOLS = “pan,wheel_zoom,box_zoom,reset,save”

x = [0,1,2,3]

y = [-10,220,40,90]

p = figure(x_axis_type=“datetime”, tools=TOOLS)

p.line(x=x, y=y, line_color=“gray”, line_width=1)

low_box = BoxAnnotation(top=80, fill_alpha=0.1, fill_color=‘red’)

mid_box1 = BoxAnnotation(name=‘mid_box’,bottom=80, top=90, fill_alpha=0.1, fill_color=‘green’)

mid_box2 = BoxAnnotation(name=‘mid_box’,bottom=100, top=100, fill_alpha=0.1, fill_color=‘green’)

mid_box3 = BoxAnnotation(name=‘mid_box’,bottom=110, top=120, fill_alpha=0.1, fill_color=‘green’)

mid_box4 = BoxAnnotation(name=‘mid_box’,bottom=120, top=130, fill_alpha=0.1, fill_color=‘green’)

mid_box5 = BoxAnnotation(name=‘mid_box’,bottom=130, top=140, fill_alpha=0.1, fill_color=‘green’)

mid_box6 = BoxAnnotation(name=‘mid_box’,bottom=140, top=150, fill_alpha=0.1, fill_color=‘green’)

mid_box7 = BoxAnnotation(name=‘mid_box’,bottom=150, top=160, fill_alpha=0.1, fill_color=‘green’)

mid_box8 = BoxAnnotation(name=‘mid_box’,bottom=160, top=170, fill_alpha=0.1, fill_color=‘green’)

mid_box9 = BoxAnnotation(name=‘mid_box’,bottom=170, top=180, fill_alpha=0.1, fill_color=‘green’)

high_box = BoxAnnotation(bottom=180, fill_alpha=0.1, fill_color=‘red’)

p.add_layout(low_box)

p.add_layout(mid_box1)

p.add_layout(mid_box2)

p.add_layout(mid_box3)

p.add_layout(mid_box4)

p.add_layout(mid_box5)

p.add_layout(mid_box6)

p.add_layout(mid_box7)

p.add_layout(mid_box8)

p.add_layout(mid_box9)

p.add_layout(high_box)

p.title.text = “Glucose Range”

p.xgrid[0].grid_line_color=None

p.ygrid[0].grid_line_alpha=0.5

p.xaxis.axis_label = ‘Time’

p.yaxis.axis_label = ‘Value’

“”"

“”"

In[0]:

#=============================================================================

This works

remove_these =

j = 0

identify the items to delete

for i,r in enumerate(p.renderers):

print("renderer loop identification phase" + str(type(r)))
if [r.name](http://r.name) == 'mid_box':
    j = j+1
    remove_these.append(r)

delete them

for j,r in enumerate(remove_these):

print("renderer loop deleting phase" + str(type(r)))
p.renderers.remove(remove_these[j])

“”"

“”"

In[1]:

#=============================================================================

This doesn’t work

“”"

print(“>>> oops, I changed my mind… let’s delete that middle box annotation.”)

for i,r in enumerate(p.renderers):

print("renderer loop" + str(type(r)))
if [r.name](http://r.name) == 'mid_box':
    p.renderers.remove(r)

print(“<<<dang… didn’t work for all of them”)

“”"

In[2]:

layout = row(p)

curdoc().add_root(layout)

curdoc().title = ‘Layout Buttons’


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/421cdd4e-c890-4c2d-9c10-42dea1e02071%40continuum.io.

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