Skip to content

High level API

andreaferretti edited this page Feb 16, 2015 · 9 revisions

High level API (graphs)

Based on the shapes above, we can construct more complex graphs. At this level, the API assume one has a collection of data that has to be shown on a graph, and take care of normalizing the data, so that for instance if you display multiple line graphs on the same chart, the scales are normalized.

All graph objects - that is, objects returned by some graph functions - have the field curves that contains an array, and possibly more fields, depending on the graph. Each element of curves has the properties item, which is a reference to the corresponding data item, index, and one or more field containing shape objects, for instance sector in the case of the pie graph, or line and area for the line charts. Thus, a graph object has the shape:

{
  curves: [
    {
      item: <datum>,
      index: <index>,
      <label>: <shape object>,
      ...
    },
    ...
  ],
  ...
}

All of the following graph APIs accept a parameter named compute which is a hash table of functions that should be evaluated for each curve to be drawn. A typical use would be to compute a color based on the index or the data item, like:

{
  compute: {
    color: function(i, item) {
      ...
    }
  }
}

All curves in the curves array will contain the corresponding properties in addition to index and item; for instance in the example above each curve will have the color property. Each function in the compute hash receives two parameters index and item; where it makes sense it also receives a third parameter group containing a group index (for items that are clustered).

This feature is useful if the resulting graph will be rendered with a somewhat static template engine, such as Mustache, that needs to have all fields precomputed. More flexible template engines, such as the one in Ractive, allow custom expressions to be evaluated in templates, so there will be generally no need for the compute parameter.

Pie graph

The Pie graph can be used as follows:

var Pie = require('paths/pie');
var pie = Pie({
  data: [
    { name: 'Italy', population: 59859996 },
    { name: 'Mexico', population: 118395054 },
    { name: 'France', population: 65806000 },
    { name: 'Argentina', population: 40117096 },
    { name: 'Japan', population: 127290000 }
  ],
  accessor: function(x) { return x.population; },
  compute: {
    color: function(i) { return somePalette[i]; }
  },
  center: [20, 15],
  r: 30,
  R: 50
});

Parameters:

  • center, r, R: have the same geometric meaning as in the Sector function
  • data: contains an array with the data to plot. The precise form of the data is not important, because the actual value of the data will be extracted by the accessor function.
  • accessor: a function that is applied to each datum in data to extract a numeric value
  • compute (optional): see the introduction.

The object returned by the Pie function contains the curves array, on which one can iterate to draw the sectors. Each member of this array has the properties sector, index and item, the latter containing the actual datum associated to the sector.

Bar graph

The Bar graph can be used as follows:

var Bar = require('paths/bar');
var bar = Bar({
  data: [
    [
      { name: 'Italy', population: 59859996 },
      { name: 'Spain', population: 46704314 }
      { name: 'France', population: 65806000 },
      { name: 'Romania', population: 20121641 },
      { name: 'Greece', population: 10815197 }
    ],
    [
      { name: 'Zambia', population: 14580290 },
      { name: 'Cameroon', population: 20386799 }
      { name: 'Nigeria', population: 173615000 },
      { name: 'Ethiopia', population: 86613986 },
      { name: 'Ghana', population: 24658823 }
    ]
  ],
  accessor: function(x) { return x.population; },
  compute: {
    color: function(i) { return somePalette[i]; }
  },
  width: 500,
  height: 400,
  gutter: 10
});

Parameters:

  • width, height: have the obvious geometric meaning
  • data: contains an array of arrays with the data to plot. The precise form of the data is not important, because the actual value of the data will be extracted by the accessor function. Each array will be represented by a series of bars with the same index.
  • accessor: a function that is applied to each datum inside each item in data to extract a numeric value
  • gutter (optional): the space to leave between each group of bars
  • compute (optional): see the introduction.

The bar chart allows multiple histograms to be drawn side by side. If you just have one series to be plotted, put it inside an array of length one anyway, like this:

Bar({
  data: [[2, 5, 3, 9, 7]],
  ...
});

