# How to color the same contour line with different colors according y value

Here is an example:

ContourPlot[Sin[y - x^2] == 0, {x, -1, 1}, {y, -10, 10}]

Because all these separate lines come from the same contour line Sin[y - x^2] == 0, ColorFunction color the contour lines as the same color. This is the correct behavior for most contour plots. However, for this example, color the same contour line with different color make sense. How can I do it in Mathematica?

## Update

Let's make this question even more silly, because I actually have a figure must be draw part by part. Consider following code:

Show[{ContourPlot[Sin[y - x^2] == 0, {x, -2, 0}, {y, -10, 10}],
ContourPlot[Sin[-y - x^2] == 0, {x, 0, }, {y, -10, 10}]},
PlotRange -> All]

The question is the same, how to color the lines with different colors?

• Related: (70102) Jul 1, 2015 at 20:24

If it is acceptable to order the lines by the y value of the first point in each contour we can use a modification of Pickett's method:

plot = Show[{ContourPlot[Sin[y - x^2] == 0, {x, -1, 0}, {y, -10, 10}],
ContourPlot[Sin[-y - x^2] == 0, {x, 0, 1}, {y, -10, 10}]}, PlotRange -> All];

cols = {Red, Black, Blue, Orange, Green, Pink, Brown};

Normal[plot] /. {a___, l : Longest[Line[_] ..], b___} :>
{a, Riffle[cols, {l} ~SortBy~ Extract[{1, 1, 2}] ], b}

Or using xslittlegrass's restylePlot2 as the base method:

restyleWithSort[p_, op : OptionsPattern[ListLinePlot]] :=
ListLinePlot[Cases[Normal@p, Line[x__] :> x, ∞] ~SortBy~ Extract[{1, 2}],
op, Options[p]]

Show[restyleWithSort /@ {
ContourPlot[Sin[y - x^2] == 0, {x, -1, 0}, {y, -10, 10}],
ContourPlot[Sin[-y - x^2] == 0, {x, 0, 1}, {y, -10, 10}]
},
PlotRange -> All
]
• +1, using Normal to flatten out GraphicsComplex is new to me. Jun 19, 2015 at 4:05
• Change the x range to (-2,2), a continuous line will be colored to two different colors. Because, the lowest segment only appear in the left side. Jun 19, 2015 at 4:33
• @Kattern I anticipated such problems which is why I specifically wrote "If it is acceptable." This is a puzzle I haven't faced before (that I can recall) and I don't have a nice solution for it. Sorry. :-/ Jun 19, 2015 at 6:01
• @Mr.Wizard it is all right. You have already helped a lot. I can manage the special cases using Inkscape. Only 10% of the figures have the problem, it is about 10 figures. It is not hard to adjust them by hand. Thanks in advance! Jun 19, 2015 at 6:17
• @Kattern Do you know that you can edit line colors from within Mathematica as well? Perhaps I should have included that in my answer but I assumed you were looking for a programmatic solution. Jun 19, 2015 at 6:19

You can manipulate the expression manually:

plot = ContourPlot[
Sin[y - x^2] == 0, {x, -1, 1}, {y, -10, 10}
];

plot /. {a___, l : Longest[Line[_] ..], b___} :>
{a, Riffle[Array[ColorData[97], Length@{l}], {l}], b}

In order to find the pattern it helps to look at plot // FullForm. ColorData[97] is the list of default colors for Mathematica 10. Here is another answer I wrote two days ago, which also shows how this technique can be used.

• I will check the answer later. It seems I cannot get control of the color used in the lines, like Black for the lowest line, Red for the second. Jun 19, 2015 at 3:36
• @Kattern It seem that the contour lines are not produced in that order. In your application is it acceptable to perform a simple sort on them? Jun 19, 2015 at 3:42
• @Mr.Wizard Yes, I noticed that as well. And please also see the updated question. Jun 19, 2015 at 3:46
func[cplot_, cf_, s_] := With[{cp = cplot},
pt = cp[[1, 1]];
lines = Cases[cp, Line[x__] :> x, -1];
max = Max[#[[All, 2]]] & /@ (Part[pt, #] & /@ lines);
Show[Graphics[
GraphicsComplex[pt,
MapThread[{cf[Abs[Rescale[#1, {Min[max], Max[max]}] - s]], Thick,
Line[#2]} &, {max, lines}]], Frame -> True,
AspectRatio -> Full]]
]

For this example:

p1 = ContourPlot[Sin[y - x^2] == 0, {x, -1, 0}, {y, -10, 10}];
p2 = ContourPlot[Sin[-y - x^2] == 0, {x, 0, 1}, {y, -10, 10}];
Manipulate[
Show @@ (func[#, color, s] & /@ {p1, p2}), {{color,
Hue}, {Hue -> "Hue", ColorData["Rainbow"] -> "Rainbow",
ColorData["Pastel"] -> "Pastel"}}, {{s, 0, "invert"}, {0, 1}}]

• Woo, this one is pretty hard to understand. Jun 19, 2015 at 6:18
• @Kattern (i) I take each ContourPlot and decompose it into coordinates and contour lines (ii) in order to deal with gradient of colour varying with y, I take the maximum y for each line (which has 1-1 correspondence with line) and put in max (iii) I then use this (rescaled) as an argument for desired color function matched with line (iv) then recompose into GraphicsComplex (v) I then map to the separate plots and combine with Show. I prefer Mr. Wizard's answer, and have up voted it. Jun 19, 2015 at 6:23
• @Kattern this worked nicely for this example as the separation by y was very easy but more complex examples may require other better approaches...hope it allows you to play around and get what you want. Jun 19, 2015 at 6:26
• Thanks for your explanations! The (ii) and (iii) steps are not easy to understand. I will explore your code to understand the mechanism. Thanks again! Jun 19, 2015 at 6:29
• ...and upvoted Pickett's of course (as basis) Jun 19, 2015 at 6:38

Not sure if this will help in other examples but you can do it like this:

sol = (y /. Solve[Sin[x^2 - y] == 0, GeneratedParameters -> a] //
Normal) /. a -> (a &);
fun = Flatten@Table[sol, {a, -2, 1}];

p1 = Plot[fun, {x, -1, 0}, Axes -> False, Frame -> True,
PlotStyle -> Directive[Dashed, Thick]];
p2 = ContourPlot[Sin[y - x^2] == 0, {x, -1, 0}, {y, -10, 10},
ContourStyle -> Black];
Show[p2, p1]

• This one is nice if the analytical expression can be solve by Solve. NSolve in this case is not handy. Jun 19, 2015 at 7:03

## MeshStyle + MeshFunctions

colors = ColorData[97, "ColorList"][[;; 15]];

ContourPlot[x , {x, -1, 1}, {y, -10, 10},  Contours->{},
MeshFunctions -> {Sin[#2 - #^2] &}, Mesh -> {{0}},
MeshStyle -> ({Thick, First[colors = RotateRight[colors]], #} &),
BaseStyle->FaceForm[]]

OP's second example can be handled in the same way using a Piecewise mesh function with some adjustment to ensure continuity at 0:

ContourPlot[x , {x, -2, 2}, {y, -10, 10}, Contours -> {},
MeshFunctions -> {Piecewise[{{Sin[-#2]-Sin[#2]+Sin[#2 - #^2] , # <= 0},
{Sin[-#2 - #^2] , # >= 0}}]&}, Mesh -> {{0}},
MeshStyle -> ({Thick, First[colors = RotateRight[colors]], #} &),
BaseStyle -> FaceForm[]]