o
    #i}8                     @  s&  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rKd dlZd
Zned\ZZg dZdefd.ddZd ejfd/ddZd0d1ddZd2ddZ dd  Z!d!d" Z"d3d$d%Z#d3d&d'Z$d3d(d)Z%d1d*d+Z&d,d- Z'dS )4    )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_ddfchannel_dimstr | int | NonedtypeDtypeLike | torch.dtypereturnr   c                 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"   ]/home/dell461/cl/sdc2/last_ska_mid/HISourceFinder-master-l/src/monai/data/itk_torch_bridge.pyr   +   s   
r   meta_tensor
int | Noner   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   r   torch.Tensorc                 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< |rPt| |\}}	|	| | }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_imager:   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     r   c                 C  s   t |  t| \}}|| | }t| \}}|| | }|r+t| |\}}|| | }| 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)r9   rB   rA   r@   r:   numpytolist)r   rF   rE   rK   rL   rI   rJ   rG   rH   r:   rC   rD   r"   r"   r#   r      s   r   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GetDirectionrN   )r   
image_sizespacingorigincenterr"   r"   r#   r      s
   r   c                 C  s   |   }|  }|  }t| }t| }t| }t| jd d d }t| }t| }	t| }
t|dkoUt|	dkoUt|
dk}t	||ogt	||ogt	||}|snt
d|stt
dd S )Nr   z9ITK-MONAI bridge: non-zero ITK region indices encounteredz9ITK-MONAI bridge: ITK regions should be of the same shape)rR   ZGetBufferedRegionZGetRequestedRegionrP   arrayrS   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#   r9      s,   (

r9   !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 Nr7   r8   )r:   rP   rQ   r   r<   r=   r>   r?   )r   rE   r:   offsetrG   rH   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< q%||fS )Nr8   r7   )r:   rP   rQ   rU   r>   r<   r=   	enumerate)r   r:   rY   rK   rL   ier"   r"   r#   rB      s   rB   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 rd   )	r:   r   array_from_matrixrW   r<   r=   r>   r?   ZGetInverseDirection)r   r:   	directionrI   Zinverse_directionrJ   r"   r"   r#   rA     s     rA   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  (    | ]}|d  d  f   V  qd S NrM   .0mr:   r"   r#   	<genexpr>     & z9_compute_reference_space_affine_matrix.<locals>.<genexpr>c                 3  rk   rl   rm   rn   rq   r"   r#   rr     rs   c                 3  rk   rl   rm   rn   rq   r"   r#   rr     rs   c                 3  rk   rl   rm   rn   rq   r"   r#   rr     s    
r\   rO   )rC   rD   )
r:   rB   rA   rP   rQ   rR   rS   rT   rV   r   )r   Z	ref_imagerK   Zinv_spacing_matrixZref_spacing_matrixZref_inv_spacing_matrixrI   Zinv_direction_matrixZref_direction_matrixZref_inv_direction_matrixrC   Zpixel_offsetrX   rD   Zref_affine_matrixr"   rq   r#   r;     s&   

 r;   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

    r7   r   .Nr\   r8   )ndminzij,...j->...i)ttype)r:   	transposetuplelistrangerP   rQ   rU   r>   r]   rW   einsumastyperT   r   FVectorImageGetImageFromArray
SetSpacing	SetOriginrV   SetDirection)	r   ddfr:   rY   rj   Zvector_component_typeZvector_pixel_typeZdisplacement_field_typeZdisplacement_fieldr"   r"   r#   r   6  s   "r   )r   r   r   r   r   r   )r$   r   r   r%   r   r   )NN)r   r6   rl   )r   rc   )(
__future__r   typingr   r   rM   rP   r<   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   rT   r   r   r   r   r9   r@   rB   rA   r;   r   r"   r"   r"   r#   <module>   s8   $
4%



