diff --git a/holoviews/plotting/bokeh/annotation.py b/holoviews/plotting/bokeh/annotation.py index c307c01322..715d56e169 100644 --- a/holoviews/plotting/bokeh/annotation.py +++ b/holoviews/plotting/bokeh/annotation.py @@ -251,7 +251,7 @@ def _init_glyph(self, plot, mapping, properties, key): """ Returns a Bokeh glyph object. """ - properties.pop('legend', None) + properties = {k: v for k, v in properties.items() if 'legend' not in k} if key == 'arrow': properties.pop('source') arrow_end = mapping.pop('arrow_end') diff --git a/holoviews/plotting/bokeh/chart.py b/holoviews/plotting/bokeh/chart.py index 3b9eb6e7c3..095178c2d2 100644 --- a/holoviews/plotting/bokeh/chart.py +++ b/holoviews/plotting/bokeh/chart.py @@ -20,7 +20,7 @@ from .element import ElementPlot, ColorbarPlot, LegendPlot from .styles import (expand_batched_style, line_properties, fill_properties, mpl_to_bokeh, rgb2hex) -from .util import categorize_array +from .util import bokeh_version, categorize_array class PointPlot(LegendPlot, ColorbarPlot): @@ -532,7 +532,7 @@ def _init_glyph(self, plot, mapping, properties): """ Returns a Bokeh glyph object. """ - properties.pop('legend', None) + properties = {k: v for k, v in properties.items() if 'legend' not in k} for prop in ['color', 'alpha']: if prop not in properties: continue @@ -897,13 +897,14 @@ def _add_color_data(self, ds, ranges, style, cdim, data, mapping, factors, color # Enable legend if colormapper is categorical cmapper = cmapping['color']['transform'] + legend_prop = 'legend_field' if bokeh_version >= '1.3.5' else 'legend' if ('color' in cmapping and self.show_legend and isinstance(cmapper, CategoricalColorMapper)): - mapping['legend'] = cdim.name + mapping[legend_prop] = cdim.name if not (self.stacked or self.stack_index) and ds.ndims > 1: - cmapping.pop('legend', None) - mapping.pop('legend', None) + cmapping.pop(legend_prop, None) + mapping.pop(legend_prop, None) # Merge data and mappings mapping.update(cmapping) diff --git a/holoviews/plotting/bokeh/element.py b/holoviews/plotting/bokeh/element.py index 3bdeedb2f7..633cab66c3 100644 --- a/holoviews/plotting/bokeh/element.py +++ b/holoviews/plotting/bokeh/element.py @@ -36,7 +36,7 @@ legend_dimensions, line_properties, mpl_to_bokeh, property_prefixes, rgba_tuple, text_properties, validate) from .util import ( - TOOL_TYPES, date_to_integer, decode_bytes, get_tab_title, + TOOL_TYPES, bokeh_version, date_to_integer, decode_bytes, get_tab_title, glyph_order, py2js_tickformatter, recursive_model_update, theme_attr_json, cds_column_replace, hold_policy, match_dim_specs, compute_layout_properties, wrap_formatter) @@ -1021,7 +1021,7 @@ def _apply_transforms(self, element, data, ranges, style, group=None): data[k] = val # If color is not valid colorspec add colormapper - numeric = isinstance(val, util.arraylike_types) and val.dtype.kind in 'uifMm' + numeric = isinstance(val, util.arraylike_types) and val.dtype.kind in 'uifMmb' if ('color' in k and isinstance(val, util.arraylike_types) and (numeric or not validate('color', val))): kwargs = {} @@ -1031,12 +1031,14 @@ def _apply_transforms(self, element, data, ranges, style, group=None): factors = ranges[range_key]['factors'] else: factors = util.unique_array(val) + if isinstance(val, util.arraylike_types) and val.dtype.kind == 'b': + factors = factors.astype(str) kwargs['factors'] = factors cmapper = self._get_colormapper(v, element, ranges, dict(style), name=k+'_color_mapper', group=group, **kwargs) categorical = isinstance(cmapper, CategoricalColorMapper) - if categorical and val.dtype.kind in 'ifMu': + if categorical and val.dtype.kind in 'ifMub': if v.dimension in element: formatter = element.get_dimension(v.dimension).pprint_value else: @@ -1046,7 +1048,8 @@ def _apply_transforms(self, element, data, ranges, style, group=None): else: field = k if categorical and getattr(self, 'show_legend', False): - new_style['legend'] = field + legend_prop = 'legend_field' if bokeh_version >= '1.3.5' else 'legend' + new_style[legend_prop] = field key = {'field': field, 'transform': cmapper} new_style[k] = key @@ -1096,7 +1099,8 @@ def _glyph_properties(self, plot, element, source, ranges, style, group=None): else: legend = element.label if legend and self.overlaid: - properties['legend'] = value(legend) + legend_prop = 'legend_label' if bokeh_version >= '1.3.5' else 'legend' + properties[legend_prop] = value(legend) return properties @@ -1123,7 +1127,8 @@ def _update_glyph(self, renderer, properties, mapping, glyph, source, data): allowed_properties = glyph.properties() properties = mpl_to_bokeh(properties) merged = dict(properties, **mapping) - legend = merged.pop('legend', None) + legend_prop = 'legend_label' if bokeh_version >= '1.3.5' else 'legend' + legend = merged.pop(legend_prop, None) columns = list(source.data.keys()) glyph_updates = [] for glyph_type in ('', 'selection_', 'nonselection_', 'hover_', 'muted_'): @@ -1752,7 +1757,8 @@ def _get_color_data(self, element, ranges, style, name='color', factors=None, co data[field] = cdata if factors is not None and self.show_legend: - mapping['legend'] = {'field': field} + legend_prop = 'legend_field' if bokeh_version >= '1.3.5' else 'legend' + mapping[legend_prop] = {'field': field} mapping[name] = {'field': field, 'transform': mapper} return data, mapping diff --git a/holoviews/plotting/bokeh/graphs.py b/holoviews/plotting/bokeh/graphs.py index 89df1004e9..add2c7390f 100644 --- a/holoviews/plotting/bokeh/graphs.py +++ b/holoviews/plotting/bokeh/graphs.py @@ -300,7 +300,8 @@ def _get_graph_properties(self, plot, element, data, mapping, ranges, style): continue properties[k] = p mappings.update(mapping.pop(key, {})) - properties = {p: v for p, v in properties.items() if p not in ('legend', 'source')} + properties = {p: v for p, v in properties.items() + if p != 'source' and 'legend' not in p} properties.update(mappings) # Initialize graph layout diff --git a/holoviews/plotting/bokeh/path.py b/holoviews/plotting/bokeh/path.py index d3a33722ac..c81772f4d4 100644 --- a/holoviews/plotting/bokeh/path.py +++ b/holoviews/plotting/bokeh/path.py @@ -244,7 +244,8 @@ def get_data(self, element, ranges, style): cmapper = self._get_colormapper(cdim, element, ranges, style, factors) mapping[self._color_style] = {'field': dim_name, 'transform': cmapper} if self.show_legend: - mapping['legend'] = dim_name + legend_prop = 'legend_field' if bokeh_version >= '1.3.5' else 'legend' + mapping[legend_prop] = dim_name return data, mapping, style def _init_glyph(self, plot, mapping, properties): diff --git a/holoviews/plotting/bokeh/stats.py b/holoviews/plotting/bokeh/stats.py index 2a00673a73..61818a99f1 100644 --- a/holoviews/plotting/bokeh/stats.py +++ b/holoviews/plotting/bokeh/stats.py @@ -17,7 +17,7 @@ from .element import CompositeElementPlot, ColorbarPlot, LegendPlot from .path import PolygonPlot from .styles import fill_properties, line_properties -from .util import decode_bytes +from .util import bokeh_version, decode_bytes class DistributionPlot(AreaPlot): @@ -95,7 +95,8 @@ def _get_axis_dims(self, element): def _glyph_properties(self, plot, element, source, ranges, style, group=None): properties = dict(style, source=source) if self.show_legend and not element.kdims and self.overlaid: - properties['legend'] = element.label + legend_prop = 'legend_label' if bokeh_version >= '1.3.5' else 'legend' + properties[legend_prop] = element.label return properties def _apply_transforms(self, element, data, ranges, style, group=None): @@ -281,7 +282,8 @@ def get_data(self, element, ranges, style): factors = list(unique_iterator(factors)) if self.show_legend: - vbar_map['legend'] = cdim.name + legend_prop = 'legend_field' if bokeh_version >= '1.3.5' else 'legend' + vbar_map[legend_prop] = cdim.name return data, mapping, style