Skip to content
Snippets Groups Projects
Commit e4d80361 authored by Paul McCarthy's avatar Paul McCarthy :mountain_bicyclist:
Browse files

MNT: Add all options to fslmaths, and minor clean-up

parent e2a116d9
No related branches found
No related tags found
No related merge requests found
...@@ -44,185 +44,436 @@ class fslmaths: ...@@ -44,185 +44,436 @@ class fslmaths:
if dt is not None: if dt is not None:
self.__args.extend(('-dt', dt)) self.__args.extend(('-dt', dt))
def abs(self): def addargs(func):
"""Absolute value.""" """Decorator used by fslmaths methods. Allows them to just return
self.__args.append("-abs") a list of arguments to add to the command invocation.
return self """
def wrapper(self, *args, **kwargs):
args = func(self, *args, **kwargs)
self.__args.extend(args)
return self
return wrapper
def bin(self): # Binary operations
"""Use (current image>0) to binarise."""
self.__args.append("-bin")
return self
def binv(self): @addargs
"""Binarise and invert (binarisation and logical inversion).""" def add(self, image):
self.__args.append("-binv") """Add input to current image."""
return self return ['-add', image]
@addargs
def sub(self, image):
"""Subtract image from current image."""
return ["-sub", image]
@addargs
def mul(self, image):
"""Multiply current image by image."""
return ["-mul", image]
@addargs
def div(self, image):
"""Divide current image by image."""
return ["-div", image]
@addargs
def rem(self, image):
"""Divide current image by following image and take remainder."""
return ["-rem", image]
@addargs
def mas(self, image):
"""Use image (>0) to mask current image."""
return ["-mas", image]
@addargs
def thr(self, image):
"""threshold below the following number (zero anything below the
number)"""
return ["-thr", image]
@addargs
def thrp(self, perc):
"""threshold below the following percentage (0-100) of ROBUST RANGE"""
return ["-thrp", perc]
@addargs
def thrP(self, perc):
"""threshold below the following percentage (0-100) of the positive
voxels' ROBUST RANGE"""
return ["-thrP", perc]
@addargs
def uthr(self, image):
"""use image number to upper-threshold current image (zero
anything above the number)."""
return ["-uthr", image]
@addargs
def uthrp(self, perc):
"""upper-threshold above the following percentage (0-100) of the
ROBUST RANGE"""
return ["-uthrp", perc]
@addargs
def uthrP(self, perc):
"""upper-threshold above the following percentage (0-100) of the
positive voxels' ROBUST RANGE"""
return ["-uthrP", perc]
@addargs
def max(self, image):
"""take maximum of following input and current image."""
return ["-max", image]
@addargs
def min(self, image):
"""take minimum of following input and current image."""
return ["-min", image]
@addargs
def seed(self, seed):
"""seed random number generator with following number"""
return ['-seed', seed]
@addargs
def restart(self, image):
"""replace the current image with input for future processing
operations"""
return ['-restart', image]
@addargs
def save(self, filename):
"""save the current working image to the input filename"""
return ['-save', filename]
# Basic unary operations
@addargs
def exp(self):
"""exponential"""
return ["-exp"]
@addargs
def log(self):
"""Natural logarithm."""
return ["-log"]
@addargs
def sin(self):
"""sine function"""
return ["-sin"]
@addargs
def cos(self):
"""cosine function"""
return ["-cos"]
@addargs
def tan(self):
"""tangent function"""
return ["-tan"]
@addargs
def asin(self):
"""arc sine function"""
return ["-asin"]
@addargs
def acos(self):
"""arc cosine function"""
return ["-acos"]
@addargs
def atan(self):
"""arc tangent function"""
return ["-atan"]
@addargs
def sqr(self): def sqr(self):
"""Square.""" """Square."""
self.__args.append("-sqr") return ["-sqr"]
return self
@addargs
def sqrt(self): def sqrt(self):
"""Square root.""" """Square root."""
self.__args.append("-sqrt") return ["-sqrt"]
return self
def log(self):
"""Natural logarithm."""
self.__args.append("-log")
return self
@addargs
def recip(self): def recip(self):
"""Reciprocal (1/current image).""" """Reciprocal (1/current image)."""
self.__args.append("-recip") return ["-recip"]
return self
def range(self):
"""Set the output calmin/max to full data range."""
self.__args.append("-range")
return self
def Tmean(self):
"""Mean across time."""
self.__args.append("-Tmean")
return self
def Tstd(self): @addargs
"""Standard deviation across time.""" def abs(self):
self.__args.append("-Tstd") """Absolute value."""
return self return ["-abs"]
def Tmin(self): @addargs
"""Min across time.""" def bin(self):
self.__args.append("-Tmin") """Use (current image>0) to binarise."""
return self return ["-bin"]
def Tmax(self): @addargs
"""Max across time.""" def binv(self):
self.__args.append("-Tmax") """Binarise and invert (binarisation and logical inversion)."""
return self return ["-binv"]
@addargs
def fillh(self): def fillh(self):
"""fill holes in a binary mask (holes are internal - i.e. do not touch """fill holes in a binary mask (holes are internal - i.e. do not touch
the edge of the FOV).""" the edge of the FOV)."""
self.__args.append("-fillh") return ["-fillh"]
return self
@addargs
def fillh26(self):
"""fill holes using 26 connectivity"""
return ["-fillh26"]
@addargs
def index(self):
"""replace each nonzero voxel with a unique (subject to wrapping) index
number"""
return ["-index"]
@addargs
def grid(self, value, spacing):
"""add a 3D grid of intensity <value> with grid spacing <spacing>"""
return ['-grid', value, spacing]
@addargs
def edge(self):
"""edge strength"""
return ["-edge"]
@addargs
def dog_edge(self, sigma1, sigma2):
"""difference of gaussians edge filter. Typical sigma1 is 1.0 and
sigma2 is 1.6
"""
return ['-dog_edge', sigma1, sigma2]
def ero(self, repeat=1): @addargs
"""Erode by zeroing non-zero voxels when zero voxels in kernel.""" def tfce(self, h, e, connectivity):
for i in range(repeat): """enhance with TFCE, e.g. -tfce 2 0.5 6 (maybe change 6 to 26 for
self.__args.append("-ero") skeletons)
return self """
return ['-tfce', h, e, connectivity]
@addargs
def tfceS(self, h, e, connectivity, x, y, z, tfce_thresh):
"""show support area for voxel (X,Y,Z)"""
return ['-tfceS', h, e, connectivity, x, y, z, tfce_thresh]
@addargs
def nan(self):
"""replace NaNs (improper numbers) with 0"""
return ["-nan"]
@addargs
def nanm(self):
"""make NaN (improper number) mask with 1 for NaN voxels, 0 otherwise"""
return ["-nanm"]
@addargs
def rand(self):
"""add uniform noise (range 0:1)"""
return ["-rand"]
@addargs
def randn(self):
"""add Gaussian noise (mean=0 sigma=1)"""
return ["-randn"]
@addargs
def inm(self, image):
"""Intensity normalisation (per 3D volume mean)"""
return ["-inm", image]
@addargs
def ing(self, image):
"""intensity normalisation, global 4D mean)"""
return ["-ing", image]
@addargs
def range(self):
"""Set the output calmin/max to full data range."""
return ["-range"]
# Matrix operations
@addargs
def tensor_decomp(self):
"""convert a 4D (6-timepoint )tensor image into L1,2,3,FA,MD,MO,V1,2,3
(remaining image in pipeline is FA)
"""
return ["-tensor_decomp"]
@addargs
def kernel(self, *args):
"""Perform a kernel operation"""
return ["-kernel"] + list(args)
# Spatial filtering
@addargs
def dilM(self, repeat=1): def dilM(self, repeat=1):
"""Mean Dilation of non-zero voxels.""" """Mean Dilation of non-zero voxels."""
for i in range(repeat): return ['-dilM'] * repeat
self.__args.append("-dilM")
return self
@addargs
def dilD(self, repeat=1): def dilD(self, repeat=1):
"""Modal Dilation of non-zero voxels.""" """Modal Dilation of non-zero voxels."""
for i in range(repeat): return ["-dilD"] * repeat
self.__args.append("-dilD")
return self
@addargs
def dilF(self, repeat=1): def dilF(self, repeat=1):
"""Maximum filtering of all voxels.""" """Maximum filtering of all voxels."""
for i in range(repeat): return ["-dilF"] * repeat
self.__args.append("-dilF")
return self
def smooth(self, sigma):
"""Spatial smoothing - mean filtering using a gauss kernel of sigma mm"""
self.__args.extend(("-s", sigma))
return self
def add(self, image):
"""Add input to current image."""
self.__args.extend(("-add", image))
return self
def sub(self, image): @addargs
"""Subtract image from current image.""" def dilall(self):
self.__args.extend(("-sub", image)) """Apply -dilM repeatedly until the entire FOV is covered"""
return self return ["-dilall"]
def mul(self, image): @addargs
"""Multiply current image by image.""" def ero(self, repeat=1):
self.__args.extend(("-mul", image)) """Erode by zeroing non-zero voxels when zero voxels in kernel."""
return self return ["-ero"] * repeat
def div(self, image): @addargs
"""Divide current image by image.""" def eroF(self, repeat=1):
self.__args.extend(("-div", image)) """Minimum filtering of all voxels"""
return self return ["-eroF"] * repeat
def mas(self, image): @addargs
"""Use image (>0) to mask current image.""" def fmedian(self):
self.__args.extend(("-mas", image)) """Median filtering"""
return self return ["-fmedian"]
def rem(self, image): @addargs
"""Divide current image by following image and take remainder.""" def fmean(self):
self.__args.extend(("-rem", image)) """Mean filtering, kernel weighted, (conventionally used with gauss kernel)"""
return self return ["-fmean"]
def thr(self, image): @addargs
"""use image number to threshold current image (zero < image).""" def fmeanu(self):
self.__args.extend(("-thr", image)) """Mean filtering, kernel weighted, un-normalised (gives edge effects)"""
return self return ["-fmeanu"]
def uthr(self, image): @addargs
"""use image number to upper-threshold current image (zero def s(self, sigma):
anything above the number).""" """Create a gauss kernel of sigma mm and perform mean filtering"""
self.__args.extend(("-uthr", image)) return ["-s", sigma]
return self
def max(self, image): # alias for -s
"""take maximum of following input and current image.""" smooth = s
self.__args.extend(("-max", image))
return self
def min(self, image): @addargs
"""take minimum of following input and current image.""" def subsamp2(self):
self.__args.extend(("-min", image)) """downsamples image by a factor of 2 (keeping new voxels centred on
return self old)"""
return ["-subsamp2"]
def inm(self, image): @addargs
"""Intensity normalisation (per 3D volume mean)""" def subsamp2offc(self):
self.__args.extend(("-inm", image)) """downsamples image by a factor of 2 (non-centred)"""
return self return ["-subsamp2offc"]
def bptf(self, hp_sigma, lp_sigma): # Dimensionality reduction operations
"""Bandpass temporal filtering; nonlinear highpass and Gaussian linear
lowpass (with sigmas in volumes, not seconds); set either sigma<0 to
skip that filter."""
self.__args.extend(("-bptf", hp_sigma, lp_sigma))
return self
def kernel(self, *args): @addargs
"""Perform a kernel operation""" def Tmean(self):
self.__args.extend(["-kernel"] + list(args)) """Mean across time."""
return self return ["-Tmean"]
def fmedian(self): @addargs
"""Median filtering""" def Tstd(self):
self.__args.append("-fmedian") """Standard deviation across time."""
return self return ["-Tstd"]
def fmeanu(self): @addargs
"""Mean filtering, kernel weighted, un-normalised (gives edge effects)""" def Tmin(self):
self.__args.append("-fmeanu") """Min across time."""
return self return ["-Tmin"]
@addargs
def Tmax(self):
"""Max across time."""
return ["-Tmax"]
@addargs
def Tmaxn(self):
"""time index of max across time."""
return ["-Tmaxn"]
@addargs
def Tmedian(self):
"""median across time."""
return ["-Tmedian"]
@addargs
def Tperc(self, percentage):
"""nth percentile (0-100) of FULL RANGE across time"""
return ["-Tperc", percentage]
@addargs
def Tar1(self):
"""temporal AR(1) coefficient (use -odt float and probably demean
first)"""
return ["-Tar1"]
# Basic statistical operations
@addargs
def pval(self):
"""Nonparametric uncorrected P-value"""
return ['-pval']
@addargs
def pval0(self):
"""Same as -pval, but treat zeros as missing data"""
return ['-pval0']
@addargs
def cpval(self):
"""Same as -pval, but gives FWE corrected P-values"""
return ['-cpval']
@addargs
def ztop(self):
"""Convert Z-stat to (uncorrected) P"""
return ['-ztop']
@addargs
def ptoz(self):
"""Convert (uncorrected) P to Z"""
return ['-ptoz']
@addargs
def rank(self):
"""Convert (uncorrected) P to Z"""
return ['-rank']
@addargs
def ranknorm(self):
"""Transform to Normal dist via ranks"""
return ['-ranknorm']
# Multi-argument operations
@addargs
def roi(self, xmin, xsize, ymin, ysize, zmin, zsize, tmin=0, tsize=-1): def roi(self, xmin, xsize, ymin, ysize, zmin, zsize, tmin=0, tsize=-1):
"""Zero outside ROI (using voxel coordinates). """ """Zero outside ROI (using voxel coordinates). """
self.__args.extend(('-roi', return ['-roi', xmin, xsize, ymin, ysize,
xmin, xsize, ymin, ysize, zmin, zsize, tmin, tsize]
zmin, zsize, tmin, tsize))
return self @addargs
def bptf(self, hp_sigma, lp_sigma):
"""Bandpass temporal filtering; nonlinear highpass and Gaussian linear
lowpass (with sigmas in volumes, not seconds); set either sigma<0 to
skip that filter."""
return ["-bptf", hp_sigma, lp_sigma]
def run(self, output=None, odt=None, **kwargs): def run(self, output=None, odt=None, **kwargs):
"""Save output of operations to image. Set ``output`` to a filename to have """Save output of operations to image. Set ``output`` to a filename to have
......
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