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.

Is it possible to attach certain pieces of code to certain controls in a Manipulate? For example, consider the following Manipulate

Manipulate[
 data = Table[function[x], {x, -Pi*10, Pi*10, Pi/1000}];
 ListPlot[{x, data}, PlotRange -> {{start, stop}, Automatic}]
 , {function, {Sin, Cos, Tan}}
 , {start, 1, Length[data]}
 , {{stop, 300}, 1, Length[data]}
 ]

Generation of the data is expensive but it only needs to be done if I change function. So, I'd like the line

data = Table[function[x], {x, -Pi*10, Pi*10, Pi/1000}];

to only run when I change the function control...i.e. I want to attach that line of code to the 'function' control. As it stands, the data is generated when I move the plot range too which is not what I want.

enter image description here

share|improve this question
    
Does it need to be a Manipulate or are you fine with a DynamicModule? One option for Manipulate is to memoize it... –  rm -rf Oct 1 '13 at 15:48
    
DynamicModule would be fine. I'm just interested in the general principle. In real applications, the data is very expensive to compute and might be huge so memoization would be costly to say the least. –  WalkingRandomly Oct 1 '13 at 15:49

3 Answers 3

up vote 7 down vote accepted

In such cases, you can get better flexibility by switching to a DynamicModule and building up the GUI yourself. Then, you can pull the data generating step out of the plotting dynamic, so that the latter can be manipulated freely without regenerating the data.

DynamicModule[{function = Sin, start, stop = 300, x = Range[-10 Pi, 10 Pi, Pi/100]},
    Dynamic@With[{data = function[x], s = Spacer@10, f = Print@10},
        Panel@Column[{
            Row[{"function", s, Control[{function, {Sin, Cos, Tan}}]}],
            Row[{"start", s, Slider[Dynamic@start, {1, Length@data}]}],
            Row[{"stop", s, Slider[Dynamic@stop, {1, Length@data}]}],
            Dynamic@ListPlot[data, PlotRange -> {{start, stop}, Automatic}, 
                ImageSize -> 400, Background -> White]
        }]
    ]
]

Note that the f = Print@10 is there just to observe evaluation of data. You can check for yourself that nothing is printed when you move the sliders and prints only when the tabs are changed.

share|improve this answer

Here's a fairly simple way to fix your Manipulate by applying Dynamic to ListPlot.

Manipulate[
 (* Beep[]; *)
 data = function @ Range[-Pi*10., Pi*10, Pi/1000];
 Dynamic @ ListPlot[data, PlotRange -> {{start, stop}, Automatic}],
 {function, {Sin, Cos, Tan}},
 {start, 1, Length[data]},
 {{stop, 300}, 1, Length[data]},
 {data, ControlType -> None}]

Mathematica graphics

Uncomment Beep[] to hear when data is reevaluated.

There are several questions on this site whose answers discuss using Dynamic for such a purpose. This one is more general than most: Using Refresh[..] with TrackedSymbols

share|improve this answer

This is good reason to use the second argument of dynamics.

enter image description here

Manipulate[     
 function; (*just to allow tracking, since not explicity in the command*)     
 ListLinePlot[data, PlotRange -> {{start, stop}, Automatic}, 
  ImageSize -> 300, ImagePadding -> 30, Frame -> True, 
  FrameLabel -> {{None, None}, {"x", function}}
  ],

 Grid[
  {
   {"function", SetterBar[Dynamic[function, {function = #; 
        data = Table[function[x], {x, -Pi*10, Pi*10, Pi/10}]} &], {Sin, Cos, Tan}]
   },

   {"start", Manipulator[Dynamic[start, {start = #} &], {1, Dynamic@Length@data, 1}],
    Dynamic[start]
   },

   {"stop",Manipulator[Dynamic[stop, {stop = #} &], {300, Dynamic@Length@data, 1}], 
     Dynamic[stop]
   }       
   }],

 {{start, 1}, None},
 {{stop, 300}, None},
 {{data, Table[Sin[x], {x, -Pi*10, Pi*10, Pi/10}]}, None},
 {{function, Sin}, None},
 {{x, Symbol}, None},
 TrackedSymbols :> {function, start, stop}
 ]
share|improve this answer
    
Thanks Nasser. How did you record the little animation? –  WalkingRandomly Oct 2 '13 at 8:14
1  
@WalkingRandomly one way to make animation gif from Manipulate is using ManToGif[] command, community.wolfram.com/groups/-/m/t/86994 another way, is to do movie screen capture and save to animation GIF. For screen capture, on windows I use CamStudio, and to convert the AVI file from camStudio to animated gif, I use VirtualDub, all free software. –  Nasser Oct 3 '13 at 0:00

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.