Expand Up @@ -426,6 +426,30 @@ axis_name = 'theta' #: Read-only name identifying the axis. _tick_class = ThetaTick def _update_label_position(self, renderer): """ Update the label position based on the bounding box enclosing all the ticklabels and axis spine """ if not self._autolabelpos: return Check warning on line 435 in lib/matplotlib/projections/polar.py
View check run for this annotation Codecov / codecov/patch lib/matplotlib/projections/polar.py#L435
Added line #L435 was not covered by tests
# get bounding boxes for this axis and any siblings # that have been set by `fig.align_xlabels()` xbboxes, xbboxes2 = self._get_tick_boxes_siblings(renderer=renderer) ybboxes, ybboxes2 = self.axes.yaxis._get_tick_boxes_siblings(renderer=renderer) # Union with extents of the bottom spine if present, of the axes otherwise. bbox = mtransforms.Bbox.union([ *xbboxes, *xbboxes2, *ybboxes, *ybboxes2, self.axes.spines.get(self.label_position, self.axes).get_window_extent()]) x, y = self.label.get_position() if self.label_position == 'bottom': y = bbox.y0 - self.labelpad * self.get_figure(root=True).dpi / 72 else: y = bbox.y1 + self.labelpad * self.get_figure(root=True).dpi / 72 Check warning on line 450 in lib/matplotlib/projections/polar.py
View check run for this annotation Codecov / codecov/patch lib/matplotlib/projections/polar.py#L450
Added line #L450 was not covered by tests
self.label.set_position((x, y)) def _wrap_locator_formatter(self): self.set_major_locator(ThetaLocator(self.get_major_locator())) self.set_major_formatter(ThetaFormatter()) Expand Down Expand Up @@ -719,6 +743,30 @@ super().__init__(*args, **kwargs) self.sticky_edges.y.append(0) def _update_label_position(self, renderer): """ Update the label position based on the bounding box enclosing all the ticklabels and axis spine """ if not self._autolabelpos: return Check warning on line 752 in lib/matplotlib/projections/polar.py
View check run for this annotation Codecov / codecov/patch lib/matplotlib/projections/polar.py#L752
Added line #L752 was not covered by tests
# get bounding boxes for this axis and any siblings # that have been set by `fig.align_xlabels()` xbboxes, xbboxes2 = self._get_tick_boxes_siblings(renderer=renderer) ybboxes, ybboxes2 = self.axes.xaxis._get_tick_boxes_siblings(renderer=renderer) # Union with extents of the linked spine if present, of the axes otherwise. bbox = mtransforms.Bbox.union([ *xbboxes, *xbboxes2, *ybboxes, *ybboxes2, self.axes.spines.get(self.label_position, self.axes).get_window_extent()]) x, y = self.label.get_position() if self.label_position == 'left': x = bbox.x0 - self.labelpad * self.get_figure(root=True).dpi / 72 else: x = bbox.x1 + self.labelpad * self.get_figure(root=True).dpi / 72 Check warning on line 767 in lib/matplotlib/projections/polar.py
View check run for this annotation Codecov / codecov/patch lib/matplotlib/projections/polar.py#L767
Added line #L767 was not covered by tests
self.label.set_position((x, y)) def _wrap_locator_formatter(self): self.set_major_locator(RadialLocator(self.get_major_locator(), self.axes)) Expand Down Expand Up @@ -757,6 +805,8 @@ """ Transform (theta, r) wedge Bbox into Axes bounding box. Additionally, this class will update the Axes patch, if set by `_set_wedge`. Parameters ---------- center : (float, float) Expand All @@ -771,6 +821,7 @@ self._center = center self._viewLim = viewLim self._originLim = originLim self._wedge = None self.set_children(viewLim, originLim) __str__ = mtransforms._make_str_method("_center", "_viewLim", "_originLim") Expand All @@ -793,21 +844,32 @@ width = min(points[1, 1] - points[0, 1], 0.5) # Generate bounding box for wedge. wedge = mpatches.Wedge(self._center, points[1, 1], points[0, 0], points[1, 0], width=width) self.update_from_path(wedge.get_path()) # Ensure equal aspect ratio. w, h = self._points[1] - self._points[0] deltah = max(w - h, 0) / 2 deltaw = max(h - w, 0) / 2 self._points += np.array([[-deltaw, -deltah], [deltaw, deltah]]) if self._wedge is None: # A PolarAxes subclass may not generate a Wedge as Axes patch and call # _WedgeBbox._set_wedge, so use a temporary instance to calculate the # bounds instead. wedge = mpatches.Wedge(self._center, points[1, 1], Check warning on line 851 in lib/matplotlib/projections/polar.py
View check run for this annotation Codecov / codecov/patch lib/matplotlib/projections/polar.py#L851
Added line #L851 was not covered by tests
points[0, 0], points[1, 0], width=width) else: # Update the owning Axes' patch. wedge = self._wedge wedge.set_center(self._center) wedge.set_theta1(points[0, 0]) wedge.set_theta2(points[1, 0]) wedge.set_radius(points[1, 1]) wedge.set_width(width) self.update_from_path(wedge.get_path(), ignore=True) self._invalid = 0 return self._points def _set_wedge(self, wedge): """Set the wedge patch to update when the transform changes.""" _api.check_isinstance(mpatches.Wedge, wedge=wedge) self._wedge = wedge class PolarAxes(Axes): """ Expand Down Expand Up @@ -859,8 +921,11 @@ self.spines['polar'].register_axis(self.yaxis) def _set_lim_and_transforms(self): # A view limit where the minimum radius can be locked if the user # specifies an alternate origin. # self.viewLim is set by the superclass and contains (θ, r) as its (x, y) # components. # This is a view limit (still in (θ, r) space) where the minimum radius can be # locked if the user specifies an alternate origin. self._originViewLim = mtransforms.LockableBbox(self.viewLim) # Handle angular offset and direction. Expand All @@ -869,30 +934,26 @@ self._theta_offset = mtransforms.Affine2D() \ .translate(self._default_theta_offset, 0.0) self.transShift = self._direction + self._theta_offset # A view limit shifted to the correct location after accounting for # orientation and offset. self._realViewLim = mtransforms.TransformedBbox(self.viewLim, self.transShift) # Transforms the x and y axis separately by a scale factor # It is assumed that this part will have non-linear components self.transScale = mtransforms.TransformWrapper( mtransforms.IdentityTransform()) # Scale view limit into a bbox around the selected wedge. This may be # smaller than the usual unit axes rectangle if not plotting the full # circle. self.axesLim = _WedgeBbox((0.5, 0.5), self._realViewLim, self._originViewLim) # Scale the wedge to fill the axes. # This is a view limit in (θ, r) shifted to the correct location after # accounting for θ orientation and offset. self._realViewLim = mtransforms.TransformedBbox(self.viewLim, self.transShift) # Transforms the θ and r axis separately by a scale factor. It is assumed that # this part will have the non-linear components. self.transScale = mtransforms.TransformWrapper(mtransforms.IdentityTransform()) # Scale view limit into a bbox around the selected wedge. This may be smaller # than the usual unit axes rectangle if not plotting the full circle. self.axesLim = _WedgeBbox((0.5, 0.5), self._realViewLim, self._originViewLim) # Scale the wedge to fill the Axes unit space. self.transWedge = mtransforms.BboxTransformFrom(self.axesLim) # Scale theaxes to fill thefigure . # Scale theAxes unit space to fill theAxes actual position . self.transAxes = mtransforms.BboxTransformTo(self.bbox) # A (possibly non-linear) projection on the (already scaled) #data. This one is aware of rmin # A (possibly non-linear) projection on the (already scaled) data. This one is # aware of rmin. self.transProjection = self.PolarTransform( self, apply_theta_transforms=False, Expand All @@ -901,52 +962,48 @@ # Add dependency on rorigin. self.transProjection.set_children(self._originViewLim) # An affine transformation on the data, generally to limit the # range of the axes # An affine transformation on the data, generally to limit the range of the axes self.transProjectionAffine = self.PolarAffine(self.transScale, self._originViewLim) # The complete data transformation stack -- from data all the # way to display coordinates # # 1. Remove any radial axis scaling (e.g. log scaling) # 2. Shift data in the theta direction # 3. Project the data from polar to cartesian values # (with the origin in the same place) # 4. Scale and translate the cartesian values to Axes coordinates # (here the origin is moved to the lower left of the Axes) # 5. Move and scale to fill the Axes # 6. Convert from Axes coordinates to Figure coordinates # The complete data transformation stack -- from data all the way to display # coordinates. self.transData = ( # 1. Remove any radial axis scaling (e.g. log scaling). self.transScale + # 2. Shift data in the θ direction. self.transShift + # 3. Project the data from polar to cartesian values (with the origin in the # same place). self.transProjection + ( # 4. Scale and translate the cartesian values to Axes coordinates (here # the origin is moved to the lower left of the Axes). self.transProjectionAffine + # 5. Move and scale to fill the Axes. self.transWedge + # 6. Convert from Axes coordinates to Figure coordinates. self.transAxes ) ) # This is the transform for theta-axis ticks. It is # equivalent to transData, except it always puts r == 0.0 and r == 1.0 # at the edge of the axis circles. # This is the transform for θ-axis ticks. It is equivalent to transData, except # it always puts r == 0.0 and r == 1.0 at the edge of the axis circles. self._xaxis_transform = ( mtransforms.blended_transform_factory( mtransforms.IdentityTransform(), mtransforms.BboxTransformTo(self.viewLim)) + self.transData) # Thetheta labels are flipped along the radius, so that text 1 is on #the outside by default. This should work the same as before. # Theθ labels are flipped along the radius, so that text 1 is on the outside by # default. This should work the same as before. flipr_transform = mtransforms.Affine2D() \ .translate(0.0, -0.5) \ .scale(1.0, -1.0) \ .translate(0.0, 0.5) self._xaxis_text_transform = flipr_transform + self._xaxis_transform # This is the transform for r-axis ticks. It scales the theta # axis so the gridlines from 0.0 to 1.0, now go from thetamin to # thetamax. # This is the transform for r-axis ticks. It scales the θ-axis so the gridlines # from 0.0 to 1.0, now go from thetamin to thetamax. self._yaxis_transform = ( mtransforms.blended_transform_factory( mtransforms.BboxTransformTo(self.viewLim), Expand Down Expand Up @@ -999,31 +1056,16 @@ def draw(self, renderer): self._unstale_viewLim() thetamin, thetamax = np.rad2deg(self._realViewLim.intervalx) if thetamin > thetamax: thetamin, thetamax = thetamax, thetamin rmin, rmax = ((self._realViewLim.intervaly - self.get_rorigin()) * self.get_rsign()) self.axesLim.get_points() # Unstale bbox and Axes patch. self.set_aspect(self.axesLim.height / self.axesLim.width) if isinstance(self.patch, mpatches.Wedge): # Backwards-compatibility: Any subclassed Axes might override the # patch to not be the Wedge that PolarAxes uses. center = self.transWedge.transform((0.5, 0.5)) self.patch.set_center(center) self.patch.set_theta1(thetamin) self.patch.set_theta2(thetamax) edge, _ = self.transWedge.transform((1, 0)) radius = edge - center[0] width = min(radius * (rmax - rmin) / rmax, radius) self.patch.set_radius(radius) self.patch.set_width(width) inner_width = radius - width inner = self.spines.get('inner', None) if inner: inner.set_visible(inner_width !=0.0 ) inner.set_visible(self.patch.r !=self.patch.width ) visible = not_is_full_circle_deg(thetamin, thetamax ) visible = not_is_full_circle_rad(*self._realViewLim.intervalx ) # For backwards compatibility, any subclassed Axes might override the # spines to not include start/end that PolarAxes uses. start = self.spines.get('start', None) Expand All @@ -1043,8 +1085,20 @@ super().draw(renderer) def _wedge_get_patch_transform(self): # See _gen_axes_patch for the use of this function. It's not a lambda or nested # function to not break pickling. return self.transWedge def _gen_axes_patch(self): return mpatches.Wedge((0.5, 0.5), 0.5, 0.0, 360.0) wedge = mpatches.Wedge((0.5, 0.5), 0.5, 0.0, 360.0) self.axesLim._set_wedge(wedge) # The caller of this function will set the wedge's transform directly to # `self.transAxes`, but `self.axesLim` will update to a pre-`self.transWedge` # coordinate space, so override the patch transform (which is otherwise always # an identity transform) to get the wedge in the right coordinate space. wedge.get_patch_transform = self._wedge_get_patch_transform return wedge def _gen_axes_spines(self): spines = { Expand Down