3
dK                 @   s$  d Z ddlZddlmZmZmZmZmZmZ ddlm	Z	 ddl
mZ dd	lmZ G d
d deZG dd deZG dd de	ZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG d d! d!eZG d"d# d#eZdS )$z
Nipype interface for seg_maths.

The maths module provides higher-level interfaces to some of the operations
that can be performed with the niftysegmaths (seg_maths) command-line program.

    N   )TraitedSpecFiletraits	isdefinedCommandLineInputSpecNipypeInterfaceError   )NiftySegCommand)get_custom_path   )split_filenamec               @   sV   e Zd ZdZeddddddZedgddddd	Zd
Zej	dddddddded	Z
dS )
MathsInputz$Input Spec for seg_maths interfaces.r   z%sTzimage to operate on)positionargstrexists	mandatorydescin_filezimage to write)Zname_sourceZname_templater   r   r   z4datatype to use for output (default uses input type)floatcharintshortdoubleinputr   z-odt %s)r   r   r   N)__name__
__module____qualname____doc__r   r   out_filer   r   EnumZoutput_datatype r#   r#   B/tmp/pip-build-7vycvbft/nipype/nipype/interfaces/niftyseg/maths.pyr      s(   r   c               @   s   e Zd ZdZeddZdS )MathsOutputz%Output Spec for seg_maths interfaces.z image written after calculations)r   N)r   r   r   r    r   r!   r#   r#   r#   r$   r%   7   s   r%   c               @   s2   e Zd ZdZedddZeZeZ	dZ
d	ddZdS )
MathsCommanda  
    Base Command Interface for seg_maths interfaces.

    The executable seg_maths enables the sequential execution of arithmetic
    operations, like multiplication (-mul), division (-div) or addition
    (-add), binarisation (-bin) or thresholding (-thr) operations and
    convolution by a Gaussian kernel (-smo). It also alows mathematical
    morphology based operations like dilation (-dil), erosion (-ero),
    connected components (-lconcomp) and hole filling (-fill), Euclidean
    (- euc) and geodesic (-geo) distance transforms, local image similarity
    metric calculation (-lncc and -lssd). Finally, it allows multiple
    operations over the dimensionality of the image, from merging 3D images
    together as a 4D image (-merge) or splitting (-split or -tp) 4D images
    into several 3D images, to estimating the maximum, minimum and average
    over all time-points, etc.
    Z	seg_mathsZNIFTYSEGDIR)Zenv_dirZ_mathsNc             C   s^   t |\}}}t | jj\}}}| j}|dkrFt| jjrFd| jj }tjj|dj	|||S )N_merged_z	{0}{1}{2})
