Bokeh Server callback from tools

前端 未结 3 1200
隐瞒了意图╮
隐瞒了意图╮ 2021-01-02 19:53

I\'m kinda new on Python, and currently working on a interactive plot visualization using Bokeh where I need to show multiple related charts. To accomplish this i\'m using b

相关标签:
3条回答
  • 2021-01-02 19:59

    The solution published by Pablo is great but it doesn't work with recent bokeh version (0.12.13). I got an runtime error (Supplying a user-defined data source AND iterable values to glyph methods is not possible)

    Following works for me ...

    from bokeh.plotting import figure, curdoc
    from bokeh.layouts import column
    from bokeh.models import ColumnDataSource
    
    TOOLS = "tap"
    p = figure(title="Some Figure", tools=TOOLS)
    
    source = ColumnDataSource(dict(x=[[1, 3, 2], [3, 4, 6, 6]], y=[[2, 1, 4], [4, 7, 8, 5]], alphas = [0.8, 0.3], colors=["firebrick", "navy"], name=['A', 'B']))
    
    pglyph = p.patches(xs='x', ys='y', source=source, line_width=2, alpha = 'alphas', color='colors')
    
    def callback_fcn(attr, old, new):
        # The index of the selected glyph is : new['1d']['indices'][0]
        patch_name =  source.data['name'][new['1d']['indices'][0]]
        print("TapTool callback executed on Patch {}".format(patch_name))
    
    pglyph.data_source.on_change('selected',callback_fcn)
    
    curdoc().add_root(column(p))
    
    0 讨论(0)
  • 2021-01-02 20:19

    Since bokeh 0.13 the solution proposed by @Karel_Marik a needs small tweak:

    from bokeh.plotting import figure, curdoc
    from bokeh.layouts import column
    from bokeh.models import ColumnDataSource
    
    TOOLS = ["tap"]
    p = figure(title="Some Figure", tools=TOOLS)
    
    source = ColumnDataSource(dict(
        x=[[1, 3, 2], [3, 4, 6, 6]],
        y=[[2, 1, 4], [4, 7, 8, 5]],
        name=['A', 'B'],color=["firebrick", "navy"],
        alpha=[0.8,0.3],line_width=[3,3]))
    
    pglyph = p.patches('x', 'y', color="color", alpha="alpha",
                       line_width="line_width", source=source)
    
    def callback(attr, old, new):
        # The index of the selected glyph is : new['1d']['indices'][0]
        selections = new['1d']['indices']
        print("Number of selections:{}".format(len(selections)))
        for index in selections:
            patch_name =  source.data['name'][index]
            print("TapTool callback executed on Patch {}".format(patch_name))
    

    pglyph.data_source.on_change('selected',callback)

    pglyph.selected.on_change('indices', callback)
    
    curdoc().add_root(column(p))
    

    I hope this helps somebody.

    0 讨论(0)
  • 2021-01-02 20:21

    Edit from project maintainers.

    There was some confusion and regressions around selections leading up to 1.0. For any post 1.0 version, for most use case you would now want to use a callback on the 'indices' property of selected:

    source.selected.on_change('indices', callback)
    

    This kind of usage is now continuously and rigorously maintained under integration tests, and is what should be used for any post 1.0 Bokeh version.


    The selected event can be linked to an update function as follows:

    from bokeh.plotting import figure, curdoc
    from bokeh.layouts import column
    from bokeh.models import ColumnDataSource
    
    TOOLS = "tap"
    p = figure(title="Some Figure", tools=TOOLS)
    
    source = ColumnDataSource(dict(x=[[1, 3, 2], [3, 4, 6, 6]],
                    y=[[2, 1, 4], [4, 7, 8, 5]], name=['A', 'B']))
    
    pglyph = p.patches('x', 'y', source=source, color=["firebrick", "navy"],
                                    alpha=[0.8, 0.3], line_width=2)
    
    def callback(attr, old, new):
        # The index of the selected glyph is : new['1d']['indices'][0]
        patch_name =  source.data['name'][new['1d']['indices'][0]]
        print("TapTool callback executed on Patch {}".format(patch_name))
    
    pglyph.data_source.on_change('selected',callback)
    
    curdoc().add_root(column(p))
    

    Update for newer Bokeh versions. Tested on version 0.12.16

    As @Karel Marik mentions glyphs can not mixed direct values assignment and ColumnDataSource at the same time. So the previous code does not work. Here is an update using only source which also includes code to print the multiple selections (made with shift + click):

    from bokeh.plotting import figure, curdoc
    from bokeh.layouts import column
    from bokeh.models import ColumnDataSource
    
    TOOLS = ["tap"]
    p = figure(title="Some Figure", tools=TOOLS)
    
    source = ColumnDataSource(dict(
        x=[[1, 3, 2], [3, 4, 6, 6]],
        y=[[2, 1, 4], [4, 7, 8, 5]],
        name=['A', 'B'],color=["firebrick", "navy"],
        alpha=[0.8,0.3],line_width=[3,3]))
    
    pglyph = p.patches('x', 'y', color="color", alpha="alpha",
                       line_width="line_width", source=source)
    
    def callback(attr, old, new):
        # The index of the selected glyph is : new['1d']['indices'][0]
        selections = new['1d']['indices']
        print("Number of selections:{}".format(len(selections)))
        for index in selections:
            patch_name =  source.data['name'][index]
            print("TapTool callback executed on Patch {}".format(patch_name))
    
    pglyph.data_source.on_change('selected',callback)
    
    curdoc().add_root(column(p))
    
    0 讨论(0)
提交回复
热议问题