From 8064a81655e893f8e461d709192db0d03707096b Mon Sep 17 00:00:00 2001 From: Eric Firing Date: Wed, 28 Jun 2017 13:31:04 -0400 Subject: [PATCH 1/5] ENH: support extend kwarg with LogNorm in contourf --- lib/matplotlib/contour.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/matplotlib/contour.py b/lib/matplotlib/contour.py index 8393a4b2b066..89b46f9d1083 100644 --- a/lib/matplotlib/contour.py +++ b/lib/matplotlib/contour.py @@ -1245,10 +1245,19 @@ def _process_levels(self): # (Colorbar needs this even for line contours.) self._levels = list(self.levels) + if self.logscale: + raised = lambda x: x * 1.1 + lowered = lambda x: x / 1.1 + else: + raised = lambda x: x + 1 + lowered = lambda x: x - 1 + if self.extend in ('both', 'min'): - self._levels.insert(0, min(self.levels[0], self.zmin) - 1) + lower = lowered(min(self.levels[0], self.zmin)) + self._levels.insert(0, lower) if self.extend in ('both', 'max'): - self._levels.append(max(self.levels[-1], self.zmax) + 1) + upper = raised(max(self.levels[-1], self.zmax)) + self._levels.append(upper) self._levels = np.asarray(self._levels) if not self.filled: @@ -1260,10 +1269,7 @@ def _process_levels(self): # ...except that extended layers must be outside the # normed range: if self.extend in ('both', 'min'): - if self.logscale: - self.layers[0] = 1e-150 - else: - self.layers[0] = -1e150 + self.layers[0] = 1e-150 if self.logscale else -1e150 if self.extend in ('both', 'max'): self.layers[-1] = 1e150 From 32b3210a982af43fe33cf28bbba8b722f845b18d Mon Sep 17 00:00:00 2001 From: Eric Firing Date: Mon, 3 Jul 2017 13:34:01 -0400 Subject: [PATCH 2/5] Contour level auto-selection: clip unused Locator output Locator.tick_values() returns levels beyond the data limits. In the case of LogLocator with a small data range, the overrun can be large because it is expanding to the decade points. In addition, no account was being taken of the "extend" kwarg. With this changeset, the outermost levels will be the miminum required to include the data interval in the default case, and will be reduced when "extend" is used so that some of the data range will fall in the extended sections. This is expected to be rare, however; normally the "extend" kwarg would be used only when levels are explicitly set, not auto-selected with a Locator. --- lib/matplotlib/contour.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/contour.py b/lib/matplotlib/contour.py index 89b46f9d1083..757f179fd2ea 100644 --- a/lib/matplotlib/contour.py +++ b/lib/matplotlib/contour.py @@ -1187,8 +1187,16 @@ def _autolev(self, N): self.locator = ticker.MaxNLocator(N + 1, min_n_ticks=1) lev = self.locator.tick_values(self.zmin, self.zmax) + i0 = np.nonzero(lev < self.zmin)[0][-1] + i1 = np.nonzero(lev > self.zmax)[0][0] + 1 + if self.extend in ('min', 'both'): + i0 += 1 + if self.extend in ('max', 'both'): + i1 -= 1 + i1 = min(i1, len(lev)) + self._auto = True - return lev + return lev[i0:i1] def _contour_level_args(self, z, args): """ From c918b30e4978822528dca52023e960c0679d80e3 Mon Sep 17 00:00:00 2001 From: Eric Firing Date: Mon, 3 Jul 2017 15:48:18 -0400 Subject: [PATCH 3/5] pep8 checker requires def in place of lambda --- lib/matplotlib/contour.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/contour.py b/lib/matplotlib/contour.py index 757f179fd2ea..87d42222d9a3 100644 --- a/lib/matplotlib/contour.py +++ b/lib/matplotlib/contour.py @@ -1254,11 +1254,14 @@ def _process_levels(self): self._levels = list(self.levels) if self.logscale: - raised = lambda x: x * 1.1 - lowered = lambda x: x / 1.1 + def raised(x): return x * 1.1 + + def lowered(x): return x / 1.1 + else: - raised = lambda x: x + 1 - lowered = lambda x: x - 1 + def raised(x): return x + 1 + + def lowered(x): return x - 1 if self.extend in ('both', 'min'): lower = lowered(min(self.levels[0], self.zmin)) From 1973beb2de0a042555fc7c74654bb25ce9631a61 Mon Sep 17 00:00:00 2001 From: Eric Firing Date: Mon, 3 Jul 2017 20:31:53 -0400 Subject: [PATCH 4/5] in _autolev, handle the case where tick_values does not overshoot --- lib/matplotlib/contour.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/contour.py b/lib/matplotlib/contour.py index 87d42222d9a3..c6dfb6bdfcfc 100644 --- a/lib/matplotlib/contour.py +++ b/lib/matplotlib/contour.py @@ -1180,6 +1180,7 @@ def _autolev(self, N): one contour line, but two filled regions, and therefore three levels to provide boundaries for both regions. """ + self._auto = True if self.locator is None: if self.logscale: self.locator = ticker.LogLocator() @@ -1187,15 +1188,25 @@ def _autolev(self, N): self.locator = ticker.MaxNLocator(N + 1, min_n_ticks=1) lev = self.locator.tick_values(self.zmin, self.zmax) - i0 = np.nonzero(lev < self.zmin)[0][-1] - i1 = np.nonzero(lev > self.zmax)[0][0] + 1 + + try: + if self.locator._symmetric: + return lev + except AttributeError: + pass + + under = np.nonzero(lev < self.zmin)[0] + i0 = under[-1] if len(under) else 0 + over = np.nonzero(lev > self.zmax)[0] + i1 = over[0] + 1 if len(over) else len(lev) if self.extend in ('min', 'both'): i0 += 1 if self.extend in ('max', 'both'): i1 -= 1 - i1 = min(i1, len(lev)) - self._auto = True + if i1 - i0 < 3: + i0, i1 = 0, len(lev) + return lev[i0:i1] def _contour_level_args(self, z, args): From 91a38f7b5b788ae8aed54d80c845d50fbe7e4ee9 Mon Sep 17 00:00:00 2001 From: Eric Firing Date: Mon, 3 Jul 2017 20:52:52 -0400 Subject: [PATCH 5/5] partial fix for contour_hatching test failure This puts the hatches in the same order as they were in the reference figure, but the images still don't match because the gray shades are not the same as they were. Furthermore, looking at the original reference figures shows that the pdf and svg backends handle the alpha differently than the agg backend. Not sure what to do about that. --- lib/matplotlib/tests/test_axes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index bd6961b16d75..37a976133d0c 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -1647,7 +1647,7 @@ def test_contour_hatching(): fig = plt.figure() ax = fig.add_subplot(111) - cs = ax.contourf(x, y, z, hatches=['-', '/', '\\', '//'], + cs = ax.contourf(x, y, z, hatches=['/', '\\', '//', '-'], cmap=plt.get_cmap('gray'), extend='both', alpha=0.5)