r   inputsr   _suffixr   	operationospathjoinformat)selfvaluenamer-   baser(   extsuffixr#   r#   r$   _overload_extensionT   s    z MathsCommand._overload_extension)N)r   r   r   r    r   Z_cmdr   
input_specr%   Zoutput_specr*   r6   r#   r#   r#   r$   r&   =   s   r&   c               @   sP   e Zd ZdZejdddddddd	d
dddddddddddddddddddZdS )UnaryMathsInputz*Input Spec for seg_maths Unary operations.sqrtexplogZrecipabsbinZotsuZlconcompZconcomp6Z	concomp26fillZeucZtpmaxZtmeanZtmaxZtminZsplitlabZ	removenanisnanZsubsamp2ZsclZ4to5rangez-%s   Ta  Operation to perform:

    * sqrt - Square root of the image).
    * exp - Exponential root of the image.
    * log - Log of the image.
    * recip - Reciprocal (1/I) of the image.
    * abs - Absolute value of the image.
    * bin - Binarise the image.
    * otsu - Otsu thresholding of the current image.
    * lconcomp - Take the largest connected component
    * concomp6 - Label the different connected components with a 6NN kernel
    * concomp26 - Label the different connected components with a 26NN kernel
    * fill - Fill holes in binary object (e.g. fill ventricle in brain mask).
    * euc - Euclidean distance transform
    * tpmax - Get the time point with the highest value (binarise 4D probabilities)
    * tmean - Mean value of all time points.
    * tmax - Max value of all time points.
    * tmin - Mean value of all time points.
    * splitlab - Split the integer labels into multiple timepoints
    * removenan - Remove all NaNs and replace then with 0
    * isnan - Binary image equal to 1 if the value is NaN and 0 otherwise
    * subsamp2 - Subsample the image by 2 using NN sampling (qform and sform scaled)
    * scl  - Reset scale and slope info.
    * 4to5 - Flip the 4th and 5th dimension.
    * range - Reset the image range to the min max.

)r   r   r   r   N)r   r   r   r    r   r"   r+   r#   r#   r#   r$   r8   _   s:   r8   c               @   s   e Zd ZdZeZdS )
UnaryMathsau  Unary mathematical operations.

    See Also
    --------
    `Source code <http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg>`__ --
    `Documentation <http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation>`__

    Examples
    --------
    >>> import copy
    >>> from nipype.interfaces import niftyseg
    >>> unary = niftyseg.UnaryMaths()
    >>> unary.inputs.output_datatype = 'float'
    >>> unary.inputs.in_file = 'im1.nii'

    >>> # Test sqrt operation
    >>> unary_sqrt = copy.deepcopy(unary)
    >>> unary_sqrt.inputs.operation = 'sqrt'
    >>> unary_sqrt.cmdline
    'seg_maths im1.nii -sqrt -odt float im1_sqrt.nii'
    >>> unary_sqrt.run()  # doctest: +SKIP

    >>> # Test sqrt operation
    >>> unary_abs = copy.deepcopy(unary)
    >>> unary_abs.inputs.operation = 'abs'
    >>> unary_abs.cmdline
    'seg_maths im1.nii -abs -odt float im1_abs.nii'
    >>> unary_abs.run()  # doctest: +SKIP

    >>> # Test bin operation
    >>> unary_bin = copy.deepcopy(unary)
    >>> unary_bin.inputs.operation = 'bin'
    >>> unary_bin.cmdline
    'seg_maths im1.nii -bin -odt float im1_bin.nii'
    >>> unary_bin.run()  # doctest: +SKIP

    >>> # Test otsu operation
    >>> unary_otsu = copy.deepcopy(unary)
    >>> unary_otsu.inputs.operation = 'otsu'
    >>> unary_otsu.cmdline
    'seg_maths im1.nii -otsu -odt float im1_otsu.nii'
    >>> unary_otsu.run()  # doctest: +SKIP

    >>> # Test isnan operation
    >>> unary_isnan = copy.deepcopy(unary)
    >>> unary_isnan.inputs.operation = 'isnan'
    >>> unary_isnan.cmdline
    'seg_maths im1.nii -isnan -odt float im1_isnan.nii'
    >>> unary_isnan.run()  # doctest: +SKIP

    N)r   r   r   r    r8   r7   r#   r#   r#   r$   rB      s   3rB   c               @   s   e Zd ZdZejdddddddd	d
