diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index a48cb9bedbf6..13c12a5f90c1 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -551,8 +551,8 @@ def add_lines(self, levels, colors, linewidths, erase=True): def _ticker(self): ''' - Return two sequences: ticks (colorbar data locations) - and ticklabels (strings). + Return the sequence of ticks (colorbar data locations), + ticklabels (strings), and the corresponding offset string. ''' locator = self.locator formatter = self.formatter @@ -653,6 +653,9 @@ def _process_values(self, b=None): self._values = v return else: + self.norm.vmin, self.norm.vmax = mtrans.nonsingular(self.norm.vmin, + self.norm.vmax, + expander=0.1) if not self.norm.scaled(): self.norm.vmin = 0 self.norm.vmax = 1 @@ -817,24 +820,21 @@ def _locate(self, x): # as to make the interpolation more accurate. b = self.norm(self._boundaries, clip=False).filled() xn = self.norm(x, clip=False).filled() + # The rest is linear interpolation with extrapolation at ends. - y = self._y - N = len(b) ii = np.searchsorted(b, xn) i0 = ii - 1 - itop = (ii == N) + itop = (ii == len(b)) ibot = (ii == 0) i0[itop] -= 1 ii[itop] -= 1 i0[ibot] += 1 ii[ibot] += 1 - #db = b[ii] - b[i0] db = np.take(b, ii) - np.take(b, i0) - #dy = y[ii] - y[i0] + y = self._y dy = np.take(y, ii) - np.take(y, i0) z = np.take(y, i0) + (xn - np.take(b, i0)) * dy / db - return z def set_alpha(self, alpha): diff --git a/lib/matplotlib/tests/baseline_images/test_colorbar/colorbar_single_scatter.png b/lib/matplotlib/tests/baseline_images/test_colorbar/colorbar_single_scatter.png new file mode 100644 index 000000000000..fd6f35d1b9c5 Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_colorbar/colorbar_single_scatter.png differ diff --git a/lib/matplotlib/tests/test_colorbar.py b/lib/matplotlib/tests/test_colorbar.py index 4dd2e915a2a6..4b6e05d6a0d2 100644 --- a/lib/matplotlib/tests/test_colorbar.py +++ b/lib/matplotlib/tests/test_colorbar.py @@ -195,6 +195,22 @@ def test_gridspec_make_colorbar(): plt.subplots_adjust(top=0.95, right=0.95, bottom=0.2, hspace=0.25) +@image_comparison(baseline_images=['colorbar_single_scatter'], + extensions=['png'], remove_text=True, + savefig_kwarg={'dpi': 40}) +def test_colorbar_single_scatter(): + # Issue #2642: if a path collection has only one entry, + # the norm scaling within the colorbar must ensure a + # finite range, otherwise a zero denominator will occur in _locate. + plt.figure() + x = np.arange(4) + y = x.copy() + z = np.ma.masked_greater(np.arange(50, 54), 50) + cmap = plt.get_cmap('jet', 16) + cs = plt.scatter(x, y, z, c=z, cmap=cmap) + plt.colorbar(cs) + + if __name__ == '__main__': import nose nose.runmodule(argv=['-s', '--with-doctest'], exit=False)