6
$\begingroup$

This is probably an extremely simple question. I have a manipulate that sets variables used to define an offset, amplitude, frequency and phase of a trigonometric function.

Manipulate[
  Module[{Vac,Vdc, ω, ϕ, f},
    Vac = ctrlVac;                      (* AC Voltage *)
    Vdc = ctrlVdc;                      (* DC Offset *)
    f = ctrlf;                          (* Frequency *)
    ω = 2 π f;
    ϕ = ctrlPhi;                        (* Phase Offset *)
    gFunc = ctrlgFunc;                  (* Function *)
    Plot[ Vdc + Vac  gFunc[ ω t + ϕ],{t,0, 0.4}]],
  {{ctrlgFunc,Sin,""},{Sin,Cos, Tan, Cot }},Delimiter,
  {{ctrlVac,1.5,Subscript["V","ac"]}, -10,10},
  {{ctrlVdc, 0.5, Subscript["V","dc"]}, -1,1},Delimiter,
  {{ctrlf, 10, "Frequency"}, 0.001,100},
  {{ctrlPhi, 0, "ϕ"}, 0, 2 π},
  ControlPlacement->Left, Paneled->True]

I would like to use the Manipulate as an editor that sets the values of the variables in the code snippet above and then passes them on as parameters to a function along with other sets of variables.

Is there a way to add a button to save the current values to a dataset?

$\endgroup$
1

2 Answers 2

6
$\begingroup$

I think I have it this time:

Here's the Manipulate, I removed the Module and cleaned up the Symbols a bit

Manipulate[(*Function*)
  Plot[ctrlVdc + ctrlVac ctrlgFunc[2 Pi ctrlf t + ctrlPhi], {t, 0, 0.4}], 
  {{ctrlgFunc, Sin, ""}, {Sin, Cos, Tan, Cot}}, 
  Delimiter, 
  {{ctrlVac, 1.5, Subscript["V", "ac"]}, -10, 10}, 
  {{ctrlVdc, 0.5, Subscript["V", "dc"]}, -1, 1}, 
  Delimiter, 
  {{ctrlf, 10, "Frequency"}, 0.001, 100}, 
  {{ctrlPhi, 0, "ϕ"}, 0, 2 π}, 
  Delimiter, 
  Button[
    "Store", 
    d = Dataset[Association @ 
          {gFunc -> ctrlgFunc, Vac -> ctrlVac, Vdc -> ctrlVdc, 
           ϕ -> ctrlPhi, ω -> 2 Pi ctrlf}]], 
  ControlPlacement -> Left, Paneled -> True]

Mathematica graphics

A Button has been added that, when pressed, creates a Dataset, d, that can be referenced outside of the Manipulate.

d

Mathematica graphics

$\endgroup$
5
  • $\begingroup$ The OP seems to explicitly ask for a Dataset -- shouldn't be hard to update. $\endgroup$
    – Michael E2
    Aug 1, 2014 at 2:19
  • $\begingroup$ @MichaelE2 Completely missed that; thanks for pointing it out. $\endgroup$ Aug 1, 2014 at 2:20
  • $\begingroup$ Thank you most kindly! This is exactly what I was looking for. $\endgroup$ Aug 1, 2014 at 11:05
  • $\begingroup$ Lastly, passing to a function without other parameters: myfunction @@ Normal@d or with other parameters myfunction @@ Values@Normal@d~Join~{x, y, z}. In both cases, it is beneficial to organize the dataset in the order needed for myfunction. $\endgroup$ Aug 1, 2014 at 11:10
  • $\begingroup$ This is an excellent answer to a good question. It has the virtue of simplicity. $\endgroup$ Aug 1, 2014 at 15:31
2
$\begingroup$

The following solution may or may not be too complicated to deal with, but it's kind of neat. It uses DynamicModule wormholes to link variables between two DynamicModules. One of the modules has to be created from within a live instance of the other one. That is to say, you instantiate one (the parent) in the Front End, and it has to create the other (the child). If the child is a Manipulate you have to use both options, InheritScope -> True and LocalizeVariables -> False. You then need to declare all the variables you want to use in the Manipulate into the parent DynamicModule or else they will be Global` variables.

In this setup, I have made the OP's Manipulate the child. Whenever the variables are changed in the Manipulate, the parent DynamicModule has access to their values. You can do with them as you please, including creating a Dataset if desired. Just as a proof of concept, I have a button whose label dynamically shows the values of the variables in the Manipulate. If the button is pressed, the global function f is called. It does nothing if f is undefined, but it's there just to give the idea. If you uncomment Print@, pressing the button will print the function call (which is shown below the image).

