Group Abstract Group Abstract

Message Boards Message Boards

[?] Modify frametick units of timeseries plot with dynamic plotrange?

Posted 9 years ago
POSTED BY: Eric Laarz
5 Replies

Here is the same code that will dynamically change the ticks as the sliders are moved. The key to making this work is to get rid of the Show[]. The DateListPlot must be in the Dynamic[] so it gets redrawn when the sliders change. Show[] seems to limit what can be redrawn and messes up the format of the ticks. I added a popup at the bottom for the number of ticks. This version (even if you delete the popup and fix the number of ticks) is much better than the previous one (above).

DynamicModule[{data, xmin, xmax, ymin, ymax, ticks, ticknum = 4, int, 
  w = 400, h = 30}, 
 data = TimeSeries[FinancialData["IBM", "Jan. 1, 2004"]];
 ymin = Min[data["Values"]];
 ymax = Max[data["Values"]]; {xmin, xmax} = {data["FirstTime"], 
   data["LastTime"]};
 int = {xmin, xmax};
 ticks = (xmax - xmin)/5*Range[4] + xmin;
 Column[{Dynamic[
    DateListPlot[data, ImageSize -> w, Joined -> True, 
     FrameTicks -> {Automatic, {ticks, None}}, 
     DateTicksFormat -> {"MonthNameShort", " ", "YearShort"}, 
     GridLines -> Automatic, PlotRange -> {int, Automatic}]], 
   IntervalSlider[
    Dynamic[int, {(int = #) &, (ticks = (int[[2]] - 
              int[[1]])/(ticknum + 1)*Range[ticknum] + 
          int[[1]]) &}], {xmin, xmax, 1}, ImageSize -> {400, 30}, 
    MinIntervalSize -> 1], 
   DateListPlot[data, Frame -> False, Axes -> False, 
    ImageSize -> {w, h}, AspectRatio -> h/w, Joined -> True, 
    Epilog -> {Opacity[0.5], Orange, 
      Dynamic[Rectangle @@ Thread[{int, {ymin, ymax}}]]}], 
   Row[{"Number of Ticks: ", 
     PopupMenu[Dynamic[ticknum], Range[10]]}]}]]

The only downside of the version above is that if you change the number of ticks in the popup, it does not redraw the plot -- you must move (or just click on) a slider. If you want the popup to instantly change the graph, you must force a variable inside the plot Dynamic[DateListPlot[...]] to change (such as the variable ticks). I added a function to the popup dynamic that will run after selection to change the variable ticks. This forces the redraw and I believe it has the behavior you are looking for.

DynamicModule[{data, xmin, xmax, ymin, ymax, ticks, ticknum = 4, int, 
  w = 400, h = 30}, 
 data = TimeSeries[FinancialData["IBM", "Jan. 1, 2004"]];
 ymin = Min[data["Values"]];
 ymax = Max[data["Values"]]; {xmin, xmax} = {data["FirstTime"], 
   data["LastTime"]};
 int = {xmin, xmax};
 ticks = (xmax - xmin)/5*Range[4] + xmin;
 Column[{Dynamic[
    DateListPlot[data, ImageSize -> w, Joined -> True, 
     FrameTicks -> {Automatic, {ticks, None}}, 
     DateTicksFormat -> {"MonthNameShort", " ", "YearShort"}, 
     GridLines -> Automatic, PlotRange -> {int, Automatic}]], 
   IntervalSlider[
    Dynamic[int, {(int = #) &, (ticks = (int[[2]] - 
              int[[1]])/(ticknum + 1)*Range[ticknum] + 
          int[[1]]) &}], {xmin, xmax, 1}, ImageSize -> {400, 30}, 
    MinIntervalSize -> 1], 
   DateListPlot[data, Frame -> False, Axes -> False, 
    ImageSize -> {w, h}, AspectRatio -> h/w, Joined -> True, 
    Epilog -> {Opacity[0.5], Orange, 
      Dynamic[Rectangle @@ Thread[{int, {ymin, ymax}}]]}], 
   Row[{"Number of Ticks: ", 
     PopupMenu[
      Dynamic[ticknum, {(ticknum = #) &, (ticks = (int[[2]] - 
                int[[1]])/(ticknum + 1)*Range[ticknum] + 
            int[[1]]) &}], Range[10]]}]}]]
POSTED BY: Neil Singer

Here is a gif of the code running:

enter image description here

POSTED BY: Neil Singer

Eric,

Your bug is that you need to initialize the variable "int". Evidently DateListPlot only picks the ticks based on the original first plot (before the dynamic) This code does what you want. I made an unrelated "improvement" by using a TimeSeries instead of raw data -- it makes the code a bit more readable and it will allow you to use all of the timeseries scaling and shifting options, i.e. if you want to later add a "shift" slider. For financial data you can also consider EventSeries so it does not interpolate between data. I added a date format which you can modify. A further improvement would be to dynamically change the number of ticks so that as you zoom in the ticks change. I'll try that next.

DynamicModule[{data, xmin, xmax, ymin, ymax, int, w = 400, h = 30}, 
 data = TimeSeries[FinancialData["IBM", "Jan. 1, 2004"]];
 ymin = Min[data["Values"]];
 ymax = Max[data["Values"]]; {xmin, xmax} = {data["FirstTime"], 
   data["LastTime"]};
 int = {xmin, xmax};
 Column[{Show[
    DateListPlot[data, ImageSize -> w, Joined -> True, 
     FrameTicks -> Automatic, 
     DateTicksFormat -> {"MonthNameShort", " ", "YearShort"}, 
     GridLines -> Automatic], 
    PlotRange -> {Dynamic[int], {0, 192.084754`}}], 
   IntervalSlider[Dynamic[int], {xmin, xmax, 1}, 
    ImageSize -> {400, 30}, MinIntervalSize -> 1], 
   DateListPlot[data, Frame -> False, Axes -> False, 
    ImageSize -> {w, h}, AspectRatio -> h/w, Joined -> True, 
    Epilog -> {Opacity[0.5], Orange, 
      Dynamic[Rectangle @@ Thread[{int, {ymin, ymax}}]]}]}]]

Regards

POSTED BY: Neil Singer

Glad I could help and I appreciate your note. I learned some interesting things about Dynamic by figuring this out! I have had related issues before that I did not fully understand.

Now that the ticks can be dynamically redrawn, you could further improve this by having the tick recomputation be a function and have it return some "smart" values so the number of ticks is chosen to give more intuitive spacing (for example, years when zoomed out, quarters when zoomed in, weeks when really zoomed in, etc.).

Regards,

Neil

POSTED BY: Neil Singer
Posted 9 years ago

Neil, your fantastic input is very much appreciated! Not only does it provide a great solution to the problems I have posted, it's also presented in a very instructive way. I did learn so much just by following your reasoning behind your problem solving choices ! ! Thank you!

Regards Eric

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