Message Boards Message Boards

0
|
5274 Views
|
2 Replies
|
1 Total Likes
View groups...
Share
Share this post:

Make ListPlot update with Locator positions in a DynamicModule?

Posted 4 years ago

In the example below, the ListPlot is intended to show straight lines between the Locator positions chosen with a LocatorPane. What must be done to allow the ListPlot to update dynamically? A table of point values is displayed on the right using Grid. To make the Grid update dynamically, putting Dynamic@ in front was sufficient. But that doesn't work for the ListPlot. enter image description here

Moving the locator positions and the values in the Grid will update. How to make the lines of the ListPlot also update?

Here is the code

plotBackground = Plot[Sin[x], {x, 0, 6}];

DynamicModule[{pt = {{0.5, 0.5}, {1.5, 1.0}, {3.1, 0}}, plotInterp}
 , plotInterp = 
  ListLinePlot[pt, InterpolationOrder -> 1, PlotStyle -> Red]; 
 {LocatorPane[Dynamic[pt], 
   Dynamic@Show[{plotBackground, plotInterp}, ImageSize -> 600], 
   LocatorAutoCreate -> True]
  , Dynamic@Grid[Prepend[pt, {"x", "y"}], Frame -> All] 
  }
 ]
Attachments:
POSTED BY: Robert McHugh
2 Replies
Posted 4 years ago

Thanks, that works and helps gets me pointed in the right direction; however, there are still a few concepts that I am not clear on. Below is a description of where my confusion lies.

The Mathematica documentation, e.g. Advanced DynamicFunctionality, may hold the answers to my misunderstandings, but I am having difficulties making the connections between the information in the documentation and my objectives. Below is a paragraph from the documentation:

DynamicModule, on the other hand, creates an environment in which evaluations of expressions in Dynamic that appear within the body of the DynamicModule are like additional lines in the compound expression in the previous example. From one dynamic update to the next the values of all the variables are preserved, just as if the separate evaluations were separate lines in a compound expression, all within the local variable context created by DynamicModule.

In my first attempt, I wanted the DynamicModule to compute values for the variable listInterp using the positions of the locator points. The paragraph above discusses "From one dynamic update to the next values of all the variables are preserved."

Could someone expand on the documentation and explain why the listInterp variable cannot be updated as in my first attempt?

I did follow the direction presented by @Bill Nelson and wrote some helper functions that take the list of locator points as input. Those seem to work and Dynamically update as desired. Using Bill's direction I was able to extend the code. But, still not clear to me what can be put in the body of the DynamicModule.

Below and attached are the revised code.

Update results

plotBackground = 
  Plot[Sin[x], {x, 0, 6}, PlotRange -> {{0, 6}, {-1, +1}} ];
orderPts[tab_] := Sort[tab, #1[[1]] < #2[[1]] &] 
makeListPlot[pts_] := 
 ListLinePlot[orderPts[pts], InterpolationOrder -> 1, PlotStyle -> Red]
makeInterpFunc[pts_] := Module[{ptsExtended},
  ptsExtended = 
   If[First[pts][[1]] <= 0, pts, Prepend[pts, {0, First[pts][[2]] }]];
  ptsExtended = 
   If[Last[pts][[1]] >= 6,  ptsExtended, 
    Prepend[ptsExtended, {6, Last[pts][[2]] }]];
  Interpolation[ptsExtended, InterpolationOrder -> 1]
  ]
makeDeviationPlot[pts_] := 
 Plot[  Evaluate[makeInterpFunc[orderPts[pts]]][x]  - Sin[x], {x, 0, 
   6}, PlotRange -> {{0, 6}, {-1, +1}}, ImageSize -> 600, 
  PlotLabel -> Style["Deviation", Bold, Black, 14] ]
makeGrid[pts_] := Module[{finterp, fdev, gridData},
  finterp = makeInterpFunc[pts];
  gridData = 
   Map[NumberForm[#, {4, 3}] &,  {#[[1]], #[[2]],  
       finterp[#[[1]]] - Sin[#[[1]]]} & /@ pts, {2} ]; 
  Grid[Prepend[orderPts[gridData], {"x", "y", "dev"}], Frame -> All]
  ]
showOptions = 
  Sequence[ImageSize -> 600, 
   PlotLabel -> 
    Style["Data and Interpolating Function", Bold, Black, 14]];

DynamicModule[{pt = {{0.5, 0.5}, {1.57, 1.}, {3.14, 0}}},
  {LocatorPane[Dynamic[pt], 
   Dynamic@ Show[{plotBackground, makeListPlot[pt]}, showOptions], 
   LocatorAutoCreate -> True]
  , Dynamic@makeGrid[pt]
  , Dynamic@ Show@makeDeviationPlot[pt]
  }
 ]

Another example of my misunderstandings, is it possible to make a local variable, ptsOrdered, which has the sorted values of the locator points? Then ptsOrdered could be passed to each of the functions. Instead, (in the working code above), the ptsOrdered function is called multiple times, inside each of the different functions that use pts.

DynamicModule[{pt = {{0.5, 0.5}, {1.57, 1.}, {3.14, 0}}, ptsOrdered},
 ptsOrdered = orderPts[pt];
  {LocatorPane[Dynamic[pt], 
   Dynamic@ Show[{plotBackground, makeListPlot[pt]}, showOptions], 
   LocatorAutoCreate -> True]
  , Dynamic@makeGrid[ptsOrdered]
  , Dynamic@ Show@makeDeviationPlot[pt]
  }
 ]

Looking for additional explanations or pointers to specific sections of the documentation or examples. All comments are welcome.

Attachments:
POSTED BY: Robert McHugh
Posted 4 years ago

Try

plotBackground=Plot[Sin[x],{x,0,6}];
DynamicModule[{pt={{0.5,0.5},{1.57,1.},{3.14,0}}},
{LocatorPane[Dynamic[pt],Dynamic@Show[{
  plotBackground,
  ListLinePlot[pt,InterpolationOrder->1,PlotStyle->Red]},
  ImageSize->600],LocatorAutoCreate->True],
  Dynamic@Grid[Prepend[pt,{"x","y"}],Frame->All]}]

and see if that works for you

POSTED BY: Bill Nelson
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract