This is a bug in the contouring code, as reported on matplotlib-devel under the title 'Use of contourf changed?' Actually it is a choice of bugs, depending on your perspective. I've condensed the problem and explanation of what is going on into the following example code
import numpy as np
import matplotlib.pyplot as plt
n = 30
x, y = np.meshgrid(np.linspace(-1, 1, n), np.linspace(-1, 1, n))
data = np.exp(-6*x*x)*np.exp(-6*y*y)
decr_levels = [0.9, 0.5, 0.1, 0.0]
incr_levels = list(reversed(decr_levels))
colors = ['b', 'b', 'b']
plt.subplot(3, 2, 1)
plt.contourf(data, levels=decr_levels, corner_mask='legacy', alpha=0.25, colors=colors)
plt.title("corner_mask='legacy', decreasing levels")
plt.subplot(3, 2, 2)
plt.contourf(data, levels=decr_levels, corner_mask=True, alpha=0.25, colors=colors)
plt.title('corner_mask=True, decreasing levels')
plt.subplot(3, 2, 3)
plt.contourf(data, levels=incr_levels, corner_mask='legacy', alpha=0.25, colors=colors)
plt.title("corner_mask='legacy', increasing levels")
plt.subplot(3, 2, 4)
plt.contourf(data, levels=incr_levels, corner_mask=True, alpha=0.25, colors=colors)
plt.title('corner_mask=True, increasing levels')
plt.subplot(3, 2, 5)
plt.contourf(data)
plt.title('defaults')
plt.subplot(3, 2, 6)
for level in decr_levels[:-1]: # Ignore lowest level.
plt.contourf(data, levels=[level, np.inf], corner_mask='legacy', alpha=0.25, colors='b')
plt.title('contourf each level to infinity')
plt.show()
and output

The OP obtained results like subplot 1 using mpl 1.4, or 1.5 and the contourf kwarg corner_mask='legacy' (i.e. the old contouring code in cntr.c). Using mpl 1.5 and the new corner masking code the results are like subplot 2. The new code is clearly wrong (though prettier). The old code is actually wrong too, but in a way that looks OK so it is a more subtle and insidious form of wrong.
The test data is a 2D gaussian, rising from 0 to 1 at the centre. Subplot 5 shows the default contour plot of this data, using either old or new code.
The problem is that the OP is passing a list of decreasing levels to contourf. This is the first time I have heard of anyone using decreasing contour levels. The documentation doesn't say the levels should be increasing, but all of our examples have them increasing. The old contour code does not check that the levels increase, nor the python wrapper of the contouring code. When I wrote the new code it didn't occur to me that I needed to check that the levels increase given that the old code didn't bother. Oops!
The new code is trying to follow the contours going backwards. We are lucky (!) that we don't get an infinite loop or segmentation violation.
The old code uses, at its top level, a single function call for both contour and contourf. This is Cntr_trace(), line 1877 in cntr.c. It takes two contour levels, levels[0] and levels[1]. If levels[1] <= levels[0] it assumes that it is a contour call returning a non-filled polyline, if not it is a contourf call returning a filled polygon. In our example then it assumes it is a contour call whereas it is in fact a contourf call. The returned polyline is rendered as a filled polygon. The output is identical to that produced by taking each of the required contour levels in turn and performing a contourf call between that level and infinity. Subplot 6 does just this to show that it is identical to subplot 1.
Finally, if we reverse the contour levels in our test code so that they are increasing, we get the results shown in subplots 3 and 4. These are correct, given that we are contouring everything from 0 to 0.9, which just leaves a circle in the middle.
So we have a bug, or at least a lack of appropriate checking of specified contour levels. I assume that it has been around since the dawn of time. The OP's results are not what she asked for, but are presumably what she wants. Anyone else who has been using decreasing contour levels has been getting output that probably looks fine but is incorrect. At least my new code fails spectacularly and highlights the problem.
What do we do? Do we enforce increasing contour levels only, or do we allow decreasing ones? If the latter, do we only allow monotonically increasing or decreasing levels, or do we allow them to go up and back down again?
Whatever we opt for, I need to add a check in the new C++ code to only allow (lower, upper) pairs of contour levels. If they are reversed, I will raise an exception. At the python level we could be more permissive, but ensure the C++ code is called with them in the correct order.
My preference is to only allow increasing levels. We have been assuming, but not enforcing, that policy for many years. But I would like other developers' opinions on the subject.
This is a bug in the contouring code, as reported on matplotlib-devel under the title 'Use of contourf changed?' Actually it is a choice of bugs, depending on your perspective. I've condensed the problem and explanation of what is going on into the following example code
and output

The OP obtained results like subplot 1 using mpl 1.4, or 1.5 and the contourf kwarg
corner_mask='legacy'(i.e. the old contouring code incntr.c). Using mpl 1.5 and the new corner masking code the results are like subplot 2. The new code is clearly wrong (though prettier). The old code is actually wrong too, but in a way that looks OK so it is a more subtle and insidious form of wrong.The test data is a 2D gaussian, rising from 0 to 1 at the centre. Subplot 5 shows the default contour plot of this data, using either old or new code.
The problem is that the OP is passing a list of decreasing levels to
contourf. This is the first time I have heard of anyone using decreasing contour levels. The documentation doesn't say the levels should be increasing, but all of our examples have them increasing. The old contour code does not check that the levels increase, nor the python wrapper of the contouring code. When I wrote the new code it didn't occur to me that I needed to check that the levels increase given that the old code didn't bother. Oops!The new code is trying to follow the contours going backwards. We are lucky (!) that we don't get an infinite loop or segmentation violation.
The old code uses, at its top level, a single function call for both
contourandcontourf. This isCntr_trace(), line 1877 incntr.c. It takes two contour levels,levels[0]andlevels[1]. Iflevels[1] <= levels[0]it assumes that it is acontourcall returning a non-filled polyline, if not it is acontourfcall returning a filled polygon. In our example then it assumes it is acontourcall whereas it is in fact acontourfcall. The returned polyline is rendered as a filled polygon. The output is identical to that produced by taking each of the required contour levels in turn and performing acontourfcall between that level and infinity. Subplot 6 does just this to show that it is identical to subplot 1.Finally, if we reverse the contour levels in our test code so that they are increasing, we get the results shown in subplots 3 and 4. These are correct, given that we are contouring everything from 0 to 0.9, which just leaves a circle in the middle.
So we have a bug, or at least a lack of appropriate checking of specified contour levels. I assume that it has been around since the dawn of time. The OP's results are not what she asked for, but are presumably what she wants. Anyone else who has been using decreasing contour levels has been getting output that probably looks fine but is incorrect. At least my new code fails spectacularly and highlights the problem.
What do we do? Do we enforce increasing contour levels only, or do we allow decreasing ones? If the latter, do we only allow monotonically increasing or decreasing levels, or do we allow them to go up and back down again?
Whatever we opt for, I need to add a check in the new C++ code to only allow
(lower, upper)pairs of contour levels. If they are reversed, I will raise an exception. At the python level we could be more permissive, but ensure the C++ code is called with them in the correct order.My preference is to only allow increasing levels. We have been assuming, but not enforcing, that policy for many years. But I would like other developers' opinions on the subject.