BoundsXY stream: reset with bokeh "reset" button

Since linked brushing between scatter and adjoining histograms appears to be broken (box select of scatter with adjoint histograms does not work. · Issue #5066 · holoviz/holoviews · GitHub), I’m trying to modify the Bounds example as a workaround.

I’m currently stuck trying to get the bokeh “reset” button to also reset the BoundsXY stream back to its original state to make the selection box disappear. Here’s what I’ve tried:

import numpy as np
import holoviews as hv
from holoviews import opts
from holoviews import streams
hv.extension('bokeh')

opts.defaults(opts.Histogram(framewise=True))

# Declare distribution of Points
points = hv.Points(np.random.multivariate_normal((0, 0), [[1, 0.1], [0.1, 1]], (1000,)))

# Declare a Bounds stream and DynamicMap to get box_select geometry and draw it
box = streams.BoundsXY(source=points, bounds=(0,0,0,0))
bounds = hv.DynamicMap(lambda bounds: hv.Bounds(bounds), streams=[box])

reset = streams.PlotReset(transient=False)
def select_points(bounds, resetting):
    if resetting:
        box.reset()
    else:
        return points.select(x=(bounds[0], bounds[2]), y=(bounds[1], bounds[3]))
                         
# Declare DynamicMap to apply bounds selection
dmap = hv.DynamicMap(select_points, streams=[box, reset])

# Compute histograms of selection along x-axis and y-axis
yhist = hv.operation.histogram(dmap, bin_range=points.range('y'), dimension='y', dynamic=True, normed=False)
xhist = hv.operation.histogram(dmap, bin_range=points.range('x'), dimension='x', dynamic=True, normed=False)

# Combine components and display
points * bounds << yhist << xhist

Calling box.reset() doesn’t seem to do anything. After hitting the bokeh reset button, all the points are rendered as they were before making the selection, but the selection box is still shown and the histograms still reflect the previous selection. Any help would be greatly appreciated.

I have a partial fix now. I think this code (modified from https://holoviews.org/reference/streams/bokeh/Bounds.html) comes very close to providing a workaround until bug 5066 has been fixed.).

import numpy as np
import holoviews as hv
from holoviews import opts
from holoviews import streams
hv.extension('bokeh')

opts.defaults(opts.Points(tools=['box_select', 'lasso_select']))

# Declare some points
points = hv.Points(np.random.randn(1000,2 ))

# Declare points as source of selection stream
selection = streams.Selection1D(source=points)

def select_points(index):
    if index:
        selected = points.iloc[index]
    else:
        selected = points.iloc[:]
    return selected
                         
# Declare DynamicMap to apply bounds selection
dmap = hv.DynamicMap(select_points, streams=[selection])
xhist = hv.operation.histogram(dmap, bin_range=points.range('x'), dimension='x', dynamic=True, normed=False)
yhist = hv.operation.histogram(dmap, bin_range=points.range('y'), dimension='y', dynamic=True, normed=False)

# Combine points and histograms
points << yhist << xhist