Correcting problems with the controls in a Manipulate

1

I am developing a toy application to teach me how to generate a more complex CDF app. The current toy app is taking integral.

Manipulate[
  DynamicModule[{f = Sin[x], xR = 1, xL = 0, Res = 0.4596976941}, 
    Column[{
      InputField[Dynamic[xL], Number], 
      InputField[Dynamic[xR], Number], 
      InputField[Dynamic[f]], 
      Button["Calculate", 
        Dynamic[Res = 
          NumberForm[NIntegrate[f, {x, xL, xR}, WorkingPrecision -> nw], np];]], 
      InputField[Dynamic[Res]], 
      Dynamic[If[fp == True, Plot[f, {x, xL, xR}]]]}]], 
  {{np, 10, "NumberFormat"}, 10, 30, 1}, 
  {{nw, 16, "WorkingPrecision"}, 10, 30, 1}, 
  {{fp, True, "Plot the function"}, {False, True}, Checkbox}]

enter image description here

But there are some of the problems that I am trying to solve.

  1. I would like to have name tags on the left or top of each of the input fields. FieldHint does not work.

    Manipulate[
      DynamicModule[{f, xR, xL, Res}, 
        Column[{
          InputField[Dynamic[xL], Number, FieldHint -> "Lower Limit"], 
          InputField[Dynamic[xR], Number, FieldHint -> "Upper Limit"], 
          InputField[Dynamic[f], FieldHint -> "Function"], 
          InputField[Dynamic[Res], FieldHint -> "Result"], 
          Button["Calculate", 
            Dynamic[Res = 
              NumberForm[NIntegrate[f, {x, xL, xR}, WorkingPrecision -> nw], np];]], 
          Dynamic[If[fp == True, Plot[f, {x, xL, xR}]]]}]], 
      {{np, 10, "NumberFormat"}, 10, 30, 1}, 
      {{nw, 16, "WorkingPrecision"}, 10, 30, 1}, 
      {{fp, False, "Plot the function"}, {False, True}, Checkbox}]
    

    enter image description here

    And I think having name tags would look much better even if the FieldHint approach were made to work.

  2. I tried to make the plotting also part of the button, but it is not working (I simply moved the ] at the end of the Button expression to the end of the plotting). Also, when I don't have the plot, I get a Null, which I don't like. Is there a way of getting rid off that? And how can I make the size of the plot bigger?

  3. The last thing I could not figure it out is to limit xL and xR inputs to a number. I specified in the input field that the input is number but when I enter something not a number, I get an error. I expected it simply not to update (according to help documentation, "The input field will not be updated if the input is not of the specified type")

Erdem

Posted 2016-04-21T19:06:47.193

Reputation: 849

Your first issue with FieldHint looks like a bug: even InputField["", Expression, FieldHint -> "Hint"] does not work. Have you reported it? – Alexey Popkov – 2016-04-23T15:45:37.463

Answers

1

You can use

Row[{"xL", InputField[Dynamic[xL], Number]}, Spacer[5]]

or

Labeled[InputField[Dynamic[xL], Number], "xL", Left]

to label the input fields.

Manipulate[DynamicModule[{f = Sin[x], xR = 1, xL = 0, Res = 0.4596976941}, 
  Column[{Row[{"xL ", InputField[Dynamic[xL], Number]}, Spacer[5]], 
    Row[{"xR ", InputField[Dynamic[xR], Number]}, Spacer[5]], 
    Row[{"f  ", InputField[Dynamic[f]]}, Spacer[5]], 
    Button["Calculate", 
     Dynamic[Res =  NumberForm[NIntegrate[f, {x, xL, xR}, WorkingPrecision -> nw],
          np];]], Row[{"res", InputField[Dynamic[Res]]}, Spacer[5]], 
    Dynamic[If[fp == True, Plot[f, {x, xL, xR}]]]}]], 
   {{np, 10, "NumberFormat"}, 10, 30, 1}, 
   {{nw, 16, "WorkingPrecision"}, 10, 30, 1},
   {{fp, True, "Plot the function"}, {False, True}, Checkbox}]

Mathematica graphics

