The pyAFQ Mask API

In the process of tractometry, it is sometimes necessary to apply masks to the data. By default, pyAFQ can automatically generate these masks from the DWI data. However, pyAFQ also has a system for users to specify which mask to use, called the Mask API. Specifying a mask, in general, is not as simple as just providing a path to a file, because each subject and each session will have a different mask. That is why we developed pyAFQ’s Mask API.

Currently, there are three different masks that pyAFQ uses for tractometry:

  1. The brain mask. This is used to mask the dwi data and throwout any signal that is outside of the brain. It is typicall applied before fitting ODF models. By default, it is calculated using AFQ.definitions.mask.B0Mask.

  2. The tractography seed mask. This mask determines where tractography is seeded. If it is floating point, the mask is thresholded interally after interpolation using the seed_threshold parameter. This is reccomended. However, the seed mask can aslo be a binary mask. By default, the seed mask is AFQ.definitions.mask.ScalarMask (best_scalar) where best_scalar is chosen by the API based on valid scalars (typically “dti_fa”).

  3. The tractography stop mask. This mask determines where tractography stops. If it is floating point, the mask is thresholded interally after interpolation using the stop_threshold parameter. This is reccomended. However, the stop mask can aslo be a binary mask. By default, the stop mask is AFQ.definitions.mask.ScalarMask (best_scalar) where best_scalar is chosen by the API based on valid scalars (typically “dti_fa”).

In AFQ/definitions/mask.py, there are several mask classes one can use to specify masks. As a user, one should initialize mask classes and pass them to the AFQ object, or write out the initialization as a string inside of one’s configuration file for use with the CLI.

  • AFQ.definitions.mask.MaskFile: The simplest mask class is AFQ.definitions.mask.MaskFile. If the mask you want to use is already generated, use this class. It is initialized using BIDS filters, which pyAFQ will use to find masks for each subject in each session.

  • AFQ.definitions.mask.FullMask: The AFQ.definitions.mask.FullMask class is used if one does not want to mask at all. This mask is True everywhere.

  • AFQ.definitions.mask.RoiMask: All ROIs are “logically or’d” together in subject space to create this mask. This is useful to provide as the seed mask. In segmentation, pyAFQ retains only streamlines that pass through the ROIs. So, for efficiency, one can choose to only seed in the ROIs in the first place.

  • AFQ.definitions.mask.B0Mask: This mask uses dipy’s median_otsu on the subject’s b0 to generate a mask. This is the default brain mask.

  • AFQ.definitions.mask.LabelledMaskFile: This mask is similar to AFQ.definitions.mask.MaskFile. It is also initialized using BIDS filters but instead expects to find a labelled segmentation file. In the initialization, the user also provides inclusive and exclusive labels. These specify which labels to include and which labels to exclude in the mask. If both inclusive and exclusive labels are set, the combine parameter is used to specify how to combine the masks generated by the inclusive and exclusive labels. A common use of this class would be to pass BIDS filters to some segmentation file, and also set exclusive_labels = [0]. This will mark all labels that are not 0 as a part of the mask, and can be used as a brain mask.

  • AFQ.definitions.mask.ThresholdedMaskFile: This mask is similar to AFQ.definitions.mask.MaskFile. It allows the user to also provide a lower and upper bound. The bounds threshold the data from the file. Note that for the tractography seed and stop masks, thresholding should typically be done using the seed_threshold and stop_threshold parameters, not using an already thresholded mask.

  • AFQ.definitions.mask.ScalarMask: This mask is initialized only by specifying a scalar. Use this mask if you want a mask to be based on a scalar that pyAFQ already calculates, like “dti_fa” or “dti_md”.

  • AFQ.definitions.mask.ThresholdedScalarMask: This mask is similar to AFQ.definitions.mask.ScalarMask. It allows the user to also provide a lower and upper bound. The bounds threshold the scalar data. Note that for the tractography seed and stop masks, thresholding should typically be done using the seed_threshold and stop_threshold parameters, not using an already thresholded mask.

  • AFQ.definitions.mask.PFTMask: A mask for specifying the segmentations used in PFT. Should only be used as a stop mask. It’s three arguments are three other masks, which specify the three segmentations: white matter, gray matter, and corticospinal fluid.

  • AFQ.definitions.mask.CombinedMask: This class can be used to combine the other masks. It takes a list of masks and allows the user to specify whether they should be combined using a logical “and” or “or”.

Here is an example of using the AFQ.definitions.mask.RoiMask and AFQ.definitions.mask.LabelledMaskFile on the HCP data with the AFQ object:

from AFQ.data import fetch_hcp
from AFQ.api.group import GroupAFQ
import AFQ.definitions.mask as afm

# Download a subject to the AWS Batch machine from s3
_, hcp_bids = fetch_hcp(
    [1],
    profile_name=False,
    study=f"HCP_1200")

# make 500,000 seeds randomly distributed in the ROIs
tracking_params = {
    "seed_mask": afm.RoiMask(),
    "n_seeds": 500000,
    "random_seeds": True}

# use segmentation file from HCP to get a brain mask,
# where everything not labelled 0 is considered a part of the brain
brain_mask_definition = afm.LabelledMaskFile(
    suffix='seg', {'scope': 'dmriprep'}, exclusive_labels=[0])

# define the api GroupAFQ object
myafq = GroupAFQ(
    hcp_bids,
    brain_mask_definition=brain_mask_definition,
    tracking_params=tracking_params)

# export_all runs the entire pipeline and creates many useful derivates
myafq.export_all()