Changing The Colour Of A Contour Plot

I have produced used the following code to create a contour plot:

ContourPlot[Cos[x] + Cos[y], {x, 0, 4 Pi}, {y, 0, 4 Pi}]


However, I would like to modify this plot so that when the function is positive the shading is blue, and when it is negative the shading is red.

Now I know there's already similar threads on this site to achieving this but I would like to impose another condition which makes things trickier.

I would also like the contours lines to have the OPPOSITE colour to the shading (i.e if the region is shaded blue then I want the contours to be red). The contours can be isolated by turning shading off:

ContourPlot[Cos[x] + Cos[y], {x, 0, 4 Pi}, {y, 0, 4 Pi},


So I would like the contours to be coloured as follows:

Combined with the shading, I hope that the final image will look like this:

The Goal

I would be really grateful if someone could shed some light on this.

I'm really hoping there's a way of implimenting an IF statement which will condition on the sign of the function.

• Related: (6916) Mar 7, 2016 at 12:05

A non-hackish method using Mesh and MeshFunctions:

ContourPlot[Cos[x] + Cos[y], {x, 0, 4 Pi}, {y, 0, 4 Pi},
ContourShading -> {Red, Blue}, Contours -> {{0}},
Mesh -> 4, MeshFunctions -> {Max[Cos[#] + Cos[#2], 0] &, Min[Cos[#] + Cos[#2], 0] &},
BaseStyle -> Thick, MeshStyle -> {Red, Blue},
PlotPoints -> 100
]


Here is a way using only contours but requiring manually generated styles. I was hoping that a function could be given directly to Contours for automatic generation but at least as I formulated it this did not work.

ContourPlot[Cos[x] + Cos[y], {x, 0, 4 Pi}, {y, 0, 4 Pi},
ContourShading -> {Red, Red, Red, Red, Red, Blue, Blue, Blue, Blue, Blue},
Contours -> Array[If[# > 0, {#, Red}, {#, Blue}] &, 9, {-2, 2}]
]


Alternatively:

sty = If[# > 0, {#, Blue}, {#, Red}] & /@ Range[-2, 2, 1/2]

ContourPlot[Cos[x] + Cos[y], {x, 0, 4 Pi}, {y, 0, 4 Pi},
ContourShading -> (sty[[All, 2]] /. {Red -> Blue, Blue -> Red}), Contours -> sty]


• Nice! (IOU one upvote.) Feb 21, 2016 at 19:54
• @J.M. Thanks! I don't know if this is best however. I often wonder how Heike would do it were she here. Feb 21, 2016 at 19:57
• This Alternative solution is really nice as it uses terminology of which I am familiar with. However, could I ask why you've included 'Red', and 'Blue' five times each in the list? Feb 21, 2016 at 20:26
• @MrS100 Because unlike the first method I could not separate the number contour lines from the number of contour fill styles. With only ContourShading -> {Red, Blue} here I would get a striped plot instead. Feb 21, 2016 at 20:29
• Thanks for the prompt reply. I've just tested this now and I see exactly what you mean. I'm struggling to understand what the function & /@ Range[#, #2, 1/2] &[-2, 2]' is doing as changing the values dramatically changes the result. I ask this because I have not seen this function before used in this context and I am keen to understand your choice of parameters. Feb 21, 2016 at 20:35

This rather hackish solution relies on the fact that the Tooltip[] objects within the output of ContourPlot[] store the height of the corresponding (set of) contours:

ContourPlot[Cos[x] + Cos[y], {x, 0, 4 π}, {y, 0, 4 π},
ColorFunction -> (Blend[{Red, Blue}, LogisticSigmoid[2 #]] &),
ColorFunctionScaling -> False, Contours -> 20] /.
Tooltip[stuff_, c_] :> Tooltip[Prepend[Cases[stuff, _Line],
Directive[{Blue, Red}[[UnitStep[c] + 1]],
Opacity[0.5], CapForm["Butt"]]], c]


• Thanks for the response J. M! I've upvoted as the code works as required. Feb 21, 2016 at 20:36

Yet another hackish solution that however regenerates the contour plot multiple times is the following combination:

Show[
(* Generate the shaded areas *)
ContourPlot[Cos[x] + Cos[y], {x, 0, 4 Pi}, {y, 0, 4 Pi},
ColorFunctionScaling -> False,
ColorFunction -> Function[z, If[z >= 0, Blue, Red]],
ContourStyle -> None
],

(* Generate the contours *)
ContourPlot[
Boole[#1[Cos[x] + Cos[y], 0]] (Cos[x] + Cos[y]),
{x, 0, 4 Pi}, {y, 0, 4 Pi}, Contours -> 4,
ContourStyle -> Directive[Thick, #2], ContourShading -> None
] &,
{{Greater, Less}, {Red, Blue}}
]
]


Mr. Wizard's solution presented in his answer above is clearly superior, but I put this together before I saw his answer, so I thought I might as well post it anyway.

• I like this response as this is how I initially thought about approaching the problem - by essentially combining two results. Upvoted Feb 21, 2016 at 20:37

I would also define my color style and use it like this:

   Clear[contours]
contours[n_?OddQ, color1_, color2_] := Module[{m},
m = IntegerPart[n/2];
cont = n;
col = Join[ConstantArray[color1, m], {Gray},
ConstantArray[color2, m]];];

contours[11, Blue, Red]

p1 = ContourPlot[Cos[x] + Cos[y], {x, 0, 4 Pi}, {y, 0, 4 Pi},
ContourShading -> None, ContourStyle -> col, Contours -> cont];
p2 = ContourPlot[Cos[x] + Cos[y], {x, 0, 4 Pi}, {y, 0, 4 Pi},
ColorFunction -> (If[# <= 0, Red, Blue] &),
ColorFunctionScaling -> False, Contours -> 1];
Show[p2, p1]


not ot get something close to your Goal picuter you can sue Show

• I somehow didn't see this answer before adding the second method to mine; sorry if I plagiarized accidentally, and +1. Feb 21, 2016 at 20:20
• Upvoted. This is a clever solution to the problem. I've only just become familiar with the show function today, but it been of use already. Feb 21, 2016 at 20:38
• @Mr.Wizard not at all and thanks for Upvote :-) Feb 21, 2016 at 20:41