{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Using Subject Space ROIs from Freesurfer\n\nAn example using the AFQ API to find bundles\nas defined by endpoint ROIs from freesurfer.\nThis example can be modified to work with ROIs\nin subject space from pipelines other than freesurfer.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import os.path as op\n\nimport nibabel as nib\nimport plotly\nimport numpy as np\n\nfrom AFQ.api.group import GroupAFQ\nimport AFQ.data.fetch as afd\nfrom AFQ.definitions.image import RoiImage\nimport AFQ.api.bundle_dict as abd" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Get some example data\n\nRetrieves High angular resolution diffusion imaging (HARDI) dataset from\nStanford's Vista Lab\n\n see https://purl.stanford.edu/ng782rw8378 for details on dataset.\n\nThe data for the first subject and first session are downloaded locally\n(by default into the users home directory) under:\n\n ``.dipy/stanford_hardi/``\n\nAnatomical data (``anat``) and Diffusion-weighted imaging data (``dwi``) are\nthen extracted, formatted to be BIDS compliant, and placed in the AFQ\ndata directory (by default in the users home directory) under:\n\n ``AFQ_data/stanford_hardi/``\n\nThis data represents the required preprocessed diffusion data necessary for\ninitializing the GroupAFQ object (which we will do next)\n\nThe clear_previous_afq is used to remove any previous runs of the afq object\nstored in the AFQ_data/stanford_hardi/ BIDS directory. Set it to None if\nyou want to use the results of previous runs. Setting it to \"track\"\nas here will only clear derivatives that depend on the tractography stage\n(i.e., bundle delination and tract profile calculation),\nas well as the tractography itself, to save time on recomputation.\nIf you want to only clear derivatives that depend on bundle delineation,\nand keep the tractography, you can set clear_previous_afq to\n\"recog\" instead.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "afd.organize_stanford_data(clear_previous_afq=\"track\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Generate left thalamus ROI from freesurfer segmentation file\n1. Load the segmentation file that was generated by Freesurfer for\n the specific subject.\n2. Identify the left thalamus within the file, which has the label\n number 41\n3. Create a Nifti image representing the left thalamus ROI:\n - Assign a value of 1 to the voxels that Freesurfer\n has labeled as 41 (i.e., the left thalamus).\n - Assign a value of 0 to all other voxels.\nThis binary mask format is the expected input for pyAFQ when\ndealing with subject space ROIs. If it's already in binary format,\nthere is no need to do this step.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "freesurfer_subject_folder = op.join(\n afd.afq_home, \"stanford_hardi\",\n \"derivatives\", \"freesurfer\",\n \"sub-01\", \"ses-01\",\n \"anat\")\n\nseg_file = nib.load(op.join(\n freesurfer_subject_folder, \"sub-01_ses-01_seg.nii.gz\"))\nleft_thal = seg_file.get_fdata() == 41\nnib.save(\n nib.Nifti1Image(\n left_thal.astype(np.float32),\n seg_file.affine),\n op.join(\n freesurfer_subject_folder,\n \"sub-01_ses-01_desc-leftThal_mask.nii.gz\"))\n\n# Fetch LV1 ROI\n# which was already generated using the process above\nafd.fetch_stanford_hardi_lv1()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Set tractography parameters (optional)\nWe make this tracking_params which we will pass to the GroupAFQ object\nwhich specifies that we want 10,000 seeds randomly distributed\nonly within the endpoint ROIs and not throughout the white matter.\nThis is controlled by passing\n`\"seed_mask\": RoiImage()` in the `tracking_params` dict.\n\nWe only do this to make this example faster and consume less space.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "tracking_params = dict(n_seeds=10000,\n random_seeds=True,\n rng_seed=42,\n seed_mask=RoiImage(use_endpoints=True))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Define custom `BundleDict` object\nIn a typical `BundleDict` object, ROIs are passed as paths to Nifti files.\nHere, we define ROIs as dictionaries instead, containing BIDS filters.\nThen pyAFQ can find the respective ROI for each subject and session.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "bundles = abd.BundleDict({\n \"L_OR\": {\n \"start\": {\n \"scope\": \"freesurfer\",\n \"suffix\": \"mask\",\n \"desc\": \"leftThal\"},\n \"end\": {\n \"scope\": \"freesurfer\",\n \"suffix\": \"anat\",\n \"desc\": \"LV1\"\n },\n \"cross_midline\": False,\n \"space\": \"subject\"\n }})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Initialize a GroupAFQ object:\n\nCreates a GroupAFQ object, that encapsulates tractometry,\npassing in our custom bundle info. Then we run the pipeline\nand generate a visualization of the bundle we found.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "myafq = GroupAFQ(\n bids_path=op.join(afd.afq_home, 'stanford_hardi'),\n dwi_preproc_pipeline='vistasoft',\n t1_preproc_pipeline='freesurfer',\n tracking_params=tracking_params,\n bundle_info=bundles)\n\nbundle_html = myafq.export(\"indiv_bundles_figures\")\nplotly.io.show(bundle_html[\"01\"][\"L_OR\"])" ] } ], "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.13.13" } }, "nbformat": 4, "nbformat_minor": 0 }