{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Calculation of Outliers with Cluster Confidence Index\n\nThis is an outlier scoring method that compares the pathways of each streamline\nin a bundle (pairwise) and scores each streamline by how many other streamlines\nhave similar pathways. The details can be found in [Jordan_2018_plm]_.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from dipy.core.gradients import gradient_table\nfrom dipy.data import default_sphere, get_fnames\nfrom dipy.direction import peaks_from_model\nfrom dipy.io.image import load_nifti, load_nifti_data\nfrom dipy.io.gradients import read_bvals_bvecs\nfrom dipy.reconst.shm import CsaOdfModel\nfrom dipy.tracking.stopping_criterion import ThresholdStoppingCriterion\nfrom dipy.tracking import utils\nfrom dipy.tracking.local_tracking import LocalTracking\nfrom dipy.tracking.streamline import Streamlines, cluster_confidence\nfrom dipy.tracking.utils import length\nfrom dipy.viz import actor, window\n\nimport matplotlib.pyplot as plt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First, we need to generate some streamlines. For a more complete\ndescription of these steps, please refer to the CSA Probabilistic Tracking and\nthe Visualization of ROI Surface Rendered with Streamlines Tutorials.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "hardi_fname, hardi_bval_fname, hardi_bvec_fname = get_fnames('stanford_hardi')\nlabel_fname = get_fnames('stanford_labels')\n\ndata, affine = load_nifti(hardi_fname)\nlabels = load_nifti_data(label_fname)\nbvals, bvecs = read_bvals_bvecs(hardi_bval_fname, hardi_bvec_fname)\ngtab = gradient_table(bvals, bvecs)\n\nwhite_matter = (labels == 1) | (labels == 2)\ncsa_model = CsaOdfModel(gtab, sh_order=6)\ncsa_peaks = peaks_from_model(csa_model, data, default_sphere,\n relative_peak_threshold=.8,\n min_separation_angle=45,\n mask=white_matter)\nstopping_criterion = ThresholdStoppingCriterion(csa_peaks.gfa, .25)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will use a slice of the anatomically-based corpus callosum ROI as our\nseed mask to demonstrate the method.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Make a corpus callosum seed mask for tracking\nseed_mask = labels == 2\nseeds = utils.seeds_from_mask(seed_mask, affine, density=[1, 1, 1])\n# Make a streamline bundle model of the corpus callosum ROI connectivity\nstreamlines = LocalTracking(csa_peaks, stopping_criterion, seeds, affine,\n step_size=2)\nstreamlines = Streamlines(streamlines)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We do not want our results inflated by short streamlines, so we remove\nstreamlines shorter than 40mm prior to calculating the CCI.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "lengths = list(length(streamlines))\nlong_streamlines = Streamlines()\nfor i, sl in enumerate(streamlines):\n if lengths[i] > 40:\n long_streamlines.append(sl)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we calculate the Cluster Confidence Index using the corpus callosum\nstreamline bundle and visualize them.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "cci = cluster_confidence(long_streamlines)\n\n# Visualize the streamlines, colored by cci\nscene = window.Scene()\n\nhue = [0.5, 1]\nsaturation = [0.0, 1.0]\n\nlut_cmap = actor.colormap_lookup_table(scale_range=(cci.min(), cci.max()/4),\n hue_range=hue,\n saturation_range=saturation)\n\nbar3 = actor.scalar_bar(lut_cmap)\nscene.add(bar3)\n\nstream_actor = actor.line(long_streamlines, cci, linewidth=0.1,\n lookup_colormap=lut_cmap)\nscene.add(stream_actor)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you set interactive to True (below), the scene will pop up in an\ninteractive window.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "interactive = False\nif interactive:\n window.show(scene)\nwindow.record(scene, n_frames=1, out_path='cci_streamlines.png',\n size=(800, 800))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ".. figure:: cci_streamlines.png\n :align: center\n\n Cluster Confidence Index of corpus callosum dataset.\n\n\nIf you think of each streamline as a sample of a potential pathway through a\ncomplex landscape of white matter anatomy probed via water diffusion,\nintuitively we have more confidence that pathways represented by many samples\n(streamlines) reflect a more stable representation of the underlying phenomenon\nwe are trying to model (anatomical landscape) than do lone samples.\n\nThe CCI provides a voting system where by each streamline (within a set\ntolerance) gets to vote on how much support it lends to. Outlier pathways score\nrelatively low on CCI, since they do not have many streamlines voting for them.\nThese outliers can be removed by thresholding on the CCI metric.\n\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fig, ax = plt.subplots(1)\nax.hist(cci, bins=100, histtype='step')\nax.set_xlabel('CCI')\nax.set_ylabel('# streamlines')\nfig.savefig('cci_histogram.png')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ".. figure:: cci_histogram.png\n :align: center\n\n Histogram of Cluster Confidence Index values.\n\nNow we threshold the CCI, defining outliers as streamlines that score below 1.\n\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "keep_streamlines = Streamlines()\nfor i, sl in enumerate(long_streamlines):\n if cci[i] >= 1:\n keep_streamlines.append(sl)\n\n# Visualize the streamlines we kept\nscene = window.Scene()\n\nkeep_streamlines_actor = actor.line(keep_streamlines, linewidth=0.1)\n\nscene.add(keep_streamlines_actor)\n\n\ninteractive = False\nif interactive:\n window.show(scene)\nwindow.record(scene, n_frames=1, out_path='filtered_cci_streamlines.png',\n size=(800, 800))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ".. figure:: filtered_cci_streamlines.png\n :align: center\n\n Outliers, defined as streamlines scoring CCI < 1, were excluded.\n\n\n## References\n\n.. [Jordan_2018_plm] Jordan, K., Amirbekian, B., Keshavan, A., Henry, R.G.\n\"Cluster Confidence Index: A Streamline\u2010Wise Pathway Reproducibility Metric\nfor Diffusion\u2010Weighted MRI Tractography\", Journal of Neuroimaging, 2017.\n\n.. include:: ../links_names.inc\n\n\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.13" } }, "nbformat": 4, "nbformat_minor": 0 }