""" Test cases for the Comparisons class over the Chart elements """ from unittest import SkipTest, skipIf import numpy as np from holoviews.core import NdOverlay from holoviews.core.options import Store from holoviews.element import ( Area, BoxWhisker, Curve, Distribution, HSpan, Image, Points, Rectangles, RGB, Scatter, Segments, Violin, VSpan, Path, QuadMesh, Polygons ) from holoviews.element.comparison import ComparisonTestCase try: import datashader as ds except: ds = None try: import spatialpandas as spd except: spd = None try: import shapely except: shapely = None spd_available = skipIf(spd is None, "spatialpandas is not available") shapelib_available = skipIf(shapely is None and spd is None, 'Neither shapely nor spatialpandas are available') shapely_available = skipIf(shapely is None, 'shapely is not available') ds_available = skipIf(ds is None, 'datashader not available') class TestSelection1DExpr(ComparisonTestCase): def setUp(self): try: import holoviews.plotting.bokeh # noqa except: raise SkipTest("Bokeh selection tests require bokeh.") super(TestSelection1DExpr, self).setUp() self._backend = Store.current_backend Store.set_current_backend('bokeh') def tearDown(self): Store.current_backend = self._backend def test_area_selection_numeric(self): area = Area([3, 2, 1, 3, 4]) expr, bbox, region = area._get_selection_expr_for_stream_value(bounds=(1, 0, 3, 2)) self.assertEqual(bbox, {'x': (1, 3)}) self.assertEqual(expr.apply(area), np.array([False, True, True, True, False])) self.assertEqual(region, NdOverlay({0: VSpan(1, 3)})) def test_area_selection_numeric_inverted(self): area = Area([3, 2, 1, 3, 4]).opts(invert_axes=True) expr, bbox, region = area._get_selection_expr_for_stream_value(bounds=(0, 1, 2, 3)) self.assertEqual(bbox, {'x': (1, 3)}) self.assertEqual(expr.apply(area), np.array([False, True, True, True, False])) self.assertEqual(region, NdOverlay({0: HSpan(1, 3)})) def test_area_selection_categorical(self): area = Area((['B', 'A', 'C', 'D', 'E'], [3, 2, 1, 3, 4])) expr, bbox, region = area._get_selection_expr_for_stream_value( bounds=(0, 1, 2, 3), x_selection=['B', 'A', 'C'] ) self.assertEqual(bbox, {'x': ['B', 'A', 'C']}) self.assertEqual(expr.apply(area), np.array([True, True, True, False, False])) self.assertEqual(region, NdOverlay({0: VSpan(0, 2)})) def test_area_selection_numeric_index_cols(self): area = Area([3, 2, 1, 3, 2]) expr, bbox, region = area._get_selection_expr_for_stream_value( bounds=(1, 0, 3, 2), index_cols=['y'] ) self.assertEqual(bbox, {'x': (1, 3)}) self.assertEqual(expr.apply(area), np.array([False, True, True, False, True])) self.assertEqual(region, None) def test_curve_selection_numeric(self): curve = Curve([3, 2, 1, 3, 4]) expr, bbox, region = curve._get_selection_expr_for_stream_value(bounds=(1, 0, 3, 2)) self.assertEqual(bbox, {'x': (1, 3)}) self.assertEqual(expr.apply(curve), np.array([False, True, True, True, False])) self.assertEqual(region, NdOverlay({0: VSpan(1, 3)})) def test_curve_selection_categorical(self): curve = Curve((['B', 'A', 'C', 'D', 'E'], [3, 2, 1, 3, 4])) expr, bbox, region = curve._get_selection_expr_for_stream_value( bounds=(0, 1, 2, 3), x_selection=['B', 'A', 'C'] ) self.assertEqual(bbox, {'x': ['B', 'A', 'C']}) self.assertEqual(expr.apply(curve), np.array([True, True, True, False, False])) self.assertEqual(region, NdOverlay({0: VSpan(0, 2)})) def test_curve_selection_numeric_index_cols(self): curve = Curve([3, 2, 1, 3, 2]) expr, bbox, region = curve._get_selection_expr_for_stream_value( bounds=(1, 0, 3, 2), index_cols=['y'] ) self.assertEqual(bbox, {'x': (1, 3)}) self.assertEqual(expr.apply(curve), np.array([False, True, True, False, True])) self.assertEqual(region, None) def test_box_whisker_single(self): box_whisker = BoxWhisker(list(range(10))) expr, bbox, region = box_whisker._get_selection_expr_for_stream_value( bounds=(0, 3, 1, 7) ) self.assertEqual(bbox, {'y': (3, 7)}) self.assertEqual(expr.apply(box_whisker), np.array([ False, False, False, True, True, True, True, True, False, False ])) self.assertEqual(region, NdOverlay({0: HSpan(3, 7)})) def test_box_whisker_single_inverted(self): box = BoxWhisker(list(range(10))).opts(invert_axes=True) expr, bbox, region = box._get_selection_expr_for_stream_value( bounds=(3, 0, 7, 1) ) self.assertEqual(bbox, {'y': (3, 7)}) self.assertEqual(expr.apply(box), np.array([ False, False, False, True, True, True, True, True, False, False ])) self.assertEqual(region, NdOverlay({0: VSpan(3, 7)})) def test_box_whisker_cats(self): box_whisker = BoxWhisker((['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C', 'C', 'C'], list(range(10))), 'x', 'y') expr, bbox, region = box_whisker._get_selection_expr_for_stream_value( bounds=(0, 1, 2, 7), x_selection=['A', 'B'] ) self.assertEqual(bbox, {'y': (1, 7), 'x': ['A', 'B']}) self.assertEqual(expr.apply(box_whisker), np.array([ False, True, True, True, True, False, False, False, False, False ])) self.assertEqual(region, NdOverlay({0: HSpan(1, 7)})) def test_box_whisker_cats_index_cols(self): box_whisker = BoxWhisker((['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C', 'C', 'C'], list(range(10))), 'x', 'y') expr, bbox, region = box_whisker._get_selection_expr_for_stream_value( bounds=(0, 1, 2, 7), x_selection=['A', 'B'], index_cols=['x'] ) self.assertEqual(bbox, {'y': (1, 7), 'x': ['A', 'B']}) self.assertEqual(expr.apply(box_whisker), np.array([ True, True, True, True, True, False, False, False, False, False ])) self.assertEqual(region, None) def test_violin_single(self): violin = Violin(list(range(10))) expr, bbox, region = violin._get_selection_expr_for_stream_value( bounds=(0, 3, 1, 7) ) self.assertEqual(bbox, {'y': (3, 7)}) self.assertEqual(expr.apply(violin), np.array([ False, False, False, True, True, True, True, True, False, False ])) self.assertEqual(region, NdOverlay({0: HSpan(3, 7)})) def test_violin_single_inverted(self): violin = Violin(list(range(10))).opts(invert_axes=True) expr, bbox, region = violin._get_selection_expr_for_stream_value( bounds=(3, 0, 7, 1) ) self.assertEqual(bbox, {'y': (3, 7)}) self.assertEqual(expr.apply(violin), np.array([ False, False, False, True, True, True, True, True, False, False ])) self.assertEqual(region, NdOverlay({0: VSpan(3, 7)})) def test_violin_cats(self): violin = Violin((['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C', 'C', 'C'], list(range(10))), 'x', 'y') expr, bbox, region = violin._get_selection_expr_for_stream_value( bounds=(0, 1, 2, 7), x_selection=['A', 'B'] ) self.assertEqual(bbox, {'y': (1, 7), 'x': ['A', 'B']}) self.assertEqual(expr.apply(violin), np.array([ False, True, True, True, True, False, False, False, False, False ])) self.assertEqual(region, NdOverlay({0: HSpan(1, 7)})) def test_violin_cats_index_cols(self): violin = Violin((['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C', 'C', 'C'], list(range(10))), 'x', 'y') expr, bbox, region = violin._get_selection_expr_for_stream_value( bounds=(0, 1, 2, 7), x_selection=['A', 'B'], index_cols=['x'] ) self.assertEqual(bbox, {'y': (1, 7), 'x': ['A', 'B']}) self.assertEqual(expr.apply(violin), np.array([ True, True, True, True, True, False, False, False, False, False ])) self.assertEqual(region, None) def test_distribution_single(self): dist = Distribution(list(range(10))) expr, bbox, region = dist._get_selection_expr_for_stream_value( bounds=(3, 0, 7, 1) ) self.assertEqual(bbox, {'Value': (3, 7)}) self.assertEqual(expr.apply(dist), np.array([ False, False, False, True, True, True, True, True, False, False ])) self.assertEqual(region, NdOverlay({0: VSpan(3, 7)})) def test_distribution_single_inverted(self): dist = Distribution(list(range(10))).opts(invert_axes=True) expr, bbox, region = dist._get_selection_expr_for_stream_value( bounds=(0, 3, 1, 7) ) self.assertEqual(bbox, {'Value': (3, 7)}) self.assertEqual(expr.apply(dist), np.array([ False, False, False, True, True, True, True, True, False, False ])) self.assertEqual(region, NdOverlay({0: HSpan(3, 7)})) class TestSelection2DExpr(ComparisonTestCase): def setUp(self): try: import holoviews.plotting.bokeh # noqa except: raise SkipTest("Bokeh selection tests require bokeh.") super(TestSelection2DExpr, self).setUp() self._backend = Store.current_backend Store.set_current_backend('bokeh') def tearDown(self): Store.current_backend = self._backend def test_points_selection_numeric(self): points = Points([3, 2, 1, 3, 4]) expr, bbox, region = points._get_selection_expr_for_stream_value(bounds=(1, 0, 3, 2)) self.assertEqual(bbox, {'x': (1, 3), 'y': (0, 2)}) self.assertEqual(expr.apply(points), np.array([False, True, True, False, False])) self.assertEqual(region, Rectangles([(1, 0, 3, 2)]) * Path([])) def test_points_selection_numeric_inverted(self): points = Points([3, 2, 1, 3, 4]).opts(invert_axes=True) expr, bbox, region = points._get_selection_expr_for_stream_value(bounds=(0, 1, 2, 3)) self.assertEqual(bbox, {'x': (1, 3), 'y': (0, 2)}) self.assertEqual(expr.apply(points), np.array([False, True, True, False, False])) self.assertEqual(region, Rectangles([(0, 1, 2, 3)]) * Path([])) @shapelib_available def test_points_selection_geom(self): points = Points([3, 2, 1, 3, 4]) geom = np.array([(-0.1, -0.1), (1.4, 0), (1.4, 2.2), (-0.1, 2.2)]) expr, bbox, region = points._get_selection_expr_for_stream_value(geometry=geom) self.assertEqual(bbox, {'x': np.array([-0.1, 1.4, 1.4, -0.1]), 'y': np.array([-0.1, 0, 2.2, 2.2])}) self.assertEqual(expr.apply(points), np.array([False, True, False, False, False])) self.assertEqual(region, Rectangles([]) * Path([list(geom)+[(-0.1, -0.1)]])) @shapelib_available def test_points_selection_geom_inverted(self): points = Points([3, 2, 1, 3, 4]).opts(invert_axes=True) geom = np.array([(-0.1, -0.1), (1.4, 0), (1.4, 2.2), (-0.1, 2.2)]) expr, bbox, region = points._get_selection_expr_for_stream_value(geometry=geom) self.assertEqual(bbox, {'y': np.array([-0.1, 1.4, 1.4, -0.1]), 'x': np.array([-0.1, 0, 2.2, 2.2])}) self.assertEqual(expr.apply(points), np.array([False, False, True, False, False])) self.assertEqual(region, Rectangles([]) * Path([list(geom)+[(-0.1, -0.1)]])) def test_points_selection_categorical(self): points = Points((['B', 'A', 'C', 'D', 'E'], [3, 2, 1, 3, 4])) expr, bbox, region = points._get_selection_expr_for_stream_value( bounds=(0, 1, 2, 3), x_selection=['B', 'A', 'C'], y_selection=None ) self.assertEqual(bbox, {'x': ['B', 'A', 'C'], 'y': (1, 3)}) self.assertEqual(expr.apply(points), np.array([True, True, True, False, False])) self.assertEqual(region, Rectangles([(0, 1, 2, 3)]) * Path([])) def test_points_selection_numeric_index_cols(self): points = Points([3, 2, 1, 3, 2]) expr, bbox, region = points._get_selection_expr_for_stream_value( bounds=(1, 0, 3, 2), index_cols=['y'] ) self.assertEqual(bbox, {'x': (1, 3), 'y': (0, 2)}) self.assertEqual(expr.apply(points), np.array([False, False, True, False, False])) self.assertEqual(region, None) def test_scatter_selection_numeric(self): scatter = Scatter([3, 2, 1, 3, 4]) expr, bbox, region = scatter._get_selection_expr_for_stream_value(bounds=(1, 0, 3, 2)) self.assertEqual(bbox, {'x': (1, 3), 'y': (0, 2)}) self.assertEqual(expr.apply(scatter), np.array([False, True, True, False, False])) self.assertEqual(region, Rectangles([(1, 0, 3, 2)]) * Path([])) def test_scatter_selection_numeric_inverted(self): scatter = Scatter([3, 2, 1, 3, 4]).opts(invert_axes=True) expr, bbox, region = scatter._get_selection_expr_for_stream_value(bounds=(0, 1, 2, 3)) self.assertEqual(bbox, {'x': (1, 3), 'y': (0, 2)}) self.assertEqual(expr.apply(scatter), np.array([False, True, True, False, False])) self.assertEqual(region, Rectangles([(0, 1, 2, 3)]) * Path([])) def test_scatter_selection_categorical(self): scatter = Scatter((['B', 'A', 'C', 'D', 'E'], [3, 2, 1, 3, 4])) expr, bbox, region = scatter._get_selection_expr_for_stream_value( bounds=(0, 1, 2, 3), x_selection=['B', 'A', 'C'], y_selection=None ) self.assertEqual(bbox, {'x': ['B', 'A', 'C'], 'y': (1, 3)}) self.assertEqual(expr.apply(scatter), np.array([True, True, True, False, False])) self.assertEqual(region, Rectangles([(0, 1, 2, 3)]) * Path([])) def test_scatter_selection_numeric_index_cols(self): scatter = Scatter([3, 2, 1, 3, 2]) expr, bbox, region = scatter._get_selection_expr_for_stream_value( bounds=(1, 0, 3, 2), index_cols=['y'] ) self.assertEqual(bbox, {'x': (1, 3), 'y': (0, 2)}) self.assertEqual(expr.apply(scatter), np.array([False, False, True, False, False])) self.assertEqual(region, None) def test_image_selection_numeric(self): img = Image(([0, 1, 2], [0, 1, 2, 3], np.random.rand(4, 3))) expr, bbox, region = img._get_selection_expr_for_stream_value(bounds=(0.5, 1.5, 2.1, 3.1)) self.assertEqual(bbox, {'x': (0.5, 2.1), 'y': (1.5, 3.1)}) self.assertEqual(expr.apply(img, expanded=True, flat=False), np.array([ [False, False, False], [False, False, False], [False, True, True], [False, True, True] ])) self.assertEqual(region, Rectangles([(0.5, 1.5, 2.1, 3.1)]) * Path([])) def test_image_selection_numeric_inverted(self): img = Image(([0, 1, 2], [0, 1, 2, 3], np.random.rand(4, 3))).opts(invert_axes=True) expr, bbox, region = img._get_selection_expr_for_stream_value(bounds=(1.5, 0.5, 3.1, 2.1)) self.assertEqual(bbox, {'x': (0.5, 2.1), 'y': (1.5, 3.1)}) self.assertEqual(expr.apply(img, expanded=True, flat=False), np.array([ [False, False, False], [False, False, False], [False, True, True], [False, True, True] ])) self.assertEqual(region, Rectangles([(1.5, 0.5, 3.1, 2.1)]) * Path([])) @ds_available @spd_available def test_img_selection_geom(self): img = Image(([0, 1, 2], [0, 1, 2, 3], np.random.rand(4, 3))) geom = np.array([(-0.4, -0.1), (0.6, -0.1), (0.4, 1.7), (-0.1, 1.7)]) expr, bbox, region = img._get_selection_expr_for_stream_value(geometry=geom) self.assertEqual(bbox, {'x': np.array([-0.4, 0.6, 0.4, -0.1]), 'y': np.array([-0.1, -0.1, 1.7, 1.7])}) self.assertEqual(expr.apply(img, expanded=True, flat=False), np.array([ [ 1., np.nan, np.nan], [ 1., np.nan, np.nan], [np.nan, np.nan, np.nan], [np.nan, np.nan, np.nan] ])) self.assertEqual(region, Rectangles([]) * Path([list(geom)+[(-0.4, -0.1)]])) @ds_available def test_img_selection_geom_inverted(self): img = Image(([0, 1, 2], [0, 1, 2, 3], np.random.rand(4, 3))).opts(invert_axes=True) geom = np.array([(-0.4, -0.1), (0.6, -0.1), (0.4, 1.7), (-0.1, 1.7)]) expr, bbox, region = img._get_selection_expr_for_stream_value(geometry=geom) self.assertEqual(bbox, {'y': np.array([-0.4, 0.6, 0.4, -0.1]), 'x': np.array([-0.1, -0.1, 1.7, 1.7])}) self.assertEqual(expr.apply(img, expanded=True, flat=False), np.array([ [ True, True, False], [ False, False, False], [ False, False, False], [False, False, False] ])) self.assertEqual(region, Rectangles([]) * Path([list(geom)+[(-0.4, -0.1)]])) def test_rgb_selection_numeric(self): img = RGB(([0, 1, 2], [0, 1, 2, 3], np.random.rand(4, 3, 3))) expr, bbox, region = img._get_selection_expr_for_stream_value(bounds=(0.5, 1.5, 2.1, 3.1)) self.assertEqual(bbox, {'x': (0.5, 2.1), 'y': (1.5, 3.1)}) self.assertEqual(expr.apply(img, expanded=True, flat=False), np.array([ [False, False, False], [False, False, False], [False, True, True], [False, True, True] ])) self.assertEqual(region, Rectangles([(0.5, 1.5, 2.1, 3.1)]) * Path([])) def test_rgb_selection_numeric_inverted(self): img = RGB(([0, 1, 2], [0, 1, 2, 3], np.random.rand(4, 3, 3))).opts(invert_axes=True) expr, bbox, region = img._get_selection_expr_for_stream_value(bounds=(1.5, 0.5, 3.1, 2.1)) self.assertEqual(bbox, {'x': (0.5, 2.1), 'y': (1.5, 3.1)}) self.assertEqual(expr.apply(img, expanded=True, flat=False), np.array([ [False, False, False], [False, False, False], [False, True, True], [False, True, True] ])) self.assertEqual(region, Rectangles([(1.5, 0.5, 3.1, 2.1)]) * Path([])) def test_quadmesh_selection(self): n = 4 coords = np.linspace(-1.5,1.5,n) X,Y = np.meshgrid(coords, coords); Qx = np.cos(Y) - np.cos(X) Qy = np.sin(Y) + np.sin(X) Z = np.sqrt(X**2 + Y**2) qmesh = QuadMesh((Qx, Qy, Z)) expr, bbox, region = qmesh._get_selection_expr_for_stream_value(bounds=(0, -0.5, 0.7, 1.5)) self.assertEqual(bbox, {'x': (0, 0.7), 'y': (-0.5, 1.5)}) self.assertEqual(expr.apply(qmesh, expanded=True, flat=False), np.array([ [False, False, False, True], [False, False, True, False], [False, True, True, False], [True, False, False, False] ])) self.assertEqual(region, Rectangles([(0, -0.5, 0.7, 1.5)]) * Path([])) def test_quadmesh_selection_inverted(self): n = 4 coords = np.linspace(-1.5,1.5,n) X,Y = np.meshgrid(coords, coords); Qx = np.cos(Y) - np.cos(X) Qy = np.sin(Y) + np.sin(X) Z = np.sqrt(X**2 + Y**2) qmesh = QuadMesh((Qx, Qy, Z)).opts(invert_axes=True) expr, bbox, region = qmesh._get_selection_expr_for_stream_value(bounds=(0, -0.5, 0.7, 1.5)) self.assertEqual(bbox, {'x': (-0.5, 1.5), 'y': (0, 0.7)}) self.assertEqual(expr.apply(qmesh, expanded=True, flat=False), np.array([ [False, False, False, True], [False, False, True, True], [False, True, False, False], [True, False, False, False] ])) self.assertEqual(region, Rectangles([(0, -0.5, 0.7, 1.5)]) * Path([])) class TestSelectionGeomExpr(ComparisonTestCase): def setUp(self): try: import holoviews.plotting.bokeh # noqa except: raise SkipTest("Bokeh selection tests require bokeh.") super(TestSelectionGeomExpr, self).setUp() self._backend = Store.current_backend Store.set_current_backend('bokeh') def tearDown(self): Store.current_backend = self._backend def test_rect_selection_numeric(self): rect = Rectangles([(0, 1, 2, 3), (1, 3, 1.5, 4), (2.5, 4.2, 3.5, 4.8)]) expr, bbox, region = rect._get_selection_expr_for_stream_value(bounds=(0.5, 0.9, 3.4, 4.9)) self.assertEqual(bbox, {'x0': (0.5, 3.4), 'y0': (0.9, 4.9), 'x1': (0.5, 3.4), 'y1': (0.9, 4.9)}) self.assertEqual(expr.apply(rect), np.array([False, True, False])) self.assertEqual(region, Rectangles([(0.5, 0.9, 3.4, 4.9)]) * Path([])) expr, bbox, region = rect._get_selection_expr_for_stream_value(bounds=(0, 0.9, 3.5, 4.9)) self.assertEqual(bbox, {'x0': (0, 3.5), 'y0': (0.9, 4.9), 'x1': (0, 3.5), 'y1': (0.9, 4.9)}) self.assertEqual(expr.apply(rect), np.array([True, True, True])) self.assertEqual(region, Rectangles([(0, 0.9, 3.5, 4.9)]) * Path([])) def test_rect_selection_numeric_inverted(self): rect = Rectangles([(0, 1, 2, 3), (1, 3, 1.5, 4), (2.5, 4.2, 3.5, 4.8)]).opts(invert_axes=True) expr, bbox, region = rect._get_selection_expr_for_stream_value(bounds=(0.9, 0.5, 4.9, 3.4)) self.assertEqual(bbox, {'x0': (0.5, 3.4), 'y0': (0.9, 4.9), 'x1': (0.5, 3.4), 'y1': (0.9, 4.9)}) self.assertEqual(expr.apply(rect), np.array([False, True, False])) self.assertEqual(region, Rectangles([(0.9, 0.5, 4.9, 3.4)]) * Path([])) expr, bbox, region = rect._get_selection_expr_for_stream_value(bounds=(0.9, 0, 4.9, 3.5)) self.assertEqual(bbox, {'x0': (0, 3.5), 'y0': (0.9, 4.9), 'x1': (0, 3.5), 'y1': (0.9, 4.9)}) self.assertEqual(expr.apply(rect), np.array([True, True, True])) self.assertEqual(region, Rectangles([(0.9, 0, 4.9, 3.5)]) * Path([])) @shapely_available def test_rect_geom_selection(self): rect = Rectangles([(0, 1, 2, 3), (1, 3, 1.5, 4), (2.5, 4.2, 3.5, 4.8)]) geom = np.array([(-0.4, -0.1), (2.2, -0.1), (2.2, 4.1), (-0.1, 4.2)]) expr, bbox, region = rect._get_selection_expr_for_stream_value(geometry=geom) self.assertEqual(bbox, {'x0': np.array([-0.4, 2.2, 2.2, -0.1]), 'y0': np.array([-0.1, -0.1, 4.1, 4.2]), 'x1': np.array([-0.4, 2.2, 2.2, -0.1]), 'y1': np.array([-0.1, -0.1, 4.1, 4.2])}) self.assertEqual(expr.apply(rect), np.array([True, True, False])) self.assertEqual(region, Rectangles([]) * Path([list(geom)+[(-0.4, -0.1)]])) @shapely_available def test_rect_geom_selection_inverted(self): rect = Rectangles([(0, 1, 2, 3), (1, 3, 1.5, 4), (2.5, 4.2, 3.5, 4.8)]).opts(invert_axes=True) geom = np.array([(-0.4, -0.1), (3.2, -0.1), (3.2, 4.1), (-0.1, 4.2)]) expr, bbox, region = rect._get_selection_expr_for_stream_value(geometry=geom) self.assertEqual(bbox, {'y0': np.array([-0.4, 3.2, 3.2, -0.1]), 'x0': np.array([-0.1, -0.1, 4.1, 4.2]), 'y1': np.array([-0.4, 3.2, 3.2, -0.1]), 'x1': np.array([-0.1, -0.1, 4.1, 4.2])}) self.assertEqual(expr.apply(rect), np.array([True, False, False])) self.assertEqual(region, Rectangles([]) * Path([list(geom)+[(-0.4, -0.1)]])) def test_segments_selection_numeric(self): segs = Segments([(0, 1, 2, 3), (1, 3, 1.5, 4), (2.5, 4.2, 3.5, 4.8)]) expr, bbox, region = segs._get_selection_expr_for_stream_value(bounds=(0.5, 0.9, 3.4, 4.9)) self.assertEqual(bbox, {'x0': (0.5, 3.4), 'y0': (0.9, 4.9), 'x1': (0.5, 3.4), 'y1': (0.9, 4.9)}) self.assertEqual(expr.apply(segs), np.array([False, True, False])) self.assertEqual(region, Rectangles([(0.5, 0.9, 3.4, 4.9)]) * Path([])) expr, bbox, region = segs._get_selection_expr_for_stream_value(bounds=(0, 0.9, 3.5, 4.9)) self.assertEqual(bbox, {'x0': (0, 3.5), 'y0': (0.9, 4.9), 'x1': (0, 3.5), 'y1': (0.9, 4.9)}) self.assertEqual(expr.apply(segs), np.array([True, True, True])) self.assertEqual(region, Rectangles([(0, 0.9, 3.5, 4.9)]) * Path([])) def test_segs_selection_numeric_inverted(self): segs = Segments([(0, 1, 2, 3), (1, 3, 1.5, 4), (2.5, 4.2, 3.5, 4.8)]).opts(invert_axes=True) expr, bbox, region = segs._get_selection_expr_for_stream_value(bounds=(0.9, 0.5, 4.9, 3.4)) self.assertEqual(bbox, {'x0': (0.5, 3.4), 'y0': (0.9, 4.9), 'x1': (0.5, 3.4), 'y1': (0.9, 4.9)}) self.assertEqual(expr.apply(segs), np.array([False, True, False])) self.assertEqual(region, Rectangles([(0.9, 0.5, 4.9, 3.4)]) * Path([])) expr, bbox, region = segs._get_selection_expr_for_stream_value(bounds=(0.9, 0, 4.9, 3.5)) self.assertEqual(bbox, {'x0': (0, 3.5), 'y0': (0.9, 4.9), 'x1': (0, 3.5), 'y1': (0.9, 4.9)}) self.assertEqual(expr.apply(segs), np.array([True, True, True])) self.assertEqual(region, Rectangles([(0.9, 0, 4.9, 3.5)]) * Path([])) @shapely_available def test_segs_geom_selection(self): rect = Segments([(0, 1, 2, 3), (1, 3, 1.5, 4), (2.5, 4.2, 3.5, 4.8)]) geom = np.array([(-0.4, -0.1), (2.2, -0.1), (2.2, 4.1), (-0.1, 4.2)]) expr, bbox, region = rect._get_selection_expr_for_stream_value(geometry=geom) self.assertEqual(bbox, {'x0': np.array([-0.4, 2.2, 2.2, -0.1]), 'y0': np.array([-0.1, -0.1, 4.1, 4.2]), 'x1': np.array([-0.4, 2.2, 2.2, -0.1]), 'y1': np.array([-0.1, -0.1, 4.1, 4.2])}) self.assertEqual(expr.apply(rect), np.array([True, True, False])) self.assertEqual(region, Rectangles([]) * Path([list(geom)+[(-0.4, -0.1)]])) @shapely_available def test_segs_geom_selection_inverted(self): rect = Segments([(0, 1, 2, 3), (1, 3, 1.5, 4), (2.5, 4.2, 3.5, 4.8)]).opts(invert_axes=True) geom = np.array([(-0.4, -0.1), (3.2, -0.1), (3.2, 4.1), (-0.1, 4.2)]) expr, bbox, region = rect._get_selection_expr_for_stream_value(geometry=geom) self.assertEqual(bbox, {'y0': np.array([-0.4, 3.2, 3.2, -0.1]), 'x0': np.array([-0.1, -0.1, 4.1, 4.2]), 'y1': np.array([-0.4, 3.2, 3.2, -0.1]), 'x1': np.array([-0.1, -0.1, 4.1, 4.2])}) self.assertEqual(expr.apply(rect), np.array([True, False, False])) self.assertEqual(region, Rectangles([]) * Path([list(geom)+[(-0.4, -0.1)]])) class TestSelectionPolyExpr(ComparisonTestCase): def setUp(self): try: import holoviews.plotting.bokeh # noqa except: raise SkipTest("Bokeh selection tests require bokeh.") super(TestSelectionPolyExpr, self).setUp() self._backend = Store.current_backend Store.set_current_backend('bokeh') def tearDown(self): Store.current_backend = self._backend def test_poly_selection_numeric(self): poly = Polygons([ [(0, 0), (0.2, 0.1), (0.3, 0.4), (0.1, 0.2)], [(0.25, -.1), (0.4, 0.2), (0.6, 0.3), (0.5, 0.1)], [(0.3, 0.3), (0.5, 0.4), (0.6, 0.5), (0.35, 0.45)] ]) expr, bbox, region = poly._get_selection_expr_for_stream_value(bounds=(0.2, -0.2, 0.6, 0.6)) self.assertEqual(bbox, {'x': (0.2, 0.6), 'y': (-0.2, 0.6)}) self.assertEqual(expr.apply(poly, expanded=False), np.array([False, True, True])) self.assertEqual(region, Rectangles([(0.2, -0.2, 0.6, 0.6)]) * Path([])) def test_poly_selection_numeric_inverted(self): poly = Polygons([ [(0, 0), (0.2, 0.1), (0.3, 0.4), (0.1, 0.2)], [(0.25, -.1), (0.4, 0.2), (0.6, 0.3), (0.5, 0.1)], [(0.3, 0.3), (0.5, 0.4), (0.6, 0.5), (0.35, 0.45)] ]).opts(invert_axes=True) expr, bbox, region = poly._get_selection_expr_for_stream_value(bounds=(0.2, -0.2, 0.6, 0.6)) self.assertEqual(bbox, {'y': (0.2, 0.6), 'x': (-0.2, 0.6)}) self.assertEqual(expr.apply(poly, expanded=False), np.array([False, False, True])) self.assertEqual(region, Rectangles([(0.2, -0.2, 0.6, 0.6)]) * Path([])) @shapely_available def test_poly_geom_selection(self): poly = Polygons([ [(0, 0), (0.2, 0.1), (0.3, 0.4), (0.1, 0.2)], [(0.25, -.1), (0.4, 0.2), (0.6, 0.3), (0.5, 0.1)], [(0.3, 0.3), (0.5, 0.4), (0.6, 0.5), (0.35, 0.45)] ]) geom = np.array([(0.2, -0.15), (0.5, 0), (0.75, 0.6), (0.1, 0.45)]) expr, bbox, region = poly._get_selection_expr_for_stream_value(geometry=geom) self.assertEqual(bbox, {'x': np.array([0.2, 0.5, 0.75, 0.1]), 'y': np.array([-0.15, 0, 0.6, 0.45])}) self.assertEqual(expr.apply(poly, expanded=False), np.array([False, True, True])) self.assertEqual(region, Rectangles([]) * Path([list(geom)+[(0.2, -0.15)]])) @shapely_available def test_poly_geom_selection_inverted(self): poly = Polygons([ [(0, 0), (0.2, 0.1), (0.3, 0.4), (0.1, 0.2)], [(0.25, -.1), (0.4, 0.2), (0.6, 0.3), (0.5, 0.1)], [(0.3, 0.3), (0.5, 0.4), (0.6, 0.5), (0.35, 0.45)] ]).opts(invert_axes=True) geom = np.array([(0.2, -0.15), (0.5, 0), (0.75, 0.6), (0.1, 0.6)]) expr, bbox, region = poly._get_selection_expr_for_stream_value(geometry=geom) self.assertEqual(bbox, {'y': np.array([0.2, 0.5, 0.75, 0.1]), 'x': np.array([-0.15, 0, 0.6, 0.6])}) self.assertEqual(expr.apply(poly, expanded=False), np.array([False, False, True])) self.assertEqual(region, Rectangles([]) * Path([list(geom)+[(0.2, -0.15)]]))