How are parameters evaluated for a Plot in Manipulate



I am trying to get my head around how Manipulate evaluates functions in a Plot. I have read the introduction to Manipulate, and introduction to Dynamic, but I still can't figure it.

For my specific example, I have a function bigA parameterised by m1 and m2 (this relates to question),

bigA[t_]:= (m1+m2) ((m1 m2 t)/(m1+m2)^3)^0.25

So when I try to plot it in Manipulate,

 Plot[bigA[t], {t, 1, 10}],
 {{m1, 1.4}, 0.8, 3},
 {{m2, 1.4}, 0.8, 3}]

Nothing appears. I presume this is because m1 and m2 aren't being evaluated. But I don't know what the order is supposed to be.


The thing is, this seems to work when I Evaluate and don't plot, i.e,

 {{m1, 1.4}, 0.8, 3},
 {{m2, 1.4}, 0.8, 3}]

So couldn't I just stick a Plot command in there somewhere?


Posted 2012-09-14T07:09:43.620

Reputation: 767


I think, this discussion is strongly relevant, even though not being specifically about Manipulate, since your real question is on how to properly localize variables in functions definitions - as the answers posted already also indicate.

– Leonid Shifrin – 2012-09-14T15:13:40.273

Related: (8625)

– Mr.Wizard – 2017-02-11T00:55:08.510



The problem is that inside the Manipulate, m1 and m2 are replaced with localized versions (as in Module) rather than assigned (as in Block). Since the m1 and m2 from bigA are outside the Manipulate, and bigA[t] is evaluated only after the replacement of m1 and m2 inside the Manipulate, they are not affected by the manipulation.

The best solution is to give m1 and m2 as extra arguments:

bigA[t_, m1_, m2_] := (m1+m2) ((m1 m2 t)/(m1+m2)^3)^0.25
Manipulate[Plot[bigA[t, m1, m2], {t, 1, 10}],
           {{m1, 1.4}, 0.8, 3},
           {{m2, 1.4}, 0.8, 3}]

If for some reason you cannot do that, you can also use replacement rules as follows:

bigA[t_] := (m1+m2) ((m1 m2 t)/(m1+m2)^3)^0.25
Manipulate[Plot[bigA[t]/.{m1->mm1,m2->mm2}, {t, 1, 10}],
           {{mm1, 1.4}, 0.8, 3},
           {{mm2, 1.4}, 0.8, 3}]

This works because ReplaceAll (/.) does the replacements only after the left hand side has been evaluated, and the mm1 and mm2 are now inside the Manipulate, so they can be properly localized.

About your edit:

By adding Evaluate@ at the beginning of the argument to Manipulate, you override Mathematica's order of evaluation. So with

           {{m1, 1.4}, 0.8, 3},
           {{m2, 1.4}, 0.8, 3}]

Mathematica first evaluates bigA[t] to (m1+m2) ((m1 m2 t)/(m1+m2)^3)^0.25, and only then proceeds to evaluate the Manipulate, which therefore sees the m1 and m2.

Now this will not work with Plot, because the whole Plot statement will be executed, before Manipulate will have a chance to insert m1 and m2. So when Plot evaluates bigA[t], it will receive an expression containing m1 and m2 instead of a number, and thus produce an empty graph. This graph (which no longer contains any trace of m1 or m2) will then be passed to Manipulate. Of course replacing m1 and m2 at this stage doesn't work, because they already vanished.

So in essence, while without Evaluate, m1 and m2 are substituted too late, with Evaluate@Plot they are consumed too early.

Now you might have the idea to use Manipulate[Plot[Evaluate@bigA[t],...],...] instead, in order to evaluate bigA[t] (to get m1 and m2 visible) but not Plot (because that only works after m1 and m2 got a value). However that doesn't work either, because Evaluate only affects order of evaluation when it appears as immediate argument of the expression being evaluated. So while evaluating Manipulate, the Evaluate in the argument of Plot is not considered. It will be considered at the time Plot is evaluated, but at that time it's already too late.


Posted 2012-09-14T07:09:43.620

Reputation: 18 543

Thanks @celtschk, what about the case where I evaluate the function, but don't plot it (please see my edited question above). Why would this work, but not the plot? – ShaunH – 2012-09-14T07:41:01.797

@ShaunH: That works because you added an explicit Evaluate here, overriding the standard order of evaluation. Note however that this works only if the Evaluate is top-level on the Manipulate argument. – celtschk – 2012-09-14T07:51:53.140

ok thanks for the explanation on how Evaluate works. That really did confuse me. So basically, it only works at the top level. Ok, so I will just have to define the parameters as variables. – ShaunH – 2012-09-14T08:21:10.280

the second method works perfect when combining manipulate and the contourplot3d command. One needs to add Evaluate inside the Contourplot3d command, and the substitution right after the contourplot3d function. Thanks a lot! – larry – 2016-11-27T04:13:49.920

