10
$\begingroup$

Is there a cleaner way to apply different styles to the different channels of a multi value interpolation function?

here is a 2-output interpolation function:

f = Interpolation[Table[ {x, N@{Sin[x], Cos[x]}}, {x, 0, 2 Pi, Pi/20}]]

if we just plot it the two functions take the same style

Plot[f[x], {x, 0, 2 Pi}, PlotStyle -> {Red, Blue}]

enter image description here

Here is one way to separately style:

Plot[{f[x][[1]], f[x][[2]]}, {x, 0, 2 Pi}, PlotStyle -> {Red, Green}]

enter image description here

This feels inefficient, apparently this computes both interpolations twice. I also cant figure an incantation to do this without explicitly listing..

Plot[Table[f[x][[i]], {i, 2}], {x, 0, 2 Pi}]

doesn't work.

We can crunch out a table and use ListPlot, but that seems unsatisfactory.

Is there a cleaner way?

$\endgroup$
  • $\begingroup$ I vaguely remember similar question where the answer was that Plot sees f[x] as a single object and therefore only recognizes one PlotStyle whereas Plot sees {f[x][[1]],f[x][[2]]} as two objects (as you've discovered). I wish I could remember but it wasn't that long ago and it had a good explanation of the issue. $\endgroup$ – JimB Nov 18 '16 at 21:50
  • 1
    $\begingroup$ just found this: mathematica.stackexchange.com/q/8637/2079 -- havent gone through to see if anything there works. $\endgroup$ – george2079 Nov 18 '16 at 21:58
  • 2
    $\begingroup$ Mr.Wizard's styleSplitter works as it stands. $\endgroup$ – corey979 Nov 18 '16 at 22:05
  • 1
    $\begingroup$ I can report this: mathematica.stackexchange.com/a/87113/2079 works. I dont think this is quite a duplicate since I hold out hope there is a cleaner method specific the the multi-value interpolation function. $\endgroup$ – george2079 Nov 18 '16 at 22:05
7
$\begingroup$

If the sampling is dense enough, as it usually is in NDSolve output, ListLinePlot will do style each curve separately.

ListLinePlot[f]

Mathematica graphics

ListLinePlot[f, PlotStyle -> {Red, Green}]

Mathematica graphics

$\endgroup$
  • 2
    $\begingroup$ nice.. the caveat here is ListLinePlot is effectively showing a linear interpolation regardless of the order of the input interpolation. Its also useful to know you can ListPlot this way and readily see the actual solution points coming from NDSolve. Stranegly this doesn't seem to be documented. $\endgroup$ – george2079 Nov 20 '16 at 21:00
  • $\begingroup$ @george2079 Yes, it's connect-the-dots, which is the reason for the condition, "If the sampling is dense enough." Perhaps, I should have been clearer. It can be an advantage over Plot, in terms of speed. BTW, ListLinePlot[.., Mesh -> All] will plot both the graph and the solution points. I don't remember where I learned this, but I use it a lot, most recently here. $\endgroup$ – Michael E2 Nov 20 '16 at 21:58
5
$\begingroup$

As already noted in the comments my styleSplitter will handle this, as will xslittlegrass's restylePlot2. If you are after the simplest possible method (least code) this is the best I can think of at the moment:

Plot[f[x], {x, 0, 2 Pi}] /.
  {d_, x__Line} :> {d, Riffle[{x}, {Red, Blue}, {1, -2, 2}]}

This could be hard-coded for only two Line expressions but Riffle is more general.


It occurs to me that you did not forbid modifying the InterpolatingFunction expression, therefore we could split that in two before plotting:

f1 = MapAt[First, f, {4, All, 1}];
f2 = MapAt[Last,  f, {4, All, 1}];

Plot[{f1[x], f2[x]}, {x, 0, 2 Pi}, PlotStyle -> {Red, Blue}]
$\endgroup$
4
$\begingroup$

In version 9.0, you can also use

Plot[f[x] , {x, 0, 2 Pi}, PlotStyle -> (i = 1; {{Red, Green}[[i++]], #} &)]

Mathematica graphics

$\endgroup$
  • $\begingroup$ i can confirm this doesn't work in 10..in fact v10 seems to not like any sort of function for PlotStyle $\endgroup$ – george2079 Nov 20 '16 at 21:05
3
$\begingroup$

Another way is as following: First, lets define a InterpolationFunction with n=30 curves.

    n = 30; f = 
    Interpolation[Table[{x, Table[x^j, {j, 1, n}]}, {x, 2, 5, 10^-3}]]

This LogPlot schows different colors.

    pl2 = LogPlot[
  Evaluate@Table[With[{i = i}, Hold[f[x][[i]]]], {i, n}], {x, 2, 5}, 
  PlotStyle -> Table[Hue[.8 j/n ], {j, 0, n - 1}]] // Timing

Although f has to be evaluated several times, it is even faster than the standard Plot.

    pl3 = LogPlot[f[x], {x, 2, 5}] // Timing

That means, time consumption for the solution pl2 can be neglected.

$\endgroup$
  • $\begingroup$ great.. this is effectively building up the list I wrote by hand in the question. Good to know how to do that! $\endgroup$ – george2079 Nov 20 '16 at 21:08

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.