U
    Ph}8                     @  sR  d dl mZ d dlmZmZ d dlZd dlZd dlm	Z	 d dl
mZmZ d dlmZ d dlmZ d dlmZ d d	lmZmZmZmZ erd dlZd
Zned\ZZddddddgZdefddddddZd ejfddddddZd,ddddZd-ddZ dd Z!d d! Z"d"dd#d$Z#d"dd%d&Z$d"dd'd(Z%ddd)d*Z&d+d Z'dS ).    )annotations)TYPE_CHECKINGcastN)	DtypeLike)	ITKReader	ITKWriter)
MetaTensor)orientation_ras_lps)EnsureChannelFirst)MetaKeys	SpaceKeysconvert_to_dst_typeoptional_importTitkitk_image_to_metatensormetatensor_to_itk_imageitk_to_monai_affinemonai_to_itk_affineget_itk_image_centermonai_to_itk_ddfzstr | int | NonezDtypeLike | torch.dtyper   )channel_dimdtypereturnc                 C  sP   t d|d}|| \}}t|||dd }t||}t|d|}tt|S )a|  
    Converts an ITK image to a MetaTensor object.

    Args:
        image: The ITK image to be converted.
        channel_dim: the channel dimension of the input image, default is None.
            This is used to set original_channel_dim in the metadata, EnsureChannelFirst reads this field.
            If None, the channel_dim is inferred automatically.
            If the input array doesn't have a channel dim, this value should be ``'no_channel'``.
        dtype: output dtype, defaults to the Python built-in `float`.

    Returns:
        A MetaTensor object containing the array data and metadata in ChannelFirst format.
    F)affine_lps_to_rasr   )dstr   r   )r   )r   get_datar   r   ensure_torch_and_prune_metar
   r   )imager   r   readerZimage_array	meta_dataZ
metatensor r    P/home/dell461/cl/sdc2/HISourceFinder-master-l/src/monai/data/itk_torch_bridge.pyr   +   s    z
int | Noner   )meta_tensorr   r   c                 K  s|   | j tjtjtjkr<|  }t| j	|_	tj|j tj< n| }t
|dd}|j| j|dd |j|j|j|j	d|j|dS )a  
    Converts a MetaTensor object to an ITK image. Expects the MetaTensor to be in ChannelFirst format.

    Args:
        meta_tensor: The MetaTensor to be converted.
        channel_dim: channel dimension of the data array, defaults to ``0`` (Channel-first).
            ``None`` indicates no channel dimension. This is used to create a Vector Image if it is not ``None``.
        dtype: output data type, defaults to `np.float32`.
        kwargs: additional keyword arguments. Currently `itk.GetImageFromArray` will get ``ttype`` from this dictionary.

    Returns:
        The ITK image.

    See also: :py:func:`ITKWriter.create_backend_obj`
    F)output_dtyper   T)
data_arrayr   squeeze_end_dims)r   affiner   r   kwargs)metagetr   SPACEr   LPSRAScloner	   r&   r   set_data_arraydatacreate_backend_objdata_objr   r#   )r"   r   r   r'   Z_meta_tensorwriterr    r    r!   r   E   s    ztorch.Tensor)r   c                 C  s   t |  | j}|rt| |}ntj|d tjd}tj|d tjd}tj|tjd|d|d|f< tj|tjd|d||f< |rt| |\}}	|	| | }t| \}
}|| |
 }t	| \}}|| | }|| S )aa  
    Converts an ITK affine matrix (2x2 for 2D or 3x3 for 3D matrix and translation vector) to a MONAI affine matrix.

    Args:
        image: The ITK image object. This is used to extract the spacing and direction information.
        matrix: The 2x2 or 3x3 ITK affine matrix.
        translation: The 2-element or 3-element ITK affine translation vector.
        center_of_rotation: The center of rotation. If provided, the affine
                            matrix will be adjusted to account for the difference
                            between the center of the image and the center of rotation.
        reference_image: The coordinate space that matrix and translation were defined
                         in respect to. If not supplied, the coordinate space of image
                         is used.

    Returns:
        A 4x4 MONAI affine matrix.
       r   N)
_assert_itk_regions_match_arrayndim&_compute_reference_space_affine_matrixtorcheyefloat64tensor_compute_offset_matrix_compute_direction_matrix_compute_spacing_matrix)r   matrixtranslationcenter_of_rotationZreference_imager6   Zreference_affine_matrixaffine_matrixoffset_matrixinverse_offset_matrixdirection_matrixinverse_direction_matrixspacing_matrixinverse_spacing_matrixr    r    r!   r   i   s      c                 C  s   t |  t| \}}|| | }t| \}}|| | }|rVt| |\}}|| | }| j}	|d|	d|	f  }
|d|	|	f  }|
|fS )a  
    Converts a MONAI affine matrix to an ITK affine matrix (2x2 for 2D or 3x3 for
    3D matrix and translation vector). See also 'itk_to_monai_affine'.

    Args:
        image: The ITK image object. This is used to extract the spacing and direction information.
        affine_matrix: The 3x3 for 2D or 4x4 for 3D MONAI affine matrix.
        center_of_rotation: The center of rotation. If provided, the affine
                            matrix will be adjusted to account for the difference
                            between the center of the image and the center of rotation.

    Returns:
        The ITK matrix and the translation vector.
    N)r5   r>   r=   r<   r6   numpytolist)r   rB   rA   rG   rH   rE   rF   rC   rD   r6   r?   r@   r    r    r!   r      s    c                 C  sV   t |   t j}t |  }t |  }|  |d d |  | }| S )a  
    Calculates the center of the ITK image based on its origin, size, and spacing.
    This center is equivalent to the implicit image center that MONAI uses.

    Args:
        image: The ITK image.

    Returns:
        The center of the image as a list of coordinates.
       g      ?)	npasarrayGetLargestPossibleRegionGetSizefloat32
