Commit f32c10dc authored by William Clarke's avatar William Clarke
Browse files

AAdd merge and split to mrs_tools. Add tests.

parent 9733cd25
......@@ -51,6 +51,59 @@ def main():
help='NIFTI-MRS tag. Do not average across this dimension.')
visparser.set_defaults(func=vis)
# Merge tool - Merge NIfTI MRS along higher dimensions
mergeparser = sp.add_parser(
'merge',
help='Merge NIfTI-MRS along higher dimensions.')
mergeparser.add_argument('--files', type=Path, required=True, nargs='+',
help='List of files to merge')
mergeparser.add_argument('--dim', type=str, required=True,
help='NIFTI-MRS dimension tag to merge across.')
mergeparser.add_argument('--output',
required=True, type=Path, default=Path('.'),
help='output folder (defaults to current directory)')
mergeparser.add_argument('--filename', type=str,
help='Override output file name.')
mergeparser.set_defaults(func=merge)
# Split tool
splitparser = sp.add_parser(
'split',
help='Split NIfTI-MRS along higher dimensions.')
splitparser.add_argument('--file', type=Path, required=True,
help='File to split')
splitparser.add_argument('--dim', type=str, required=True,
help='NIFTI-MRS dimension tag to split across.')
group = splitparser.add_mutually_exclusive_group(required=True)
group.add_argument('--indices', type=int, nargs='+',
help='List of indices to extract into second file.'
'All indices are zero-indexed.')
group.add_argument('--index', type=int, nargs='+',
help='Index to split at (split after index, zero-indexed).')
splitparser.add_argument('--output',
required=True, type=Path, default=Path('.'),
help='output folder (defaults to current directory)')
splitparser.add_argument('--filename', type=str,
help='Override output file names.')
splitparser.set_defaults(func=split)
# Reorder tool
reorderparser = sp.add_parser(
'reorder',
help='Reorider higher dimensions of NIfTI-MRS.')
reorderparser.add_argument('--file', type=Path, required=True,
help='File to reorder')
reorderparser.add_argument('--dim_order', type=str, nargs='+', required=True,
help='NIFTI-MRS dimension tags in desired order. '
'Enter as strings (min:1, max:3). '
'Can create singleton dimension at end.')
reorderparser.add_argument('--output',
required=True, type=Path, default=Path('.'),
help='output folder (defaults to current directory)')
reorderparser.add_argument('--filename', type=str,
help='Override output file names.')
reorderparser.set_defaults(func=reorder)
# Parse command-line arguments
args = p.parse_args()
......@@ -59,6 +112,10 @@ def main():
def info(args):
"""Prints basic information about NIfTI-MRS files
:param args: Argparse interpreted arguments
:type args: Namespace
"""
from fsl_mrs.utils.mrs_io import read_FID
from fsl_mrs.utils.constants import GYRO_MAG_RATIO
......@@ -80,6 +137,10 @@ def info(args):
def vis(args):
"""Visualiser for NIfTI-MRS files
:param args: Argparse interpreted arguments
:type args: Namespace
"""
from fsl_mrs.utils.plotting import plot_spectrum, FID2Spec, plot_spectra
from fsl_mrs.utils.mrs_io import read_FID, read_basis
import matplotlib.pyplot as plt
......@@ -168,5 +229,86 @@ def vis(args):
mrsi.plot()
def merge(args):
"""Merges one or more NIfTI-MRS files along a specified dimension
:param args: Argparse interpreted arguments
:type args: Namespace
"""
from fsl_mrs.utils import nifti_mrs_tools as nmrs_tools
from fsl_mrs.utils import mrs_io
# 1. Load the files
if len(args.files) < 2:
raise ValueError('Files argument must provide two or more files to merge.')
to_concat = []
concat_names = []
for fp in args.files:
concat_names.append(fp.with_suffix('').with_suffix('').name)
to_concat.append(mrs_io.read_FID(str(fp)))
# 2. Merge the files
merged = nmrs_tools.merge(to_concat, args.dim)
# 3. Save the output file
if args.filename:
file_out = args.output / args.filename
else:
file_out = args.output / ('_'.join(concat_names) + '_merged')
merged.save(file_out)
def split(args):
"""Splits a NIfTI-MRS file into two along a specified dimension
:param args: Argparse interpreted arguments
:type args: Namespace
"""
from fsl_mrs.utils import nifti_mrs_tools as nmrs_tools
from fsl_mrs.utils import mrs_io
# 1. Load the file
to_split = mrs_io.read_FID(str(args.file))
split_name = args.file.with_suffix('').with_suffix('').name
# 2. Merge the files
if args.index:
split_1, split_2 = nmrs_tools.split(to_split, args.dim, args.index)
elif args.indices:
split_1, split_2 = nmrs_tools.split(to_split, args.dim, args.indices)
# 3. Save the output file
if args.filename:
file_out_1 = args.output / (args.filename + '_1')
file_out_2 = args.output / (args.filename + '_2')
else:
file_out_1 = args.output / (split_name + '_1')
file_out_2 = args.output / (split_name + '_2')
split_1.save(file_out_1)
split_2.save(file_out_2)
def reorder(args):
"""Reorders the higher dimensions of a NIfTI-MRS file
:param args: Argparse interpreted arguments
:type args: Namespace
"""
from fsl_mrs.utils import nifti_mrs_tools as nmrs_tools
from fsl_mrs.utils import mrs_io
# 1. Load the file
to_reorder = mrs_io.read_FID(str(args.file))
reorder_name = args.file.with_suffix('').with_suffix('').name
# 2. Merge the files
dim_order = args.dim_order
while len(dim_order) < 3:
dim_order.append(None)
reordered = nmrs_tools.reorder(to_reorder, args.dim_order)
# 3. Save the output file
if args.filename:
file_out = args.output / args.filename
else:
file_out = args.output / (reorder_name + '_reordered')
reordered.save(file_out)
if __name__ == '__main__':
main()
......@@ -17,7 +17,7 @@ basis = testsPath / 'testdata/fsl_mrs/steam_basis'
def test_vis_svs(tmp_path):
subprocess.check_call(['mrs_vis',
subprocess.check_call(['mrs_tools', 'vis',
'--ppmlim', '0.2', '4.2',
'--save', str(tmp_path / 'svs.png'),
svs])
......@@ -26,7 +26,7 @@ def test_vis_svs(tmp_path):
def test_vis_basis(tmp_path):
subprocess.check_call(['mrs_vis',
subprocess.check_call(['mrs_tools', 'vis',
'--ppmlim', '0.2', '4.2',
'--save', str(tmp_path / 'basis.png'),
basis])
......@@ -40,8 +40,106 @@ unprocessed = testsPath / 'testdata/fsl_mrs_preproc/metab_raw.nii.gz'
def test_single_info(tmp_path):
subprocess.check_call(['mrs_info', str(processed)])
subprocess.check_call(['mrs_tools', 'info', str(processed)])
def test_multi_info(tmp_path):
subprocess.check_call(['mrs_info', str(processed), str(unprocessed)])
subprocess.check_call(['mrs_tools', 'info', str(processed), str(unprocessed)])
# Testing merge option
test_data_merge_1 = testsPath / 'testdata' / 'fsl_mrs_preproc' / 'wref_raw.nii.gz'
test_data_merge_2 = testsPath / 'testdata' / 'fsl_mrs_preproc' / 'quant_raw.nii.gz'
def test_merge(tmp_path):
"""The tests here only check that the expected files are created.
I rely on the much more detailed tests in test_utils_nifti_mrs_tools_split_merge.py
to check that the merge is carried out correctly.
"""
subprocess.check_call(['mrs_tools', 'merge',
'--dim', 'DIM_DYN',
'--output', str(tmp_path),
'--filename', 'test_2_merge',
'--files', str(test_data_merge_1), str(test_data_merge_2)])
assert (tmp_path / 'test_2_merge.nii.gz').exists()
subprocess.check_call(['mrs_tools', 'merge',
'--dim', 'DIM_DYN',
'--output', str(tmp_path),
'--filename', 'test_3_merge',
'--files', str(test_data_merge_1), str(test_data_merge_2), str(test_data_merge_2)])
assert (tmp_path / 'test_3_merge.nii.gz').exists()
subprocess.check_call(['mrs_tools', 'merge',
'--dim', 'DIM_DYN',
'--output', str(tmp_path),
'--files', str(test_data_merge_1), str(test_data_merge_2)])
assert (tmp_path / 'wref_raw_quant_raw_merged.nii.gz').exists()
# Test split option
test_data_split = testsPath / 'testdata' / 'fsl_mrs_preproc' / 'metab_raw.nii.gz'
def test_split(tmp_path):
"""The tests here only check that the expected files are created.
I rely on the much more detailed tests in test_utils_nifti_mrs_tools_split_merge.py
to check that the merge is carried out correctly.
"""
subprocess.check_call(['mrs_tools', 'split',
'--dim', 'DIM_DYN',
'--index', '31',
'--output', str(tmp_path),
'--filename', 'split_file',
'--file', str(test_data_split)])
assert (tmp_path / 'split_file_1.nii.gz').exists()
assert (tmp_path / 'split_file_2.nii.gz').exists()
subprocess.check_call(['mrs_tools', 'split',
'--dim', 'DIM_DYN',
'--index', '31',
'--output', str(tmp_path),
'--file', str(test_data_split)])
assert (tmp_path / 'metab_raw_1.nii.gz').exists()
assert (tmp_path / 'metab_raw_2.nii.gz').exists()
subprocess.check_call(['mrs_tools', 'split',
'--dim', 'DIM_DYN',
'--indices', '31', '34', '40',
'--output', str(tmp_path),
'--file', str(test_data_split)])
assert (tmp_path / 'metab_raw_1.nii.gz').exists()
assert (tmp_path / 'metab_raw_2.nii.gz').exists()
# Test reorder option
def test_reorder(tmp_path):
subprocess.check_call(['mrs_tools', 'reorder',
'--dim_order', 'DIM_DYN', 'DIM_COIL',
'--output', str(tmp_path),
'--filename', 'reordered_file',
'--file', str(test_data_split)])
assert (tmp_path / 'reordered_file.nii.gz').exists()
subprocess.check_call(['mrs_tools', 'reorder',
'--dim_order', 'DIM_COIL', 'DIM_DYN', 'DIM_EDIT',
'--output', str(tmp_path),
'--file', str(test_data_split)])
assert (tmp_path / 'metab_raw_reordered.nii.gz').exists()
subprocess.check_call(['mrs_tools', 'reorder',
'--dim_order', 'DIM_EDIT', 'DIM_COIL', 'DIM_DYN',
'--output', str(tmp_path),
'--filename', 'reordered_file',
'--file', str(test_data_split)])
assert (tmp_path / 'reordered_file.nii.gz').exists()
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment