Contour Label Problem

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

Consider:

f[x_, y_] = x^2 + y^2;
g[x_, y_] = x^4 + y^4;
critPts =
g[x, y] == 1}, {x, y, \[Lambda]} \[Element] Reals]


Then:

ContourPlot[f[x, y], {x, -2, 2}, {y, -2, 2},
PlotLegends -> Automatic,
MeshFunctions -> Function[{x, y}, g[x, y]],
Mesh -> {{1}},
MeshStyle -> {Thick, Yellow},
Epilog -> {
Red, PointSize[Large], Point[{x, y}] /. critPts
}]


Which produces this image:

ContourPlot[f[x, y], {x, -2, 2}, {y, -2, 2},
Contours -> {1, Sqrt[2]},
PlotLegends -> Automatic,
MeshFunctions -> Function[{x, y}, g[x, y]],
Mesh -> {{1}},
MeshStyle -> {Thick, Yellow},
Epilog -> {
Red, PointSize[Large], Point[{x, y}] /. critPts
}]


Which produces this image.

Now, if you hover your mouse over the two contours, tooltip labels of 1 and $\sqrt2$ appear.

Now consider this:

ContourPlot[f[x, y], {x, -2, 2}, {y, -2, 2},
Contours -> {1, Sqrt[2], 3},
PlotLegends -> Automatic,
MeshFunctions -> Function[{x, y}, g[x, y]],
Mesh -> {{1}},
MeshStyle -> {Thick, Yellow},
Epilog -> {
Red, PointSize[Large], Point[{x, y}] /. critPts
}]


Which produces this image.

Now, hover your mouse over each contour and you will see the incorrect tooltip labels pop up.

Is this a bug?

• Wow. Almost certainly? For simplicity, compare ContourPlot[f[x, y], {x, -2, 2}, {y, -2, 2}, Contours -> {1, Sqrt[2], 3}] to ContourPlot[f[x, y], {x, -2, 2}, {y, -2, 2}, Contours -> {1, N@Sqrt[2], 3}]. Nov 17, 2015 at 22:11

As far as I'm concerned, this is a clear bug.

Let's do a small amount of spelunking:

p1 = ContourPlot[f[x, y]
, {x, -2, 2}, {y, -2, 2}
, Contours -> {1, N@Sqrt[2], 3}, ContourShading -> None];
p2 = ContourPlot[f[x, y]
, {x, -2, 2}, {y, -2, 2}
, Contours -> {1, Sqrt[2], 3}, ContourShading -> None];
GraphicsRow@{p1,p2}


Hovering on the outer-most contour yields:

To be sure that these contours are mislabeled, let's extract the contours and plot them with the values of the Tooltips:

ListLinePlot[#1, Frame -> True, FrameLabel -> {{None, None}, {None, #2}}] & @@@ Cases[Normal@p1, Tooltip[{__, Line[a_]}, b_] :> {a, b}, Infinity]


ListLinePlot[#1, Frame -> True, FrameLabel -> {{None, None}, {None, #2}}] & @@@ Cases[Normal@p2, Tooltip[{__, Line[a_]}, b_] :> {a, b}, Infinity]


The contours are absolutely mislabeled when you use the symbolic Sqrt[2] instead of the approximate value N@Sqrt[2].

As noticed by J.M., the problem is that ContourPlot sorts the values of the contour, and of course,

Sort[{1, Sqrt[2], 3}]


yields

(* {1, 3, Sqrt[2]} *)


We can see this by evaluating

TracePrint[ContourPlot[x^2 + y^2, {x, -2, 2}, {y, -2, 2}, Contours -> {1,Sqrt[2], 3}, ContourShading -> None], SortBy[__], TraceInternal -> True]

• Spelunking (that is, TracePrint[ContourPlot[x^2 + y^2, {x, -2, 2}, {y, -2, 2}, Contours -> {1, Sqrt[2], 3}, ContourShading -> None], SortBy[__], TraceInternal -> True]) shows that this is indeed due to mis-sorting; cf. Sort[{1, Sqrt[2], 3}]. Nov 17, 2015 at 22:51
• @J.M. Ah, of course it is! Moral of the story: use approximate values for the numbers so that the sorting works correctly. I wonder if this is a "Possible Issue" somewhere in the documentation. In that sense, it might not actually be a bug. Nov 17, 2015 at 22:53
• Doesn't seem to be, but I will still classify this as a bug. Nov 17, 2015 at 22:57