Skip to content
Snippets Groups Projects
Commit 55d57e02 authored by Martin Craig's avatar Martin Craig
Browse files

Merge branch 'msc' of https://git.fmrib.ox.ac.uk/paulmc/fslpy into msc

parents 0384e0b4 b1a428d7
No related branches found
No related tags found
No related merge requests found
...@@ -166,8 +166,8 @@ def run(*args, **kwargs): ...@@ -166,8 +166,8 @@ def run(*args, **kwargs):
- stderr: Optional file-like object to which the command's - stderr: Optional file-like object to which the command's
standard error stream can be forwarded. standard error stream can be forwarded.
- cmd: If ``True``, the command itself is logged to the - cmd: Optional file-like object to which the command itself
standard output stream(s). is logged.
:returns: If ``submit`` is provided, the return value of :returns: If ``submit`` is provided, the return value of
:func:`.fslsub` is returned. Otherwise returns a single :func:`.fslsub` is returned. Otherwise returns a single
...@@ -194,7 +194,7 @@ def run(*args, **kwargs): ...@@ -194,7 +194,7 @@ def run(*args, **kwargs):
tee = log .get('tee', False) tee = log .get('tee', False)
logStdout = log .get('stdout', None) logStdout = log .get('stdout', None)
logStderr = log .get('stderr', None) logStderr = log .get('stderr', None)
logCmd = log .get('cmd', False) logCmd = log .get('cmd', None)
args = _prepareArgs(args) args = _prepareArgs(args)
if not bool(submit): if not bool(submit):
...@@ -272,8 +272,8 @@ def _realrun(tee, logStdout, logStderr, logCmd, *args): ...@@ -272,8 +272,8 @@ def _realrun(tee, logStdout, logStderr, logCmd, *args):
:arg logStderr: Optional file-like object to which the command's standard :arg logStderr: Optional file-like object to which the command's standard
error stream can be forwarded. error stream can be forwarded.
:arg logCmd: If ``True``, the command itself is logged to the standard :arg logCmd: Optional file-like object to which the command itself is
output stream(s). logged.
:arg args: Command to run :arg args: Command to run
...@@ -308,15 +308,13 @@ def _realrun(tee, logStdout, logStderr, logCmd, *args): ...@@ -308,15 +308,13 @@ def _realrun(tee, logStdout, logStderr, logCmd, *args):
if logStdout is not None: outstreams.append(logStdout) if logStdout is not None: outstreams.append(logStdout)
if logStderr is not None: errstreams.append(logStderr) if logStderr is not None: errstreams.append(logStderr)
# log the command to # log the command if requested
# stdout if requested if logCmd is not None:
if logCmd:
cmd = ' '.join(args) + '\n' cmd = ' '.join(args) + '\n'
for o in outstreams: if 'b' in getattr(logCmd, 'mode', 'w'):
if 'b' in getattr(o, 'mode', 'w'): logCmd.write(cmd.encode('utf-8'))
o.write(cmd.encode('utf-8')) else:
else: logCmd.write(cmd)
o.write(cmd)
stdoutt = _forwardStream(proc.stdout, *outstreams) stdoutt = _forwardStream(proc.stdout, *outstreams)
stderrt = _forwardStream(proc.stderr, *errstreams) stderrt = _forwardStream(proc.stderr, *errstreams)
...@@ -340,23 +338,35 @@ def _realrun(tee, logStdout, logStderr, logCmd, *args): ...@@ -340,23 +338,35 @@ def _realrun(tee, logStdout, logStderr, logCmd, *args):
def runfsl(*args, **kwargs): def runfsl(*args, **kwargs):
"""Call a FSL command and return its output. This function simply prepends """Call a FSL command and return its output.
``$FSLDIR/bin/`` to the command before passing it to :func:`run`.
This function searches for the command in the following
locations (ordered by priority):
1. ``FSL_PREFIX``
2. ``$FSLDEVDIR/bin``
3. ``$FSLDIR/bin``
If found, the full path to the command is then passed to :func:`run`.
""" """
prefixes = []
prefix = None
if FSL_PREFIX is not None: if FSL_PREFIX is not None:
prefix = FSL_PREFIX prefixes.append(FSL_PREFIX)
elif fslplatform.fsldevdir is not None: if fslplatform.fsldevdir is not None:
prefix = op.join(fslplatform.fsldevdir, 'bin') prefixes.append(op.join(fslplatform.fsldevdir, 'bin'))
elif fslplatform.fsldir is not None: if fslplatform.fsldir is not None:
prefix = op.join(fslplatform.fsldir, 'bin') prefixes.append(op.join(fslplatform.fsldir, 'bin'))
else:
if not prefixes:
raise FSLNotPresent('$FSLDIR is not set - FSL cannot be found!') raise FSLNotPresent('$FSLDIR is not set - FSL cannot be found!')
args = _prepareArgs(args) args = _prepareArgs(args)
args[0] = op.join(prefix, args[0]) for prefix in prefixes:
cmdpath = op.join(prefix, args[0])
if op.isfile(cmdpath):
args[0] = cmdpath
break
return run(*args, **kwargs) return run(*args, **kwargs)
......
...@@ -80,8 +80,10 @@ from .wrapperutils import (LOAD,) # noqa ...@@ -80,8 +80,10 @@ from .wrapperutils import (LOAD,) # noqa
from .bet import (bet, # noqa from .bet import (bet, # noqa
robustfov) robustfov)
from .eddy import (eddy_cuda, # noqa from .eddy import (eddy_cuda, # noqa
topup) topup,
applytopup)
from .fast import (fast,) # noqa from .fast import (fast,) # noqa
from .fsl_anat import (fsl_anat,) # noqa
from .flirt import (flirt, # noqa from .flirt import (flirt, # noqa
invxfm, invxfm,
applyxfm, applyxfm,
......
...@@ -35,6 +35,7 @@ def bet(input, output, **kwargs): ...@@ -35,6 +35,7 @@ def bet(input, output, **kwargs):
'robust' : 'R', 'robust' : 'R',
'fracintensity' : 'f', 'fracintensity' : 'f',
'seg' : 'n', 'seg' : 'n',
'centre' : 'c',
} }
valmap = { valmap = {
...@@ -55,6 +56,14 @@ def bet(input, output, **kwargs): ...@@ -55,6 +56,14 @@ def bet(input, output, **kwargs):
} }
cmd = ['bet', input, output] cmd = ['bet', input, output]
# The 'centre' argument requires three co-ordinates and can't be passed
# as a single value, so needs to be handled separately. Assume it is
# passed as a Python sequence
centre = kwargs.pop("c", None)
if centre is not None:
cmd += ['c', ] + list(centre)
cmd += wutils.applyArgStyle('-', argmap=argmap, valmap=valmap, **kwargs) cmd += wutils.applyArgStyle('-', argmap=argmap, valmap=valmap, **kwargs)
return cmd return cmd
......
...@@ -61,8 +61,8 @@ def eddy_cuda(imain, mask, index, acqp, bvecs, bvals, out, **kwargs): ...@@ -61,8 +61,8 @@ def eddy_cuda(imain, mask, index, acqp, bvecs, bvals, out, **kwargs):
return cmd return cmd
@wutils.fileOrImage('imain', 'fout', 'iout') @wutils.fileOrImage('imain', 'fout', 'iout', outprefix='out')
@wutils.fileOrArray('datain') @wutils.fileOrArray('datain', outprefix='out')
@wutils.fslwrapper @wutils.fslwrapper
def topup(imain, datain, **kwargs): def topup(imain, datain, **kwargs):
"""Wrapper for the ``topup`` command.""" """Wrapper for the ``topup`` command."""
...@@ -78,3 +78,25 @@ def topup(imain, datain, **kwargs): ...@@ -78,3 +78,25 @@ def topup(imain, datain, **kwargs):
cmd += wutils.applyArgStyle('--=', valmap=valmap, **kwargs) cmd += wutils.applyArgStyle('--=', valmap=valmap, **kwargs)
return cmd return cmd
@wutils.fileOrImage('imain', 'out')
@wutils.fileOrArray('datain')
@wutils.fslwrapper
def applytopup(imain, datain, index, **kwargs):
"""Wrapper for the ``applytopup`` command."""
valmap = {
'verbose' : wutils.SHOW_IF_TRUE
}
asrt.assertFileExists(datain)
asrt.assertIsNifti(imain)
cmd = [
'applytopup', '--imain={}'.format(imain),
'--inindex={}'.format(index),
'--datain={}'.format(datain),
]
cmd += wutils.applyArgStyle('--=', valmap=valmap, **kwargs)
return cmd
...@@ -33,12 +33,19 @@ def fast(imgs, out='fast', **kwargs): ...@@ -33,12 +33,19 @@ def fast(imgs, out='fast', **kwargs):
asrt.assertIsNifti(*imgs) asrt.assertIsNifti(*imgs)
valmap = {
'nobias' : wutils.SHOW_IF_TRUE,
'verbose' : wutils.SHOW_IF_TRUE,
'Prior' : wutils.SHOW_IF_TRUE,
'segments' : wutils.SHOW_IF_TRUE,
}
argmap = { argmap = {
'n_classes' : 'class', 'n_classes' : 'class',
} }
cmd = ['fast', '-v', '--out=%s' % out] cmd = ['fast', '-v', '--out=%s' % out]
cmd += wutils.applyArgStyle('--=', argmap=argmap, **kwargs) cmd += wutils.applyArgStyle('--=', valmap=valmap, argmap=argmap, singlechar_args=True, **kwargs)
cmd += imgs cmd += imgs
return cmd return cmd
...@@ -59,14 +59,15 @@ def flirt(src, ref, **kwargs): ...@@ -59,14 +59,15 @@ def flirt(src, ref, **kwargs):
return cmd return cmd
def applyxfm(src, ref, mat, out, interp='spline'): def applyxfm(src, ref, mat, out, interp='spline', **kwargs):
"""Convenience function which runs ``flirt -applyxfm ...``.""" """Convenience function which runs ``flirt -applyxfm ...``."""
return flirt(src, return flirt(src,
ref, ref,
out=out, out=out,
applyxfm=True, applyxfm=True,
init=mat, init=mat,
interp=interp) interp=interp,
**kwargs)
@wutils.fileOrArray() @wutils.fileOrArray()
......
...@@ -27,12 +27,12 @@ from . import wrapperutils as wutils ...@@ -27,12 +27,12 @@ from . import wrapperutils as wutils
'refout', 'refmask', 'inmask') 'refout', 'refmask', 'inmask')
@wutils.fileOrArray('aff') @wutils.fileOrArray('aff')
@wutils.fslwrapper @wutils.fslwrapper
def fnirt(src, ref, **kwargs): def fnirt(src, **kwargs):
"""Wrapper for the ``fnirt`` command.""" """Wrapper for the ``fnirt`` command."""
asrt.assertIsNifti(src, ref) asrt.assertIsNifti(src)
cmd = ['fnirt', '--in={}'.format(src), '--ref={}'.format(ref)] cmd = ['fnirt', '--in={}'.format(src)]
cmd += wutils.applyArgStyle('--=', **kwargs) cmd += wutils.applyArgStyle('--=', **kwargs)
return cmd return cmd
...@@ -41,7 +41,7 @@ def fnirt(src, ref, **kwargs): ...@@ -41,7 +41,7 @@ def fnirt(src, ref, **kwargs):
@wutils.fileOrImage('src', 'ref', 'out', 'warp', 'mask') @wutils.fileOrImage('src', 'ref', 'out', 'warp', 'mask')
@wutils.fileOrArray('premat', 'postmat') @wutils.fileOrArray('premat', 'postmat')
@wutils.fslwrapper @wutils.fslwrapper
def applywarp(src, ref, out, warp, **kwargs): def applywarp(src, ref, out, **kwargs):
"""Wrapper for the ``applywarp`` command. """ """Wrapper for the ``applywarp`` command. """
valmap = { valmap = {
...@@ -55,8 +55,7 @@ def applywarp(src, ref, out, warp, **kwargs): ...@@ -55,8 +55,7 @@ def applywarp(src, ref, out, warp, **kwargs):
cmd = ['applywarp', cmd = ['applywarp',
'--in={}'.format(src), '--in={}'.format(src),
'--ref={}'.format(ref), '--ref={}'.format(ref),
'--out={}'.format(out), '--out={}'.format(out)]
'--warp={}'.format(warp)]
cmd += wutils.applyArgStyle('--=', valmap=valmap, **kwargs) cmd += wutils.applyArgStyle('--=', valmap=valmap, **kwargs)
...@@ -76,7 +75,7 @@ def invwarp(warp, ref, out, **kwargs): ...@@ -76,7 +75,7 @@ def invwarp(warp, ref, out, **kwargs):
'verbose' : wutils.SHOW_IF_TRUE, 'verbose' : wutils.SHOW_IF_TRUE,
} }
asrt.assertIsNifti(warp, ref, out) asrt.assertIsNifti(warp, ref)
cmd = ['invwarp', cmd = ['invwarp',
'--warp={}'.format(warp), '--warp={}'.format(warp),
...@@ -88,7 +87,7 @@ def invwarp(warp, ref, out, **kwargs): ...@@ -88,7 +87,7 @@ def invwarp(warp, ref, out, **kwargs):
return cmd return cmd
@wutils.fileOrImage('out', 'ref', 'warp1', 'warp2', 'shiftmap') @wutils.fileOrImage('out', 'ref', 'warp1', 'warp2', 'shiftmap', 'jacobian')
@wutils.fileOrArray('premat', 'midmat', 'postmat') @wutils.fileOrArray('premat', 'midmat', 'postmat')
@wutils.fslwrapper @wutils.fslwrapper
def convertwarp(out, ref, **kwargs): def convertwarp(out, ref, **kwargs):
...@@ -99,7 +98,6 @@ def convertwarp(out, ref, **kwargs): ...@@ -99,7 +98,6 @@ def convertwarp(out, ref, **kwargs):
'rel' : wutils.SHOW_IF_TRUE, 'rel' : wutils.SHOW_IF_TRUE,
'absout' : wutils.SHOW_IF_TRUE, 'absout' : wutils.SHOW_IF_TRUE,
'relout' : wutils.SHOW_IF_TRUE, 'relout' : wutils.SHOW_IF_TRUE,
'jacobian' : wutils.SHOW_IF_TRUE,
'jstats' : wutils.SHOW_IF_TRUE, 'jstats' : wutils.SHOW_IF_TRUE,
'constrainj' : wutils.SHOW_IF_TRUE, 'constrainj' : wutils.SHOW_IF_TRUE,
'verbose' : wutils.SHOW_IF_TRUE, 'verbose' : wutils.SHOW_IF_TRUE,
...@@ -107,5 +105,4 @@ def convertwarp(out, ref, **kwargs): ...@@ -107,5 +105,4 @@ def convertwarp(out, ref, **kwargs):
cmd = ['convertwarp', '--ref={}'.format(ref), '--out={}'.format(out)] cmd = ['convertwarp', '--ref={}'.format(ref), '--out={}'.format(out)]
cmd += wutils.applyArgStyle('--=', valmap=valmap, **kwargs) cmd += wutils.applyArgStyle('--=', valmap=valmap, **kwargs)
return cmd return cmd
#!/usr/bin/env python
#
# fsl_anat.py - Wrapper for the FSL_ANAT command.
#
# Author: Martin Craig <martin.craig@eng.ox.ac.uk>
#
"""This module provides the :func:`fsl_anat` function, a wrapper for the FSL
`FSL_ANAT <https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/fsl_anat>`_ command.
"""
import six
import fsl.utils.assertions as asrt
from . import wrapperutils as wutils
@wutils.fileOrImage('img', outprefix='out')
@wutils.fslwrapper
def fsl_anat(img, out='fsl_anat', **kwargs):
"""Wrapper for the ``fsl_anat`` command.
:arg img: Input structural image
:arg out: Output directory name
"""
asrt.assertIsNifti(img)
valmap = {
'strongbias' : wutils.SHOW_IF_TRUE,
'weakbias' : wutils.SHOW_IF_TRUE,
'noreorient' : wutils.SHOW_IF_TRUE,
'nocrop' : wutils.SHOW_IF_TRUE,
'nobias' : wutils.SHOW_IF_TRUE,
'noreg' : wutils.SHOW_IF_TRUE,
'nononlinreg' : wutils.SHOW_IF_TRUE,
'noseg' : wutils.SHOW_IF_TRUE,
'nosubcortseg' : wutils.SHOW_IF_TRUE,
'nosearch' : wutils.SHOW_IF_TRUE,
'nocleanup' : wutils.SHOW_IF_TRUE,
}
argmap = {
}
img_type = kwargs.pop("img_type", "T1")
cmd = ['fsl_anat', '-i', img, '-o', out, '-t', img_type]
smoothing = kwargs.pop("bias_smoothing", None)
if smoothing is not None:
cmd += ['-s', str(smoothing)]
cmd += wutils.applyArgStyle('--=', valmap=valmap, argmap=argmap, singlechar_args=True, **kwargs)
return cmd
...@@ -152,11 +152,13 @@ def cmdwrapper(func): ...@@ -152,11 +152,13 @@ def cmdwrapper(func):
:func:`fsl.utils.run.run` function in a standardised manner. :func:`fsl.utils.run.run` function in a standardised manner.
""" """
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
stdout = kwargs.pop('stdout', True)
stderr = kwargs.pop('stderr', False)
exitcode = kwargs.pop('exitcode', False)
submit = kwargs.pop('submit', None) submit = kwargs.pop('submit', None)
stderr = kwargs.pop('stderr', True)
log = kwargs.pop('log', {'tee' : True}) log = kwargs.pop('log', {'tee' : True})
cmd = func(*args, **kwargs) cmd = func(*args, **kwargs)
return run.run(cmd, stderr=stderr, log=log, submit=submit) return run.run(cmd, stderr=stderr, log=log, submit=submit, stdout=stdout, exitcode=exitcode)
return _update_wrapper(wrapper, func) return _update_wrapper(wrapper, func)
...@@ -166,11 +168,13 @@ def fslwrapper(func): ...@@ -166,11 +168,13 @@ def fslwrapper(func):
:func:`fsl.utils.run.runfsl` function in a standardised manner. :func:`fsl.utils.run.runfsl` function in a standardised manner.
""" """
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
stdout = kwargs.pop('stdout', True)
stderr = kwargs.pop('stderr', False)
exitcode = kwargs.pop('exitcode', False)
submit = kwargs.pop('submit', None) submit = kwargs.pop('submit', None)
stderr = kwargs.pop('stderr', True)
log = kwargs.pop('log', {'tee' : True}) log = kwargs.pop('log', {'tee' : True})
cmd = func(*args, **kwargs) cmd = func(*args, **kwargs)
return run.runfsl(cmd, stderr=stderr, log=log, submit=submit) return run.runfsl(cmd, stderr=stderr, log=log, submit=submit, stdout=stdout, exitcode=exitcode)
return _update_wrapper(wrapper, func) return _update_wrapper(wrapper, func)
...@@ -192,7 +196,7 @@ generated command line arguments. ...@@ -192,7 +196,7 @@ generated command line arguments.
""" """
def applyArgStyle(style, valsep=None, argmap=None, valmap=None, **kwargs): def applyArgStyle(style, valsep=None, argmap=None, valmap=None, singlechar_args=False, **kwargs):
"""Turns the given ``kwargs`` into command line options. This function """Turns the given ``kwargs`` into command line options. This function
is intended to be used to automatically generate command line options is intended to be used to automatically generate command line options
from arguments passed into a Python function. from arguments passed into a Python function.
...@@ -251,6 +255,9 @@ def applyArgStyle(style, valsep=None, argmap=None, valmap=None, **kwargs): ...@@ -251,6 +255,9 @@ def applyArgStyle(style, valsep=None, argmap=None, valmap=None, **kwargs):
The argument for any options not specified in the ``valmap`` The argument for any options not specified in the ``valmap``
will be converted into strings. will be converted into strings.
:arg singlechar_args: If True, single character arguments always take a single
hyphen prefix (e.g. -h) regardless of the style
:arg kwargs: Arguments to be converted into command-line options. :arg kwargs: Arguments to be converted into command-line options.
:returns: A list containing the generated command-line options. :returns: A list containing the generated command-line options.
...@@ -276,7 +283,7 @@ def applyArgStyle(style, valsep=None, argmap=None, valmap=None, **kwargs): ...@@ -276,7 +283,7 @@ def applyArgStyle(style, valsep=None, argmap=None, valmap=None, **kwargs):
if valmap is None: valmap = {} if valmap is None: valmap = {}
def fmtarg(arg): def fmtarg(arg):
if style in ('-', '-='): arg = '-{}'.format(arg) if style in ('-', '-=') or (singlechar_args and len(arg) == 1): arg = '-{}'.format(arg)
elif style in ('--', '--='): arg = '--{}'.format(arg) elif style in ('--', '--='): arg = '--{}'.format(arg)
return arg return arg
...@@ -303,11 +310,12 @@ def applyArgStyle(style, valsep=None, argmap=None, valmap=None, **kwargs): ...@@ -303,11 +310,12 @@ def applyArgStyle(style, valsep=None, argmap=None, valmap=None, **kwargs):
for k, v in kwargs.items(): for k, v in kwargs.items():
if v is None: continue
k = argmap.get(k, k) k = argmap.get(k, k)
mapv = valmap.get(k, fmtval(v)) mapv = valmap.get(k, fmtval(v))
k = fmtarg(k) k = fmtarg(k)
if mapv in (SHOW_IF_TRUE, HIDE_IF_TRUE): if mapv in (SHOW_IF_TRUE, HIDE_IF_TRUE):
if (mapv is SHOW_IF_TRUE and v) or \ if (mapv is SHOW_IF_TRUE and v) or \
(mapv is HIDE_IF_TRUE and not v): (mapv is HIDE_IF_TRUE and not v):
...@@ -849,7 +857,6 @@ class _FileOrThing(object): ...@@ -849,7 +857,6 @@ class _FileOrThing(object):
for prefixed in it.chain(*allPrefixed): for prefixed in it.chain(*allPrefixed):
fullpath = prefixed fullpath = prefixed
prefixed = op.relpath(prefixed, workdir) prefixed = op.relpath(prefixed, workdir)
for prefPat, prefName in prefixes.items(): for prefPat, prefName in prefixes.items():
if not fnmatch.fnmatch(prefixed, '{}*'.format(prefPat)): if not fnmatch.fnmatch(prefixed, '{}*'.format(prefPat)):
continue continue
...@@ -862,10 +869,17 @@ class _FileOrThing(object): ...@@ -862,10 +869,17 @@ class _FileOrThing(object):
# not of the correct type. # not of the correct type.
fval = self.__load(fullpath) fval = self.__load(fullpath)
if fval is not None: if fval is not None:
prefixed = self.__removeExt(prefixed) noext = self.__removeExt(prefixed)
prefPat = prefPat.replace('\\', '\\\\') prefPat = prefPat.replace('\\', '\\\\')
prefixed = re.sub('^' + prefPat, prefName, prefixed) noext = re.sub('^' + prefPat, prefName, noext)
result[prefixed] = fval # If there is already an item in result with the
# name (stripped of prefix), then instead store
# the result with the full prefixed name
if noext not in result:
result[noext] = fval
else:
withext = re.sub('^' + prefPat, prefName, prefixed)
result[withext] = fval
break break
return result return result
...@@ -887,8 +901,11 @@ def fileOrImage(*args, **kwargs): ...@@ -887,8 +901,11 @@ def fileOrImage(*args, **kwargs):
infile = None infile = None
if isinstance(val, (fslimage.Image, nib.nifti1.Nifti1Image)): if isinstance(val, fslimage.Image):
intypes.append(type(val)) intypes.append(fslimage.Image)
elif isinstance(val, nib.nifti1.Nifti1Image):
intypes.append(nib.nifti1.Nifti1Image)
if isinstance(val, fslimage.Image): if isinstance(val, fslimage.Image):
val = val.nibImage val = val.nibImage
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment