# Speed up manipulate by exporting each step as an image

Consider a manipulate function such as:

Manipulate[
per = 12.34;
pdata = Table[Sin[2 \[Pi] x/per], {x, n}] + RandomReal[.1, {n}];
ListPlot[pdata], {n, 100, 200, 10}]


which takes some time to re-evaluate each step of its manipulation. I would like to export each step of the manipulation as an image (rasterized or otherwise) & then create a manipulation that simply scrolls though the images, allowing it to run smoothly and quickly. Is there a way to automate something like this?

(NB The code I am working with takes far longer to re-evaluate each step that the example code above, but it works with much the same idea.)

-

You can create the images with

images = Image[
ListPlot[
pdata = Table[Sin[2 \[Pi] x/12.34], {x, #}] +
RandomReal[.1, {#}]]] & /@ Table[i, {i, 100, 200, 10}];


and show them with

Manipulate[images[[n]], {n, 1, Length[images], 1}]


then you can export them with

Export[NotebookDirectory[] <> "image" <> ToString[#] <> ".tif", Image[images[[#]]]] & /@ Range[Length[images]]


later on (i.e. in another notebook residing in the same directory) you simply load the images into a list and view them with

Manipulate[images[[n]], {n, 1, Length[images], 1}]

-
@ Kardashev3, again, many thanks - but please see update. –  martin Nov 10 '13 at 12:35
@ Kardashev3, Great! Many thanks - I will now try to implement it in the code I am working with (... could be a long time!) :) –  martin Nov 10 '13 at 12:57
@ Kardashev3, Many thanks for your update - I was about to ask you about exporting them! –  martin Nov 10 '13 at 13:00
@ Kardashev3, I suppose this answers my other question also, as it should be fairly straightforward to use Show to overlay all exported images (if exported in eps, pdf format,etc.):) –  martin Nov 10 '13 at 13:02
@martin: You have to produce plots with the same plot range (in your example the maximum plot range of 200) in order to correctly show all points altogether. I have updated my answer with the respective options, see mathematica.stackexchange.com/questions/36725/…. –  Kardashev3 Nov 10 '13 at 13:43

In this case memoization can be used. It can often be used for cases like this.

pdata[n_, per_] := pdata[n, per] = Table[Sin[2 \[Pi] x/per], {x, n}] + RandomReal[.1, {n}];


Makes sure pdata never performs the same calculation twice. If we calculate all relevant values in advance,

Do[pdata[n, 12.34], {n, 100, 200, 10}]


They will already be stored when you run Manipulate:

Manipulate[
per = 12.34;
ListPlot[pdata[n, per]], {n, 100, 200, 10}]

-
@ Anon, Thanks for your answer - I will try out both approaches & see which is most efficient ;) –  martin Nov 10 '13 at 13:06
@martin If you want to see it used to improve speed in a manipulate with somewhat heavy calculations, you may want to take a look at this: mathematica.stackexchange.com/a/34857/731 –  Pickett Nov 10 '13 at 13:09
@ Anon, Wow! That is quick! My only worry is that Mathematica would have to go through the evaluation process every time the file is reopened - could this be avoided? Or is it better to export all images? –  martin Nov 10 '13 at 13:12
@ Anon, Perhaps I am missing the point - I will have to experiment with it to understand more fully what you mean, I think... –  martin Nov 10 '13 at 13:18
@martin Execute Clear[pdata] before the definition of pdata[n_, per_] := .... Your old pdata definition is probably hanging around. –  Michael E2 Nov 10 '13 at 15:00

An alternative to saving images is to save the graphics themselves with DumpSave.

per = 12.34;
myPlots =
Table[ListPlot[Table[Sin[2 \[Pi] x/per], {x, i}] + RandomReal[.1, {i}]],
{i, 100, 200, 10}];
DumpSave[FileNameJoin[{NotebookDirectory[], "foo.mx"}], myPlots];

Manipulate[
Show[myPlots[[i]], Framed -> True],
{i, 1, Dynamic @ Length @ myPlots, 1},
Initialization :> (Get[FileNameJoin[{NotebookDirectory[], "foo.mx"}]])]


One can alter the options to the Graphics, such as adding a frame, and interact with the output as Graphics. This can't be done with images, at least in the same way.

Another alternative that is more self-contained is below. It auto-generates the plots and the .mx file if the file is missing. Of course that takes time, but the notebook file containing the Manipulate can be sent alone and the Manipulate output can be copied and pasted into another notebook, which might be in a different directory or in no directory at all. This means that the notebook can be shared with or without the accompanying .mx file.

If there is no .mx file, then the Manipulate pauses while all the plots are generated. This is accomplished by the combination of

SynchronousInitialization -> False,


and the line in the Initialization:

Do[plot[nn], {nn, 100, 200, 10}]


(This line may be omitted, but there will be a wait each time a plot is displayed for the first time. Once all the plots have been generated, the Manipulate will operate smoothly.)

The plots are generated and stored via memoization, as in Anon's answer, and the definitions create are save by DumpSave in the Deinitialization. It's not absolutely foolproof, e.g. Mathematica crashes, or a user executes Clear[plot].

Manipulate[
Show[plot[n], Frame -> True],

{n, 100, 200, 10}, {directory, None},

SynchronousInitialization -> False,
Initialization :> (
directory = Quiet@Check[NotebookDirectory[], \$TemporaryDirectory];
per = 12.34;
Quiet@Get[FileNameJoin[{directory, "foo2.mx"}]];
(* this would have been loaded from the .mx ... unless there's no .mx file *)
plot[n_] := plot[n] =
ListPlot[Pause[0.5]; Table[Sin[2 Pi x/per], {x, n}] + RandomReal[.1, {n}]];
(* fast if plot is loaded from .mx; otherwise predefines all the plots *)
Do[plot[nn], {nn, 100, 200, 10}]
),
Deinitialization :> DumpSave[FileNameJoin[{directory, "foo2.mx"}], plot]
]

-