8000 Make .selected a proper Bokeh model · Issue #6845 · bokeh/bokeh · GitHub
[go: up one dir, main page]

Skip to content

Make .selected a proper Bokeh model #6845

@crashMOGWAI

Description

@crashMOGWAI

This seems to be a pain point with users, and I've stumbled into as well. Resetting the whole .selected dict seems to trigger updates in most simple cases, but reliability is finicky at best with more complex selection updates. @bryevdv Your idea, not mine.

proper  #selected

Currently the only way to spoof this type of selection function is to create multiple grouped sources and manipulate the selection/nonselection attributes, or stack multiple sources and use the filters. It starts to get out of hand when dealing with larger data sets. Rather than dealing with multiple sources, a single data source paired with a callback that sets the .selected index based on a selection within that group, and reliable plot update trigger is preferred. @clairetang6 Maybe a CDSView extension concept 7BB8 , SelectFilter?

This standalone would select groups accordingly if .selected could detect an internal change and push an update trigger.

def mod_doc(doc):
    ''''''
    import numpy as np
    from bokeh.plotting import figure
    from bokeh.layouts import layout
    from bokeh.models import ColumnDataSource
    from bokeh.sampledata.iris import flowers
    from bokeh.palettes import Spectral6
    from bokeh.transform import factor_cmap
    
    source = ColumnDataSource(flowers)  
    plot_size_and_tools = {
        'plot_height': 500, 'plot_width': 500,
        'tools':['box_select','tap','reset', 'help']
        }
    p1 = figure(title="Proper .selected", **plot_size_and_tools)
    p1.circle(
        x='petal_length', y='petal_width', source=source,
        color=factor_cmap('species', palette=Spectral6[3:], 
                          factors=list(set(flowers.species))), size=10)
    
    def cb_change(attr,old,new):
        data = source.data.copy()
        selected = source.selected.copy()
        species = np.asarray(data['species'])
        idx = selected['1d']['indices']
        if len(idx) != 0:
            selected['1d']['indices'] = []
            species_sel = list(set(species[idx]))  
            for each in species_sel:
                idx = np.where(species == each)[0].tolist()
                selected['1d']['indices'].extend(idx)
            source.selected.update(selected)
            
    source.on_change('selected', cb_change)
    worksheet = layout([[p1]], sizing_mode='fixed')
    doc.add_root(worksheet)
    return doc

def main():
    '''''' 
    from tornado.ioloop import IOLoop
    from bokeh.document import Document
    from bokeh.application.handlers import FunctionHandler
    from bokeh.application import Application
    from bokeh.server.server import Server

    io_loop = IOLoop.current()    
    doc = Document()
    app = Application(FunctionHandler(mod_doc))
    server = Server({'/proper.selected': app}, io_loop=io_loop, port=0)
    server.start()
    io_loop.add_callback(server.show,'/proper.selected')
    io_loop.start()

if __name__ == '__main__':
    main()

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    0