Skip to content

Commit

Permalink
Improved support for style mapping constant values (#3578)
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr authored and jlstevens committed Mar 26, 2019
1 parent f645b44 commit 8d7f701
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 6 deletions.
10 changes: 6 additions & 4 deletions holoviews/plotting/bokeh/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from bokeh.models.widgets import Panel, Tabs
from bokeh.plotting.helpers import _known_tools as known_tools

from ...core import DynamicMap, CompositeOverlay, Element, Dimension
from ...core import DynamicMap, CompositeOverlay, Element, Dimension, Dataset
from ...core.options import abbreviated_exception, SkipRendering
from ...core import util
from ...element import Graph, VectorField, Path, Contours, Tiles
Expand Down Expand Up @@ -953,16 +953,18 @@ def _apply_transforms(self, element, data, ranges, style, group=None):
'as not all dimensions could be resolved.' % (k, v))
continue

if len(v.ops) == 0 and v.dimension in self.overlay_dims:
val = self.overlay_dims[v.dimension]
if v.dimension in self.overlay_dims:
ds = Dataset({d.name: v for d, v in self.overlay_dims.items()},
list(self.overlay_dims))
val = v.apply(ds, ranges=ranges, flat=True)[0]
elif isinstance(element, Path) and not isinstance(element, Contours):
val = np.concatenate([v.apply(el, ranges=ranges, flat=True)[:-1]
for el in element.split()])
else:
val = v.apply(element, ranges=ranges, flat=True)

if (not util.isscalar(val) and len(util.unique_array(val)) == 1 and
(not 'color' in k or validate('color', val))):
((not 'color' in k or validate('color', val)) or k in self._nonvectorized_styles)):
val = val[0]

if not util.isscalar(val):
Expand Down
6 changes: 4 additions & 2 deletions holoviews/plotting/mpl/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -558,8 +558,10 @@ def _apply_transforms(self, element, ranges, style):
% (k, v))
continue

if len(v.ops) == 0 and v.dimension in self.overlay_dims:
val = self.overlay_dims[v.dimension]
if v.dimension in self.overlay_dims:
ds = Dataset({d.name: v for d, v in self.overlay_dims.items()},
list(self.overlay_dims))
val = v.apply(ds, ranges=ranges, flat=True)[0]
elif type(element) is Path:
val = np.concatenate([v.apply(el, ranges=ranges, flat=True)[:-1]
for el in element.split()])
Expand Down
53 changes: 53 additions & 0 deletions holoviews/tests/plotting/bokeh/testcurveplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from holoviews.element import Curve
from holoviews.plotting.util import rgb2hex
from holoviews.streams import PointerX
from holoviews.util.transform import dim

from .testplot import TestBokehPlot, bokeh_renderer

Expand Down Expand Up @@ -377,3 +378,55 @@ def test_curve_line_width_op(self):
vdims=['y', 'linewidth']).options(line_width='linewidth')
with self.assertRaises(Exception):
bokeh_renderer.get_plot(curve)

def test_curve_style_mapping_ndoverlay_dimensions(self):
ndoverlay = NdOverlay({
(0, 'A'): Curve([1, 2, 0]), (0, 'B'): Curve([1, 2, 1]),
(1, 'A'): Curve([1, 2, 2]), (1, 'B'): Curve([1, 2, 3])},
['num', 'cat']
).opts({
'Curve': dict(
color=dim('num').categorize({0: 'red', 1: 'blue'}),
line_dash=dim('cat').categorize({'A': 'solid', 'B': 'dashed'})
)
})
plot = bokeh_renderer.get_plot(ndoverlay)
for (num, cat), sp in plot.subplots.items():
glyph = sp.handles['glyph']
color = glyph.line_color
if num == 0:
self.assertEqual(color, 'red')
else:
self.assertEqual(color, 'blue')
linestyle = glyph.line_dash
if cat == 'A':
self.assertEqual(linestyle, [])
else:
self.assertEqual(linestyle, [6])

