How to clear old labels from a plot

Problem with labels not clearing and legends items becoming invisible

I have a Bokeh plot which I am updating in a python callback in Bokeh serve. using Bokeh 2.2.3

On each call the plot is rendered with new data, a background image, some glyphs and a LabelSet.
Before the plot is run I clear the plot with:
p.renderers = []

This clears the all the glyphs and the image fine but does not clear the labels. I also find that after the first run the legend goes blank other than the first item?

In an attempt to cure the labels issue I tried adding a pre-emptive:
try:
p.renderers.remove(labels)
except:
pass

But this had no effect.

Below is a skeleton of my code.

p = figure(title = 'My Labeled Circles', 
           plot_height = 800 ,
           plot_width = 800, 
           toolbar_location = 'right',
           tools = '',
           y_range=(512, 0),   
           x_range=(0, 512)               
          )

yn=['yes','no']
my_dropdown = Dropdown(label='my label', menu=yn, height_policy='fit' )
my_dropdown.on_click(myplot_triggering_event)


def myplot_triggering_event(event):
      
        p.renderers = []

        p.image_rgba(image=[my_image], x=0, y=h, dw=w, dh=h, legend_label="Image")

	    call_function_that_returns_two_data_frames() #returns df1 and df2	

        source1 = ColumnDataSource(df1)         
        source2 = ColumnDataSource(df2) 

        source1.selected.on_change("indices", another_handler) 
        
        my_patches = p.patches('xs','ys', source = source1,
                    fill_color =  None,  #'yellow'
                    line_color = 'blue', line_width = 0.8, fill_alpha = 0.6,
                    selection_color="firebrick",
                    selection_fill_alpha = 0.2,           
                    nonselection_fill_alpha=0.1,
                    nonselection_fill_color="green",
                    nonselection_line_color="pink",
                    nonselection_line_alpha=1.0,                              
                    legend_label="my patches")       

        my_circles=p.circle(x='x', y='y', 
                    fill_color="orange",
                    source=source2,
                    line_color=None, 
                    size=10, fill_alpha = 1.0, 
		    legend_label="My Circles")

        labels = LabelSet(x='x', y='y', text='my_circle_name', level='annotation',
              x_offset=10, y_offset=10, source=source2, render_mode='canvas')
        
        try:
            p.renderers.remove(labels)
        except:
            pass
            
        p.add_layout(labels)

        p.add_tools(HoverTool(renderers = [my_circles], tooltips = [('My Circle', '@circle_name')])) 
         
        p.legend.location = "top_left"
        p.legend.click_policy="hide"
        p.legend.level="overlay"
    
tab1 = Panel(child=p,   title="My Plot")
tabs = Tabs(tabs=[tab1])

curdoc().add_root(tabs)

Any thoughts welcome

Rather than removing the renderer, better practice in Bokeh would be to either:

  • set the visible property to False to hide it
  • empty out the arrays in source2.data

Awesome thanks for taking a look at that Bryan.
Your solution solved both problems
Removing the p.renderers = [] tided up the mis-behaving legend and setting the data source to empty removed the old labels using your example
try:
colnames=list(mydf.keys())
`source2.data = { name : for name in colnames }

except:
pass

1 Like