MathGroup Archive 2009

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Re: How to find which variable caused the trigger in Manipulate[]

  • To: mathgroup at smc.vnet.net
  • Subject: [mg104157] Re: [mg104136] Re: How to find which variable caused the trigger in Manipulate[]
  • From: John Fultz <jfultz at wolfram.com>
  • Date: Wed, 21 Oct 2009 06:31:00 -0400 (EDT)
  • Reply-to: jfultz at wolfram.com

On Tue, 20 Oct 2009 13:44:11 -0500, Nasser M. Abbasi wrote:
>
>
>> Manipulate[Row[{
>> Dynamic[Refresh[r = x; "", TrackedSymbols -> {x}]],
>> Dynamic[Refresh[r = y; "", TrackedSymbols -> {y}]],
>> Dynamic[Refresh[Text[r], TrackedSymbols -> {y, x}]]}
>> ],
>> {x, 0, 1, 0.01},
>> {y, 0, 1, 0.01},
>> {r, "", "", ControlType -> None}
>> ]
>>
> ...
>
>>>>> "John Fultz" wrote in message
>>>>>
> "I can't reproduce this.  In 7.0.0 and 7.0.1, your example perfectly
> remembers for me both the values of x and y, setting the sliders at
> exactly the right point upon reloading.  Perhaps what you meant is that
> it's not remembering the value of *r* after you move the x slider, save,
> and
> reload."
>
>
> Yes, sorry John I was not too clear. Yes, that is what I meant.  The "x"
> slide position does remain in the same position as before closing, BUT
> what is displayed in the Manipulate output is NOT what was there just
> before closing the notebook (which was the value of the current "x"
> slider). This is becuase what is being displayed comes from "r" now "x",
> and "r" is being refreshed each time the notebook is reopened.
>
>
> "It does properly store the value of r, but once you reload the notebook,
> all of the Dynamics compute again.  Since computing the Dynamics has the
> side effect of setting r, the stored value of r will get wiped out."
>
>
> Yes, but the problem is that "r" is what gets displayed, hence the
> display does change when closing/opening the notebook, and this is the
> problem. The Display as well as the slides positions should remain the
> same as before closing the notebook. This is a demo requirments. This is
> what happens with Manipulate without using Dynamics[Refresh[...]]] so I
> was trying to get this to behave the same way.
>
>
> "  This amounts to the same problem as I mentioned in my first
> response...in this example, whether r is initially set to the value of x
> or y is undefined."
>
>
> Yes, you are correct, I see your point more clearly now. This is the
> _main_ problem.
>
>
> "  It's undefined because there's nothing in the Mathematica
> documentation which guarantees the order in which the Dynamics are
> evaluated.  This is true both when you initially create it, and also when
> you load it again from disk (or copy and paste it, as well).  It so
> happens that it's evaluating Dynamics left-to-right in the Row, but
> that's not behavior you should count on.  So the setting of r (if that
> is, indeed, what you're seeing) is within the designed behavior, and not
> a bug."
>
>
> Ok. But now I need to find a way to fix this if I want to have the same
> GUI design as is. I need to way to have "r" have the same value as it was
> before closing the notebook.  Else, this whole approach will not work. I
> think there is some limitation here. I tried many trick to see if I can
> save "r" value somewhere and use a flag and such, I am still looking at
> it.
>
> I needed a way to be able to detect which slider is being moved each time,
> and at the same time, when the user closes the notebook and reopen it, the
> sliders and the display to be restored to the same state as before=
 closing
> the notebook.
>
> The above 2 requirements seem not to be possible to achieve with the
> current Dynamic[Refresh[...]] solution due to the undefined order of
> Dynamic evaluation.
>
>
> Oh, well, back to the drawing board. I could always go back to my old
> solution of using flags to remember the state from. But your solution
> above was much better, except for this one problem of how to restore "r"
> to its old value before closing.
>
> Thanks for your help John
>
> --Nasser

Actually, I'm not without ideas.  I just don't have the time to develop them too 
carefully when I'm not sure I understand the real problem.  Now that you've
clarified that the problem is, indeed, what I suspected it was, here's a 
solution I've developed:

Manipulate[
 Row[{Dynamic[Refresh[r = x; "", TrackedSymbols -> {x}]], 
   Dynamic[Refresh[r = y; "", TrackedSymbols -> {y}]], 
   Dynamic[Refresh[
     If[initializing === True, initializing = False; 
      r = initialState]; initialState = r; Text[r], 
     TrackedSymbols -> {y, x}]]}], {x, 0, 1, 0.01}, {y, 0, 1, 
  0.01}, {r, "", "", ControlType -> None},
 {{initialState, 0}, ControlType -> None}, {{initializing, False}, 
  ControlType -> None}, Initialization :> (initializing = True)]

The really important feature of this solution is that it uses the Initialization 
option of Manipulate to determine when Manipulate is in its starting state, and 
thereby determine when to initialize r by some means other than the first two 
Dynamics.

Now this code has the distinct advantage that it works, and it's not so 
complicated, but there's one fatal flaw in it.  It relies on the same 
undocumented assumption I discussed earlier...that Dynamics are validated 
left-to-right.  It would fall down if you flipped the order of the Row[], or in 
a hypothetical future implementation of Dynamic that violates this assumption.  
So that's not my final solution.  But I wanted you to see this so you could
understand better how I built my final solution.  My final solution takes the 
same approach, but tracks the Dynamics as they're initialized, forcing the 
Text[] Dynamic to evaluate (possibly again) after the others.  The solution
doesn't seem very elegant, but it does work.  I'm afraid that the educational 
value of this example will require some study of the code, but you seem willing 
to do that.  I reversed the Row[] in this example to prove that it does, in
fact, work as advertised.

Manipulate[Row[{
   Dynamic[Refresh[
     Switch[dynamicsInitialized,
      {True, True, False}, dynamicsInitialized[[3]] = True; 
      r = initialState,
      {True, True, True}, initialState = r];
     Text[r], TrackedSymbols -> {y, x, dynamicsInitialized}]], 
   Dynamic[Refresh[dynamicsInitialized[[1]] = True; r = x; "", 
     TrackedSymbols -> {x}]], 
   Dynamic[Refresh[dynamicsInitialized[[2]] = True; r = y; "", 
     TrackedSymbols -> {y}]]}],
 {x, 0, 1, 0.01}, {y, 0, 1, 0.01},
 {r, "", "", ControlType -> None},
 {{initialState, 0}, 
  ControlType -> 
   None}, {{dynamicsInitialized, {False, False, False}}, 
  ControlType -> None}, 
 Initialization :> (dynamicsInitialized = {False, False, False})]

Sincerely,
 
John Fultz
jfultz at wolfram.com
User Interface Group
Wolfram Research, Inc.





  • Prev by Date: Re: How to find which variable caused the trigger in Manipulate[]
  • Next by Date: DAE system
  • Previous by thread: Re: How to find which variable caused the trigger in Manipulate[]
  • Next by thread: Simple Optimization Problem: Using BinCounts within objective