Repository: holoviz/holoviews

Issue:
HoloMap crash with matplotlib using %opts Points (s=...)
Dear Holoviews developers,

There seems to be a problem with hv.Points plot in HoloMap in the recent holoviews (v 1.11.0). If I set %opts Points (s=50) or any other value it crashes:

I'm trying to reproduce the [holomap example](http://holoviews.org/reference/containers/matplotlib/HoloMap.html) using hv.Points instead of hv.Curve:
```
import numpy as np
import holoviews as hv
hv.extension('matplotlib')

%opts Points (s=50)

frequencies = [0.5, 0.75, 1.0, 1.25]

def sine_curve(phase, freq):
    xvals = [0.1* i for i in range(100)]
    #return hv.Curve((xvals, [np.sin(phase+freq*x) for x in xvals]))
    return hv.Points((xvals, [np.sin(phase+freq*x) for x in xvals]))

curve_dict = {f:sine_curve(0,f) for f in frequencies}

hv.HoloMap(curve_dict, kdims='frequency')
```

The error message:

```
...
C:\ProgramData\Anaconda3\lib\site-packages\holoviews\plotting\mpl\chart.py in update_handles(self, key, axis, element, ranges, style)
    668         paths.set_offsets(np.column_stack([xs, ys]))
    669         if 's' in style:
--> 670             paths.set_sizes(style['s'])
    671         if 'vmin' in style:
    672             paths.set_clim((style['vmin'], style['vmax']))

C:\ProgramData\Anaconda3\lib\site-packages\matplotlib\collections.py in set_sizes(self, sizes, dpi)
    871         else:
    872             self._sizes = np.asarray(sizes)
--> 873             self._transforms = np.zeros((len(self._sizes), 3, 3))
    874             scale = np.sqrt(self._sizes) * dpi / 72.0 * self._factor
    875             self._transforms[:, 0, 0] = scale

TypeError: len() of unsized object
```

I was wondering if you know how to change the point size correctly in this case?

In the earlier holoviews version 1.9.1 the same example works perfectly well.

Many thanks!
Best regards,
/Alexey






Discussion:

Resolving patch:
diff --git a/holoviews/plotting/mpl/chart.py b/holoviews/plotting/mpl/chart.py
--- a/holoviews/plotting/mpl/chart.py
+++ b/holoviews/plotting/mpl/chart.py
@@ -15,7 +15,7 @@
 from ...core.util import (
     OrderedDict, match_spec, unique_iterator, basestring, max_range,
     isfinite, datetime_types, dt_to_int, dt64_to_dt, search_indices,
-    unique_array
+    unique_array, isscalar
 )
 from ...element import Raster, HeatMap
 from ...operation import interpolate_curve
@@ -670,7 +670,10 @@ def update_handles(self, key, axis, element, ranges, style):
         (xs, ys), style, _ = self.get_data(element, ranges, style)
         paths.set_offsets(np.column_stack([xs, ys]))
         if 's' in style:
-            paths.set_sizes(style['s'])
+            sizes = style['s']
+            if isscalar(sizes):
+                sizes = [sizes]
+            paths.set_sizes(sizes)
         if 'vmin' in style:
             paths.set_clim((style['vmin'], style['vmax']))
         if 'c' in style:
diff --git a/holoviews/plotting/mpl/element.py b/holoviews/plotting/mpl/element.py
--- a/holoviews/plotting/mpl/element.py
+++ b/holoviews/plotting/mpl/element.py
@@ -466,6 +466,10 @@ def update_frame(self, key, ranges=None, element=None):
         ranges = self.compute_ranges(self.hmap, key, ranges)
         ranges = util.match_spec(element, ranges)
 
+        max_cycles = self.style._max_cycles
+        style = self.lookup_options(element, 'style')
+        self.style = style.max_cycles(max_cycles) if max_cycles else style
+
         label = element.label if self.show_legend else ''
         style = dict(label=label, zorder=self.zorder, **self.style[self.cyclic_index])
         axis_kwargs = self.update_handles(key, axis, element, ranges, style)


Test patch:
diff --git a/holoviews/tests/plotting/matplotlib/testpointplot.py b/holoviews/tests/plotting/matplotlib/testpointplot.py
--- a/holoviews/tests/plotting/matplotlib/testpointplot.py
+++ b/holoviews/tests/plotting/matplotlib/testpointplot.py
@@ -153,6 +153,15 @@ def test_points_padding_datetime_nonsquare(self):
         self.assertEqual(y_range[0], 0.8)
         self.assertEqual(y_range[1], 3.2)
 
+    def test_points_sizes_scalar_update(self):
+        hmap = HoloMap({i: Points([1, 2, 3]).opts(s=i*10) for i in range(1, 3)})
+        plot = mpl_renderer.get_plot(hmap)
+        artist = plot.handles['artist']
+        plot.update((1,))
+        self.assertEqual(artist.get_sizes(), np.array([10]))
+        plot.update((2,))
+        self.assertEqual(artist.get_sizes(), np.array([20]))
+
     ###########################
     #    Styling mapping      #
     ###########################