{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Reconstruct with Generalized Q-Sampling Imaging\n\nWe show how to apply Generalized Q-Sampling Imaging [Yeh2010]_\nto diffusion MRI datasets. You can think of GQI as an analytical version of\nDSI orientation distribution function (ODF) (Garyfallidis, PhD thesis, 2012).\n\nFirst import the necessary modules:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import numpy as np\nfrom dipy.core.gradients import gradient_table\nfrom dipy.data import get_fnames, get_sphere\nfrom dipy.io.gradients import read_bvals_bvecs\nfrom dipy.io.image import load_nifti\nfrom dipy.reconst.gqi import GeneralizedQSamplingModel\nfrom dipy.direction import peaks_from_model" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Download and get the data filenames for this tutorial.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fraw, fbval, fbvec = get_fnames('taiwan_ntu_dsi')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "img contains a nibabel Nifti1Image object (data) and gtab contains a\n``GradientTable`` object (gradient information e.g. b-values). For example to\nread the b-values it is possible to write::\n\n print(gtab.bvals)\n\nLoad the raw diffusion data and the affine.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "data, affine, voxel_size = load_nifti(fraw, return_voxsize=True)\nbvals, bvecs = read_bvals_bvecs(fbval, fbvec)\nbvecs[1:] = (bvecs[1:] /\n np.sqrt(np.sum(bvecs[1:] * bvecs[1:], axis=1))[:, None])\ngtab = gradient_table(bvals, bvecs)\nprint('data.shape (%d, %d, %d, %d)' % data.shape)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "data.shape ``(96, 96, 60, 203)``\n\nThis dataset has anisotropic voxel sizes, therefore reslicing is necessary.\n\nInstantiate the model and apply it to the data.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "gqmodel = GeneralizedQSamplingModel(gtab, sampling_length=3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The parameter ``sampling_length`` is used here to\n\nLets just use one slice only from the data.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "dataslice = data[:, :, data.shape[2] // 2]\n\nmask = dataslice[..., 0] > 50\n\ngqfit = gqmodel.fit(dataslice, mask=mask)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Load an ODF reconstruction sphere\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sphere = get_sphere('repulsion724')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Calculate the ODFs with this specific sphere\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "ODF = gqfit.odf(sphere)\n\nprint('ODF.shape (%d, %d, %d)' % ODF.shape)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ODF.shape ``(96, 96, 724)``\n\nUsing ``peaks_from_model`` we can find the main peaks of the ODFs and other\nproperties.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "gqpeaks = peaks_from_model(model=gqmodel,\n data=dataslice,\n sphere=sphere,\n relative_peak_threshold=.5,\n min_separation_angle=25,\n mask=mask,\n return_odf=False,\n normalize_peaks=True)\n\ngqpeak_values = gqpeaks.peak_values" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "``gqpeak_indices`` show which sphere points have the maximum values.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "gqpeak_indices = gqpeaks.peak_indices" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is also possible to calculate GFA.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "GFA = gqpeaks.gfa\n\nprint('GFA.shape (%d, %d)' % GFA.shape)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With parameter ``return_odf=True`` we can obtain the ODF using ``gqpeaks.ODF``\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "gqpeaks = peaks_from_model(model=gqmodel,\n data=dataslice,\n sphere=sphere,\n relative_peak_threshold=.5,\n min_separation_angle=25,\n mask=mask,\n return_odf=True,\n normalize_peaks=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This ODF will be of course identical to the ODF calculated above as long as\nthe same data and mask are used.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print(np.sum(gqpeaks.odf != ODF) == 0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "True\n\nThe advantage of using ``peaks_from_model`` is that it calculates the ODF only\nonce and saves it or deletes if it is not necessary to keep.\n\n.. [Yeh2010] Yeh, F-C et al., Generalized Q-sampling imaging, IEEE Transactions\n on Medical Imaging, vol 29, no 9, 2010.\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 }