2
2
import types
3
3
4
4
import numpy as np
5
+ import warnings
5
6
6
7
from matplotlib .axes import Axes
7
8
import matplotlib .axis as maxis
@@ -57,7 +58,8 @@ def transform_non_affine(self, tr):
57
58
t += self ._axis .get_theta_offset ()
58
59
59
60
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
+
61
63
mask = r < 0
62
64
x [:] = np .where (mask , np .nan , r * np .cos (t ))
63
65
y [:] = np .where (mask , np .nan , r * np .sin (t ))
@@ -161,6 +163,7 @@ def transform_non_affine(self, xy):
161
163
162
164
if self ._use_rmin and self ._axis is not None :
163
165
r += self ._axis .get_rorigin ()
166
+ r *= self ._axis .get_rsign ()
164
167
165
168
return np .concatenate ((theta , r ), 1 )
166
169
transform_non_affine .__doc__ = \
@@ -421,10 +424,9 @@ def __call__(self):
421
424
# Ensure previous behaviour with full circle non-annular views.
422
425
if self ._axes :
423
426
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 ()
425
428
if self ._axes .get_rmin () <= rorigin :
426
429
show_all = False
427
-
428
430
if show_all :
429
431
return self .base ()
430
432
else :
@@ -444,7 +446,10 @@ def refresh(self):
444
446
445
447
def view_limits (self , vmin , vmax ):
446
448
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 )
448
453
449
454
450
455
class _ThetaShift (mtransforms .ScaledTranslation ):
@@ -767,7 +772,6 @@ def __str__(self):
767
772
def get_points (self ):
768
773
if self ._invalid :
769
774
points = self ._viewLim .get_points ().copy ()
770
-
771
775
# Scale angular limits to work with Wedge.
772
776
points [:, 0 ] *= 180 / np .pi
773
777
if points [0 , 0 ] > points [1 , 0 ]:
@@ -992,8 +996,8 @@ def draw(self, *args, **kwargs):
992
996
thetamin , thetamax = np .rad2deg (self ._realViewLim .intervalx )
993
997
if thetamin > thetamax :
994
998
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 ())
997
1001
if isinstance (self .patch , mpatches .Wedge ):
998
1002
# Backwards-compatibility: Any subclassed Axes might override the
999
1003
# patch to not be the Wedge that PolarAxes uses.
@@ -1160,12 +1164,83 @@ def set_rorigin(self, rorigin):
1160
1164
def get_rorigin (self ):
1161
1165
return self ._originViewLim .y0
1162
1166
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
+ """
1164
1174
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"' )
1166
1180
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 )
1169
1244
1170
1245
def get_rlabel_position (self ):
1171
1246
"""
0 commit comments