11

I was wondering if it is possible to use a custom Dynamic[var, function] inside a Manipulate. The reason for the need is this:

Suppose you have a time consuming computation like

timeConsuming[x_] := (Pause[1]; x)

and you want to use it in a Manipulate. Writing

DynamicModule[{y},
 Manipulate[
  y = timeConsuming[x]; {x, y, other},
  {x, 0, 1},
  {other, 0, 1}]
 ]

entails the following issue: you have to wait for timeConsuming to be computed even when you change other and leave x unmodified. A (simple) solution is to code the dynamic by hand:

DynamicModule[{x = 0, y = timeConsuming[0], other = 0},
 Panel@Column[{
    Grid[{
      {"x", Slider[Dynamic[x, (x = #; y = timeConsuming[x]) &], {0, 1}]},
      {"other", Slider[Dynamic[other], {0, 1}]}
      }],
    Dynamic@{x, y, other}
    }]
 ]

This is feasible, but as a drawback makes you renounce all other Module's conveniences.

I tried coding something like

Module[(* result *), {x, 0, 1, some-suitable-function}]

but had no success in the attempt. A (clean) use of Manipulate would be much appreciated.

Just to summarize, the question is: How can I make some statements be executed only when some specified controls are touched?

rm -rf
  • 88,781
  • 21
  • 293
  • 472
Federico
  • 2,553
  • 16
  • 16

3 Answers3

10

Is this what you're after?

timeConsuming[x_] := (Pause[1]; x);
DynamicModule[{y},
 Manipulate[y = timeConsuming[x]; {Dynamic@x, y, Dynamic@other},
  {x, 0, 1}, {other, 0, 1},
  SynchronousUpdating -> False]
 ]

SynchronousUpdating -> False keeps the front end from being blocked while timeConsuming is computing, and Dynamic lets different segments be updated. So x and other both update when the sliders are moved, and y is updated one second after x is.

Michael E2
  • 235,386
  • 17
  • 334
  • 747
5
  • It is straightforward to use Dynamic[var] in a Manipulate :

Simply insert Dynamic in the code !
This gives :

timeConsuming[x_] := (Pause[1]; x)

DynamicModule[{y},
Manipulate[
 y = timeConsuming[x]; {x, y, Dynamic[other]},
 {x, 0, 1},
 {other, 0, 1}]
 ]

You will see that this has exactly the effect you want : The slider other will respond immediatly.

This is documented in the "Advanced Manipulate Tutorial" (chapter "Using Dynamic inside Manipulate")

  • But if you want something like to use a Dynamic[var,function] in a Manipulate , I have no solution (presummatly it is useful).
andre314
  • 18,474
  • 1
  • 36
  • 69
  • Thank you very much for pointing that chapter out to me. For some reason i missed it. Anyway, I have never had the necessity to implement sophisticated dynamic construct, so my knowledge is very limited in this field. – Federico Mar 21 '13 at 00:52
2

I came up with a different solution, using Dynamic[var, function]:

customControl[Dynamic[x_], Dynamic[y_], b_, e_] :=
 Slider[Dynamic[x, (x = #; y = timeConsuming[x]) &], {b, e}]
Manipulate[
 {x, y, other},
 {{x, 0}, customControl[#1, Dynamic[y], 0, 1] &},
 {{y, timeConsuming[0]}, ControlType -> None},
 {other, 0, 1},
 SaveDefinitions -> True]

although it is still not completely clear to me why the wrapper Dynamic is required around y. As far as I can tell, its only purpose is to prevent y from being evaluated and make it retain its symbolic nature. Therefore, the same could be achieved by

customControl[Dynamic[x_], Hold[y_], b_, e_] :=
 Slider[Dynamic[x, (x = #; y = timeConsuming[x]) &], {b, e}]
Manipulate[
 {x, y, other},
 {{x, 0}, customControl[#1, Hold[y], 0, 1] &},
 {{y, timeConsuming[0]}, ControlType -> None},
 {other, 0, 1},
 SaveDefinitions -> True]
Federico
  • 2,553
  • 16
  • 16
  • This has a behavior similar to andre's: the update of x and y in the output and the x control have to wait until timeConsuming finishes. In mine both x and other respond immediately to their controls; only y has to wait. Any of them might be a desired solution to a given problem, but there is a difference. – Michael E2 Mar 21 '13 at 02:27
  • You're right about Dynamic vs. Hold. The main requirement is that the first argument has to match Dynamic[var], where var is the Manipulate variable, because that is what Manipulate will pass to your function. You could for instance start your definition customControl[_[x_], _[y_], b_, e_] := .. – Michael E2 Mar 21 '13 at 02:30
  • I just wonder why Manipulate does not pass the variable itself. It looks more versatile to me, because there is no "functional" way (at least that I know) to extract the variable from Dynamic[var] without recurring to an external definition and pattern matching, whereas one could prevent the evaluation of a naked passed variable with Unevaluated and HoldFirst. – Federico Mar 21 '13 at 02:52
  • Because the standard controls are defined like this: Slider[Dynamic[x],..] etc. And because x must be held, not evaluated, although there are other ways to do this. – Michael E2 Mar 21 '13 at 02:57