3

I'm doing a CDF document where I'm placing Dynamic pieces in the middle of the text. This document is supposed to work in the Player.

What is the best way to register glogal values that should be accessed from all the dynamic pieces that are scattered around different cells?

For instance, I want to define g=9.8, and I want this value to be accessed by all the dynamics that are placed in the different cells. Since this should work on the player, this value should persist across sessions of Mathematica.

I could only think of 2 different ways:

  • an action button that has to be clicked by the user, when he opens the file, that launches all the needed = and := used around the notebook
  • create an empty manipulate, with a SaveDefinitions->True, and whose variable are not localized to the Manipulate

Both seem too artificial.

Having any other method that only sets the definitions once it is displayed is not good, since the person that accepts to display the dynamics may have already scrolled down, and passed by the dynamic that implements all the needed definitions.

So, how to "SaveDefintions" without using the Manipulate structure?

Verbeia
  • 4,400
  • 2
  • 23
  • 44
P. Fonseca
  • 549
  • 4
  • 12
  • Why not use the `Initialization` option? It will evaluate initialization only one time when the dynamic object is displayed for the first time. – Alexey Popkov Aug 28 '11 at 08:33
  • @Alexey - in which one of the dynamics would I use it? On the first one? And if the user has already scrolled down, and passed it, before accepting the display of the dynamics? If I define in all, it loses sense, because some definitions are just the initial values of input fields that are repeated along the document (I let the user define a new value in different places...). For info, the definitions are: start values for variables that can be lately changed by the users, variables that will never be changed, and functions, both pure and := – P. Fonseca Aug 28 '11 at 08:38
  • Another option I thought, but also not very good, is to just show a button when the user opens the file. All the rest of the document is in a hidden chapter. Once the button clicked, it defines the variables, disappears itself, and unhides the chapter that is the main document body. But also seems to artificial – P. Fonseca Aug 28 '11 at 08:46
  • @Alexey - it is possible. The warning changes nothing in the viewing of the document, with the exceptions that the dynamics are all displayed in dark gray – P. Fonseca Aug 28 '11 at 08:58

3 Answers3

2

One possibility is to define conditional Initialization for every Dynamic object in the document and place initialization expressions in an initialization cell (or in some other cell with a tag which allow easily identify it). For example, using initialization cell:

Manipulate[
 Plot[n f[x], {x, -3, 3}], {n, 1, 4}, 
 Initialization :> If[!TrueQ[$initialized],
                      FrontEndTokenExecute["EvaluateInitialization"]]]

In this way you need not to store initialization expressions in every Dynamic object and these expressions will not be evaluated repeatedly for every of them.


Update

It seems that NotebookDynamicExpression option of Notebook is what you want. John Fultz wrote about it:

"Dynamics can be stored in the front end options CellDynamicExpression, NotebookDynamicExpression, and FrontEndDynamicExpression. These Dynamics are not displayed, but are updated when the cell/notebook/frontend to which they are attached is displayed."

So the solution is:

SetOptions[EvaluationNotebook[], NotebookDynamicExpression :> (a = 1)]

Try to save and open again notebook after evaluating the above. And check definition for a.

Alexey Popkov
  • 9,355
  • 4
  • 42
  • 93
  • It should work. Despite the fact that it will add some "garbage" code in the middle of all my very small/elegant dynamics code, I may go in this direction. – P. Fonseca Aug 28 '11 at 09:42
  • Do you know how to use NotebookDynamicExpression. The help is so small on this function that I can't figure out how to use and if it does something like what I want... – P. Fonseca Aug 28 '11 at 09:43
  • @P. Fonseca It seems that `NotebookDynamicExpression` option of Notebook is what you want. John Fultz [wrote](http://groups.google.com/group/comp.soft-sys.math.mathematica/msg/3eb582e5fb8b0162) about it: "`Dynamic`s can be stored in the front end options `CellDynamicExpression`, `NotebookDynamicExpression`, and `FrontEndDynamicExpression`. These `Dynamic`s are not displayed, but are updated when the cell/notebook/frontend to which they are attached is displayed." – Alexey Popkov Aug 28 '11 at 09:56
  • I'll try it and get back to you asap – P. Fonseca Aug 28 '11 at 10:01
  • Doesn't work with setdelayed (crashes Mathematica), which seems normal (not the part of crashing), since setdelayed normally causes infinite loops inside dynamics. Any ideas? – P. Fonseca Aug 29 '11 at 15:06
0

I have not tried this in dynamics document like you have, but you can try this:

"Using initialization cells, you can specify that particular input cells of a notebook should be evaluated first. This ensures that your code is evaluated in the correct order, such as defining functions before evaluating cells that use those definitions."

http://reference.wolfram.com/mathematica/howto/WorkWithInitializationCells.html

Nasser
  • 12,849
  • 6
  • 52
  • 104
0

You can use something along these lines:

DynamicModule[{savetext = ""},
 Dynamic[If[StringQ[string], savetext = string, savetext],
  Initialization :> (string = savetext)]]

On first evaluation string does not exist, so StringQ results in the Dynamic showing "". Thereafter StringQ evaluates to True, and Dynamic shows the text in string. savetext is saved across sessions by being a DynamicModule local variable.

string can be updated directly, e.g. string = "new text"

However, if more than one copy of this construction is open at the same time, one string variable will update the other.

It would be interesting to see suggestions on how instances could be isolated, (without renaming 'string').

Chris Degnen
  • 8,443
  • 2
  • 23
  • 40