Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion holoviews/selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,12 @@ class link_selections(_base_link_selections):
are expressed solely in terms of discrete values along the
index_cols. All Elements given to link_selections must define the index_cols, either as explicit dimensions or by sharing an underlying Dataset that defines them.""")

re_enable_regions_on_user_interaction = param.Boolean(
default=True, doc="""
If True, a subsequent user interaction (e.g. box/lasso select)
will re-enable region highlighting after a programmatic change
that disabled it.""")

selection_expr = param.Parameter(default=None, doc="""
dim expression of the current selection or None to indicate
that everything is selected.""")
Expand Down Expand Up @@ -392,10 +398,15 @@ def update_selection_expr(*_):
new_selection_expr = inst.selection_expr
current_selection_expr = inst._cross_filter_stream.selection_expr
if repr(new_selection_expr) != repr(current_selection_expr):
# Reset the streams
for s in inst._selection_expr_streams.values():
s.reset()
s.event()
# Disable regions if setting selection_expr directly
if inst.show_regions:
inst.show_regions = False
inst._selection_override.event(selection_expr=new_selection_expr)
inst._cross_filter_stream.selection_expr = new_selection_expr
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what fixes #6688


inst.param.watch(
update_selection_expr, ['selection_expr']
Expand All @@ -405,6 +416,9 @@ def selection_expr_changed(*_):
new_selection_expr = inst._cross_filter_stream.selection_expr
if repr(inst.selection_expr) != repr(new_selection_expr):
inst.selection_expr = new_selection_expr
if inst.re_enable_regions_on_user_interaction:
if not inst.show_regions:
inst.show_regions = True

inst._cross_filter_stream.param.watch(
selection_expr_changed, ['selection_expr']
Expand All @@ -415,7 +429,6 @@ def selection_expr_changed(*_):
def clear_stream_history(resetting, stream=stream):
if resetting:
stream.clear_history()
print("registering reset for ", stream)
stream.plot_reset_stream.param.watch(
clear_stream_history, ['resetting']
)
Expand Down
12 changes: 12 additions & 0 deletions holoviews/tests/test_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@
self.assertEqual(region, Rectangles([]))

def test_points_selection_hide_region(self):
self.test_points_selection(show_regions=False)

Check failure on line 119 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / core:test-core:ubuntu-latest

TestLinkSelectionsBokeh.test_points_selection_hide_region AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 119 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-313:macos-latest

TestLinkSelectionsBokeh.test_points_selection_hide_region AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 119 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-313:macos-latest

TestLinkSelectionsPlotly.test_points_selection_hide_region AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 119 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-313:ubuntu-latest

TestLinkSelectionsBokeh.test_points_selection_hide_region AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 119 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-313:ubuntu-latest

TestLinkSelectionsPlotly.test_points_selection_hide_region AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 119 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-310:macos-latest

TestLinkSelectionsBokeh.test_points_selection_hide_region AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 119 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-310:macos-latest

TestLinkSelectionsPlotly.test_points_selection_hide_region AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 119 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-310:ubuntu-latest

TestLinkSelectionsBokeh.test_points_selection_hide_region AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 119 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-310:ubuntu-latest

TestLinkSelectionsPlotly.test_points_selection_hide_region AssertionError: Rectangles not of matching length, 1 vs. 0.

def test_points_selection_dynamic(self):
self.test_points_selection(dynamic=True)
Expand Down Expand Up @@ -175,6 +175,18 @@
]
)

def test_select_expr_show_regions(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need a UI test for this change.

lnk_sel = link_selections.instance()
self.assertTrue(lnk_sel.show_regions)
se = (
(hv.dim('x') >= 0) & (hv.dim('x') <= 1) &
(hv.dim('y') >= 0) & (hv.dim('y') <= 1)
)
lnk_sel.selection_expr = se
self.assertTrue(lnk_sel.show_regions)

Check failure on line 186 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / core:test-core:ubuntu-latest

TestLinkSelectionsBokeh.test_select_expr_show_regions AssertionError: False is not true

Check failure on line 186 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-313:macos-latest

TestLinkSelectionsBokeh.test_select_expr_show_regions AssertionError: False is not true

Check failure on line 186 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-313:macos-latest

TestLinkSelectionsPlotly.test_select_expr_show_regions AssertionError: False is not true

Check failure on line 186 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-313:ubuntu-latest

TestLinkSelectionsBokeh.test_select_expr_show_regions AssertionError: False is not true

Check failure on line 186 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-313:ubuntu-latest

TestLinkSelectionsPlotly.test_select_expr_show_regions AssertionError: False is not true

Check failure on line 186 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-310:macos-latest

TestLinkSelectionsBokeh.test_select_expr_show_regions AssertionError: False is not true

Check failure on line 186 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-310:macos-latest

TestLinkSelectionsPlotly.test_select_expr_show_regions AssertionError: False is not true

Check failure on line 186 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-310:ubuntu-latest

TestLinkSelectionsBokeh.test_select_expr_show_regions AssertionError: False is not true

Check failure on line 186 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-310:ubuntu-latest

TestLinkSelectionsPlotly.test_select_expr_show_regions AssertionError: False is not true
lnk_sel.selection_expr = None
self.assertTrue(lnk_sel.show_regions)

def test_overlay_points_errorbars(self, dynamic=False):
points = Points(self.data)
error = ErrorBars(self.data, kdims='x', vdims=['y', 'e'])
Expand Down Expand Up @@ -637,7 +649,7 @@
self.test_points_histogram_overwrite_intersect(dynamic=True)

def test_points_histogram_overwrite_intersect_hide_region(self, dynamic=False):
self.do_crossfilter_points_histogram(

Check failure on line 652 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / core:test-core:ubuntu-latest

TestLinkSelectionsBokeh.test_points_histogram_overwrite_intersect_hide_region AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 652 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-313:macos-latest

TestLinkSelectionsBokeh.test_points_histogram_overwrite_intersect_hide_region AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 652 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-313:macos-latest

TestLinkSelectionsPlotly.test_points_histogram_overwrite_intersect_hide_region AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 652 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-313:ubuntu-latest

TestLinkSelectionsBokeh.test_points_histogram_overwrite_intersect_hide_region AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 652 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-313:ubuntu-latest

TestLinkSelectionsPlotly.test_points_histogram_overwrite_intersect_hide_region AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 652 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-310:macos-latest

TestLinkSelectionsBokeh.test_points_histogram_overwrite_intersect_hide_region AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 652 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-310:macos-latest

TestLinkSelectionsPlotly.test_points_histogram_overwrite_intersect_hide_region AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 652 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-310:ubuntu-latest

TestLinkSelectionsBokeh.test_points_histogram_overwrite_intersect_hide_region AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 652 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-310:ubuntu-latest

TestLinkSelectionsPlotly.test_points_histogram_overwrite_intersect_hide_region AssertionError: Rectangles not of matching length, 1 vs. 0.
selection_mode="overwrite", cross_filter_mode="intersect",
selected1=[1, 2], selected2=[1], selected3=[0], selected4=[2],
points_region1=[],
Expand All @@ -649,7 +661,7 @@
)

def test_points_histogram_overwrite_intersect_hide_region_dynamic(self):
self.test_points_histogram_overwrite_intersect_hide_region(dynamic=True)

Check failure on line 664 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / core:test-core:ubuntu-latest

TestLinkSelectionsBokeh.test_points_histogram_overwrite_intersect_hide_region_dynamic AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 664 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-313:macos-latest

TestLinkSelectionsBokeh.test_points_histogram_overwrite_intersect_hide_region_dynamic AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 664 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-313:macos-latest

TestLinkSelectionsPlotly.test_points_histogram_overwrite_intersect_hide_region_dynamic AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 664 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-313:ubuntu-latest

TestLinkSelectionsBokeh.test_points_histogram_overwrite_intersect_hide_region_dynamic AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 664 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-313:ubuntu-latest

TestLinkSelectionsPlotly.test_points_histogram_overwrite_intersect_hide_region_dynamic AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 664 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-310:macos-latest

TestLinkSelectionsBokeh.test_points_histogram_overwrite_intersect_hide_region_dynamic AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 664 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-310:macos-latest

TestLinkSelectionsPlotly.test_points_histogram_overwrite_intersect_hide_region_dynamic AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 664 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-310:ubuntu-latest

TestLinkSelectionsBokeh.test_points_histogram_overwrite_intersect_hide_region_dynamic AssertionError: Rectangles not of matching length, 1 vs. 0.

Check failure on line 664 in holoviews/tests/test_selection.py

View workflow job for this annotation

GitHub Actions / unit:test-310:ubuntu-latest

TestLinkSelectionsPlotly.test_points_histogram_overwrite_intersect_hide_region_dynamic AssertionError: Rectangles not of matching length, 1 vs. 0.

def test_points_histogram_intersect_intersect(self, dynamic=False):
self.do_crossfilter_points_histogram(
Expand Down
64 changes: 64 additions & 0 deletions holoviews/tests/ui/bokeh/test_link_selections.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@

import pytest

import holoviews as hv
from holoviews.plotting.bokeh.renderer import BokehRenderer
from holoviews.selection import link_selections

from .. import expect

pytestmark = pytest.mark.ui


@pytest.mark.usefixtures("bokeh_backend")
def test_link_selections_programmatic_clear_removes_region(serve_hv):
points = hv.Points([1, 2, 3, 4, 5, 6, 7, 8]).opts(width=400, height=300)

# Helper to inspect bokeh model renderers for region-like glyphs
def count_highlighted_region_renderers(bokeh_plot):
cnt = 0
for r in bokeh_plot.renderers:
data = r.data_source.data
if len(data.get("left", [])) > 0:
cnt += 1
continue
return cnt

ls = link_selections.instance()
linked = ls(points).opts(active_tools=["box_select"])

page = serve_hv(linked)
hv_plot = page.locator(".bk-events")
expect(hv_plot).to_have_count(1)
bbox = hv_plot.bounding_box()

page.wait_for_timeout(300)
initial_count = count_highlighted_region_renderers(BokehRenderer.get_plot(linked[()]).state)
assert initial_count == 0

# Box-drag selection
start_x = bbox["x"] + bbox["width"] * 0.25
start_y = bbox["y"] + bbox["height"] * 0.25
end_x = bbox["x"] + bbox["width"] * 0.75
end_y = bbox["y"] + bbox["height"] * 0.75

hv_plot.click()
page.mouse.move(start_x, start_y)
page.mouse.down(button="left")
page.mouse.move(end_x, end_y, steps=10)
page.mouse.up(button="left")

page.wait_for_timeout(200)

assert ls.selection_expr is not None

# Ensure at least one new region renderer was created by the interaction
post_select_count = count_highlighted_region_renderers(BokehRenderer.get_plot(linked[()]).state)
assert post_select_count == initial_count + 1

ls.selection_expr = None
page.wait_for_timeout(200)

# Final region count should be back to initial
final_count = count_highlighted_region_renderers(BokehRenderer.get_plot(linked[()]).state)
assert final_count == initial_count
Loading