3
$\begingroup$

I would like to call some complex plotting function, which accepts a list of variables and would like to get sliders for each variable.

Currently I write something like below

PlotSines[a_List] := Block[{funcs},
   funcs = Table[Sin[a[[i]] x] + i - 1, {i, 1, Length[a]}];
   Plot[funcs, {x, -5, 5}]
   ];

Manipulate[PlotSines[{a1, a2, a3}], {{a1, 1}, 0.1, 5}, {{a2, 1}, 0.1, 5}, {{a3, 1}, 0.1, 5}]

enter image description here

i.e. explicitly writing each "abstraction" clause of kind {{a1, 1}, 0.1, 5}. I name them "abstraction" clauses like in lambda calculus, because these clauses "remove" mentioned variable from outer expression.

Now I want to have variable number of a-s and so I can't hardcode expression then.

Can I generate such construction programmatically, so that it generated list of some names, acceptable by Manipulate function?

I tried to write this way

varlist = Table[Symbol[ToString[StringForm["a``", i]]], {i, 1, 5}]

which gave

{a1, a2, a3, a4, a5}

then

clauses = Sequence[Table[{{a, 1}, 0.1, 5}, {a, varlist}]]

which gave

Sequence[{{{a1, 1}, 0.1, 5}, {{a2, 1}, 0.1, 5}, {{a3, 1}, 0.1, 5}, {{a4, 1}, 0.1, 5}, {{a5, 1}, 0.1, 5}}]

I was hoping sequnce will "expand" inside manipulate and wrote

Manipulate[PlotSines[varlist], clauses]

but it complained

Manipulate::vsform: Manipulate argument clauses does not have the correct form for a variable specification.

UPDATE

I thought I should play with evaluation order somehow. I tried to write

 Manipulate[PlotSines[varlist], Evaluate[clauses]]

but it drew

enter image description here

apparently PlotSines function was executed before Manipulate called it

$\endgroup$
4
$\begingroup$
PlotSines[a_List] := 
  Block[{funcs}, 
   funcs = Table[Sin[a[[i]] x] + i - 1, {i, 1, Length[a]}];
   Plot[funcs, {x, -5, 5}]];

foo[n_Integer] := Module[{vars, varSpec},
  vars = Table[Unique["x"], {n}];
  varSpec = Table[{{vars[[i]], 1, StringTemplate["a``"]@i}, 0.1, 5}, {i, 
     Length@vars}];

  Manipulate[
    PlotSines[vars],
    Evaluate[Sequence @@ varSpec]
    ] /. OwnValues[vars]
  ]

I am creating unique xi because I don't want to care if they already exist. Then I just label them as consecutive ai :)

$\endgroup$
1
$\begingroup$
varlist = Table[Symbol["a"<>ToString[i]],{i,1,5}];
clauses = Table[{{a,1},0.1,5},{a,varlist}];
manipulate = "Manipulate[PlotSines["<>ToString[varlist]<>"],
    Evaluate[Sequence@@"<>ToString[clauses]<>"]]";
ToExpression[manipulate]

Apparently Manipulate will automatically hold all of its elements in unevaluated form, but that makes this specific problem a bit tricky to solve. The easiest method I've seen to deal with the holds is to write the command in full as a string and then execute it.

$\endgroup$
  • $\begingroup$ This will fail if e,g, a1 = 2; was evaluated or any of ai have value $\endgroup$ – Kuba Oct 19 '17 at 15:59
1
$\begingroup$

I found a way without string coding:

PlotSines[a_List] := Block[{funcs},
   funcs = Table[Sin[a[[i]] x] + i - 1, {i, 1, Length[a]}];
   Plot[funcs, {x, -5, 5}]
   ];

n = 5
varlist = Table[Symbol[ToString[StringForm["a``", i]]], {i, 1, n}]
clauses = Sequence @@ Table[{{a, 1}, 0.1, 5}, {a, varlist}]
Activate[Inactive[Manipulate][Inactive[PlotSines][varlist], clauses]]

draws

enter image description here

$\endgroup$
  • 1
    $\begingroup$ This will fail if e,g, a1 = 2; was evaluate or any of ai have value. $\endgroup$ – Kuba Oct 19 '17 at 15:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.