Clearing Plot or Removing all glyphs

Is there a good way to do this? I see the add glyph function but no function to remove glyphs. I also have seen that you can remove glyphs from renderers list in the figure but I’m thinking that may cause issues based on this github issue:

The reason I want to do this - I have a plot embedded in an angular application and I need to rescale or change the data dynamically without reloading the figure.

You don’t need to remove the glyph for this. You can update the data sources for existing glyphs. Or if you really need to, set their visible property to false. Bokeh is best at updating an existing objects, rather than removing them.

When I set the visible property to False the glyphs (lines) still show up in the legend. Any way around that behavior?

I’m curious is there deeper reasoning for not having a remove_glyph function or has it just never been coded?

@Steven_Van_Buskirk Bokeh is at it’s core, a “building block” architecture, with lots of small pieces that can be assembled in many ways. This has many benefits for both users and developers, but is not also without some drawbacks. One of those is that there are some times things that work well in simple scenarios that maybe don’t work as well in arbitrarily complicated assemblies some users might come up with. [1] I’d say removing glyphs falls in to that category. It’s not impossible, but sometimes it’s more difficult or has subtle issues to deal with, and accordingly we just don’t want to encourage it as common usage.

If you just have one simple plot with a legend then you can probably:

  • remove the associated GlyphRenderer from .renderers
  • delete the corresponding LegendItem from the Legend

There is an open issue to discuss making legend items hide-able.

What is your actual concern with “reloading the figure”? Have you actually tested or benchmarked that doing the simplest thing and just deleting the old plot entirely and adding a new one is not sufficient? Is it because your data is large? In that case you could add a new hidden plot that shares the data same sources, then only the non-data parts would need to be sent.

  1. Just as an off the cuff example: Users can make CustomJS callbacks that reference a glyph or its GlyphRender that do absolutely arbitrary things in JS code that we have no knowledge of or control over. In that case removing a glyph without “breaking something” can be more difficult, and it’s not always clear even what the necessary actions are. In this case should we find all things that might reference the removed glyph and also remove them? There’s 100% certainly users who would not want that to happen. There’s not a clean-cut “right” answer so again, we simply discourage this pattern. ↩︎

@Bryan Thanks for the explanation.

If you just have one simple plot with a legend then you can probably:

  • remove the associated GlyphRenderer from .renderers
  • delete the corresponding LegendItem from the Legend

I wasn’t sure if it was that simple since I read other objects can hold onto references of GlyphRenderers. The CustomJS example makes sense as an issue.

We actually started off by trying to dynamically change the data via holoviews and DynamicMaps but that turned into a headache (there were a lot of bugs) so we switched to pure bokeh and are currently reloading the entire figure (running the js embed_items function on our frontend and pulling a new bokeh session each time we want to change the data). There are two issues with this though -

  1. The user experience on our frontend web app isn’t great as it takes a few seconds to rerender the plot and we change the data out about every 10 seconds. We decided we could accept this though.
  2. Now the bigger problem though is we have added custom tool extensions where by the user can mark up the plot with custom overlay annotations and we need those to persist across changes to the data.

It sounds like you are using a Bokeh server application? If so, then I was suggesting replacing a plot in an existing session:

some_layout.children[2] = new_plot

I don’t understand why users would need to close and open new entire sessions, but it sounds like you have a very complicated/sophisticated situation, so its certainly possible (likely) that I don’t have the complete picture.

I haven’t tried that but it makes sense. Would that though solve this problem I mentioned before -

I tried out removing the glyps via how you mentioned -

Removing the legend item seemed to work fine but removing the glyph generated this weird effect where there looks to be a plot within the plot. Any ideas on this? -

The code looked something like -

fig = doc.get_model_by_name('main-figure')
line_glyph = doc.get_model_by_name('line-glyph-name')

And yes this is all using bokeh server.

That’s always some bug that results in corrupted canvas state. I can’t investigate or speculate about any workarounds without a complete, minimal reproducer to run.

Would that though solve this problem I mentioned before -

I don’t know nearly enough about anything you are doing to say much of anything. Offhand it seems like it should always be simpler to persist state inside a single session (i.e what I proposed) than it would be to communicate it across multiple sessions for the same user.

Turns out if you remove the legend item first, then remove the glyph renderer you don’t see the bug. If you remove the glyph renderer before you remove the legend item you get the corrupted canvas state bug.

Removing the glyph rendering will itself trigger a re-render, so then the legend will be trying to render for a glyph that is no longer present. I can imagine that being problematic, and this kind of order sensitivity is another reason we generally try to encourage alternative approaches. In general, the Bokeh best practice boils down to “try to update properties existing models, rather than replace models wholesale”.