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

Skip to content

Commit b23708a

Browse files
committed
FIX: special-case LogNorm when resealing
closes #18415 We need to special case when rescaling the user input for interpolation with LogNorm. The issue is that due to the inherent precision limits of floating point math we can end up with errors on the order if 1e-18 of the overall data range when rescaling. If the bottom vlim is close to 0 and the top is order 10e20 than this error can result in the rescaled vmin being negative which then fails when we (temporarily) change the vmin/vmax on the norm. We started adjusting the vmin/vmax to work around the same issue with float precision in #17636 / 3dea5c7 to make sure that values exactly equal to the limits did not move across the boundary and get erroneously mapped is over/under. Long term we may want to add the ability for the norms to suggest to their clients what the constraints on the vmin/vmax are, but hard-coding a special case for LogNorm is the pragmatic solution.
1 parent d13b20a commit b23708a

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

lib/matplotlib/image.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -534,9 +534,13 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
534534
resampled_masked = np.ma.masked_array(A_resampled, out_mask)
535535
# we have re-set the vmin/vmax to account for small errors
536536
# that may have moved input values in/out of range
537+
s_vmin, s_vmax = vrange
538+
if isinstance(self.norm, mcolors.LogNorm):
539+
if s_vmin < 0:
540+
s_vmin = max(s_vmin, np.finfo(scaled_dtype).eps)
537541
with cbook._setattr_cm(self.norm,
538-
vmin=vrange[0],
539-
vmax=vrange[1],
542+
vmin=s_vmin,
543+
vmax=s_vmax,
540544
):
541545
output = self.norm(resampled_masked)
542546
else:

lib/matplotlib/tests/test_image.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,3 +1204,22 @@ def test_imshow_quantitynd():
12041204
ax.imshow(arr)
12051205
# executing the draw should not raise an exception
12061206
fig.canvas.draw()
1207+
1208+
1209+
@check_figures_equal(extensions=['png'])
1210+
def test_huge_range_log(fig_test, fig_ref):
1211+
data = np.full((5, 5), -1, dtype=np.float64)
1212+
data[0:2, :] = 1E20
1213+
1214+
ax = fig_test.subplots()
1215+
im = ax.imshow(data, norm=colors.LogNorm(vmin=100, vmax=data.max()),
1216+
interpolation='nearest', cmap='viridis')
1217+
1218+
data = np.full((5, 5), -1, dtype=np.float64)
1219+
data[0:2, :] = 1000
1220+
1221+
cm = copy(plt.get_cmap('viridis'))
1222+
cm.set_under('w')
1223+
ax = fig_ref.subplots()
1224+
im = ax.imshow(data, norm=colors.Normalize(vmin=100, vmax=data.max()),
1225+
interpolation='nearest', cmap=cm)

0 commit comments

Comments
 (0)