From b5a8da80db6625b31e84ed19babdfd14f595c34d Mon Sep 17 00:00:00 2001
From: Philipp Rudiger
Date: Thu, 13 Apr 2017 18:59:31 +0100
Subject: [PATCH 1/2] Ensure max_cycles persists on style for non-batched plots
---
holoviews/plotting/bokeh/chart.py | 4 +++-
holoviews/plotting/bokeh/element.py | 10 ++++++++--
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/holoviews/plotting/bokeh/chart.py b/holoviews/plotting/bokeh/chart.py
index b7c2d63246..6194b7ada6 100644
--- a/holoviews/plotting/bokeh/chart.py
+++ b/holoviews/plotting/bokeh/chart.py
@@ -630,7 +630,9 @@ def update_frame(self, key, ranges=None, plot=None, element=None):
self.current_key = key
self.current_frame = element
- self.style = self.lookup_options(element, 'style')
+ max_cycles = len(self.style._options)
+ self.style = self.lookup_options(style_element, 'style').max_cycles(max_cycles)
+
self.set_param(**self.lookup_options(element, 'plot').options)
ranges = self.compute_ranges(self.hmap, key, ranges)
ranges = match_spec(element, ranges)
diff --git a/holoviews/plotting/bokeh/element.py b/holoviews/plotting/bokeh/element.py
index edc9a0a502..e084cd1839 100644
--- a/holoviews/plotting/bokeh/element.py
+++ b/holoviews/plotting/bokeh/element.py
@@ -772,8 +772,14 @@ def update_frame(self, key, ranges=None, plot=None, element=None, empty=False):
if not element or (not self.dynamic and self.static):
return
- style_element = element.last if self.batched else element
- self.style = self.lookup_options(style_element, 'style')
+ if self.batched:
+ style_element = element.last
+ max_cycles = None
+ else:
+ style_element = element
+ max_cycles = len(self.style._options)
+ style = self.lookup_options(style_element, 'style')
+ self.style = style.max_cycles(max_cycles) if max_cycles else style
ranges = self.compute_ranges(self.hmap, key, ranges)
self.set_param(**self.lookup_options(style_element, 'plot').options)
From dd8ed703329f87436b9d5396d60ceabebf2fc022 Mon Sep 17 00:00:00 2001
From: Philipp Rudiger
Date: Thu, 13 Apr 2017 23:14:22 +0100
Subject: [PATCH 2/2] Added unit test for cyclic styles with palettes
---
holoviews/plotting/bokeh/chart.py | 6 +++---
holoviews/plotting/bokeh/path.py | 5 ++---
holoviews/plotting/bokeh/util.py | 10 +---------
holoviews/plotting/util.py | 9 +++++++++
tests/testplotinstantiation.py | 17 ++++++++++++++++-
5 files changed, 31 insertions(+), 16 deletions(-)
diff --git a/holoviews/plotting/bokeh/chart.py b/holoviews/plotting/bokeh/chart.py
index 6194b7ada6..73d77d44a5 100644
--- a/holoviews/plotting/bokeh/chart.py
+++ b/holoviews/plotting/bokeh/chart.py
@@ -15,12 +15,12 @@
from ...core.options import abbreviated_exception
from ...operation import interpolate_curve
from ..util import (compute_sizes, get_sideplot_ranges, match_spec,
- map_colors, get_min_distance)
+ map_colors, get_min_distance, rgb2hex)
from .element import (ElementPlot, ColorbarPlot, LegendPlot, line_properties,
fill_properties)
from .path import PathPlot, PolygonPlot
-from .util import (get_cmap, mpl_to_bokeh, update_plot, rgb2hex,
- bokeh_version, expand_batched_style, filter_batched_data)
+from .util import (get_cmap, mpl_to_bokeh, update_plot, bokeh_version,
+ expand_batched_style, filter_batched_data)
class PointPlot(LegendPlot, ColorbarPlot):
diff --git a/holoviews/plotting/bokeh/path.py b/holoviews/plotting/bokeh/path.py
index 6e8644e057..b13e715d78 100644
--- a/holoviews/plotting/bokeh/path.py
+++ b/holoviews/plotting/bokeh/path.py
@@ -6,10 +6,9 @@
from bokeh.models import HoverTool
from ...core import util
-from ..util import map_colors
+from ..util import map_colors, rgb2hex
from .element import ElementPlot, ColorbarPlot, line_properties, fill_properties
-from .util import (get_cmap, rgb2hex, expand_batched_style,
- filter_batched_data)
+from .util import get_cmap, expand_batched_style, filter_batched_data
class PathPlot(ElementPlot):
diff --git a/holoviews/plotting/bokeh/util.py b/holoviews/plotting/bokeh/util.py
index b2d9b87171..3ecb776f30 100644
--- a/holoviews/plotting/bokeh/util.py
+++ b/holoviews/plotting/bokeh/util.py
@@ -29,7 +29,7 @@
from ...core.overlay import Overlay
from ...core.util import basestring, unique_array
-from ..util import dim_axis_label
+from ..util import dim_axis_label, rgb2hex
# Conversion between matplotlib and bokeh markers
markers = {'s': {'marker': 'square'},
@@ -61,14 +61,6 @@
'LinearAxis', 'ColumnDataSource']
-def rgb2hex(rgb):
- """
- Convert RGB(A) tuple to hex.
- """
- if len(rgb) > 3:
- rgb = rgb[:-1]
- return "#{0:02x}{1:02x}{2:02x}".format(*(int(v*255) for v in rgb))
-
def rgba_tuple(rgba):
"""
diff --git a/holoviews/plotting/util.py b/holoviews/plotting/util.py
index fae17fc3cf..f35534f491 100644
--- a/holoviews/plotting/util.py
+++ b/holoviews/plotting/util.py
@@ -356,6 +356,15 @@ def get_min_distance(element):
return distances[distances>0].min()
+def rgb2hex(rgb):
+ """
+ Convert RGB(A) tuple to hex.
+ """
+ if len(rgb) > 3:
+ rgb = rgb[:-1]
+ return "#{0:02x}{1:02x}{2:02x}".format(*(int(v*255) for v in rgb))
+
+
# linear_kryw_0_100_c71 (aka "fire"):
# A perceptually uniform equivalent of matplotlib's "hot" colormap, from
# http://peterkovesi.com/projects/colourmaps
diff --git a/tests/testplotinstantiation.py b/tests/testplotinstantiation.py
index 7ccda4df09..5c3821ceda 100644
--- a/tests/testplotinstantiation.py
+++ b/tests/testplotinstantiation.py
@@ -12,7 +12,8 @@
import param
import numpy as np
from holoviews import (Dimension, Overlay, DynamicMap, Store, Dataset,
- NdOverlay, GridSpace, HoloMap, Layout, Cycle)
+ NdOverlay, GridSpace, HoloMap, Layout, Cycle,
+ Palette)
from holoviews.core.util import pd
from holoviews.element import (Curve, Scatter, Image, VLine, Points,
HeatMap, QuadMesh, Spikes, ErrorBars,
@@ -21,6 +22,7 @@
from holoviews.element.comparison import ComparisonTestCase
from holoviews.streams import PositionXY, PositionX
from holoviews.plotting import comms
+from holoviews.plotting.util import rgb2hex
# Standardize backend due to random inconsistencies
try:
@@ -83,6 +85,7 @@ def __exit__(self, *args):
self.stream.seek(0)
+
class TestMPLPlotInstantiation(ComparisonTestCase):
def setUp(self):
@@ -358,6 +361,18 @@ def test_batched_points_size_and_color(self):
self.assertEqual(plot.handles['source'].data['color'], color)
self.assertEqual(plot.handles['source'].data['size'], size)
+ def test_cyclic_palette_curves(self):
+ palette = Palette('Set1')
+ opts = dict(color=palette)
+ hmap = HoloMap({i: NdOverlay({j: Curve(np.random.rand(3))(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_batched_points_line_color_and_color(self):
opts = {'NdOverlay': dict(plot=dict(legend_limit=0)),
'Points': dict(style=dict(line_color=Cycle(values=['red', 'blue'])))}