3
$\begingroup$

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}, 
 ContourShading -> None]

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

The Contours

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

The Goal

Final Result

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.

Thanks in advance!

$\endgroup$
4
$\begingroup$

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
]

enter image description here


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]

enter image description here

$\endgroup$
  • $\begingroup$ Nice! (IOU one upvote.) $\endgroup$ – J. M. is away Feb 21 '16 at 19:54
  • $\begingroup$ @J.M. Thanks! I don't know if this is best however. I often wonder how Heike would do it were she here. $\endgroup$ – Mr.Wizard Feb 21 '16 at 19:57
  • $\begingroup$ 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? $\endgroup$ – Mr S 100 Feb 21 '16 at 20:26
  • $\begingroup$ @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. $\endgroup$ – Mr.Wizard Feb 21 '16 at 20:29
  • $\begingroup$ 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. $\endgroup$ – Mr S 100 Feb 21 '16 at 20:35
2
$\begingroup$

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 *)
 MapThread[
  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}}
 ]
]

Mathematica graphics


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.

$\endgroup$
  • $\begingroup$ I like this response as this is how I initially thought about approaching the problem - by essentially combining two results. Upvoted $\endgroup$ – Mr S 100 Feb 21 '16 at 20:37
2
$\begingroup$

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]

enter image description here

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

$\endgroup$
  • 1
    $\begingroup$ I somehow didn't see this answer before adding the second method to mine; sorry if I plagiarized accidentally, and +1. $\endgroup$ – Mr.Wizard Feb 21 '16 at 20:20
  • 1
    $\begingroup$ 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. $\endgroup$ – Mr S 100 Feb 21 '16 at 20:38
  • $\begingroup$ @Mr.Wizard not at all and thanks for Upvote :-) $\endgroup$ – Algohi Feb 21 '16 at 20:41
1
$\begingroup$

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]

looks a bit trippy to me

$\endgroup$
  • $\begingroup$ Thanks for the response J. M! I've upvoted as the code works as required. $\endgroup$ – Mr S 100 Feb 21 '16 at 20:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.