3
$\begingroup$

I'm trying to visualise the graph of a function $f(x,y)$ of two real variables using ContourPlot. Here are the things I'm after:

  • The points where $f(x,y)=0$ should be easily seen. This can be done with a separate ContourPlot of the form ContourPlot[f[x,y]==0,{x,x1,x2},{y,y1,y2}].

  • There should be a clear distinction between the areas where $f(x,y)>0$ and $f(x,y)<0$. For example, the positive areas will coloured in shades of green, and the negative ones with shades of red.

  • The plot should be symmetric with respect to the contour line $f(x,y)=0$. That is, if we're using different shades of green and red say, the points where $f(x,y)=10$ should have the same brightness as those where $f(x,y)=-10$.


To give an example, I'm not satisfied with the default

ContourPlot[y-x^2,{x,-5,5},{y,-5,5}]

since it's not easy to tell the positive and negative areas apart.

I would appreciate any help on this. Thanks!

$\endgroup$
  • $\begingroup$ You can use ColorFunctionScaling -> False, which means that the values of the function will be directly passed to the colour function, without rescaling. Then you can identify where 0 is, precisely. But you need to write your own colour function. For example, Show[ DensityPlot[y - x^2 == 0, {x, -5, 5}, {y, -3, 7}, ColorFunction -> (ColorData["ThermometerColors"][ 1/2 + ArcTan[.2 #]/Pi] &), ColorFunctionScaling -> False, PlotPoints -> 50], ContourPlot[y - x^2 == 0, {x, -5, 5}, {y, -3, 7}, ContourStyle -> Directive[Black, Dashed]] ] $\endgroup$ – Szabolcs Jul 14 '15 at 6:52
  • $\begingroup$ @Szabolcs Thanks! I'd like the transition from positive to negative to be sharper though, and also instead of the blue-red colors your picture has, use red-green respectively. Can this be done? $\endgroup$ – user1337 Jul 14 '15 at 7:00
  • $\begingroup$ You could use Rescale[] (@Szabolcs ;) ) along with maybe the "RedGreenSplit" gradient. $\endgroup$ – J. M. is away Jul 14 '15 at 7:05
  • $\begingroup$ @Guesswhoitis. I'm afraid I'm not fluent enough in Mathematica to use your comment. $\endgroup$ – user1337 Jul 14 '15 at 7:17
  • $\begingroup$ To add to @Szabolcs's suggestion, you can skip the generation of the separate ContourPlot[] by adding Mesh -> {{0}}, MeshFunctions -> {#3 &}, MeshStyle -> Directive[Black, Dashed]. user, Szabolcs here asked a question about Rescale[]; try looking for it under his profile. $\endgroup$ – J. M. is away Jul 14 '15 at 7:20
4
$\begingroup$

As I understand your requirements, the following should meet them.

ContourPlot[x y^2 + x^3, {x, -5, 5}, {y, -5, 5},
  Contours -> 15, 
  ColorFunction -> (If[# > .5, RGBColor[#, 0, 0], RGBColor[0, 1 - #, 0]] &)]

plot

$\endgroup$
  • $\begingroup$ Thank you! This seems to achieve what I'm after for this particular function. But if you use y-x^2 instead the change from green to red doesn't happen at the right contour. $\endgroup$ – user1337 Jul 14 '15 at 6:54
3
$\begingroup$

I'll use a Blend that is specified at three values, but you could use more.

With[{
  blend := 
   Blend[{{MinValue[{y - x^2, -5 < x < 5 && -5 < y < 5}, {x, y}], 
       Red}, {0, 
       Black}, {MaxValue[{y - x^2, -5 < x < 5 && -5 < y < 5}, {x, y}],
        Green}}, #] &},
 ContourPlot[y - x^2, {x, -5, 5}, {y, -5, 5}, ColorFunction -> blend, 
  ColorFunctionScaling -> False]
 ]

Out

Adding two more Blend value specifications to reduce the extend of the black area:

With[{
  blend := 
   Blend[{{MinValue[{x y^2 + x^3, -5 < x < 5 && -5 < y < 5}, {x, y}], 
       Red}, {-1, Darker[Red, 0.85]}, {0, 
       Black}, {MaxValue[{x y^2 + x^3, -5 < x < 5 && -5 < y < 5}, {x, 
         y}], Green}, {1, Darker[Green, 0.85]}}, #] &},
 ContourPlot[x y^2 + x^3, {x, -5, 5}, {y, -5, 5}, Contours -> 30, 
  ColorFunction -> blend, ColorFunctionScaling -> False]
 ]

Out2

As a function with symmetric coloring:

myCP[f_, {x_, xmin_, xmax_}, {y_, ymin_, ymax_}, opts : OptionsPattern[ListLogPlot]] := 
 Module[{minmax = 
    Max[-MinValue[{f, xmin < x < xmax && ymin < y < ymax}, {x, y}], 
     MaxValue[{f, xmin < x < xmax && ymin < y < ymax}, {x, y}]],
   blend},
  blend = Blend[{{-minmax, Red}, {-minmax/100, Darker[Red, 0.9]}, {0, Black}, 
   {minmax/100, Darker[Green, 0.9]}, {minmax, Green}}, #] &;
  ContourPlot[f, {x, xmin, xmax}, {y, ymin, ymax}, opts, 
   ColorFunction -> blend, ColorFunctionScaling -> False]]

myCP[y - x^2, {x, -5, 5}, {y, -5, 5}, Contours -> 20]

Out3

$\endgroup$
  • $\begingroup$ Thanks Karsten. However, I'd like the colors to be darker at lower values, and not the other way around. $\endgroup$ – user1337 Jul 14 '15 at 7:02
  • $\begingroup$ @user1337 like this one? $\endgroup$ – Karsten 7. Jul 14 '15 at 7:37
  • $\begingroup$ I'm not completely satisfied with the first plot, but the second looks great. I'm going to test it for different functions f soon. $\endgroup$ – user1337 Jul 14 '15 at 7:47

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.