Browser

Download jsnetworkx.js and include it in your page:

<script src="jsnetworkx.js"></script>

If you want to visualize graphs, you have to include D3.js as well.

Node.js

Install JSNetworkX with npm

npm install jsnetworkx

and import it in your application

var jsnx = require('jsnetworkx');

Environment

JSNetworkX makes heavy use of upcoming ES2015 features, such as iterators. If possible, write your code in ES2015 as well, and transpile it to ES5. If that's not possible, you can at least polyfill certain standard functions, such as Array.from, which allows you to easily convert an iterable to an array.

If you are already familiar with NetworkX, then most of the following information will already be familiar to you. Most (if not all) method and function names are the same as in NetworkX.

Once you included JSNetworkX you can start working with graphs. If you are working in a browser environment, including jsnetworkx.js will create a global variable jsnx, which is an object. All functions/methods/modules are properties of this object. In Node.js use the name of variable you assigned the module to.

There are basically three ways to create a new graph:

  1. By calling the Graph constructor or one of its subclasses (DiGraph, MultiGraph or MultiDiGraph).
  2. By transforming an existing graph into a new graph, for example by creating a subgraph with G.subgraph or convert an undirected graph to a directed one (G.toDirected).
  3. With a graph generator, such as completeGraph().

Here are some examples:

// This creates a new empty, undirected graph
var G = new jsnx.Graph();

// Generates a complete graph with six nodes
var G = jsnx.completeGraph(6);

// Generates a random graph with six nodes and
// an edge between each node is created with a probability of 0.3
var G = jsnx.binomialGraph(6, 0.3);

v0.3.0 API changes

Prior to v0.3.0 all functions and graph methods followed underscore naming convention (i.e. jsnx.binomial_graph(...)) instead of camelCase.

JSNetworkX provides support for four types of graphs: undirected graphs ( Graph), directed graphs (DiGraph), multi edge undirected graphs (MultiGraph) and multi edge directed graphs ( MultiDiGraph). Each type provides specific methods to access and extract information about the structure of the graph.

Once you obtained a graph, you can modify it, by adding or removing nodes and edges, or access node and edge information.

Adding and removing nodes

Single nodes can be added with G.addNode and a collection of nodes with G.addNodesFrom. Typically the collection will be an array, but it could be another graph as well, or any node collection returned by another library function.
Lets have a look at an example and let us print the nodes:

var G = new jsnx.Graph();
G.addNode(1);
G.addNodesFrom([3, 5, 7, 11]);
console.log(G.nodes());
// shows [1, 3, 5, 7, 11] -- v0.2.0
// shows ["1", "3", "5", "7", "11"] -- v0.1.1 and below

G.nodes returns an array nodes, which shows us that the graph now has four nodes, namely 1, 3, 5 and 7.

Removing nodes is as simple as adding them. You can use either G.removeNode or G.removeNodesFrom.

G.removeNode(11); // same as G.removeNode("5");
console.log(G.nodes());
// shows [1, 3, 5, 7] -- v0.2.0
// shows ["1", "3", "5", "7"] -- v0.1.1 and below
Info: Removing a node will also remove all connected edges.

Adding and removing edges

Adding and removing edges works pretty much the same way, with the methods G.addEdge which accepts two nodes as arguments, and G.addEdgesFrom which accepts a list of 2-tuples (arrays).

Info: If you add an edge between non-existing nodes, the nodes will automatically be created.
G.addEdge(1,3);
G.addEdge(3,1); // does not do anything in undirected graphs
G.addEdgesFrom([[1,5], [1,7], [7,3], [7,9]]); // node 9 does not exist!
console.log(G.nodes());
// shows [1, 3, 5, 7, 9] -- v0.2.0
// shows ["1", "3", "5", "7", "9"] -- v0.1.1 and below
console.log(G.edges());
// shows [[1, 3], [1, 5], [1, 7], [7, 3], [7, 9]] -- v0.2.0
// shows [["1", "3"], ["1", "5"], ["1", "7"], ["7", "3"], ["7", "9"]] -- v0.1.1 and below

