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.

I want to use Manipulate (I am open to other alternatives) to apply one of two different functions f or g to a set of values. The issue is that, I want to update the evaluation only when the user clicks on one of the button f or g. I came up with the following work around but I wonder if there is a better/standard way to implement such a thing?

Module[{val},
 Manipulate[
  val = Switch[op, "f", op = ""; f[x], "g", op = ""; g[x], "", val]; 
  val, {x, {1, 2, 3}, Setter}, {op, {"f", "g"}, Setter}, 
  TrackedSymbols -> {op}]
 ]

As a side question: is there any way to tell Manipulate to ignore the current evaluation and keep the last evaluated value?

share|improve this question
add comment

4 Answers

up vote 5 down vote accepted

While your solution works, I personally find it a bit off, since you are actually trying to have dynamic controls for a variable, who's state you immediately change away from the dynamic value just to use it to trigger an event. In short, you want to have one of two actions associated with the button presses, and could code this explicitly using a custom control, rather then indirectly implementing it in the guise of a dynamic controller with an added added event trigger somewhere else. Here is an example of a custom control implementing the events directly:

  Manipulate[
  val,
  {x, {1, 2, 3}, Setter},
  {{val, 0, "operator"}, 
           Row[{ Button["Call f", val = f[x]], 
                 Button["Call g", val = g[x]]}] &}
  ]

Here I added a new scoped variable since the spec for Manipulate needs to associate a variable with the custom control, even though it's not actually controlling any variable. If you wanted access to the operator that performed the last call, you could associate that variable with it.

share|improve this answer
    
+1 (although I would use DynamicModule instead of Module –  Ajasja Oct 15 '12 at 10:18
    
novar the Module variable is not the same as novar localized within Manipulate and is not needed. If you want val to be stored then it should be a DynamicModule. –  Mike Honeychurch Oct 15 '12 at 10:40
    
@MikeHoneychurch Thanks, I actually thought it was DynamicModule, I copied the original code without noticing. –  jVincent Oct 15 '12 at 10:48
1  
no worries but novar in the DM is still redundant. –  Mike Honeychurch Oct 15 '12 at 11:02
1  
@jVincent: one of the strongest advantages of using buttons as you do is that you could use Method->"Queued" for them which would make this work even when the evaluation of f or g would take long enough for an abort of the dynamic (which might be the case from what the OP mentioned in a comment). As novar is just a dummy variable, you could use val instead there and get rid of the DynamicModule: `Manipulate[val, {x, {1, 2, 3}, Setter}, {{val, "please click button...", "operator"}, Row[{Button["Call f", val = f[x]], Button["Call g", val = g[x]]}] &}] –  Albert Retey Oct 15 '12 at 12:06
show 3 more comments

Three variations using SetterBar, ButtonBar and Setters:

SetterBar:

Manipulate[op, {x, {1, 2, 3}, SetterBar}, 
 {{op, f[1], "op"}, {"f", "g"},SetterBar[Dynamic@op, {(f[x]) ->"f", (g[x]) ->"g"}] &}, 
    TrackedSymbols -> {op}]

ButtonBar:

 Manipulate[op, {x, {1, 2, 3}, SetterBar}, 
 {{op, f[1], "op"}, {"f", "g"}, ButtonBar[{"f" :> (op = f[x]), "g" :>(op = g[x])}] &}, 
   TrackedSymbols -> {op}]

Two Setters:

 Manipulate[op, {x, {1, 2, 3}, SetterBar},
  Row[{Control[{{op, f[1], "op"}, {}, Setter[Dynamic[op], f[x], "f"] &}],
       Control[{{op, g[1], ""}, {}, Setter[Dynamic[op], g[x], "g"] &}]}], 
  TrackedSymbols -> {op}]
share|improve this answer
    
I have mentioned the same thing for jVincents answer: the ButtonBar solution has the potential advantage over the Setter* solutions that it uses the Method->"Queued" option: that will prevent an early abort of the Manipulate when the evaluations of f and g take to long. This might be the case as the OP has mentioned somewhere that they are expensive... –  Albert Retey Oct 15 '12 at 12:28
    
@Albert, I was just playing with that variation for the same reasons, as a possible answer to this related question which exactly about that issue. –  kguler Oct 15 '12 at 12:36
add comment

@Mohsen. Here is a cleaned up version of your original Manipulate. The Module wrapper is eliminated by introducing val as an invisible control. This is a common and useful way to introduce addition dynamic variables into a Manipulate expression.

Manipulate[
 If[op != "",
   val = Switch[op,
           "f", f[x],
           "g", g[x]];
   op = ""];
 val,
 {val, ControlType -> None},
 {x, {1, 2, 3}, Setter},
 {op, {"f", "g"}, Setter},
 TrackedSymbols -> {op},
 Initialization :> (op = ""; val = "";)]  

It is also good to initialize op and val so that nothing is displayed until the first click is made on the "op" setter. With these minor changes your original approach is really quite valid.

share|improve this answer
    
Thank you! I didn't know about Initialization option. –  Mohsen Oct 16 '12 at 3:20
add comment

It looks like I misinterpreted what the OP wanted. So here is something that updates only when f or g is chosen. I've gone with DynamicModule because I find it more intuitive than Manipulate and stuck with the basic features of the OPs own implementation which will hopefully make it easy to follow.

DynamicModule[{op, x},

 Column[{
   SetterBar[Dynamic[x], {1, 2, 3}],
   SetterBar[Dynamic[op], {f, g}],
   Dynamic[op[x], TrackedSymbols :> {op}]

   }]
 ]

You can add control labelling, panes, backgrounds and so on but this is bare essentials.

share|improve this answer
    
This updates with every click; OP wants "to update the evaluation only when the user clicks on one of the buttons f or g". –  kguler Oct 15 '12 at 8:19
    
@Mike: This is not what I am looking for, indeed. I want to update the result only if one of f or g are clicked. Your approach may result in the same result in theory, but it is not so practical because f and g are CPU intensive and/or stateful (by stateful I mean a function which has side effect, so calling f twice is different from calling it once). Also, using Manipulate[op[x],{x, {1, 2, 3}, Setter},{op, {f, g}, Setter},TrackedSymbols->{op}] doesn't work. –  Mohsen Oct 15 '12 at 8:35
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.