# How to make a movie from a complex demonstration?

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}}]

-
– Karsten 7. Mar 9 '15 at 10:08
@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? – Alexei Boulbitch Mar 9 '15 at 10:23
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. – Alexei Boulbitch Mar 11 '15 at 10:34

## 4 Answers

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]


or

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


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

-
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 – Nasser Mar 9 '15 at 12:36
@Nasser Thanks for the link. Bookmarked it. – Karsten 7. Mar 9 '15 at 12:44
@Karsten 7. Could you please explain, what is the purpose of padding? It seems to work also without it. – Alexei Boulbitch Mar 10 '15 at 15:43
@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. – Karsten 7. Mar 10 '15 at 15:55

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]
]
]


-

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]*)


-
Thank you, this seems to be a rather close to what I had in mind. – Alexei Boulbitch Mar 9 '15 at 10:27

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).

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}
]

-
I am afraid just exporting Manipulate produces the avi file that does not play. – Alexei Boulbitch Mar 9 '15 at 10:56