22
$\begingroup$

This is a very basic question, but I don't understand the following behavior. The usage to Refresh reads

represents an object whose value in a Dynamic should be refreshed at times specified by the options opts.

Although the word times was mentioned explicitly the examples suggest, that Refresh can also be used to restrict the TrackedSymbols in an expression inside Dynamic. Here is a basic example from the help, which works like a charm

Manipulate[
 {x, Refresh[y, TrackedSymbols :> {x}]},
 {x, 0, 1},
 {y, 0, 1}
]

Mathematica graphics

When you move the y-slider, nothing happens because the second expression containing y is restricted to keep only track of x. When you then move x, the y values jumps to it's current value.

Now, let's extend this example a bit

Manipulate[
 {Refresh[{x, y}, TrackedSymbols :> {y}], 
  Refresh[{x, y}, TrackedSymbols :> {x}]},
 {x, 0, 1},
 {y, 0, 1}
]

What I had hoped for was, that when I move the x-slider, only the x-value in the second {x,y} is updated because the first {x,y} tracks only y. Equivalent for the y-slider. Unfortunately, all values are always updated.

Solutions to this is can be found at the end of the post, but first my question:

Can someone explain what I have missed in the documentation of Refresh and how this is supposed to be used?

Several solutions to the toy-example can be found. The most prominent one is to wrap each Refresh in Dynamic

Manipulate[{
  Dynamic@Refresh[{x, y}, TrackedSymbols :> {y}], 
  Dynamic@Refresh[{x, y}, TrackedSymbols :> {x}]}, 
  {x, 0, 1}, 
  {y, 0, 1}
]

This goes along with the suggestion of andre's answer, when I understood him right.

Further solutions are

Manipulate[
 {Dynamic[{x, y}, TrackedSymbols :> {y}], 
  Dynamic[{x, y}, TrackedSymbols :> {x}]},
 {x, 0, 1},
 {y, 0, 1}
]

DynamicModule[{},
 Column@{Dynamic[{x, y}, TrackedSymbols :> {y}], 
   Dynamic[{x, y}, TrackedSymbols :> {x}],
   Slider[Dynamic[x]],
   Slider[Dynamic[y]]
}]


DynamicModule[{},
 Column@{Dynamic@Refresh[{x, y}, TrackedSymbols :> {y}], 
   Dynamic@Refresh[{x, y}, TrackedSymbols :> {x}],
   Slider[Dynamic[x]],
   Slider[Dynamic[y]]
}]

This leaves the question, when I have to use Dynamic anyway, why does the documentation suggest Refresh can do this alone. I still think I'm missing something.

$\endgroup$
0

3 Answers 3

23
$\begingroup$

I think I have to explain how I look at Dynamic before I can speak about Refresh.

Dynamic is the basic element of dynamic updating, and the only one as far as I can tell. Anything that behaves dynamically has Dynamic somewhere inside it, I believe.

If you think of an expression as a tree, then Dynamic[code] marks out the branch representing code for dynamic updating. An update can occur only if code evaluates to something visible in the front end. The whole branch will be reevaluated when an update occurs -- even the invisible parts if code is, say, a CompoundExpression.

By default, an update occurs any time one or more of the symbols in code changes value. Refresh can be used to restrict when updating occurs through the TrackedSymbols option. (It can also cause updates that depend only on time through the UpdateInterval option.) TrackedSymbols does not make an expression depend on symbols it does not contain; rather, the dependence will be on the intersection of the symbols in code and in the TrackedSymbols list.

Refresh always needs a surrounding Dynamic for updates to occur. Manipulate does this automatically, so Refresh by itself inside a Manipulate will have an effect. See, for instance, Advanced Manipulate Functionality:

In reading those, keep in mind that Manipulate simply wraps its first argument in Dynamic and passes the value of its TrackedSymbols option to a Refresh inside that.

See also the section on Refresh in Advanced Dynamic Functionality. These expand the cryptic explanation from the manual page:

When Refresh[expr,opts] is evaluated inside a Dynamic, it gives the current value of expr, then specifies criteria for when the Dynamic should be updated.