GetSpacing	GetOriginGetDirectionrJ   )r   
image_sizespacingorigincenterr    r    r!   r      s
    c                 C  s   |   }|  }|  }t| }t| }t| }t| jd d d }t| }t| }	t| }
t|dkot|	dkot|
dk}t	||ot	||ot	||}|st
d|st
dd S )Nr   z9ITK-MONAI bridge: non-zero ITK region indices encounteredz9ITK-MONAI bridge: ITK regions should be of the same shape)rN   ZGetBufferedRegionZGetRequestedRegionrL   arrayrO   shapeZGetIndexallarray_equalAssertionError)r   Zlargest_regionZbuffered_regionZrequested_regionZlargest_region_sizeZbuffered_region_sizeZrequested_region_size
array_sizeZlargest_region_indexZbuffered_region_indexZrequested_region_indexZindices_are_zerosZsizes_matchr    r    r!   r5      s*    (

r5   z!tuple[torch.Tensor, torch.Tensor]c                 C  s   | j }tt| t| }tj|d tjd}tj|tjd|d ||f< tj|d tjd}tj|tjd |d ||f< ||fS Nr3   r4   )r6   rL   rM   r   r8   r9   r:   r;   )r   rA   r6   offsetrC   rD   r    r    r!   r<      s    r<   c                 C  sx   | j }tj|  tjd}tj|d tjd}tj|d tjd}t|D ]$\}}||||f< d| |||f< qJ||fS )Nr4   r3   )r6   rL   rM   rQ   r:   r8   r9   	enumerate)r   r6   rU   rG   rH   ier    r    r!   r>      s    r>   c                 C  s   | j }t|  }tj|d tjd}tj|tjd|d |d |f< t|  }tj|d tjd}tj|tjd|d |d |f< ||fS r_   )	r6   r   array_from_matrixrS   r8   r9   r:   r;   ZGetInverseDirection)r   r6   	directionrE   Zinverse_directionrF   r    r    r!   r=     s      r=   c                   s   |j   fddt| D \}} fddt|D \}} fddt| D \}} fddt|D \}}	|| | | }
d}t|  tj}|| ||  ||  d }|t| t|   7 }t	| |
|d}|S )	Nc                 3  s&   | ]}|d  d  f   V  qd S NrI   .0mr6   r    r!   	<genexpr>  s     z9_compute_reference_space_affine_matrix.<locals>.<genexpr>c                 3  s&   | ]}|d  d  f   V  qd S rf   rg   rh   rk   r    r!   rl     s     c                 3  s&   | ]}|d  d  f   V  qd S rf   rg   rh   rk   r    r!   rl     s     c                 3  s&   | ]}|d  d  f   V  qd S rf   rg   rh   rk   r    r!   rl     s    rX   rK   )r?   r@   )
r6   r>   r=   rL   rM   rN   rO   rP   rR   r   )r   Z	ref_imagerG   Zinv_spacing_matrixZref_spacing_matrixZref_inv_spacing_matrixrE   Zinv_direction_matrixZref_direction_matrixZref_inv_direction_matrixr?   Zpixel_offsetrT   r@   Zref_affine_matrixr    rk   r!   r7     s&    

 r7   c           	      C  s   | j }|tttd|d dg }|ddddf }tj|  tjd}|tj	||d d9 }tj| 
 tjd}tjd||tjdtj}tj}tj||f }tj||f }tj||d	}||   ||   || 
  |S )
a?  
    converting the dense displacement field from the MONAI space to the ITK
    Args:
        image: itk image of array shape 2D: (H, W) or 3D: (D, H, W)
        ddf: numpy array of shape 2D: (2, H, W) or 3D: (3, D, H, W)
    Returns:
        displacement_field: itk image of the corresponding displacement field

    r3   r   .NrX   r4   )ndminzij,...j->...i)ttype)r6   	transposetuplelistrangerL   rM   rQ   r:   rY   rS   einsumastyperP   r   FVectorImageGetImageFromArray
SetSpacing	SetOriginrR   SetDirection)	r   Zddfr6   rU   re   Zvector_component_typeZvector_pixel_typeZdisplacement_field_typeZdisplacement_fieldr    r    r!   r   6  s    ")NN)N)(
__future__r   typingr   r   rI   rL   r8   monai.config.type_definitionsr   
monai.datar   r   monai.data.meta_tensorr   monai.data.utilsr	   monai.transformsr
   monai.utilsr   r   r   r   r   has_itk__all__floatr   rP   r   r   r   r   r5   r<   r>   r=   r7   r   r    r    r    r!   <module>   sF     $4
%