Commit f335f4b8 authored by Paul McCarthy's avatar Paul McCarthy 🚵
Browse files

Initial work on wrappers package. Very messy and unusable.

parent 5196449a
#!/usr/bin/env python
#
# __init__.py - Wrappers for FSL command-line tools.
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
"""This package contains wrappers for various FSL command line tools, allowing
them to be called from Python.
"""
from .bet import (bet,) # noqa
from .eddy import (eddy_cuda, # noqa
topup)
from .flirt import (flirt, # noqa
invxfm,
applyxfm,
concatxfm,
mcflirt)
from .fnirt import (fnirt, # noqa
applywarp,
invwarp,
convertwarp)
from .fslmaths import (fslmaths,) # noqa
from .fugue import (fugue, # noqa
sigloss)
from .melodic import (melodic, # noqa
fsl_regfilt)
from .misc import (fslreorient2std, # noqa
fslroi,
slicer,
cluster)
#!/usr/bin/env python
#
# bet.py -
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
import fsl.utils.assertions as asrt
import fsl.utils.run as run
from . import wrapperutils as wutils
@wutils.fileOrImage('input', 'output')
def bet(input, output, **kwargs):
"""Delete non-brain tissue from an image of the whole head.
:arg input: Required
:arg output: Required
:arg mask:
:arg robust:
:arg fracintensity:
:arg seg:
Refer to the ``bet`` command-line help for details on all arguments.
"""
asrt.assertIsNifti(input)
argmap = {
'mask' : 'm',
'robust' : 'R',
'fracintensity' : 'f',
'seg' : 'n',
}
valmap = {
'm' : wutils.SHOW_IF_TRUE,
'R' : wutils.SHOW_IF_TRUE,
'n' : wutils.HIDE_IF_TRUE,
}
cmd = ['bet', input, output]
cmd += wutils.applyArgStyle('-', argmap, valmap, **kwargs)
return run.runfsl(*cmd)
#!/usr/bin/env python
#
# eddy.py -
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
def eddy_cuda(imain, mask, index, acqp, bvecs, bvals, out, very_verbose=False,
niter=None, fwhm=None, s2v_niter=None, mporder=None, nvoxhp=None,
slspec=None, b0_only=False, topup=None, field=None,
field_mat=None, debug=None, s2v_fwhm=None, interp=None,
dont_mask_output=False, s2v_interp=None, ref_scan_no=None,
data_is_shelled=False, estimate_move_by_susceptibility=False,
mbs_niter=None, mbs_lambda=None, mbs_ksp=None, s2v_lambda=None,
cnr_maps=False, residuals=False):
"""Correct eddy current-induced distortions and subject movements."""
asrt.assertFileExists(imain, mask, index, acqp, bvecs, bvals)
asrt.assertIsNifti(imain, mask)
assert not (topup and field), "topup and field arguments are incompatible"
out = img.splitext(out)[0]
opts = " --imain={0} --mask={1} --index={2} --bvals={3} " \
"--bvecs={4} --acqp={5} --out={6}".format(imain, mask, index, bvals,
bvecs, acqp, out)
cmd = op.join(os.getenv('DHCP_EDDY_PATH', ''), 'eddy_cuda')
# cmd = 'eddy_cuda'
cmd = cmd + opts
if very_verbose:
cmd += " --very_verbose"
if estimate_move_by_susceptibility:
cmd += " --estimate_move_by_susceptibility"
if data_is_shelled:
cmd += " --data_is_shelled"
if mbs_niter is not None:
cmd += " --mbs_niter={0}".format(mbs_niter)
if mbs_lambda is not None:
cmd += " --mbs_lambda={0}".format(mbs_lambda)
if mbs_ksp is not None:
cmd += " --mbs_ksp={0}".format(mbs_ksp)
if niter is not None:
cmd += " --niter={0}".format(niter)
if fwhm is not None:
cmd += " --fwhm={0}".format(fwhm)
if s2v_fwhm is not None:
cmd += " --s2v_fwhm={0}".format(s2v_fwhm)
if s2v_niter is not None:
cmd += " --s2v_niter={0}".format(s2v_niter)
if s2v_interp is not None:
cmd += " --s2v_interp={0}".format(s2v_interp)
if interp is not None:
cmd += " --interp={0}".format(interp)
if mporder is not None:
cmd += " --mporder={0}".format(mporder)
if nvoxhp is not None:
cmd += " --nvoxhp={0}".format(nvoxhp)
if slspec is not None:
cmd += " --slspec={0}".format(slspec)
if topup is not None:
cmd += " --topup={0}".format(topup)
if field is not None:
field = img.splitext(field)[0]
cmd += " --field={0}".format(field)
if b0_only:
cmd += " --b0_only"
if field_mat is not None:
cmd += " --field_mat={0}".format(field_mat)
if debug is not None:
cmd += " --debug={0}".format(debug)
if dont_mask_output:
cmd += " --dont_mask_output"
if ref_scan_no is not None:
cmd += " --ref_scan_no={0}".format(ref_scan_no)
if s2v_lambda is not None:
cmd += " --s2v_lambda={0}".format(s2v_lambda)
if cnr_maps:
cmd += " --cnr_maps"
if residuals:
cmd += " --residuals"
shops.run(cmd)
def topup(imain, datain, config=None, fout=None, iout=None, out=None,
verbose=False, subsamp=None, logout=None):
"""Estimate and correct susceptibility induced distortions."""
asrt.assertFileExists(imain, datain)
asrt.assertIsNifti(imain)
cmd = "topup --imain={0} --datain={1}".format(imain, datain)
if config is not None:
cmd += " --config={0}".format(config)
if fout is not None:
cmd += " --fout={0}".format(fout)
if iout is not None:
cmd += " --iout={0}".format(iout)
if out is not None:
cmd += " --out={0}".format(out)
if subsamp is not None:
cmd += " --subsamp={0}".format(subsamp)
if logout is not None:
cmd += " --logout={0}".format(logout)
if verbose:
cmd += " -v"
shops.run(cmd)
#!/usr/bin/env python
#
# flirt.py -
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
"""
.. autosummary::
:nosignatures:
flirt
invxfm
applyxfm
concatxfm
mcflirt
"""
import fsl.utils.run as run
import fsl.utils.assertions as asrt
import fsl.data.image as fslimage
def flirt(src, ref, out=None, omat=None, dof=None, cost=None, wmseg=None,
init=None, schedule=None, echospacing=None, pedir=None,
fieldmap=None, fieldmapmask=None, bbrslope=None, bbrtype=None,
interp=None, refweight=None, applyisoxfm=None, usesqform=False,
nosearch=False, verbose=0):
"""FLIRT (FMRIB's Linear Image Registration Tool)."""
asrt.assertIsNifti(src, ref)
asrt.assertFileExists(src, ref)
cmd = "flirt -in {0} -ref {1}".format(src, ref)
if out is not None:
asrt.assertIsNifti(out)
cmd += " -out {0}".format(out)
if omat is not None:
cmd += " -omat {0}".format(omat)
if dof is not None:
cmd += " -dof {0}".format(dof)
if cost is not None:
cmd += " -cost {0}".format(cost)
if wmseg is not None:
asrt.assertIsNifti(wmseg)
cmd += " -wmseg {0}".format(wmseg)
if init is not None:
cmd += " -init {0}".format(init)
if schedule is not None:
cmd += " -schedule {0}".format(schedule)
if echospacing is not None:
cmd += " -echospacing {0}".format(echospacing)
if pedir is not None:
cmd += " -pedir {0}".format(pedir)
if fieldmap is not None:
cmd += " -fieldmap {0}".format(fieldmap)
if fieldmapmask is not None:
cmd += " -fieldmapmask {0}".format(fieldmapmask)
if bbrslope is not None:
cmd += " -bbrslope {0}".format(bbrslope)
if bbrtype is not None:
cmd += " -bbrtype {0}".format(bbrtype)
if interp is not None:
cmd += " -interp {0}".format(interp)
if refweight is not None:
asrt.assertIsNifti(refweight)
cmd += " -refweight {0}".format(refweight)
if applyisoxfm is not None:
cmd += " -applyisoxfm {0}".format(applyisoxfm)
if verbose is not None:
cmd += " -verbose {0}".format(verbose)
if usesqform:
cmd += " -usesqform"
if nosearch:
cmd += " -nosearch"
return run.runfsl(cmd)
def invxfm(inmat, omat):
"""Tool for inverting FSL transformation matrices."""
asrt.assertFileExists(inmat)
cmd = "convert_xfm -omat {0} -inverse {1}".format(omat, inmat)
return run.runfsl(cmd)
def applyxfm(src, ref, mat, out, interp='spline'):
"""Tool for applying FSL transformation matrices."""
asrt.assertFileExists(src, ref)
asrt.assertIsNifti(src, ref)
cmd = "flirt -init {0} -in {1} -ref {2} -applyxfm -out {3} -interp {4}"
return run.runfsl(cmd.format(mat, src, ref, out, interp))
def concatxfm(inmat1, inmat2, outmat):
"""Tool to concatenate two FSL transformation matrices."""
asrt.assertFileExists(inmat1, inmat2)
cmd = "convert_xfm -omat {0} -concat {1} {2}"
return run.runfsl(cmd.format(outmat, inmat2, inmat1))
def mcflirt(infile, outfile, reffile=None, spline_final=True, plots=True,
mats=True, refvol=None):
"""Rigid-body motion correction using mcflirt."""
outfile = fslimage.removeExt(outfile)
cmd = "mcflirt -in {0} -out {1} -rmsrel -rmsabs".format(infile, outfile)
if reffile is not None:
cmd += " -reffile {0}".format(reffile)
if refvol is not None:
cmd += " -refvol {0}".format(refvol)
if spline_final:
cmd += " -spline_final"
if plots:
cmd += " -plots"
if mats:
cmd += " -mats"
return run.runfsl(cmd)
#!/usr/bin/env python
#
# fnirt.py - FNIRT wrapper functions.
#
# Author: Sean Fitzgibbon <sean.fitzgibbon@ndcn.ox.ac.uk>
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
"""This module provides wrapper functions for the FSL `FNIRT
<https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FNIRT/>`_ tool, used for performing
non-linear registration of 3D images.
.. autosummary::
:nosignatures:
fnirt
applywarp
invwarp
convertwarp
"""
import os.path as op
import glob
import fsl.utils.run as run
import fsl.utils.assertions as asrt
def fnirt(src, ref, aff=None, imprefm=None, impinm=None, applyrefmask=None,
applyinmask=None, subsamp=None, miter=None, infwhm=None,
reffwhm=None, lmbda=None, estint=None, warpres=None, ssqlambda=None,
regmod=None, intmod=None, intorder=None, biasres=None,
biaslambda=None, refderiv=None, cout=None, intout=None, refout=None,
iout=None, interp=None, inwarp=None, minmet=None, verbose=False,
intin=None, jout=None):
"""Do nonlinear image registration."""
cmd = 'fnirt --in={0} --ref={1}'.format(src, ref)
if aff is not None:
cmd += " --aff={0}".format(aff)
if imprefm is not None:
cmd += " --imprefm={0}".format(imprefm)
if impinm is not None:
cmd += " --impinm={0}".format(impinm)
if applyrefmask is not None:
cmd += " --applyrefmask={0}".format(applyrefmask)
if applyinmask is not None:
cmd += " --applyinmask={0}".format(applyinmask)
if subsamp is not None:
cmd += " --subsamp={0}".format(subsamp)
if miter is not None:
cmd += " --miter={0}".format(miter)
if infwhm is not None:
cmd += " --infwhm={0}".format(infwhm)
if reffwhm is not None:
cmd += " --reffwhm={0}".format(reffwhm)
if lmbda is not None:
cmd += " --lambda={0}".format(lmbda)
if estint is not None:
cmd += " --estint={0}".format(estint)
if warpres is not None:
cmd += " --warpres={0}".format(warpres)
if ssqlambda is not None:
cmd += " --ssqlambda={0}".format(ssqlambda)
if regmod is not None:
cmd += " --regmod={0}".format(regmod)
if intmod is not None:
cmd += " --intmod={0}".format(intmod)
if intorder is not None:
cmd += " --intorder={0}".format(intorder)
if biasres is not None:
cmd += " --biasres={0}".format(biasres)
if biaslambda is not None:
cmd += " --biaslambda={0}".format(biaslambda)
if refderiv is not None:
cmd += " --refderiv={0}".format(refderiv)
if cout is not None:
cmd += " --cout={0}".format(cout)
if intout is not None:
cmd += " --intout={0}".format(intout)
if refout is not None:
cmd += " --refout={0}".format(refout)
if iout is not None:
cmd += " --iout={0}".format(iout)
if interp is not None:
cmd += " --interp={0}".format(interp)
if inwarp is not None:
cmd += " --inwarp={0}".format(inwarp)
if minmet is not None:
cmd += " --minmet={0}".format(minmet)
if intin is not None:
cmd += " --intin={0}".format(intin)
if jout is not None:
cmd += " --jout={0}".format(jout)
if verbose:
cmd += " --verbose"
return run.runfsl(cmd)
def applywarp(src, ref, out, warp=None, premat=None, prematdir=None,
postmat=None, postmatdir=None, interp="spline",
paddingsize=None, abs=False, rel=False):
"""Tool for applying FSL warps.
The ``prematdir`` and ``postmatdir`` arguments can be used when warping a
4D image. You can specify a directory containing multiple affines, named
``MAT_????`` (as output by e.g. ``mcflirt``). Each file will be applied to
one volume (in order) of the image.
"""
assert (warp or premat or postmat or prematdir or postmatdir), \
"either a warp or mat (premat, postmat or prematdir) must be supplied"
assert not (premat and prematdir), \
"cannot use premat and prematdir arguments together"
assert not (postmat and postmatdir), \
"cannot use postmat and postmatdir arguments together"
def catmats(matdir, out):
"""Concatenate FSL trasformations files into a single file."""
mats = sorted(glob.glob(op.join(matdir, "MAT_????")))
with open(out, 'w') as outfile:
for fname in mats:
with open(fname) as infile:
outfile.write(infile.read())
cmd = "--in={0} --ref={1} --out={2} --interp={3}".format(src, ref, out,
interp)
cmd = "applywarp " + cmd
if prematdir:
premat = op.join(prematdir, 'allmats.txt')
catmats(prematdir, premat)
if postmatdir:
postmat = op.join(postmatdir, 'allmats.txt')
catmats(postmatdir, postmat)
if warp:
cmd += " --warp={0}".format(warp)
if premat:
cmd += " --premat={0}".format(premat)
if postmat:
cmd += " --postmat={0}".format(postmat)
if paddingsize:
cmd += " --paddingsize={0}".format(paddingsize)
if abs:
cmd += " --abs"
if rel:
cmd += " --rel"
return run.runfsl(cmd)
def invwarp(inwarp, ref, outwarp):
"""Tool for inverting FSL warps."""
asrt.assertFileExists(inwarp, ref)
asrt.assertIsNifti(inwarp, ref, outwarp)
cmd = 'invwarp'
cmd += ' --warp={}'.format(inwarp)
cmd += ' --out={}'.format(outwarp)
cmd += ' --ref={}'.format(ref)
return run.runfsl(cmd)
def convertwarp(out, ref, warp1=None, warp2=None, premat=None, midmat=None,
postmat=None, shiftmap=None, shiftdir=None, absout=False,
abs=False, rel=False, relout=False):
"""Tool for converting FSL warps."""
assert (warp1 or warp2 or premat or midmat or postmat), \
"either a warp (warp1 or warp2) or mat (premat, midmat, or " + \
"postmat) must be supplied"
cmd = "convertwarp --ref={0} --out={1}".format(ref, out)
if warp1:
cmd = cmd + " --warp1={0}".format(warp1)
if warp2:
cmd = cmd + " --warp2={0}".format(warp2)
if premat:
cmd = cmd + " --premat={0}".format(premat)
if midmat:
cmd = cmd + " --midmat={0}".format(midmat)
if postmat:
cmd = cmd + " --postmat={0}".format(postmat)
if shiftmap:
cmd = cmd + " --shiftmap={0}".format(shiftmap)
if shiftdir:
cmd = cmd + " --shiftdir={0}".format(shiftdir)
if absout:
cmd = cmd + " --absout"
if relout:
cmd = cmd + " --relout"
if abs:
cmd = cmd + " --abs"
if rel:
cmd = cmd + " --rel"
return run.runfsl(cmd)
#!/usr/bin/env python
#
# fslmaths.py -
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
from fsl.utils.run import runfsl
class fslmaths(object):
"""Perform mathematical manipulation of images."""
def __init__(self, input):
"""Constructor."""
self.inputImage = input
self.outputImage = None
self.operations = []
def abs(self):
"""Absolute value."""
self.operations.append("-abs")
return self
def bin(self):
"""Use (current image>0) to binarise."""
self.operations.append("-bin")
return self
def binv(self):
"""Binarise and invert (binarisation and logical inversion)."""
self.operations.append("-binv")
return self
def recip(self):
"""Reciprocal (1/current image)."""
self.operations.append("-recip")
return self
def Tmean(self):
"""Mean across time."""
self.operations.append("-Tmean")
return self
def Tstd(self):
"""Standard deviation across time."""
self.operations.append("-Tstd")
return self
def Tmin(self):
"""Min across time."""
self.operations.append("-Tmin")
return self
def Tmax(self):
"""Max across time."""
self.operations.append("-Tmax")
return self
def fillh(self):
"""fill holes in a binary mask (holes are internal - i.e. do not touch
the edge of the FOV)."""
self.operations.append("-fillh")
return self
def ero(self, repeat=1):
"""Erode by zeroing non-zero voxels when zero voxels in kernel."""
for i in range(repeat):
self.operations.append("-ero")
return self
def dilM(self, repeat=1):
"""Mean Dilation of non-zero voxels."""
for i in range(repeat):
self.operations.append("-dilM")
return self
def dilF(self, repeat=1):
"""Maximum filtering of all voxels."""
for i in range(repeat):
self.operations.append("-dilF")
return self
def add(self, input):
"""Add input to current image."""
self.operations.append("-add {0}".format(input))
return self
def sub(self, input):
"""Subtract input from current image."""
self.operations.append("-sub {0}".format(input))
return self