5
$\begingroup$

Context

More often than not I end up doing plots one after the other so that I have a set of plots with the same colour style. When I want to make it more publishable ready, I would like to reassign colours to each line.

How to assign colours from a given style to existing sets of plots?

Example

pl1= Plot[Sin[x],{x,0,4Pi}];
pl2= Plot[Cos[2x],{x,0,4Pi}];
Show[pl1,pl2];

Mathematica graphics

Attempt

I while back I wrote the following function

Clear[ShowColor];
ShowColor[list___]:=ShowColor[{list}]/; Length[{list}]>1;
ShowColor[list_,ColorRange->color__,opt___]:= Module[{len=Length[list]},
     Table[list[[i]] /. RGBColor[_,_,_]->
          GradientColor[color][(i-1)/(len-1)],{i,len}]//Show[#,opt]&]
ShowColor[list_,opt___]:= Module[{len=Length[list]},
     Table[list[[i]] /. RGBColor[_,_,_]->
          GradientColor[ColorData[10] /@ Range[10]][(i-1)/(len-1)],{i,len}]//Show[#,opt]&]

which uses the GradientColor Package, so that

ShowColor[{pl1,pl2}]

produces

Mathematica graphics

But I am left with the impression that it could be done more elegantly and generally with the modern version of Mathematica, making use of the set of default styles and working in harmony with other features.

Also, my implementation is not very robust. For instance,

 Show[pl1, pl2] // ShowColor 

fails.

What would be great would be to have a function which e.g. would take standard Options such as

 ShowColor[plots,PlotStyle-> ColorData[10]]

or

  ShowColor[plots,PlotStyle-> Directive[{Dashed,Blue}]]

Any suggestion on how to make this as generic as possible?

Thanks!

$\endgroup$
  • $\begingroup$ you might find this interesting. $\endgroup$ – kglr Jul 1 at 17:08
  • $\begingroup$ thanks for the link $\endgroup$ – chris Jul 1 at 17:15
7
$\begingroup$

Using DLichti's ingenious idea / function from this q/a:

dLichtiIncrement[n0_Integer: 0, n1_Integer: 0, f_Function: Identity] := 
  Module[{N0 = n0, N1 = n1}, (If[# <= N1, N0 = N0 + N1]; N1 = #; f[N0 + #]) & ]

to define a function color which increments the color every time it is invoked as color[1]:

ClearAll[color, reColor]
color = dLichtiIncrement[(ColorData[97][#] &)];
reColor[] = # /. _?ColorQ :> color[1] &;
reColor[_] := Module[{}, ClearAll[color]; 
  color = dLichtiIncrement[(ColorData[97][#] &)]; reColor[]]

Examples:

pl1 = Plot[Sin[x], {x, 0, 4 Pi}];
pl2 = Plot[Cos[2 x], {x, 0, 4 Pi}];
Show[pl1, pl2]//reColor[]

enter image description here

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

enter image description here

Plot[{x Sin[x], x Cos[x], Sin[x Cos[x]]}, {x, 0, 2 Pi}, 
  PlotTheme -> "Monochrome", Filling -> Axis, FillingStyle -> Opacity[.5]] // reColor[]

enter image description here

ContourPlot[Evaluate[Sum[Sin[RandomReal[5, 2].{x, y}], {5}]], {x, 0, 5}, {y, 0, 5},
 PlotTheme -> "Monochrome"] // reColor[]

enter image description here

 ContourPlot[Cos[x] + Cos[y], {x, 0, 4 Pi}, {y, 0, 4 Pi},
    ContourShading -> False] // reColor[]

enter image description here

You can also use color[1] in setting ChartStyle/PlotStyle:

BarChart[{{1, 2, 3}, {1, 3, 2}}, ChartStyle -> Table[color[1], 3]]

enter image description here

Using reColor[blah] @ Red resets color[1] to its initial state:

 reColor[blah] @ Red == ColorData[97][1]

True

$\endgroup$
  • $\begingroup$ This is almost perfect: would it be possible to give reColor an argument to allow for the colours to reincrement from the beginning? I.e. plots//reColor[] would yield the same sets of colours ? $\endgroup$ – chris Jul 1 at 18:35
  • $\begingroup$ @chris, i made small changes to allow resetting: regular call is reColor[] and reColor[anything] resets color to its initial definition. $\endgroup$ – kglr Jul 1 at 19:28
  • 1
    $\begingroup$ Great ! I modified it slightly to choose the ColourTable: ClearAll[color, reColor] color = dLichtiIncrement[(ColorData[10][#] &)]; reColor[] = # /. _?ColorQ :> color[1] &; reColor[val_: 10] := Module[{}, ClearAll[color]; color = dLichtiIncrement[(ColorData[val][#] &)]; reColor[]] $\endgroup$ – chris Jul 1 at 20:08
  • $\begingroup$ The only remaining question is : are you nostalgic of the 70ies ? :-) $\endgroup$ – chris Jul 2 at 8:36
  • $\begingroup$ ... those were the days:) $\endgroup$ – kglr Jul 2 at 13:55
4
$\begingroup$

A simple way is to pass the coordinates in the plots to ListLinePlot.

recolor[plot_, opts___] := ListLinePlot[
  Cases[plot, Line[coords_] :> coords, Infinity],
  opts
  ]

Show[
 recolor[pl1, PlotStyle -> Directive[Blue, Dashed]],
 recolor[pl2, PlotStyle -> Red]
 ]

Mathematica graphics

It can also be used to recolor already combined plots:

recolor[
 Plot[{Sin[x], Cos[2 x]}, {x, 0, 4 Pi}],
 PlotStyle -> {
   Directive[Blue, Dashed],
   Red
   }]

Mathematica graphics

And it also works on this:

recolor[pl3=Show[pl1, pl2],
 PlotStyle -> {
   Directive[Blue, Dashed],
   Red
   }]

You can also use existing themes:

  recolor[pl3, PlotTheme -> "Detailed"]

Mathematica graphics

$\endgroup$
  • $\begingroup$ @chris that's always a good idea, you never know what someone might come up with. $\endgroup$ – C. E. Jul 1 at 16:56
  • 1
    $\begingroup$ Thanks again for your solution: I would have accepted both if I could. $\endgroup$ – chris Jul 2 at 13:58

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.