8000 Merge pull request #2002 from pelson/contour_levels_with_colors · matplotlib/matplotlib@355b056 · GitHub
[go: up one dir, main page]

Skip to content

Commit 355b056

Browse files
committed
Merge pull request #2002 from pelson/contour_levels_with_colors
Added support for providing 1 or 2 extra colours to the contour routines to easily specify the under and over colors.
2 parents 24a635f + dac1530 commit 355b056

File tree

4 files changed

+76
-13
lines changed

4 files changed

+76
-13
lines changed

doc/api/api_changes.rst

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -122,16 +122,25 @@ Changes in 1.3.x
122122
value of this kwarg is ``head_width = 20 * width``.
123123

124124
* Removed call of :meth:`~matplotlib.axes.Axes.grid` in
125-
:meth:`~matplotlib.pyplot.plotfile`. To draw the axes grid, set to *True*
126-
matplotlib.rcParams['axes.grid'] or ``axes.grid`` in ``.matplotlibrc`` or
127-
explicitly call :meth:`~matplotlib.axes.Axes.grid`
125+
:meth:`~matplotlib.pyplot.plotfile`. To draw the axes grid, set the
126+
``axes.grid`` rcParam to *True*, or explicitly call
127+
:meth:`~matplotlib.axes.Axes.grid`.
128+
129+
* It is now posible to provide ``number of levels + 1`` colors in the case of
130+
`extend='both'` for contourf (or just ``number of levels`` colors for an
131+
extend value ``min`` or ``max``) such that the resulting colormap's
132+
``set_under`` and ``set_over`` are defined appropriately. Any other number
133+
of colors will continue to behave as before (if more colors are provided
134+
than levels, the colors will be unused). A similar change has been applied
135+
to contour, where ``extend='both'`` would expect ``number of levels + 2``
136+
colors.
128137

129138
* A new keyword *extendrect* in :meth:`~matplotlib.pyplot.colorbar` and
130139
:class:`~matplotlib.colorbar.ColorbarBase` allows one to control the shape
131140
of colorbar extensions.
132141

133142
* The `~matplotlib.mpl` module is now deprecated. Those who relied on this
134-
module should transition to simply using `import matplotlib as mpl`.
143+
module should transition to simply using ``import matplotlib as mpl``.
135144

136145
* The extension of :class:`~matplotlib.widgets.MultiCursor` to both vertical
137146
(default) and/or horizontal cursor implied that ``self.line`` is replaced
@@ -142,8 +151,8 @@ Changes in 1.3.x
142151
raises :class:`NotImplementedError` instead of :class:`OSError` if the
143152
:command:`ps` command cannot be run.
144153

145-
* The :func:`~matplotlib.cbook.check_output` function has been moved to
146-
`~matplotlib.compat.subprocess`.
154+
* The :func:`matplotlib.cbook.check_output` function has been moved to
155+
:func:`matplotlib.compat.subprocess`.
147156

148157
* :class:`~matplotlib.patches.Patch` now fully supports using RGBA values for
149158
its ``facecolor`` and ``edgecolor`` attributes, which enables faces and

lib/matplotlib/contour.py

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -864,7 +864,32 @@ def __init__(self, ax, *args, **kwargs):
864864
ncolors = len(self.levels)
865865
if self.filled:
866866
ncolors -= 1
867-
cmap = colors.ListedColormap(self.colors, N=ncolors)
867+
i0 = 0
868+
869+
# Handle the case where colors are given for the extended
870+
# parts of the contour.
871+
extend_min = self.extend in ['min', 'both']
872+
extend_max = self.extend in ['max', 'both']
873+
use_set_under_over = False
874+
# if we are extending the lower end, and we've been given enough
875+
# colors then skip the first color in the resulting cmap. For the
876+
# extend_max case we don't need to worry about passing more colors
877+
# than ncolors as ListedColormap will clip.
878+
total_levels = ncolors + int(extend_min) + int(extend_max)
879+
if (len(self.colors) == total_levels and
880+
any([extend_min, extend_max])):
881+
use_set_under_over = True
882+
if extend_min:
883+
i0 = 1
884+
885+
cmap = colors.ListedColormap(self.colors[i0:None], N= EDBE ncolors)
886+
887+
if use_set_under_over:
888+
if extend_min:
889+
cmap.set_under(self.colors[0])
890+
if extend_max:
891+
cmap.set_over(self.colors[-1])
892+
868893
if self.filled:
869894
self.collections = cbook.silent_list('mcoll.PathCollection')
870895
else:
@@ -1172,16 +1197,16 @@ def _process_levels(self):
11721197
# (Colorbar needs this even for line contours.)
11731198
self._levels = list(self.levels)
11741199

1175-
if not self.filled:
1176-
self.layers = self.levels
1177-
return
1178-
11791200
if self.extend in ('both', 'min'):
11801201
self._levels.insert(0, min(self.levels[0], self.zmin) - 1)
11811202
if self.extend in ('both', 'max'):
11821203
self._levels.append(max(self.levels[-1], self.zmax) + 1)
11831204
self._levels = np.asarray(self._levels)
11841205

1206+
if not self.filled:
1207+
self.layers = self.levels
1208+
return
1209+
11851210
# layer values are mid-way between levels
11861211
self.layers = 0.5 * (self._levels[:-1] + self._levels[1:])
11871212
# ...except that extended layers must be outside the
@@ -1526,9 +1551,7 @@ def _check_xyz(self, args, kwargs):
15261551
if y.shape != z.shape:
15271552
raise TypeError("Shape of y does not match that of z: found "
15281553
"{0} instead of {1}.".format(y.shape, z.shape))
1529-
15301554
else:
1531-
15321555
raise TypeError("Inputs x and y must be 1D or 2D.")
15331556

15341557
return x, y, z
Loading

lib/matplotlib/tests/test_contour.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,34 @@ def test_contour_manual_labels():
149149
cs = plt.contour(x,y,z)
150150
pts = np.array([(1.5, 3.0), (1.5, 4.4), (1.5, 6.0)])
151151
plt.clabel(cs, manual=pts)
152+
153+
154+
@image_comparison(baseline_images=['contour_manual_colors_and_levels'],
155+
extensions=['png'], remove_text=True)
156+
def test_given_colors_levels_and_extends():
157+
_, axes = plt.subplots(2, 4)
158+
159+
data = np.arange(12).reshape(3, 4)
160+
161+
colors = ['red', 'yellow', 'pink', 'blue', 'black']
162+
levels = [2, 4, 8, 10]
163+
164+
for i, ax in enumerate(axes.flatten()):
165+
plt.sca(ax)
166+
167+
filled = i % 2 == 0.
168+
extend = ['neither', 'min', 'max', 'both'][i // 2]
169+
170+
if filled:
171+
last_color = -1 if extend in ['min', 'max'] else None
172+
plt.contourf(data, colors=colors[:last_color], levels=levels, extend=extend)
173+
else:
174+
last_level = -1 if extend == 'both' else None
175+
plt.contour(data, colors=colors, levels=levels[:last_level], extend=extend)
176+
177+
plt.colorbar()
178+
179+
180+
if __name__ == '__main__':
181+
import nose
182+
nose.runmodule(argv=['-s', '--with-doctest'], exit=False)

0 commit comments

Comments
 (0)
0