diff --git a/doc/api/api_changes_3.3/deprecations.rst b/doc/api/api_changes_3.3/deprecations.rst index 920e208399c1..4d12f59edbe7 100644 --- a/doc/api/api_changes_3.3/deprecations.rst +++ b/doc/api/api_changes_3.3/deprecations.rst @@ -433,3 +433,8 @@ Normalization of upper or mixed-case property names to lowercase in `.Artist.set` and `.Artist.update` is deprecated. In the future, property names will be passed as is, allowing one to pass names such as *patchA* or *UVC*. + +``ContourSet.ax``, ``Quiver.ax`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +These attributes are deprecated in favor of ``ContourSet.axes`` and +``Quiver.axes``, for consistency with other artists. diff --git a/lib/matplotlib/contour.py b/lib/matplotlib/contour.py index 40c2195c48a1..8c67d09f0c72 100644 --- a/lib/matplotlib/contour.py +++ b/lib/matplotlib/contour.py @@ -261,7 +261,7 @@ def set_label_props(self, label, text, color): label.set_text(text) label.set_color(color) label.set_fontproperties(self.labelFontProps) - label.set_clip_box(self.ax.bbox) + label.set_clip_box(self.axes.bbox) def get_text(self, lev, fmt): """Get the text of the label.""" @@ -401,7 +401,7 @@ def calc_label_rot_and_inline(self, slc, ind, lw, lc=None, spacing=5): return rotation, nlc def _get_label_text(self, x, y, rotation): - dx, dy = self.ax.transData.inverted().transform((x, y)) + dx, dy = self.axes.transData.inverted().transform((x, y)) t = text.Text(dx, dy, rotation=rotation, horizontalalignment='center', verticalalignment='center', zorder=self._clabel_zorder) @@ -412,7 +412,7 @@ def _get_label_clabeltext(self, x, y, rotation): # the data coordinate and create a label using ClabelText # class. This way, the rotation of the clabel is along the # contour line always. - transDataInv = self.ax.transData.inverted() + transDataInv = self.axes.transData.inverted() dx, dy = transDataInv.transform((x, y)) drotation = transDataInv.transform_angles(np.array([rotation]), np.array([[x, y]])) @@ -432,7 +432,7 @@ def _add_label(self, t, x, y, lev, cvalue): self.labelXYs.append((x, y)) # Add label to plot here - useful for manual mode label selection - self.ax.add_artist(t) + self.axes.add_artist(t) def add_label(self, x, y, rotation, lev, cvalue): """ @@ -476,7 +476,7 @@ def add_label_near(self, x, y, inline=True, inline_spacing=5, """ if transform is None: - transform = self.ax.transData + transform = self.axes.transData if transform: x, y = transform.transform((x, y)) @@ -495,7 +495,7 @@ def add_label_near(self, x, y, inline=True, inline_spacing=5, # grab its vertices lc = active_path.vertices # sort out where the new vertex should be added data-units - xcmin = self.ax.transData.inverted().transform([xmin, ymin]) + xcmin = self.axes.transData.inverted().transform([xmin, ymin]) # if there isn't a vertex close enough if not np.allclose(xcmin, lc[imin]): # insert new data into the vertex list @@ -511,13 +511,13 @@ def add_label_near(self, x, y, inline=True, inline_spacing=5, lc = paths[segmin].vertices # In pixel/screen space - slc = self.ax.transData.transform(lc) + slc = self.axes.transData.transform(lc) # Get label width for rotating labels and breaking contours lw = self.get_label_width(self.labelLevelList[lmin], self.labelFmt, self.labelFontSizeList[lmin]) # lw is in points. - lw *= self.ax.figure.dpi / 72.0 # scale to screen coordinates + lw *= self.axes.figure.dpi / 72 # scale to screen coordinates # now lw in pixels # Figure out label rotation. @@ -556,7 +556,7 @@ def labels(self, inline, inline_spacing): con = self.collections[icon] trans = con.get_transform() lw = self.get_label_width(lev, self.labelFmt, fsize) - lw *= self.ax.figure.dpi / 72.0 # scale to screen coordinates + lw *= self.axes.figure.dpi / 72 # scale to screen coordinates additions = [] paths = con.get_paths() for segNum, linepath in enumerate(paths): @@ -773,7 +773,7 @@ def __init__(self, ax, *args, Keyword arguments are as described in the docstring of `~.Axes.contour`. """ - self.ax = ax + self.axes = ax self.levels = levels self.filled = filled self.linewidths = linewidths @@ -889,7 +889,7 @@ def __init__(self, ax, *args, alpha=self.alpha, transform=self.get_transform(), zorder=self._contour_zorder) - self.ax.add_collection(col, autolim=False) + self.axes.add_collection(col, autolim=False) self.collections.append(col) else: tlinewidths = self._process_linewidths() @@ -911,14 +911,14 @@ def __init__(self, ax, *args, transform=self.get_transform(), zorder=self._contour_zorder) col.set_label('_nolegend_') - self.ax.add_collection(col, autolim=False) + self.axes.add_collection(col, autolim=False) self.collections.append(col) for col in self.collections: col.sticky_edges.x[:] = [self._mins[0], self._maxs[0]] col.sticky_edges.y[:] = [self._mins[1], self._maxs[1]] - self.ax.update_datalim([self._mins, self._maxs]) - self.ax.autoscale_view(tight=True) + self.axes.update_datalim([self._mins, self._maxs]) + self.axes.autoscale_view(tight=True) self.changed() # set the colors @@ -927,16 +927,21 @@ def __init__(self, ax, *args, cbook._warn_external('The following kwargs were not used by ' 'contour: ' + s) + @cbook.deprecated("3.3") + @property + def ax(self): + return self.axes + def get_transform(self): """ Return the :class:`~matplotlib.transforms.Transform` instance used by this ContourSet. """ if self._transform is None: - self._transform = self.ax.transData + self._transform = self.axes.transData elif (not isinstance(self._transform, mtransforms.Transform) and hasattr(self._transform, '_as_mpl_transform')): - self._transform = self._transform._as_mpl_transform(self.ax) + self._transform = self._transform._as_mpl_transform(self.axes) return self._transform def __getstate__(self): @@ -1431,9 +1436,9 @@ def _process_args(self, *args, corner_mask=None, **kwargs): # if the transform is not trans data, and some part of it # contains transData, transform the xs and ys to data coordinates - if (t != self.ax.transData and - any(t.contains_branch_seperately(self.ax.transData))): - trans_to_data = t - self.ax.transData + if (t != self.axes.transData and + any(t.contains_branch_seperately(self.axes.transData))): + trans_to_data = t - self.axes.transData pts = np.vstack([x.flat, y.flat]).T transformed_pts = trans_to_data.transform(pts) x = transformed_pts[..., 0] @@ -1498,9 +1503,9 @@ def _check_xyz(self, args, kwargs): convert them to 2D using meshgrid. """ x, y = args[:2] - kwargs = self.ax._process_unit_info(xdata=x, ydata=y, kwargs=kwargs) - x = self.ax.convert_xunits(x) - y = self.ax.convert_yunits(y) + kwargs = self.axes._process_unit_info(xdata=x, ydata=y, kwargs=kwargs) + x = self.axes.convert_xunits(x) + y = self.axes.convert_yunits(y) x = np.asarray(x, dtype=np.float64) y = np.asarray(y, dtype=np.float64) diff --git a/lib/matplotlib/quiver.py b/lib/matplotlib/quiver.py index abed5202cbb8..673424d104e5 100644 --- a/lib/matplotlib/quiver.py +++ b/lib/matplotlib/quiver.py @@ -259,7 +259,7 @@ def __init__(self, Q, X, Y, U, label, self.color = color self.label = label self._labelsep_inches = labelsep - self.labelsep = (self._labelsep_inches * Q.ax.figure.dpi) + self.labelsep = (self._labelsep_inches * Q.axes.figure.dpi) # try to prevent closure over the real self weak_self = weakref.ref(self) @@ -272,8 +272,8 @@ def on_dpi_change(fig): # the start of draw. self_weakref._initialized = False - self._cid = Q.ax.figure.callbacks.connect('dpi_changed', - on_dpi_change) + self._cid = Q.axes.figure.callbacks.connect( + 'dpi_changed', on_dpi_change) self.labelpos = labelpos self.labelcolor = labelcolor @@ -293,13 +293,10 @@ def on_dpi_change(fig): self.zorder = Q.zorder + 0.1 def remove(self): - """ - Overload the remove method - """ - self.Q.ax.figure.callbacks.disconnect(self._cid) + # docstring inherited + self.Q.axes.figure.callbacks.disconnect(self._cid) self._cid = None - # pass the remove call up the stack - martist.Artist.remove(self) + super().remove() # pass the remove call up the stack def _init(self): if True: # not self._initialized: @@ -355,16 +352,12 @@ def draw(self, renderer): self.stale = False def _set_transform(self): - if self.coord == 'data': - self.set_transform(self.Q.ax.transData) - elif self.coord == 'axes': - self.set_transform(self.Q.ax.transAxes) - elif self.coord == 'figure': - self.set_transform(self.Q.ax.figure.transFigure) - elif self.coord == 'inches': - self.set_transform(self.Q.ax.figure.dpi_scale_trans) - else: - raise ValueError('unrecognized coordinates') + self.set_transform(cbook._check_getitem({ + "data": self.Q.axes.transData, + "axes": self.Q.axes.transAxes, + "figure": self.Q.axes.figure.transFigure, + "inches": self.Q.axes.figure.dpi_scale_trans, + }, coordinates=self.coord)) def set_figure(self, fig): martist.Artist.set_figure(self, fig) @@ -477,7 +470,7 @@ def __init__(self, ax, *args, by the following pyplot interface documentation: %s """ - self.ax = ax + self._axes = ax # The attr actually set by the Artist.axes property. X, Y, U, V, C = _parse_args(*args, caller_name='quiver()') self.X = X self.Y = Y @@ -510,8 +503,7 @@ def __init__(self, ax, *args, self.set_UVC(U, V, C) self._initialized = False - # try to prevent closure over the real self - weak_self = weakref.ref(self) + weak_self = weakref.ref(self) # Prevent closure over the real self. def on_dpi_change(fig): self_weakref = weak_self() @@ -522,18 +514,17 @@ def on_dpi_change(fig): # the start of draw. self_weakref._initialized = False - self._cid = self.ax.figure.callbacks.connect('dpi_changed', - on_dpi_change) + self._cid = ax.figure.callbacks.connect('dpi_changed', on_dpi_change) + + @cbook.deprecated("3.3", alternative="axes") + def ax(self): + return self.axes def remove(self): - """ - Overload the remove method - """ - # disconnect the call back - self.ax.figure.callbacks.disconnect(self._cid) + # docstring inherited + self.axes.figure.callbacks.disconnect(self._cid) self._cid = None - # pass the remove call up the stack - mcollections.PolyCollection.remove(self) + super().remove() # pass the remove call up the stack def _init(self): """ @@ -544,8 +535,7 @@ def _init(self): # available to have this work on an as-needed basis at present. if True: # not self._initialized: trans = self._set_transform() - ax = self.ax - self.span = trans.inverted().transform_bbox(ax.bbox).width + self.span = trans.inverted().transform_bbox(self.axes.bbox).width if self.width is None: sn = np.clip(math.sqrt(self.N), 8, 25) self.width = 0.06 * self.span / sn @@ -606,31 +596,30 @@ def _dots_per_unit(self, units): """ Return a scale factor for converting from units to pixels """ - ax = self.ax if units in ('x', 'y', 'xy'): if units == 'x': - dx0 = ax.viewLim.width - dx1 = ax.bbox.width + dx0 = self.axes.viewLim.width + dx1 = self.axes.bbox.width elif units == 'y': - dx0 = ax.viewLim.height - dx1 = ax.bbox.height + dx0 = self.axes.viewLim.height + dx1 = self.axes.bbox.height else: # 'xy' is assumed - dxx0 = ax.viewLim.width - dxx1 = ax.bbox.width - dyy0 = ax.viewLim.height - dyy1 = ax.bbox.height + dxx0 = self.axes.viewLim.width + dxx1 = self.axes.bbox.width + dyy0 = self.axes.viewLim.height + dyy1 = self.axes.bbox.height dx1 = np.hypot(dxx1, dyy1) dx0 = np.hypot(dxx0, dyy0) dx = dx1 / dx0 else: if units == 'width': - dx = ax.bbox.width + dx = self.axes.bbox.width elif units == 'height': - dx = ax.bbox.height + dx = self.axes.bbox.height elif units == 'dots': dx = 1.0 elif units == 'inches': - dx = ax.figure.dpi + dx = self.axes.figure.dpi else: raise ValueError('unrecognized units') return dx @@ -647,9 +636,9 @@ def _set_transform(self): return trans def _angles_lengths(self, U, V, eps=1): - xy = self.ax.transData.transform(self.XY) + xy = self.axes.transData.transform(self.XY) uv = np.column_stack((U, V)) - xyp = self.ax.transData.transform(self.XY + eps * uv) + xyp = self.axes.transData.transform(self.XY + eps * uv) dxy = xyp - xy angles = np.arctan2(dxy[:, 1], dxy[:, 0]) lengths = np.hypot(*dxy.T) / eps @@ -667,7 +656,7 @@ def _make_verts(self, U, V, angles): # Calculate eps based on the extents of the plot # so that we don't end up with roundoff error from # adding a small number to a large. - eps = np.abs(self.ax.dataLim.extents).max() * 0.001 + eps = np.abs(self.axes.dataLim.extents).max() * 0.001 angles, lengths = self._angles_lengths(U, V, eps=eps) if str_angles and self.scale_units == 'xy': a = lengths @@ -803,7 +792,6 @@ def _h_arrows(self, length): : / \ \ \ : ------------------------------ - The largest increment is given by a triangle (or "flag"). After those come full lines (barbs). The smallest increment is a half line. There is only, of course, ever at most 1 half line. If the magnitude is @@ -815,8 +803,6 @@ def _h_arrows(self, length): See also https://en.wikipedia.org/wiki/Wind_barb. - - Parameters ---------- X, Y : 1D or 2D array-like, optional