Mike,
The attached file masked_interior.py illustrates masking failure in a very simple case; you can see masking working in the plot on the left, where a contour intersects the masked region, but when that contour level is removed the masked region is getting filled in.
The file contourf_demo.py is slightly modified from the one in the mpl examples directory, and shows a failure of masking in a more complicated setting. The masked region at the lower-left corner is correct, but the masked region in the middle of the plot is getting filled with gray instead of being left blank.
In cntr.c there is a function, print_Csite, that may be helpful for debugging the simplest case, where the array size is not too large.
Note that the code path for filled contours is quite different, and more complicated, than for line contours--and in fact, even neglecting branch cuts, the two code paths don't always yield the same contours.
cntr.c is somewhat unusual among contour algorithms in that it works with rectangles without subdividing them into triangles.
Eric
------------------------------------------------------------------------
#!/usr/bin/env python
'''
This is a very simple illustration of what is causing
the problem with masked interior regions for filled contours.
The exterior contour and the interior contour are being
separated into two polygons instead of being joined by the
branch cut.
'''
import sys
from pylab import *
import matplotlib.numerix.npyma as ma
rc('figure', dpi=120)
x = y = arange(5)
X, Y = meshgrid(x, y)
Z = Y
ax = (0,4,0,4)
badmask = zeros(shape(X))
badmask[2, 2] = 1
Z = ma.array(Z, mask=badmask)
print Z
subplot(2,1,1)
CS = contourf(X, Y, Z, (-0.1, 0.8, 2.0, 6.0),
colors=('r', 'g', 'b'))
CS.collections[0].set_edgecolor('c')
CS.collections[0].set_linewidth(6)
CS.collections[1].set_edgecolor('y')
CS.collections[1].set_linewidth(2)
CS.collections[2].set_edgecolor('m')
CS.collections[2].set_linewidth(4)
title('Masked correctly')
subplot(2,1,2)
CS = contourf(X, Y, Z, (-0.1, 0.8, 6.0),
colors=('r', 'b'))
CS.collections[0].set_edgecolor('c')
CS.collections[0].set_linewidth(6)
CS.collections[1].set_edgecolor('y')
CS.collections[1].set_linewidth(2)
title('Wrong: masked region filled')
print "len(CS.collections)", len(CS.collections)
colls = CS.collections
# We want to look at the actual polygons individually.
for i, coll in enumerate(colls):
print "level ", i
for j, T in enumerate(coll._verts):
print "polygon ", j
print T
# The second collection has two polygons, but should only have
# one; the two should be joined by a branch cut.
show()
------------------------------------------------------------------------
#!/usr/bin/env python
from pylab import *
import matplotlib.numerix.npyma as ma
origin = 'lower'
#origin = 'upper'
test_masking = True # There is a bug in filled contour masking.
if test_masking:
# Use a coarse grid so only a few masked points are needed.
delta = 0.5
else:
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)
Z = 10 * (Z1 - Z2)
# interior badmask doesn't work yet for filled contours
if test_masking:
badmask = zeros(shape(Z))
badmask[5,5] = 1
badmask[5,6] = 1
Z[5,5] = 0
Z[5,6] = 0
badmask[0,0] = 1
Z[0,0] = 0
Z = ma.array(Z, mask=badmask)
# 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],
#alpha=0.5,
cmap=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.
CS2 = contour(X, Y, Z, CS.levels[::2],
colors = 'r',
origin=origin,
hold='on')
title('Nonsense')
xlabel('word length anomaly')
ylabel('sentence length anomaly')
# Make a colorbar for the ContourSet returned by the contourf call.
cbar = colorbar(CS)
cbar.ax.set_ylabel('verbosity coefficient')
# Add the contour line levels to the colorbar
cbar.add_lines(CS2)
figure()
# Now make a contour plot with the levels specified,
# and with the colormap generated automatically from a list
# of colors.
levels = [-2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5]
CS3 = contourf(X, Y, Z, levels,
colors = ('r', 'g', 'b'),
origin=origin)
CS4 = contour(X, Y, Z, levels,
colors = ('k',),
linewidths = (3,),
origin = origin)
title('Listed colors')
clabel(CS4, fmt = '%2.1f', colors = 'w', fontsize=14)
colorbar(CS3)
#savefig('contourf_demo')
show()