Edges are removed with G.removeEdge and G.removeEdgesFrom.

G.removeEdge(5,1); // or G.removeEdge(1,5);
G.removeEdgesFrom([[9,7], [7,1]]);
// Removing a node removes its connected edges as well
G.removeNode(3);
console.log(G.nodes());
// shows [1, 5, 7, 9] -- v0.2.0
// shows ["1", "5", "7", "9"] -- v0.1.1 and below
console.log(G.edges());
// shows []

A great feature of NetworkX is the possibility to assign arbitrary attributes to nodes and edges and of course JSNetworkX allows you to do this too.

New nodes, edges

G.addNode accepts an object as second argument. Its properties will be the node's attributes. Similarly, G.addNodesFrom accepts a list of 2-tuples, where the first element is the node, and the second element is a data object. It also accepts an object as second argument. Attributes passed through this object will be added to all nodes.

var G = new jsnx.Graph();
// Adds a new node, 10, with the attribute {someData: 42}
G.addNode(10, {someData: 42});

// Adds the nodes, "foo" and "bar", with individual attributes and 
// attributes for both nodes
G.addNodesFrom([['foo', {size: 5}], ['bar', {size: 10}]], {color: 'blue'});

// Passing `true` to `G.nodes` changes the return value to include the attributes for each node
console.log(G.nodes(true));
// shows
// [
//    [10,{"someData":42}],
//    ["foo",{"color":"blue","size":5}],
//    ["bar",{"color":"blue","size":10}]
// ]

It works the same for edges: G.addEdge accepts an object as third argument and G.addEdgesFrom a list of 3-tuples, where the first two elements are nodes and the third one is an attributes object.

Existing nodes, edges

You have two ways to set attributes on existing nodes and edges: Either just add the node (edge) again, the passed data will be merged, or access the nodes (edges) via the graphs G.node (G.adj) properties.

var G = new jsnx.Graph();
G.addNodesFrom([0,1]);
G.addEdge(0,1);

G.node.get(0).foo = 'bar';
// G.node[0].foo = 'bar';  // v0.1.1 and below
G.adj.get(0).get(1).color = 'blue';
// G.adj[0][1].color = 'blue'; // v0.1.1 and below

console.log(G.nodes(true));
// shows [[0,{"foo":"bar"}],[1,{}]]
console.log(G.edges(true));
// shows [[0,1,{"color":"blue"}]]
Warning You should not directly modify the G.nodes or G.adj properties, since this can lead to inconsistency within the graph.

What is this data useful for?

That is really up to your use case. For example, if you are modeling a social network, the node data can contain more detailed information about a person. If you are modeling a street network, the edge data could contain timeseries data about congestion.

Node and edge data can be very useful if you want to customize the style of nodes and edges in a visualization. This will be explained later, but here is already a short example of how this can look like:

var G = new jsnx.Graph();
G.addNodesFrom([
    [1, {color: 'red'}],
    [2, {color: 'green'}],
    [3, {color: 'white'}]
]);

G.addEdgesFrom([[1,2], [1,3]]);

// `jsnx.draw` accept a graph and configuration object
jsnx.draw(G, {
  element: '#demo-canvas',
  withLabels: true,
  nodeStyle: {
      fill: function(d) {
          return d.data.color;
      }
  }
});

NetworkX provides a variety of algorithms to analyze graphs, such as detecting cliques, computing shortest paths or the centrality of a graph. JSNetworkX aims to provide those algorithms as well. You can see the progress and which algorithms are available on the API progress page. To learn about the algorithms which are generally available, have a look at the NetworkX documentation.

Most functions implementing those algorithms are available on the jsnx object (just like with NetworkX). Here is a small example, which computes the shortest path between two nodes, draws the graph and colors the found nodes differently.

