# ListContourPlot has wrong colouring: workaround?

Bug introduced in 8 or earlier and persisting through 11.0.1 or later

ListContourPlot uses the wrong colouring here:

res = Import["https://dl.dropboxusercontent.com/u/38623/res.wdx", "WDX"];

ListContourPlot[res, Contours -> Range[0.66, 0.9, 0.02], ColorFunction -> "Rainbow"]


The contour plot shows that the function value decreases around the bottom middle, even though it reaches its maximum there in reality.

The tooltips for the contour values between the red and orange regions are correct however: one contour shows 0.84 and the other 0.86. It's just the colouring that's wrong.

Compare

ListDensityPlot[res, ColorFunction -> "Rainbow"]


What is the simplest, most convenient workaround for this problem? Also, is this a bug or am I missing something? Can anyone explain why this happens?

I do need these specific contour values. Interpolation + ContourPlot gives the exact same result:

if = Interpolation[res]

ContourPlot[if[x, y], {x, 0.1, 1}, {y, 7, 9.4},
Contours -> Range[0.66, 9, 0.02], ColorFunction -> "Rainbow"]

• If you don't need the contour tooltips: ListDensityPlot[res, ColorFunction -> "Rainbow", Mesh -> {Range[0.66, 0.9, 0.02]}, MeshFunctions -> {#3 &}, MeshStyle -> GrayLevel[0, 0.5]] – J. M. will be back soon Oct 22 '15 at 11:28

This seems like a bug of some kind to me. But replacing the second argument to Range with the very last contour you want to see, as a workaround, gives the same contours but with proper coloring

Grid[{ListContourPlot[res, Contours -> Range[0.2, #, 0.02],
ColorFunction -> "Rainbow",
PlotLegends -> Automatic] & /@ {.86, .90}}]


And the bug seems to go away if you increase the scale of your data by a factor of 10, but it shows a completely different wrong color if you decrease it by a factor of 10.

Grid@Partition[#, 3] &@
Table[ListContourPlot[{#1, #2, x #3} & @@@ res,
Contours -> Range[x .2, x .9, x 0.02], ColorFunction -> "Rainbow",
ImageSize -> 300], {x, {.001, .01, .1, 1, 10, 100}}]


So apparently ListContourPlot and ContourPlot have trouble with their ColorFunctionScaling when the data is smaller than 1.

• Thank you Jason! Interesting observation that the plot legends have the wrong colouring too! – Szabolcs Oct 22 '15 at 9:22
• It has to be some issue with the ColorFunctionScaling right? If it rescales the data properly, to lie between 0 and 1, then it should have no effect when you multiply the data by 10. – Jason B. Oct 22 '15 at 9:24
• @JasonB But the bug doesn't present when using ListDensityPlot. Maybe there is something wrong with the ListContourPlot itself? – Silvia Oct 22 '15 at 13:11
• @Silvia, yeah - it must have to do with how the contour plot interacts with the scaling function. Perhaps someone needs to go spelunking? – Jason B. Oct 22 '15 at 13:45

The issue seems to be with colorfunction scaling, as a work around, turn it off and do our own interpolation in the ColorFunction:

 range = (res[[All, 3]] // Sort)[[{1, -1}]];
int = Interpolation[Transpose[{range, {0, 1}}],
InterpolationOrder -> 1];

ListContourPlot[res, Contours -> Range[0.66, 0.9, 0.02],
ColorFunctionScaling -> False,
ColorFunction -> (ColorData["Rainbow"][int[#]] &)]]


Trying to get to the bottom of this, here are the specific normalized values passed to the color function:

 cvals = Union[
Reap[ListContourPlot[res, Contours -> Range[0.66, 0.9, 0.02],
ColorFunction -> (Sow[#] &)]][[2, 1]]]


{0., 0.0937872, 0.186559, 0.279331, 0.372103, 0.464875, 0.557647, 0.650419, 0.743191, 0.835963, 0.865364, 0.928735, 1.}

and see where they are plotted:

 Row@Table[ ListContourPlot[res, Contours -> Range[0.66, 0.9, 0.02],
ColorFunction -> (If[# == cv, Red, Blue] &)] , {cv, cvals[[9 ;;]]}]


that bottom region is fed a "normalized" value of 0.865364.. which is in fact the actual average raw data value in that region (!) (That makes some sense of @JasonB's scaling observation )

One thing you see is the specified contour range is a tad large and produces a completely empty band. If you make the range Range[0.66, 0.86, 0.02] that fixes it too, but that should not really be a problem.