From fda65b46a67963ed26f4b35f3f646f3e7bd388d2 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Fri, 2 Mar 2018 14:50:15 -0500 Subject: [PATCH 1/8] Fixes issue #8946 --- lib/matplotlib/axes/_base.py | 21 ++++++++++++++++++++- lib/matplotlib/tests/test_axes.py | 23 +++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index fc37069f3030..10b2a3b43be8 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -3203,6 +3203,12 @@ def set_xticks(self, ticks, minor=False): """ ret = self.xaxis.set_ticks(ticks, minor=minor) self.stale = True + + g = self.get_shared_x_axes() + for ax in g.get_siblings(self): + ax.xaxis.set_ticks(ticks, minor=minor) + ax.stale = True + return ret def get_xmajorticklabels(self): @@ -3290,6 +3296,12 @@ def set_xticklabels(self, labels, fontdict=None, minor=False, **kwargs): ret = self.xaxis.set_ticklabels(labels, minor=minor, **kwargs) self.stale = True + + g = self.get_shared_x_axes() + for ax in g.get_siblings(self): + ax.xaxis.set_ticklabels(labels, minor=minor, **kwargs) + ax.stale = True + return ret def invert_yaxis(self): @@ -3521,6 +3533,9 @@ def set_yticks(self, ticks, minor=False): Default is ``False``. """ ret = self.yaxis.set_ticks(ticks, minor=minor) + g = self.get_shared_y_axes() + for ax in g.get_siblings(self): + ax.yaxis.set_ticks(ticks, minor=minor) return ret def get_ymajorticklabels(self): @@ -3605,8 +3620,12 @@ def set_yticklabels(self, labels, fontdict=None, minor=False, **kwargs): """ if fontdict is not None: kwargs.update(fontdict) - return self.yaxis.set_ticklabels(labels, + ret = self.yaxis.set_ticklabels(labels, minor=minor, **kwargs) + g = self.get_shared_y_axes() + for ax in g.get_siblings(self): + ax.yaxis.set_ticklabels(labels, minor=minor, **kwargs) + return ret def xaxis_date(self, tz=None): """ diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 3b381a294f44..5c2a1801f4e5 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -5128,6 +5128,29 @@ def test_remove_shared_axes_relim(): assert_array_equal(ax_lst[0][1].get_xlim(), orig_xlim) +def test_shared_axes_retick(): + # related to GitHub issue 8946 + # set_xticks should set shared axes limits + fig, ax_lst = plt.subplots(2, 2, sharex='all', sharey='all') + + data = np.random.randn(10) + data2 = np.random.randn(10) + index = range(10) + index2 = [x + 5.5 for x in index] + + ax_lst[0][0].scatter(index, data) + ax_lst[0][1].scatter(index2, data2) + + ax_lst[1][0].scatter(index, data) + ax_lst[1][1].scatter(index2, data2) + + ax_lst[0][0].set_xticks(range(-10, 20, 1)) + ax_lst[0][0].set_yticks(range(-10, 20, 1)) + + assert ax_lst[0][0].get_xlim() == ax_lst[0][1].get_xlim() + assert ax_lst[0][0].get_ylim() == ax_lst[1][0].get_ylim() + + def test_adjust_numtick_aspect(): fig, ax = plt.subplots() ax.yaxis.get_major_locator().set_params(nbins='auto') From 55e39efac21c44e24fe5bc8e21d53ab41f51a834 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Sat, 3 Mar 2018 13:37:41 -0500 Subject: [PATCH 2/8] Share viewLim instead of calling set_ticks --- lib/matplotlib/axes/_base.py | 138 ++++++++++++++++++++++++++++++----- lib/matplotlib/axis.py | 20 ++--- 2 files changed, 128 insertions(+), 30 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 10b2a3b43be8..a2e55687d80d 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -3143,6 +3143,67 @@ def set_xlim(self, left=None, right=None, emit=True, auto=False, **kw): self.stale = True return left, right + def _set_xviewlim(self, left=None, right=None, emit=True): + """ + Set the view limits for the x-axis directly + + .. ACCEPTS: (left: float, right: float) + + Parameters + ---------- + left : scalar, optional + The left xlim (default: None, which leaves the left limit + unchanged). + + right : scalar, optional + The right xlim (default: None, which leaves the right limit + unchanged). + + emit : bool, optional + Whether to notify observers of limit change (default: True). + + xlimits : tuple, optional + The left and right xlims may be passed as the tuple + (`left`, `right`) as the first positional argument (or as + the `left` keyword argument). + + Returns + ------- + xlimits : tuple + Returns the new x-axis view limits as (`left`, `right`). + + Notes + ----- + The `left` value may be greater than the `right` value, in which + case the x-axis values will decrease from left to right. + + Examples + -------- + >>> _set_xviewlim(left, right) + >>> _set_xviewlim((left, right)) + >>> left, right = _set_xviewlim(left, right) + + """ + if right is None and iterable(left): + left, right = left + if left is None or right is None: + raise ValueError('Invalid view limits provided: %s, %s', + left, right) + + self.viewLim.intervalx = (left, right) + + if emit: + self.callbacks.process('xlim_changed', self) + # Call all of the other x-axes that are shared with this one + for other in self._shared_x_axes.get_siblings(self): + if other is not self: + other._set_xviewlim(self.viewLim.intervalx, emit=False) + if (other.figure != self.figure and + other.figure.canvas is not None): + other.figure.canvas.draw_idle() + self.stale = True + return left, right + def get_xscale(self): return self.xaxis.get_scale() get_xscale.__doc__ = "Return the xaxis scale string: %s""" % ( @@ -3203,12 +3264,6 @@ def set_xticks(self, ticks, minor=False): """ ret = self.xaxis.set_ticks(ticks, minor=minor) self.stale = True - - g = self.get_shared_x_axes() - for ax in g.get_siblings(self): - ax.xaxis.set_ticks(ticks, minor=minor) - ax.stale = True - return ret def get_xmajorticklabels(self): @@ -3296,12 +3351,6 @@ def set_xticklabels(self, labels, fontdict=None, minor=False, **kwargs): ret = self.xaxis.set_ticklabels(labels, minor=minor, **kwargs) self.stale = True - - g = self.get_shared_x_axes() - for ax in g.get_siblings(self): - ax.xaxis.set_ticklabels(labels, minor=minor, **kwargs) - ax.stale = True - return ret def invert_yaxis(self): @@ -3475,6 +3524,62 @@ def set_ylim(self, bottom=None, top=None, emit=True, auto=False, **kw): self.stale = True return bottom, top + def _set_yviewlim(self, bottom=None, top=None, emit=True): + """ + Set the view limits for the y-axis directly + + .. ACCEPTS: (bottom: float, top: float) + + Parameters + ---------- + bottom : scalar, optional + The bottom ylim (default: None, which leaves the bottom + limit unchanged). + + top : scalar, optional + The top ylim (default: None, which leaves the top limit + unchanged). + + emit : bool, optional + Whether to notify observers of limit change (default: True). + + ylimits : tuple, optional + The bottom and top yxlims may be passed as the tuple + (`bottom`, `top`) as the first positional argument (or as + the `bottom` keyword argument). + + Returns + ------- + ylimits : tuple + Returns the new y-axis limits as (`bottom`, `top`). + + Examples + -------- + >>> _set_yviewlim(bottom, top) + >>> _set_yviewlim((bottom, top)) + >>> bottom, top = _set_yviewlim(bottom, top) + """ + + if top is None and iterable(bottom): + bottom, top = bottom + if top is None or bottom is None: + raise ValueError('Invalid view limits provided: %s, %s', + bottom, top) + + self.viewLim.intervaly = (bottom, top) + + if emit: + self.callbacks.process('ylim_changed', self) + # Call all of the other y-axes that are shared with this one + for other in self._shared_y_axes.get_siblings(self): + if other is not self: + other._set_yviewlim(self.viewLim.intervaly, emit=False) + if (other.figure != self.figure and + other.figure.canvas is not None): + other.figure.canvas.draw_idle() + self.stale = True + return bottom, top + def get_yscale(self): return self.yaxis.get_scale() get_yscale.__doc__ = "Return the yaxis scale string: %s""" % ( @@ -3533,9 +3638,6 @@ def set_yticks(self, ticks, minor=False): Default is ``False``. """ ret = self.yaxis.set_ticks(ticks, minor=minor) - g = self.get_shared_y_axes() - for ax in g.get_siblings(self): - ax.yaxis.set_ticks(ticks, minor=minor) return ret def get_ymajorticklabels(self): @@ -3620,12 +3722,8 @@ def set_yticklabels(self, labels, fontdict=None, minor=False, **kwargs): """ if fontdict is not None: kwargs.update(fontdict) - ret = self.yaxis.set_ticklabels(labels, + return self.yaxis.set_ticklabels(labels, minor=minor, **kwargs) - g = self.get_shared_y_axes() - for ax in g.get_siblings(self): - ax.yaxis.set_ticklabels(labels, minor=minor, **kwargs) - return ret def xaxis_date(self, tz=None): """ diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index 5163c7833f26..887e7fa9cd3b 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -2070,15 +2070,15 @@ def set_view_interval(self, vmin, vmax, ignore=False): """ if ignore: - self.axes.viewLim.intervalx = vmin, vmax + self.axes._set_xviewlim(vmin, vmax) else: Vmin, Vmax = self.get_view_interval() if Vmin < Vmax: - self.axes.viewLim.intervalx = (min(vmin, vmax, Vmin), - max(vmin, vmax, Vmax)) + self.axes._set_xviewlim(min(vmin, vmax, Vmin), + max(vmin, vmax, Vmax)) else: - self.axes.viewLim.intervalx = (max(vmin, vmax, Vmin), - min(vmin, vmax, Vmax)) + self.axes._set_xviewlim(max(vmin, vmax, Vmin), + min(vmin, vmax, Vmax)) def get_minpos(self): return self.axes.dataLim.minposx @@ -2448,15 +2448,15 @@ def set_view_interval(self, vmin, vmax, ignore=False): """ if ignore: - self.axes.viewLim.intervaly = vmin, vmax + self.axes._set_yviewlim(vmin, vmax) else: Vmin, Vmax = self.get_view_interval() if Vmin < Vmax: - self.axes.viewLim.intervaly = (min(vmin, vmax, Vmin), - max(vmin, vmax, Vmax)) + self.axes._set_yviewlim(min(vmin, vmax, Vmin), + max(vmin, vmax, Vmax)) else: - self.axes.viewLim.intervaly = (max(vmin, vmax, Vmin), - min(vmin, vmax, Vmax)) + self.axes._set_yviewlim(max(vmin, vmax, Vmin), + min(vmin, vmax, Vmax)) self.stale = True def get_minpos(self): From a9abf15897f0bedd7873a44a053452bab00c9f6e Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Fri, 2 Mar 2018 14:50:15 -0500 Subject: [PATCH 3/8] Fixes issue #8946 --- lib/matplotlib/axes/_base.py | 21 ++++++++++++++++++++- lib/matplotlib/tests/test_axes.py | 23 +++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 9071e30f7f85..cbe4a1549814 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -3194,6 +3194,12 @@ def set_xticks(self, ticks, minor=False): """ ret = self.xaxis.set_ticks(ticks, minor=minor) self.stale = True + + g = self.get_shared_x_axes() + for ax in g.get_siblings(self): + ax.xaxis.set_ticks(ticks, minor=minor) + ax.stale = True + return ret def get_xmajorticklabels(self): @@ -3281,6 +3287,12 @@ def set_xticklabels(self, labels, fontdict=None, minor=False, **kwargs): ret = self.xaxis.set_ticklabels(labels, minor=minor, **kwargs) self.stale = True + + g = self.get_shared_x_axes() + for ax in g.get_siblings(self): + ax.xaxis.set_ticklabels(labels, minor=minor, **kwargs) + ax.stale = True + return ret def invert_yaxis(self): @@ -3512,6 +3524,9 @@ def set_yticks(self, ticks, minor=False): Default is ``False``. """ ret = self.yaxis.set_ticks(ticks, minor=minor) + g = self.get_shared_y_axes() + for ax in g.get_siblings(self): + ax.yaxis.set_ticks(ticks, minor=minor) return ret def get_ymajorticklabels(self): @@ -3596,8 +3611,12 @@ def set_yticklabels(self, labels, fontdict=None, minor=False, **kwargs): """ if fontdict is not None: kwargs.update(fontdict) - return self.yaxis.set_ticklabels(labels, + ret = self.yaxis.set_ticklabels(labels, minor=minor, **kwargs) + g = self.get_shared_y_axes() + for ax in g.get_siblings(self): + ax.yaxis.set_ticklabels(labels, minor=minor, **kwargs) + return ret def xaxis_date(self, tz=None): """ diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index abd2b6675b48..3e421f2ca186 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -5127,6 +5127,29 @@ def test_remove_shared_axes_relim(): assert_array_equal(ax_lst[0][1].get_xlim(), orig_xlim) +def test_shared_axes_retick(): + # related to GitHub issue 8946 + # set_xticks should set shared axes limits + fig, ax_lst = plt.subplots(2, 2, sharex='all', sharey='all') + + data = np.random.randn(10) + data2 = np.random.randn(10) + index = range(10) + index2 = [x + 5.5 for x in index] + + ax_lst[0][0].scatter(index, data) + ax_lst[0][1].scatter(index2, data2) + + ax_lst[1][0].scatter(index, data) + ax_lst[1][1].scatter(index2, data2) + + ax_lst[0][0].set_xticks(range(-10, 20, 1)) + ax_lst[0][0].set_yticks(range(-10, 20, 1)) + + assert ax_lst[0][0].get_xlim() == ax_lst[0][1].get_xlim() + assert ax_lst[0][0].get_ylim() == ax_lst[1][0].get_ylim() + + def test_adjust_numtick_aspect(): fig, ax = plt.subplots() ax.yaxis.get_major_locator().set_params(nbins='auto') From f95e53c4e3d8425cfafa8f1282cb48fc8575867c Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Sat, 3 Mar 2018 13:37:41 -0500 Subject: [PATCH 4/8] Share viewLim instead of calling set_ticks --- lib/matplotlib/axes/_base.py | 138 ++++++++++++++++++++++++++++++----- lib/matplotlib/axis.py | 20 ++--- 2 files changed, 128 insertions(+), 30 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index cbe4a1549814..7d6b4c9c0c70 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -3134,6 +3134,67 @@ def set_xlim(self, left=None, right=None, emit=True, auto=False, **kw): self.stale = True return left, right + def _set_xviewlim(self, left=None, right=None, emit=True): + """ + Set the view limits for the x-axis directly + + .. ACCEPTS: (left: float, right: float) + + Parameters + ---------- + left : scalar, optional + The left xlim (default: None, which leaves the left limit + unchanged). + + right : scalar, optional + The right xlim (default: None, which leaves the right limit + unchanged). + + emit : bool, optional + Whether to notify observers of limit change (default: True). + + xlimits : tuple, optional + The left and right xlims may be passed as the tuple + (`left`, `right`) as the first positional argument (or as + the `left` keyword argument). + + Returns + ------- + xlimits : tuple + Returns the new x-axis view limits as (`left`, `right`). + + Notes + ----- + The `left` value may be greater than the `right` value, in which + case the x-axis values will decrease from left to right. + + Examples + -------- + >>> _set_xviewlim(left, right) + >>> _set_xviewlim((left, right)) + >>> left, right = _set_xviewlim(left, right) + + """ + if right is None and iterable(left): + left, right = left + if left is None or right is None: + raise ValueError('Invalid view limits provided: %s, %s', + left, right) + + self.viewLim.intervalx = (left, right) + + if emit: + self.callbacks.process('xlim_changed', self) + # Call all of the other x-axes that are shared with this one + for other in self._shared_x_axes.get_siblings(self): + if other is not self: + other._set_xviewlim(self.viewLim.intervalx, emit=False) + if (other.figure != self.figure and + other.figure.canvas is not None): + other.figure.canvas.draw_idle() + self.stale = True + return left, right + def get_xscale(self): return self.xaxis.get_scale() get_xscale.__doc__ = "Return the xaxis scale string: %s""" % ( @@ -3194,12 +3255,6 @@ def set_xticks(self, ticks, minor=False): """ ret = self.xaxis.set_ticks(ticks, minor=minor) self.stale = True - - g = self.get_shared_x_axes() - for ax in g.get_siblings(self): - ax.xaxis.set_ticks(ticks, minor=minor) - ax.stale = True - return ret def get_xmajorticklabels(self): @@ -3287,12 +3342,6 @@ def set_xticklabels(self, labels, fontdict=None, minor=False, **kwargs): ret = self.xaxis.set_ticklabels(labels, minor=minor, **kwargs) self.stale = True - - g = self.get_shared_x_axes() - for ax in g.get_siblings(self): - ax.xaxis.set_ticklabels(labels, minor=minor, **kwargs) - ax.stale = True - return ret def invert_yaxis(self): @@ -3466,6 +3515,62 @@ def set_ylim(self, bottom=None, top=None, emit=True, auto=False, **kw): self.stale = True return bottom, top + def _set_yviewlim(self, bottom=None, top=None, emit=True): + """ + Set the view limits for the y-axis directly + + .. ACCEPTS: (bottom: float, top: float) + + Parameters + ---------- + bottom : scalar, optional + The bottom ylim (default: None, which leaves the bottom + limit unchanged). + + top : scalar, optional + The top ylim (default: None, which leaves the top limit + unchanged). + + emit : bool, optional + Whether to notify observers of limit change (default: True). + + ylimits : tuple, optional + The bottom and top yxlims may be passed as the tuple + (`bottom`, `top`) as the first positional argument (or as + the `bottom` keyword argument). + + Returns + ------- + ylimits : tuple + Returns the new y-axis limits as (`bottom`, `top`). + + Examples + -------- + >>> _set_yviewlim(bottom, top) + >>> _set_yviewlim((bottom, top)) + >>> bottom, top = _set_yviewlim(bottom, top) + """ + + if top is None and iterable(bottom): + bottom, top = bottom + if top is None or bottom is None: + raise ValueError('Invalid view limits provided: %s, %s', + bottom, top) + + self.viewLim.intervaly = (bottom, top) + + if emit: + self.callbacks.process('ylim_changed', self) + # Call all of the other y-axes that are shared with this one + for other in self._shared_y_axes.get_siblings(self): + if other is not self: + other._set_yviewlim(self.viewLim.intervaly, emit=False) + if (other.figure != self.figure and + other.figure.canvas is not None): + other.figure.canvas.draw_idle() + self.stale = True + return bottom, top + def get_yscale(self): return self.yaxis.get_scale() get_yscale.__doc__ = "Return the yaxis scale string: %s""" % ( @@ -3524,9 +3629,6 @@ def set_yticks(self, ticks, minor=False): Default is ``False``. """ ret = self.yaxis.set_ticks(ticks, minor=minor) - g = self.get_shared_y_axes() - for ax in g.get_siblings(self): - ax.yaxis.set_ticks(ticks, minor=minor) return ret def get_ymajorticklabels(self): @@ -3611,12 +3713,8 @@ def set_yticklabels(self, labels, fontdict=None, minor=False, **kwargs): """ if fontdict is not None: kwargs.update(fontdict) - ret = self.yaxis.set_ticklabels(labels, + return self.yaxis.set_ticklabels(labels, minor=minor, **kwargs) - g = self.get_shared_y_axes() - for ax in g.get_siblings(self): - ax.yaxis.set_ticklabels(labels, minor=minor, **kwargs) - return ret def xaxis_date(self, tz=None): """ diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index 5163c7833f26..887e7fa9cd3b 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -2070,15 +2070,15 @@ def set_view_interval(self, vmin, vmax, ignore=False): """ if ignore: - self.axes.viewLim.intervalx = vmin, vmax + self.axes._set_xviewlim(vmin, vmax) else: Vmin, Vmax = self.get_view_interval() if Vmin < Vmax: - self.axes.viewLim.intervalx = (min(vmin, vmax, Vmin), - max(vmin, vmax, Vmax)) + self.axes._set_xviewlim(min(vmin, vmax, Vmin), + max(vmin, vmax, Vmax)) else: - self.axes.viewLim.intervalx = (max(vmin, vmax, Vmin), - min(vmin, vmax, Vmax)) + self.axes._set_xviewlim(max(vmin, vmax, Vmin), + min(vmin, vmax, Vmax)) def get_minpos(self): return self.axes.dataLim.minposx @@ -2448,15 +2448,15 @@ def set_view_interval(self, vmin, vmax, ignore=False): """ if ignore: - self.axes.viewLim.intervaly = vmin, vmax + self.axes._set_yviewlim(vmin, vmax) else: Vmin, Vmax = self.get_view_interval() if Vmin < Vmax: - self.axes.viewLim.intervaly = (min(vmin, vmax, Vmin), - max(vmin, vmax, Vmax)) + self.axes._set_yviewlim(min(vmin, vmax, Vmin), + max(vmin, vmax, Vmax)) else: - self.axes.viewLim.intervaly = (max(vmin, vmax, Vmin), - min(vmin, vmax, Vmax)) + self.axes._set_yviewlim(max(vmin, vmax, Vmin), + min(vmin, vmax, Vmax)) self.stale = True def get_minpos(self): From 9b446e0978481e90ecb028c51817a0ecb1e155c9 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Wed, 7 Mar 2018 16:39:38 -0500 Subject: [PATCH 5/8] Delegate viewLim sharing to set_view_interval --- lib/matplotlib/axes/_base.py | 208 ++++++++--------------------- lib/matplotlib/axis.py | 71 +++++++--- lib/mpl_toolkits/mplot3d/axes3d.py | 82 ++++-------- lib/mpl_toolkits/mplot3d/axis3d.py | 96 ++++++++++++- 4 files changed, 232 insertions(+), 225 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 7d6b4c9c0c70..fc1ed2e60afa 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -40,6 +40,9 @@ rcParams = matplotlib.rcParams +is_string_like = cbook.is_string_like +is_sequence_of_strings = cbook.is_sequence_of_strings + _hold_msg = """axes.hold is deprecated. See the API Changes document (http://matplotlib.org/api/api_changes.html) for more details.""" @@ -338,7 +341,8 @@ def _makefill(self, x, y, kw, kwargs): # modify the kwargs dictionary. self._setdefaults(default_dict, kwargs) - seg = mpatches.Polygon(np.column_stack((x, y)), + seg = mpatches.Polygon(np.hstack((x[:, np.newaxis], + y[:, np.newaxis])), facecolor=facecolor, fill=kwargs.get('fill', True), closed=kw['closed']) @@ -1128,6 +1132,11 @@ def cla(self): self.stale = True + @property + @cbook.deprecated("2.1", alternative="Axes.patch") + def axesPatch(self): + return self.patch + def clear(self): """Clear the axes.""" self.cla() @@ -1210,16 +1219,16 @@ def set_prop_cycle(self, *args, **kwargs): self._get_lines.set_prop_cycle(prop_cycle) self._get_patches_for_fill.set_prop_cycle(prop_cycle) - @cbook.deprecated('1.5', alternative='`.set_prop_cycle`') def set_color_cycle(self, clist): """ Set the color cycle for any future plot commands on this Axes. - Parameters - ---------- - clist - A list of mpl color specifiers. + *clist* is a list of mpl color specifiers. + + .. deprecated:: 1.5 """ + cbook.warn_deprecated( + '1.5', name='set_color_cycle', alternative='set_prop_cycle') if clist is None: # Calling set_color_cycle() or set_prop_cycle() with None # effectively resets the cycle, but you can't do @@ -3117,82 +3126,10 @@ def set_xlim(self, left=None, right=None, emit=True, auto=False, **kw): 'invalid limits will be ignored.') left, right = self.xaxis.limit_range_for_scale(left, right) - self.viewLim.intervalx = (left, right) - if auto is not None: - self._autoscaleXon = bool(auto) - - if emit: - self.callbacks.process('xlim_changed', self) - # Call all of the other x-axes that are shared with this one - for other in self._shared_x_axes.get_siblings(self): - if other is not self: - other.set_xlim(self.viewLim.intervalx, - emit=False, auto=auto) - if (other.figure != self.figure and - other.figure.canvas is not None): - other.figure.canvas.draw_idle() - self.stale = True - return left, right - - def _set_xviewlim(self, left=None, right=None, emit=True): - """ - Set the view limits for the x-axis directly - - .. ACCEPTS: (left: float, right: float) - - Parameters - ---------- - left : scalar, optional - The left xlim (default: None, which leaves the left limit - unchanged). - - right : scalar, optional - The right xlim (default: None, which leaves the right limit - unchanged). - - emit : bool, optional - Whether to notify observers of limit change (default: True). - - xlimits : tuple, optional - The left and right xlims may be passed as the tuple - (`left`, `right`) as the first positional argument (or as - the `left` keyword argument). - - Returns - ------- - xlimits : tuple - Returns the new x-axis view limits as (`left`, `right`). - - Notes - ----- - The `left` value may be greater than the `right` value, in which - case the x-axis values will decrease from left to right. - - Examples - -------- - >>> _set_xviewlim(left, right) - >>> _set_xviewlim((left, right)) - >>> left, right = _set_xviewlim(left, right) - - """ - if right is None and iterable(left): - left, right = left - if left is None or right is None: - raise ValueError('Invalid view limits provided: %s, %s', - left, right) - - self.viewLim.intervalx = (left, right) - - if emit: - self.callbacks.process('xlim_changed', self) - # Call all of the other x-axes that are shared with this one - for other in self._shared_x_axes.get_siblings(self): - if other is not self: - other._set_xviewlim(self.viewLim.intervalx, emit=False) - if (other.figure != self.figure and - other.figure.canvas is not None): - other.figure.canvas.draw_idle() - self.stale = True + # We force the use of `maxis.XAxis` so that subclasses have access + # to changing `viewLim` in this way (see Axes3D) + maxis.XAxis.set_view_interval(self.xaxis, left, right, ignore=True, + emit=emit, auto=auto) return left, right def get_xscale(self): @@ -3498,77 +3435,10 @@ def set_ylim(self, bottom=None, top=None, emit=True, auto=False, **kw): 'invalid limits will be ignored.') bottom, top = self.yaxis.limit_range_for_scale(bottom, top) - self.viewLim.intervaly = (bottom, top) - if auto is not None: - self._autoscaleYon = bool(auto) - - if emit: - self.callbacks.process('ylim_changed', self) - # Call all of the other y-axes that are shared with this one - for other in self._shared_y_axes.get_siblings(self): - if other is not self: - other.set_ylim(self.viewLim.intervaly, - emit=False, auto=auto) - if (other.figure != self.figure and - other.figure.canvas is not None): - other.figure.canvas.draw_idle() - self.stale = True - return bottom, top - - def _set_yviewlim(self, bottom=None, top=None, emit=True): - """ - Set the view limits for the y-axis directly - - .. ACCEPTS: (bottom: float, top: float) - - Parameters - ---------- - bottom : scalar, optional - The bottom ylim (default: None, which leaves the bottom - limit unchanged). - - top : scalar, optional - The top ylim (default: None, which leaves the top limit - unchanged). - - emit : bool, optional - Whether to notify observers of limit change (default: True). - - ylimits : tuple, optional - The bottom and top yxlims may be passed as the tuple - (`bottom`, `top`) as the first positional argument (or as - the `bottom` keyword argument). - - Returns - ------- - ylimits : tuple - Returns the new y-axis limits as (`bottom`, `top`). - - Examples - -------- - >>> _set_yviewlim(bottom, top) - >>> _set_yviewlim((bottom, top)) - >>> bottom, top = _set_yviewlim(bottom, top) - """ - - if top is None and iterable(bottom): - bottom, top = bottom - if top is None or bottom is None: - raise ValueError('Invalid view limits provided: %s, %s', - bottom, top) - - self.viewLim.intervaly = (bottom, top) - - if emit: - self.callbacks.process('ylim_changed', self) - # Call all of the other y-axes that are shared with this one - for other in self._shared_y_axes.get_siblings(self): - if other is not self: - other._set_yviewlim(self.viewLim.intervaly, emit=False) - if (other.figure != self.figure and - other.figure.canvas is not None): - other.figure.canvas.draw_idle() - self.stale = True + # We force the use of `maxis.YAxis` so that subclasses have access + # to changing `viewLim` in this way (see Axes3D) + maxis.YAxis.set_view_interval(self.yaxis, bottom, top, ignore=True, + emit=emit, auto=auto) return bottom, top def get_yscale(self): @@ -4152,6 +4022,38 @@ def format_deltas(key, dx, dy): self.set_xlim(points[:, 0]) self.set_ylim(points[:, 1]) + @cbook.deprecated("2.1") + def get_cursor_props(self): + """ + Return the cursor propertiess as a (*linewidth*, *color*) + tuple, where *linewidth* is a float and *color* is an RGBA + tuple + """ + return self._cursorProps + + @cbook.deprecated("2.1") + def set_cursor_props(self, *args): + """Set the cursor property as + + Call signature :: + + ax.set_cursor_props(linewidth, color) + + or:: + + ax.set_cursor_props((linewidth, color)) + + ACCEPTS: a (*float*, *color*) tuple + """ + if len(args) == 1: + lw, c = args[0] + elif len(args) == 2: + lw, c = args + else: + raise ValueError('args must be a (linewidth, color) tuple') + c = mcolors.to_rgba(c) + self._cursorProps = lw, c + def get_children(self): """return a list of child artists""" children = [] diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index 887e7fa9cd3b..3f17e271cad9 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -931,14 +931,15 @@ def get_view_interval(self): 'return the Interval instance for this axis view limits' raise NotImplementedError('Derived must override') - def set_view_interval(self, vmin, vmax, ignore=False): + def set_view_interval(self, vmin, vmax, ignore=False, emit=True, + auto=False): raise NotImplementedError('Derived must override') def get_data_interval(self): 'return the Interval instance for this axis data limits' raise NotImplementedError('Derived must override') - def set_data_interval(self): + def set_data_interval(self, vmin, vmax, ignore=False): '''set the axis data limits''' raise NotImplementedError('Derived must override') @@ -2059,26 +2060,45 @@ def get_view_interval(self): 'return the Interval instance for this axis view limits' return self.axes.viewLim.intervalx - def set_view_interval(self, vmin, vmax, ignore=False): + def set_view_interval(self, vmin, vmax, ignore=False, emit=True, + auto=False): """ If *ignore* is *False*, the order of vmin, vmax does not matter; the original axis orientation will be preserved. In addition, the view limits can be - expanded, but will not be reduced. This method is + expanded, but will not be reduced. + If *emit* is *True*, observers will be notified of + limit change. If *auto* is *True*, it turns on + autoscaling of the x-axis, and if *auto* is *False*, + it turns off autoscaling of the x-axis, while *None* + leaves autoscaling unchanged. This method is for mpl internal use; for normal use, see :meth:`~matplotlib.axes.Axes.set_xlim`. """ if ignore: - self.axes._set_xviewlim(vmin, vmax) + self.axes.viewLim.intervalx = (vmin, vmax) else: Vmin, Vmax = self.get_view_interval() if Vmin < Vmax: - self.axes._set_xviewlim(min(vmin, vmax, Vmin), - max(vmin, vmax, Vmax)) + self.axes.viewLim.intervalx = (min(vmin, vmax, Vmin), + max(vmin, vmax, Vmax)) else: - self.axes._set_xviewlim(max(vmin, vmax, Vmin), - min(vmin, vmax, Vmax)) + self.axes.viewLim.intervalx = (max(vmin, vmax, Vmin), + min(vmin, vmax, Vmax)) + if auto is not None: + self.axes.set_autoscalex_on(bool(auto)) + if emit: + self.axes.callbacks.process('xlim_changed', self.axes) + # Call all of the other axes that are shared with this one + for other in self.axes.get_shared_x_axes().get_siblings(self.axes): + if other is not self.axes: + other.set_xlim(self.axes.viewLim.intervalx, emit=False, + auto=auto) + if (other.figure != self.axes.figure and + other.figure.canvas is not None): + other.figure.canvas.draw_idle() + self.axes.stale = True def get_minpos(self): return self.axes.dataLim.minposx @@ -2437,26 +2457,45 @@ def get_view_interval(self): 'return the Interval instance for this axis view limits' return self.axes.viewLim.intervaly - def set_view_interval(self, vmin, vmax, ignore=False): + def set_view_interval(self, vmin, vmax, ignore=False, emit=True, + auto=False): """ If *ignore* is *False*, the order of vmin, vmax does not matter; the original axis orientation will be preserved. In addition, the view limits can be - expanded, but will not be reduced. This method is + expanded, but will not be reduced. + If *emit* is *True*, observers will be notified of + limit change. If *auto* is *True*, it turns on + autoscaling of the y-axis, and if *auto* is *False*, + it turns off autoscaling of the y-axis, while *None* + leaves autoscaling unchanged. This method is for mpl internal use; for normal use, see :meth:`~matplotlib.axes.Axes.set_ylim`. """ if ignore: - self.axes._set_yviewlim(vmin, vmax) + self.axes.viewLim.intervaly = (vmin, vmax) else: Vmin, Vmax = self.get_view_interval() if Vmin < Vmax: - self.axes._set_yviewlim(min(vmin, vmax, Vmin), - max(vmin, vmax, Vmax)) + self.axes.viewLim.intervaly = (min(vmin, vmax, Vmin), + max(vmin, vmax, Vmax)) else: - self.axes._set_yviewlim(max(vmin, vmax, Vmin), - min(vmin, vmax, Vmax)) + self.axes.viewLim.intervaly = (max(vmin, vmax, Vmin), + min(vmin, vmax, Vmax)) + if auto is not None: + self.axes.set_autoscaley_on(bool(auto)) + if emit: + self.axes.callbacks.process('ylim_changed', self.axes) + # Call all of the other axes that are shared with this one + for other in self.axes.get_shared_y_axes().get_siblings(self.axes): + if other is not self.axes: + other.set_ylim(self.axes.viewLim.intervaly, emit=False, + auto=auto) + if (other.figure != self.axes.figure and + other.figure.canvas is not None): + other.figure.canvas.draw_idle() + self.axes.stale = True self.stale = True def get_minpos(self): diff --git a/lib/mpl_toolkits/mplot3d/axes3d.py b/lib/mpl_toolkits/mplot3d/axes3d.py index 3f73f5e804a1..6291c34ad340 100644 --- a/lib/mpl_toolkits/mplot3d/axes3d.py +++ b/lib/mpl_toolkits/mplot3d/axes3d.py @@ -29,6 +29,7 @@ import matplotlib.scale as mscale import matplotlib.transforms as mtransforms from matplotlib.axes import Axes, rcParams +from matplotlib.cbook import _backports from matplotlib.colors import Normalize, LightSource from matplotlib.transforms import Bbox from matplotlib.tri.triangulation import Triangulation @@ -640,22 +641,9 @@ def set_xlim3d(self, left=None, right=None, emit=True, auto=False, **kw): 'left=%s, right=%s') % (left, right)) left, right = mtransforms.nonsingular(left, right, increasing=False) left, right = self.xaxis.limit_range_for_scale(left, right) - self.xy_viewLim.intervalx = (left, right) - - if auto is not None: - self._autoscaleXon = bool(auto) - - if emit: - self.callbacks.process('xlim_changed', self) - # Call all of the other x-axes that are shared with this one - for other in self._shared_x_axes.get_siblings(self): - if other is not self: - other.set_xlim(self.xy_viewLim.intervalx, - emit=False, auto=auto) - if (other.figure != self.figure and - other.figure.canvas is not None): - other.figure.canvas.draw_idle() - self.stale = True + + self.xaxis.set_view_interval(left, right, ignore=True, emit=emit, + auto=auto) return left, right set_xlim = set_xlim3d @@ -692,22 +680,9 @@ def set_ylim3d(self, bottom=None, top=None, emit=True, auto=False, **kw): 'bottom=%s, top=%s') % (bottom, top)) bottom, top = mtransforms.nonsingular(bottom, top, increasing=False) bottom, top = self.yaxis.limit_range_for_scale(bottom, top) - self.xy_viewLim.intervaly = (bottom, top) - - if auto is not None: - self._autoscaleYon = bool(auto) - - if emit: - self.callbacks.process('ylim_changed', self) - # Call all of the other y-axes that are shared with this one - for other in self._shared_y_axes.get_siblings(self): - if other is not self: - other.set_ylim(self.xy_viewLim.intervaly, - emit=False, auto=auto) - if (other.figure != self.figure and - other.figure.canvas is not None): - other.figure.canvas.draw_idle() - self.stale = True + + self.yaxis.set_view_interval(bottom, top, ignore=True, emit=emit, + auto=auto) return bottom, top set_ylim = set_ylim3d @@ -744,22 +719,9 @@ def set_zlim3d(self, bottom=None, top=None, emit=True, auto=False, **kw): 'bottom=%s, top=%s') % (bottom, top)) bottom, top = mtransforms.nonsingular(bottom, top, increasing=False) bottom, top = self.zaxis.limit_range_for_scale(bottom, top) - self.zz_viewLim.intervalx = (bottom, top) - - if auto is not None: - self._autoscaleZon = bool(auto) - - if emit: - self.callbacks.process('zlim_changed', self) - # Call all of the other y-axes that are shared with this one - for other in self._shared_z_axes.get_siblings(self): - if other is not self: - other.set_zlim(self.zz_viewLim.intervalx, - emit=False, auto=auto) - if (other.figure != self.figure and - other.figure.canvas is not None): - other.figure.canvas.draw_idle() - self.stale = True + + self.zaxis.set_view_interval(bottom, top, ignore=True, emit=emit, + auto=auto) return bottom, top set_zlim = set_zlim3d @@ -950,6 +912,10 @@ def clabel(self, *args, **kwargs): """ return None + def get_shared_z_axes(self): + """Return a reference to the shared axes Grouper object for z axes.""" + return self._shared_z_axes + def view_init(self, elev=None, azim=None): """ Set the elevation and azimuth of the axes. @@ -1562,7 +1528,7 @@ def plot(self, xs, ys, *args, **kwargs): zdir = kwargs.pop('zdir', 'z') # Match length - zs = np.broadcast_to(zs, len(xs)) + zs = _backports.broadcast_to(zs, len(xs)) lines = super().plot(xs, ys, *args, **kwargs) for line in lines: @@ -2000,7 +1966,11 @@ def plot_trisurf(self, *args, **kwargs): xt = tri.x[triangles] yt = tri.y[triangles] zt = z[triangles] - verts = np.stack((xt, yt, zt), axis=-1) + + # verts = np.stack((xt, yt, zt), axis=-1) + verts = np.concatenate(( + xt[..., np.newaxis], yt[..., np.newaxis], zt[..., np.newaxis] + ), axis=-1) polyc = art3d.Poly3DCollection(verts, *args, **kwargs) @@ -2355,7 +2325,7 @@ def scatter(self, xs, ys, zs=0, zdir='z', s=20, c=None, depthshade=True, patches = super().scatter(xs, ys, s=s, c=c, *args, **kwargs) is_2d = not cbook.iterable(zs) - zs = np.broadcast_to(zs, len(xs)) + zs = _backports.broadcast_to(zs, len(xs)) art3d.patch_collection_2d_to_3d(patches, zs=zs, zdir=zdir, depthshade=depthshade) @@ -2394,7 +2364,7 @@ def bar(self, left, height, zs=0, zdir='z', *args, **kwargs): patches = super().bar(left, height, *args, **kwargs) - zs = np.broadcast_to(zs, len(left)) + zs = _backports.broadcast_to(zs, len(left)) verts = [] verts_zs = [] @@ -2681,7 +2651,8 @@ def calc_arrow(uvw, angle=15): UVW = np.column_stack(input_args[3:argi]).astype(float) # Normalize rows of UVW - norm = np.linalg.norm(UVW, axis=1) + # Note: with numpy 1.9+, could use np.linalg.norm(UVW, axis=1) + norm = np.sqrt(np.sum(UVW**2, axis=1)) # If any row of UVW is all zeros, don't make a quiver for it mask = norm > 0 @@ -2806,12 +2777,13 @@ def voxels(filled, **kwargs): if xyz is None: x, y, z = np.indices(coord_shape) else: - x, y, z = (np.broadcast_to(c, coord_shape) for c in xyz) + x, y, z = (_backports.broadcast_to(c, coord_shape) for c in xyz) def _broadcast_color_arg(color, name): if np.ndim(color) in (0, 1): # single color, like "red" or [1, 0, 0] - return np.broadcast_to(color, filled.shape + np.shape(color)) + return _backports.broadcast_to( + color, filled.shape + np.shape(color)) elif np.ndim(color) in (3, 4): # 3D array of strings, or 4D array with last axis rgb if np.shape(color)[:3] != filled.shape: diff --git a/lib/mpl_toolkits/mplot3d/axis3d.py b/lib/mpl_toolkits/mplot3d/axis3d.py index 4093e9bd81e0..6fcd087473d4 100644 --- a/lib/mpl_toolkits/mplot3d/axis3d.py +++ b/lib/mpl_toolkits/mplot3d/axis3d.py @@ -451,7 +451,8 @@ def get_view_interval(self): """return the Interval instance for this 3d axis view limits""" return self.v_interval - def set_view_interval(self, vmin, vmax, ignore=False): + def set_view_interval(self, vmin, vmax, ignore=False, emit=True, + auto=False): if ignore: self.v_interval = vmin, vmax else: @@ -467,17 +468,110 @@ def get_tightbbox(self, renderer): # Use classes to look at different data limits + class XAxis(Axis): def get_data_interval(self): 'return the Interval instance for this axis data limits' return self.axes.xy_dataLim.intervalx + def set_view_interval(self, vmin, vmax, ignore=False, emit=True, + auto=False): + """ + If *ignore* is *False*, the order of vmin, vmax + does not matter; the original axis orientation will + be preserved. In addition, the view limits can be + expanded, but will not be reduced. + If *emit* is *True*, observers will be notified of + limit change. If *auto* is *True*, it turns on + autoscaling of the x-axis, and if *auto* is *False*, + it turns off autoscaling of the x-axis, while *None* + leaves autoscaling unchanged. + + """ + Axis.set_view_interval(self, vmin, vmax, ignore=ignore, emit=emit, + auto=auto) + self.axes.xy_viewLim.intervalx = self.v_interval + if auto is not None: + self.axes.set_autoscalex_on(bool(auto)) + if emit: + self.axes.callbacks.process('xlim_changed', self.axes) + # Call all of the other x-axes that are shared with this one + for other in self.axes.get_shared_x_axes().get_siblings(self.axes): + if other is not self.axes: + other.set_xlim(self.v_interval, emit=False, auto=auto) + if (other.figure != self.axes.figure and + other.figure.canvas is not None): + other.figure.canvas.draw_idle() + self.axes.stale = True + + class YAxis(Axis): def get_data_interval(self): 'return the Interval instance for this axis data limits' return self.axes.xy_dataLim.intervaly + def set_view_interval(self, vmin, vmax, ignore=False, emit=True, + auto=False): + """ + If *ignore* is *False*, the order of vmin, vmax + does not matter; the original axis orientation will + be preserved. In addition, the view limits can be + expanded, but will not be reduced. + If *emit* is *True*, observers will be notified of + limit change. If *auto* is *True*, it turns on + autoscaling of the y-axis, and if *auto* is *False*, + it turns off autoscaling of the y-axis, while *None* + leaves autoscaling unchanged. + + """ + Axis.set_view_interval(self, vmin, vmax, ignore=ignore, emit=emit, + auto=auto) + self.axes.xy_viewLim.intervaly = self.v_interval + if auto is not None: + self.axes.set_autoscaley_on(bool(auto)) + if emit: + self.axes.callbacks.process('ylim_changed', self.axes) + # Call all of the other x-axes that are shared with this one + for other in self.axes.get_shared_y_axes().get_siblings(self.axes): + if other is not self.axes: + other.set_ylim(self.v_interval, emit=False, auto=auto) + if (other.figure != self.axes.figure and + other.figure.canvas is not None): + other.figure.canvas.draw_idle() + self.axes.stale = True + + class ZAxis(Axis): def get_data_interval(self): 'return the Interval instance for this axis data limits' return self.axes.zz_dataLim.intervalx + + def set_view_interval(self, vmin, vmax, ignore=False, emit=True, + auto=False): + """ + If *ignore* is *False*, the order of vmin, vmax + does not matter; the original axis orientation will + be preserved. In addition, the view limits can be + expanded, but will not be reduced. + If *emit* is *True*, observers will be notified of + limit change. If *auto* is *True*, it turns on + autoscaling of the z-axis, and if *auto* is *False*, + it turns off autoscaling of the z-axis, while *None* + leaves autoscaling unchanged. + + """ + Axis.set_view_interval(self, vmin, vmax, ignore=ignore, emit=emit, + auto=auto) + self.axes.zz_viewLim.intervalx = self.v_interval + if auto is not None: + self.axes.set_autoscalez_on(bool(auto)) + if emit: + self.axes.callbacks.process('zlim_changed', self.axes) + # Call all of the other x-axes that are shared with this one + for other in self.axes.get_shared_z_axes().get_siblings(self.axes): + if other is not self.axes: + other.set_zlim(self.v_interval, emit=False, auto=auto) + if (other.figure != self.axes.figure and + other.figure.canvas is not None): + other.figure.canvas.draw_idle() + self.axes.stale = True From 4900fe93afecd551775f53fc4e62a1f3da6102cb Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Wed, 7 Mar 2018 16:53:07 -0500 Subject: [PATCH 6/8] Remove changes not needed for PR --- lib/matplotlib/axes/_base.py | 53 ++++-------------------------- lib/mpl_toolkits/mplot3d/axes3d.py | 19 ++++------- 2 files changed, 13 insertions(+), 59 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index fc1ed2e60afa..5464404b7595 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -40,9 +40,6 @@ rcParams = matplotlib.rcParams -is_string_like = cbook.is_string_like -is_sequence_of_strings = cbook.is_sequence_of_strings - _hold_msg = """axes.hold is deprecated. See the API Changes document (http://matplotlib.org/api/api_changes.html) for more details.""" @@ -341,8 +338,7 @@ def _makefill(self, x, y, kw, kwargs): # modify the kwargs dictionary. self._setdefaults(default_dict, kwargs) - seg = mpatches.Polygon(np.hstack((x[:, np.newaxis], - y[:, np.newaxis])), + seg = mpatches.Polygon(np.column_stack((x, y)), facecolor=facecolor, fill=kwargs.get('fill', True), closed=kw['closed']) @@ -1132,11 +1128,6 @@ def cla(self): self.stale = True - @property - @cbook.deprecated("2.1", alternative="Axes.patch") - def axesPatch(self): - return self.patch - def clear(self): """Clear the axes.""" self.cla() @@ -1219,16 +1210,16 @@ def set_prop_cycle(self, *args, **kwargs): self._get_lines.set_prop_cycle(prop_cycle) self._get_patches_for_fill.set_prop_cycle(prop_cycle) + @cbook.deprecated('1.5', alternative='`.set_prop_cycle`') def set_color_cycle(self, clist): """ Set the color cycle for any future plot commands on this Axes. - *clist* is a list of mpl color specifiers. - - .. deprecated:: 1.5 + Parameters + ---------- + clist + A list of mpl color specifiers. """ - cbook.warn_deprecated( - '1.5', name='set_color_cycle', alternative='set_prop_cycle') if clist is None: # Calling set_color_cycle() or set_prop_cycle() with None # effectively resets the cycle, but you can't do @@ -4022,38 +4013,6 @@ def format_deltas(key, dx, dy): self.set_xlim(points[:, 0]) self.set_ylim(points[:, 1]) - @cbook.deprecated("2.1") - def get_cursor_props(self): - """ - Return the cursor propertiess as a (*linewidth*, *color*) - tuple, where *linewidth* is a float and *color* is an RGBA - tuple - """ - return self._cursorProps - - @cbook.deprecated("2.1") - def set_cursor_props(self, *args): - """Set the cursor property as - - Call signature :: - - ax.set_cursor_props(linewidth, color) - - or:: - - ax.set_cursor_props((linewidth, color)) - - ACCEPTS: a (*float*, *color*) tuple - """ - if len(args) == 1: - lw, c = args[0] - elif len(args) == 2: - lw, c = args - else: - raise ValueError('args must be a (linewidth, color) tuple') - c = mcolors.to_rgba(c) - self._cursorProps = lw, c - def get_children(self): """return a list of child artists""" children = [] diff --git a/lib/mpl_toolkits/mplot3d/axes3d.py b/lib/mpl_toolkits/mplot3d/axes3d.py index 6291c34ad340..e573e70252fc 100644 --- a/lib/mpl_toolkits/mplot3d/axes3d.py +++ b/lib/mpl_toolkits/mplot3d/axes3d.py @@ -29,7 +29,6 @@ import matplotlib.scale as mscale import matplotlib.transforms as mtransforms from matplotlib.axes import Axes, rcParams -from matplotlib.cbook import _backports from matplotlib.colors import Normalize, LightSource from matplotlib.transforms import Bbox from matplotlib.tri.triangulation import Triangulation @@ -1528,7 +1527,7 @@ def plot(self, xs, ys, *args, **kwargs): zdir = kwargs.pop('zdir', 'z') # Match length - zs = _backports.broadcast_to(zs, len(xs)) + zs = np.broadcast_to(zs, len(xs)) lines = super().plot(xs, ys, *args, **kwargs) for line in lines: @@ -1967,10 +1966,7 @@ def plot_trisurf(self, *args, **kwargs): yt = tri.y[triangles] zt = z[triangles] - # verts = np.stack((xt, yt, zt), axis=-1) - verts = np.concatenate(( - xt[..., np.newaxis], yt[..., np.newaxis], zt[..., np.newaxis] - ), axis=-1) + verts = np.stack((xt, yt, zt), axis=-1) polyc = art3d.Poly3DCollection(verts, *args, **kwargs) @@ -2325,7 +2321,7 @@ def scatter(self, xs, ys, zs=0, zdir='z', s=20, c=None, depthshade=True, patches = super().scatter(xs, ys, s=s, c=c, *args, **kwargs) is_2d = not cbook.iterable(zs) - zs = _backports.broadcast_to(zs, len(xs)) + zs = np.broadcast_to(zs, len(xs)) art3d.patch_collection_2d_to_3d(patches, zs=zs, zdir=zdir, depthshade=depthshade) @@ -2364,7 +2360,7 @@ def bar(self, left, height, zs=0, zdir='z', *args, **kwargs): patches = super().bar(left, height, *args, **kwargs) - zs = _backports.broadcast_to(zs, len(left)) + zs = np.broadcast_to(zs, len(left)) verts = [] verts_zs = [] @@ -2651,8 +2647,7 @@ def calc_arrow(uvw, angle=15): UVW = np.column_stack(input_args[3:argi]).astype(float) # Normalize rows of UVW - # Note: with numpy 1.9+, could use np.linalg.norm(UVW, axis=1) - norm = np.sqrt(np.sum(UVW**2, axis=1)) + norm = np.linalg.norm(UVW, axis=1) # If any row of UVW is all zeros, don't make a quiver for it mask = norm > 0 @@ -2777,12 +2772,12 @@ def voxels(filled, **kwargs): if xyz is None: x, y, z = np.indices(coord_shape) else: - x, y, z = (_backports.broadcast_to(c, coord_shape) for c in xyz) + x, y, z = (np.broadcast_to(c, coord_shape) for c in xyz) def _broadcast_color_arg(color, name): if np.ndim(color) in (0, 1): # single color, like "red" or [1, 0, 0] - return _backports.broadcast_to( + return np.broadcast_to( color, filled.shape + np.shape(color)) elif np.ndim(color) in (3, 4): # 3D array of strings, or 4D array with last axis rgb From b9511bbe571955262a3cccdbc6bcaf31e3d44ca3 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Thu, 29 Mar 2018 12:16:46 -0400 Subject: [PATCH 7/8] numpydoc compliant docstrings for set_view_interval --- lib/matplotlib/axis.py | 102 +++++++++++++++----- lib/mpl_toolkits/mplot3d/axis3d.py | 147 +++++++++++++++++++++++------ 2 files changed, 200 insertions(+), 49 deletions(-) diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index 3f17e271cad9..1bf35423237e 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -2063,18 +2063,47 @@ def get_view_interval(self): def set_view_interval(self, vmin, vmax, ignore=False, emit=True, auto=False): """ - If *ignore* is *False*, the order of vmin, vmax - does not matter; the original axis orientation will - be preserved. In addition, the view limits can be - expanded, but will not be reduced. - If *emit* is *True*, observers will be notified of - limit change. If *auto* is *True*, it turns on - autoscaling of the x-axis, and if *auto* is *False*, - it turns off autoscaling of the x-axis, while *None* - leaves autoscaling unchanged. This method is - for mpl internal use; for normal use, see - :meth:`~matplotlib.axes.Axes.set_xlim`. + Set the x-axis view limits for the parent Axes instance. + .. ACCEPTS: (vmin: float, vmax: float) + + Parameters + ---------- + vmin : scalar + The smaller value of viewLim. + + vmax : scalar + The higher value of viewLim. + + ignore : bool, optional + Whether we should take (vmin, vmax) literally (default: False). + If this is False, the order of vmin, vmax does not matter; the + original axis orientation will be preserved. + + emit : bool, optional + Whether to notify observers of limit change (default: True). + + auto : bool or None, optional + Whether to turn on autoscaling of this axis. True turns on, + False turns off (default action), None leaves unchanged. + + Notes + ----- + If `ignore` is False (default), the view limits can be expanded, but + will not be reduced. Otherwise, if `ignore` is True, the `vmin` value + may be greater than the `vmax` value, in which case the viewLim will + decrease from left to right. + + Examples + -------- + >>> set_view_interval(vmin, vmax, ignore=True) + + Sets the new view interval to (vmin, vmax). + + >>> set_view_interval(vmin, vmax) + + Expands the view interval to the minimum of the current interval + and vmin, and the maximum of the current interval and vmax. """ if ignore: self.axes.viewLim.intervalx = (vmin, vmax) @@ -2460,18 +2489,47 @@ def get_view_interval(self): def set_view_interval(self, vmin, vmax, ignore=False, emit=True, auto=False): """ - If *ignore* is *False*, the order of vmin, vmax - does not matter; the original axis orientation will - be preserved. In addition, the view limits can be - expanded, but will not be reduced. - If *emit* is *True*, observers will be notified of - limit change. If *auto* is *True*, it turns on - autoscaling of the y-axis, and if *auto* is *False*, - it turns off autoscaling of the y-axis, while *None* - leaves autoscaling unchanged. This method is - for mpl internal use; for normal use, see - :meth:`~matplotlib.axes.Axes.set_ylim`. + Set the y-axis view limits for the parent Axes instance. + + .. ACCEPTS: (vmin: float, vmax: float) + + Parameters + ---------- + vmin : scalar + The smaller value of viewLim. + + vmax : scalar + The higher value of viewLim. + + ignore : bool, optional + Whether we should take (vmin, vmax) literally (default: False). + If this is False, the order of vmin, vmax does not matter; the + original axis orientation will be preserved. + + emit : bool, optional + Whether to notify observers of limit change (default: True). + + auto : bool or None, optional + Whether to turn on autoscaling of this axis. True turns on, + False turns off (default action), None leaves unchanged. + + Notes + ----- + If `ignore` is False (default), the view limits can be expanded, but + will not be reduced. Otherwise, if `ignore` is True, the `vmin` value + may be greater than the `vmax` value, in which case the viewLim will + decrease from left to right. + + Examples + -------- + >>> set_view_interval(vmin, vmax, ignore=True) + + Sets the new view interval to (vmin, vmax). + + >>> set_view_interval(vmin, vmax) + Expands the view interval to the minimum of the current interval + and vmin, and the maximum of the current interval and vmax. """ if ignore: self.axes.viewLim.intervaly = (vmin, vmax) diff --git a/lib/mpl_toolkits/mplot3d/axis3d.py b/lib/mpl_toolkits/mplot3d/axis3d.py index 6fcd087473d4..bd477b62fd2d 100644 --- a/lib/mpl_toolkits/mplot3d/axis3d.py +++ b/lib/mpl_toolkits/mplot3d/axis3d.py @@ -477,16 +477,47 @@ def get_data_interval(self): def set_view_interval(self, vmin, vmax, ignore=False, emit=True, auto=False): """ - If *ignore* is *False*, the order of vmin, vmax - does not matter; the original axis orientation will - be preserved. In addition, the view limits can be - expanded, but will not be reduced. - If *emit* is *True*, observers will be notified of - limit change. If *auto* is *True*, it turns on - autoscaling of the x-axis, and if *auto* is *False*, - it turns off autoscaling of the x-axis, while *None* - leaves autoscaling unchanged. + Set the x-axis view limits for the parent Axes3D instance. + .. ACCEPTS: (vmin: float, vmax: float) + + Parameters + ---------- + vmin : scalar + The smaller value of viewLim. + + vmax : scalar + The higher value of viewLim. + + ignore : bool, optional + Whether we should take (vmin, vmax) literally (default: False). + If this is False, the order of vmin, vmax does not matter; the + original axis orientation will be preserved. + + emit : bool, optional + Whether to notify observers of limit change (default: True). + + auto : bool or None, optional + Whether to turn on autoscaling of this axis. True turns on, + False turns off (default action), None leaves unchanged. + + Notes + ----- + If `ignore` is False (default), the view limits can be expanded, but + will not be reduced. Otherwise, if `ignore` is True, the `vmin` value + may be greater than the `vmax` value, in which case the viewLim will + decrease from left to right. + + Examples + -------- + >>> set_view_interval(vmin, vmax, ignore=True) + + Sets the new view interval to (vmin, vmax). + + >>> set_view_interval(vmin, vmax) + + Expands the view interval to the minimum of the current interval + and vmin, and the maximum of the current interval and vmax. """ Axis.set_view_interval(self, vmin, vmax, ignore=ignore, emit=emit, auto=auto) @@ -513,16 +544,47 @@ def get_data_interval(self): def set_view_interval(self, vmin, vmax, ignore=False, emit=True, auto=False): """ - If *ignore* is *False*, the order of vmin, vmax - does not matter; the original axis orientation will - be preserved. In addition, the view limits can be - expanded, but will not be reduced. - If *emit* is *True*, observers will be notified of - limit change. If *auto* is *True*, it turns on - autoscaling of the y-axis, and if *auto* is *False*, - it turns off autoscaling of the y-axis, while *None* - leaves autoscaling unchanged. + Set the y-axis view limits for the parent Axes3D instance. + + .. ACCEPTS: (vmin: float, vmax: float) + + Parameters + ---------- + vmin : scalar + The smaller value of viewLim. + + vmax : scalar + The higher value of viewLim. + + ignore : bool, optional + Whether we should take (vmin, vmax) literally (default: False). + If this is False, the order of vmin, vmax does not matter; the + original axis orientation will be preserved. + + emit : bool, optional + Whether to notify observers of limit change (default: True). + auto : bool or None, optional + Whether to turn on autoscaling of this axis. True turns on, + False turns off (default action), None leaves unchanged. + + Notes + ----- + If `ignore` is False (default), the view limits can be expanded, but + will not be reduced. Otherwise, if `ignore` is True, the `vmin` value + may be greater than the `vmax` value, in which case the viewLim will + decrease from left to right. + + Examples + -------- + >>> set_view_interval(vmin, vmax, ignore=True) + + Sets the new view interval to (vmin, vmax). + + >>> set_view_interval(vmin, vmax) + + Expands the view interval to the minimum of the current interval + and vmin, and the maximum of the current interval and vmax. """ Axis.set_view_interval(self, vmin, vmax, ignore=ignore, emit=emit, auto=auto) @@ -549,16 +611,47 @@ def get_data_interval(self): def set_view_interval(self, vmin, vmax, ignore=False, emit=True, auto=False): """ - If *ignore* is *False*, the order of vmin, vmax - does not matter; the original axis orientation will - be preserved. In addition, the view limits can be - expanded, but will not be reduced. - If *emit* is *True*, observers will be notified of - limit change. If *auto* is *True*, it turns on - autoscaling of the z-axis, and if *auto* is *False*, - it turns off autoscaling of the z-axis, while *None* - leaves autoscaling unchanged. + Set the z-axis view limits for the parent Axes3D instance. + + .. ACCEPTS: (vmin: float, vmax: float) + + Parameters + ---------- + vmin : scalar + The smaller value of viewLim. + + vmax : scalar + The higher value of viewLim. + + ignore : bool, optional + Whether we should take (vmin, vmax) literally (default: False). + If this is False, the order of vmin, vmax does not matter; the + original axis orientation will be preserved. + + emit : bool, optional + Whether to notify observers of limit change (default: True). + + auto : bool or None, optional + Whether to turn on autoscaling of this axis. True turns on, + False turns off (default action), None leaves unchanged. + + Notes + ----- + If `ignore` is False (default), the view limits can be expanded, but + will not be reduced. Otherwise, if `ignore` is True, the `vmin` value + may be greater than the `vmax` value, in which case the viewLim will + decrease from left to right. + + Examples + -------- + >>> set_view_interval(vmin, vmax, ignore=True) + + Sets the new view interval to (vmin, vmax). + + >>> set_view_interval(vmin, vmax) + Expands the view interval to the minimum of the current interval + and vmin, and the maximum of the current interval and vmax. """ Axis.set_view_interval(self, vmin, vmax, ignore=ignore, emit=emit, auto=auto) From d7f075fd5b0597e7a47d2bb89700af64265085f8 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Sat, 31 Mar 2018 17:39:06 -0400 Subject: [PATCH 8/8] Fix PEP8 from merge --- lib/matplotlib/tests/test_axes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index c5bb4cfc1ab6..cd67b49f4eb9 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -5172,7 +5172,7 @@ def test_shared_axes_autoscale(): assert not ax1.get_autoscaley_on() and not ax2.get_autoscaley_on() assert ax1.get_xlim() == ax2.get_xlim() == (-1000, 1000) assert ax1.get_ylim() == ax2.get_ylim() == (-1000, 1000) - + def test_adjust_numtick_aspect(): fig, ax = plt.subplots()