Source code for unravel.image_tools.means_in_mask

#!/usr/bin/env python3

"""
Use ``img_means_in_mask`` or ``means_in_mask`` from UNRAVEL to calculate the mean intensity for each image within a mask.

Usage:
------
    means_in_mask -i path/to/images/`*`.nii.gz -m path/to/mask.nii.gz [-o mean_in_mask.csv] [-v]
"""

import pandas as pd
from pathlib import Path
from rich import print
from rich.live import Live
from rich.traceback import install

from unravel.core.img_io import load_nii
from unravel.core.help_formatter import RichArgumentParser, SuppressMetavar, SM
from unravel.core.utils import initialize_progress_bar, log_command, match_files
from unravel.voxel_stats.apply_mask import load_mask


[docs] def parse_args(): parser = RichArgumentParser(formatter_class=SuppressMetavar, add_help=False, docstring=__doc__) reqs = parser.add_argument_group('Required arguments') reqs.add_argument('-m', '--mask', help="Path to the mask .nii.gz file.", required=True, action=SM) opts = parser.add_argument_group('Optional arguments') opts.add_argument('-i', '--input', help="Path to input .nii.gz image(s) or glob pattern(s). Default: '*.nii.gz'.", nargs='*', default=['*.nii.gz'], action=SM) opts.add_argument('-o', '--output', help='Output CSV file path. Default: mean_in_mask.csv', default='mean_in_mask.csv', action=SM) general = parser.add_argument_group('General arguments') general.add_argument('-v', '--verbose', help='Increase verbosity. Default: False', action='store_true', default=False) return parser.parse_args()
[docs] @log_command def main(): install() args = parse_args() nii_files = match_files(args.input) mask_file = Path(args.mask) mask = load_mask(mask_file) n_voxels = mask.sum() if n_voxels == 0: raise ValueError(f"Mask {mask_file.name} contains no non-zero voxels.") rows = [] progress, task_id = initialize_progress_bar(len(nii_files), "[red]Processing .nii.gz files...") with Live(progress): for nii in nii_files: if args.verbose: print(f"\nProcessing image: {nii.name} with mask: {mask_file.name}") img = load_nii(nii) if img.shape != mask.shape: raise ValueError(f"Image and mask shapes do not match for {nii.name} and {mask_file.name}.") mean_intensity = img[mask].mean() if args.verbose: print(f"{nii.name}: Mean intensity in segmented region = {mean_intensity:.2f}") rows.append({ 'mask': mask_file.name, 'image': nii.name, 'mean_in_mask': mean_intensity }) progress.update(task_id, advance=1) df = pd.DataFrame(rows) output_path = Path(args.output) output_path.parent.mkdir(parents=True, exist_ok=True) df.to_csv(output_path, index=False) print(f"\nResults saved to {output_path}\n")
if __name__ == '__main__': main()