8000 FIX: allow flipped ylimits · matplotlib/matplotlib@0adc483 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0adc483

Browse files
committed
FIX: allow flipped ylimits
1 parent d5a4eda commit 0adc483

File tree

3 files changed

+120
-25
lines changed

3 files changed

+120
-25
lines changed

lib/matplotlib/axes/_base.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3083,8 +3083,8 @@ def set_xlim(self, left=None, right=None, emit=True, auto=False,
30833083
The left xlim (default: None, which leaves the left limit
30843084
unchanged).
30853085
The left and right xlims may be passed as the tuple
3086-
(`left`, `right`) as the first positional argument (or as
3087-
the `left` keyword argument).
3086+
(*left*, *right*) as the first positional argument (or as
3087+
the *left* keyword argument).
30883088
30893089
right : scalar, optional
30903090
The right xlim (default: None, which leaves the right limit
@@ -3100,17 +3100,17 @@ def set_xlim(self, left=None, right=None, emit=True, auto=False,
31003100
xmin, xmax : scalar, optional
31013101
These arguments are deprecated and will be removed in a future
31023102
version. They are equivalent to left and right respectively,
3103-
and it is an error to pass both `xmin` and `left` or
3104-
`xmax` and `right`.
3103+
and it is an error to pass both *xmin* and *left* or
3104+
*xmax* and *right*.
31053105
31063106
Returns
31073107
-------
31083108
xlimits : tuple
3109-
Returns the new x-axis limits as (`left`, `right`).
3109+
Returns the new x-axis limits as (*left*, *right*).
31103110
31113111
Notes
31123112
-----
3113-
The `left` value may be greater than the `right` value, in which
3113+
The *left* value may be greater than the *right* value, in which
31143114
case the x-axis values will decrease from left to right.
31153115
31163116
Examples
@@ -3124,7 +3124,7 @@ def set_xlim(self, left=None, right=None, emit=True, auto=False,
31243124
>>> set_xlim(right=right_lim)
31253125
31263126
Limits may be passed in reverse order to flip the direction of
3127-
the x-axis. For example, suppose `x` represents the number of
3127+
the x-axis. For example, suppose *x* represents the number of
31283128
years before present. The x-axis limits might be set like the
31293129
following so 5000 years ago is on the left of the plot and the
31303130
present is on the right.
@@ -3417,15 +3417,15 @@ def set_ylim(self, bottom=None, top=None, emit=True, auto=False,
34173417
The bottom ylim (default: None, which leaves the bottom
34183418
limit unchanged).
34193419
The bottom and top ylims may be passed as the tuple
3420-
(`bottom`, `top`) as the first positional argument (or as
3421-
the `bottom` keyword argument).
3420+
(*bottom*, *top*) as the first positional argument (or as
3421+
the *bottom* keyword argument).
34223422
34233423
top : scalar, optional
34243424
The top ylim (default: None, which leaves the top limit
34253425
unchanged).
34263426
34273427
emit : bool, optional
3428-
Whether to notify observers of limit change (default: True).
3428+
Whether to notify observers of limit change (default: ``True``).
34293429
34303430
auto : bool or None, optional
34313431
Whether to turn on autoscaling of the y-axis. True turns on,
@@ -3434,17 +3434,17 @@ def set_ylim(self, bottom=None, top=None, emit=True, auto=False,
34343434
ymin, ymax : scalar, optional
34353435
These arguments are deprecated and will be removed in a future
34363436
version. They are equivalent to bottom and top respectively,
3437-
and it is an error to pass both `xmin` and `bottom` or
3438-
`xmax` and `top`.
3437+
and it is an error to pass both *ymin* and *bottom* or
3438+
*ymax* and *top*.
34393439
34403440
Returns
34413441
-------
34423442
ylimits : tuple
3443-
Returns the new y-axis limits as (`bottom`, `top`).
3443+
Returns the new y-axis limits as (*bottom*, *top*).
34443444
34453445
Notes
34463446
-----
3447-
The `bottom` value may be greater than the `top` value, in which
3447+
The *bottom* value may be greater than the *top* value, in which
34483448
case the y-axis values will decrease from bottom to top.
34493449
34503450
Examples

lib/matplotlib/projections/polar.py

Lines changed: 87 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import types
33

44
import numpy as np
5+
import warnings
56

67
from matplotlib.axes import Axes
78
import 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))
@@ -168,6 +170,7 @@ def transform_non_affine(self, xy):
168170

169171
if self._use_rmin and self._axis is not None:
170172
r += self._axis.get_rorigin()
173+
r *= self._axis.get_rsign()
171174

172175
return np.concatenate((theta, r), 1)
173176
transform_non_affine.__doc__ = \
@@ -431,10 +434,9 @@ def __call__(self):
431434
# Ensure previous behaviour with full circle non-annular views.
432435
if self._axes:
433436
if _is_full_circle_rad(*self._axes.viewLim.intervalx):
434-
rorigin = self._axes.get_rorigin()
437+
rorigin = self._axes.get_rorigin() * self._axes.get_rsign()
435438
if self._axes.get_rmin() <= rorigin:
436439
show_all = False
437-
438440
if show_all:
439441
return self.base()
440442
else:
@@ -454,7 +456,7 @@ def refresh(self):
454456

455457
def view_limits(self, vmin, vmax):
456458
vmin, vmax = self.base.view_limits(vmin, vmax)
457-
return mtransforms.nonsingular(min(0, vmin), vmax)
459+
return mtransforms.nonsingular(vmin, vmax)
458460

459461

460462
class _ThetaShift(mtransforms.ScaledTranslation):
@@ -789,7 +791,6 @@ def __str__(self):
789791
def get_points(self):
790792
if self._invalid:
791793
points = self._viewLim.get_points().copy()
792-
793794
# Scale angular limits to work with Wedge.
794795
points[:, 0] *= 180 / np.pi
795796
if points[0, 0] > points[1, 0]:
@@ -1014,8 +1015,8 @@ def draw(self, *args, **kwargs):
10141015
thetamin, thetamax = np.rad2deg(self._realViewLim.intervalx)
10151016
if thetamin > thetamax:
10161017
thetamin, thetamax = thetamax, thetamin
1017-
rmin, rmax = self._realViewLim.intervaly - self.get_rorigin()
1018-
1018+
rmin, rmax = ((self._realViewLim.intervaly - self.get_rorigin()) *
1019+
self.get_rsign())
10191020
if isinstance(self.patch, mpatches.Wedge):
10201021
# Backwards-compatibility: Any subclassed Axes might override the
10211022
# patch to not be the Wedge that PolarAxes uses.
@@ -1182,12 +1183,87 @@ def set_rorigin(self, rorigin):
11821183
def get_rorigin(self):
11831184
return self._originViewLim.y0
11841185

1185-
def set_rlim(self, *args, **kwargs):
1186+
def get_rsign(self):
1187+
return np.sign(self._originViewLim.y1 - self._originViewLim.y0)
1188+
1189+
def set_rlim(self, bottom=None, top=None, emit=True, auto=False, **kwargs):
1190+
"""
1191+
See `~.polar.PolarAxes.set_ylim`.
1192+
"""
11861193
if 'rmin' in kwargs:
1187-
kwargs['ymin'] = kwargs.pop('rmin')
1194+
if bottom is None:
1195+
bottom = kwargs.pop('rmin')
1196+
else:
1197+
raise ValueError('Cannot supply both positional "bottom"'
1198+
'argument and kwarg "rmin"')
11881199
if 'rmax' in kwargs:
1189-
kwargs['ymax'] = kwargs.pop('rmax')
1190-
return self.set_ylim(*args, **kwargs)
1200+
if top is None:
1201+
top = kwargs.pop('rmax')
1202+
else:
1203+
raise ValueError('Cannot supply both positional "top"'
1204+
'argument and kwarg "rmax"')
1205+
return self.set_ylim(bottom=bottom, top=top, emit=emit, auto=auto,
1206+
**kwargs)
1207+
1208+
def set_ylim(self, bottom=None, top=None, emit=True, auto=False,
1209+
*, ymin=None, ymax=None):
1210+
"""
1211+
Set the data limits for the radial-axis.
1212+
1213+
Parameters
1214+
----------
1215+
bottom : scalar, optional
1216+
The bottom limit (default: None, which leaves the bottom
1217+
limit unchanged).
1218+
The bottom and top ylims may be passed as the tuple
1219+
(*bottom*, *top*) as the first positional argument (or as
1220+
the *bottom* keyword argument).
1221+
1222+
top : scalar, optional
1223+
The top ylim (default: None, which leaves the top limit
1224+
unchanged).
1225+
1226+
emit : bool, optional
1227+
Whether to notify observers of limit change (default: True).
1228+
1229+
auto : bool or None, optional
1230+
Whether to turn on autoscaling of the y-axis. True turns on,
1231+
False turns off (default action), None leaves unchanged.
1232+
1233+
ymin, ymax : scalar, optional
1234+
These arguments are deprecated and will be removed in a future
1235+
version. They are equivalent to bottom and top respectively,
1236+
and it is an error to pass both *ymin* and *bottom* or
1237+
*ymax* and *top*.
1238+
1239+
Returns
1240+
-------
1241+
ylimits : tuple
1242+
Returns the new y-axis limits as (*bottom*, *top*).
1243+
1244+
Notes
1245+
-----
1246+
The *bottom* value must be less than the *top* value, or a
1247+
ValueError is raised.
1248+
"""
1249+
1250+
if ymin is not None:
1251+
if bottom is not None:
1252+
raise ValueError('Cannot supply both positional "bottom" '
1253+
'argument and kwarg "ymin"')
1254+
else:
1255+
bottom = ymin
1256+
if ymax is not None:
1257+
if top is not None:
1258+
raise ValueError('Cannot supply both positional "top" '
1259+
'argument and kwarg "ymax"')
1260+
else:
1261+
top = ymax
1262+
if top is None and len(bottom) == 2:
1263+
top = bottom[1]
1264+
bottom = bottom[0]
1265+
1266+
return super().set_ylim(bottom=bottom, top=top, emit=emit, auto=auto)
11911267

11921268
def get_rlabel_position(self):
11931269
"""

lib/matplotlib/tests/test_axes.py

Lines changed: 19 additions & 0 deletions
< 3189 /tbody>
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,23 @@ def test_polar_rorigin():
735735
ax.set_rorigin(0.0)
736736

737737

738+
@image_comparison(baseline_images=['polar_invertedylim'], style='default',
739+
extensions=['png'])
740+
def test_polar_invertedylim():
741+
fig = plt.figure()
742+
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True)
743+
ax.set_ylim(2, 0)
744+
745+
746+
@image_comparison(baseline_images=['polar_invertedylim_rorigin'],
747+
style='default', extensions=['png'])
748+
def test_polar_invertedylim_rorigin():
749+
fig = plt.figure()
750+
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True)
751+
ax.set_ylim(2, 0)
752+
ax.set_rorigin(3)
753+
754+
738755
@image_comparison(baseline_images=['polar_theta_position'], style='default')
739756
def test_polar_theta_position():
740757
r = np.arange(0, 3.0, 0.01)
@@ -747,6 +764,8 @@ def test_polar_theta_position():
747764
ax.set_theta_direction('clockwise')
748765

749766

767+
768+
750769
@image_comparison(baseline_images=['polar_rlabel_position'], style='default')
751770
def test_polar_rlabel_position():
752771
fig = plt.figure()

0 commit comments

Comments
 (0)
0