Skip to content

Commit aa87937

Browse files
ivanovMeeseeksDev[bot]
authored and
MeeseeksDev[bot]
committed
Backport PR #15258: Don't fallback to view limits when autoscale()ing no data.
1 parent 9461967 commit aa87937

File tree

4 files changed

+46
-15
lines changed

4 files changed

+46
-15
lines changed

lib/matplotlib/axes/_base.py

+18-14
Original file line numberDiff line numberDiff line change
@@ -2409,17 +2409,9 @@ def handle_single_axis(scale, autoscaleon, shared_axes, interval,
24092409
dl.extend(y_finite)
24102410

24112411
bb = mtransforms.BboxBase.union(dl)
2412-
# fall back on the viewlimits if this is not finite:
2413-
vl = None
2414-
if not np.isfinite(bb.intervalx).all():
2415-
vl = mtransforms.BboxBase.union([ax.viewLim for ax in shared])
2416-
bb.intervalx = vl.intervalx
2417-
if not np.isfinite(bb.intervaly).all():
2418-
if vl is None:
2419-
vl = mtransforms.BboxBase.union(
2420-
[ax.viewLim for ax in shared])
2421-
bb.intervaly = vl.intervaly
24222412
x0, x1 = getattr(bb, interval)
2413+
# If x0 and x1 are non finite, use the locator to figure out
2414+
# default limits.
24232415
locator = axis.get_major_locator()
24242416
x0, x1 = locator.nonsingular(x0, x1)
24252417

@@ -3260,20 +3252,26 @@ def set_xscale(self, value, **kwargs):
32603252
- `matplotlib.scale.SymmetricalLogScale`
32613253
- `matplotlib.scale.LogitScale`
32623254
3263-
32643255
Notes
32653256
-----
32663257
By default, Matplotlib supports the above mentioned scales.
32673258
Additionally, custom scales may be registered using
32683259
`matplotlib.scale.register_scale`. These scales can then also
32693260
be used here.
32703261
"""
3262+
old_default_lims = (self.xaxis.get_major_locator()
3263+
.nonsingular(-np.inf, np.inf))
32713264
g = self.get_shared_x_axes()
32723265
for ax in g.get_siblings(self):
32733266
ax.xaxis._set_scale(value, **kwargs)
32743267
ax._update_transScale()
32753268
ax.stale = True
3276-
self._request_autoscale_view(scaley=False)
3269+
new_default_lims = (self.xaxis.get_major_locator()
3270+
.nonsingular(-np.inf, np.inf))
3271+
if old_default_lims != new_default_lims:
3272+
# Force autoscaling now, to take advantage of the scale locator's
3273+
# nonsingular() before it possibly gets swapped out by the user.
3274+
self.autoscale_view(scaley=False)
32773275

32783276
@cbook._make_keyword_only("3.2", "minor")
32793277
def get_xticks(self, minor=False):
@@ -3645,20 +3643,26 @@ def set_yscale(self, value, **kwargs):
36453643
- `matplotlib.scale.SymmetricalLogScale`
36463644
- `matplotlib.scale.LogitScale`
36473645
3648-
36493646
Notes
36503647
-----
36513648
By default, Matplotlib supports the above mentioned scales.
36523649
Additionally, custom scales may be registered using
36533650
`matplotlib.scale.register_scale`. These scales can then also
36543651
be used here.
36553652
"""
3653+
old_default_lims = (self.yaxis.get_major_locator()
3654+
.nonsingular(-np.inf, np.inf))
36563655
g = self.get_shared_y_axes()
36573656
for ax in g.get_siblings(self):
36583657
ax.yaxis._set_scale(value, **kwargs)
36593658
ax._update_transScale()
36603659
ax.stale = True
3661-
self._request_autoscale_view(scalex=False)
3660+
new_default_lims = (self.yaxis.get_major_locator()
3661+
.nonsingular(-np.inf, np.inf))
3662+
if old_default_lims != new_default_lims:
3663+
# Force autoscaling now, to take advantage of the scale locator's
3664+
# nonsingular() before it possibly gets swapped out by the user.
3665+
self.autoscale_view(scalex=False)
36623666

36633667
@cbook._make_keyword_only("3.2", "minor")
36643668
def get_yticks(self, minor=False):

lib/matplotlib/dates.py

+8
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,10 @@ def nonsingular(self, vmin, vmax):
11181118
Given the proposed upper and lower extent, adjust the range
11191119
if it is too close to being singular (i.e. a range of ~0).
11201120
"""
1121+
if not np.isfinite(vmin) or not np.isfinite(vmax):
1122+
# Except if there is no data, then use 2000-2010 as default.
1123+
return (date2num(datetime.date(2000, 1, 1)),
1124+
date2num(datetime.date(2010, 1, 1)))
11211125
if vmax < vmin:
11221126
vmin, vmax = vmax, vmin
11231127
unit = self._get_unit()
@@ -1337,6 +1341,10 @@ def tick_values(self, vmin, vmax):
13371341
def nonsingular(self, vmin, vmax):
13381342
# whatever is thrown at us, we can scale the unit.
13391343
# But default nonsingular date plots at an ~4 year period.
1344+
if not np.isfinite(vmin) or not np.isfinite(vmax):
1345+
# Except if there is no data, then use 2000-2010 as default.
1346+
return (date2num(datetime.date(2000, 1, 1)),
1347+
date2num(datetime.date(2010, 1, 1)))
13401348
if vmax < vmin:
13411349
vmin, vmax = vmax, vmin
13421350
if vmin == vmax:

lib/matplotlib/tests/test_axes.py

+7
Original file line numberDiff line numberDiff line change
@@ -2170,6 +2170,13 @@ def test_log_scales():
21702170
ax.set_xscale('log', basex=9.0)
21712171

21722172

2173+
def test_log_scales_no_data():
2174+
_, ax = plt.subplots()
2175+
ax.set(xscale="log", yscale="log")
2176+
ax.xaxis.set_major_locator(mticker.MultipleLocator(1))
2177+
assert ax.get_xlim() == ax.get_ylim() == (1, 10)
2178+
2179+
21732180
def test_log_scales_invalid():
21742181
fig = plt.figure()
21752182
ax = fig.add_subplot(1, 1, 1)

lib/matplotlib/ticker.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -1710,7 +1710,19 @@ def raise_if_exceeds(self, locs):
17101710
return locs
17111711

17121712
def nonsingular(self, v0, v1):
1713-
"""Expand a range as needed to avoid singularities."""
1713+
"""
1714+
Adjust a range as needed to avoid singularities.
1715+
1716+
This method gets called during autoscaling, with ``(v0, v1)`` set to
1717+
the data limits on the axes if the axes contains any data, or
1718+
``(-inf, +inf)`` if not.
1719+
1720+
- If ``v0 == v1`` (possibly up to some floating point slop), this
1721+
method returns an expanded interval around this value.
1722+
- If ``(v0, v1) == (-inf, +inf)``, this method returns appropriate
1723+
default view limits.
1724+
- Otherwise, ``(v0, v1)`` is returned without modification.
1725+
"""
17141726
return mtransforms.nonsingular(v0, v1, expander=.05)
17151727

17161728
def view_limits(self, vmin, vmax):

0 commit comments

Comments
 (0)