22import types
33
44import numpy as np
5+ import warnings
56
67from matplotlib .axes import Axes
78import matplotlib .axis as maxis
@@ -57,7 +58,8 @@ def transform_non_affine(self, tr):
5758 t += self ._axis .get_theta_offset ()
5859
5960 if self ._use_rmin and self ._axis is not None :
60- r = r - self ._axis .get_rorigin ()
61+ r = (r - self ._axis .get_rorigin ()) * self ._axis .get_rsign ()
62+
6163 mask = r < 0
6264 x [:] = np .where (mask , np .nan , r * np .cos (t ))
6365 y [:] = np .where (mask , np .nan , r * np .sin (t ))
@@ -161,6 +163,7 @@ def transform_non_affine(self, xy):
161163
162164 if self ._use_rmin and self ._axis is not None :
163165 r += self ._axis .get_rorigin ()
166+ r *= self ._axis .get_rsign ()
164167
165168 return np .concatenate ((theta , r ), 1 )
166169 transform_non_affine .__doc__ = \
@@ -421,10 +424,9 @@ def __call__(self):
421424 # Ensure previous behaviour with full circle non-annular views.
422425 if self ._axes :
423426 if _is_full_circle_rad (* self ._axes .viewLim .intervalx ):
424- rorigin = self ._axes .get_rorigin ()
427+ rorigin = self ._axes .get_rorigin () * self . _axes . get_rsign ()
425428 if self ._axes .get_rmin () <= rorigin :
426429 show_all = False
427-
428430 if show_all :
429431 return self .base ()
430432 else :
@@ -444,7 +446,10 @@ def refresh(self):
444446
445447 def view_limits (self , vmin , vmax ):
446448 vmin , vmax = self .base .view_limits (vmin , vmax )
447- return mtransforms .nonsingular (min (0 , vmin ), vmax )
449+ if vmax > vmin :
450+ # this allows inverted r/y-lims
451+ vmin = min (0 , vmin )
452+ return mtransforms .nonsingular (vmin , vmax )
448453
449454
450455class _ThetaShift (mtransforms .ScaledTranslation ):
@@ -767,7 +772,6 @@ def __str__(self):
767772 def get_points (self ):
768773 if self ._invalid :
769774 points = self ._viewLim .get_points ().copy ()
770-
771775 # Scale angular limits to work with Wedge.
772776 points [:, 0 ] *= 180 / np .pi
773777 if points [0 , 0 ] > points [1 , 0 ]:
@@ -992,8 +996,8 @@ def draw(self, *args, **kwargs):
992996 thetamin , thetamax = np .rad2deg (self ._realViewLim .intervalx )
993997 if thetamin > thetamax :
994998 thetamin , thetamax = thetamax , thetamin
995- rmin , rmax = self ._realViewLim .intervaly - self .get_rorigin ()
996-
999+ rmin , rmax = (( self ._realViewLim .intervaly - self .get_rorigin ()) *
1000+ self . get_rsign ())
9971001 if isinstance (self .patch , mpatches .Wedge ):
9981002 # Backwards-compatibility: Any subclassed Axes might override the
9991003 # patch to not be the Wedge that PolarAxes uses.
@@ -1160,12 +1164,83 @@ def set_rorigin(self, rorigin):
11601164 def get_rorigin (self ):
11611165 return self ._originViewLim .y0
11621166
1163- def set_rlim (self , * args , ** kwargs ):
1167+ def get_rsign (self ):
1168+ return np .sign (self ._originViewLim .y1 - self ._originViewLim .y0 )
1169+
1170+ def set_rlim (self , bottom = None , top = None , emit = True , auto = False , ** kwargs ):
1171+ """
1172+ See `~.polar.PolarAxes.set_ylim`.
1173+ """
11641174 if 'rmin' in kwargs :
1165- kwargs ['ymin' ] = kwargs .pop ('rmin' )
1175+ if bottom is None :
1176+ bottom = kwargs .pop ('rmin' )
1177+ else :
1178+ raise ValueError ('Cannot supply both positional "bottom"'
1179+ 'argument and kwarg "rmin"' )
11661180 if 'rmax' in kwargs :
1167- kwargs ['ymax' ] = kwargs .pop ('rmax' )
1168- return self .set_ylim (* args , ** kwargs )
1181+ if top is None :
1182+ top = kwargs .pop ('rmax' )
1183+ else :
1184+ raise ValueError ('Cannot supply both positional "top"'
1185+ 'argument and kwarg "rmax"' )
1186+ return self .set_ylim (bottom = bottom , top = top , emit = emit , auto = auto ,
1187+ ** kwargs )
1188+
1189+ def set_ylim (self , bottom = None , top = None , emit = True , auto = False ,
1190+ * , ymin = None , ymax = None ):
1191+ """
1192+ Set the data limits for the radial axis.
1193+
1194+ Parameters
1195+ ----------
1196+ bottom : scalar, optional
1197+ The bottom limit (default: None, which leaves the bottom
1198+ limit unchanged).
1199+ The bottom and top ylims may be passed as the tuple
1200+ (*bottom*, *top*) as the first positional argument (or as
1201+ the *bottom* keyword argument).
1202+
1203+ top : scalar, optional
1204+ The top limit (default: None, which leaves the top limit
1205+ unchanged).
1206+
1207+ emit : bool, optional
1208+ Whether to notify observers of limit change (default: True).
1209+
1210+ auto : bool or None, optional
1211+ Whether to turn on autoscaling of the y-axis. True turns on,
1212+ False turns off (default action), None leaves unchanged.
1213+
1214+ ymin, ymax : scalar, optional
1215+ These arguments are deprecated and will be removed in a future
1216+ version. They are equivalent to *bottom* and *top* respectively,
1217+ and it is an error to pass both *ymin* and *bottom* or
1218+ *ymax* and *top*.
1219+
1220+ Returns
1221+ -------
1222+ ylimits : tuple
1223+ Returns the new y-axis limits as (*bottom*, *top*).
1224+
1225+ """
1226+
1227+ if ymin is not None :
1228+ if bottom is not None :
1229+ raise ValueError ('Cannot supply both positional "bottom" '
1230+ 'argument and kwarg "ymin"' )
1231+ else :
1232+ bottom = ymin
1233+ if ymax is not None :
1234+ if top is not None :
1235+ raise ValueError ('Cannot supply both positional "top" '
1236+ 'argument and kwarg "ymax"' )
1237+ else :
1238+ top = ymax
1239+ if top is None and len (bottom ) == 2 :
1240+ top = bottom [1 ]
1241+ bottom = bottom [0 ]
1242+
1243+ return super ().set_ylim (bottom = bottom , top = top , emit = emit , auto = auto )
11691244
11701245 def get_rlabel_position (self ):
11711246 """
0 commit comments