filled contours: progress, a minor bug (?), and a point of curiosity

Perry, John, Progress!

Cool!

    > I found that the problem I was having with PolyCollection
    > was this: the vertices argument must be a sequence (list or
    > tuple) of tuples of tuples--if one gives it a list of
    > *lists* of tuples, one gets

    > [first part of trace omitted] File
    > "/usr/lib/python2.3/site-packages/matplotlib/collections.py",
    > line 205, in draw self._offsets, self._transOffset)
    > TypeError: CXX: type error

    > (The line number was smaller before I put in some debugging
    > print statements.)

    > I think this fussiness qualifies as a bug; the docstring for
    > PolyCollection says vertices can be a sequence of sequences
    > of tuples. I don't know what the right way to fix it is,
    > however, so I am working around it.

Fair enough -- I just fixed all the agg collection drawing routines to
work with the sequence API and not require tuples. Glad to see you're
making progress -- poly contouring is something I'd like to see added.

    > Having solved that problem, I am getting more optimistic
    > about being able to come up with a usable filled contour
    > capability fairly quickly. Still no promises, though.

Great -- be mindful of the contourf matlab docstrings. Strict
adherence is not required, but it is nice to be compatible where
possible.

    > All this brings to mind a question that has puzzled me for a
    > long time: why does matplotlib internally use sequences of
    > (x,y) tuples instead of numerix arrays--either a 2-D array,
    > or a pair (or tuple) of 1-D arrays? I would think that
    > running all plotted numbers through the conversion from
    > arrays to Python tuples, and then from there into the native
    > data types for each backend, would incur a big performance
    > penalty when plotting large numbers of points. Not that I
    > am suggesting a redesign--I am just curious.

Historical and other reasons. The historical part is that this part
of the code was written before Todd had solved the numeric/numarray
API compatibility problem for matplotlib. These are now solved, 've
been slowly adding some numerix code to backend agg, most recently in
0.72. I don't think it would make a lot of difference for
collections. In the first place, you'd have to create all these lists
of numarray lists, since the collection is by definition a list of
disconnected lines. In the second place, there is a fair amount going
on in the inner loop that I think would offset the gains you get from
using numeric. In draw_lines, where the x,y access is a major part of
the inner loop, I do use numerix.

The backend API is moving to a path drawing model, which may obviate
the need for specialized collection drawing methods. The collection
interface would remain unchanged, but we might get away w/o having
special methods to draw them.

JDH

John,

    > Having solved that problem, I am getting more optimistic
    > about being able to come up with a usable filled contour
    > capability fairly quickly. Still no promises, though.

Great -- be mindful of the contourf matlab docstrings. Strict
adherence is not required, but it is nice to be compatible where
possible.

I have the basic filled contour functionality working, with the following caveats, comments, and questions:

0) I've done only the simplest of testing so far.

1) There is a fundamental difference in strategy between Matlab's contour patch generation algorithm and gcntr.c: Matlab makes all patches as simply connected regions without branch cuts, but gcntr polygons have branch cuts. This means that we can't use the polygon edges; if one wants line contours at the contour levels, they must be drawn separately, by asking gcntr for lines, as contour does. My inclination is to leave it this way: the user can simply call contourf to get the filled regions, and then call contour to add lines as needed. Typically I draw lines at only a few of the color boundaries, and sometimes I draw additional lines within colored regions, so this is the way I normally use matlab contourf and contour anyway.

2) In the present version, there is much too much duplication of code between contour and contourf in axes.py; I copied the contour function to contourf, modified what I needed to, and moved only the ContourMappable class out to the module level. I would like to factor out more of the common code.

3) The docstrings in axes.py are driving me nuts--lacking proper indentation, they make it very difficult to find the function definitions. I presume this is because of the way boilerplate.py is generating the pylab.py functions and their docstrings. I haven't looked at boilerplate.py (I haven't used it yet at all), but I suspect it would be easy to change things so that it would handle properly indented docstrings. Is it OK if I do this?

4) ToDo: it is not standard in matlab, but for filled contouring I always use a matching colorbar--essentially a colorbar contoured with the same levels and colors as the contour plot itself, rather than one that shows the whole colormap.

5) ToDo: I haven't tried to do anything with region masking yet; maybe I will get to it soon, since it is something I need.

5) gcntr.c uses global variables, which presumably means that it will fail if called from more than one thread at a time. Longer term, should I/we/someone modify it so that this not the case? Or is this characteristic of other routines used by matplotlib, so there is no point in worrying about gcntr.c in particular?

6) When the time comes to send you my modifications, how should I do it: diffs, or complete files? Send to you directly, or to the list? If you would prefer diffs, please give me an example of the exact diff command options to use. (I am working with matplotlib-0.72.1 as a starting point.) Modified files will include axes.py, pylab.py (and/or boilerplate.py), _contour.c, and an example.

Eric