ddddddddddddddZeddddddgddZej	dddd dgd!d"Z
d#Zejd$d%d&ddddd ged"Zd'S )(BinaryMathsInputz+Input Spec for seg_maths Binary operations.muldivaddsubpowthruthrsmoedgesobel3sobel5minsmolZgeollsnormmasknanhdr_copy
splitinterTz-%srA   a  Operation to perform:

    * mul - <float/file> - Multiply image <float> value or by other image.
    * div - <float/file> - Divide image by <float> or by other image.
    * add - <float/file> - Add image by <float> or by other image.
    * sub - <float/file> - Subtract image by <float> or by other image.
    * pow - <float> - Image to the power of <float>.
    * thr - <float> - Threshold the image below <float>.
    * uthr - <float> - Threshold image above <float>.
    * smo - <float> - Gaussian smoothing by std <float> (in voxels and up to 4-D).
    * edge - <float> - Calculate the edges of the image using a threshold <float>.
    * sobel3 - <float> - Calculate the edges of all timepoints using a Sobel filter
      with a 3x3x3 kernel and applying <float> gaussian smoothing.
    * sobel5 - <float> - Calculate the edges of all timepoints using a Sobel filter
      with a 5x5x5 kernel and applying <float> gaussian smoothing.
    * min - <file> - Get the min per voxel between <current> and <file>.
    * smol - <float> - Gaussian smoothing of a 3D label image.
    * geo - <float/file> - Geodesic distance according to the speed function <float/file>
    * llsnorm  <file_norm> - Linear LS normalisation between current and <file_norm>
    * masknan <file_norm> - Assign everything outside the mask (mask==0) with NaNs
    * hdr_copy <file> - Copy header from working image to <file> and save in <output>.
    * splitinter <x/y/z> - Split interleaved slices in direction <x/y/z>
      into separate time points

)r   r   r   r   z%s   operand_valueoperand_strz&second image to perform operation with)r   r   r   r   xorr   z%.8foperand_filez%float value to perform operation with)r   r   r   rX   r   z,string value to perform operation splitinterxyzN)r   r   r   r    r   r"   r+   r   rY   FloatrV   r   rW   r#   r#   r#   r$   rC      s^   rC   c                   s2   e Zd ZdZeZ fddZd fdd	Z  ZS )BinaryMathsa  Binary mathematical operations.

    See Also
    --------
    `Source code <http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg>`__ --
    `Documentation <http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation>`__

    Examples
    --------
    >>> import copy
    >>> from nipype.interfaces import niftyseg
    >>> binary = niftyseg.BinaryMaths()
    >>> binary.inputs.in_file = 'im1.nii'
    >>> binary.inputs.output_datatype = 'float'

    >>> # Test sub operation
    >>> binary_sub = copy.deepcopy(binary)
    >>> binary_sub.inputs.operation = 'sub'
    >>> binary_sub.inputs.operand_file = 'im2.nii'
    >>> binary_sub.cmdline
    'seg_maths im1.nii -sub im2.nii -odt float im1_sub.nii'
    >>> binary_sub.run()  # doctest: +SKIP

    >>> # Test mul operation
    >>> binary_mul = copy.deepcopy(binary)
    >>> binary_mul.inputs.operation = 'mul'
    >>> binary_mul.inputs.operand_value = 2.0
    >>> binary_mul.cmdline
    'seg_maths im1.nii -mul 2.00000000 -odt float im1_mul.nii'
    >>> binary_mul.run()  # doctest: +SKIP

    >>> # Test llsnorm operation
    >>> binary_llsnorm = copy.deepcopy(binary)
    >>> binary_llsnorm.inputs.operation = 'llsnorm'
    >>> binary_llsnorm.inputs.operand_file = 'im2.nii'
    >>> binary_llsnorm.cmdline
    'seg_maths im1.nii -llsnorm im2.nii -odt float im1_llsnorm.nii'
    >>> binary_llsnorm.run()  # doctest: +SKIP

    >>> # Test splitinter operation
    >>> binary_splitinter = copy.deepcopy(binary)
    >>> binary_splitinter.inputs.operation = 'splitinter'
    >>> binary_splitinter.inputs.operand_str = 'z'
    >>> binary_splitinter.cmdline
    'seg_maths im1.nii -splitinter z -odt float im1_splitinter.nii'
    >>> binary_splitinter.run()  # doctest: +SKIP

    c          	      s   |dkr | j jdkr d}t||dkr|dkrPt| j jsdj|}t|nH|dkrxt| j jsdj|}t|n |dkrt| j jsd}t||dkrt|dkrdS t	t
| j|||S )z2Convert input to appropriate format for seg_maths.rW   rT   zAoperand_str set but with an operation different than "splitinter"r+   rH   rI   rJ   rK   rL   rM   rN   rP   zoperand_value not set for {0}.rO   rQ   rR   rS   zoperand_file not set for {0}.z#operand_str not set for splitinter.rV   g        0)rH   rI   rJ   rK   rL   rM   rN   rP   )rO   rQ   rR   rS   )r)   r+   r   r   rV   r/   rY   rW   r   superr^   _format_arg)r0   optspecvalerr)	__class__r#   r$   ra   [  s&    



zBinaryMaths._format_argNc                sb   | j jdkrLt|\}}}t| j j\}}}| j j}tjj|dj|||S tt	| j
||S d S )NrS   z	{0}{1}{2})r)   r+   r   rY   r,   r-   r.   r/   r`   r^   r6   )r0   r1   r2   r-   r3   r(   r4   r5   )rf   r#   r$   r6   y  s    zBinaryMaths._overload_extension)N)	r   r   r   r    rC   r7   ra   r6   __classcell__r#   r#   )rf   r$   r^   '  s   0r^   c               @   s@   e Zd ZdZejdddddddd	d
dd
ZejdddddZdS )BinaryMathsInputIntegerz@Input Spec for seg_maths Binary operations that require integer.ZdilZerotpequalpadZcropTz-%srA   az  Operation to perform:

    * equal - <int> - Get voxels equal to <int>
    * dil - <int>  - Dilate the image <int> times (in voxels).
    * ero - <int> - Erode the image <int> times (in voxels).
    * tp - <int> - Extract time point <int>
    * crop - <int> - Crop <int> voxels around each 3D volume.
    * pad - <int> -  Pad <int> voxels with NaN value around each 3D volume.

)r   r   r   r   z%drU   z#int value to perform operation with)r   r   r   r   N)	r   r   r   r    r   r"   r+   IntrV   r#   r#   r#   r$   rh     s"   rh   c               @   s   e Zd ZdZeZdS )BinaryMathsIntegeraB  Integer mathematical operations.

    See Also
    --------
    `Source code <http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg>`__ --
    `Documentation <http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation>`__

    Examples
    --------
    >>> import copy
    >>> from nipype.interfaces.niftyseg import BinaryMathsInteger
    >>> binaryi = BinaryMathsInteger()
    >>> binaryi.inputs.in_file = 'im1.nii'
    >>> binaryi.inputs.output_datatype = 'float'
    >>> # Test dil operation
    >>> binaryi_dil = copy.deepcopy(binaryi)
    >>> binaryi_dil.inputs.operation = 'dil'
    >>> binaryi_dil.inputs.operand_value = 2
    >>> binaryi_dil.cmdline
    'seg_maths im1.nii -dil 2 -odt float im1_dil.nii'
    >>> binaryi_dil.run()  # doctest: +SKIP
    >>> # Test dil operation
    >>> binaryi_ero = copy.deepcopy(binaryi)
    >>> binaryi_ero.inputs.operation = 'ero'
    >>> binaryi_ero.inputs.operand_value = 1
    >>> binaryi_ero.cmdline
    'seg_maths im1.nii -ero 1 -odt float im1_ero.nii'
    >>> binaryi_ero.run()  # doctest: +SKIP
    >>> # Test pad operation
    >>> binaryi_pad = copy.deepcopy(binaryi)
    >>> binaryi_pad.inputs.operation = 'pad'
    >>> binaryi_pad.inputs.operand_value = 4
    >>> binaryi_pad.cmdline
    'seg_maths im1.nii -pad 4 -odt float im1_pad.nii'
    >>> binaryi_pad.run()  # doctest: +SKIP

    N)r   r   r   r    rh   r7   r#   r#   r#   r$   rm     s   %rm   c            	   @   s   e Zd ZdZejdddddddd	Zedd
dddgddZdZ	ej
ddddge	dZedd
dddgddZdZ	ej
ddddge	dZdS )TupleMathsInputz*Input Spec for seg_maths Tuple operations.ZlnccZlssdZlltsnormTz-%srA   a&  Operation to perform:

    * lncc <file> <std> Local CC between current img and <file> on a kernel with <std>
    * lssd <file> <std> Local SSD between current img and <file> on a kernel with <std>
    * lltsnorm <file_norm> <float>  Linear LTS normalisation assuming <float> percent outliers

)r   r   r   r   z%srU   operand_value1z!image to perform operation 1 with)r   r   r   r   rX   r   z'float value to perform operation 1 withz%.8foperand_file1)r   r   r   rX   r      operand_value2z!image to perform operation 2 withz'float value to perform operation 2 withoperand_file2N)r   r   r   r    r   r"   r+   r   rp   r   r]   ro   rs   rr   r#   r#   r#   r$   rn     s:   rn   c               @   s   e Zd ZdZeZdS )
TupleMathsa'  Mathematical operations on tuples.

    See Also
    --------
    `Source code <http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg>`__ --
    `Documentation <http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation>`__

    Examples
    --------
    >>> import copy
    >>> from nipype.interfaces import niftyseg
    >>> tuple = niftyseg.TupleMaths()
    >>> tuple.inputs.in_file = 'im1.nii'
    >>> tuple.inputs.output_datatype = 'float'

    >>> # Test lncc operation
    >>> tuple_lncc = copy.deepcopy(tuple)
    >>> tuple_lncc.inputs.operation = 'lncc'
    >>> tuple_lncc.inputs.operand_file1 = 'im2.nii'
    >>> tuple_lncc.inputs.operand_value2 = 2.0
    >>> tuple_lncc.cmdline
    'seg_maths im1.nii -lncc im2.nii 2.00000000 -odt float im1_lncc.nii'
    >>> tuple_lncc.run()  # doctest: +SKIP

    >>> # Test lssd operation
    >>> tuple_lssd = copy.deepcopy(tuple)
    >>> tuple_lssd.inputs.operation = 'lssd'
    >>> tuple_lssd.inputs.operand_file1 = 'im2.nii'
    >>> tuple_lssd.inputs.operand_value2 = 1.0
    >>> tuple_lssd.cmdline
    'seg_maths im1.nii -lssd im2.nii 1.00000000 -odt float im1_lssd.nii'
    >>> tuple_lssd.run()  # doctest: +SKIP

    >>> # Test lltsnorm operation
    >>> tuple_lltsnorm = copy.deepcopy(tuple)
    >>> tuple_lltsnorm.inputs.operation = 'lltsnorm'
    >>> tuple_lltsnorm.inputs.operand_file1 = 'im2.nii'
    >>> tuple_lltsnorm.inputs.operand_value2 = 0.01
    >>> tuple_lltsnorm.cmdline
    'seg_maths im1.nii -lltsnorm im2.nii 0.01000000 -odt float im1_lltsnorm.nii'
    >>> tuple_lltsnorm.run()  # doctest: +SKIP

    N)r   r   r   r    rn   r7   r#   r#   r#   r$   rt      s   +rt   c               @   s8   e Zd ZdZejdddZejeddddddd	Z	d
S )
MergeInputz)Input Spec for seg_maths merge operation.TzDimension to merge the images.)r   r   )r   z%srA   z5List of images to merge to the working image <input>.)r   r   r   r   N)
r   r   r   r    r   rl   	dimensionListr   merge_filesr#   r#   r#   r$   ru   0  s   ru   c                   s(   e Zd ZdZeZdZ fddZ  ZS )Mergeam  Merge image files.

    See Also
    --------
    `Source code <http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg>`__ --
    `Documentation <http://cmictig.cs.ucl.ac.uk/wiki/index.php/NiftySeg_documentation>`__

    Examples
    --------
    >>> from nipype.interfaces import niftyseg
    >>> node = niftyseg.Merge()
    >>> node.inputs.in_file = 'im1.nii'
    >>> files = ['im2.nii', 'im3.nii']
    >>> node.inputs.merge_files = files
    >>> node.inputs.dimension = 2
    >>> node.inputs.output_datatype = 'float'
    >>> node.cmdline
    'seg_maths im1.nii -merge 2 2 im2.nii im3.nii -odt float im1_merged.nii'

    r'   c                s8   |dkr$dt || jjdj|f S tt| j|||S )z2Convert input to appropriate format for seg_maths.rx   z-merge %d %d %s )lenr)   rv   r.   r`   ry   ra   )r0   rb   rc   rd   )rf   r#   r$   ra   V  s    zMerge._format_arg)	r   r   r   r    ru   r7   r*   ra   rg   r#   r#   )rf   r$   ry   =  s   ry   )r    r,   r3   r   r   r   r   r   r   r
   Zniftyreg.baser   Zutils.filemanipr   r   r%   r&   r8   rB   rC   r^   rh   rm   rn   rt   ru   ry   r#   r#   r#   r$   <module>	   s$    "=8S\"*10