3

I've noticed that using the SaveDefinitions option of Manipulate makes it take a long time to evaluate.

For example, here is a notebook that uses Manipulate to show the frames from a gif (code below):

enter image description here

Code:

Clear["Global`"];
ims = Import["http://imgur.com/download/TbwMsiF"]; (* a 1MB gif *)
Length@ims
ByteCount[ims]

t0 = Now;
AbsoluteTiming[
 Manipulate[ims[[i]],
  {{i, 4, "frame"}, 1, Length@ims, 1, Appearance -> "Open"}]
 ]
t1 = Now;
t1 - t0

FileByteCount[NotebookFileName[]]

You can see that AbsoluteTiming claims the Manipulate call takes less than a millisecond, whereas our two calls to Now say it took half a second. Fine.

Adding SaveDefinitions makes it take almost 2 minutes, despite AbsoluteTiming claiming it ran in a millisecond (code below):

enter image description here

Code:

Clear["Global`"]; 
ims = Import["http://imgur.com/download/TbwMsiF"]; (* a 1MB gif *)
Length@ims
ByteCount[ims]

t0 = Now;
AbsoluteTiming[
 Manipulate[ims[[i]],
  {{i, 4, "frame"}, 1, Length@ims, 1, Appearance -> "Open"},
  SaveDefinitions -> True]
 ]
t1 = Now;
t1 - t0

FileByteCount[NotebookFileName[]]

I'm not sure what Manipulate is doing for those 2 minutes: you can see from the pic that the whole notebook is only 3 MB.

Question 1: Why does it take so long for SaveDefinitions to save the 50 frames of the gif into 3 MB?

Question 2: Is there a simple workaround for this?

I would really like to use SaveDefinitions to make the notebook self-contained, so that I don't have to re-run the notebook every time I open it.

(I'm aware that SaveDefinitions is dangerous [1, 2].)

ConvexMartian
  • 1,641
  • 11
  • 18

1 Answers1

3

Let me ignore the first question :)

This should work:

ims = Import["http://imgur.com/download/TbwMsiF"];

With[{ims = ims, l = Length@ims},
    Manipulate[
       ims2[[i]]
     , {{i, 4, "frame"}, 1, l, 1, Appearance -> "Open"}
     , {ims2, None}
     , Initialization :> (ims2 = ims)
     , UnsavedVariables :> {ims2}
    ]
]

So we inject images to Initialization and access it via localized variable ims2. UnsavedVariables prevents it to save it automatically, we don't need it saved twice.

What does None mean in a control specification for Manipulate?

How can I include functions from a package into a CDF file?

Kuba
  • 136,707
  • 13
  • 279
  • 740
  • Incredible, many thanks! What is the purpose of the outer With statement, and also the {ims2,None} argument? – ConvexMartian Jun 09 '17 at 13:23
  • @ConvexMartian added links. – Kuba Jun 09 '17 at 13:26
  • Kuba, thanks for the links. I'm still confused about the With[{ims=ims},...] idiom. In your second link, you say "We have to use With to inject source into DynamicModule's Initialization because Initialization is set with RuleDelayed which is HoldRest." I know what HoldRest means, but I don't know why it necessitates the With[{ims=ims},...]. I searched around but "mathematica With initialization idiom" doesn't return many useful results... – ConvexMartian Jun 09 '17 at 15:34
  • @ConvexMartian sorry for a delay please see 7758 – Kuba Jun 14 '17 at 13:40