14
$\begingroup$

I have a complex Manipulate-based demonstration containing a few sliders and a Setterbar.

I would like to make a movie out of it, avi, or whatever else. The movie will then be used for a journal publication as a Supporting material, so the quality should be good enough.

When the movie plays, the Setterbar should set its first value, then the sliders should move one after another, and then together. Further, the setter bar should set its second value and the slider manipulations should be repeated with this new Setterbar value. And so it should go for all Setterbar values. There will be something like 3-4 of them.

Is it possible at all?

To be more precise, I prepared a simplified demonstration with such controls:

    Manipulate[Plot[{Sin[a*x] + b*Cos[3 a*x], k*x}, {x, 0, \[Pi]}],
 {a, 1, 2}, {b, 0, 1}, {k, {0, 0.5, 1}}]
$\endgroup$
3
  • $\begingroup$ Using AutorunSequencing? $\endgroup$
    – Karsten7
    Commented Mar 9, 2015 at 10:08
  • $\begingroup$ @Karsten 7. It seems to be a step in the right direction, though I did not achieve the needed functioning yet. The Animate with AutorunSequencing exports as an avi file, but does not vary the Setterbar settings. It plays, however, if instead of the Setterbar I put a Slider. Could you kindly address this aspect, and formulate your comment as a regular answer? $\endgroup$ Commented Mar 9, 2015 at 10:23
  • $\begingroup$ I thank very much all of you. I like all the solutions, they even overcome my requirements. Therefore, I cannot really tell, which one is better. In this situation I choose to accept the one given first. Thank you all once more. $\endgroup$ Commented Mar 11, 2015 at 10:34

4 Answers 4

9
$\begingroup$

You can define a function that creates Manipulates with a "fake" SetterBar and a specific AutorunSequencing

m[k_, seq_] := Manipulate[
 Plot[{Sin[a*x] + b*Cos[3 a*x], k*x}, {x, 0, Pi}, ImageSize -> 400], 
 {a, 1, 2}, {b, 0, 1}, Grid@{{"k", SetterBar[k, {0, .5, 1}]}}, 
 AutorunSequencing -> seq, ContentSize -> {420, 270}]

then create the frames for the movie with

