pyAFQ: Automated Fiber Quantification in Python¶
The core of the tractometry.org ecosystem is the pyAFQ software library. This library uses inputs from various other programs to perform the delineation of major white matter pathways and to quantify white matter tissue properties along their lengths - tract profiles. The final output of the program includes a tabular summary with these tract profiles for each subject in the dataset, and one merged table that includes the tract profiles for all of the subjects.
Along the way, the program produces many different intermediate data, including tractography results, maps of tissue properties, and visualizations, which can be used for quality assurance of the data and processing.
There are two ways to use pyAFQ: through a command line interface, and by writing Python code. Here, we will focus on the latter, using pyAFQ's Python Application Programming Interface (API).
Setup¶
We start with a few setup steps. The pyAFQ software downloads templates that
are required for anatomical delineation of tracts into a designated directory
on the user's machine. For the purpose of these examples, we will set the
path to this directory to /data/tractometry
.
You will see a similar setup step at the top of many of the notebooks here,
and it always does the same thing.
import os.path as op
from paths import afq_home
Next, we import the GroupAFQ
class from the pyAFQ api
module. We also
import plotly
, which we will use for visualization.
from AFQ.api.group import GroupAFQ
import plotly
Set up tracking parameters¶
Before we initialize the GroupAFQ
object, we create a tracking_params
variable, which we will pass to the GroupAFQ
object to specify the
tractography part of the pipeline. Here, we specify that we want 100,000 seeds
randomly distributed in the white matter. We also set num_chunks
to True
.
This will tell pyAFQ to use the ray
software library to parallelize the
tracking across all cores. This can be removed to process in serial, or set to
use a particular distribution of work by setting num_chunks
to an integer
number.
tracking_params = dict(n_seeds=100000,
random_seeds=True,
rng_seed=2022,
num_chunks=True)
Initialize an AFQ object¶
Next, we initialize the GroupAFQ
object. Upon initialization, the object
does some validation steps, but no major computation is triggered. Instead,
computation is deferred until the export
method is called.
myafq = GroupAFQ(
bids_path=op.join(afq_home, 'stanford_hardi'),
preproc_pipeline='vistasoft',
tracking_params=tracking_params,
viz_backend_spec='plotly_no_gif')
INFO:AFQ:No seed mask given, using FA (or first scalar if none are FA)thresholded to 0.2 INFO:AFQ:No stop mask given, using FA (or first scalar if none are FA)thresholded to 0.2
Recognize the tracts and calculating tract profiles:¶
The myafq
class instance now has all the information that it needs in order to
do all kinds of computations on the data. Typically, we will want to calculate
the tract profiles. To trigger the
pyAFQ pipeline that calculates the profiles, users can call the
export('profiles')
method.
For the purpose of this demonstration, the pipeline has been run in advance and
cached in the data folder (under /data
). In usual practice, the
following line of code would trigger the full computational pipeline, which
takes about 10 minutes to run and requires about 6GB RAM. However, the caching behavior is typical to pyAFQ. Once derivatives are computed, they are cached such that they
can be reused.
myafq.export('profiles')
{'01': '../data_/tractometry/stanford_hardi/derivatives/afq/sub-01/ses-01/dwi/sub-01_ses-01_desc-profiles_tractography.csv'}
After this line of code has finished running, a CSV file that contains the
tract profiles should be saved into the afq folder within the derivatives
folder of the dataset. At this point, we can export a visualization that
shows all of the tracts and tract profiles of FA by calling export
again.
The call to plotly then renders the html of the figure into the notebook.
bundle_html = myafq.export("all_bundles_figure")
plotly.io.show(bundle_html["01"][0])
INFO:AFQ:Forceps Major and Callosum Occipital bundles are co-located, and AFQ assigns each streamline to only one bundle. Only Callosum Occipital will be used. INFO:AFQ:Forceps Minor and Callosum Orbital bundles are co-located, and AFQ assigns each streamline to only one bundle. Only Callosum Orbital will be used. INFO:AFQ:Forceps Major and Callosum Occipital bundles are co-located, and AFQ assigns each streamline to only one bundle. Only Callosum Occipital will be used. INFO:AFQ:Forceps Minor and Callosum Orbital bundles are co-located, and AFQ assigns each streamline to only one bundle. Only Callosum Orbital will be used. INFO:AFQ:Loading Volume... INFO:AFQ:Loading Volume... INFO:AFQ:Loading Stateful Tractogram... /Users/john/pyAFQ/AFQ/utils/streamlines.py:93: UserWarning: Pass ['to_space'] as keyword args. From version 2.0.0 passing these as positional arguments will result in an error. INFO:AFQ:Generating colorful lines from tractography... WARNING:AFQ:Failed to write HTML file: ../data_/tractometry/stanford_hardi/derivatives/afq/sub-01/ses-01.html