Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update Manipulate[]'d plots when parameters change

I've been fighting with Mathematica's Manipulate function for the last few days for a project.

I'm working on tweaking assumptions and boundary conditions that go into a physical model. For this, I want to be able to plot different equations and adjust the parameters and have the graphs update on the fly. Manipulate seems to be the perfect tool for the job -- except that I can't get it to work. The plots won't update when the parameters are changed.

Basic example:

a =.;
b =.;
c =.;
func1[x_] := a*x;
func2[x_] := a*x^2 + b*x + c;
funcNamesList := {"Linear", "Quadratic"};
funcList := {func1[x], func2[x]}
Manipulate[
   Plot[function, {x, -5, 5}], {function,MapThread[Function[#1 -> #2],
    {funcList, funcNamesList}]}, {a, -5, 5}, {b, -5, 5}, {c, -5, 5},
    LocalizeVariables -> False
]

I can get, for example, func1 to refresh by clicking func1, adjusting a, and then clickingfunc1 again, but I'm hoping to have it update when I adjust a because the real functions I'm using are rather temperamental with respect to their parameters.

-Because I'll be dealing with long functions that have different parameters, using a list of functions is useful.

EDIT:

In case it produces any ideas for anyone, here are some working examples of the individual components of what I want to do (from the Wolfram documentation):

Plot graphs and have them update when parameters are changed:

Manipulate[
    Plot[Sin[a x + b], {x, 0, 6}], {{a, 2, "Multiplier"}, 1, 4},
    {{b, 0, "Phase Parameter"}, 0, 10}
]

Note: This breaks when the function is taken outside:

func[x] := Sin[a x + b];
Manipulate[
  Plot[func[x], {x, 0, 6}], {{a, 2, "Multiplier"}, 1, 4},
  {{b, 0, "Phase Parameter"}, 0, 10}, LocalizeVariables -> False
]

Example of changing the function being plotted:

Manipulate[
   Plot[f[x], {x, 0, 2 Pi}], {f, {Sin -> "sine", Cos -> "cosine", Tan -> "tangent"}}
]

Edit 2 Changed func2 from a*x^2 to a*x^2 + b*x + c to reflect the fact that the functions may have different parameters.

Edit 3 Added the tidbit I use to get nice names on the function buttons.

like image 220
BenB Avatar asked Aug 19 '11 19:08

BenB


2 Answers

There are two problems that prevent your Manipulate statement from working.

First, while the Manipulate variable a is global due to the LocalizeVariables -> False setting, the Plot variable x is not. x is local to the Plot expression.

The second problem is that Manipulate, by default, assumes TrackedSymbols -> Full. This means that only symbols that explicitly appear in the manipulated expression are tracked. Note that a does not appear in the expression, so it is not tracked.

We can correct both problems thus:

a =.;
function =.;
func1[x_] := a*x;
func2[x_] := a*x^2;
funcList := {func1, func2}
Manipulate[
 Plot[function[x], {x, -5, 5}], {function, funcList}, {a, -5, 5}, 
 LocalizeVariables -> False, TrackedSymbols :> {a, function}
 ]

The changes are:

  1. funcList was changed to {func1, func2}
  2. The Plot expression was changed to function[x], thereby referencing the local x variable.
  3. The Manipulate option TrackedSymbols :> {a, function} was added.
  4. function is initially unset.
like image 186
WReach Avatar answered Sep 19 '22 10:09

WReach


I'd do this in a slightly different way:

func1[x_, a_] := a*x;
func2[x_, a_] := a*x^2;
funcList = {func1, func2};
Manipulate[
    Plot[Evaluate[function[x, b]],
        {x, -5, 5},
        PlotLabel \[Rule] funcList
    ],
    {function, funcList},
    {b, -5, 5}
 ]

but this may be unsuitable for what you want. Do your functions have different signatures?

EDIT: I've renamed the parameter to b to make it clearer that is it just a parameter being passed, as opposed to a global variable as you were using it.

like image 21
acl Avatar answered Sep 22 '22 10:09

acl