diff --git a/fsl/scripts/fsl_convert_x5.py b/fsl/scripts/fsl_convert_x5.py index 5dc220cf021e8c967054cb465a6e9f733801815f..4cf94ceb183ba6ea6beb5cc635907ef1c6665f60 100644 --- a/fsl/scripts/fsl_convert_x5.py +++ b/fsl/scripts/fsl_convert_x5.py @@ -9,47 +9,64 @@ transformation file formats. """ -import os.path as op -import sys -import shutil -import logging -import argparse +import os.path as op +import sys +import shutil +import logging +import argparse +from collections import OrderedDict -import fsl.data.image as fslimage -import fsl.transform as transform +import fsl.data.image as fslimage +import fsl.transform.flirt as flirt +import fsl.transform.fnirt as fnirt +import fsl.transform.x5 as x5 log = logging.getLogger(__name__) def parseArgs(args): + """Create an argument parser and parse the given ``args``. + + :arg args: Sequence of commane line arguments. + :return: An ``argparse.Namespace`` object containing parsed arguments. + """ + + helps = { + 'input' : 'Input file', + 'output' : 'Output file', + 'source' : 'Source image', + 'reference' : 'Reference image', + 'input_format' : 'Input format - if not provided, the input format ' + 'is automatically inferred from the input file ' + 'name.', + 'output_format' : 'Output format - if not provided, the output format ' + 'is automatically inferred from the output file ' + 'name.', + } parser = argparse.ArgumentParser('fsl_convert_x5') subparsers = parser.add_subparsers(dest='ctype') flirt = subparsers.add_parser('flirt') fnirt = subparsers.add_parser('fnirt') - - flirt.add_argument('input') - flirt.add_argument('output') - flirt.add_argument('-s', '--source') - flirt.add_argument('-r', '--reference') - flirt.add_argument('-if', '--input_format', choices=('x5', 'mat')) - flirt.add_argument('-of', '--output_format', choices=('x5', 'mat')) - - intype = fnirt.add_mutually_exclusive_group() - outtype = fnirt.add_mutually_exclusive_group() - - fnirt .add_argument('input') - fnirt .add_argument('output') - fnirt .add_argument('-s', '--source') - fnirt .add_argument('-r', '--reference') - fnirt .add_argument('-if', '--input_format', choices=('x5', 'nii')) - fnirt .add_argument('-of', '--output_format', choices=('x5', 'nii')) - intype .add_argument('-ai', '--absin', action='store_const', const='absolute', dest='inDispType') - intype .add_argument('-ri', '--relin', action='store_const', const='relative', dest='inDispType') - outtype.add_argument('-ao', '--absout', action='store_const', const='absolute', dest='outDispType') - outtype.add_argument('-ro', '--relout', action='store_const', const='relative', dest='outDispType') + flirt.add_argument('input', help=helps['input']) + flirt.add_argument('output', help=helps['output']) + flirt.add_argument('-s', '--source', help=helps['source']) + flirt.add_argument('-r', '--reference', help=helps['reference']) + flirt.add_argument('-if', '--input_format', help=helps['input_format'], + choices=('x5', 'mat')) + flirt.add_argument('-of', '--output_format', help=helps['output_format'], + choices=('x5', 'mat')) + + fnirt .add_argument('input', help=helps['input']) + fnirt .add_argument('output', help=helps['output']) + fnirt .add_argument('-s', '--source', help=helps['source']) + fnirt .add_argument('-r', '--reference', help=helps['reference']) + fnirt .add_argument('-if', '--input_format', help=helps['input_format'], + choices=('x5', 'nii')) + fnirt .add_argument('-of', '--output_format', help=helps['output_format'], + choices=('x5', 'nii')) args = parser.parse_args(args) @@ -57,34 +74,54 @@ def parseArgs(args): parser.print_help() sys.exit(0) - def getfmt(arg, fname): + # If input/output formats were not + # specified, infer them from the + # file names + def getfmt(arg, fname, exist): ext = op.splitext(fname)[1] if ext in ('.mat', '.x5'): return ext[1:] - if fslimage.looksLikeImage(fslimage.fixExt(fname)): + + fname = fslimage.addExt(fname, mustExist=exist) + + # TODO broken + if fslimage.looksLikeImage(fname): return 'nii' parser.error('Could not infer format from ' 'filename: {}'.format(args.input)) - if args.input_format is None: args.input_format = getfmt('input', args.input) - if args.output_format is None: args.output_format = getfmt('output', args.output) + if args.input_format is None: + args.input_format = getfmt('input', args.input, True) + if args.output_format is None: + args.output_format = getfmt('output', args.output, False) + + # The source and reference arguments are + # required if the input is a FLIRT matrix + # or a FNIRT displacement/coefficient field. + if args.input_format in ('mat', 'nii') and \ + (args.source is None or args.reference is None): + parser.error('You must specify a source and reference ' + 'when the input is not an X5 file!') return args def flirtToX5(args): + """Convert a linear FLIRT transformation matrix to an X5 transformation + file. + """ src = fslimage.Image(args.source, loadData=False) ref = fslimage.Image(args.reference, loadData=False) - xform = transform.readFlirt(args.input) - xform = transform.fromFlirt(xform, src, ref, 'world', 'world') - transform.writeLinearX5(args.output, xform, src, ref) + xform = flirt.readFlirt(args.input) + xform = flirt.fromFlirt(xform, src, ref, 'world', 'world') + x5.writeLinearX5(args.output, xform, src, ref) def X5ToFlirt(args): """Convert a linear X5 transformation file to a FLIRT matrix. """ - xform, src, ref = transform.readLinearX5(args.input) - xform = transform.toFlirt(xform, src, ref, 'world', 'world') - transform.writeFlirt(xform, args.output) + xform, src, ref = x5.readLinearX5(args.input) + xform = flirt.toFlirt(xform, src, ref, 'world', 'world') + flirt.writeFlirt(xform, args.output) def fnirtToX5(args): @@ -93,21 +130,17 @@ def fnirtToX5(args): """ src = fslimage.Image(args.source, loadData=False) ref = fslimage.Image(args.reference, loadData=False) - field = transform.readFnirt(args.input, - src=src, - ref=ref, - dispType=args.inDispType) - field = transform.fromFnirt(field, 'world', 'world') - transform.writeNonLinearX5(args.output, field) + field = fnirt.readFnirt(args.input, src=src, ref=ref) + x5.writeNonLinearX5(args.output, field) def X5ToFnirt(args): """Convert a non-linear X5 transformation file to a FNIRT-style transformation file. """ - field = transform.readNonLinearX5(args.input) - field = transform.toFnirt(field, 'world', 'world') - transform.writeFnirt(field, args.output) + field = x5.readNonLinearX5(args.input) + field = fnirt.toFnirt(field) + field.save(args.output) def doFlirt(args): diff --git a/fsl/transform/fnirt.py b/fsl/transform/fnirt.py index 30db64fd34e7d82dbc915859025388ff97822628..74589fa0793a079d7ed9917a9af373fc099de31e 100644 --- a/fsl/transform/fnirt.py +++ b/fsl/transform/fnirt.py @@ -247,7 +247,7 @@ def toFnirt(field): field.data, src=field.src, ref=field.ref, - fieldType=field.fieldType, + xform=field.voxToWorldMat, dispType=field.displacementType) # Otherwise we have to adjust the