// This is a graph generator
var G = jsnx.cycleGraph(6);
// Compute the shortest path between 0 and 4
var path = jsnx.bidirectionalShortestPath(G, 0, 4);
// A simple way to color all nodes in the path:
G.addNodesFrom(path, {color: '#FFF'});
// Color the start and end differently
G.node.get(0).color = '#0F0'; // start is green
G.node.get(4).color = '#F00'; // end is red

jsnx.draw(G, {
  element: '#demo-canvas',
  withLabels: true,
  nodeStyle: {
    fill: function(d) {
      return d.data.color || '#AAA'; // any node without color is gray
    }
  }
});
Info The drawing API is not finalized yet and will be extended greatly to make it easier to customize and modify visualizations.

You already have seen some examples of how to draw graphs. Here is a more detailed introduction.

JSNetworkX uses D3.js to draw graphs as SVG. D3 is a very powerful library to bind data to DOM elements and provides many useful methods for data visualization. You are encouraged to learn more about it to get the most out of drawing graphs. JSNetworkX takes care of setting up the connections between the graph, the layout and the SVG elements, and lets you apply custom styles to nodes and edges.

jsnx.draw is the method with which you can draw a graph and it accepts the following arguments:

jsnx.draw(G, options [, update]);
  • G can be either a directed or undirected graph. Multi edge graphs are not supported.
  • options is an object which controls the look and behavior of the visualization.
  • update is a boolean value and controls whether modifications to the graph should be reflects in the visualization.

Drawing options

A complete list of options with explanation can be found in the wiki. In the following we will describe the most important options and concepts you need to know about.

The only required option is element, so that the library knows where to draw the graph. It can either be a CSS selector or a DOM element. Internally, the method uses d3.select to select the element.

jsnx.draw will add a new <svg> container to the element, which by default has the same width and height as its parent. You can explicitly set the dimensions by specifying the width and height options.

The most interesting options are probably nodeStyle, nodeAttr, edgeStyle and edgeAttr, which with you can specify the look of nodes and edges. Since the graph is drawn with SVG elements, the *Style options should hold values for CSS properties and the *Attr options values for element attributes. If you are not very familiar with SVG, have a look at the MDN SVG documentation. The options are explained in greater detail in the next section.

Data binding and styling

As mentioned earlier, D3's main feature is the binding of data to DOM elements. This is also the foundation for the graph visualization: Each SVG element representing a node or edge has an object bound to it, with various information.
By using a function as one of the style or attribute values, you will have access to that information, because internally, the library just passes the values along to D3's .style and .attr methods.

The data object bound to an element for a node has the following properties:

  • node, the node value
  • data, the node data from the graph (see Node and edge data)
  • G, a reference to the graph object

The data object for an edge has similar properties:

  • edge, a 2-tuple (array) containing the nodes this edge connects
  • data, the edge data from the graph (see Node and edge data)
  • G, a reference to the graph object

To better illustrate this concept, here is a small example: Each node in the graph has a property count. We will later use this property to draw the nodes in different sizes. The nodes are drawn as <circle> SVG elements and the radius is controlled by the elements r attribute. Hence we have to use the nodeAttr option.

var G = new jsnx.Graph();
G.addNode(1, {count: 12});
G.addNode(2, {count: 8});
G.addNode(3, {count: 15});
G.addEdgesFrom([[1,2],[2,3]]);

jsnx.draw(G, {
  element: '#demo-canvas',
  withLabels: true,
  nodeAttr: {
    r: function(d) {
      // `d` has the properties `node`, `data` and `G`
      return d.data.count;
    }
  }
});

Graph layouts

JSNetworkX currently only supports a force based layout but we will add other layouts in the future.

Limitations and other drawing techniques

SVG has its pros and cons. It is easier to add interaction but there is an upper limit of how elements can be drawn, which depends a lot on the user's computer and browser.

We aim to support different drawing techniques, like canvas and WebGL and with the expectation that this will allow us to draw larger graphs reasonably well.