def test_batched_points_line_width_and_color(self): opts = { 'NdOverlay': dict(plot=dict(legend_limit=0)), 'Points': dict(style=dict(line_width=Cycle(values=[0.5, 1]))) } overlay = NdOverlay( {i: Points([(i, j) for j in range(2)]) for i in range(2)}).opts(opts) plot = bokeh_renderer.get_plot(overlay).subplots[()] line_width = np.array([0.5, 0.5, 1., 1.]) color = np.array(['#30a2da', '#30a2da', '#fc4f30', '#fc4f30'], dtype='<U7') self.assertEqual(plot.handles['source'].data['line_width'], line_width) self.assertEqual(plot.handles['source'].data['color'], color)
def test_points_overlay_datetime_hover(self): if pd is None: raise SkipTest("Test requires pandas") obj = NdOverlay( { i: Points((list(pd.date_range('2016-01-01', '2016-01-31')), range(31))) for i in range(5) }, kdims=['Test']) opts = {'Points': {'tools': ['hover']}} obj = obj(plot=opts) self._test_hover_info(obj, [('Test', '@{Test}'), ('x', '@{x_dt_strings}'), ('y', '@{y}')])
def test_curve_overlay_hover_batched(self): obj = NdOverlay({i: Curve(np.random.rand(10, 2)) for i in range(5)}, kdims=['Test']) opts = { 'Curve': { 'tools': ['hover'] }, 'NdOverlay': { 'legend_limit': 0 } } obj = obj(plot=opts) self._test_hover_info(obj, [('Test', '@{Test}')], 'prev')
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_cyclic_palette_curves(self): palette = Palette('Set1') opts = dict(color=palette) hmap = HoloMap({ i: NdOverlay({ j: Curve(np.random.rand(3)).opts(style=opts) for j in range(3) }) for i in range(3) }) colors = palette[3].values plot = bokeh_renderer.get_plot(hmap) for subp, color in zip(plot.subplots.values(), colors): self.assertEqual(subp.handles['glyph'].line_color, rgb2hex(color))
def test_polygons_colored_batched_unsanitized(self): polygons = NdOverlay({ j: Polygons([[(i**j, i) for i in range(10)] for i in range(2)], level=j, vdims=['some ? unescaped name']) for j in range(5) }).opts(plot=dict(legend_limit=0)) plot = list(bokeh_renderer.get_plot(polygons).subplots.values())[0] cmapper = plot.handles['color_mapper'] self.assertEqual(cmapper.low, 0) self.assertEqual(cmapper.high, 4) source = plot.handles['source'] self.assertEqual(source.data['some_question_mark_unescaped_name'], [j for i in range(5) for j in [i, i]])
def test_batched_curve_subscribers_correctly_attached(self): posx = PointerX() opts = { 'NdOverlay': dict(plot=dict(legend_limit=0)), 'Curve': dict(style=dict(line_color=Cycle(values=['red', 'blue']))) } overlay = DynamicMap(lambda x: NdOverlay( {i: Curve([(i, j) for j in range(2)]) for i in range(2)}).opts(opts), kdims=[], streams=[posx]) plot = bokeh_renderer.get_plot(overlay) self.assertIn(plot.refresh, posx.subscribers) self.assertNotIn( list(plot.subplots.values())[0].refresh, posx.subscribers)
def test_points_overlay_hover(self): obj = NdOverlay({i: Points(np.random.rand(10, 2)) for i in range(5)}, kdims=['Test']) opts = { 'Points': { 'tools': ['hover'] }, 'NdOverlay': { 'legend_limit': 0 } } obj = obj(plot=opts) self._test_hover_info(obj, [('Test', '@{Test}'), ('x', '@{x}'), ('y', '@{y}')])
def test_points_errorbars_text_ndoverlay_categorical_xaxis_invert_axes( self): overlay = NdOverlay({ i: Points(([chr(65 + i)] * 10, np.random.randn(10))) for i in range(5) }) error = ErrorBars([ (el['x'][0], np.mean(el['y']), np.std(el['y'])) for el in overlay ]).opts(plot=dict(invert_axes=True)) text = Text('C', 0, 'Test') plot = bokeh_renderer.get_plot(overlay * error * text) x_range = plot.handles['x_range'] y_range = plot.handles['y_range'] self.assertIsInstance(x_range, Range1d) self.assertIsInstance(y_range, FactorRange) self.assertEqual(y_range.factors, ['A', 'B', 'C', 'D', 'E'])
def test_points_errorbars_text_ndoverlay_categorical_xaxis(self): overlay = NdOverlay({i: Points(([chr(65+i)]*10,np.random.randn(10))) for i in range(5)}) error = ErrorBars([(el['x'][0], np.mean(el['y']), np.std(el['y'])) for el in overlay]) text = Text('C', 0, 'Test') plot = bokeh_renderer.get_plot(overlay*error*text) x_range = plot.handles['x_range'] y_range = plot.handles['y_range'] self.assertIsInstance(x_range, FactorRange) factors = ['A', 'B', 'C', 'D', 'E'] self.assertEqual(x_range.factors, ['A', 'B', 'C', 'D', 'E']) self.assertIsInstance(y_range, Range1d) error_plot = plot.subplots[('ErrorBars', 'I')] for xs, factor in zip(error_plot.handles['source'].data['base'], factors): self.assertEqual(factor, xs)
def test_batched_curve_subscribers_correctly_linked(self): # Checks if a stream callback is created to link batched plot # to the stream posx = PointerX() opts = { 'NdOverlay': dict(plot=dict(legend_limit=0)), 'Curve': dict(style=dict(line_color=Cycle(values=['red', 'blue']))) } overlay = DynamicMap(lambda x: NdOverlay( {i: Curve([(i, j) for j in range(2)]) for i in range(2)}).opts(opts), kdims=[], streams=[posx]) plot = bokeh_renderer.get_plot(overlay) self.assertEqual(len(Callback._callbacks), 1) key = list(Callback._callbacks.keys())[0] self.assertEqual(key, (id(plot.handles['plot']), id(PointerXCallback)))
def test_polygons_overlay_hover(self): obj = NdOverlay( { i: Polygons([np.random.rand(10, 2)], vdims=['z'], level=0) for i in range(5) }, kdims=['Test']) opts = { 'Polygons': { 'tools': ['hover'] }, 'NdOverlay': { 'legend_limit': 0 } } obj = obj(plot=opts) self._test_hover_info(obj, [('Test', '@{Test}'), ('z', '@{z}')])
def test_segments_overlay_datetime_hover(self): if pd is None: raise SkipTest("Test requires pandas") obj = NdOverlay( { i: Segments( (list(pd.date_range('2016-01-01', '2016-01-31')), range(31), pd.date_range('2016-01-02', '2016-02-01'), range(31))) for i in range(5) }, kdims=['Test']).opts({'Segments': { 'tools': ['hover'] }}) tooltips = [('Test', '@{Test}'), ('x0', '@{x0}{%F %T}'), ('y0', '@{y0}'), ('x1', '@{x1}{%F %T}'), ('y1', '@{y1}')] formatters = {'@{x0}': "datetime", '@{x1}': "datetime"} self._test_hover_info(obj, tooltips, formatters=formatters)
def test_batched_points(self): overlay = NdOverlay({i: Points(np.arange(i)) for i in range(1, 100)}) plot = bokeh_renderer.get_plot(overlay) extents = plot.get_extents(overlay, {}) self.assertEqual(extents, (0, 0, 98, 98))
def from_records(cls, records, dataset=None, on=None, value=None, index=[], drop_missing=False, **kwargs): """ Load data from a collection of ``cartopy.io.shapereader.Record`` objects and optionally merge it with a dataset to assign values to each polygon and form a chloropleth. Supplying just records will return an NdOverlay of Shape Elements with a numeric index. If a dataset is supplied, a mapping between the attribute names in the records and the dimension names in the dataset must be supplied. The values assigned to each shape file can then be drawn from the dataset by supplying a ``value`` and keys the Shapes are indexed by specifying one or index dimensions. * records - An iterator of cartopy.io.shapereader.Record objects. * dataset - Any HoloViews Dataset type. * on - A mapping between the attribute names in the records and the dimensions in the dataset. * value - The value dimension in the dataset the values will be drawn from. * index - One or more dimensions in the dataset the Shapes will be indexed by. * drop_missing - Whether to drop shapes which are missing from the provided dataset. Returns an NdOverlay of Shapes. """ if dataset is not None and not on: raise ValueError('To merge dataset with shapes mapping ' 'must define attribute(s) to merge on.') if pd and isinstance(dataset, pd.DataFrame): dataset = Dataset(dataset) if not isinstance(on, (dict, list)): on = [on] if on and not isinstance(on, dict): on = {o: o for o in on} if not isinstance(index, list): index = [index] kdims = [] for ind in (index if index else ['Index']): if dataset and dataset.get_dimension(ind): dim = dataset.get_dimension(ind) else: dim = Dimension(ind) kdims.append(dim) ddims = [] if dataset: vdim = dataset.get_dimension(value) kwargs['vdims'] = [vdim] if not vdim: raise ValueError('Value dimension not found ' 'in dataset: {}'.format(vdim)) ddims = dataset.dimensions() data = [] notfound = False for i, rec in enumerate(records): if dataset: selection = { dim: rec.attributes.get(attr, None) for attr, dim in on.items() } row = dataset.select(**selection) if len(row): value = row[vdim.name][0] elif drop_missing: continue else: value = np.NaN kwargs['level'] = value if index: key = [] for kdim in kdims: if kdim in ddims and len(row): k = row[kdim.name][0] elif kdim.name in rec.attributes: k = rec.attributes[kdim.name] else: k = None notfound = True key.append(k) key = tuple(key) else: key = (i, ) data.append((key, Shape(rec.geometry, **kwargs))) if notfound: kdims = ['Index'] + kdims data = [((i, ) + subk, v) for i, (subk, v) in enumerate(data)] return NdOverlay(data, kdims=kdims)
def test_ndoverlay_legend_muted(self): overlay = NdOverlay({i: Curve(np.random.randn(10).cumsum()) for i in range(5)}).options(legend_muted=True) plot = bokeh_renderer.get_plot(overlay) for sp in plot.subplots.values(): self.assertTrue(sp.handles['glyph_renderer'].muted)
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_overlay_empty_layers(self): overlay = Curve(range(10)) * NdOverlay() plot = bokeh_renderer.get_plot(overlay) self.assertEqual(len(plot.subplots), 1) self.log_handler.assertContains('WARNING', 'is empty and will be skipped during plotting')
def test_curve_overlay_datetime_hover(self): obj = NdOverlay({i: Curve((list(pd.date_range('2016-01-01', '2016-01-31')), range(31))) for i in range(5)}, kdims=['Test']) opts = {'Curve': {'tools': ['hover']}} obj = obj(plot=opts) self._test_hover_info(obj, [('Test', '@{Test}'), ('x', '@{x_dt_strings}'), ('y', '@{y}')])
def test_collate_ndoverlay(self): collated = self.nested_overlay.collate(NdOverlay) ndoverlay = NdOverlay(self.phase_boundaries, kdims=self.dimensions) self.assertEqual(collated.kdims, ndoverlay.kdims) self.assertEqual(collated.keys(), ndoverlay.keys()) self.assertEqual(repr(collated), repr(ndoverlay))
def test_overlay_propagates_batched(self): overlay = NdOverlay({ i: Curve([1, 2, 3]).opts(yformatter='%.1f') for i in range(10) }).opts(yformatter='%.3f', legend_limit=1) plot = bokeh_renderer.get_plot(overlay) self.assertEqual(plot.state.yaxis.formatter.format, '%.3f')
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 cb(X): return NdOverlay({i: Curve(np.arange(10)+i) for i in range(X-2, X)})
def callback(items): return NdOverlay({j: Overlay([Curve([1, 2, j])]) for j in range(items)})
def test_overlay_empty_layers(self): overlay = Curve(range(10)) * NdOverlay() plot = mpl_renderer.get_plot(overlay) self.assertEqual(len(plot.subplots), 1)
def test_curve_overlay_hover(self): obj = NdOverlay({i: Curve(np.random.rand(10,2)) for i in range(5)}, kdims=['Test']) opts = {'Curve': {'tools': ['hover']}} obj = obj(plot=opts) self._test_hover_info(obj, [('Test', '@{Test}'), ('x', '@{x}'), ('y', '@{y}')], 'nearest')
def test_op_ndoverlay_value(self): colors = ['blue', 'red'] overlay = NdOverlay({color: Spikes(np.arange(i+2)) for i, color in enumerate(colors)}, 'Color').options('Spikes', color='Color') plot = bokeh_renderer.get_plot(overlay) for subplot, color in zip(plot.subplots.values(), colors): self.assertEqual(subplot.handles['glyph'].line_color, color)
def test_layout_empty_subplots(self): layout = Curve(range(10)) + NdOverlay() + HoloMap() + HoloMap({1: Image(np.random.rand(10,10))}) plot = bokeh_renderer.get_plot(layout) self.assertEqual(len(plot.subplots.values()), 2)
def test_callback_on_ndoverlay_is_attached(self): ndoverlay = NdOverlay({i: Curve([i]) for i in range(5)}) selection = Selection1D(source=ndoverlay) plot = bokeh_renderer.get_plot(ndoverlay) self.assertEqual(len(plot.callbacks), 1) self.assertIsInstance(plot.callbacks[0], Selection1DCallback)