3
$\begingroup$

I'm trying to build a custom dynamic interface that reads data from a file as a Dataset, converts that to TemporalData, then plots the data along with a MovingAverage with a dynamic sample window. I'm having issues with the behavior and I think it is related to Dynamic. It is somewhat complicated so I created a very simplified version for this post. This version creates a random Dataset rather than reading a file. When run, the first thing that happens is to display a small palette notebook that has an ActionMenu. The 1st action is used to choose the "Create Temporal Data". This must be done before trying to plot. I don't have any error checking at this time. The 2nd is used to CreatePalette and plot the data within that palette notebook. The 2nd action is what is failing. Error messages are printed in the Messages window. I believe the fundamental error message is from Rule::argr. I've tried various placements of Dynamic, but nothing I've tried resolves the issue. The unusual thing is that when I move the Control to change the sample window width, nSamp, I can see it changing in the palette notebook. But, neither MovingAverage or DateListPlot evaluate.

The main function is gui2[]. There are 2 helper functions buildDataset and toTemporalData. There are also a number of Echo's to the Message window for debugging.

Another related question is why did I have to wrap DateListPlot with Show to enable dynamic updating of PlotRange via IntervalSlider? Seems like this should be possible within DateListPlot's own PlotRange option.

I'm running Win 11 and Wolfram 14.1.

buildDataset[n_Integer] :=
 (
  SeedRandom[1234];
  Dataset[
   AssociationThread[{"Date", "p1", "p2"} -> #] & /@ 
    Transpose[{DateRange[Today - Quantity[n - 1, "Days"], Today], 
      RandomReal[{50, 100}, n], RandomReal[{0, 50}, n]}]]
  )

toTemporalData[ds_Dataset] :=
 Module[{p1, p2, dates},
  {dates, p1, p2} = {ds[All, "Date"], ds[All, "p1"], ds[All, "p2"]} //
     Normal;
  TemporalData[{p1, p2}, {dates}, 
   MetaInformation -> {"PathNames" -> {"p1", "p2"}}]
  ]

gui2[] :=
 (
  FrontEndExecute[
   {(* Clear Message Notebook before continuing *)
    FrontEndToken[FrontEnd`MessagesNotebook[], "SelectAll"],
    FrontEndToken[FrontEnd`MessagesNotebook[], "Clear"]
    }
   ];
  CreatePalette[
   DynamicModule[{td, sd, ed, nSamp, xRng, yRng, mAvg, 
     daySec = 24 60 60, w = 400, h = 30},
    ActionMenu[
     Style["Select from the menu:", FontSize -> 18],
     {
      Style["Create Temporal Data", FontSize -> 14] :>
       (
        Echo["Create Temporal Data"];
        Echo[td = toTemporalData[buildDataset[25]]];
        yRng = QuantityMagnitude@MinMax[td];
        {sd, ed} = {td["FirstTime"], td["LastTime"]};
        ),
      Style["Plot TemporalData", FontSize -> 14] :>
       (
        Echo["Plot TemporalData"];
        Echo[{sd, ed}];
        Echo[yRng];
        Echo[DayCount[td["FirstDate"], Today] + 1];
        Echo[td];
        CreatePalette[
         DynamicModule[{},
          Column@
           {
            Dynamic@nSamp,(* For debugging *)
            Dynamic@xRng,(* For debugging *)
            
            MovingAverage[TimeSeries[td["Path", "p1"]], 
             Dynamic@nSamp],(* For debugging *)
            Show[
             DateListPlot[
              {TimeSeries[td["Path", "p1"]], 
               MovingAverage[TimeSeries[td["Path", "p1"]],(*7*)
                Dynamic@nSamp]},
              Joined -> {False, True},
              GridLines -> Automatic,
              ImageSize -> w,
              Background -> White,
              PlotHighlighting -> None
              ],
             PlotRange -> {Dynamic[xRng], yRng}
             ],
            
            IntervalSlider[Dynamic[xRng], {sd, ed, daySec}, 
             ImageSize -> {w, h}, Method -> "Push", 
             MinIntervalSize -> daySec],
            Row[{Control[{{nSamp, 7}, 2, 10, 1}], "   nSamp"}]
            },
          InheritScope -> True
          ],
         Saveable -> False,
         WindowTitle -> "Paths",
         
         WindowElements -> {"VerticalScrollBar", 
           "HorizontalScrollBar"},
         WindowMargins -> Automatic,
         WindowFloating -> True,
         WindowSize -> {w, 500}
         ]
        )
      }
     ],
    InheritScope -> True
    ],
   Saveable -> False,
   WindowMargins -> {{100, Automatic}, {Automatic, 100}}
   ]
  )

gui2[]

$\endgroup$
0

1 Answer 1

4
$\begingroup$

A shorter example showing the problem is this:

ts = TimeSeries[RandomReal[1, 100]]; 

(* Works as expected *)
Manipulate[MovingAverage[ts, k], {{k, 5}, 1, 10, 1}]

(* Same problem as yours *)
Manipulate[MovingAverage[ts, Dynamic[k]], {{k, 5}, 1, 10, 1}]

This is a somehow delicate issue, but the problem is in your placement of Dynamic. Read more about it in Introduction to Dynamic: Where Should Dynamic Be Placed in an Expression?.

The usual solution is to either move Dynamic to a more outer place, or define a custom function:

(* Works as expected *)
Manipulate[Dynamic[MovingAverage[ts, k]], {{k, 5}, 1, 10, 1}]

(* Works as expected *)
movingAverage[ts_, Dynamic[n_]] := MovingAverage[ts, n]
Manipulate[movingAverage[ts, Dynamic[k]], {{k, 5}, 1, 10, 1}]

Both of the solutions work also for your complicated case.

$\endgroup$

Your Answer

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

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