DynamicModule[
 {ctrlgFunc = Sin, ctrlVac = 1.5, ctrlVdc = 0.5, ctrlf = 10, ctrlPhi = 0},

 Button[
  Inactive[f][Dynamic@{ctrlgFunc, ctrlVac, ctrlVdc, ctrlf, ctrlPhi}], 
  (*Print@*)f[ctrlgFunc, ctrlVac, ctrlVdc, ctrlf, ctrlPhi]],

 Initialization :> {
   CellPrint@
    ExpressionCell[
     Manipulate[Module[{Vac, Vdc, ω, ϕ, f},
       Vac = ctrlVac;(*AC Voltage*)Vdc = ctrlVdc;(*DC Offset*)
       f = ctrlf;(*Frequency*)ω = 2 π f;
       ϕ = ctrlPhi;(*Phase Offset*)gFunc = ctrlgFunc;(*Function*)
       Plot[Vdc + Vac gFunc[ω t + ϕ], {t, 0, 
         0.4}]], {{ctrlgFunc, ctrlgFunc, ""}, {Sin, Cos, Tan, Cot}}, 
      Delimiter, {{ctrlVac, ctrlVac, Subscript["V", "ac"]}, -10, 
       10}, {{ctrlVdc, ctrlVdc, Subscript["V", "dc"]}, -1, 1}, 
      Delimiter, {{ctrlf, ctrlf, "Frequency"}, 0.001, 100},
      {{ctrlPhi, ctrlPhi, "ϕ"}, 0, 2 π}, 
      ControlPlacement -> Left, Paneled -> True, InheritScope -> True,
       LocalizeVariables -> False],
     "Output"]
   }
 ]

Mathematica graphics

f[Sin, 1.5, 0.5, 10, 0]

Postscript

Here's an f that yields a Dataset:

f[func_, vac_, vdc_, f_, phi_] :=
  output = Dataset[<|"func" -> func, "vac" -> vac, "vcd" -> vdc, "f" -> f,  "phi" -> phi|>]

Update - Variations

Having the Manipulate cell automatically created by Initialization may prove troublesome, which I hinted at rather obscurely above. One variation would be to put the code in a button that would print the Manipulate in a cell whenever button was pushed. In the OP's application, another variation that might be convenient would be to have an edit button that creates the Manipulate in a new dialog/palette. All these approaches might allow the user to create multiple copies, which is probably not particularly desirable. One can put in code to block the check whether a Manipulate is already displayed. The following is one way to create palette. Make the changes indicated in the following:

DynamicModule[
 {ctrlgFunc = Sin, ctrlVac = 1.5, ctrlVdc = 0.5, ctrlf = 10, ctrlPhi = 0, 
  editpalette},

 Column[{
   Dynamic @ Dataset[<|"func" -> ctrlgFunc, "vac" -> ctrlVac, "vcd" -> ctrlVdc,
       "f" -> ctrlf, "phi" -> ctrlPhi|>],
   Button[
    "edit",
    If[! MemberQ[Notebooks[], editpalette], 
     editpalette = CreatePalette[
       Manipulate[..., InheritScope -> True, LocalizeVariables -> False],
       Saveable -> False
       ]]
    ]
   }]
 ]
$\endgroup$
4
  • $\begingroup$ @m_goldberg It's mentioned in the text. Or hidden in the definition of f. :) I primarily responded to "I would like to use the Manipulate as an editor that sets the values of the variables in the code snippet above and then passes them on as parameters to a function along with other sets of variables." $\endgroup$
    – Michael E2
    Aug 1, 2014 at 3:25
  • $\begingroup$ @m_goldberg I had actually already written f, but decided to leave it out. $\endgroup$
    – Michael E2
    Aug 1, 2014 at 3:27
  • $\begingroup$ This is very good information and starts to address some design pattern questions I have been considering. While a Model layer in the classic MVP or MVC Design Pattern could be implemented in earlier versions, the new Dataset makes this more accessible. This line of thought would be another question and from the existing posts, I see some very good thoughts around design patterns are already here. Thank you very much for the code sections and discussions above - extremely helpful. $\endgroup$ Aug 1, 2014 at 11:20
  • $\begingroup$ @user1585715 You're welcome. As you move ahead, you may find it easier to construct sophisticated interfaces with DynamicModule instead of Manipulate. Manipulate constructs a DynamicModule automatically, and the automatic things it does can be either conveniences or obstacles. You'll find some debate on this site about which to use. For small, simple things, I find Manipulate quite convenient. Others who develop applications for clients usually need DynamicModule. $\endgroup$
    – Michael E2
    Aug 1, 2014 at 12:53

Your Answer

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

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