Interactive Time Series Plotting

BeakerX comes with its own charting library for creating interactive plots that you can click on, drag, zoom, and annotate. Right-click brings up a menu allowing export to SVG and PNG.

You can access it from any language, but the most complete documentation is in Groovy.

This tutorial shows you how to use and how to interact with it, with step-by-step examples.

Custom Plot Example

Normally one expects long-term interest rates to be higher than short-term rates. But there are times when the spread between the rates goes negative. Two such incidents are visible in the below chart of freely available historical data on US Treasury interest rates.

Wikipedia says:

Strongly inverted Yield Curves have historically preceded economic depressions.

First Prepare the Data

In [1]:
rates = new CsvPlotReader().read("demoResources/interest-rates.csv")
def f = new java.text.SimpleDateFormat("yyyy MM dd")
lehmanDate = f.parse("2008 09 15")
bubbleBottomDate = f.parse("2002 10 09")
inversion1 = [f.parse("2000 07 22"), f.parse("2001 02 16")]
inversion2 = [f.parse("2006 08 01"), f.parse("2007 06 07")]
def size = rates.size()
(0 ..< size).each{row = rates[it]; row.spread = row.y10 - row.m3}


Then Build the Top and Bottom Plots

In [2]:
def ch = new Crosshair(color: Color.gray, width: 2, style: StrokeType.DOT)

// The top plot has 2 lines.
p1 = new TimePlot(yLabel: "Interest Rate", crosshair: ch)
p1 << new Line(x: rates.time, y: rates.m3, displayName: "3 month")
p1 << new Line(x: rates.time, y: rates.y10, displayName: "10 year")

// The bottom plot has an area filled in.
p2 = new TimePlot(yLabel: "Spread", crosshair: ch)
p2 << new Area(x: rates.time, y: rates.spread, color: new Color(120, 60, 0))

// Highlight the inversion intervals
def b1 = new ConstantBand(x: inversion1, color: new Color(240, 100, 100, 55))
def b2 = new ConstantBand(x: inversion2, color: new Color(240, 100, 100, 55))

// Add notation and line for Lehman Bankruptcy.
p1 << new Text(x: lehmanDate, y: 7.5, text: "Lehman Brothers Bankruptcy")
def l1 = new ConstantLine(x: lehmanDate, style: StrokeType.DOT, color: Color.gray)

// Add notation and line for Stocks Nadir.
p1 << new Text(x: bubbleBottomDate, y: 5.75, text: "Stocks Hit Bottom")
def l2 = new ConstantLine(x: bubbleBottomDate, style: StrokeType.DOT, color: Color.gray)

// add the notations and highlight bands to both plots
p1 << l1 << l2 << b1 << b2
p2 << l1 << l2 << b1 << b2

In [3]:
// Then use a CombinedPlot to get stacked plots with linked X axis.
def c = new CombinedPlot(title: "US Treasuries", initWidth: 1000)

// add both plots to the combined plot, and including their relative heights.
c.add(p1, 3)
c.add(p2, 1)

Simple Automatic Plot

In [4]:
// The simplest chart function with all defaults:
new SimpleTimePlot(rates, ["y1", "y10"])

Scatter Plot

In [5]:
def c = new Color(120, 120, 120, 100)
new Plot() << new Points(x: rates.y1, y: rates.y30, displayName: "y1 vs y30") \
           << new Points(x: rates.m3, y: rates.y5, displayName: "m3 vs y5") \
           << new Line(x: rates.m3, y: rates.y5, color: c) \
           << new Line(x: rates.y1, y: rates.y30, color: c)

First, let’s see how to navigate in a plot. The following navigation methods are supported


Click at some empty place of the plot, then drag the view around.


Click to start interacting with the chart. Then Scroll your mouse-wheel to zoom in / out. Zoom will be centered at your mouse cursor, and scaled proportionally at each side.On a Mac laptop, drag two fingers vertically up and down to zoom.

You may choose to zoom along a single (x / y), To zoom along the x-axis, move the mouse cursor below the x-axis, and then zoom. To zoom along the y-axis, move the mouse cursor left to the y-axis, and then zoom.

Box Zoom

You can zoom to a selected rectangle region. Right click the mouse and drag out the box you’d like to zoom into. You do NOT necessarily need to drag the box from the left-top to the bottom-right. Any direction will do.

Reset Zoom Focus

Double click anywhere on the plot background to reset the focus range to its default values.

It is possible to reset the focused range of only the x / y axis! To reset the zoom along the x-axis, double click anywhere below the x-axis. To reset the zoom along the y-axis, double click anywhere left to the y-axis.


Now it would be a good time for you to try the above interactions in the following demo plot. How about some challenges? :)

Okay.. Challenge accepted. Now use the navigation method to:

  • Find and display an orange ‘T’ character without distortion!
  • Find and display a blue ‘S’ character without distortion!
In [6]:
p = new Plot()
p << new Line(x:[1000, 10000], y:[10000, 10000], width: 10, color:
p << new Line(x:[5500, 5500], y:[10000, 9999], width: 10, color:
p << new Line(x:[14000, 14000, 15002], y:[900, 901, 901], width: 1, color:
p << new Line(x:[14000, 15002, 15002], y:[900, 900, 899], width: 1, color:
p << new Line(x:[14000, 15002], y:[899, 899], width: 1, color: