10

What are some approaches to integrate Ghost trails methods with Animate, which otherwise seem more suited for exporting individual frames?

For example, given this rootPlot function, how can trails be added and displayed as a dynamic alterative to RootLocusPlot?

Animate[rootPlot[(Range[0, 20, 3] // Map[x^# &] // Apply[Plus]) + 
    k x^3, x] // Show[{Graphics@{Gray, Circle[{0, 0}, 1]}, #},
    PlotRange -> 2 {{-1, 1}, {-1, 1}}, Axes -> True] &,
 {k, -50, 50, 1}]

enter image description here

alancalvitti
  • 15,143
  • 3
  • 27
  • 92

1 Answers1

14

It really helps others reading your code if you split things up and name parts of the code. Let's start with the polynomial.

polynomial[k_] := Total[x^Range[0, 20, 3]] + k x^3;

and the function that finds the roots, and the function that visualizes them

roots[poly_, x_] := roots[poly, x] = Through@*{Re, Im} /@ (x /. NSolve[poly, x])
frame[k_, opacity_] := ListPlot[
  roots[polynomial[k], x],
  PlotStyle -> Opacity[opacity]
  ]

And the background can also have its own name so that it is clearly distinguishable in the code.

background = Graphics[{
    Gray, Circle[{0, 0}, 1]
    },
   PlotRange -> 2 {{-1, 1}, {-1, 1}},
   Axes -> True
   ];

Now, a ghost trail is nothing but a plot that includes the current frame and the last lag number of frames, with each frame faded by age.

visualize[k_, lag_, {min_, max_}] := 
 visualize[k, lag, {min, max}] = Module[{mink, frames},
   mink = Max[min, k - lag];
   frames = frame[#, (# - mink)/(k - mink)] & /@ Range[mink, k];
   Show[background, Sequence @@ frames]
   ]

And so finally:

Animate[
 visualize[k, 10, {-50,50}],
 {k, -50, 50}
 ]

enter image description here

C. E.
  • 70,533
  • 6
  • 140
  • 264
  • And it helps copying the code if it is not riffled with text :P – Kuba Feb 26 '15 at 09:13
  • @Kuba I know, but I think my reasons for sacrificing copyability are sound. – C. E. Feb 26 '15 at 11:13
  • 1
    Maybe text as comment in code block is a good idea? I don't know, I'm just thinking about general approach because often when I have to do multiple copy+paste I just skip that :P – Kuba Feb 26 '15 at 11:16
  • 2
    @Kuba But then, you wouldn't have the joy of writing code to extract the code. :) code=StringJoin[Cases[First[Cases[Import["http://mathematica.stackexchange.com/questions/75936/ghost-trails-with-animate","XMLObject"], XMLElement["td", {_, _, "class" -> "answercell"}, ___],Infinity]],XMLElement["pre", {}, {XMLElement["code", _, {code_}]}] :> code, Infinity]] – Mark McClure Feb 26 '15 at 13:44
  • Sadly, the Import code I just wrote doesn't seem to survive a copy from the comment box. Hopefully, you get the idea. – Mark McClure Feb 26 '15 at 14:10
  • @MarkMcClure I do, very nice! Try StringJoin[ Cases[First[ Cases[Import[ "http://mathematica.stackexchange.com/a/75941/5478", "XMLObject"], XMLElement["td", {_, _, "class" -> "answercell"}, ___], Infinity]], XMLElement["pre", {}, {XMLElement["code", _, {code_}]}] :> code, Infinity]] // MathLink`CallFrontEnd[ FrontEnd`UndocumentedTestFEParserPacket[#, True]] & // Cell[#[[1]], "Input"] & // CellPrint – Kuba Feb 26 '15 at 14:40
  • @Kuba Neat! I never noticed a function that actually declares itself as undocumented in its name before. I'm curious - how did you avoid the problem that I had with the misbehaving invisible characters after copy/paste? It looks like you used 4 space indentation; maybe that's it? My code was inline. – Mark McClure Feb 26 '15 at 14:56
  • 1
    @MarkMcClure Maybe it is OS specific. Your code worked as it is for me. UndocumentedTestFEParserPacket – Kuba Feb 26 '15 at 15:02
  • @Kuba. I don't think interspersing text with code adds any significant difficulty to copying the code. – m_goldberg Feb 26 '15 at 16:37
  • Pickett, this is nice, thanks. – alancalvitti Feb 27 '15 at 20:33