6

I can't get the syntax to do what I want, and I am now not sure if it is even possible.

small review: One can do this:

{Slider[Dynamic[b], {-2 Pi, 2 Pi}], Dynamic[Sin[b]]}

and now each time the slider moves, 'b' changes, and its Sin[] is automatically printed

enter image description here

But suppose I want to do the computation (Sin[]) directly where the slider is and only show the final result of Sin[], then I can use the second argument of Dynamic like this:

{Slider[Dynamic[b, (b = #; a = Sin[b]; #) &], {-2 Pi, 2 Pi}], 
 Dynamic[a]}

enter image description here

Now I want to use Manipulate, and do the same thing. I can do the same as the first example above like this:

Manipulate[
 Sin[b],
 Control[{{b, 0, "b="}, -2 Pi, 2 Pi, ControlType -> Slider}]
 ]

enter image description here

In the above, Manipulate took care of the 'Dynamic' stuff, and updated Sin[b] whenever 'b' changes.

Now, I want to see if I can do the second case using Manipulate, so I can write:

Manipulate[
 a,
 Control[{{b, 0, "b="}, -2 Pi, 2 Pi, ControlType -> Slider}] (*where to insert Sin[b]?*)
 ]

('a' has to initialized to some value for initial display).

But I am not able to figure how to use the second argument for 'b' in the above. Can't figure the syntax, and now sure if it possible?

of course, one can't just write

Manipulate[
 a,
 {Slider[Dynamic[b, (b = #; a = Sin[b]; #) &], {-2 Pi, 2 Pi}]}
 ]

This is not even valid syntax of Manipulate controls.

Question is: Is it possible to use second argument of Dynamic in setting up Manipulate controls?

The reason I am asking, is that it could make it easier to 'localize' computation right there, where the control variable changes, and only show the final result elsewhere. Like a local callback function in a way, where computation related to changes for each control sits right next to where the control is.

thanks

Update 9/16/11

Well, after a month of struggle, finally I have the Mathematica CDF up and running.

Thanks to the help of the trick shown here by Simon, and others who answered my questions while I was doing this CDF (Leonid, Heike, WReach, Belisarius and others).

The few tricks I learned here helped finish this demonstration, here is a link if someone wants to try it.

enter image description here

The design of this CDF is different from everything I've done before. It is based on finite state machine. There is only ONE tracked symbol in the whole CDF. Using the second argument of dynamics, the event name is recorded, and in the main expression of Manipulate, which runs the finite state machines, it has 5 states it can be in, and there are 8 events. Depending on the current state and the current event that just happened, it switches to new state (or can stay in the same state, depending), and the main display is updated. No trigger needed. The state machine runs as fast as you allow it, controlled only by the time step size.

This simplifies the logic greatly, and makes it possible to handle make much more advanced UI and inter-dependent logic, since everything now runs in a well controlled way, and all the logic is in one place.

Without being able to set the event using the second argument of dynamics, this whole approach would not have been possible.

I need to write a note on this method to make it more clear.

So, just wanted to thank everyone here. I am now finishing another CDF using this method, a triple pendulum simulation.

Nasser
  • 12,849
  • 6
  • 52
  • 104
  • Wow, the final result looks really nice! Runs slow on my machine, but most things do... It would be nice if you could provide a download link for those who can not use the browser plugin. – Simon Sep 17 '11 at 08:39
  • 1
    @Simon, I just added 2 links there for the CDF and the notebook itself. http://12000.org/my_notes/mma_demos/simple_pendulum_damped_driven/index.htm it runs as fast as it can, there is no clock, other than the Dynamic that is tracked. – Nasser Sep 17 '11 at 08:53
  • I have better idea now on the 'slowness' issue. When more stuff is displayed, the update to the screen starts to take more time, and the whole loop slows down, waiting for screen to be painted each time. Getting higher fps has been a problem for me with CDF demos. I do not know if there are tricks to make this more efficient or not. But it definitely seems to be due to this. When I reduce the number of graphics/plots to display, the simulation runs faster. No clock is used, just a loop with Show[Graphics[..]] in it. Latest CDF I just finished showed this issue very clearly. – Nasser Sep 19 '11 at 11:09

1 Answers1

8

Not all of the arguments of Manipulate after the first one have to be Control objects. You can put anything you like there - including completely customized dynamic controls. So, how about something like

Manipulate[a, {a, None}, {b, None}, 
 Row[{"b= ",Slider[Dynamic[b, (b = #; a = Sin[b]; #)&], {-2 Pi, 2 Pi}]}]]

Where the {a, None} and {b, None} ensure that the variables are local, but aren't strictly necessary.

Simon
  • 14,631
  • 4
  • 41
  • 101
  • Nice trick Simon! This opens new possibilities :). Btw, I do not know why you added Dynamic before Row above. It works without it, like this: Row[{"b= ", Slider[Dynamic[b, (b = #; a = Sin[b]; #) &], {-2 Pi, 2 Pi}]}], the extra Dynamic does not seem to be needed. Thanks again! – Nasser Sep 07 '11 at 06:51
  • @Nasser: Thanks, I've removed that extraneous `Dynamic`. – Simon Sep 07 '11 at 07:10
  • I have been trying this method, and it is working very well. I simplified the logic a lot. Now, I have a state machine in the Manipulate expression, and I can change the state whenever any control changes easily. Before I had to use complicated Dynamic/Refresh code all over the place for each control, or set of controls, to detect when a control changes. But now I can simply switch the state right there very simply without using Dynamic[Refresh[..]] in the main Manipulate Expression. Using Which[] in the Manipulate main expression, I always know which state I am in. – Nasser Sep 07 '11 at 19:09