import numpy as np from holoviews.core import (HoloMap, GridSpace, NdOverlay, Dataset, DynamicMap, GridMatrix) from holoviews.element import Curve, Image, Points from holoviews.operation import gridmatrix from holoviews.streams import Stream from .testplot import TestBokehPlot, bokeh_renderer try: from bokeh.layouts import Column from bokeh.models import Div, ToolbarBox from holoviews.plotting.bokeh.util import LooseVersion, bokeh_version except: pass class TestGridPlot(TestBokehPlot): def test_grid_title(self): grid = GridSpace({(i, j): HoloMap({a: Image(np.random.rand(10,10)) for a in range(3)}, kdims=['X']) for i in range(2) for j in range(3)}) plot = bokeh_renderer.get_plot(grid) title = plot.handles['title'] self.assertIsInstance(title, Div) text = ('X: 0') self.assertEqual(title.text, text) def test_grid_title_update(self): grid = GridSpace({(i, j): HoloMap({a: Image(np.random.rand(10,10)) for a in range(3)}, kdims=['X']) for i in range(2) for j in range(3)}) plot = bokeh_renderer.get_plot(grid) plot.update(1) title = plot.handles['title'] self.assertIsInstance(title, Div) text = ('X: 1') self.assertEqual(title.text, text) def test_gridmatrix_overlaid_batched(self): ds = Dataset((['A']*5+['B']*5, np.random.rand(10), np.random.rand(10)), kdims=['a', 'b', 'c']) gmatrix = gridmatrix(ds.groupby('a', container_type=NdOverlay)) plot = bokeh_renderer.get_plot(gmatrix) sp1 = plot.subplots[('b', 'c')] self.assertEqual(sp1.state.xaxis[0].visible, False) self.assertEqual(sp1.state.yaxis[0].visible, True) sp2 = plot.subplots[('b', 'b')] self.assertEqual(sp2.state.xaxis[0].visible, True) self.assertEqual(sp2.state.yaxis[0].visible, True) sp3 = plot.subplots[('c', 'b')] self.assertEqual(sp3.state.xaxis[0].visible, True) self.assertEqual(sp3.state.yaxis[0].visible, False) sp4 = plot.subplots[('c', 'c')] self.assertEqual(sp4.state.xaxis[0].visible, False) self.assertEqual(sp4.state.yaxis[0].visible, False) def test_gridspace_sparse(self): grid = GridSpace({(i, j): Curve(range(i+j)) for i in range(1, 3) for j in range(2,4) if not (i==1 and j == 2)}) plot = bokeh_renderer.get_plot(grid) size = bokeh_renderer.get_size(plot.state) if bokeh_version < LooseVersion('2.0.2'): self.assertEqual(size, (318, 310)) else: self.assertEqual(size, (320, 311)) def test_grid_shared_source_synced_update(self): hmap = HoloMap({i: Dataset({chr(65+j): np.random.rand(i+2) for j in range(4)}, kdims=['A', 'B', 'C', 'D']) for i in range(3)}) # Create two holomaps of points sharing the same data source hmap1= hmap.map(lambda x: Points(x.clone(kdims=['A', 'B'])), Dataset) hmap2 = hmap.map(lambda x: Points(x.clone(kdims=['D', 'C'])), Dataset) # Pop key (1,) for one of the HoloMaps and make GridSpace hmap2.pop(1) grid = GridSpace({0: hmap1, 2: hmap2}, kdims=['X']).opts(plot=dict(shared_datasource=True)) # Get plot plot = bokeh_renderer.get_plot(grid) # Check plot created shared data source and recorded expected columns sources = plot.handles.get('shared_sources', []) source_cols = plot.handles.get('source_cols', {}) self.assertEqual(len(sources), 1) source = sources[0] data = source.data cols = source_cols[id(source)] self.assertEqual(set(cols), {'A', 'B', 'C', 'D'}) # Ensure the source contains the expected columns self.assertEqual(set(data.keys()), {'A', 'B', 'C', 'D'}) # Update to key (1,) and check the source contains data # corresponding to hmap1 and filled in NaNs for hmap2, # which was popped above plot.update((1,)) self.assertEqual(data['A'], hmap1[1].dimension_values(0)) self.assertEqual(data['B'], hmap1[1].dimension_values(1)) self.assertEqual(data['C'], np.full_like(hmap1[1].dimension_values(0), np.NaN)) self.assertEqual(data['D'], np.full_like(hmap1[1].dimension_values(0), np.NaN)) def test_grid_set_toolbar_location(self): grid = GridSpace({0: Curve([]), 1: Points([])}, 'X').options(toolbar='left') plot = bokeh_renderer.get_plot(grid) self.assertIsInstance(plot.state, Column) self.assertIsInstance(plot.state.children[0].children[0], ToolbarBox) def test_grid_disable_toolbar(self): grid = GridSpace({0: Curve([]), 1: Points([])}, 'X').options(toolbar=None) plot = bokeh_renderer.get_plot(grid) self.assertIsInstance(plot.state, Column) self.assertEqual([p for p in plot.state.children if isinstance(p, ToolbarBox)], []) def test_grid_dimensioned_stream_title_update(self): stream = Stream.define('Test', test=0)() dmap = DynamicMap(lambda test: Curve([]), kdims=['test'], streams=[stream]) grid = GridMatrix({0: dmap, 1: Curve([])}, 'X') plot = bokeh_renderer.get_plot(grid) self.assertIn('test: 0', plot.handles['title'].text) stream.event(test=1) self.assertIn('test: 1', plot.handles['title'].text) plot.cleanup() self.assertEqual(stream._subscribers, [])