Introduction

When charts contain large numbers of links between individual pairs of nodes or combos, it can become difficult to really understand the connections and to analyse the chart.

To solve this, you can set up your chart to display groups of links between pairs of nodes as aggregate links. Each aggregate link represents a group of one or multiple links, which reduces the number of connections drawn in the chart. You can also style aggregate links to show information such as the number, or type, of underlying child links. Aggregate link functionality is currently in beta.

Aggregate links are a visual representation of the child links they represent. The child links inside an aggregate link aren't removed or marked as hidden, but are simply not displayed as individual links.

To see how link aggregation can help you explore and understand the connections in your chart more easily, take a look at the Aggregating Links demo.

Enabling aggregate links

To enable link aggregation within your chart, set the aggregateLinks chart option. When enabled, any number of links betwen a pair of nodes (including a single link) can be aggregated.

To simply aggregate all links between all pairs of nodes, set the option to true:

chart.options({ aggregateLinks: true });

You might want to aggregate just the links that have a particular property. Suppose your links all have a type property defined within their d property, then to aggregate links with that property:

chart.options({ aggregateLinks: { aggregateBy: 'type' } });

Your links might have a direction associated with them, indicated by their arrows. If so, you can also aggregate your links by direction, by setting aggregateByDirection. Arrowheads are added by default if the child links have them.

chart.options({ aggregateLinks: { aggregateBy: 'type', aggregateByDirection: true } });

When an aggregate link is created between a pair of nodes or combos, its id1 and id2 properties are assigned in the alphabetical order of the node/combo ids. This creates consistency in case the id1 and id2 properties of underlying child links aren't all assigned in the same order.

You should consider this alphabetical order if you:

  • Set arrows directly on aggregate links - a1 and a2 of aggregate and child links may be reversed
  • Set flow animation on aggregate links - directions of aggregate and child links may be reversed

Reversed order of aggregate and child links can also affect sequential layout when top or level aren't specified.

See examples of aggregate links in our Aggregating Links demo.

Styling

Once the aggregateLinks option has been specified, KeyLines fires a link-aggregation event each time an aggregate link is created, deleted or updated. The update occurs when at least one of its child links is updated in a relevant way:

  • A child link is added, removed, hidden or unhidden.
  • A child link's (a1 or a2) arrow is updated.
  • In the d object, the custom property used for aggregating links is changed.

The event props include the type of the change, its id, and any additional information indicating the property by which the link was aggregated (reflecting the aggregateLinks option).

Use the event handler to style your aggregate links accordingly using chart.setProperties in the same way as any other link:

chart.on('link-aggregation', ({ change, links, aggregateByValue, id, id1, id2 }) => {
    if (change !== "deleted") { // only style new or updated aggregate links
      chart.setProperties({ id, c: 'red', w: Math.sqrt(links.length) });
    }
  }
);

The default style of an aggregate link is the same as for a regular link, i.e. a grey link with a width of 1.

Aggregate links inherit any arrows set on a1 and a2 properties of the child links. They do not inherit any other styling properties.

Note that you must bind your link-aggregation event handler by calling chart.on before loading the chart data so that the handler is called when the data is first loaded.

To explore this further, take a look at the Aggregating Links demo.

Obtaining aggregation information

To get the aggregation information associated with a particular link or links, you can use the chart.getAggregateInfo() function which checks the specified id(s) and returns their link aggregation information object(s).

  • If an aggregate link, the object contains the relevant aggregation information such as the child link(s) and the method of aggregation (by a data value or by direction).
  • If a child link, the object contains the id of its parent aggregate link.
  • If a node, the function returns null.

For example:

// if a link is an aggregate link's child, returns the id of the parent aggregate link
const linkInfo = chart.getAggregateInfo(linkId).parentAggregate

Inheriting state from child links

Some APIs cannot be used directly on aggregate links and should be set on child links instead. When set for all child links, the aggregate link state is automatically updated as well:

  • bg - Aggregate links are backgrounded if all child links are backgrounded.
  • chart.foreground() - Iterates over child links, aggregate links are backgrounded if all child links are backgrounded.

  • hi - Aggregate links are removed if all child links are hidden.
  • chart.filter() - Iterates over child links, aggregate links are removed if all child links are hidden.

Interactions with other features

Some features of KeyLines do not consider aggregate links, and instead operate as if link aggregation was not in use.

Using graph functions with aggregate links

Because the child links of aggregate links aren't actually removed or treated as hidden, but are simply displayed as a single aggregate link, link aggregation doesn't affect graph centrality calculations:

  • The components function doesn't include aggregate links in its links array.
  • The neighbours function doesn't include aggregate links in its results.

This means that:

  • Centrality metrics aren't affected as they don't consider aggregate links in their calculations, just their child links.
  • The distances and shortestPaths functions aren't affected because aggregate links aren't used in the calculations.

Aggregate links and chart serialization

When saving your chart using chart.serialize, link aggregation is ignored.

To reapply your chart's link aggregation state, save your aggregateLinks options and your link-aggregation event handler. You can then load the serialized chart, and reapply the saved chart options and handler, so that KeyLines generates your aggregate links.