From 80650446bda3c2cc707629309dba508b7e536021 Mon Sep 17 00:00:00 2001 From: Gabriel Girard Date: Tue, 3 Dec 2024 14:51:45 -0500 Subject: [PATCH 1/9] NF - added input options for multiple ROI masks --- scripts/scil_volume_stats_in_ROI.py | 103 ++++++++++++++-------------- 1 file changed, 52 insertions(+), 51 deletions(-) diff --git a/scripts/scil_volume_stats_in_ROI.py b/scripts/scil_volume_stats_in_ROI.py index 831373fdc..86b311a87 100755 --- a/scripts/scil_volume_stats_in_ROI.py +++ b/scripts/scil_volume_stats_in_ROI.py @@ -33,9 +33,9 @@ def _build_arg_parser(): p = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawTextHelpFormatter) - p.add_argument('in_mask', - help='Mask volume filename.\nCan be a binary mask or a ' - 'weighted mask.') + p.add_argument('in_masks', nargs='+', + help='Mask volume filenames.\nCan be binary masks or ' + 'weighted masks.') g = p.add_argument_group('Metrics input options') gg = g.add_mutually_exclusive_group(required=True) @@ -74,59 +74,60 @@ def main(): if not os.path.exists(args.metrics_dir): parser.error("Metrics directory does not exist: {}" .format(args.metrics_dir)) - assert_inputs_exist(parser, args.in_mask) + assert_inputs_exist(parser, args.in_masks) tmp_file_list = glob.glob(os.path.join(args.metrics_dir, '*nii.gz')) args.metrics_file_list = [os.path.join(args.metrics_dir, f) for f in tmp_file_list] else: - assert_inputs_exist(parser, [args.in_mask] + args.metrics_file_list) - assert_headers_compatible(parser, - [args.in_mask] + args.metrics_file_list) - - # Loading - mask_data = nib.load(args.in_mask).get_fdata(dtype=np.float32) - if len(mask_data.shape) > 3: - parser.error('Mask should be a 3D image.') - if np.min(mask_data) < 0: - parser.error('Mask should not contain negative values.') - roi_name = split_name_with_nii(os.path.basename(args.in_mask))[0] - - # Discussion about the way the normalization is done. - # https://github.com/scilus/scilpy/pull/202#discussion_r411355609 - # Summary: - # 1) We don't want to normalize with data = (data-min) / (max-min) because - # it zeroes out the minimal values of the array. This is not a large error - # source, but not preferable. - # 2) data = data / max(data) or data = data / sum(data): in practice, when - # we use them in numpy using their weights argument, leads to the same - # result. - if args.normalize_weights: - mask_data /= np.max(mask_data) - elif args.bin: - mask_data[np.where(mask_data > 0.0)] = 1.0 - elif np.min(mask_data) < 0.0 or np.max(mask_data) > 1.0: - parser.error('Mask data should only contain values between 0 and 1. ' - 'Try --normalize_weights.') - - # Load and process all metrics files. - json_stats = {roi_name: {}} - for f in args.metrics_file_list: - metric_img = nib.load(f) - metric_name = split_name_with_nii(os.path.basename(f))[0] - if len(metric_img.shape) == 3: - data = metric_img.get_fdata(dtype=np.float64) - if np.any(np.isnan(data)): - logging.warning("Metric '{}' contains some NaN. Ignoring " - "voxels with NaN." - .format(os.path.basename(f))) - mean, std = weighted_mean_std(mask_data, data) - json_stats[roi_name][metric_name] = {'mean': mean, - 'std': std} - else: - parser.error( - 'Metric {} is not a 3D image ({}D shape).' - .format(f, len(metric_img.shape))) + assert_inputs_exist(parser, args.in_masks + args.metrics_file_list) + assert_headers_compatible(parser, args.in_masks + args.metrics_file_list) + + # Computing stats for all masks and metrics files + json_stats = {} + for mask_filename in args.in_masks: + mask_data = nib.load(mask_filename).get_fdata(dtype=np.float32) + if len(mask_data.shape) > 3: + parser.error('Mask should be a 3D image.') + if np.min(mask_data) < 0: + parser.error('Mask should not contain negative values.') + roi_name = split_name_with_nii(os.path.basename(mask_filename))[0] + + # Discussion about the way the normalization is done. + # https://github.com/scilus/scilpy/pull/202#discussion_r411355609 + # Summary: + # 1) We don't want to normalize with data = (data-min) / (max-min) because + # it zeroes out the minimal values of the array. This is not a large error + # source, but not preferable. + # 2) data = data / max(data) or data = data / sum(data): in practice, when + # we use them in numpy using their weights argument, leads to the same + # result. + if args.normalize_weights: + mask_data /= np.max(mask_data) + elif args.bin: + mask_data[np.where(mask_data > 0.0)] = 1.0 + elif np.min(mask_data) < 0.0 or np.max(mask_data) > 1.0: + parser.error('Mask data should only contain values between 0 and 1. ' + 'Try --normalize_weights.') + + # Load and process all metrics files. + json_stats[roi_name] = {} + for f in args.metrics_file_list: + metric_img = nib.load(f) + metric_name = split_name_with_nii(os.path.basename(f))[0] + if len(metric_img.shape) == 3: + data = metric_img.get_fdata(dtype=np.float64) + if np.any(np.isnan(data)): + logging.warning("Metric '{}' contains some NaN. Ignoring " + "voxels with NaN." + .format(os.path.basename(f))) + mean, std = weighted_mean_std(mask_data, data) + json_stats[roi_name][metric_name] = {'mean': mean, + 'std': std} + else: + parser.error( + 'Metric {} is not a 3D image ({}D shape).' + .format(f, len(metric_img.shape))) # Print results print(json.dumps(json_stats, indent=args.indent, sort_keys=args.sort_keys)) From 9846bd27bb6b55471eca50e0e3daac5b67f43ffb Mon Sep 17 00:00:00 2001 From: Gabriel Girard Date: Tue, 3 Dec 2024 15:44:53 -0500 Subject: [PATCH 2/9] RF - removed the roi dict if a single ROI is used --- scripts/scil_volume_stats_in_ROI.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/scil_volume_stats_in_ROI.py b/scripts/scil_volume_stats_in_ROI.py index 86b311a87..da5257a2b 100755 --- a/scripts/scil_volume_stats_in_ROI.py +++ b/scripts/scil_volume_stats_in_ROI.py @@ -129,6 +129,9 @@ def main(): 'Metric {} is not a 3D image ({}D shape).' .format(f, len(metric_img.shape))) + + if len(args.in_masks) == 1: + json_stats = json_stats[roi_name] # Print results print(json.dumps(json_stats, indent=args.indent, sort_keys=args.sort_keys)) From 1857abd85ebd5ac6ce1fbc9d6c8d33d4edf32459 Mon Sep 17 00:00:00 2001 From: Gabriel Girard Date: Tue, 3 Dec 2024 15:45:24 -0500 Subject: [PATCH 3/9] NF - allow for multiple metrics input --- scripts/scil_volume_stats_in_labels.py | 54 ++++++++++++++++++++------ 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/scripts/scil_volume_stats_in_labels.py b/scripts/scil_volume_stats_in_labels.py index 07fc290b7..57211b170 100755 --- a/scripts/scil_volume_stats_in_labels.py +++ b/scripts/scil_volume_stats_in_labels.py @@ -11,8 +11,10 @@ """ import argparse +import glob import json import logging +import os import nibabel as nib import numpy as np @@ -20,6 +22,7 @@ from scilpy.image.labels import get_data_as_labels, get_stats_in_label from scilpy.io.utils import (add_overwrite_arg, add_verbose_arg, assert_inputs_exist, assert_headers_compatible) +from scilpy.utils.filenames import split_name_with_nii def _build_arg_parser(): @@ -30,8 +33,16 @@ def _build_arg_parser(): p.add_argument('in_labels_lut', help='Path of the LUT file corresponding to labels,' 'used to name the regions of interest.') - p.add_argument('in_map', - help='Path of the input map file. Expecting a 3D file.') + + g = p.add_argument_group('Metrics input options') + gg = g.add_mutually_exclusive_group(required=True) + gg.add_argument('--metrics_dir', metavar='dir', + help='Name of the directory containing metrics files: ' + 'we will \nload all nifti files.') + gg.add_argument('--metrics', dest='metrics_file_list', nargs='+', + metavar='file', + help='Metrics nifti filename. List of the names of the ' + 'metrics file, \nin nifti format.') add_verbose_arg(p) add_overwrite_arg(p) @@ -45,21 +56,42 @@ def main(): logging.getLogger().setLevel(logging.getLevelName(args.verbose)) # Verifications - assert_inputs_exist(parser, - [args.in_labels, args.in_map, args.in_labels_lut]) - assert_headers_compatible(parser, [args.in_labels, args.in_map]) + + # Get input list. Either all files in dir or given list. + if args.metrics_dir: + if not os.path.exists(args.metrics_dir): + parser.error("Metrics directory does not exist: {}" + .format(args.metrics_dir)) + assert_inputs_exist(parser, [args.in_labels, args.in_labels_lut]) + + tmp_file_list = glob.glob(os.path.join(args.metrics_dir, '*nii.gz')) + args.metrics_file_list = [os.path.join(args.metrics_dir, f) + for f in tmp_file_list] + else: + assert_inputs_exist(parser, [args.in_labels] + args.metrics_file_list) + assert_headers_compatible(parser, [args.in_labels] + args.metrics_file_list) + # Loading label_data = get_data_as_labels(nib.load(args.in_labels)) with open(args.in_labels_lut) as f: label_dict = json.load(f) - map_data = nib.load(args.in_map).get_fdata(dtype=np.float32) - if len(map_data.shape) > 3: - parser.error('Mask should be a 3D image.') - # Process - out_dict = get_stats_in_label(map_data, label_data, label_dict) - print(json.dumps(out_dict)) + # Computing stats for all metrics files + json_stats = {} + for metric_filename in args.metrics_file_list: + metric_data = nib.load(metric_filename).get_fdata(dtype=np.float32) + metric_name = split_name_with_nii(os.path.basename(metric_filename))[0] + if len(metric_data.shape) > 3: + parser.error('Mask should be a 3D image.') + + # Process + out_dict = get_stats_in_label(metric_data, label_data, label_dict) + json_stats[metric_name] = out_dict + + if len(args.metrics_file_list) == 1: + json_stats = json_stats[metric_name] + print(json.dumps(json_stats)) if __name__ == "__main__": From 4ac43ea42b920876f2fa437d76421f02489c5f11 Mon Sep 17 00:00:00 2001 From: Gabriel Girard Date: Tue, 3 Dec 2024 15:55:27 -0500 Subject: [PATCH 4/9] RF - change variable names from mask to roi --- scripts/scil_volume_stats_in_ROI.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/scripts/scil_volume_stats_in_ROI.py b/scripts/scil_volume_stats_in_ROI.py index da5257a2b..e6ce2363c 100755 --- a/scripts/scil_volume_stats_in_ROI.py +++ b/scripts/scil_volume_stats_in_ROI.py @@ -33,7 +33,7 @@ def _build_arg_parser(): p = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawTextHelpFormatter) - p.add_argument('in_masks', nargs='+', + p.add_argument('in_rois', nargs='+', help='Mask volume filenames.\nCan be binary masks or ' 'weighted masks.') @@ -74,24 +74,24 @@ def main(): if not os.path.exists(args.metrics_dir): parser.error("Metrics directory does not exist: {}" .format(args.metrics_dir)) - assert_inputs_exist(parser, args.in_masks) + assert_inputs_exist(parser, args.in_rois) tmp_file_list = glob.glob(os.path.join(args.metrics_dir, '*nii.gz')) args.metrics_file_list = [os.path.join(args.metrics_dir, f) for f in tmp_file_list] else: - assert_inputs_exist(parser, args.in_masks + args.metrics_file_list) - assert_headers_compatible(parser, args.in_masks + args.metrics_file_list) + assert_inputs_exist(parser, args.in_rois + args.metrics_file_list) + assert_headers_compatible(parser, args.in_rois + args.metrics_file_list) # Computing stats for all masks and metrics files json_stats = {} - for mask_filename in args.in_masks: - mask_data = nib.load(mask_filename).get_fdata(dtype=np.float32) - if len(mask_data.shape) > 3: + for roi_filename in args.in_rois: + roi_data = nib.load(roi_filename).get_fdata(dtype=np.float32) + if len(roi_data.shape) > 3: parser.error('Mask should be a 3D image.') - if np.min(mask_data) < 0: + if np.min(roi_data) < 0: parser.error('Mask should not contain negative values.') - roi_name = split_name_with_nii(os.path.basename(mask_filename))[0] + roi_name = split_name_with_nii(os.path.basename(roi_filename))[0] # Discussion about the way the normalization is done. # https://github.com/scilus/scilpy/pull/202#discussion_r411355609 @@ -103,10 +103,10 @@ def main(): # we use them in numpy using their weights argument, leads to the same # result. if args.normalize_weights: - mask_data /= np.max(mask_data) + roi_data /= np.max(roi_data) elif args.bin: - mask_data[np.where(mask_data > 0.0)] = 1.0 - elif np.min(mask_data) < 0.0 or np.max(mask_data) > 1.0: + roi_data[np.where(roi_data > 0.0)] = 1.0 + elif np.min(roi_data) < 0.0 or np.max(roi_data) > 1.0: parser.error('Mask data should only contain values between 0 and 1. ' 'Try --normalize_weights.') @@ -121,7 +121,7 @@ def main(): logging.warning("Metric '{}' contains some NaN. Ignoring " "voxels with NaN." .format(os.path.basename(f))) - mean, std = weighted_mean_std(mask_data, data) + mean, std = weighted_mean_std(roi_data, data) json_stats[roi_name][metric_name] = {'mean': mean, 'std': std} else: @@ -130,7 +130,7 @@ def main(): .format(f, len(metric_img.shape))) - if len(args.in_masks) == 1: + if len(args.in_rois) == 1: json_stats = json_stats[roi_name] # Print results print(json.dumps(json_stats, indent=args.indent, sort_keys=args.sort_keys)) From c9819927833ce4d81239574764392ea02d26858f Mon Sep 17 00:00:00 2001 From: Gabriel Girard Date: Tue, 3 Dec 2024 16:01:13 -0500 Subject: [PATCH 5/9] DOC - updated script documentation --- scripts/scil_volume_stats_in_ROI.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/scripts/scil_volume_stats_in_ROI.py b/scripts/scil_volume_stats_in_ROI.py index e6ce2363c..6f726277e 100755 --- a/scripts/scil_volume_stats_in_ROI.py +++ b/scripts/scil_volume_stats_in_ROI.py @@ -3,11 +3,11 @@ """ Compute the statistics (mean, std) of scalar maps, which can represent -diffusion metrics, in a ROI. Prints the results. +diffusion metrics, in ROIs. Prints the results. -The mask can either be a binary mask, or a weighting mask. If the mask is -a weighting mask it should either contain floats between 0 and 1 or should be -normalized with --normalize_weights. IMPORTANT: if the mask contains weights +The ROIs can either be a binary masks, or a weighting masks. If the ROIs are + weighting masks it should either contain floats between 0 and 1 or should be +normalized with --normalize_weights. IMPORTANT: if the ROIs contain weights (and not 0 and 1 exclusively), the standard deviation will also be weighted. """ @@ -34,7 +34,7 @@ def _build_arg_parser(): formatter_class=argparse.RawTextHelpFormatter) p.add_argument('in_rois', nargs='+', - help='Mask volume filenames.\nCan be binary masks or ' + help='ROIs volume filenames.\nCan be binary masks or ' 'weighted masks.') g = p.add_argument_group('Metrics input options') @@ -83,14 +83,15 @@ def main(): assert_inputs_exist(parser, args.in_rois + args.metrics_file_list) assert_headers_compatible(parser, args.in_rois + args.metrics_file_list) - # Computing stats for all masks and metrics files + # Computing stats for all ROIs and metrics files json_stats = {} for roi_filename in args.in_rois: roi_data = nib.load(roi_filename).get_fdata(dtype=np.float32) if len(roi_data.shape) > 3: - parser.error('Mask should be a 3D image.') + parser.error('ROI {} should be a 3D image.'.format(roi_filename)) if np.min(roi_data) < 0: - parser.error('Mask should not contain negative values.') + parser.error('ROI {} should not contain negative values.' + .format(roi_filename)) roi_name = split_name_with_nii(os.path.basename(roi_filename))[0] # Discussion about the way the normalization is done. @@ -107,8 +108,9 @@ def main(): elif args.bin: roi_data[np.where(roi_data > 0.0)] = 1.0 elif np.min(roi_data) < 0.0 or np.max(roi_data) > 1.0: - parser.error('Mask data should only contain values between 0 and 1. ' - 'Try --normalize_weights.') + parser.error('ROI {} data should only contain values between 0 and 1. ' + 'Try --normalize_weights.' + .format(roi_filename)) # Load and process all metrics files. json_stats[roi_name] = {} @@ -129,9 +131,9 @@ def main(): 'Metric {} is not a 3D image ({}D shape).' .format(f, len(metric_img.shape))) - if len(args.in_rois) == 1: json_stats = json_stats[roi_name] + # Print results print(json.dumps(json_stats, indent=args.indent, sort_keys=args.sort_keys)) From 992be21fda532e4c136c3ed1305ff1942f912751 Mon Sep 17 00:00:00 2001 From: Gabriel Girard Date: Tue, 3 Dec 2024 16:05:30 -0500 Subject: [PATCH 6/9] TST - updated tests, pep8 --- scripts/scil_volume_stats_in_ROI.py | 2 +- scripts/scil_volume_stats_in_labels.py | 3 +-- scripts/tests/test_volume_stats_in_ROI.py | 4 ++-- scripts/tests/test_volume_stats_in_labels.py | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/scripts/scil_volume_stats_in_ROI.py b/scripts/scil_volume_stats_in_ROI.py index 6f726277e..9fc6002bf 100755 --- a/scripts/scil_volume_stats_in_ROI.py +++ b/scripts/scil_volume_stats_in_ROI.py @@ -125,7 +125,7 @@ def main(): .format(os.path.basename(f))) mean, std = weighted_mean_std(roi_data, data) json_stats[roi_name][metric_name] = {'mean': mean, - 'std': std} + 'std': std} else: parser.error( 'Metric {} is not a 3D image ({}D shape).' diff --git a/scripts/scil_volume_stats_in_labels.py b/scripts/scil_volume_stats_in_labels.py index 57211b170..35d5c6c16 100755 --- a/scripts/scil_volume_stats_in_labels.py +++ b/scripts/scil_volume_stats_in_labels.py @@ -71,7 +71,6 @@ def main(): assert_inputs_exist(parser, [args.in_labels] + args.metrics_file_list) assert_headers_compatible(parser, [args.in_labels] + args.metrics_file_list) - # Loading label_data = get_data_as_labels(nib.load(args.in_labels)) with open(args.in_labels_lut) as f: @@ -88,7 +87,7 @@ def main(): # Process out_dict = get_stats_in_label(metric_data, label_data, label_dict) json_stats[metric_name] = out_dict - + if len(args.metrics_file_list) == 1: json_stats = json_stats[metric_name] print(json.dumps(json_stats)) diff --git a/scripts/tests/test_volume_stats_in_ROI.py b/scripts/tests/test_volume_stats_in_ROI.py index af3dd29ec..71eb2bc8d 100644 --- a/scripts/tests/test_volume_stats_in_ROI.py +++ b/scripts/tests/test_volume_stats_in_ROI.py @@ -19,10 +19,10 @@ def test_help_option(script_runner): def test_execution_tractometry(script_runner, monkeypatch): monkeypatch.chdir(os.path.expanduser(tmp_dir.name)) - in_mask = os.path.join(SCILPY_HOME, 'tractometry', + in_roi = os.path.join(SCILPY_HOME, 'tractometry', 'IFGWM.nii.gz') in_ref = os.path.join(SCILPY_HOME, 'tractometry', 'mni_masked.nii.gz') ret = script_runner.run('scil_volume_stats_in_ROI.py', - in_mask, '--metrics', in_ref) + in_roi, '--metrics', in_ref) assert ret.success diff --git a/scripts/tests/test_volume_stats_in_labels.py b/scripts/tests/test_volume_stats_in_labels.py index 83bd07b8f..df1ea8064 100644 --- a/scripts/tests/test_volume_stats_in_labels.py +++ b/scripts/tests/test_volume_stats_in_labels.py @@ -21,5 +21,5 @@ def test_execution(script_runner, monkeypatch): in_atlas = os.path.join(SCILPY_HOME, 'plot', 'atlas_brainnetome.nii.gz') atlas_lut = os.path.join(SCILPY_HOME, 'plot', 'atlas_brainnetome.json') ret = script_runner.run('scil_volume_stats_in_labels.py', - in_atlas, atlas_lut, in_map) + in_atlas, atlas_lut, "--metrics", in_map) assert ret.success From 78def7a691706ba0632dfe7721fdf5a81debaa6a Mon Sep 17 00:00:00 2001 From: Gabriel Girard Date: Tue, 3 Dec 2024 16:15:53 -0500 Subject: [PATCH 7/9] NF - added add_json_args to the arguments, format the output json --- scripts/scil_volume_stats_in_ROI.py | 16 ++++++++-------- scripts/scil_volume_stats_in_labels.py | 9 +++++---- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/scripts/scil_volume_stats_in_ROI.py b/scripts/scil_volume_stats_in_ROI.py index 9fc6002bf..4382a4a9c 100755 --- a/scripts/scil_volume_stats_in_ROI.py +++ b/scripts/scil_volume_stats_in_ROI.py @@ -97,19 +97,19 @@ def main(): # Discussion about the way the normalization is done. # https://github.com/scilus/scilpy/pull/202#discussion_r411355609 # Summary: - # 1) We don't want to normalize with data = (data-min) / (max-min) because - # it zeroes out the minimal values of the array. This is not a large error - # source, but not preferable. - # 2) data = data / max(data) or data = data / sum(data): in practice, when - # we use them in numpy using their weights argument, leads to the same - # result. + # 1) We don't want to normalize with data = (data-min) / (max-min) + # because it zeroes out the minimal values of the array. This is + # not a large error source, but not preferable. + # 2) data = data / max(data) or data = data / sum(data): in practice, + # when we use them in numpy using their weights argument, leads to the + # same result. if args.normalize_weights: roi_data /= np.max(roi_data) elif args.bin: roi_data[np.where(roi_data > 0.0)] = 1.0 elif np.min(roi_data) < 0.0 or np.max(roi_data) > 1.0: - parser.error('ROI {} data should only contain values between 0 and 1. ' - 'Try --normalize_weights.' + parser.error('ROI {} data should only contain values between 0 ' + 'and 1. Try --normalize_weights.' .format(roi_filename)) # Load and process all metrics files. diff --git a/scripts/scil_volume_stats_in_labels.py b/scripts/scil_volume_stats_in_labels.py index 35d5c6c16..6a311459f 100755 --- a/scripts/scil_volume_stats_in_labels.py +++ b/scripts/scil_volume_stats_in_labels.py @@ -20,7 +20,7 @@ import numpy as np from scilpy.image.labels import get_data_as_labels, get_stats_in_label -from scilpy.io.utils import (add_overwrite_arg, add_verbose_arg, +from scilpy.io.utils import (add_json_args, add_overwrite_arg, add_verbose_arg, assert_inputs_exist, assert_headers_compatible) from scilpy.utils.filenames import split_name_with_nii @@ -43,7 +43,7 @@ def _build_arg_parser(): metavar='file', help='Metrics nifti filename. List of the names of the ' 'metrics file, \nin nifti format.') - + add_json_args(p) add_verbose_arg(p) add_overwrite_arg(p) @@ -69,7 +69,8 @@ def main(): for f in tmp_file_list] else: assert_inputs_exist(parser, [args.in_labels] + args.metrics_file_list) - assert_headers_compatible(parser, [args.in_labels] + args.metrics_file_list) + assert_headers_compatible(parser, + [args.in_labels] + args.metrics_file_list) # Loading label_data = get_data_as_labels(nib.load(args.in_labels)) @@ -90,7 +91,7 @@ def main(): if len(args.metrics_file_list) == 1: json_stats = json_stats[metric_name] - print(json.dumps(json_stats)) + print(json.dumps(json_stats, indent=args.indent, sort_keys=args.sort_keys)) if __name__ == "__main__": From cc2dc8d2d6230a83f458b88d222262b88b9e6992 Mon Sep 17 00:00:00 2001 From: Gabriel Girard Date: Thu, 19 Dec 2024 15:50:41 -0500 Subject: [PATCH 8/9] TST - Scripts inputs --- scripts/tests/test_volume_stats_in_ROI.py | 26 +++++++++++++++++++- scripts/tests/test_volume_stats_in_labels.py | 19 ++++++++++++-- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/scripts/tests/test_volume_stats_in_ROI.py b/scripts/tests/test_volume_stats_in_ROI.py index 71eb2bc8d..c03593858 100644 --- a/scripts/tests/test_volume_stats_in_ROI.py +++ b/scripts/tests/test_volume_stats_in_ROI.py @@ -20,9 +20,33 @@ def test_help_option(script_runner): def test_execution_tractometry(script_runner, monkeypatch): monkeypatch.chdir(os.path.expanduser(tmp_dir.name)) in_roi = os.path.join(SCILPY_HOME, 'tractometry', - 'IFGWM.nii.gz') + 'IFGWM.nii.gz') in_ref = os.path.join(SCILPY_HOME, 'tractometry', 'mni_masked.nii.gz') + + # Test with a single ROI input ret = script_runner.run('scil_volume_stats_in_ROI.py', in_roi, '--metrics', in_ref) assert ret.success + + # Test with multiple ROIs input + ret = script_runner.run('scil_volume_stats_in_ROI.py', + in_roi, in_roi, in_roi, '--metrics', in_ref) + assert ret.success + + # Test with multiple metric input + ret = script_runner.run('scil_volume_stats_in_ROI.py', + in_roi, '--metrics', in_ref, in_ref, in_ref) + assert ret.success + + # Test with multiple metric and ROIs input + ret = script_runner.run('scil_volume_stats_in_ROI.py', + in_roi, in_roi, '--metrics', in_ref, in_ref) + assert ret.success + + # Test with a metric folder + metrics_dir = os.path.join(SCILPY_HOME, 'plot') + in_roi = os.path.join(SCILPY_HOME, 'plot', 'mask_wm.nii.gz') + ret = script_runner.run('scil_volume_stats_in_ROI.py', + in_roi, '--metrics_dir', metrics_dir) + assert ret.success diff --git a/scripts/tests/test_volume_stats_in_labels.py b/scripts/tests/test_volume_stats_in_labels.py index df1ea8064..4a4471384 100644 --- a/scripts/tests/test_volume_stats_in_labels.py +++ b/scripts/tests/test_volume_stats_in_labels.py @@ -17,9 +17,24 @@ def test_help_option(script_runner): def test_execution(script_runner, monkeypatch): monkeypatch.chdir(os.path.expanduser(tmp_dir.name)) - in_map = os.path.join(SCILPY_HOME, 'plot', 'fa.nii.gz') + in_metric = os.path.join(SCILPY_HOME, 'plot', 'fa.nii.gz') in_atlas = os.path.join(SCILPY_HOME, 'plot', 'atlas_brainnetome.nii.gz') atlas_lut = os.path.join(SCILPY_HOME, 'plot', 'atlas_brainnetome.json') + + # Test with a single metric + ret = script_runner.run('scil_volume_stats_in_labels.py', + in_atlas, atlas_lut, "--metrics", in_metric) + assert ret.success + + # Test with multiple metrics + ret = script_runner.run('scil_volume_stats_in_labels.py', + in_atlas, atlas_lut, "--metrics", + in_metric, in_metric, in_metric) + assert ret.success + + # Test with a metric folder + metrics_dir = os.path.join(SCILPY_HOME, 'plot') ret = script_runner.run('scil_volume_stats_in_labels.py', - in_atlas, atlas_lut, "--metrics", in_map) + in_atlas, atlas_lut, "--metrics_dir", + metrics_dir) assert ret.success From fe35d8e9adb449eb7e7758e9dcb3bca4a51803d7 Mon Sep 17 00:00:00 2001 From: Gabriel Girard Date: Wed, 8 Jan 2025 11:24:59 -0500 Subject: [PATCH 9/9] BF - fixed errenous path when using metrics_dir --- scripts/scil_volume_stats_in_ROI.py | 4 +--- scripts/scil_volume_stats_in_labels.py | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/scripts/scil_volume_stats_in_ROI.py b/scripts/scil_volume_stats_in_ROI.py index 4382a4a9c..88916becf 100755 --- a/scripts/scil_volume_stats_in_ROI.py +++ b/scripts/scil_volume_stats_in_ROI.py @@ -76,9 +76,7 @@ def main(): .format(args.metrics_dir)) assert_inputs_exist(parser, args.in_rois) - tmp_file_list = glob.glob(os.path.join(args.metrics_dir, '*nii.gz')) - args.metrics_file_list = [os.path.join(args.metrics_dir, f) - for f in tmp_file_list] + args.metrics_file_list = glob.glob(os.path.join(args.metrics_dir, '*nii.gz')) else: assert_inputs_exist(parser, args.in_rois + args.metrics_file_list) assert_headers_compatible(parser, args.in_rois + args.metrics_file_list) diff --git a/scripts/scil_volume_stats_in_labels.py b/scripts/scil_volume_stats_in_labels.py index 6a311459f..05963e5af 100755 --- a/scripts/scil_volume_stats_in_labels.py +++ b/scripts/scil_volume_stats_in_labels.py @@ -64,9 +64,7 @@ def main(): .format(args.metrics_dir)) assert_inputs_exist(parser, [args.in_labels, args.in_labels_lut]) - tmp_file_list = glob.glob(os.path.join(args.metrics_dir, '*nii.gz')) - args.metrics_file_list = [os.path.join(args.metrics_dir, f) - for f in tmp_file_list] + args.metrics_file_list = glob.glob(os.path.join(args.metrics_dir, '*nii.gz')) else: assert_inputs_exist(parser, [args.in_labels] + args.metrics_file_list) assert_headers_compatible(parser,