44
$\begingroup$

I have a function that operates on a list of parameters of variable-length $n$. I would like to create a Manipulate[] that has $n$ sliders, one for each list element, each considered a separate parameter. The syntax Manipulate[expr,{u,...},{v,...},...]] does not lend itself to this, as it is geared toward a fixed number of parameters known in advance, and referenced by separate variable names.

I have started exploring preparing a list of arguments to Manipulate[] and then using Apply[], but this seems tricky and complicated.

Anyone come upon this conundrum before?

$\endgroup$
1

3 Answers 3

38
$\begingroup$

The Advanced Dynamic Functionality in Mathematica documentation has the following example that looks like what you need.

DynamicModule[{n = 5, data = Table[RandomReal[], {20}]},
Column[{
Slider[Dynamic[n], {1, 20, 1}],
Dynamic[Grid[Table[With[{i = i},
   {Slider[Dynamic[data[[i]]]], Dynamic[data[[i]]]}], {i, n}]
 ]]}]]

nested sliders

It builds a list of controllers (Slider-s in this particular case) by using the fact that you can assign values to not just symbols but also to members of a list by doing data[[1]] = value. Which is exactly the thing that happens inside Dynamic[data[[i]]], as it is equivalent to:

Dynamic[data[[i]], (data[[i]] = #)&]

telling Mathematica to whenever the actual value of data[[i]] is changed, use the new value (#) to update the expression data[[i]].

Also from the Documentation Center, the last example in Manipulate: Neat Examples may be useful:

Manipulate[
ArrayPlot[
Take[data, h, w]], {{data, RandomInteger[{0, 1}, {10, 20}]}, 
ControlType -> None}, {{h, 5}, 1, 10, 1}, {{w, 5}, 1, 20, 1}, 
Dynamic[Panel[
 Grid[Outer[Checkbox[Dynamic[data[[#1, #2]]], {0, 1}] &, Range[h], 
 Range[w]]]]]]

which gives

enter image description here

$\endgroup$
2
  • $\begingroup$ This is very helpful---Thanks so much! $\endgroup$ Commented Feb 2, 2012 at 19:42
  • $\begingroup$ @Joseph, glad the link was helpful. $\endgroup$
    – kglr
    Commented Feb 2, 2012 at 19:53
10
$\begingroup$

Here is a followup to my question, code based on the example provided by kguler. Note there is no longer any need for Manipulate[]— it is all handled by Dynamic[].

data = Table[RandomReal[], {5}];

DynamicModule[ {n = Length[data]},

 Column[{

   Dynamic[
    Grid[
     Table[
      With[{i = i},
       {i,
        Slider[Dynamic[data[[i]]]],
        Dynamic[data[[i]]]
        }
       ],
      {i, n}
      ](*Table*)
     ]],(*Dynamic*)

   Dynamic[ListPlot[data, Joined -> True]]

   }, Center](*Column*)
 ]


     enter image description here

$\endgroup$
9
$\begingroup$

This is similar to kguler's solution, but it assumes that there is a more complex updating going on during slider-interaction (namely, both list and total are updated), to illustrate more realistic cases where a single Dynamic object might affect more than one variables. Also it shows how to use Map with a variable number of Slider-s. For localization and elegance, the whole code should be wrapped into DynamicModule, but since this is not the point here, I omitted.

update[n_] := (list = Table[0, {n}]; total = Total@list); (* function called when n is changed *)

n = 5;
update[n]; (* initialize list and total *)

Slider[Dynamic[n, (n = #; update[#]) &], {1, 10, 1}]

Dynamic[total]

Dynamic[Grid[
  {
   #,
   Slider[Dynamic[list[[#]], 
       Function[{x}, list[[#]] = x; total = Total@list]], {0, 1}], 
   Dynamic[list[[#]]]
  } & /@ Range[n]
  ], TrackedSymbols :> {n}]

Mathematica graphics

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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