I have been trying to put together something that allows me to extract points from a ListPlot in order to use them in further computations. My current approach is to select points with a Locator[]. This works fine for displaying points, but I cannot figure out how to extract numerical values from a construct with head Dynamic[]. Below is a self-contained example. By dragging the gray locator, you should be able to select points (indicated by the pink locator and stored in q
, a list of two elements). This is the second line below the plot. Now I would like to pass q[[2]] to a function, or perhaps simply display it. However, Mathematica treats q
as a single entity with head Dynamic
, and thus taking the second part is impossible (hence the error message). Can anyone shed light on how to convert q
into a regular list?
EuclideanDistanceMod[p1_List, p2_List, fac_: {1, 1}] /;
Length[p1] == Length[p2] :=
Plus @@ (fac.MapThread[Abs[#1 - #2]^2 &, {p1, p2}]) // Sqrt;
test1 = {{1.`, 6.340196001221532`}, {1.`,
13.78779876355869`}, {1.045`, 6.2634018978377295`}, {1.045`,
13.754947081416544`}, {1.09`, 6.178367702583522`}, {1.09`,
13.72055251752498`}, {1.135`, 1.8183153704413153`}, {1.135`,
6.082497198000075`}, {1.135`, 13.684582525399742`}, {1.18`,
1.6809452373465104`}, {1.18`, 5.971583107298081`}, {1.18`,
13.646996905469383`}, {1.225`, 1.9480537697339537`}, {1.225`,
5.838386922625636`}, {1.225`, 13.607746407088161`}, {1.27`,
2.1183174369679234`}, {1.27`, 5.669799095595362`}, {1.27`,
13.566771130126131`}, {1.315`, 2.2572975468163463`}, {1.315`,
5.444014254828522`}, {1.315`, 13.523998701347882`}, {1.36`,
2.380307009155079`}, {1.36`, 5.153024664297602`}, {1.36`,
13.479342200528283`}, {1.405`, 2.4941312539733285`}, {1.405`,
4.861423833512566`}, {1.405`, 13.432697814928654`}, {1.45`,
2.6028066447609426`}, {1.45`, 4.619367407525507`}, {1.45`,
13.383942212133244`}};
DynamicModule[{p = {1.2, 10}, q = {1.3, 11}},
q := Dynamic@
First@test1[[
Ordering[{#, EuclideanDistanceMod[p, #, {1, .1}]} & /@ test1,
1, #1[[2]] < #2[[2]] &]]];
Grid[{{Show[{ListPlot[test1, Frame -> True, ImageSize -> 300],
Graphics@Locator[Dynamic[p]],
Graphics@
Locator[q, Appearance -> {Small},
Background -> Pink]}]}, {Dynamic@p}, {q},{q[[2]]}}]]
In dart and flutter, this example converts a list of dynamic types to a list of Strings. map() is used to iterate over a list of dynamic strings. To convert each element in the map to a String, toString() is used. Finally, use the toList() method to return a list.
In order to convert a string representation of a list to an actual list in Flutter, just import dart:convert and call json. decode().
There are several ways to extract values from a dynamic expression. What you probably want is Setting
(documentation), which resolves all dynamic values into their values at the time Setting
is evaluated.
In[75]:= Slider[Dynamic[x]] (* evaluate then move the slider *)
In[76]:= FullForm[Dynamic[x]]
Out[76]//FullForm= Dynamic[x]
In[77]:= FullForm[Setting[Dynamic[x]]]
Out[77]//FullForm= 0.384`
Here's a slightly more complicated example:
DynamicModule[{x},
{Dynamic[x], Slider[Dynamic[x]],
Button["Set y to the current value of x", y = Setting[Dynamic[x]]]}
]
If you evaluate the above expression, move the slider and then click the button, the current value of x
as set by the slider is assigned to y
. If you then move the slider again, the value of y
doesn't change until you update it again by clicking the button.
Instead of assigning to a variable, you can of course paste values into the notebook, call a function, export a file, etc.
After a little more research, it appears that the answer revolves around the fact that Dynamic[] is a wrapper for updating and displaying the expression. Any computations that you want dynamically updated must be placed inside the wrapper: for instance, instead of doing something like q = Dynamic[p] + 1
one should use something like Dynamic[q = p + 1; q]}]
. For my example, where I wanted to split q
into two parts, here's the updated code:
DynamicModule[{p = {1.2, 10}, q = {1.3, 11}, qq, q1, q2},
q := Dynamic[
qq = First@
test1[[Ordering[{#, EuclideanDistanceMod[p, #, {1, .1}]} & /@
test1, 1, #1[[2]] < #2[[2]] &]]];
{q1, q2} = qq;
qq
];
Grid[{{Show[{ListPlot[test1, Frame -> True, ImageSize -> 300],
Graphics@Locator[Dynamic[p]],
Graphics@
Locator[q, Appearance -> {Small},
Background -> Pink]}]}, {Dynamic@p}, {Dynamic@q}, {Dynamic@
q1}}]]
If I am still missing something, or if there's a cleaner way to do this, I welcome any suggestions...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With