3
d3                 @   s   d Z ddljZddlZddlmZ ddlm	Z	 ddl
mZmZmZmZmZ ddlmZ ddlmZ e	jd	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 ) zP
Miscellaneous algorithms for 2D contours and 3D triangularized meshes handling
    N)linalg   )logging)BaseInterfacetraitsTraitedSpecFileBaseInterfaceInputSpec)tvtk)vtkbaseznipype.interfacec                   s$   e Zd ZdZdZ fddZ  ZS )TVTKBaseInterfacez%A base class for interfaces using VTKTc                s&   t j rtdtt| jf | d S )Nz$This interface requires tvtk to run.)VTKInfoZno_tvtkImportErrorsuperr   __init__)selfinputs)	__class__ 8/tmp/pip-build-7vycvbft/nipype/nipype/algorithms/mesh.pyr      s    zTVTKBaseInterface.__init__)__name__
__module____qualname____doc__Z_redirect_xr   __classcell__r   r   )r   r   r      s   r   c               @   sP   e Zd ZeddddZeddddZejddddddd	Zed
dddddZ	dS )WarpPointsInputSpecTzfile containing the point set)exists	mandatorydescz%dense deformation field to be appliedZcubicZnearestZlinearinterpolation)
usedefaultr   r   pointsz	%s_warped
out_pointszthe warped point set)Zname_sourceZname_templateZoutput_nameZkeep_extensionr   N)
r   r   r   r   r!   warpr   EnumZinterpr"   r   r   r   r   r   $   s    r   c               @   s   e Zd ZeddZdS )WarpPointsOutputSpeczthe warped point set)r   N)r   r   r   r   r"   r   r   r   r   r%   :   s   r%   c               @   s2   e Zd ZdZeZeZd
ddZdd Z	dd	 Z
dS )
WarpPointsa)  
    Applies a displacement field to a point set given in vtk format.
    Any discrete deformation field, given in physical coordinates and
    which volume covers the extent of the vtk point set, is a valid
    ``warp`` file. FSL interfaces are compatible, for instance any
    field computed with :class:`nipype.interfaces.fsl.utils.ConvertWarp`.

    Example::

        from nipype.algorithms.mesh import WarpPoints
        wp = WarpPoints()
        wp.inputs.points = 'surf1.vtk'
        wp.inputs.warp = 'warpfield.nii'
        res = wp.run()

    	generatedNc             C   sj   t jt j|\}}|dkr2t j|\}}|| }|d kr>|}|d dkrV|dd  }t jd|||f S )Nz.gzr   .   z%s_%s.%s)opsplitextbasenameabspath)r   in_filesuffixextfnameZfextZfext2r   r   r   
