This example explains how we can use QuickBundles [Garyfallidis12] to
simplify/cluster streamlines. First import the necessary modules. For educational purposes we will try to cluster a small streamline bundle known
from neuroanatomy as the fornix. Load fornix streamlines. Perform QuickBundles clustering using the MDF metric and a 10mm distance
threshold. Keep in mind that since the MDF metric requires streamlines to have
the same number of points, the clustering algorithm will internally use a
representation of streamlines that have been automatically downsampled/upsampled
so they have only 12 points (To set manually the number of points,
see Resample Feature). clusters is a ClusterMap object which contains attributes that
provide information about the clustering result. clusters also has attributes such as centroids (cluster representatives), and
methods like add, remove, and clear to modify the clustering result. Let’s first show the initial dataset. Show the centroids of the fornix after clustering (with random colors): Showing the different QuickBundles centroids with random colors. Show the labeled fornix (colors from centroids). It is also possible to save the complete ClusterMap object with pickling. Finally, here is a video of QuickBundles applied on a larger dataset. Garyfallidis E. et al., QuickBundles a method for
tractography simplification, Frontiers in Neuroscience, vol
6, no 175, 2012. Example source code You can download Tractography Clustering with QuickBundles
import numpy as np
from dipy.io.streamline import load_tractogram
from dipy.segment.clustering import QuickBundles
from dipy.io.pickles import save_pickle
from dipy.data import get_fnames
from dipy.viz import window, actor, colormap
fname = get_fnames('fornix')
fornix = load_tractogram(fname, 'same', bbox_valid_check=False)
streamlines = fornix.streamlines
qb = QuickBundles(threshold=10.)
clusters = qb.cluster(streamlines)
print("Nb. clusters:", len(clusters))
print("Cluster sizes:", map(len, clusters))
print("Small clusters:", clusters < 10)
print("Streamlines indices of the first cluster:\n", clusters[0].indices)
print("Centroid of the last cluster:\n", clusters[-1].centroid)
Nb. clusters: 4
Cluster sizes: [64, 191, 47, 1]
Small clusters: array([False, False, False, True], dtype=bool)
Streamlines indices of the first cluster:
[0, 7, 8, 10, 11, 12, 13, 14, 15, 18, 26, 30, 33, 35, 41, 65, 66, 85, 100,
101, 105, 115, 116, 119, 122, 123, 124, 125, 126, 128, 129, 135, 139, 142,
143, 144, 148, 151, 159, 167, 175, 180, 181, 185, 200, 208, 210, 224, 237,
246, 249, 251, 256, 267, 270, 280, 284, 293, 296, 297, 299]
Centroid of the last cluster:
array([[ 84.83773804, 117.92590332, 77.32278442],
[ 86.10850525, 115.84362793, 81.91885376],
[ 86.40357208, 112.25676727, 85.72930145],
[ 86.48336792, 107.60327911, 88.13782501],
[ 86.23897552, 102.5100708 , 89.29447174],
[ 85.04563904, 97.46020508, 88.54240417],
[ 82.60240173, 93.14851379, 86.84208679],
[ 78.98937225, 89.57682037, 85.63652039],
[ 74.72344208, 86.60827637, 84.9391861 ],
[ 70.40846252, 85.15874481, 82.4484024 ],
[ 66.74534607, 86.00262451, 78.82582092],
[ 64.02451324, 88.43942261, 75.0697403 ]], dtype=float32)
# Enables/disables interactive visualization
interactive = False
scene = window.Scene()
scene.SetBackground(1, 1, 1)
scene.add(actor.streamtube(streamlines, window.colors.white))
window.record(scene, out_path='fornix_initial.png', size=(600, 600))
if interactive:
window.show(scene)
colormap = colormap.create_colormap(np.arange(len(clusters)))
scene.clear()
scene.SetBackground(1, 1, 1)
scene.add(actor.streamtube(streamlines, window.colors.white, opacity=0.05))
scene.add(actor.streamtube(clusters.centroids, colormap, linewidth=0.4))
window.record(scene, out_path='fornix_centroids.png', size=(600, 600))
if interactive:
window.show(scene)
colormap_full = np.ones((len(streamlines), 3))
for cluster, color in zip(clusters, colormap):
colormap_full[cluster.indices] = color
scene.clear()
scene.SetBackground(1, 1, 1)
scene.add(actor.streamtube(streamlines, colormap_full))
window.record(scene, out_path='fornix_clusters.png', size=(600, 600))
if interactive:
window.show(scene)
save_pickle('QB.pkl', clusters)
References
the full source code of this example
. This same script is also included in the dipy source distribution under the doc/examples/
directory.