4
$\begingroup$

Dynamic functionally of Mathematica it is really very confusing and I tried and spent a lot of time reading and reading but still not figuring it out comfortably. I am trying to write a function that does an extraction (kind of zoom) of data within desire range.

let us say I have the following data:

data1 = Table[
   PDF[NormalDistribution[3.5, .8], i] + 
    PDF[NormalDistribution[6, 1], i], {i, -5, 15, .01}];
noise = RandomReal /@ RandomReal[{-0.2, .2}, Length[data1]];
data2 = data1 + noise;

My goal is to write a function that does extraction (zoom) easily.

I have wrote this function, which does the job perfectly.

Clear[zoom];
zoom[list_List] := DynamicModule[{pt1 = {100, 0}, pt2 = {300, 0}},
  Row[{LocatorPane[Dynamic@{pt1, pt2}, 
     ListLinePlot[list, ImageSize -> 400, 
      Epilog -> 
       Dynamic@{InfiniteLine[{pt1, pt1 + {0, 1}}], 
         InfiniteLine[{pt2, pt2 + {0, 1}}]}, PlotRange -> All]
     ], Dynamic@
     ListLinePlot[
      zoomlist= 
       If[Length[Dimensions@list] > 1, 
        list[[;; , IntegerPart@pt1[[1]] ;; IntegerPart@pt2[[1]]    ]],
         list[[IntegerPart@pt1[[1]] ;; IntegerPart@pt2[[1]]    ]]], 
      PlotRange -> All, ImageSize -> 400]}]]

I can now perform zoom by evaluating:

zoom[data2]

The problem I am facing is that if I want to put the Dynamic object of extracting the data (zoomlist) in a separate line, I have to suppress the output using semicolon (otherwise the output will be huge).

If the function is in this shape:

    Clear[zoom]; 
zoom[list_List] := DynamicModule[{pt1 = {100, 0}, pt2 = {300, 0}},
  Dynamic[
   zoomlist = 
    If[Length[Dimensions@list] > 1, 
     list[[;; , IntegerPart@pt1[[1]] ;; IntegerPart@pt2[[1]]]], 
     list[[IntegerPart@pt1[[1]] ;; IntegerPart@pt2[[1]]]]]]; 
  Row[{LocatorPane[Dynamic@{pt1, pt2}, 
     ListLinePlot[list, ImageSize -> 400, 
      Epilog -> 
       Dynamic@{InfiniteLine[{pt1, pt1 + {0, 1}}], 
         InfiniteLine[{pt2, pt2 + {0, 1}}]}, PlotRange -> All]], 
    Dynamic@ListLinePlot[zoomlist, PlotRange -> All, 
      ImageSize -> 400]}]]

In this case Dynamic of zoomlist does not work because it is not outputted.

What would be a good solution (workaround) to this issue.

Thank you

$\endgroup$
4
$\begingroup$

You can make the CompoundExpression Dynamic:

zoom[list_List] := 
 DynamicModule[{pt1 = {100, 0}, pt2 = {300, 0}}, 
  Dynamic[zoomlist = 
    If[Length[Dimensions@list] > 1, 
     list[[;; , IntegerPart@pt1[[1]] ;; IntegerPart@pt2[[1]]]], 
     list[[IntegerPart@pt1[[1]] ;; IntegerPart@pt2[[1]]]]];
   Row[{LocatorPane[Dynamic@{pt1, pt2}, 
      ListLinePlot[list, ImageSize -> 400, 
       Epilog -> 
        Dynamic@{InfiniteLine[{pt1, pt1 + {0, 1}}], 
          InfiniteLine[{pt2, pt2 + {0, 1}}]}, PlotRange -> All]], 
     Dynamic@ListLinePlot[zoomlist, PlotRange -> All, 
       ImageSize -> 400]}]]]

You could also use DynamicWrapper with an invisible display as a part of the Row:

Clear[zoom];
zoom[list_List] := 
 DynamicModule[{pt1 = {100, 0}, pt2 = {300, 0}},
  Row[{DynamicWrapper["", 
     zoomlist = 
       If[Length[Dimensions@list] > 1, 
        list[[;; , IntegerPart@pt1[[1]] ;; IntegerPart@pt2[[1]]]], 
        list[[IntegerPart@pt1[[1]] ;; IntegerPart@pt2[[1]]]]];], 
    LocatorPane[Dynamic@{pt1, pt2}, 
     ListLinePlot[list, ImageSize -> 400, 
      Epilog -> 
       Dynamic@{InfiniteLine[{pt1, pt1 + {0, 1}}], 
         InfiniteLine[{pt2, pt2 + {0, 1}}]}, PlotRange -> All]],
    Dynamic@ListLinePlot[zoomlist, PlotRange -> All, ImageSize -> 400]}]]

Or you update zoomlist within the ListLinePlot:

Clear[zoom];
zoom[list_List] := 
 DynamicModule[{pt1 = {100, 0}, pt2 = {300, 0}}, 
  Row[{LocatorPane[Dynamic@{pt1, pt2}, 
     ListLinePlot[list, ImageSize -> 400, 
      Epilog -> 
       Dynamic@{InfiniteLine[{pt1, pt1 + {0, 1}}], 
         InfiniteLine[{pt2, pt2 + {0, 1}}]}, PlotRange -> All]], 
    Dynamic[ListLinePlot[
      zoomlist = 
       If[Length[Dimensions@list] > 1, 
        list[[;; , IntegerPart@pt1[[1]] ;; IntegerPart@pt2[[1]]]], 
        list[[IntegerPart@pt1[[1]] ;; IntegerPart@pt2[[1]]]]], 
      PlotRange -> All, ImageSize -> 400]]}]]
$\endgroup$
  • 1
    $\begingroup$ DynamicWrapper is the good solution. The first one (CompoundExpression ) means reevaluate every thing which could delay the performance for large data. Thanks $\endgroup$ – Algohi Oct 17 '15 at 4:37
  • 1
    $\begingroup$ @Algohi Yes, the first one basically behaves similar to a simple Manipulate and the possible advantages of using DynamicModule are lost. $\endgroup$ – Karsten 7. Oct 17 '15 at 4:50
  • $\begingroup$ @Algohi You might add a TrackedSymbols options to DynamicWrapper, to ensure best performance within a bigger DynamicModule. $\endgroup$ – Karsten 7. Oct 17 '15 at 4:54
  • $\begingroup$ Thanks, but note that zoomlist should not be localized. The point is to extract the zoomed data (zoomlist) for forward usage. $\endgroup$ – Algohi Oct 17 '15 at 5:58
  • $\begingroup$ What is the point of using TrackedSymbols? The whole variable symbols are pt1 and pt2. $\endgroup$ – Algohi Oct 31 '15 at 16:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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