David; in the example you show
Manipulate[Plot[Sin[x (1 + a x)], {x, 0, 6}], {a, 0, 2}]
The manipulate expression is anything between the start of Manipulate the first ",", i..e this
Manipulate[ expression, controlVariables, Initialization :> ()]
In your case, it is:
Plot[Sin[x (1 + a x)], {x, 0, 6}]
Hence, the dependent variable, which is "a" is visible to Manipulate. i.e. Manipulate "sees" that there is a dependent variable (symbol) in its expression which needs to be tracked by the change in the slider.
If you change this example to
foo[] := Plot[Sin[x (1 + a x)], {x, 0, 6}]
Manipulate[Evaluate@foo[], {a, 0, 2}]
Which is basically what you had, now Manipulate looks at its expression and does not "see" the "a" in there any more. So, it has nothing to track. It is important that symbols to be tracked to appear literally in the expression of Manipulate, or somewhere in the body of Manipulate. Otherwise, you have to tell Manipulate to track all symbols all over the place. This is what "LocalizeVariables -> False" does. However, this is not a good solution. It is better to put all code and data used by Manipulate inside Manipulate and not in the global context as you had.
Here is a summary of all the cases:
Case 1move "foo[]" in the above example to inside Manipulate, in the initialization section, add literal symbol "a" so Manipulate will track it
Manipulate[
a;
foo[], {a, 0, 2},
Initialization :>
(
foo[] := Plot[Sin[x (1 + a x)], {x, 0, 6}];
)
]
Notice the trick above. "a;" was added so that it appears in the Manipulate expression. Otherwise, it will
not be tracked. You'll get an initial plot, but nothing will happen when moving the slider
Case 2move "foo[]" to global context, but have to tell Manipulate that LocalizeVariable is false
foo[] := Plot[Sin[x (1 + a x)], {x, 0, 6}];
Manipulate[
a;
foo[],
{a, 0, 2},
LocalizeVariables -> False
]
But notice, we still need to put "a" somewhere in the expression for it to tracked. Not enough just to say LocalizeVariables -> False
Case 3It is not enough to use "TrackedSymbols :>a", if the symbol itself do not show up in the expression. Hence this does not work
foo[] := Plot[Sin[x (1 + a x)], {x, 0, 6}];
Manipulate[
foo[],
{a, 0, 2},
LocalizeVariables -> False,
TrackedSymbols :> a
]
Notice there is no "a" in the expression. Manipulate will not track "a" even though we told it to !
case 4Same as case 3, even if we put the function inside the Initialization section, it will still not track "a" . One will get an initial plot, but that is all.
Manipulate[
foo[],
{a, 0, 2},
TrackedSymbols :> a,
Initialization :>
(
foo[] := Plot[Sin[x (1 + a x)], {x, 0, 6}];
)
]
Case 5Putting the function definition of foo[] itself inside Manipulate expression, now Manipulate sees "a" there and will automatically track it. No need to do anything more:
Manipulate[
Module[{},
foo[] := Plot[Sin[x (1 + a x)], {x, 0, 6}];
foo[]
],
{a, 0, 2}
]
Or simply
Manipulate[
Plot[Sin[x (1 + a x)], {x, 0, 6}],
{a, 0, 2}
]
Case 6This is the method I use myself. Put all the functions inside the initialization section, but pass the dependent variables by argument call.
Manipulate[
foo[a],
{a, 0, 2},
Initialization :>
(
foo[a_] := Module[{x}, Plot[Sin[x (1 + a x)], {x, 0, 6}]]
)
]
I like this, becuase it achieves both the goal of having all the slider symbols inside the Manipulate expression, hence Manipulate will track them, and at the same time, it avoid the function be in global context, and it is the modular way, since one can see which parameter each function depends on by looking at the signature of the function.
Case 7
Similar to case 6, but the function itself is now in the global context. This is a fine solution as well, if this function needs to be called from somewhere else as well other than from the Manipulate. Otherwise, it is best not to have in the global context and use case 6.
foo[a_] := Module[{x}, Plot[Sin[x (1 + a x)], {x, 0, 6}]];
Manipulate[
foo[a],
{a, 0, 2}
]