Different contours in contour and contourf

Hi,

running the simple test code:

from pylab import *
X, Y = meshgrid(linspace(-3,3,11),linspace(-3,3,11))
Z = randn(*X.shape)
lev = linspace(Z.min(),Z.max(),11)[1:-1]
contourf(X,Y,Z, lev, extend='both')
contour(X,Y,Z, lev, colors='k')
show()

you will probably notice that the 'contourf' contours are not always exactly the sames as the 'contour' contours. Why is it so? Don't contour and contourf use the same contour constructor?

Cheers.

···

--
             / \ , ,
   _._ _ |oo| _ / \__/ \
  _|||| ((/ () \)) / \ Yannick COPIN (o:>* Doctus cum libro
  >>>>>/| ( ==== ) |oo| Institut de physique nucleaire de Lyon
   \____/ _`\ /'_ / \ (IN2P3 - France)
   / /.-' /\<>/\ `\.( () )_._ Tel: (33/0) 472 431 968
   > ` / \/ \ /`'--'////) http://snovae.in2p3.fr/ycopin/
    \__,-'`| |. |\/ |/\/\|"\"` AIM: YcCopin ICQ: 236931013
       jgs | |. | \___/\___/
           > >. | | |

Yannick Copin wrote:

Hi,

running the simple test code:

from pylab import *
X, Y = meshgrid(linspace(-3,3,11),linspace(-3,3,11))
Z = randn(*X.shape)
lev = linspace(Z.min(),Z.max(),11)[1:-1]
contourf(X,Y,Z, lev, extend='both')
contour(X,Y,Z, lev, colors='k')
show()

you will probably notice that the 'contourf' contours are not always exactly the sames as the 'contour' contours. Why is it so? Don't contour and contourf use the same contour constructor?

The same overall routine is used for contour as for contourf, but the contour tracing operation is not identical. Tracing a filled contour is much more complicated--that is probably why it is so hard to find filled contour routines. I suspect that whoever wrote the original code we are using wrote the line contour version first, then had to add quite a bit of logic and code to get it to make filled contours.

Now, you may be wondering why we can't simply use the boundary of the filled regions for the lines as well, to guarantee they are the same. The reason is that filled contour boundaries include cuts connecting inner and outer contours, and also inner boundaries (edges of masked regions--except when affected by a bug) and the outer boundaries of the domain). It might be possible to simply exclude those line segments from the line contours, but it is not clear to me that the effort would be well-spent.

I think that the differences illustrated in your example will occur almost entirely in pathologically ambiguous cases, but it is also possible that they reflect actual bugs or shortcomings of the algorithms used. Understanding the logic and tracing the code path in the present cntr.c is difficult; I have tried but failed to figure out and correct the interior masked region bug in contourf. If a better core contour routine with a suitable license could be found and substituted for the present one, that would be very nice. I have searched many times without turning anything up.

Eric

Hi,

Eric Firing wrote:

from pylab import *
X, Y = meshgrid(linspace(-3,3,11),linspace(-3,3,11))
Z = randn(*X.shape)
lev = linspace(Z.min(),Z.max(),11)[1:-1]
contourf(X,Y,Z, lev, extend='both')
contour(X,Y,Z, lev, colors='k')
show()

Now, you may be wondering why we can't simply use the boundary of the filled regions for the lines as well, to guarantee they are the same. The reason is that filled contour boundaries include cuts connecting inner and outer contours, and also inner boundaries (edges of masked regions--except when affected by a bug) and the outer boundaries of the domain). It might be possible to simply exclude those line segments from the line contours, but it is not clear to me that the effort would be well-spent.

OK, thanks for the explanations. I was using this dual approach contourf+contour to emphasize the contours from contourf. So is there a direct way to set the linewidth and linecolor (and linestyle?) of contours from contourf? (I suspect not, according to contourf documentation:

     contourf differs from the Matlab (TM) version in that it does not
         draw the polygon edges, because the contouring engine yields
         simply connected regions with branch cuts. To draw the edges,
         add line contours with calls to contour.

)

I think that the differences illustrated in your example will occur almost entirely in pathologically ambiguous cases, but it is also

Not necessarily pathological cases, just noisy data :-/ (I agree my randn-based example was a bit extreme!)

Cheers.

···

--
             / \ , ,
   _._ _ |oo| _ / \__/ \
  _|||| ((/ () \)) / \ Yannick COPIN (o:>* Doctus cum libro
  >>>>>/| ( ==== ) |oo| Institut de physique nucleaire de Lyon
   \____/ _`\ /'_ / \ (IN2P3 - France)
   / /.-' /\<>/\ `\.( () )_._ Tel: (33/0) 472 431 968
   > ` / \/ \ /`'--'////) http://snovae.in2p3.fr/ycopin/
    \__,-'`| |. |\/ |/\/\|"\"` AIM: YcCopin ICQ: 236931013
       jgs | |. | \___/\___/
           > >. | | |

Yannick Copin wrote:

Hi,

Eric Firing wrote:

from pylab import *
X, Y = meshgrid(linspace(-3,3,11),linspace(-3,3,11))
Z = randn(*X.shape)
lev = linspace(Z.min(),Z.max(),11)[1:-1]
contourf(X,Y,Z, lev, extend='both')
contour(X,Y,Z, lev, colors='k')
show()

Now, you may be wondering why we can't simply use the boundary of the filled regions for the lines as well, to guarantee they are the same. The reason is that filled contour boundaries include cuts connecting inner and outer contours, and also inner boundaries (edges of masked regions--except when affected by a bug) and the outer boundaries of the domain). It might be possible to simply exclude those line segments from the line contours, but it is not clear to me that the effort would be well-spent.

OK, thanks for the explanations. I was using this dual approach contourf+contour to emphasize the contours from contourf. So is there a direct way to set the linewidth and linecolor (and linestyle?) of contours from contourf? (I suspect not, according to contourf documentation:

    contourf differs from the Matlab (TM) version in that it does not
        draw the polygon edges, because the contouring engine yields
        simply connected regions with branch cuts. To draw the edges,
        add line contours with calls to contour.

)

You could turn on coloring of the edges, but I don't think you would like the result because the edges would include the boundary lines and the cut lines.

The ContourSet object returned by contour and contourf has a .collections attribute. For contourf it is a list of PolyCollections, and you can set their attributes.

I think that the differences illustrated in your example will occur almost entirely in pathologically ambiguous cases, but it is also

Not necessarily pathological cases, just noisy data :-/ (I agree my randn-based example was a bit extreme!)

You might be able to avoid the problem most of the time by using some gridding routine, preferably something that uses a bit of curvature, to double the number of points in each dimension. I haven't tried it, but I suspect that this would turn even a very noisy field into something that would be contoured the same by contour and contourf.

···

Cheers.