As a first example, consider

DynamicModule[{x, y},
 Column[{
   {x,
    Dynamic[{x,
      Dynamic@Refresh[{x, y}, TrackedSymbols :> {y}]}],
    Dynamic@Refresh[{x, y}, TrackedSymbols :> {y}]},

   Slider[Dynamic[x]],
   Slider[Dynamic[y]]
   }]
 ]

The main expression to consider is

{x, 
 Dynamic[{x,
   Dynamic[{x, y}, TrackedSymbols :> {y}]}], 
 Dynamic[{x, y}, TrackedSymbols :> {y}]}

Note that two of the subexpressions look the same. I might represent it as a tree thus:

Tree diagram of the code show the dynamic sub-branches

The frames on the branches represent Dynamic wrappers, and the tracked symbols are in the upper left corner.

When the slider for x is moved, dynamic expressions depending on x are reevaluated (in the kernel) and updated (in the front end). Only the middle one is dynamic and depends on x. The first x is never even initialized (see note* below), and it never changes.

When the slider for y is moved, dynamic expressions depending on y are reevaluated and updated. These are the last two. The middle one has an interior Dynamic that depends on y (only), which would seem to make the whole middle Dynamic depend on y, too; however, it is wrapped in Dynamic so changes to y only affect that branch. (Mathematica will updated the smallest branch necessary.) [Thanks to @andre for pointing out a mistake in the previous explanation.]

There is a curious difference between the middle and last expressions. The two Dynamic@Refresh.. expressions look identical but they do not behave the same. When x is changed, the one inside the middle updates its display, but the one at the end does not. The reason is the outer Dynamic in the middle depends on x. It reevaluates its expression when x changes, including evaluating the Dynamic@Refresh that is a part of the expression.

(*In fact, the first x is never even mapped to a front end context symbol, something like FE`x$$14. It displays as simply x$$. The other x in the expression are in a Dynamic and they get renamed to something like FE`x$$14. Try DynamicModule[{x, y}, {x, Dynamic[Hold[x]]}] and see.)


Analysis of a couple of @halirutan's examples.

A. This one

Manipulate[
 {x, Refresh[y, TrackedSymbols :> {x}]},
 {x, 0, 1}, {y, 0, 1}]

is equivalent to

Dynamic@Refresh[{x, Refresh[y, TrackedSymbols :> {x}]}, 
  TrackedSymbols :> {x, y}]

The main expression, {x,Refresh[y,TrackedSymbols:>{x}]}, depends only on x: Refresh limits the expression y to depend on the symbols in the tracked symbols list that occur in the expression. So it can depend only on x, but no x appears in y. Therefore the Refresh does not depend on any symbol and will not generate an update. In all then, the main expression depends only on x.

So it is not updated when y changes, only when x changes.

B. And this one

Manipulate[
 {Refresh[{x, y}, TrackedSymbols :> {y}],
  Refresh[{x, y}, TrackedSymbols :> {x}]},
 {x, 0, 1}, {y, 0, 1}]

is equivalent to

Dynamic@Refresh[
  {Refresh[{x, y}, TrackedSymbols :> {y}],
   Refresh[{x, y}, TrackedSymbols :> {x}]},
  TrackedSymbols :> {x, y}]

Again there is only one Dynamic. Since only subexpressions inside a Dynamic are updated and like above the single Dynamic contains everything, then everything will be updated or nothing will be. The first Refresh depends on y and the second on x; thus together, the whole depends on both x and y. Therefore it is updated whenever x or y changes.

