Source code for unravel.cluster_stats.clusters

#!/usr/bin/env python3

"""
Use ``cstats_clusters`` (``clusters``) from UNRAVEL to make a cluster index image from a .nii.gz image.
Note:
    - This uses the cluster command from FSL and then reverses the clusters so that the largest cluster is 1, the second largest is 2, etc.

Usage
-----
    cstats_clusters -i path/image.nii.gz [-ms 100] [-t 0.5] [-o path/image_rev_cluster_index.nii.gz] [-v]
"""

from pathlib import Path
import numpy as np
import nibabel as nib
from rich.traceback import install

from unravel.cluster_stats.fdr import cluster_index, reverse_clusters
from unravel.core.help_formatter import RichArgumentParser, SuppressMetavar, SM
from unravel.core.config import Configuration
from unravel.core.utils import log_command, verbose_start_msg, verbose_end_msg


[docs] def parse_args(): parser = RichArgumentParser(formatter_class=SuppressMetavar, add_help=False, docstring=__doc__) reqs = parser.add_argument_group('Required arguments') reqs.add_argument('-i', '--input', help='path/image.nii.gz', required=True, action=SM) opts = parser.add_argument_group('Optional args') opts.add_argument('-ms', '--min_size', help='Min cluster size in voxels. Default: 100', default=100, type=int, action=SM) opts.add_argument('-t', '--threshold', help='Threshold for cluster formation. Default: 1', default=1, type=float, action=SM) opts.add_argument('-o', '--output', help='path/image_cluster_index.nii.gz', default=None, action=SM) general = parser.add_argument_group('General arguments') general.add_argument('-v', '--verbose', help='Increase verbosity. Default: False', default=False, action='store_true') return parser.parse_args()
# TODO: Some code here is redundant with code in fdr.py. Refactor to avoid redundancy.
[docs] @log_command def main(): install() args = parse_args() Configuration.verbose = args.verbose verbose_start_msg() output = args.output if args.output else args.input.replace('.nii.gz', '_rev_cluster_index.nii.gz') # Create the cluster index cluster_info = cluster_index(args.input, args.min_size, args.threshold, output) # Save cluster info with open(Path(args.input).parent / f"{str(Path(args.input).name).replace('.nii.gz', '_cluster_info.txt')}", 'w') as f: f.write(cluster_info) # Load the cluster index and convert to an ndarray cluster_index_nii = nib.load(output) cluster_index_img = np.asanyarray(cluster_index_nii.dataobj, dtype=np.uint16).squeeze() # Lower the data type if the max cluster ID is less than 256 max_cluster_id = int(cluster_index_img.max()) data_type = np.uint16 if max_cluster_id >= 256 else np.uint8 cluster_index_img = cluster_index_img.astype(data_type) # Reverse cluster ID order in cluster_index and save it rev_cluster_index_img = reverse_clusters(cluster_index_img, output, data_type, cluster_index_nii) verbose_end_msg()
if __name__ == '__main__': main()