diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 865b621d16d1..c6afe628cf19 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -1251,7 +1251,6 @@ def __init__(self, *args, **kwargs): **{k: ba.arguments.pop(k) for k in ["vmin", "vmax", "clip"]}) self._scale = scale_cls(axis=None, **ba.arguments) self._trf = self._scale.get_transform() - self._inv_trf = self._trf.inverted() def __call__(self, value, clip=None): value, is_scalar = self.process_value(value) @@ -1283,7 +1282,10 @@ def inverse(self, value): raise ValueError("Invalid vmin or vmax") rescaled = value * (t_vmax - t_vmin) rescaled += t_vmin - return self._inv_trf.transform(rescaled).reshape(np.shape(value)) + return (self._trf + .inverted() + .transform(rescaled) + .reshape(np.shape(value))) Norm.__name__ = base_norm_cls.__name__ Norm.__qualname__ = base_norm_cls.__qualname__ diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index 2ef2226dc0bf..17b4da2d16f0 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -534,9 +534,13 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0, resampled_masked = np.ma.masked_array(A_resampled, out_mask) # we have re-set the vmin/vmax to account for small errors # that may have moved input values in/out of range + s_vmin, s_vmax = vrange + if isinstance(self.norm, mcolors.LogNorm): + if s_vmin < 0: + s_vmin = max(s_vmin, np.finfo(scaled_dtype).eps) with cbook._setattr_cm(self.norm, - vmin=vrange[0], - vmax=vrange[1], + vmin=s_vmin, + vmax=s_vmax, ): output = self.norm(resampled_masked) else: diff --git a/lib/matplotlib/tests/test_image.py b/lib/matplotlib/tests/test_image.py index 1b9dd306a4dc..80803d576464 100644 --- a/lib/matplotlib/tests/test_image.py +++ b/lib/matplotlib/tests/test_image.py @@ -1204,3 +1204,22 @@ def test_imshow_quantitynd(): ax.imshow(arr) # executing the draw should not raise an exception fig.canvas.draw() + + +@check_figures_equal(extensions=['png']) +def test_huge_range_log(fig_test, fig_ref): + data = np.full((5, 5), -1, dtype=np.float64) + data[0:2, :] = 1E20 + + ax = fig_test.subplots() + im = ax.imshow(data, norm=colors.LogNorm(vmin=100, vmax=data.max()), + interpolation='nearest', cmap='viridis') + + data = np.full((5, 5), -1, dtype=np.float64) + data[0:2, :] = 1000 + + cm = copy(plt.get_cmap('viridis')) + cm.set_under('w') + ax = fig_ref.subplots() + im = ax.imshow(data, norm=colors.Normalize(vmin=100, vmax=data.max()), + interpolation='nearest', cmap=cm)