Skip to content

Commit

Permalink
Various fixes and cleanup of bokeh BarsPlot
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Oct 27, 2017
1 parent b129189 commit 91b8b09
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 35 deletions.
70 changes: 37 additions & 33 deletions holoviews/plotting/bokeh/chart.py
Expand Up @@ -726,10 +726,12 @@ def get_stack(self, xvals, yvals, baselines, sign='positive'):
if sign == 'positive':
bottom = baseline
top = bottom+y
baseline = top
else:
top = baseline
bottom = top+y
baselines[x][sign] = top
baseline = bottom
baselines[x][sign] = baseline
bottoms.append(bottom)
tops.append(top)
return bottoms, tops
Expand All @@ -739,6 +741,31 @@ def _glyph_properties(self, *args):
del props['width']
return props


def _add_color_data(self, ds, ranges, style, cdim, data, mapping, factors, colors):
# Get colormapper
cdata, cmapping = self._get_color_data(ds, ranges, dict(style),
factors=factors, colors=colors)
if 'color' not in cmapping:
return

# Enable legend if colormapper is categorical
cmapper = cmapping['color']['transform']
if ('color' in cmapping and self.show_legend and
isinstance(cmapper, CategoricalColorMapper)):
mapping['legend'] = cdim.name

# Merge data and mappings
mapping.update(cmapping)
for k, cd in cdata.items():
if self.color_index is None and cd.dtype.kind in 'if':
cd = categorize_array(cd, color_dim)
if k not in data or len(data[k]) != [len(data[key]) for key in data if key != k][0]:
data[k].append(cd)
else:
data[k][-1] = cd


def get_data(self, element, ranges, style):
# Get x, y, group, stack and color dimensions
grouping = None
Expand Down Expand Up @@ -817,10 +844,8 @@ def get_data(self, element, ranges, style):
k = k[0] if isinstance(k, tuple) else k
if group_dim:
gval = k if isinstance(k, basestring) else group_dim.pprint_value(k)

# Apply stacking or grouping
if grouping == 'stacked':
ds = ds.sort(ds.vdims[0])
for sign, slc in [('negative', (None, 0)), ('positive', (0, None))]:
slc_ds = ds.select(**{ds.vdims[0].name: slc})
xs = slc_ds.dimension_values(xdim)
Expand All @@ -829,7 +854,10 @@ def get_data(self, element, ranges, style):
data['bottom'].append(bs)
data['top'].append(ts)
data[xdim.name].append(xs)
data[stack_dim.name].append(slc_ds.dimension_values(stack_dim))
if hover: data[ydim.name].append(ys)
self._add_color_data(slc_ds, ranges, style, cdim, data,
mapping, factors, colors)
elif grouping == 'grouped':
xs = ds.dimension_values(xdim)
ys = ds.dimension_values(ydim)
Expand All @@ -838,44 +866,20 @@ def get_data(self, element, ranges, style):
data['xoffsets'].append(xoffsets)
data[ydim.name].append(ys)
if hover: data[xdim.name].append(xs)
if group_dim not in ds.dimensions():
ds = ds.add_dimension(group_dim.name, ds.ndims, gval)
data[group_dim.name].append(ds.dimension_values(group_dim))
else:
data[xdim.name].append(ds.dimension_values(xdim))
data[ydim.name].append(ds.dimension_values(ydim))

# Add group dimension to data
if group_dim and group_dim not in ds.dimensions():
ds = ds.add_dimension(group_dim.name, ds.ndims, gval)

if hover:
# Fill in missing hover data if dimension other than group_dim is colormapped
if group_dim and cdim != group_dim:
data[group_dim.name].append(ds.dimension_values(group_dim))
# Add other hover info
for vd in ds.vdims[1:]:
data[vd.name].append(ds.dimension_values(vd))

# Get colormapper
cdata, cmapping = self._get_color_data(ds, ranges, dict(style),
factors=factors, colors=colors)

# Skip if no colormapper applied
if 'color' not in cmapping:
continue

# Enable legend if colormapper is categorical
cmapper = cmapping['color']['transform']
if ('color' in cmapping and self.show_legend and
isinstance(cmapper, CategoricalColorMapper)):
mapping['legend'] = cdim.name

# Merge data and mappings
mapping.update(cmapping)
for k, cd in cdata.items():
# If values have already been added, skip
if no_cidx and cd.dtype.kind in 'if':
cd = categorize_array(cd, color_dim)
if not len(data[k]) == i+1:
data[k].append(cd)
if not grouping == 'stacked':
self._add_color_data(ds, ranges, style, cdim, data,
mapping, factors, colors)

# Concatenate the stacks or groups
sanitized_data = {}
Expand Down
4 changes: 2 additions & 2 deletions tests/testplotinstantiation.py
Expand Up @@ -985,7 +985,7 @@ def test_bars_grouped_categories(self):
source = plot.handles['source']
self.assertEqual([tuple(x) for x in source.data['xoffsets']],
[('A', '0'), ('B', '0'), ('A', '1')])
self.assertEqual(list(source.data['Category']), ['0', '0', '1'])
self.assertEqual(list(source.data['Category']), [0, 0, 1])
self.assertEqual(source.data['Value'], np.array([1, 2, -1]))
x_range = plot.handles['x_range']
self.assertEqual(x_range.factors, [('A', '0'), ('A', '1'), ('B', '0'), ('B', '1')])
Expand All @@ -995,7 +995,7 @@ def test_bars_positive_negative_mixed(self):
kdims=['Index', 'Category'], vdims=['Value'])
plot = bokeh_renderer.get_plot(bars.opts(plot=dict(stack_index=1)))
source = plot.handles['source']
self.assertEqual(list(source.data['Category']), ['1', '0', '0'])
self.assertEqual(list(source.data['Category']), [1, 0, 0])
self.assertEqual(list(source.data['Index']), ['A', 'A', 'B'])
self.assertEqual(source.data['top'], np.array([0, 1, 2]))
self.assertEqual(source.data['bottom'], np.array([-1, 0, 0]))
Expand Down

0 comments on commit 91b8b09

Please sign in to comment.