How to change the default ColorData used in Mathematica's Plot?
Update August 2014
The Legacy Solution below has been corrected to work in recent versions (9 and 10).
At the same time however the introduction of PlotTheme
functionality makes my solution largely academic as plot themes are designed to combine in the same manner. If no existing theme has the desired style you can create a custom one.
This example demonstrates setting new default plot colors as well a custom thickness and these correctly combining with the dashing directives in PlotStyle
:
System`PlotThemeDump`resolvePlotTheme["Thick5", "Plot"] :=
Themes`SetWeight[{"DefaultThickness" -> {AbsoluteThickness[5]}},
System`PlotThemeDump`$ComponentWeight]
SetOptions[Plot, PlotTheme -> {"DarkColor", "Thick5"}];
fns = Table[x^n, {n, 0, 5}];
dash = Table[AbsoluteDashing[i], {i, 1, 6}];
Plot[fns, {x, -1, 1}, PlotStyle -> dash]
Legacy Solution
The following updated solution is based on the existing solutions from Janus and belisarius with considerable extension and enhancement.
Supporting functions
ClearAll[toDirective, styleJoin]
toDirective[{ps__} | ps__] :=
Flatten[Directive @@ Flatten[{#}]] & /@ {ps}
styleJoin[style_, base_] :=
Module[{ps, n},
ps = toDirective /@ {PlotStyle /. Options[base], style};
ps = ps /. Automatic :> Sequence[];
n = LCM @@ Length /@ ps;
MapThread[Join, PadRight[#, n, #] & /@ ps]
]
Main function
pp
is the list of Plot functions you want to affect.
sh
is needed to handle pass-through plots like LogPlot
, LogLinearPlot
, DateListLogPlot
, etc.
pp = {Plot, ListPlot, ParametricPlot, ParametricPlot3D};
Unprotect /@ pp;
(#[a__, b : OptionsPattern[]] :=
Block[{$alsoPS = True, sh},
sh = Cases[{b}, ("MessagesHead" -> hd_) :> hd, {-2}, 1] /. {{z_} :> z, {} -> #};
With[{new = styleJoin[OptionValue[PlotStyle], sh]}, #[a, PlotStyle -> new, b]]
] /; ! TrueQ[$alsoPS];
DownValues[#] = RotateRight[DownValues@#]; (* fix for versions 9 and 10 *)
) & /@ pp;
Usage
Now different plot types may be individually styled as follows:
SetOptions[Plot, PlotStyle -> ColorData[3, "ColorList"]];
Or in groups (here using pp
defined above):
SetOptions[pp, PlotStyle -> ColorData[3, "ColorList"]];
Examples
PlotStyle
options are then automatically added:
fns = Table[x^n, {n, 0, 5}];
dash = Table[AbsoluteDashing[i], {i, 1, 6}];
Plot[fns, {x, -1, 1}, PlotStyle -> dash]
Plot[...]
and Plot[..., PlotStyle -> Automatic]
are consistent:
Plot[fns, {x, -1, 1}]
Plot[fns, {x, -1, 1}, PlotStyle -> Automatic]
Pass-through plots (those that call Plot
, ListPlot
or ParametricPlot
) can be given their own style:
SetOptions[LogPlot, PlotStyle -> ColorData[2, "ColorList"]];
LogPlot[{Tanh[x], Erf[x]}, {x, 1, 5}]
LogPlot[{Tanh[x], Erf[x]}, {x, 1, 5}, PlotStyle -> {{Dashed, Thick}}]
PlotStyle
handling can be extended to different Plot types.
I included ParametricPlot3D
above as an example:
fns = {1.16^v Cos[v](1 + Cos[u]), -1.16^v Sin[v](1 + Cos[u]), -2 1.16^v (1 + Sin[u])};
ParametricPlot3D[fns, {u, 0, 2 Pi}, {v, -15, 6},
Mesh -> None, PlotStyle -> Opacity[0.6], PlotRange -> All, PlotPoints -> 25]
Implementation note
As it stands, resetting SetOptions[..., PlotStyle -> Automatic]
will revert the colors to the original defaults. If this behavior is undesirable, the code can be modified to give a different default color, in the manner of Janus' also
function, upon which my styleJoin
is clearly based.
Here is one take on it -- the hard part was estimating how the PlotStyle
option is turned into a list of directives. I think this works as the internal implementation:
canonicalPlotStyle::usage =
"Turn a PlotStyle option into the canonical form {_Directive...}";
canonicalPlotStyle[ps_] := Replace[ps, {
a_List :> (Flatten[Directive @@ Flatten[{#}]] &) /@ a,
a_ :> {Flatten@Directive[a]}}]
Building on canonicalPlotStyle
it's now just a matter of combining two lists of unequal length:
also::usage =
"Combines a specified plotstyle with the current defaults as \
specified by Options.";
also[plotstyle_] := Module[{ps, n},
ps = canonicalPlotStyle /@ {
(PlotStyle /. Options[Plot]) /. Automatic :> ColorData[1, "ColorList"],
plotstyle};
n = LCM @@ (Length /@ ps);
Join @@@ Transpose[Flatten[Table[#, {n/Length[#]}], 1] & /@ ps ]]
This does require you to call the function when you plot, but I couldn't see any way around that part:
SetOptions[Plot, PlotStyle -> ColorData[3, "ColorList"]];
GraphicsRow[{Plot[fns, {x, -1, 1}],
Plot[fns, {x, -1, 1}, PlotStyle -> also@dash]}]
HTH
This is work in progress, I'm posting it because I'm not sure to be able to finish it, and perhaps someone wants to.
The idea is to combine the wonderful Janus's solution with this nice trick to redefine the Plot[ ] standard behavior.
The program below works for a large subset of the help page for Plot[ ], but fails for two or three. The code is not tidied up, just a draft with leftovers.
Unprotect[Plot];
Plot[argsANDopts___] :=
Block[
{$inMsg = True, result, also, canonicalPlotStyle, opts, args,
optPstyle},
If[(opts =
FilterRules[Cases[{argsANDopts}, _Rule], Options[Plot]]) == {},
opts = {Axes -> (Axes /. Options[Plot])}];(*Anything not null*)
args = Cases[{argsANDopts}, Except@_Rule];
If[(optPstyle = Cases[opts, Rule[PlotStyle, y__] :> y]) == {},
optPstyle = (PlotStyle /. Options[Plot])];
canonicalPlotStyle[ps_] :=
Replace[ps, {a_List :> (Flatten[Directive @@ Flatten[{#}]] &) /@
a, a_ :> {Flatten@Directive[a]}}];
also[plotstyle_] :=
Module[{ps, n},
ps = canonicalPlotStyle /@ {(PlotStyle /. Options[Plot]) /.
Automatic :> ColorData[1, "ColorList"], plotstyle};
n = LCM @@ (Length /@ ps);
Join @@@ Transpose[Flatten[Table[#, {n/Length[#]}], 1] & /@ ps]];
(*Print@opts;
Print@args;
Print@optPstyle;
Print@Evaluate@also[opts];*)
result = Plot[
Evaluate@Sequence@@args,
PlotStyle -> also[optPstyle],
Evaluate@Sequene@@opts
];
result
] /; ! TrueQ[$inMsg];
SetOptions[Plot, PlotStyle -> ColorData[3, "ColorList"]];
Protect[Plot];
samples:
Does not work for:
Plot[{Sin[x], Sin[2 x], Sin[3 x]}, {x, 0, 2 Pi},
PlotStyle -> {Red, Green, Blue}]