6
$\begingroup$

While trying to analyse several different datasets I got what I thought was a good idea: define a "function" that returns a Manipulate object. But this has some problems when larger amounts of data are passed to Manipulate. When the code is first run there is long delay before the manipulate pane is displayed, because the the data gets embedded inside "Body" of Manipulate.

Here is a code snippet that illustrates the problem:

(*Generate some data*)
data = RandomVariate[BinormalDistribution[Abs@Random[]], {5, 10^4}];
histograms = DensityHistogram[#, 30, PerformanceGoal -> "Speed"] & /@ data;
images = Rasterize[#, ImageSize -> Medium] & /@ histograms;

AnalysePlots[plots_] := 
  Manipulate[plots[[i]], {i, 1, Length[plots], 1}];

(*Now compare:*)
t = AbsoluteTime[];
AnalysePlots[images] // AbsoluteTiming
AbsoluteTime[] - t
(* ==>3.7091792<---HERE IMAGES GET EMBEDDED*)

t = AbsoluteTime[];
Manipulate[images[[i]], {i, 1, Length[images], 1}] // AbsoluteTiming
AbsoluteTime[] - t

(* ==>0.0312500<---Here they don't*)

Can I somehow choose whether to embed the data (in this case the variable plots) into Manipulate?

When developing the function AnalysePlots it would be nice if I could do something like:

AnalysePlots[images, "Embed"->False]

which would have the benefit of displaying quickly. Then when I've finished AnalyzePlots I would deploy it with:

AnalysePlots[images, "Embed"->True]

which I could then copy and paste to a new notebook, deploy to CDF etc...

(I've already tried SaveDefinitions->False and UnsavedVariables :> {plots})

$\endgroup$
1
  • $\begingroup$ It is something to do with defining your Manipulates via functions. Because this starts very quickly: Manipulate[rasterizedSmall[[i]], {i, 1, Length[rasterizedSmall], 1}] $\endgroup$ May 23, 2012 at 22:46

2 Answers 2

2
$\begingroup$

This should do the trick:

SetAttributes[AnalysePlots, HoldFirst]

and if you want to embed the images use Evaluate:

AnalysePlots[Evaluate@images]
$\endgroup$
2
  • $\begingroup$ +1 This indeed works. Could you comment on why it works? $\endgroup$
    – Ajasja
    May 24, 2012 at 12:43
  • $\begingroup$ @Ajasja, without setting HoldFirst the symbol images gets evaluated by AnalysePlots, so the call to Manipulate is Manipulate[(**HUGE CHUNK OF DATA**)[[i]],.... Setting the HoldFirst attribute tells AnalysePlots to pass images[[i]] through to Manipulate unevaluated, so the call to Manipulate is Manipulate[images[[i]],..., just as it is when you call Manipulate directly in your second example. $\endgroup$ May 24, 2012 at 14:06
1
$\begingroup$

During lunch I had an inspiration: If SaveDefinitions-> False is not working on named argument patters of SetDelayed (probably due to special scoping), then perhaps it will work on variables defined using Module. So the following works OK:

Options[AnalysePlots] = Options[Manipulate];
AnalysePlots[plots_, opts : OptionsPattern[]] := 
 Module[{aplots = plots},
  Manipulate[aplots[[i]], {i, 1, Length[aplots], 1}, opts]]

(*Now compare:*)
t = AbsoluteTime[];
AnalysePlots[images, SaveDefinitions -> False] // AbsoluteTiming
AbsoluteTime[] - t
(* ==>0.025<---no images embedded*)

t = AbsoluteTime[];
Manipulate[images[[i]], {i, 1, Length[images], 1}] // AbsoluteTiming
AbsoluteTime[] - t

(* ==>0.39<---no images embedded*)

t = AbsoluteTime[];
AnalysePlots[images, SaveDefinitions -> True] // AbsoluteTiming
AbsoluteTime[] - t
(* ==>7.045<---HERE IMAGES GET EMBEDDED*)
$\endgroup$

Your Answer

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

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