frames = Join @@ (ArrayPad[
    ImportString[ExportString[#, "AVI"], "ImageList"], {0, 3}, "Fixed"] & /@ 
  Flatten[Table[{m[k, {{1, 1}, {2, 1}}], m[k, {All, 2.85}]}, {k, 0, 1, 0.5}]]);

and export them as using

Export["D:\\animationTest.gif", frames]

SmotherAnimation

or

Export["D:\\animationTest.avi", frames]

Without a specified ContentSize exporting to "AVI" fails, as the size of the frames varies.

$\endgroup$
4
  • 1
    $\begingroup$ nice. Fyi, to export to animated gif file, there is a function by community.wolfram.com/groups/-/m/t/86994 Vitaliy Kaurov that simplifies this process. Called ManToGif $\endgroup$
    – Nasser
    Commented Mar 9, 2015 at 12:36
  • $\begingroup$ @Nasser Thanks for the link. Bookmarked it. $\endgroup$
    – Karsten7
    Commented Mar 9, 2015 at 12:44
  • $\begingroup$ @Karsten 7. Could you please explain, what is the purpose of padding? It seems to work also without it. $\endgroup$ Commented Mar 10, 2015 at 15:43
  • $\begingroup$ @AlexeiBoulbitch It works also without padding. I added it to make the change from one SetterBar value to another less abrupt. With the padding the movie is smoother as it adds a small pause between the changes for the SetterBar, similar to the small pause AutorunSequencing -> {1,2} produces between switching from one slider to the next. $\endgroup$
    – Karsten7
    Commented Mar 10, 2015 at 15:55
8
$\begingroup$

I wrote something to do something a little like what you wanted. Here I've adapted it so you can get a run through for each setting of the SetterBar. Some description of the functions.

autolist[control_pattern] := list of manipulate settings for the animation

specs is a pattern for culling variable specifications out of a Manipulate

rulefunction[variable_spec] yields a rule for injecting a setting into a Manipulate

steps[man, sequence, frames] creates an animation of the Manipulate code man by animating the controls in sequence by interpolating over a number of frames, which can be a list the number of frames for each control (in order of the controls). The argument sequence has the form

{{i11, i12,...}, {i22,...},...}

For each setting of the controls in the first list, the controls in the second list run through there settings and so forth (like the iterators of Table).

specs = HoldPattern[Manipulate[body_, stuff___]] :> 
   Cases[Hold[stuff], sp_List :> Hold[sp], {1}];

rulefunction[spec : {{var_, i_, label___}, __} | {var_, __}] :=
  HoldPattern[{_?(MemberQ[{#}, HoldPattern[var], 2] &), rest___}] :> {{var, #,
       label}, rest} &;

(*Manipulator*)
autolist[Hold[
    spec : {var_, min_?NumericQ, max_?NumericQ, opts : OptionsPattern[]}], 
   nFrames_: 20] := Module[{init},
   init = If[Head[var] === List, var[[2]], min];
   Map[
    rulefunction@spec,
    Interpolation[
      Transpose[{Range[0, 1, 
           1/(Length[#] - 1)], #}] &@(DeleteDuplicates[{init, max, min}]~
         Append~init),
      InterpolationOrder -> 1]@Rescale@N@Range@nFrames
    ]
   ];
(*SetterBar/PopupMenu*)
striplabels[data : {__Rule}] := First /@ data;
striplabels[data_] := data
autolist[Hold[spec : {var_, data_List, opts : OptionsPattern[]}], 
   nFrames_: 20] :=
  Map[
   rulefunction@spec,
   striplabels[
       data][[Clip[
        Round[Rescale[#, {0, 1}, {0.5, Length@data + 0.5}]], {1, 
         Length@data}]]] &@Rescale@N@Range@Ceiling[nFrames, Length@data] 
   ];
(*skip anything else - add more cases to handle other controls*)
autolist[__] := {};

Clear[steps];
steps[man_, seq : {__List}, frames_: 20] := 
  With[{specifications = (man /. specs)[[First[seq]]]},
   Table[steps[Replace[man, setting, 1], Rest[seq], frames], {setting, 
     Flatten[MapThread[
       autolist, {specifications, 
        If[Head[frames] === List, frames[[First[seq]]], 
         ConstantArray[frames, Length@specifications]]}]]}]
   ];
steps[man_, {}, ___] := man;

Export["1Example.gif", #] &@
 With[{man = 
    Manipulate[
     Plot[{Sin[a*x] + b*Cos[3 a*x], k*x}, {x, 0, \[Pi]}], {a, 1, 2}, {b, 0, 
      1}, {k, {0, 0.5, 1}}],
   frames = {20, 20, 3}},
  Module[{seq},
   seq = {{3}, {1, 2}};
   Flatten[
    steps[man, seq, frames],
    Length[seq] - 1]
   ]
  ]

enter image description here

$\endgroup$
7
$\begingroup$

This is just an idea how to prepare frames to export, don't have time for more now:

f = Interpolation[
  {
   {0, {1, 0, 0}},
   {1, {2, 0, 0}},
   {2, {2, 1, 0}},
   {2.02, {1, 0, .5}},
   {3, {1, 0, .5}},
   {4, {2, 0, .5}},
   {5, {2, 1, .5}},
   {5.02, {1, 0, 1}},
   {6, {1, 0, 1}},
   {7, {2, 0, 1}},
   {8, {2, 1, 1}}
   },
  InterpolationOrder -> 1];

ClearAll[expr, a, b, k];

expr := Plot[{Sin[a*x] + b*Cos[3 a*x], k*x}, {x, 0, \[Pi]}, 
   PlotRange -> {{0, Pi}, {-2, 2}}];

frames = Block[{a = #, b = #2, k = #3}, expr] & @@@  Array[f, 80, {0, 8}];

ListAnimate @ frames      (*Export["gif.gif", frames]*)

enter image description here

$\endgroup$
1
  • $\begingroup$ Thank you, this seems to be a rather close to what I had in mind. $\endgroup$ Commented Mar 9, 2015 at 10:27
7
$\begingroup$

The export to movie is easy. (just write p=Manipulate[..] then export p to movie.

Controlling the sequences as you want, I think have to be programmed in. Autorunsquences does not give one full control of all the scenario needed.

Here is the Manipulate you have. It runs in 2 modes. Automode, runs pre-programmed scenario. Click again, turn this off, so you can use the Manipulate as before (manually).

enter image description here

Manipulate[
 tick;
 Module[{p},
  p = Plot[{Sin[a*x] + b*Cos[3 a*x], k*x}, {x, 0, Pi},PlotRange ->{Automatic, {-3, 3}}];
  If[autoMode,
   Which[1 <= a <= 1.9, a += 0.1; tick = Not[tick],
    0 <= b <= .9, b += 0.1; tick = Not[tick],
    state == "ka", state = "kb"; a = 1; b = 0; k = 0.5; tick = Not[tick],
    state == "kb", state = "done"; k = 1; a = 1; b = 0; tick = Not[tick],
    True, autoMode = False
    ]
   ];
  p],
 Grid[{
   {"a", Manipulator[Dynamic[a, {a = #; tick = Not[tick]} &], {1, 2, .1}, 
      ImageSize -> Tiny], Dynamic[a]},
   {"b", Manipulator[Dynamic[b, {b = #; tick = Not[tick]} &], {0, 1, .1}, 
      ImageSize -> Tiny], Dynamic[b]},
   {"k", SetterBar[Dynamic[k, {k = #, tick = Not[tick]} &], {0, .5, 1}]},
   {Button["run auto mode", autoMode = Not[autoMode];
     If[autoMode, state = "ka"; a = 1; b = 0; k = 0; tick = Not[tick]]]}
   }],
 {{a, 1}, None},
 {{b, 0}, None},
 {{k, 0}, None},
 {{tick, False}, None},
 {{autoMode, False}, None},
 {{state, "ka"}, None},
 TrackedSymbols :> {tick}
 ]
$\endgroup$
1
  • $\begingroup$ I am afraid just exporting Manipulate produces the avi file that does not play. $\endgroup$ Commented Mar 9, 2015 at 10:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.