Skip to content

Changed axis selection when zooming datalim-adjustable fixed-aspect axes #14899

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 28 additions & 41 deletions lib/matplotlib/axes/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1898,55 +1898,42 @@ def apply_aspect(self, position=None):
box_aspect = fig_aspect * (position.height / position.width)
data_ratio = box_aspect / aspect

y_expander = data_ratio * xsize / ysize - 1
# If y_expander > 0, the dy/dx viewLim ratio needs to increase
if abs(y_expander) < 0.005:
y_expander = data_ratio * xsize / ysize
# If y_expander > 1, the dy/dx viewLim ratio needs to increase
if abs(y_expander - 1) < 0.005:
return

dL = self.dataLim
x0, x1 = x_trf.transform(dL.intervalx)
y0, y1 = y_trf.transform(dL.intervaly)
xr = 1.05 * (x1 - x0)
yr = 1.05 * (y1 - y0)

xmarg = xsize - xr
ymarg = ysize - yr
Ysize = data_ratio * xsize
Xsize = ysize / data_ratio
Xmarg = Xsize - xr
Ymarg = Ysize - yr
# Setting these targets to, e.g., 0.05*xr does not seem to help.
xm = 0
ym = 0

# What axes do we adjust?
# - We can't adjust shared axes because it's too easy to break sharing
# given the sequential handling of axes (that may be possible if we
# first collected all the constraints on all axes and considered them
# all at once).
# - Assuming no constraints from sharing, prefer expanding axes rather
# than shrinking them, as the latter can hide plot elements.
shared_x = self in self._shared_x_axes
shared_y = self in self._shared_y_axes
# Not sure whether we need this check:
if shared_x and shared_y:
raise RuntimeError("adjustable='datalim' is not allowed when both "
"axes are shared")

# If y is shared, then we are only allowed to change x, etc.
if shared_y:
adjust_y = False
else:
if xmarg > xm and ymarg > ym:
adjy = ((Ymarg > 0 and y_expander < 0) or
(Xmarg < 0 and y_expander > 0))
else:
adjy = y_expander > 0
adjust_y = shared_x or adjy # (Ymarg > xmarg)

if adjust_y:
yc = 0.5 * (ymin + ymax)
y0 = yc - Ysize / 2.0
y1 = yc + Ysize / 2.0
self.set_ybound(y_trf.inverted().transform([y0, y1]))
if shared_x:
adjust = "y"
elif shared_y:
adjust = "x"
elif y_expander > 1:
adjust = "y"
else: # y_expander < 1
adjust = "x"

if adjust == "y":
yc = (ymin + ymax) / 2
ymin = yc - (yc - ymin) * y_expander
ymax = yc + (ymax - yc) * y_expander
self.set_ybound(*map(y_trf.inverted().transform, (ymin, ymax)))
else:
xc = 0.5 * (xmin + xmax)
x0 = xc - Xsize / 2.0
x1 = xc + Xsize / 2.0
self.set_xbound(x_trf.inverted().transform([x0, x1]))
xc = (xmin + xmax) / 2
xmin = xc - (xc - xmin) / y_expander
xmax = xc + (xmax - xc) / y_expander
self.set_xbound(*map(x_trf.inverted().transform, (xmin, xmax)))

def axis(self, *args, emit=True, **kwargs):
"""
Expand Down
7 changes: 7 additions & 0 deletions lib/matplotlib/tests/test_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5039,6 +5039,13 @@ def test_pie_frame_grid():
frame=True, center=(3, 5))
# Set aspect ratio to be equal so that pie is drawn as a circle.
plt.axis('equal')
plt.gcf().canvas.draw()
xmin, xmax = plt.xlim()
ymin, ymax = plt.ylim()
assert xmin < 0 and xmax > 7 and ymin == 0 and ymax == 7
# These limits reproduce an old, buggy implementation of axis("equal").
plt.xlim(0, 7)
plt.ylim(0.7903225806451615, 6.209677419354838)


@image_comparison(['pie_rotatelabels_true.png'])
Expand Down