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

Skip to content

Don't fallback to view limits when autoscale()ing no data. #15258

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

Merged
merged 3 commits into from
Oct 2, 2019
Merged
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
32 changes: 18 additions & 14 deletions lib/matplotlib/axes/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2409,17 +2409,9 @@ def handle_single_axis(scale, autoscaleon, shared_axes, interval,
dl.extend(y_finite)

bb = mtransforms.BboxBase.union(dl)
# fall back on the viewlimits if this is not finite:
vl = None
if not np.isfinite(bb.intervalx).all():
vl = mtransforms.BboxBase.union([ax.viewLim for ax in shared])
bb.intervalx = vl.intervalx
if not np.isfinite(bb.intervaly).all():
if vl is None:
vl = mtransforms.BboxBase.union(
[ax.viewLim for ax in shared])
bb.intervaly = vl.intervaly
x0, x1 = getattr(bb, interval)
# If x0 and x1 are non finite, use the locator to figure out
# default limits.
locator = axis.get_major_locator()
x0, x1 = locator.nonsingular(x0, x1)

Expand Down Expand Up @@ -3260,20 +3252,26 @@ def set_xscale(self, value, **kwargs):
- `matplotlib.scale.SymmetricalLogScale`
- `matplotlib.scale.LogitScale`


Notes
-----
By default, Matplotlib supports the above mentioned scales.
Additionally, custom scales may be registered using
`matplotlib.scale.register_scale`. These scales can then also
be used here.
"""
old_default_lims = (self.xaxis.get_major_locator()
.nonsingular(-np.inf, np.inf))
g = self.get_shared_x_axes()
for ax in g.get_siblings(self):
ax.xaxis._set_scale(value, **kwargs)
ax._update_transScale()
ax.stale = True
self._request_autoscale_view(scaley=False)
new_default_lims = (self.xaxis.get_major_locator()
.nonsingular(-np.inf, np.inf))
if old_default_lims != new_default_lims:
# Force autoscaling now, to take advantage of the scale locator's
# nonsingular() before it possibly gets swapped out by the user.
self.autoscale_view(scaley=False)

@cbook._make_keyword_only("3.2", "minor")
def get_xticks(self, minor=False):
Expand Down Expand Up @@ -3645,20 +3643,26 @@ def set_yscale(self, value, **kwargs):
- `matplotlib.scale.SymmetricalLogScale`
- `matplotlib.scale.LogitScale`


Notes
-----
By default, Matplotlib supports the above mentioned scales.
Additionally, custom scales may be registered using
`matplotlib.scale.register_scale`. These scales can then also
be used here.
"""
old_default_lims = (self.yaxis.get_major_locator()
.nonsingular(-np.inf, np.inf))
g = self.get_shared_y_axes()
for ax in g.get_siblings(self):
ax.yaxis._set_scale(value, **kwargs)
ax._update_transScale()
ax.stale = True
self._request_autoscale_view(scalex=False)
new_default_lims = (self.yaxis.get_major_locator()
.nonsingular(-np.inf, np.inf))
if old_default_lims != new_default_lims:
# Force autoscaling now, to take advantage of the scale locator's
# nonsingular() before it possibly gets swapped out by the user.
self.autoscale_view(scalex=False)

@cbook._make_keyword_only("3.2", "minor")
def get_yticks(self, minor=False):
Expand Down
8 changes: 8 additions & 0 deletions lib/matplotlib/dates.py
Original file line number Diff line number Diff line change
Expand Up @@ -1118,6 +1118,10 @@ def nonsingular(self, vmin, vmax):
Given the proposed upper and lower extent, adjust the range
if it is too close to being singular (i.e. a range of ~0).
"""
if not np.isfinite(vmin) or not np.isfinite(vmax):
# Except if there is no data, then use 2000-2010 as default.
return (date2num(datetime.date(2000, 1, 1)),
date2num(datetime.date(2010, 1, 1)))
if vmax < vmin:
vmin, vmax = vmax, vmin
unit = self._get_unit()
Expand Down Expand Up @@ -1337,6 +1341,10 @@ def tick_values(self, vmin, vmax):
def nonsingular(self, vmin, vmax):
# whatever is thrown at us, we can scale the unit.
# But default nonsingular date plots at an ~4 year period.
if not np.isfinite(vmin) or not np.isfinite(vmax):
# Except if there is no data, then use 2000-2010 as default.
return (date2num(datetime.date(2000, 1, 1)),
date2num(datetime.date(2010, 1, 1)))
if vmax < vmin:
vmin, vmax = vmax, vmin
if vmin == vmax:
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 @@ -2170,6 +2170,13 @@ def test_log_scales():
ax.set_xscale('log', basex=9.0)


def test_log_scales_no_data():
_, ax = plt.subplots()
ax.set(xscale="log", yscale="log")
ax.xaxis.set_major_locator(mticker.MultipleLocator(1))
assert ax.get_xlim() == ax.get_ylim() == (1, 10)


def test_log_scales_invalid():
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
Expand Down
14 changes: 13 additions & 1 deletion lib/matplotlib/ticker.py
Original file line number Diff line number Diff line change
Expand Up @@ -1710,7 +1710,19 @@ def raise_if_exceeds(self, locs):
return locs

def nonsingular(self, v0, v1):
"""Expand a range as needed to avoid singularities."""
"""
Adjust a range as needed to avoid singularities.

This method gets called during autoscaling, with ``(v0, v1)`` set to
the data limits on the axes if the axes contains any data, or
``(-inf, +inf)`` if not.

- If ``v0 == v1`` (possibly up to some floating point slop), this
method returns an expanded interval around this value.
- If ``(v0, v1) == (-inf, +inf)``, this method returns appropriate
default view limits.
- Otherwise, ``(v0, v1)`` is returned without modification.
"""
return mtransforms.nonsingular(v0, v1, expander=.05)

def view_limits(self, vmin, vmax):
Expand Down