From 1a85e2d1ff97ccf18359d6bbcb24ecca10e543eb Mon Sep 17 00:00:00 2001 From: David Stansby Date: Tue, 24 Oct 2017 20:29:01 +0100 Subject: [PATCH] Improve step performance --- doc/api/api_changes/2017-10-24-DS.rst | 10 ++++++ lib/matplotlib/axes/_axes.py | 13 ++++--- lib/matplotlib/container.py | 11 ++++-- lib/matplotlib/legend_handler.py | 34 ++++++++++++------ .../tests/baseline_images/test_axes/stem.png | Bin 0 -> 14306 bytes lib/matplotlib/tests/test_axes.py | 11 ++++++ 6 files changed, 61 insertions(+), 18 deletions(-) create mode 100644 doc/api/api_changes/2017-10-24-DS.rst create mode 100644 lib/matplotlib/tests/baseline_images/test_axes/stem.png diff --git a/doc/api/api_changes/2017-10-24-DS.rst b/doc/api/api_changes/2017-10-24-DS.rst new file mode 100644 index 000000000000..c1c3c6ec9c55 --- /dev/null +++ b/doc/api/api_changes/2017-10-24-DS.rst @@ -0,0 +1,10 @@ +`StemContainer` now stores `LineCollection` +------------------------------------------- + +`StemContainer` objects now store a `LineCollection` object instead of a list +of `Line2D` objects for stem lines plotted using `ax.stem`. This gives a very +large performance boost to displaying and moving `ax.stem` plots. + +Line segments can be extracted from the `LineCollection` using +`LineCollection.get_segements()`. See the `LineCollection` documentation for +other methods to retrieve the collection properties. diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 9fa6e6650b00..67d5d5007aa1 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -2370,6 +2370,9 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, x = y y = np.asarray(args[0], dtype=float) args = args[1:] + self._process_unit_info(xdata=x, ydata=y) + x = self.convert_xunits(x) + y = self.convert_yunits(y) # defaults for formats if linefmt is None: @@ -2421,12 +2424,12 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, markerline, = self.plot(x, y, color=markercolor, linestyle=markerstyle, marker=markermarker, label="_nolegend_") - stemlines = [] + lines = [] for thisx, thisy in zip(x, y): - l, = self.plot([thisx, thisx], [bottom, thisy], - color=linecolor, linestyle=linestyle, - marker=linemarker, label="_nolegend_") - stemlines.append(l) + lines.append(((thisx, bottom), (thisx, thisy))) + stemlines = mcoll.LineCollection(lines, linestyles=linestyle, + colors=linecolor, label='_nolegend_') + self.add_collection(stemlines) baseline, = self.plot([np.min(x), np.max(x)], [bottom, bottom], color=basecolor, linestyle=basestyle, diff --git a/lib/matplotlib/container.py b/lib/matplotlib/container.py index 552d6da5a761..0f71c606fe5c 100644 --- a/lib/matplotlib/container.py +++ b/lib/matplotlib/container.py @@ -174,10 +174,17 @@ class StemContainer(Container): baseline : :class:`~matplotlib.lines.Line2D` The artist of the horizontal baseline. - """ - def __init__(self, markerline_stemlines_baseline, **kwargs): + ''' + Parameters + ---------- + markerline_stemlines_baseline : tuple + Tuple of ``(markerline, stemlines, baseline)``. + ``markerline`` contains the `LineCollection` of the markers, + ``stemlines`` is a `LineCollection` of the main lines, + ``baseline`` is the `Line2D` of the baseline. + ''' markerline, stemlines, baseline = markerline_stemlines_baseline self.markerline = markerline self.stemlines = stemlines diff --git a/lib/matplotlib/legend_handler.py b/lib/matplotlib/legend_handler.py index ad574dcf33d0..44f1afc0b236 100644 --- a/lib/matplotlib/legend_handler.py +++ b/lib/matplotlib/legend_handler.py @@ -589,7 +589,6 @@ def get_ydata(self, legend, xdescent, ydescent, width, height, fontsize): def create_artists(self, legend, orig_handle, xdescent, ydescent, width, height, fontsize, trans): - markerline, stemlines, baseline = orig_handle xdata, xdata_marker = self.get_xdata(legend, xdescent, ydescent, @@ -603,31 +602,44 @@ def create_artists(self, legend, orig_handle, else: bottom = self._bottom - leg_markerline = Line2D(xdata_marker, ydata[:len(xdata_marker)]) - self.update_prop(leg_markerline, markerline, legend) - leg_stemlines = [] - for thisx, thisy in zip(xdata_marker, ydata): - l = Line2D([thisx, thisx], [bottom, thisy]) - leg_stemlines.append(l) - for lm, m in zip(leg_stemlines, stemlines): - self.update_prop(lm, m, legend) + # update_prop() usually takes two Line2D collections; + # override temporarily to copy properties from a LineCollection + orig_update_func = self._update_prop_func + self._update_prop_func = self._copy_collection_props + + for thisx, thisy in zip(xdata_marker, ydata): + thisline = Line2D([thisx, thisx], [bottom, thisy]) + leg_stemlines.append(thisline) + self.update_prop(thisline, stemlines, legend) + # Reset update_prop_func + self._update_prop_func = orig_update_func leg_baseline = Line2D([np.min(xdata), np.max(xdata)], [bottom, bottom]) self.update_prop(leg_baseline, baseline, legend) - artists = [leg_markerline] - artists.extend(leg_stemlines) + leg_markerline = Line2D(xdata_marker, ydata[:len(xdata_marker)]) + self.update_prop(leg_markerline, markerline, legend) + + artists = leg_stemlines artists.append(leg_baseline) + artists.append(leg_markerline) for artist in artists: artist.set_transform(trans) return artists + def _copy_collection_props(self, legend_handle, orig_handle): + ''' + Method to copy properties from a LineCollection (orig_handle) to a + Line2D (legend_handle). + ''' + legend_handle._color = orig_handle.get_color()[0] + class HandlerTuple(HandlerBase): """ diff --git a/lib/matplotlib/tests/baseline_images/test_axes/stem.png b/lib/matplotlib/tests/baseline_images/test_axes/stem.png new file mode 100644 index 0000000000000000000000000000000000000000..407c977f5b72fca5104cec2881bcc5e3a67553e5 GIT binary patch literal 14306 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 KNfd|~`u#6fx#Ls- literal 0 HcmV?d00001 diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 12197bd8e55f..8a6515dbe045 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -2876,6 +2876,17 @@ def test_hist_stacked_weighted(): ax.hist((d1, d2), weights=(w1, w2), histtype="stepfilled", stacked=True) +@image_comparison(baseline_images=['stem'], extensions=['png'], style='mpl20', + remove_text=True) +def test_stem(): + x = np.linspace(0.1, 2 * np.pi, 100) + + fig, ax = plt.subplots() + ax.stem(x, np.cos(x), linefmt='C2-', markerfmt='k+', basefmt='C1-.', + label='Stem') + ax.legend() + + def test_stem_args(): fig = plt.figure() ax = fig.add_subplot(1, 1, 1)