$\endgroup$
3
  • $\begingroup$ I think there is a mistake in the text :"The middle one has an interior Dynamic that depends on y (only), which makes the whole middle Dynamic depend on y, too; so the whole middle Dynamic is updated, which causes the interior Dynamic to be evaluated, since it is part of the whole." In fact when you move y only the inner Dynamic is updated. This error may be due to a stupid typing error in my answer (yet corrected). I have tested this with the following code (see next comment) $\endgroup$
    – andre314
    Mar 21, 2013 at 23:31
  • $\begingroup$ Here is the code : z = 0; Dynamic[z] -next cell- DynamicModule[{x, y}, Column[{ {x, Dynamic[{z = z + 1; x, Dynamic@Refresh[{x, y}, TrackedSymbols :> {y}]}, TrackedSymbols :> {x, y}], Dynamic@Refresh[{x, y}, TrackedSymbols :> {y}] }, Slider[Dynamic[x]], Slider[Dynamic[y]]} ]]. The idea is to increment a new variable z in the outer Dynamic and to observe it dynamically. I have also added TrackedSymbols:>{x,y} in the outer Dynamic. It does not change the problem and avoid auto-updating of z. If not clear, where can I put the commented code ? $\endgroup$
    – andre314
    Mar 21, 2013 at 23:36
  • $\begingroup$ @andre Yes, of course. I just now wrote a complete explanation of how it work before I realized I had misspoken above: The Dynamic around the interior isolates it so that changes to y cause updates only to that branch of the code; the rest of the middle part is independent of y and is not updated. Thanks! $\endgroup$
    – Michael E2
    Mar 22, 2013 at 1:53
15
$\begingroup$

Imagine you are the front end. Once upon a time, you were told to display some DynamicBox

So, you need to know what it evaluates to AND the list of tracked symbols that would trigger its next update, and perhaps some upper bound on the update interval.

So you ask your friend the kernel to evaluate what is inside. Whatever symbol responsible for a transformation, gets added to that list of tracked symbols. If in the process he runs into a Refresh, then it evaluates like Identity but while he is in the process of evaluating it, some special behaviour can be set. Refresh can provide a list of candidates to be tracked (they still have to be used in a transformation to be added to the list), or set "manually" the dynamic's update interval for example. Once evaluation is over, and boxed up, you display it and just sit and wait for your friend the kernel to tell you some symbol of the list has changed, or the maximum waiting time is up.

And they lived happily ever after

Moral:

  • There is one tracked symbol list and one update interval for each Dynamic

  • Refresh controls what gets added to those lists while the contents of the Dynamic are being evaluated

  • Refresh[x, TrackedSymbols:>{y}] does nothing different than Refresh[x, None]

  • {x, Refresh[x, None]} is equivalent to {x, x}

$\endgroup$
1
  • $\begingroup$ +1 What a nice story! And a good summary of what's going on. $\endgroup$
    – Michael E2
    Mar 19, 2013 at 14:10
6
$\begingroup$

I think that Refresh triggers the update of the next enclosing Dynamic, but Refresh itself is not triggerable

... and once Dynamic triggered, Refresh has no effect.

In that case the documentation should be something like : "represents an object in a Dynamic. This Dynamic should be refreshed at times specified by the options opts."

$\endgroup$
7
  • $\begingroup$ When I understand you correctly, than this goes along with what I have found while searching for different solutions. I'm still a bit disappointed about the situation. Nevertheless +1 $\endgroup$
    – halirutan
    Mar 18, 2013 at 23:26
  • $\begingroup$ Are there problems with my "English" ? $\endgroup$
    – andre314
    Mar 18, 2013 at 23:30
  • $\begingroup$ Hehe, or with mine :-) I'm a bit confused about the word fires, because to fire an updating event a controller like Slider is necessary. When you watch the communication between front end and kernel, then you notice, that an expression like Dynamic[x] only receives the update events. But your point, that Refresh sometimes needs a surrounding Dynamic seems to be valid. $\endgroup$
    – halirutan
    Mar 18, 2013 at 23:36
  • $\begingroup$ @haliturian I have made a very stupid typing error. "Nest" should be "Next". Otherwise, "to fire" = "to trigger" in this context. "Trigger" would have been better because less metaphoric. I'm still not clear on all this and working on the subject. Be patient. $\endgroup$
    – andre314
    Mar 21, 2013 at 21:13
  • $\begingroup$ I have seen the nest thing. Why don't you edit your answer. There is a button and you can always change/improve/update your answer! $\endgroup$
    – halirutan
    Mar 21, 2013 at 21:58

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.