def test_curve_style_mapping_constant_value_dimensions(self):
vdims = ['y', 'num', 'cat']
ndoverlay = NdOverlay({
0: Curve([(0, 1, 0, 'A'), (1, 0, 0, 'A')], vdims=vdims),
1: Curve([(0, 1, 0, 'B'), (1, 1, 0, 'B')], vdims=vdims),
2: Curve([(0, 1, 1, 'A'), (1, 2, 1, 'A')], vdims=vdims),
3: Curve([(0, 1, 1, 'B'), (1, 3, 1, 'B')], vdims=vdims)}
).opts({
'Curve': dict(
color=dim('num').categorize({0: 'red', 1: 'blue'}),
line_dash=dim('cat').categorize({'A': 'solid', 'B': 'dashed'})
)
})
plot = bokeh_renderer.get_plot(ndoverlay)
for k, sp in plot.subplots.items():
glyph = sp.handles['glyph']
color = glyph.line_color
if ndoverlay[k].iloc[0, 2] == 0:
self.assertEqual(color, 'red')
else:
self.assertEqual(color, 'blue')
linestyle = glyph.line_dash
if ndoverlay[k].iloc[0, 3] == 'A':
self.assertEqual(linestyle, [])
else:
self.assertEqual(linestyle, [6])
53 changes: 53 additions & 0 deletions holoviews/tests/plotting/matplotlib/testcurveplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from holoviews.core.overlay import NdOverlay
from holoviews.core.util import pd
from holoviews.element import Curve
from holoviews.util.transform import dim

from .testplot import TestMPLPlot, mpl_renderer

Expand Down Expand Up @@ -185,3 +186,55 @@ def test_curve_linewidth_op(self):
vdims=['y', 'linewidth']).options(linewidth='linewidth')
with self.assertRaises(Exception):
mpl_renderer.get_plot(curve)

def test_curve_style_mapping_ndoverlay_dimensions(self):
ndoverlay = NdOverlay({
(0, 'A'): Curve([1, 2, 0]), (0, 'B'): Curve([1, 2, 1]),
(1, 'A'): Curve([1, 2, 2]), (1, 'B'): Curve([1, 2, 3])},
['num', 'cat']
).opts({
'Curve': dict(
color=dim('num').categorize({0: 'red', 1: 'blue'}),
linestyle=dim('cat').categorize({'A': '-.', 'B': '-'})
)
})
plot = mpl_renderer.get_plot(ndoverlay)
for (num, cat), sp in plot.subplots.items():
artist = sp.handles['artist']
color = artist.get_color()
if num == 0:
self.assertEqual(color, 'red')
else:
self.assertEqual(color, 'blue')
linestyle = artist.get_linestyle()
if cat == 'A':
self.assertEqual(linestyle, '-.')
else:
self.assertEqual(linestyle, '-')

def test_curve_style_mapping_constant_value_dimensions(self):
vdims = ['y', 'num', 'cat']
ndoverlay = NdOverlay({
0: Curve([(0, 1, 0, 'A'), (1, 0, 0, 'A')], vdims=vdims),
1: Curve([(0, 1, 0, 'B'), (1, 1, 0, 'B')], vdims=vdims),
2: Curve([(0, 1, 1, 'A'), (1, 2, 1, 'A')], vdims=vdims),
3: Curve([(0, 1, 1, 'B'), (1, 3, 1, 'B')], vdims=vdims)}
).opts({
'Curve': dict(
color=dim('num').categorize({0: 'red', 1: 'blue'}),
linestyle=dim('cat').categorize({'A': '-.', 'B': '-'})
)
})
plot = mpl_renderer.get_plot(ndoverlay)
for k, sp in plot.subplots.items():
artist = sp.handles['artist']
color = artist.get_color()
if ndoverlay[k].iloc[0, 2] == 0:
self.assertEqual(color, 'red')
else:
self.assertEqual(color, 'blue')
linestyle = artist.get_linestyle()
if ndoverlay[k].iloc[0, 3] == 'A':
self.assertEqual(linestyle, '-.')
else:
self.assertEqual(linestyle, '-')

0 comments on commit 8d7f701

Please sign in to comment.