Skip to content

Commit

Permalink
Fix floating point issues in axes limits.
Browse files Browse the repository at this point in the history
plt.plot([-.1, .2]) used to pick (in round numbers mode) [-.1, .25] as
ylims due to floating point inaccuracies; change it to pick [-.1, .2]
(up to floating point inaccuracies).

Note that this requires working around a bug in numpy's implementation
of divmod (numpy/numpy#6127).

Many test images have changed!

See matplotlib#5767.

Probably also wraps up work on matplotlib#5738, but tests are missing.
  • Loading branch information
anntzer committed Dec 31, 2015
1 parent 892fc5f commit 9302442
Show file tree
Hide file tree
Showing 23 changed files with 3,479 additions and 3,566 deletions.
Binary file not shown.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
436 changes: 194 additions & 242 deletions lib/matplotlib/tests/baseline_images/test_axes/autoscale_tiny_range.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
1,012 changes: 506 additions & 506 deletions lib/matplotlib/tests/baseline_images/test_axes/errorbar_mixed.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
234 changes: 107 additions & 127 deletions lib/matplotlib/tests/baseline_images/test_axes/formatter_large_small.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 2 additions & 3 deletions lib/matplotlib/tests/test_axes.py
Expand Up @@ -21,7 +21,7 @@
from matplotlib.testing.decorators import image_comparison, cleanup
import matplotlib.pyplot as plt
import matplotlib.markers as mmarkers
from numpy.testing import assert_array_equal
from numpy.testing import assert_allclose, assert_array_equal
import warnings
from matplotlib.cbook import IgnoredKeywordWarning

Expand Down Expand Up @@ -3708,8 +3708,7 @@ def test_vline_limit():
ax.axvline(0.5)
ax.plot([-0.1, 0, 0.2, 0.1])
(ymin, ymax) = ax.get_ylim()
assert ymin == -0.1
assert ymax == 0.25
assert_allclose(ax.get_ylim(), (-.1, .2))


@cleanup
Expand Down
38 changes: 27 additions & 11 deletions lib/matplotlib/ticker.py
Expand Up @@ -169,6 +169,15 @@
long = int


# Work around numpy/numpy#6127.
def divmod(x, y):
if isinstance(x, np.generic):
x = x.item()
if isinstance(y, np.generic):
y = y.item()
return six.moves.builtins.divmod(x, y)


def _mathdefault(s):
"""
For backward compatibility, in classic mode we display
Expand Down Expand Up @@ -1324,7 +1333,7 @@ def view_limits(self, dmin, dmax):


def scale_range(vmin, vmax, n=1, threshold=100):
dv = abs(vmax - vmin) # > 0 as nonsingular is called before.
dv = abs(vmax - vmin) # > 0 as nonsingular is called before.
meanv = (vmax + vmin) / 2
offset = (math.copysign(10 ** (math.log10(abs(meanv)) // 1), meanv)
if abs(meanv) / dv >= threshold
Expand Down Expand Up @@ -1415,7 +1424,7 @@ def set_params(self, **kwargs):
if self._integer:
self._steps = [n for n in self._steps if divmod(n, 1)[1] < 0.001]

def bin_boundaries(self, vmin, vmax):
def _raw_ticks(self, vmin, vmax):
nbins = self._nbins
if nbins == 'auto':
nbins = self.axis.get_tick_space()
Expand All @@ -1438,18 +1447,19 @@ def bin_boundaries(self, vmin, vmax):
if best_vmax >= vmax:
break

bounds = np.arange(nbins + 1) * step + best_vmin
bounds = bounds[(bounds >= vmin) & (bounds <= vmax)]
return bounds + offset
bounds = np.arange(nbins + 1) * step
return (bounds[(bounds >= Base(step).le(vmin - best_vmin)) &
(bounds <= Base(step).ge(vmax - best_vmin))] +
best_vmin + offset)

def __call__(self):
vmin, vmax = self.axis.get_view_interval()
return self.tick_values(vmin, vmax)

def tick_values(self, vmin, vmax):
vmin, vmax = mtransforms.nonsingular(vmin, vmax, expander=1e-13,
tiny=1e-14)
locs = self.bin_boundaries(vmin, vmax)
vmin, vmax = mtransforms.nonsingular(
vmin, vmax, expander=1e-13, tiny=1e-14)
locs = self._raw_ticks(vmin, vmax)
prune = self._prune
if prune == 'lower':
locs = locs[1:]
Expand All @@ -1466,11 +1476,17 @@ def view_limits(self, dmin, dmax):
dmin = -maxabs
dmax = maxabs

dmin, dmax = mtransforms.nonsingular(dmin, dmax, expander=1e-12,
tiny=1.e-13)
dmin, dmax = mtransforms.nonsingular(
dmin, dmax, expander=1e-12, tiny=1e-13)

if rcParams['axes.autolimit_mode'] == 'round_numbers':
return np.take(self.bin_boundaries(dmin, dmax), [0, -1])
locs = self._raw_ticks(dmin, dmax)
step = locs[1] - locs[0]
low = (locs[0] if locs[0] < dmin or closeto(locs[0], dmin)
else locs[0] - step)
high = (locs[-1] if locs[-1] > dmax or closeto(locs[-1], dmax)
else locs[-1] + step)
return low, high
else:
return dmin, dmax

Expand Down
Binary file modified lib/mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d.pdf
Binary file not shown.
Binary file modified lib/mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 9302442

Please sign in to comment.