The object returned by the Bar function contains the curves array, on which one can iterate to draw the rectangles. Each member of this array has the properties line, index and item, the latter containing the actual datum associated to the rectangle.

Stock graph

The Stock graph is used to represent one or more line charts. It can be used as follows:

var Stock = require('paths/stock');
var data = [
  [
    { year: 2012, month: 1, value: 13 },
    { year: 2012, month: 2, value: 12 },
    { year: 2012, month: 3, value: 15 }
  ],
  [
    { year: 2012, month: 1, value: 21 },
    { year: 2012, month: 2, value: 22 },
    { year: 2012, month: 3, value: 22 }
  ]
];

function date(data) {
  var d = new Date();
  d.setYear(data.year);
  d.setMonth(data.month - 1);
  return d.getTime();
}

var stock = Stock({
  data: data,
  xaccessor: date,
  yaccessor: function(d) { return d.value; },
  width: 300,
  height: 200,
  compute: {
    color: function(i) { return somePalette[i]; }
  },
  closed: true
});

Parameters:

  • width and height: have the obvious geometric meaning; data will be rescaled to fit into a rectangle of these dimensions
  • data: contains the actual data to plot. It should be an array of arrays, each internal array representing a time series to be plotted. The actual format of the data in the time series is not important; the actual abscissa and ordinate of the point are extracted by the xaccessor and yaccessor function.
  • xaccessor, yaccessor: two functions that extract from each datum its x and y coordinates. They default to function(d) { return d[0] } and function(d) { return d[1] } respectively, so if data is passed as an array of arrays of arrays of 2 elements, the accessor functions are optional.
  • closed (optional, default false): a boolean used to decide how to construct the paths for the area plots. If closed is set to true, these will be stretched to include part of the x axis, even if the data are not around 0. Use this if you want to be sure that the area paths touch the horizontal axis
  • compute (optional): see the introduction.

The Stock function will then return an object with the properties curves, xscale and yscale. Under curves it contains an array of objects, each having the properties line, area, item and index. line and area are two polygon objects, as in the previous paragraph; the first one holds the polygon for the line chart, while the second one is a closed polygon that can be used to draw the area fill. Under item one finds the original element in the data.

Finally, xscale and yscale are the scales used to represent the data on the given width and height. They can be used to find the coordinates of the axis and draw them.

Smooth line graph

The smooth line graph is used to represent one or more line charts; unlike Stock it interpolates between the data points with smooth Bézier curves. The API for paths.smooth-line is identical to paths.stock, so the two can be used interchangeably.

Radar graph

The radar graph can be used as follows:

var Radar = require('paths/radar');
var data = [
  { hp: 45, attack: 49, defense: 49, sp_attack: 65, sp_defense: 65, speed: 45 },
  { hp: 60, attack: 62, defense: 63, sp_attack: 80, sp_defense: 80, speed: 60 },
  { hp: 80, attack: 82, defense: 83, sp_attack: 100, sp_defense: 100, speed: 80 },
  { hp: 45, attack: 25, defense: 50, sp_attack: 25, sp_defense: 25, speed: 35 }
]
var radar = Radar({
  data: data,
  accessor: {
    attack: function(x) { return x.attack; },
    defense: function(x) { return x.defense; },
    speed: function(x) { return x.speed; }
  },
  compute: {
    color: function(i) { return somePalette[i]; }
  },
  max: 100,
  center: [20, 15],
  r: 30,
  rings: 5
});

Parameters:

  • data: contains an array of data to be plotted.
  • accessor: an object that describes how to extract the various features from the data. The keys of this object correspond to the axes that are shown in the radar chart, and associated to each key is a function that maps a datum to its value along this axis. accessor is optional in the case where each datum is itself an object with numeric properties. For instance, if in the example above accessor was left out, we would obtain a radar graph of hexagons.
  • max: represents the ideal maximum of each feature. max is optional; if it is left out, it is computed as the actual maximum of each feature, but one may want to override the computed value, for instance for constancy of scale during an animation.
  • r and center: the radius and the center of the figure, respectively. So, the whole figure is scaled in such a way that a feature with value max will be sent to a distance r from the center.
  • rings (optional, default 3): the number of polygonal rings that shall appear in the chart.
  • compute (optional): see the introduction.

