Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
2012-07-24 Contourf handles the extend kwarg by mapping the extended
ranges outside the normed 0-1 range so that they are
handled by colormap colors determined by the set_under
and set_over methods. Previously the extended ranges
were mapped to 0 or 1 so that the "under" and "over"
colormap colors were ignored. - EF

2012-06-24 Make use of mathtext in tick labels configurable - DSD

2012-06-05 Images loaded through PIL are now ordered correctly - CG
Expand Down
10 changes: 10 additions & 0 deletions doc/api/api_changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ For new features that were added to matplotlib, please see
Changes in 1.2.x
================

* In :meth:`~matplotlib.axes.Axes.contourf`, the handling of the *extend*
kwarg has changed. Formerly, the extended ranges were mapped
after to 0, 1 after being normed, so that they always corresponded
to the extreme values of the colormap. Now they are mapped
outside this range so that they correspond to the special
colormap values determined by the
:meth:`~matplotlib.colors.Colormap.set_under` and
:meth:`~matplotlib.colors.Colormap.set_over` methods, which
default to the colormap end points.

* The new rc parameter ``savefig.format`` replaces ``cairo.format`` and
``savefig.extension``, and sets the default file format used by
:meth:`matplotlib.figure.Figure.savefig`.
Expand Down
70 changes: 45 additions & 25 deletions examples/pylab_examples/contourf_demo.py
Original file line number Diff line number Diff line change
@@ -1,68 +1,70 @@
#!/usr/bin/env python
from pylab import *
import numpy as np
import matplotlib.pyplot as plt

origin = 'lower'
#origin = 'upper'

delta = 0.025

x = y = arange(-3.0, 3.01, delta)
X, Y = meshgrid(x, y)
Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
x = y = np.arange(-3.0, 3.01, delta)
X, Y = np.meshgrid(x, y)
Z1 = plt.mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = plt.mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = 10 * (Z1 - Z2)

nr, nc = Z.shape

