Eric,

Thanks for the scripts -- they make it quite clear what the problem is.

As you know, cntr.c is a fairly opaque chunk of code, and I'm not having 
much luck so far tracking down why the branch-cutting between the outer 
and inner polygons is not working.

In the meantime, I have some more general questions.

It looks like that the backend API isn't really set up to do compound 
paths.  The PolygonCollection class appears to be just a list of simple 
polygons, rather than something that could be used for compound paths.  
(Correct me if I'm wrong.)  Is the only reason for wanting branch cuts 
in contours because matplotlib doesn't support compound paths?  Is there 
a reason matplotlib doesn't support compound paths?  I suspect you guys 
have been down that "path" [haha] already.  I would anticipate problems 
if different backends have different winding rules, but perhaps there 
are some ways to around that?  This could be useful in general in 
matplotlib...

Another option is to remove the mask from the contours in a 
post-processing step (i.e. don't worry about trying to do it as part of 
the main two passes in cntr.c).  The result may be a bit of a 
Frankenstein's monster, admittedly, but it is an option of last resort 
if we choose to take it.  cntr.c is creating the inner and outer 
polygons correctly, just not connecting them with a slit, right?

In the meantime, I'll continue to look for the root cause.

Cheers,
Mike

Eric Firing wrote:
> 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()
>
>   


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Reply via email to