The replacement rule in the second solution should be inside Plot[]: Plot[bigA[t] /. {m1 -> mm1, m2 -> mm2}, {t, 1, 10}]. Since you haven't been around in a month or so, I'll edit. You can fix it how you like, if you don't like what I did. – Michael E2 – 2018-05-22T18:40:41.290

Shouldn't the first Manipulate not have bigA[t,m1,m2] instead of bigA[t]? – Sjoerd C. de Vries – 2013-05-20T10:09:52.910

@SjoerdC.deVries: Yes, you're right. I'll correct this. – celtschk – 2013-05-30T18:01:18.910


A couple of tips:

  • Make sure you evaluate the function - best way is to put it in Initialization :> ...
  • Rather keep parameters m1, m2 as arguments
  • Fix PlotRange to see function change, not the axes scale
  • Use SaveDefinitions -> True so interface will remember your defined function when you reopen notebook

I updated the code below to encompass your derivative question:

Manipulate[Plot[Evaluate@{bigA[t, m1, m2], D[bigA[t, m1, m2], t]}, {t, 1, 10}, 
  PlotRange -> {0, 3}, Filling -> 0], {{m1, 1.4}, 0.8, 3}, {{m2, 1.4}, 0.8, 3}, 
 Initialization :> (bigA[t_, m1_, m2_] := (m1 + m2) ((m1 m2 t)/(m1 + m2)^3)^0.25), 
 SaveDefinitions -> True]

enter image description here

Vitaliy Kaurov

Posted 2012-09-14T07:09:43.620

Reputation: 66 672

Thanks @Vitaliy. So the key change here is to put the parameters m1 and m2 as functions, right? I guess that is just the way you should do things in Mathematica. But for some reason it doesn't seem right to me. For example, if I wanted to differentiate bigA with respect to t, would m1 and m2 still be kept symbolic? – ShaunH – 2012-09-14T07:31:03.943

@ShaunH (1) you mean m1 and m2 as "variables", - and the answer is yes, celtschk in his answer has good explanation. (2) yes, m1 and m2 would still be kept symbolic, in Mathematica by default almost everything is symbolic, unless defined to be numeric. I updated the code to illustrate this by adding the computation and graph of derivative – Vitaliy Kaurov – 2012-09-14T07:44:57.770

Sorry, I meant variables, not functions. You've almost sold me that this should be the way to go, except for one thing. It seems to work when you Evaluate, but not plot (see my edit to the original question). Isn't there someway we could just include an Evaluate command and keep m1, m2 as parameters? – ShaunH – 2012-09-14T07:50:20.463


Manipulate does not temporarily change the global value of its variables, as does Table and Do. Compare:

Do[Pause[1], {x, 0, 10}]


Manipulate[x, {x, 0, 10}]

Since your definition of bigA relies on Global` symbols m1 and m2 you must manually change these values, e.g. using Block:

bigA[t_] := (m1 + m2) ((m1 m2 t)/(m1 + m2)^3)^0.25

 Block[{m1 = mm1, m2 = mm2},
  Plot[bigA[t], {t, 1, 10}]
 {{mm1, 1.4}, 0.8, 3},
 {{mm2, 1.4}, 0.8, 3}

Or you could insert the definition of bigA into manipulate using With so that it appears explicitly (assuming no global values for m1, m2, or t):

With[{x = bigA[t]},
  Plot[x, {t, 1, 10}],
  {{m1, 1.4}, 0.8, 3},
  {{m2, 1.4}, 0.8, 3}

Simpler and cleaner is to just parametrize m1 and m2 as belisarius shows.


Posted 2012-09-14T07:09:43.620

Reputation: 259 163


For example you can do the following to get proper localization

bigA[t_, m1_, m2_] := (m1 + m2) ((m1 m2 t)/(m1 + m2)^3)^0.25
 Plot[bigA[t, m1, m2], {t, 1, 10}],
 {{m1, 1.4}, 0.8, 3},
 {{m2, 1.4}, 0.8, 3}]

Dr. belisarius

Posted 2012-09-14T07:09:43.620

Reputation: 112 848


This works and is very simple!!

bigA[t_] := (m1 + m2) ((m1 m2 t)/(m1 + m2)^3)^0.25;
  Plot[#, {t, 1, 10}], 
  {{m1, 1.4}, 0.8, 3},
  {{m2, 1.4}, 0.8, 3}] &@bigA[t]


Posted 2012-09-14T07:09:43.620

Reputation: 475


Copy-paste the definition of the function (or evaluate it and copy the resulting code) to inside the plot. In other words

 Plot[(m1+m2) ((m1 m2 t)/(m1+m2)^3)^0.25, {t, 1, 10}],
 {{m1, 1.4}, 0.8, 3},
 {{m2, 1.4}, 0.8, 3}]

I understand that this is not the neatest solution, but the big elephant in the room is that this is by far the simplest and most convenient way to circumvent this limitation.

Jorge Leitao

Posted 2012-09-14T07:09:43.620

Reputation: 783