# put NaNs in one corner:
Z[-nr//6:, -nc//6:] = nan
Z[-nr//6:, -nc//6:] = np.nan
# contourf will convert these to masked


Z = ma.array(Z)
Z = np.ma.array(Z)
# mask another corner:
Z[:nr//6, :nc//6] = ma.masked
Z[:nr//6, :nc//6] = np.ma.masked

# mask a circle in the middle:
interior = sqrt((X**2) + (Y**2)) < 0.5
Z[interior] = ma.masked
interior = np.sqrt((X**2) + (Y**2)) < 0.5
Z[interior] = np.ma.masked


# We are using automatic selection of contour levels;
# this is usually not such a good idea, because they don't
# occur on nice boundaries, but we do it here for purposes
# of illustration.
CS = contourf(X, Y, Z, 10, # [-1, -0.1, 0, 0.1],
CS = plt.contourf(X, Y, Z, 10, # [-1, -0.1, 0, 0.1],
#alpha=0.5,
cmap=cm.bone,
cmap=plt.cm.bone,
origin=origin)

# Note that in the following, we explicitly pass in a subset of
# the contour levels used for the filled contours. Alternatively,
# We could pass in additional levels to provide extra resolution,
# or leave out the levels kwarg to use all of the original levels.

CS2 = contour(CS, levels=CS.levels[::2],
CS2 = plt.contour(CS, levels=CS.levels[::2],
colors = 'r',
origin=origin,
hold='on')

title('Nonsense (3 masked regions)')
xlabel('word length anomaly')
ylabel('sentence length anomaly')
plt.title('Nonsense (3 masked regions)')
plt.xlabel('word length anomaly')
plt.ylabel('sentence length anomaly')

# Make a colorbar for the ContourSet returned by the contourf call.
cbar = colorbar(CS)
cbar = plt.colorbar(CS)
cbar.ax.set_ylabel('verbosity coefficient')
# Add the contour line levels to the colorbar
cbar.add_lines(CS2)

figure()
plt.figure()

# Now make a contour plot with the levels specified,
# and with the colormap generated automatically from a list
# of colors.
levels = [-1.5, -1, -0.5, 0, 0.5, 1]
CS3 = contourf(X, Y, Z, levels,
CS3 = plt.contourf(X, Y, Z, levels,
colors = ('r', 'g', 'b'),
origin=origin,
extend='both')
Expand All @@ -72,16 +74,34 @@
CS3.cmap.set_under('yellow')
CS3.cmap.set_over('cyan')

CS4 = contour(X, Y, Z, levels,
CS4 = plt.contour(X, Y, Z, levels,
colors = ('k',),
linewidths = (3,),
origin = origin)
title('Listed colors (3 masked regions)')
clabel(CS4, fmt = '%2.1f', colors = 'w', fontsize=14)
plt.title('Listed colors (3 masked regions)')
plt.clabel(CS4, fmt = '%2.1f', colors = 'w', fontsize=14)

# Notice that the colorbar command gets all the information it
# needs from the ContourSet object, CS3.
colorbar(CS3)

show()
plt.colorbar(CS3)

# Illustrate all 4 possible "extend" settings:
extends = ["neither", "both", "min", "max"]
cmap = plt.cm.get_cmap("winter")
cmap.set_under("magenta")
cmap.set_over("yellow")
# Note: contouring simply excludes masked or nan regions, so
# instead of using the "bad" colormap value for them, it draws
# nothing at all in them. Therefore the following would have
# no effect:
#cmap.set_bad("red")

fig, axs = plt.subplots(2,2)
for ax, extend in zip(axs.ravel(), extends):
cs = ax.contourf(X, Y, Z, levels, cmap=cmap, extend=extend, origin=origin)
fig.colorbar(cs, ax=ax, shrink=0.9)
ax.set_title("extend = %s" % extend)
ax.locator_params(nbins=4)

plt.show()

30 changes: 17 additions & 13 deletions lib/matplotlib/contour.py
Original file line number Diff line number Diff line change
Expand Up @@ -870,10 +870,10 @@ def legend_elements(self, variable_name='x', str_format=str):
lower = str_format(lower)
upper = str_format(upper)

if i == 0 and self.extend in ('lower', 'both'):
labels.append(r'$%s \leq %s$' % (variable_name, upper, ))
elif i == n_levels-1 and self.extend in ('upper', 'both'):
labels.append(r'$%s > %s$' % (variable_name, lower, ))
if i == 0 and self.extend in ('min', 'both'):
labels.append(r'$%s \leq %s$' % (variable_name, lower, ))
elif i == n_levels-1 and self.extend in ('max', 'both'):
labels.append(r'$%s > %s$' % (variable_name, upper, ))
else:
labels.append(r'$%s < %s \leq %s$' % (lower, variable_name, upper))
else:
Expand Down Expand Up @@ -1029,24 +1029,25 @@ def _contour_level_args(self, z, args):
raise ValueError("Filled contours require at least 2 levels.")

def _process_levels(self):
# Color mapping range (norm vmin, vmax) is based on levels.
self.vmin = np.amin(self.levels)
self.vmax = np.amax(self.levels)
# Make a private _levels to include extended regions.
self._levels = list(self.levels)
if self.extend in ('both', 'min'):
self._levels.insert(0, min(self.levels[0],self.zmin) - 1)
if self.extend in ('both', 'max'):
self._levels.append(max(self.levels[-1],self.zmax) + 1)
self._levels = np.asarray(self._levels)
self.vmin = np.amin(self.levels) # alternative would be self.layers
self.vmax = np.amax(self.levels)
if self.extend in ('both', 'min'):
self.vmin = 2 * self.levels[0] - self.levels[1]
if self.extend in ('both', 'max'):
self.vmax = 2 * self.levels[-1] - self.levels[-2]
if self.filled:
# layer values are mid-way between levels
self.layers = 0.5 * (self._levels[:-1] + self._levels[1:])
# ...except that extended layers must be outside the
# normed range:
if self.extend in ('both', 'min'):
self.layers[0] = 0.5 * (self.vmin + self._levels[1])
self.layers[0] = -np.inf
if self.extend in ('both', 'max'):
self.layers[-1] = 0.5 * (self.vmax + self._levels[-2])
self.layers[-1] = np.inf
else:
self.layers = self.levels # contour: a line is a thin layer
# Use only original levels--no extended levels
Expand All @@ -1065,9 +1066,11 @@ def _process_colors(self):
"""
self.monochrome = self.cmap.monochrome
if self.colors is not None:
# Generate integers for direct indexing.
i0, i1 = 0, len(self.levels)
if self.filled:
i1 -= 1
# Out of range indices for over and under:
if self.extend in ('both', 'min'):
i0 = -1
if self.extend in ('both', 'max'):
Expand All @@ -1080,7 +1083,8 @@ def _process_colors(self):
self.set_clim(self.vmin, self.vmax)
if self.extend in ('both', 'max', 'min'):
self.norm.clip = False
self.set_array(self.layers)
self.set_array(self.layers) # Required by colorbar, but not
# actually used.
# self.tcolors are set by the "changed" method

def _process_linewidths(self):
Expand Down