The return value from Radar is an object with the properties curves and rings. curves is an array of objects, each one having the properties polygon, item and index, where polygon contains the actual path object. rings is an array of path objects, representing concentric regular polygons of increasing radius.

Tree graph

The tree graph can be used as follows:

var Tree = require('paths/tree');
var data = {
  name: 1,
  descendants: [
    {
      name: 2,
      descendants: [
        {
          name: 4,
          descendants: [{
            name: 6,
            descendants: [{ name: 7 }]
          }]
        },
        { name: 5 }
      ]
    },
    {
      name: 3,
      descendants: [{ name: 8 }, { name: 9 }]
    }
  ]
};
var tree = Tree({
  data: data,
  children: function(x) { return x.descendants; },
  compute: {
    color: function(i) { return somePalette[i]; }
  },
  width: 400,
  height: 300
});

Parameters:

  • data: contains a tree-like structure with the data to be plotted.
  • width and height: the dimensions of the graph
  • children (optional): a function that returns the list of children of the given node. Defaults to function(x) { return x.children; }
  • compute (optional): see the introduction.

The return value from Tree is an object with the properties curves and nodes. curves is an array of objects, each one having the properties connector, item and index, where connector contains the actual path object. nodes is an array of objects, each one having the properties point and item, representing the nodes of the tree.

Waterfall graph

The Waterfall graph is a nice way to represent some values on a bar chart, together with other values that add up to their difference. A typical use would be breaking incomes or expenses into pieces. Since a picture is worth a thousand word, make sure to have a look at the demo. It can be used as follows:

var Waterfall = require('paths/waterfall');
var waterfall = Waterfall({
  data: [
    {
      name: 'Gross income',
      value: 30,
      absolute: true
    }
    {
      name: 'Transport',
      value: -6
    }
    {
      name: 'Distribution',
      value: -3
    }
    {
      name: 'Detail income'
      absolute: true
    }
    {
      name: 'Taxes',
      value: -8
    }
    {
      name: 'Net income'
      absolute: true
    }
  ],
  compute: {
    color: function(i, item) {
      if (item.absolute) return 'green';
      else return 'red';
    }
  },
  width: 500,
  height: 400,
  gutter: 10
});

Parameters:

  • width, height: have the obvious geometric meaning
  • data: contains an array with the data to plot. The precise form of the data is not important, because the actual value of the data will be extracted by the accessor function.
  • accessor: a function that is applied to each datum inside each item in data to extract its value. It should return an object with either the absolute or value property, or both. value represents the height of the current bar. absolute should be true if the bar should stand on its own, rather than appearing as the difference between consecutive bars.
  • max, min (optional): maximum and minimum values represented on the chart. They are computed if they are not given explicitly, but setting them explicitly can be useful to draw more than one chart on the same scale.
  • gutter (optional): the space to leave between each bar
  • compute (optional): see the introduction.

The first item in the waterfall chart should have the value property and absolute set to true. The subsequent bars will usually have either value or absolute but not both. If they have value, this is considered relative to the previous bar. If they have absolute set to true, the value will be computed by summing all relative values up to that point.

For instance, the height of Detail income in the example is 21 = 30 - 6 - 3, while the height of Net income is 13 = 21 - 8.

The object returned by the Waterfall function contains the curves array, on which one can iterate to draw the rectangles. Each member of this array has the properties line, index, value and item, the latter containing the actual datum associated to the rectangle. value instead contains the height computed for this rectangle: it coincides with item.value whenever this is present, and otherwise it is equal to the cumulative value computed. For instance, value would be 21 for the Detail Income rectangle in the example above.

  • [Force-directed graphs (experimental)](Force-directed graphs)
  • [Sankey Diagrams](Sankey Diagrams)
Clone this wiki locally