13
$\begingroup$

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

$\endgroup$
2
  • $\begingroup$ Does it need to be a Manipulate or are you fine with a DynamicModule? One option for Manipulate is to memoize it... $\endgroup$
    – rm -rf
    Oct 1, 2013 at 15:48
  • $\begingroup$ 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. $\endgroup$ Oct 1, 2013 at 15:49

3 Answers 3

9
$\begingroup$

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.

$\endgroup$
13
$\begingroup$

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

$\endgroup$
7
$\begingroup$

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}
 ]
$\endgroup$
2
  • $\begingroup$ Thanks Nasser. How did you record the little animation? $\endgroup$ Oct 2, 2013 at 8:14
  • 1
    $\begingroup$ @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. $\endgroup$
    – Nasser
    Oct 3, 2013 at 0:00

Your Answer

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

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