Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Add MATLAB-Like contourc #367

ddale opened this Issue Jun 20, 2011 · 25 comments


None yet

ddale commented Jun 20, 2011

Original report at SourceForge, opened Sun Oct 10 22:25:55 2010

This would probably be in mlab. I haven't checked but the count plotting functions probably use a private function similar to contourc behind the scenes. Having access to this would be great. Currently I am creating a figure. drawing a contour plot, than closing the figure.

I'd like to say that I too would appreciate this, and judging by the mailing list so would a few others who would like to be able to extract points from a contour.


pelson commented Jun 30, 2012

You can get the paths that a contour would produce with:

import matplotlib.pyplot as plt
import numpy

data = numpy.arange(1200).reshape(30, 40)
cs = plt.contour(data, levels=[10])

for collection in cs.collections:
    for path in collection.get_paths():
        print path

Does this do what a contourc function might do?


dmcdougall commented Aug 23, 2012

@pelson Yes, but Matlab's actual contourc does not require you to produce a plot. It's basically a 'low-level' contour generator, storing the result in an array rather than plotting it. See here for details.


WeatherGod commented Aug 23, 2012

Note, there is a subtle difference between the contouring results from contour and contourf (mostly in domain edge handling and masked areas). So, a contourc function would have to know which one of these the user would want.

Essentially, contour() and contourf() are creating a ContourSet object, which is fairly close to what we want, but it does greatly blur the boundary between the low-level processing and the figure/axes/coloring parts of the process. Maybe some work could be done to more cleanly delineate the plot-making part and the calculation/processing part.


ianthomas23 commented Aug 23, 2012

The contour calculations are coordinated by the method _get_allsegs_and_allkinds of classes derived from ContourSet (currently QuadContourSet and TriContourSet). These methods are fairly self-contained, but do depend on various things being set up correctly before they are called.

I frequently use code like @pelson's example above and have passed on similar examples to others. Although you have to put up with the overhead of creating a dummy Axes, there is no unwanted graphical output. I have never benchmarked exactly how much of an overhead there is but my suspicion is that it is negligible for all but the simplest of examples which will be lightning fast anyway.

I always emphasize that care is needed with the example code. Each path may be just an array of vertices corresponding to a single open or closed polygon, which is what most people expect, but a path may also correspond to 2 or more polygons if the member codes is set to indicate at which indices the polygons start. Naive use of the paths may not be what is wanted; often the use of path.to_polygons() is better.


pelson commented Oct 18, 2012

@ianthomas23 : I found your write-up very useful. Do you have any appetite to wrap this up in a function, or do you think that is asking for trouble compared to the example that I gave?


ianthomas23 commented Oct 18, 2012

@pelson: I'd like to put this on hold for a few weeks more.

I am currently working on a rewrite of the behind-the-scenes C code to add extra functionality and improve performance of contour and contourf. Depending on how it goes and the approval of the community, it may or may not result in changes to how the contour results are stored and hence how this contourc idea would be implemented. I'd prefer to concentrate on this at the moment, and then someone (possibly me!) can look at improvements to the python contour code which may help with contourc and perhaps the other issue recently discussed about how a ContourSet is not an Artist. I am only a couple of weeks away from having something concrete to demonstrate.


WeatherGod commented Oct 18, 2012

@ianthomas23, let me know when you get to the point where you want closer reviews of results. I have a huge dataset of gridded fields, and work very closely to the results of contourf (converting them into polygons for shapefiles).


mdboom commented Oct 22, 2012

@ianthomas23: Thanks for this! contour has needed some rationalization for a long time.

aaren commented Nov 7, 2013

Disclaimer: Do not do this!

Maybe this isn't good practice (see below) but for now you can call the
underlying C function directly, which avoids doing any drawing. I think this is
the closest to a contourc like function.

import numpy as np
from matplotlib._cntr import Cntr

# some exciting test function
x = np.linspace(-3, 3, 100)
A, B = np.meshgrid(x, x)
fab = np.sin(A**2) + np.cos(B**2)

# the actual call 
contour = Cntr(A, B, fab)
# let's find where f(a, b) = 0
zero_traces = contour.trace(0)

# bundle all the points together (ignoring 'allkinds' type arrays)
zero_contour = np.row_stack(traces[:len(traces) / 2])

It would be easy to map to this function directly. @ianthomas23 are you
planning to have the same interface for the c code as for plt.contour? (less
all the drawing stuff)


ianthomas23 commented Nov 7, 2013

@aaren: Please do not do this nor encourage others to. Accessing the underlying C code in this manner is completely unsupported and bypasses reams of consistency checks that are very important. Simple examples may well work fine, but more complicated ones could cause a segmentation violation or produce garbage output. Use @pelson's code above along with path.to_polygons().

I hacked an attempt here: https://github.com/mfouesneau/mpl_contourc
It is based on the ContourSet and QuadContourSet classes but only computes the contours. So in principle, it keeps the consistency with mpl checks and current implementation


tacaswell commented Mar 5, 2014

@mfouesneau Could you put that in a PR? That is the path of least resistance to get your code into mpl.

@tacaswell sorry but PR meaning?


efiring commented Mar 5, 2014

@tacaswell, simply putting it in a PR might be premature, since I think it represents quite a bit of code duplication. We need to consider whether this can be part of a refactoring, so that there is little or no duplication required to provide the contour paths and the full contour plot.
@mfouesneau, "PR" is "Pull Request".

@efiring @tacaswell, yes sorry I figured PR a bit late.

I think you the easiest would be a parent class to QuadContourSet that does the calculations only and refactor QuadContourSet to only deal with the rest.
(I did not look at TriContourSet)

@tacaswell tacaswell added this to the v1.5.x milestone Aug 18, 2014


tacaswell commented Aug 18, 2014

@mfouesneau Are you still interested in working on this?

@tacaswell have a look at

I believe it should be easy to integrate.

@tacaswell tacaswell modified the milestone: v1.5.x, unassigned Aug 18, 2014


tacaswell commented Aug 18, 2014

On more careful reading, I think http://scikit-image.org/docs/dev/auto_examples/plot_contours.html does what you want.

If you want to merge skimage into mpl yes.

The version I made (link above) is only a re-write of what was in mpl at that time. It only provides a simple intermediate class as QuadContourSet etc, but offers access to the polygons.


tacaswell commented Aug 18, 2014

Sorry I wasn't clear. I meant skimage already provides this functionality so it is less important that mpl provides it as well, I am not suggesting merging (or even depending on) skimage.

If you want to do the refactoring we will happily review/merge it, but this is not very high on my list of priorities right now.

What would be most efficient? writing a class and making ContourSet a child or what?


petehuang commented Dec 31, 2016

@tacaswell Sounds like we should make a call on whether or not this functionality should be in MPL and close if not

One argument against relying on skimage is its only for 2d datasets, whereas MPL is in position (with some refactoring) to make this functionality possible for irregular, triangulated data also (with tricontour).

This would be difficult to refactor given the current structure. Currently most of the work of preparing the data and handing it off to the C/C++ code is done in QuadContourSet for contour and TriContourSet for tricontour, both of which are children of ContourSet. But ContourSet handles some of the calculation setup as well as the graphical side of things. To separate out calculation from plotting all plotting related tasks would have to be removed from ContourSet and a new mixin created that re-introduced it. Then the hierarchy would look something like:

ContourSet -> QuadContourSet ---> QuadContourSetPlotter
ContourPlotter ----------------/ 


ContourSet -> TriContourSet ---> TriContourSetPlotter
ContourPlotter ---------------/ 

Also, another argument against using skimage is that it does not support masked arrays.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment