Search code examples
holoviewspyvizhvplot

synchronize selection of > 1 chart


How do I synchronize the selection in the 2 charts below? Also, how do I get the bounds of the box selection?

import holoviews as hv
import hvplot.pandas
from bokeh.sampledata.autompg import autompg
hv.extension('bokeh')

hv.Layout([autompg.hvplot.scatter(x='mpg', y='yr', tools=['box_select']), autompg.hvplot.scatter(x='mpg', y='yr', tools=['box_select'])]).cols(1)

Solution

  • The linked selection is easy:

    import holoviews as hv
    import hvplot.pandas
    from bokeh.sampledata.autompg import autompg
    hv.extension('bokeh')
    
    from holoviews.plotting.links import DataLink
    a = autompg.hvplot.scatter(x='mpg', y='yr', tools=['box_select'])
    b = autompg.hvplot.scatter(x='mpg', y='yr', tools=['box_select'])
    DataLink(a, b)
    hv.Layout([a, b]).cols(1)
    

    Documentation: https://www.holoviews.org/user_guide/Linking_Plots.html

    Now for retrieving the bounds. You can use BoundsXY for that:

    import numpy as np
    import holoviews as hv
    from holoviews.streams import BoundsXY
    
    data = np.random.multivariate_normal((0, 0), [[1, 0.1], [0.1, 1]], (1000,))
    points = hv.Points(data).opts(tools=['box_select'])
    sel = BoundsXY(source=points)
    def cog(bounds):
        'Center of gravity'
        if bounds is None:
            bounds=(0, 0, 0, 0)
        index = points.dframe().x.between(*bounds[::2]) & points.dframe().y.between(*bounds[1::2])
        x = points.dframe().loc[index, 'x'].mean() if index.any() else []
        y = points.dframe().loc[index, 'y'].mean() if index.any() else []
        return hv.Points((x, y)).opts(size=10)
    
    mean_sel = hv.DynamicMap(cog, kdims=[], streams=[sel])
    
    points * mean_sel
    

    (modelled on http://holoviews.org/reference/apps/bokeh/selection_stream.html)