Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

The following is a toy example that hopefully shows the problem clearly enough.

Why does the following code create a nice, manipulable output:

simulationOutput = {1337, 2337, 30, 3337};
Clear[tmax]
{irrelevantOutput1, irrelevantOutput2, tmax, irrelevantOutput3} = simulationOutput;
Manipulate[
 Plot[t^2, {t, startTime, endTime}], 
{startTime, Manipulator[Dynamic[startTime, (startTime = Min[tmax - 1, #]; 
       endTime = Max[endTime, Min[# + 1, tmax]]) &], {0, tmax}] &}, 
{endTime, Manipulator[Dynamic[endTime, (endTime = Max[1, #]; 
       startTime = Min[startTime, Max[0, # - 1]]) &], {0, tmax}] &}, 
 Initialization :> ({startTime, endTime} = {0, 1})]

enter image description here

But this (almost identical) code, with the additional Block[],

simulationOutput = {1337, 2337, 30, 3337};
Clear[tmax]
Block[{irrelevantOutput1, irrelevantOutput2, tmax, irrelevantOutput3},
  {irrelevantOutput1, irrelevantOutput2, tmax, irrelevantOutput3} = simulationOutput;
Manipulate[
 Plot[t^2, {t, startTime, endTime}], 
{startTime, Manipulator[Dynamic[startTime, (startTime = Min[tmax - 1, #]; 
       endTime = Max[endTime, Min[# + 1, tmax]]) &], {0, tmax}] &}, 
{endTime, Manipulator[Dynamic[endTime, (endTime = Max[1, #]; 
       startTime = Min[startTime, Max[0, # - 1]]) &], {0, tmax}] &}, 
 Initialization :> ({startTime, endTime} = {0, 1})]]

result in this, un-manipulate-able output?

enter image description here

If you're interested, the background behind my question is as follows. I have a simulation of a system of oscillators. The behavior of this system is then studied by providing initial conditions, then using NDSolve to find the behavior from t=0 to t=tmax. The output of the simulation (as simulationOutput) is then fed into a function (of which the following is a simplified example) so that I can see the results - this is the reason why I'm limiting the range of times in which the startTime and endTime can vary in to keep the values in the range of the InterpolatingFunction.

share|improve this question
add comment

1 Answer

up vote 5 down vote accepted

What Block does is to change the values of the existing global values for the time its body is evaluated. In your example because Manipulate has attributes HoldAll that means all arguments of the Manipulate don't evalute during evaluation of that Block's body and the Manipulate with unevaluated content is returned from the Block and sent to the FrontEnd for rendering.

Only in the process of rendering the Manipulate its content is sent from the FrontEnd to the Kernel for another evaluation and that then doesn't know anything about the Blocked values during the original evaluation anymore, which is why your code doesn't work as expected.

You can use Module instead of Block and everything will work as intended, at least as a first impression. But what you then do is to actually create new symbols with every call that will survive and will aggregate memory which might become a problem if that's done often. You could solve that by cleaning them up with a Deinitialization when the Manipulate is deleted, but that might have some issues (it's not exactly easy to understand if and when exactly such a deinitialization is executed, the documentation is vague and experiments don't help much to understand these details).

As long as the values of those local variables are small the best solution is to use DynamicModule (or additional Manipulate-variables without controlers) to store that data. If these values become large in memory size, you'll suffer from the extra effor of moving that data from Kernel to FrontEnd and back, though. Here is how that could look like:

Manipulate[
  Plot[t^2, {t, startTime, endTime}], 
  {
     startTime, 
     Manipulator[Dynamic[startTime,(
          startTime = Min[tmax - 1, #];
          endTime = Max[endTime, Min[# + 1, tmax]]
       ) &], {0, tmax}] &
   },{
     endTime, 
     Manipulator[Dynamic[endTime, (
         endTime = Max[1, #];
         startTime = Min[startTime, Max[0, # - 1]]
       ) &], {0, tmax}] &
   },
   {irrelevantOutput1, None},
   {irrelevantOutput2, None},
   {tmax, None},
   {irrelevantOutput3, None},
   Initialization :> (
     {startTime, endTime} = {0, 1};
     {irrelevantOutput1, irrelevantOutput2, tmax, irrelevantOutput3} = 
        simulationOutput;
    )
]

Unfortunately when working with Manipulate and Dynamic (and to some extent with any functionality that has an unusual evaluation order) the scoping constructs available need fairly much care to achieve what one wants without unexpected side effects...

share|improve this answer
    
+1 Nice explanation of a difficult question! –  Michael E2 Jun 14 '13 at 14:30
    
Just to clarify, I suppose by values of local variables being small or large, you mean their (memory) size? –  Michael E2 Jun 14 '13 at 14:34
    
@MichaelE2: yes, sure. I meant the memory size. I'll edit the answer. Thanks for the clarification... –  Albert Retey Jun 15 '13 at 10:38
    
@AlbertRetey - thank you! So, to clarify, if I want the performance to be as fast as possible, then I would still have to fall back on the first section of code, yes? –  Vincent Tjeng Jun 17 '13 at 2:07
    
@VincentTjeng: I only would search for another solution than DynamicModule if you really see that it is too slow. If it is and you can be reasonably sure it is the datatransfer between frontend and kernel causing it, I probably would use the Module approach. Another possibility would be to use "global" symbols e.g. in a specific Context (namespace) reserved for that purpose which I think is about as "local" as a local variable that leaks from a Module. Either way, you'll need to handle the cleanup manually to not leave behind symbols potentially containing large data... –  Albert Retey Jun 17 '13 at 21:37
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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