MRocklin
MRocklin

Reputation: 57271

How to clear a selection from a Bokeh plot?

I use selection in a figure to drive my Bokeh server application. However after the user selects something I don't actually want that selection to have any visual effect on the figure. How can I remove the selection effects?

I can imagine two ways of solving this, but am having trouble getting either to work:

  1. Remove the selection in the callback

    def cb(attr, old, new):
        source.selected.indices.clear()
        ...
    
    source.on_change('selected', cb)
    
  2. Keep the selected indices, but remove any styling difference between them. I found this:

    http://docs.bokeh.org/en/latest/docs/user_guide/styling.html#selected-and-unselected-glyphs

    but wasn't sure how to effectively apply this to my problem.

Upvotes: 1

Views: 2247

Answers (2)

ChesuCR
ChesuCR

Reputation: 9630

If you only want to hide the selection indices you can do what Mateusz says.

Normally you would have only a glyph with selected and non-selected elements like this:

c = self.plot.scatter(
    x='x',
    y='x',
    size=4,
    line_color=None,
    fill_color='blue',
    source=source,
    view=view,

    nonselection_line_color=None,
    nonselection_fill_color='blue',
    nonselection_fill_alpha=1.0,
)
c.selection_glyph = Circle(
    line_color=None,
    line_alpha=1.0,
    fill_color='red',
)

But, if you want to change the selection, and keep the selections color on the custom selection (previous selection), as a workaround you can manage another list custom_selection with the samples that are actually selected. So you would need to create two glyphs, one for the selected and another one with the non-selected samples. Something like this:

c = self.plot.scatter(
    x='x',
    y='x',
    size=4,
    line_color=None,
    fill_color='blue',
    source=source,
    view=view_non_selected,          # here the view should have the non-selected samples

    nonselection_line_color=None,
    nonselection_fill_color='blue',
    nonselection_fill_alpha=1.0,
)
c.selection_glyph = Circle(
    line_color=None,
    line_alpha=1.0,
    fill_color='blue',  # I plot the selected point with blue color here as well
)

c_sel = self.plot.scatter(
    x='x',
    y='x',
    size=4,
    line_color=None,
    fill_color='red',
    source=source,
    view=view_selected,          # here the view should have the selected samples

    nonselection_line_color=None,
    nonselection_fill_color='red',
    nonselection_fill_alpha=1.0,
)
c_sel.selection_glyph = Circle(
    line_color=None,
    line_alpha=1.0,
    fill_color='red',  # I plot the selected point with blue color here as well
)

Each time you want to update the selections you will have to update the view indexes list:

view_non_selected.filters = [IndexFilter(non_selected_indices_list)]
view_selected.filters = [IndexFilter(custom_selection)]

Youcould create one single glyph with a color column as well and update the source. It may be more efficient.

Upvotes: 2

Mateusz Paprocki
Mateusz Paprocki

Reputation: 156

Selection/non-selection glyphs can be either disabled or use the main glyph, e.g.:

r = plot.scatter(...)
r.selection_glyph = None
r.nonselection_glyph = None

or

r = plot.scatter(...)
r.selection_glyph = r.glyph
r.nonselection_glyph = r.glyph

Upvotes: 2

Related Questions