Chord diagrams with python and the mne library

logo of a chart:Chord

The mne library is a powerful library to plot chord diagrams with Python. This blogpost goes through its basic usage with explanation and reproducible examples.

The mne package

It is possible to build chord diagrams from a connectivity matrix thanks to the neuroscience library MNE. It comes with a visual function called plot_connectivity_circle() that is pretty handy to get good-looking chord diagrams in minutes!

Let's load the library and see what it can make!

from mne.viz import plot_connectivity_circle

# only for the exemple
import numpy as np

Most basic chord diagram with mne

Let's start with a basic examples. 20 nodes that are randomly connected. Two objects are created:

  • node_names that is a list of 20 node names
  • con that is an object containing some random links between nodes.

Both object are passed to the plot_connectivity_circle() function that automatically builds the chord diagram.

N = 20  # Number of nodes
node_names = [f"N{i}" for i in range(N)]  # List of labels [N]

# Random connectivity
ran = np.random.rand(N, N)
# NaN so it doesn't display the weak links
con = np.where(ran > 0.9, ran, np.nan)
fig, axes = plot_connectivity_circle(con, node_names)

Split the chord

It is possible to split the chord diagram in several parts. It can be handy to build chord diagrams where nodes are split in 2 groups, like origin and destination for instance.

start, end = 45, 135
first_half = (np.linspace(start, end, len(node_names)//2) +
              90).astype(int)[::+1] % 360
second_half = (np.linspace(start, end, len(node_names)//2) -
               90).astype(int)[::-1] % 360
node_angles = np.array(list(first_half) + list(second_half))
fig, axes = plot_connectivity_circle(con, node_names,
                                     node_angles=node_angles)

Style: node customization

Pretty much all parts of the chord diagram can be customized. Let's start by changing the node width (with node_width) and filtering the links that are shown (with vmin and vmax)

fig, axes = plot_connectivity_circle(con, node_names,
                                     node_width=2, vmin=0.97, vmax=0.98)

Now let's customize the nodes a bit more:

  • node_colors for the fill color
  • node_edgecolor for the edges
  • node_linewidth for the width
node_edgecolor = N//2 * [(0, 0, 0, 0.)] + N//2 * ['green']
node_colors = N//2 * ['crimson'] + N//2 * [(0, 0, 0, 0.)]
fig, axes = plot_connectivity_circle(con, node_names,
                                     node_colors=node_colors, node_edgecolor=node_edgecolor, node_linewidth=2)

Style: labels and links

Now some customization for labels, links and background:

  • colormap
  • facecolor
  • textcolor
  • colorbar
  • linewidth
fig, axes = plot_connectivity_circle(con, node_names,
                                     colormap='Blues', facecolor='white', textcolor='black', colorbar=False,
                                     linewidth=10)

Brocoli

Let's get some fun and build a data art brocoli like chord diagram 😊 !

N = 200
node_names = N * ['']
ran = np.random.rand(N, N)
con = np.where(ran > 0.95, ran, np.nan)
first_half = (np.linspace(0, 180, len(node_names)//2)).astype(int)[::+1] % 360
second_half = (np.linspace(70, 110, len(node_names)//2) -
               180).astype(int)[::-1] % 360
node_angles = np.array(list(first_half) + list(second_half))
node_colors = node_edgecolor = N * ['green']
fig, axes = plot_connectivity_circle(con, node_names,
                                     node_angles=node_angles,
                                     colormap='Greens', facecolor='w', textcolor='k', colorbar=False,
                                     node_colors=node_colors, node_edgecolor=node_edgecolor,
                                     node_width=0.1, node_linewidth=1, linewidth=1)

Contact & Edit


👋 This document is a work by Yan Holtz. You can contribute on github, send me a feedback on twitter or subscribe to the newsletter to know when new examples are published! 🔥

This page is just a jupyter notebook, you can edit it here. Please help me making this website better 🙏!