Alternatively, you can use Grid instead of Column as follows:

Grid[{{"xL", InputField[Dynamic[xL], Number]},
      {"xR", InputField[Dynamic[xR], Number]}, 
      {"f",  InputField[Dynamic[f]]}, 
      {Button["Calculate",  Dynamic[Res = NumberForm[NIntegrate[f, {x, xL, xR},
        WorkingPrecision -> nw], np];]], SpanFromLeft},
      {"res", InputField[Dynamic[Res]]}, 
      {Dynamic[If[fp == True, Plot[f, {x, xL, xR}]]], SpanFromLeft}}]

To get rid of Null you can change the part If[...] in your code to

If[fp, Plot[f, {x, xL, xR}], ""]

kglr

Posted 2016-04-21T19:06:47.193

Reputation: 302 076

1

A few points and my version:

  • Manipulate[DynamicModule[{f = Sin[x],... means whenever Manipulate updates itself, f etc. are reinitialized. (It does this only first time the calculate button is pushed.) I would suggest doing it all inside one DynamicModule or one Manipulate. I show the Manipulate approach below. I constructed the controls in the standard Manipulate way, which I thought I should do if I was going to use Manipulate at all. (For control type None, see this question.)

  • NumberForm messes up the output as displayed in the InputField, imo. One can takes advantage of the internal rules by using SetPrecision instead.

  • The option ImageSize will control the size of many displayed objects, including Plot. Pane is another construct that will control size.

  • With respect to restricting InputField, Manipulate makes certain things automatic & easy and some things difficult to implement. For this reason, some prefer to use DynamicModule and construct everything by hand, but exactly in the way desired. To get Number into the second argument of InputField as a Manipulate control, you have to use the custom-control syntax, {..., InputField[#, Number]&}.

  • To have a button control the updating, a standard trick is to use a dummy variable. Restrict the TrackedSymbols in Manipulate to it and any others that should cause an immediate update, leaving out parameters. I included fp, which controls the plot; however, clicking it will also cause the integral to be updated. One can use Dynamic@If[...] so that only the plot will be affected, but it will be replotted with the new settings, without updating the integral, if fp is clicked twice (off-on).

My code:

Pane[ (* controls overall width: sets the size of ImageSize -> Full, too *)
 Manipulate[
  update;
  Column[{
    Dynamic@If[fp == True,
      Plot[f, {x, xL, xR}, PlotLabel -> f, ImageSize -> Full],
      Graphics[{}, PlotLabel -> " ", ImageSize -> Full, 
       Options[Plot, AspectRatio]]],
    Button[
     Mouseover[Style["http://www.wolfram.com", "Hyperlink"], 
      Style["http://www.wolfram.com", "HyperlinkActive"]], 
     NotebookLocate[{URL["http://www.wolfram.com"], None}], 
     Appearance -> None]}
   ],

  Style["1D Definite Integral Calculator", "Function"],
  {{fp, True, "Plot the function"}, {False, True}, Checkbox, 
   ControlPlacement -> Bottom},
  {{np, 16, "NumberFormat"}, 5, 30, 1, ControlPlacement -> Bottom},
  {{nw, 16, "WorkingPrecision"}, 10, 30, 1, 
   ControlPlacement -> Bottom},
  {{xL, 0, "Lower Limit"}, InputField[#, Number, ImageSize -> Full] &},
  {{xR, 1, "Upper Limit"}, InputField[#, Number, ImageSize -> Full] &},
  {{f, Sin[x], "Function"}, InputField, ImageSize -> Full},
  Button[Style["Calculate", Green, Bold], 
   Res = SetPrecision[NIntegrate[f, {x, xL, xR}, WorkingPrecision -> nw], np];
   update = 1 - update],     (* triggers update *)
  {{Res, 0.4596976941318603`16, "Result"}, InputField, 
   Enabled -> False, ImageSize -> Full},
  {{update, 1}, None},
  TrackedSymbols :> {update, fp}],
 {350, Automatic}]    (* {width, height} of output *)

Mathematica graphics

Michael E2

Posted 2016-04-21T19:06:47.193

Reputation: 190 928

Thank you for the help. I am learning Mathematica and this is my only first week. So it takes sometime for me to understand all you suggested. You are right about the NumberForm and also ImageSize. I am working on understanding why using Manipulate DynamicModule at the same time would create a problem. Below I updated my code with some improvements and additional questions. – Erdem – 2016-04-24T16:34:32.927

1

@Erdem You're welcome. You've picked a somewhat complicated problem to start with. I learned by working my way through the first four tutorials under the "Tutorials" drop-down menu at the top of the Manipulate docs. Note that Manipulate constructs a DynamicModule for all its control variables. Variables that need persistent values are best put there, with ControlType -> None if no control is needed. Temporary scratch variables can be nested inside a DynamicModule or Module as in your code.

– Michael E2 – 2016-04-24T16:44:42.960

0

Thank you for the answers. I made a little change to avoid the Null from the if statement. I carried the If statement in front of the InputField for the plot. by using the suggestions: to get the FullSize plot, fixed the " " marks in the result section. Create a function DGL to make the calculation. Next step is to create a package and use the package instead of the function (still having problems with that)

What I did and what I would like to be able to do are;

To overcome the issue of non-numeric input breaking the calculation I used xL and xR check variables with NumberQ and if statement. This is working for the DGL function but not plotting. For example when I input "a" for Lower Limit, I get an error message for calculation but plotting part is failing. I am not sure why NumberQ is not updated before the plotting. This might be due to using Manipulate and DynamicModule together. I am not sure. Maybe if I can return xLcheck and xRcheck from DGL function it will be ok but I don't know how to take out more than one variable from a function (Yet!!!). Even if I can do that I would like to understand why the way I am doing is not working.

Also I used IntegerPart and Re commands for WorkingPrecision and SetPrecision.

I moved the function plotting checkbox inside the column.

Manipulate[DynamicModule[{f = Sin[x], xR = 1, xL = 0, 
Res = 0.4596976941318603`16}, Column[
{Style["1D Definite Integral Calculator", "Function"] logo,
 Row[{"Lower Limit ", InputField[Dynamic[xL], Number]}, Spacer[5]],
 Row[{"Upper Limit ", InputField[Dynamic[xR], Number]}, Spacer[5]],
 Row[{"Function  ", InputField[Dynamic[f]]}, Spacer[20]], 
 Button[Style["Calculate", Green, Bold], 
  Dynamic[Res = DGL[f, xR, xL, np, nw];]], 
 Row[{"Result", InputField[Dynamic[Res], Enabled -> False]}, 
  Spacer[51]],
 Row[{"Plot the Function ", Checkbox[Dynamic[fp], {False, True}]}],
 fp,
 xLcheck = NumberQ[xL], xRcheck = NumberQ[xR],
 If[fp == True && xLcheck == True && xRcheck == True, 
  InputField[
   Dynamic[Plot[f, {x, xL, xR}, Dynamic[PlotLabel -> f], 
     ImageSize -> Full]], FieldSize -> {30, 15}]],

  Button[
  Mouseover[Style["http://www.wolfram.com", "Hyperlink"], 
   Style["http://www.wolfram.com", "HyperlinkActive"]], 
  NotebookLocate[{URL["http://www.wolfram.com"], None}], 
  Appearance -> None]
 }]],{{np, 16, "NumberFormat"}, ControlPlacement -> Bottom},{{nw, 16, "WorkingPrecision"}, ControlPlacement -> Bottom},
 Initialization :> (
DGL[f_, xR_, xL_, np_, nw_] := Module[{xLcheck, xRcheck},
  xLcheck = NumberQ[xL];
  xRcheck = NumberQ[xR];
  If[xLcheck == True && xRcheck == True ,
   ResultTF = 
    SetPrecision[
     NIntegrate[f, {x, xL, xR}, 
      WorkingPrecision -> Re[IntegerPart[nw]]], 
     Re[IntegerPart[np]]], 
   "Enter numeric inputs for Lower and Upper Limits"]]
) ]

Thank you for the help again. I hope these will be helpful to other people too.

Erdem

Posted 2016-04-21T19:06:47.193

Reputation: 849