_gen_fnameS   s    zWarpPoints._gen_fnamec                s`  dd l }ddlm} tj| jjd}|j  tj	|}t
j|j}|jj|j| jj}|d j}|ddddf }	t
jj|	|dddf  t
j fdd|D }
g }xN|D ]F}|j}t
j|dkr|j||
j }nt
j|jd f}|j| qW t
jt
j|}dd t||D }||_tj }tj|| | j| jjdd	d
|_ |j!  |S )Nr   )ndimage)	file_name   c                s   g | ]}t j|  qS r   )npdot).0p)originras2voxr   r   
<listcomp>p   s    z-WarpPoints._run_interface.<locals>.<listcomp>c             S   s   g | ]\}}|| qS r   r   )r8   r9   dr   r   r   r<   }   s    warpedz.vtk)r/   r0   )"ZnibabelZscipyr3   r
   PolyDataReaderr   r!   updater   
vtk_outputr6   arrayfuncsZfour_to_threeloadr#   affiner   invZdataobjanyZmap_coordinates	transposezerosshapeappendZsqueezeZdstackzipPolyDataWriterconfigure_input_datar2   r4   write)r   runtimenbr3   rZmeshr!   Z	warp_dimsrE   Zvox2rasZ	voxpointsZwarpsaxisZwdatar#   ZdispsZ	newpointswr   )r:   r;   r   _run_interfacea   s6    


zWarpPoints._run_interfacec             C   s(   | j  j }| j| jjddd|d< |S )Nr>   z.vtk)r/   r0   r"   )_outputsgetr2   r   r!   )r   outputsr   r   r   _list_outputs   s    zWarpPoints._list_outputs)r'   N)r   r   r   r   r   
input_specr%   output_specr2   rU   rY   r   r   r   r   r&   >   s   
$r&   c               @   sh   e Zd ZeddddZeddddZejdddddZejd	d
dddZ	eddddZ
eddddZdS )ComputeMeshWarpInputSpecTz9Reference surface (vtk format) to which compute distance.)r   r   r   z6Test surface (vtk format) from which compute distance.Z	euclideansqeuclideanznorm used to report distance)r    r   noneareazh"none": no weighting is performed, surface": edge distance is weighted by the corresponding surface areazsurfwarp.vtkz>vtk file based on surface1 and warpings mapping it to surface2zdistance.npyz1numpy file keeping computed distances and weightsN)r   r   r   r   surface1surface2r   r$   metric	weightingout_warpout_filer   r   r   r   r\      s.   r\   c               @   s0   e Zd ZejddZedddZedddZdS )ComputeMeshWarpOutputSpeczcomputed distance)r   Tz=vtk file with the vertex-wise mapping of surface1 to surface2)r   r   z1numpy file keeping computed distances and weightsN)	r   r   r   r   Floatdistancer   rd   re   r   r   r   r   rf      s   rf   c               @   s0   e Zd ZdZeZeZdd Zdd Z	dd Z
dS )	ComputeMeshWarpa  
    Calculates a the vertex-wise warping to get surface2 from surface1.
    It also reports the average distance of vertices, using the norm specified
    as input.

    .. warning:

      A point-to-point correspondence between surfaces is required


    Example::

        import nipype.algorithms.mesh as m
        dist = m.ComputeMeshWarp()
        dist.inputs.surface1 = 'surf1.vtk'
        dist.inputs.surface2 = 'surf2.vtk'
        res = dist.run()

    c             C   sr   t j|}t j|}t j|}tj|| tj||  }t j|| || }t j|| }d| t j| }|S )Ng      ?)r6   rB   nlanormr7   Zarccossin)r   ABCZABxACprodZangler_   r   r   r   _triangle_area   s    


zComputeMeshWarp._triangle_areac             C   s6  t j| jjd}t j| jjd}tj|}tj|}|j  |j  t|j	t|j	ks\t
tj|j	}tj|j	}|| }tjt|}	ytj|dd}
W n$ tk
r   tjtjd|}
Y nX | jjdkr|
dC }
| jjdkr|jj jddjtd d dd f }xt|D ]\}}d}||d d d d f |kjdd }xP|D ]H}|t|d	  }|t|d  }|t|d  }|| j|||7 }qLW ||	|< qW tj|
|	g}tjtj| jj |j!  t j" }|j	|_	|j|_||j#_$d
|j#j$_%t j&tj| jj'd}tj(|| |j)  tj*|
|	d| _+|S )N)r4   r)   )rS   r]   r   r_      g        r   Zwarpings)weights),r
   r?   r   r`   ra   r   rA   r@   lenr!   AssertionErrorr6   rB   Zonesrj   rk   	TypeErrorZapply_along_axisrb   rc   ZpolysZto_arrayZreshapeZastypeint	enumeraterG   rq   Zvstacksaver*   r-   re   rH   ZPolyData
point_datavectorsnamerM   rd   rN   rO   Zaverage	_distance)r   rP   r1r2vtk1vtk2points1Zpoints2Zdiffrs   Z	errvectorZfacesip1rT   Zpoint_facesZidsetfp1fp2Zfp3resultZout_meshwriterr   r   r   rU      sP    

($

zComputeMeshWarp._run_interfacec             C   s>   | j  j }tj| jj|d< tj| jj|d< | j|d< |S )Nre   rd   rh   )rV   rW   r*   r-   r   re   rd   r~   )r   rX   r   r   r   rY     s
    
