Mathematica Stack Exchange is a question and answer site for users of Mathematica. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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!

share|improve this question
    
Related: (6916) – Mr.Wizard Mar 7 at 12:05
up vote 3 down vote accepted

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

share|improve this answer
    
Nice! (IOU one upvote.) – J. M. Feb 21 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. – Mr.Wizard Feb 21 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? – Mr S 100 Feb 21 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. – Mr.Wizard Feb 21 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. – Mr S 100 Feb 21 at 20:35

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.

share|improve this answer
    
I like this response as this is how I initially thought about approaching the problem - by essentially combining two results. Upvoted – Mr S 100 Feb 21 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]

enter image description here

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

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

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

share|improve this answer
    
Thanks for the response J. M! I've upvoted as the code works as required. – Mr S 100 Feb 21 at 20:36

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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