Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1dc52df

Browse files
authored
Merge pull request #15258 from anntzer/nonsingular
Don't fallback to view limits when autoscale()ing no data.
2 parents bde67e9 + 63454db commit 1dc52df

File tree

4 files changed

+46
-15
lines changed

4 files changed

+46
-15
lines changed

lib/matplotlib/axes/_base.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2483,17 +2483,9 @@ def handle_single_axis(scale, autoscaleon, shared_axes, interval,
24832483
dl.extend(y_finite)
24842484

24852485
bb = mtransforms.BboxBase.union(dl)
2486-
# fall back on the viewlimits if this is not finite:
2487-
vl = None
2488-
if not np.isfinite(bb.intervalx).all():
2489-
vl = mtransforms.BboxBase.union([ax.viewLim for ax in shared])
2490-
bb.intervalx = vl.intervalx
2491-
if not np.isfinite(bb.intervaly).all():
2492-
if vl is None:
2493-
vl = mtransforms.BboxBase.union(
2494-
[ax.viewLim for ax in shared])
2495-
bb.intervaly = vl.intervaly
24962486
x0, x1 = getattr(bb, interval)
2487+
# If x0 and x1 are non finite, use the locator to figure out
2488+
# default limits.
24972489
locator = axis.get_major_locator()
24982490
x0, x1 = locator.nonsingular(x0, x1)
24992491

@@ -3325,20 +3317,26 @@ def set_xscale(self, value, **kwargs):
33253317
- `matplotlib.scale.SymmetricalLogScale`
33263318
- `matplotlib.scale.LogitScale`
33273319
3328-
33293320
Notes
33303321
-----
33313322
By default, Matplotlib supports the above mentioned scales.
33323323
Additionally, custom scales may be registered using
33333324
`matplotlib.scale.register_scale`. These scales can then also
33343325
be used here.
33353326
"""
3327+
old_default_lims = (self.xaxis.get_major_locator()
3328+
.nonsingular(-np.inf, np.inf))
33363329
g = self.get_shared_x_axes()
33373330
for ax in g.get_siblings(self):
33383331
ax.xaxis._set_scale(value, **kwargs)
33393332
ax._update_transScale()
33403333
ax.stale = True
3341-
self._request_autoscale_view(scaley=False)
3334+
new_default_lims = (self.xaxis.get_major_locator()
3335+
.nonsingular(-np.inf, np.inf))
3336+
if old_default_lims != new_default_lims:
3337+
# Force autoscaling now, to take advantage of the scale locator's
3338+
# nonsingular() before it possibly gets swapped out by the user.
3339+
self.autoscale_view(scaley=False)
33423340

33433341
@cbook._make_keyword_only("3.2", "minor")
33443342
def get_xticks(self, minor=False):
@@ -3701,20 +3699,26 @@ def set_yscale(self, value, **kwargs):
37013699
- `matplotlib.scale.SymmetricalLogScale`
37023700
- `matplotlib.scale.LogitScale`
37033701
3704-
37053702
Notes
37063703
-----
37073704
By default, Matplotlib supports the above mentioned scales.
37083705
Additionally, custom scales may be registered using
37093706
`matplotlib.scale.register_scale`. These scales can then also
37103707
be used here.
37113708
"""
3709+
old_default_lims = (self.yaxis.get_major_locator()
3710+
.nonsingular(-np.inf, np.inf))
37123711
g = self.get_shared_y_axes()
37133712
for ax in g.get_siblings(self):
37143713
ax.yaxis._set_scale(value, **kwargs)
37153714
ax._update_transScale()
37163715
ax.stale = True
3717-
self._request_autoscale_view(scalex=False)
3716+
new_default_lims = (self.yaxis.get_major_locator()
3717+
.nonsingular(-np.inf, np.inf))
3718+
if old_default_lims != new_default_lims:
3719+
# Force autoscaling now, to take advantage of the scale locator's
3720+
# nonsingular() before it possibly gets swapped out by the user.
3721+
self.autoscale_view(scalex=False)
37183722

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

lib/matplotlib/dates.py

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

lib/matplotlib/tests/test_axes.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2169,6 +2169,13 @@ def test_log_scales():
21692169
ax.set_xscale('log', basex=9.0)
21702170

21712171

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

lib/matplotlib/ticker.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1692,7 +1692,19 @@ def raise_if_exceeds(self, locs):
16921692
return locs
16931693

16941694
def nonsingular(self, v0, v1):
1695-
"""Expand a range as needed to avoid singularities."""
1695+
"""
1696+
Adjust a range as needed to avoid singularities.
1697+
1698+
This method gets called during autoscaling, with ``(v0, v1)`` set to
1699+
the data limits on the axes if the axes contains any data, or
1700+
``(-inf, +inf)`` if not.
1701+
1702+
- If ``v0 == v1`` (possibly up to some floating point slop), this
1703+
method returns an expanded interval around this value.
1704+
- If ``(v0, v1) == (-inf, +inf)``, this method returns appropriate
1705+
default view limits.
1706+
- Otherwise, ``(v0, v1)`` is returned without modification.
1707+
"""
16961708
return mtransforms.nonsingular(v0, v1, expander=.05)
16971709

16981710
def view_limits(self, vmin, vmax):

0 commit comments

Comments
 (0)