zComputeMeshWarp._list_outputsN)r   r   r   r   r\   rZ   rf   r[   rq   rU   rY   r   r   r   r   ri      s   
5ri   c               @   s   e Zd ZeddddZejejdejejdejdejdZ	eje	edddddddZ
ejdd	d
ddddZeddddZeddddZdS )MeshWarpMathsInputSpecTz_Input surface in vtk format, with associated warp field as point data (ie. from ComputeMeshWarp)r   r   r   g      ?)r   z2image, float or tuple of floats to act as operator)defaultr    r   r   sumsubmuldivzoperation to be performed)r    r   zwarp_maths.vtkz=vtk file based on in_surf and warpings mapping it to out_filezwarped_surf.vtkzvtk with surface warpedN)r   r   r   r   in_surfr   ZEitherrg   TupleZfloat_traitoperatorr$   	operationrd   re   r   r   r   r   r     s*   "r   c               @   s$   e Zd ZedddZedddZdS )MeshWarpMathsOutputSpecTz=vtk file with the vertex-wise mapping of surface1 to surface2)r   r   zvtk with surface warpedN)r   r   r   r   rd   re   r   r   r   r   r   =  s   r   c               @   s(   e Zd ZdZeZeZdd Zdd Z	dS )MeshWarpMathsa(  
    Performs the most basic mathematical operations on the warping field
    defined at each vertex of the input surface. A surface with scalar
    or vector data can be used as operator for non-uniform operations.

    .. warning:

      A point-to-point correspondence between surfaces is required


    Example::

        import nipype.algorithms.mesh as m
        mmath = m.MeshWarpMaths()
        mmath.inputs.in_surf = 'surf1.vtk'
        mmath.inputs.operator = 'surf2.vtk'
        mmath.inputs.operation = 'mul'
        res = mmath.run()

    c             C   s  t j| jjd}tj|}|j  tj|j	}|j
jd krBtd| jj}tj|}t|ttfrt j| jjd}tj|}|j  t|t|j	kst|j
j}|d kr|j
j}|d krtdtj|}|jd |jd k rtj|j g|jd  j}ntj|}||9 }tj|j
j}	| jjdkr6|	|7 }	nF| jjdkrN|	|8 }	n.| jjdkrf|	|9 }	n| jjdkr||	| }	|	|j
_t jtj| jjd}
tj|
| |
j   d |j
_||	 |_	t jtj| jj!d}
tj|
| |
j   |S )	N)r4   z%No warping field was found in in_surfz)No operator values found in operator filer)   r   r   r   r   )"r
   r?   r   r   r   rA   r@   r6   rB   r!   r{   r|   RuntimeErrorr   Z	ones_like
isinstancestrbytesra   ru   rv   ZscalarsrJ   tolistTZ
atleast_1dr   rM   r*   r-   rd   rN   rO   re   )r   rP   r   r   r   r   Zopfieldr   r   Zwarpingr   r   r   r   rU   ^  sT    








zMeshWarpMaths._run_interfacec             C   s4   | j  j }tj| jj|d< tj| jj|d< |S )Nre   rd   )rV   rW   r*   r-   r   re   rd   )r   rX   r   r   r   rY     s    zMeshWarpMaths._list_outputsN)
r   r   r   r   r   rZ   r   r[   rU   rY   r   r   r   r   r   E  s
   9r   c                   s    e Zd ZdZ fddZ  ZS )P2PDistancez
    Calculates a point-to-point (p2p) distance between two corresponding
    VTK-readable meshes or contours.

    A point-to-point correspondence between nodes is required

    .. deprecated:: 1.0-dev
       Use :py:class:`ComputeMeshWarp` instead.
    c                s    t t| jf | tjd d S )NzHThis interface has been deprecated since 1.0, please use ComputeMeshWarp)r   r   r   IFLOGGERwarning)r   r   )r   r   r   r     s    zP2PDistance.__init__)r   r   r   r   r   r   r   r   )r   r   r     s   	r   )"r   os.pathpathr*   numpyr6   r   rj    r   Zinterfaces.baser   r   r   r   r	   Zinterfaces.vtkbaser
   Z
interfacesr   r   	getLoggerr   r   r   r%   r&   r\   rf   ri   r   r   r   r   r   r   r   r   <module>   s&   

O#_#Y