Take the 2-minute tour ×

I'm trying to produce a plot which uses both contour and contourf where they both use the same colormap, plotting the same data. However, contourf is only used to plot data which is 'significant' in some way (using a masked array). Meanwhile, contour is used to plot all the data. The aim is to produce a plot where all the information is available, but the eye is drawn to the more important areas.

I nearly have this working as I would like, but I am finding that the color of the contour lines is slightly different from the color of the filled contours from contourf.

I'm guessing that the differences come from the fact that either the contour colors are actually half-way between the contour colors (which would make sense, as the contour lines are defined at a value, e.g. 1, 2, etc, and the filled contours are between 1 and 2, i.e. with a 'value' of 1.5 etc).

I am defining my colormap as

cmap = cm.coolwarm

my contour levels, used for both contour and contourf are

clevs = [-3.,-2.,-1.,1.,2.,3.]

The contour lines are plotted as


and the filled contours are plotted as


Is there a straight-forward way to have the colors of the contour lines 'match' those of the filled contours, i.e. the line at 1 is the color of the 1-2 filled contour, the line at 2 is the color of the 2-3 filled contour, the line at -1 have the color of the -2--1 filled contour etc.?

Many thanks for your help.

share|improve this question
Deleted my answer because it was wrong ;) On consideration, I think the 'right' thing to do is to leave the color mis-match (most honest to data). A slightly orthogonal approach is to replace the contourf call with a contour call on the same masked data but with 3x the line density or something like that. –  tcaswell Jul 24 '13 at 15:17
add comment

1 Answer

up vote 0 down vote accepted

I think that one possible solution here is to create a new colormap for the call to contour. If the original colormap is defined as

cmap = matplotlib.cm.coolwarm

and the contour levels to plot as


then the new colormap can be created by

new_cw_vals_t = np.float128(cw_vals[4::8,:])
new_cw_vals_b = np.float128(cw_vals[12::8,:])
for i in np.arange(new_cw_vals.shape[0]):
    if clevs[i] < 0.0:
newcmap = matplotlib.colors.LinearSegmentedColormap.from_list("newcw", new_cw_vals)

I had to put a shift in to allow for the fact that I'm not plotting the 0 line.

which is then used in the call to contour


Essentially I am creating a colormap with 8 times the number of points, and then picking out the mid-points. It isn't quite perfect though, the colors are ever-so-slightly off from the colors from contourf. This may be down to rounding differences (the colormap values seem to be float32). It is also a bit specific to the values used in clevs, although it could easily be changed for other values.

share|improve this answer
add comment

Your Answer


