Skip to content

Commit b5fd761

Browse files
committed
Make set_x/ymargin() update axes limits, just like margins().
Previously, setting the margins via set_x/ymargin() would not update axes limits, unlike calling margins(). This appears to be a simple oversight. The change in collections.py is necessary because the difference in timing at which autoscale is executed now exposed a floating point inaccuracy (which gets amplified by the old round_numbers autolimits mode).
1 parent 58c6698 commit b5fd761

File tree

3 files changed

+22
-15
lines changed

3 files changed

+22
-15
lines changed

lib/matplotlib/axes/_base.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -2239,6 +2239,7 @@ def set_xmargin(self, m):
22392239
if m <= -0.5:
22402240
raise ValueError("margin must be greater than -0.5")
22412241
self._xmargin = m
2242+
self._request_autoscale_view(scalex=True, scaley=False)
22422243
self.stale = True
22432244

22442245
def set_ymargin(self, m):
@@ -2261,6 +2262,7 @@ def set_ymargin(self, m):
22612262
if m <= -0.5:
22622263
raise ValueError("margin must be greater than -0.5")
22632264
self._ymargin = m
2265+
self._request_autoscale_view(scalex=False, scaley=True)
22642266
self.stale = True
22652267

22662268
def margins(self, *margins, x=None, y=None, tight=True):
@@ -2331,15 +2333,13 @@ def margins(self, *margins, x=None, y=None, tight=True):
23312333
cbook._warn_external(f'ignoring tight={tight!r} in get mode')
23322334
return self._xmargin, self._ymargin
23332335

2336+
if tight is not None:
2337+
self._tight = tight
23342338
if x is not None:
23352339
self.set_xmargin(x)
23362340
if y is not None:
23372341
self.set_ymargin(y)
23382342

2339-
self._request_autoscale_view(
2340-
tight=tight, scalex=(x is not None), scaley=(y is not None)
2341-
)
2342-
23432343
def set_rasterization_zorder(self, z):
23442344
"""
23452345
Parameters

lib/matplotlib/collections.py

+10-11
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,6 @@ def get_datalim(self, transData):
213213
# we may have transform.contains_branch(transData) but not
214214
# transforms.get_affine().contains_branch(transData). But later,
215215
# be careful to only apply the affine part that remains.
216-
if not transOffset.is_affine:
217-
offsets = transOffset.transform_non_affine(offsets)
218216

219217
if isinstance(offsets, np.ma.MaskedArray):
220218
offsets = offsets.filled(np.nan)
@@ -228,17 +226,18 @@ def get_datalim(self, transData):
228226
# also use this algorithm (like streamplot).
229227
result = mpath.get_path_collection_extents(
230228
transform.get_affine(), paths, self.get_transforms(),
231-
offsets, transOffset.get_affine().frozen())
229+
transOffset.transform_non_affine(offsets),
230+
transOffset.get_affine().frozen())
232231
return result.inverse_transformed(transData)
233232
if not self._offsetsNone:
234-
# this is for collections that have their paths (shapes)
235-
# in physical, axes-relative, or figure-relative units
236-
# (i.e. like scatter). We can't uniquely set limits based on
237-
# those shapes, so we just set the limits based on their
238-
# location.
239-
# Finish the transform:
240-
offsets = (transOffset.get_affine() +
241-
transData.inverted()).transform(offsets)
233+
# This is for collections that have their paths (shapes) in
234+
# physical, axes-relative, or figure-relative units (i.e.
235+
# like scatter). We can't uniquely set limits based on those
236+
# shapes, so we just set the limits based on their location.
237+
# It is important to use "transOffset - transData" here so that
238+
# if transOffset == transData, then they exactly cancel out,
239+
# rather than possibly accumulating floating point error.
240+
offsets = (transOffset - transData).transform(offsets)
242241
offsets = np.ma.masked_invalid(offsets)
243242
if not offsets.mask.all():
244243
points = np.row_stack((offsets.min(axis=0),

lib/matplotlib/tests/test_axes.py

+8
Original file line numberDiff line numberDiff line change
@@ -5346,6 +5346,14 @@ def test_margins():
53465346
ymax + (ymax - ymin) * 0.5)
53475347

53485348

5349+
def test_set_margin_updates_limits():
5350+
mpl.style.use("default")
5351+
fig, ax = plt.subplots()
5352+
ax.plot([1, 2], [1, 2])
5353+
ax.set(xscale="log", xmargin=0)
5354+
assert ax.get_xlim() == (1, 2)
5355+
5356+
53495357
def test_length_one_hist():
53505358
fig, ax = plt.subplots()
53515359
ax.hist(1)

0 commit comments

Comments
 (0)