o
    iq,  ã                   @  sÀ   d Z ddlmZ ddlZddlmZ ddlmZ ddl	m
Z
mZ ddlmZmZ d0dd„Zd0dd„Zd1dd„Zd2dd„Zd3dd„Z	d4d5dd„Zd6d d!„Zd7d%d&„Zd8d9d+d,„Zd8d:d.d/„ZdS );zW
This script contains utility functions for developing new networks/blocks in PyTorch.
é    )ÚannotationsN)ÚTensor)Ú
functional)Úcomplex_conj_tÚcomplex_mul_t)Úfftn_centered_tÚifftn_centered_tÚxr   Úreturnc                 C  sÂ   | j d dkrtd| j d › dƒ‚t| j ƒdkr4| j \}}}}}|  ddddd	¡ ¡  |d| ||¡S t| j ƒd
krY| j \}}}}}}|  ddddd	d¡ ¡  |d| |||¡S td| j › ƒ‚)aC  
    Swaps the complex dimension with the channel dimension so that the network treats real/imaginary
    parts as two separate channels.

    Args:
        x: input of shape (B,C,H,W,2) for 2D data or (B,C,H,W,D,2) for 3D data

    Returns:
        output of shape (B,C*2,H,W) for 2D data or (B,C*2,H,W,D) for 3D data
    éÿÿÿÿé   z'last dim must be 2, but x.shape[-1] is Ú.é   r   é   é   é   é   úLonly 2D (B,C,H,W,2) and 3D (B,C,H,W,D,2) data are supported but x has shape )ÚshapeÚ
ValueErrorÚlenÚpermuteÚ
contiguousÚview©r	   ÚbÚcÚhÚwÚtwoÚd© r!   úo/home/dell461/cl/sdc2/last_ska_mid/HISourceFinder-master-l/src/monai/apps/reconstruction/networks/nets/utils.pyÚreshape_complex_to_channel_dim   s   &*r#   c                 C  sÆ   | j d d dkrtd| j d › dƒ‚t| j ƒdkr6| j \}}}}|d }|  |d|||¡ ddddd¡S t| j ƒdkr[| j \}}}}}|d }|  |d||||¡ dddddd¡S td	| j › ƒ‚)
a,  
    Swaps the complex dimension with the channel dimension so that the network output has 2 as its last dimension

    Args:
        x: input of shape (B,C*2,H,W) for 2D data or (B,C*2,H,W,D) for 3D data

    Returns:
        output of shape (B,C,H,W,2) for 2D data or (B,C,H,W,D,2) for 3D data
    r   r   r   z&channel dimension should be even but (z	) is odd.r   r   r   zLonly 2D (B,C*2,H,W) and 3D (B,C*2,H,W,D) data are supported but x has shape )r   r   r   r   r   )r	   r   Úc2r   r   r   r    r!   r!   r"   Ú#reshape_channel_complex_to_last_dim4   s   
 $r%   útuple[Tensor, int]c                 C  sŒ   t | jƒdkr| j\}}}}}|  ¡  || d|||¡|fS t | jƒdkr>| j\}}}}}}|  ¡  || d||||¡|fS td| j› ƒ‚)zû
    Combines batch and channel dimensions.

    Args:
        x: input of shape (B,C,H,W,2) for 2D data or (B,C,H,W,D,2) for 3D data

    Returns:
        A tuple containing:
            (1) output of shape (B*C,1,...)
            (2) batch size
    r   r   r   r   )r   r   r   r   r   r   r!   r!   r"   Úreshape_channel_to_batch_dimO   s    r'   Ú
batch_sizeÚintc           	      C  s„   t | jƒdkr| j\}}}}}|| }|  |||||¡S t | jƒdkr:| j\}}}}}}|| }|  ||||||¡S td| j› ƒ‚)zÝ
    Detaches batch and channel dimensions.

    Args:
        x: input of shape (B*C,1,H,W,2) for 2D data or (B*C,1,H,W,D,2) for 3D data
        batch_size: batch size

    Returns:
        output of shape (B,C,...)
    r   r   zPonly 2D (B*C,1,H,W,2) and 3D (B*C,1,H,W,D,2) data are supported but x has shape )r   r   r   r   )	r	   r(   ÚbcÚoner   r   r   r   r    r!   r!   r"   Ú$reshape_batch_channel_to_channel_dimh   s   r,   útuple[Tensor, Tensor, Tensor]c                 C  sÐ  t | jƒdkrk| j\}}}}|  ¡  |d|d | | ¡} | jdd |dddd¡ |d|d dd¡ ¡  ||dd¡}| jddd |dddd¡ |d|d dd¡ ¡  ||dd¡}|  ||||¡} | | | ||fS t | jƒdkrà| j\}}}}}|  ¡  |d|d | | | ¡} | jdd |ddddd¡ |d|d ddd¡ ¡  ||ddd¡}| jddd |ddddd¡ |d|d ddd¡ ¡  ||ddd¡}|  |||||¡} | | | ||fS td| j› ƒ‚)	a¼  
    Performs layer mean-std normalization for complex data. Normalization is done for each batch member
    along each part (part refers to real and imaginary parts), separately.

    Args:
        x: input of shape (B,C,H,W) for 2D data or (B,C,H,W,D) for 3D data

    Returns:
        A tuple containing
            (1) normalized output of shape (B,C,H,W) for 2D data or (B,C,H,W,D) for 3D data
            (2) mean
            (3) std
    r   r   )Údimr   F)r.   Úunbiasedr   úHonly 2D (B,C,H,W) and 3D (B,C,H,W,D) data are supported but x has shape )r   r   r   r   ÚmeanÚexpandÚstdr   )r	   r   r   r   r   r1   r3   r    r!   r!   r"   Úcomplex_normalize   s(   <>"Bûr4   é   ÚkúVtuple[Tensor, tuple[tuple[int, int], tuple[int, int], tuple[int, int], int, int, int]]c                 C  sZ  t | jƒdkrJ| j\}}}}|d |d B d }|d |d B d }t|| d ƒ}t|| d ƒ}	t | ||	 ¡} d}
d}|	|||||
f}| |fS t | jƒdkr¥| j\}}}}}|d |d B d }|d |d B d }|d |d B d }
t|| d ƒ}t|| d ƒ}	t|
| d ƒ}t | || |	 ¡} |	|||||
f}| |fS td| j› ƒ‚)ah  
    Pad input to feed into the network (torch script compatible)

    Args:
        x: input of shape (B,C,H,W) for 2D data or (B,C,H,W,D) for 3D data
        k: padding factor. each padded dimension will be divisible by k.

    Returns:
        A tuple containing
            (1) padded input
            (2) pad sizes (in order to reverse padding if needed)

    Example:
        .. code-block:: python

            import torch

            # 2D data
            x = torch.ones([3,2,50,70])
            x_pad,padding_sizes = divisible_pad_t(x, k=16)
            # the following line should print (3, 2, 64, 80)
            print(x_pad.shape)

            # 3D data
            x = torch.ones([3,2,50,70,80])
            x_pad,padding_sizes = divisible_pad_t(x, k=16)
            # the following line should print (3, 2, 64, 80, 80)
            print(x_pad.shape)

    r   r   r   r   )r   r   r   r0   )r   r   Ú
floor_ceilÚFÚpadr   )r	   r6   r   r   r   r   Úw_multÚh_multÚw_padÚh_padÚd_multÚd_padÚ	pad_sizesr    r!   r!   r"   Údivisible_pad_t©   s.   !òþrB   rA   úGtuple[tuple[int, int], tuple[int, int], tuple[int, int], int, int, int]c                 C  sª   |\}}}}}}t | jƒdkr&| d|d ||d  …|d ||d  …f S t | jƒdkrM| d|d ||d  …|d ||d  …|d ||d  …f S td| j› ƒ‚)zÙ
    De-pad network output to match its original shape

    Args:
        x: input of shape (B,C,H,W) for 2D data or (B,C,H,W,D) for 3D data
        pad_sizes: padding values

    Returns:
        de-padded input
    r   .r   r   r   r0   )r   r   r   )r	   rA   r>   r=   r@   r<   r;   r?   r!   r!   r"   Úinverse_divisible_pad_tç   s   .@rD   ÚnÚfloatútuple[int, int]c                 C  s   t  | ¡t  | ¡fS )z«
    Returns floor and ceil of the input

    Args:
        n: input number

    Returns:
        A tuple containing:
            (1) floor(n)
            (2) ceil(n)
    )ÚmathÚfloorÚceil)rE   r!   r!   r"   r8      s   r8   r   ÚkspaceÚ	sens_mapsÚspatial_dimsc                 C  s&   t | |dd}t|t|ƒƒjdddS )a  
    Reduces coil measurements to a corresponding image based on the given sens_maps. Let's say there
    are C coil measurements inside kspace, then this function multiplies the conjugate of each coil sensitivity map with the
    corresponding coil image. The result of this process will be C images. Summing those images together gives the
    resulting "reduced image."

    Args:
        kspace: 2D kspace (B,C,H,W,2) with the last dimension being 2 (for real/imaginary parts) and C denoting the
            coil dimension. 3D data will have the shape (B,C,H,W,D,2).
        sens_maps: sensitivity maps of the same shape as input x.
        spatial_dims: is 2 for 2D data and is 3 for 3D data

    Returns:
        reduction of x to (B,1,H,W,2) for 2D data or (B,1,H,W,D,2) for 3D data.
    T©rM   Ú
is_complexr   )r.   Úkeepdim)r   r   r   Úsum)rK   rL   rM   Úimgr!   r!   r"   Úsensitivity_map_reduce  s   rS   rR   c                 C  s   t t| |ƒ|ddS )an  
    Expands an image to its corresponding coil images based on the given sens_maps. Let's say there
    are C coils. This function multiples image img with each coil sensitivity map in sens_maps and stacks
    the resulting C coil images along the channel dimension which is reserved for coils.

    Args:
        img: 2D image (B,1,H,W,2) with the last dimension being 2 (for real/imaginary parts). 3D data will have
            the shape (B,1,H,W,D,2).
        sens_maps: Sensitivity maps for combining coil images. The shape is (B,C,H,W,2) for 2D data
            or (B,C,H,W,D,2) for 3D data (C denotes the coil dimension).
        spatial_dims: is 2 for 2D data and is 3 for 3D data

    Returns:
        Expansion of x to (B,C,H,W,2) for 2D data and (B,C,H,W,D,2) for 3D data. The output is transferred
            to the frequency domain to yield coil measurements.
    TrN   )r   r   )rR   rL   rM   r!   r!   r"   Úsensitivity_map_expand#  s   rT   )r	   r   r
   r   )r	   r   r
   r&   )r	   r   r(   r)   r
   r   )r	   r   r
   r-   )r5   )r	   r   r6   r)   r
   r7   )r	   r   rA   rC   r
   r   )rE   rF   r
   rG   )r   )rK   r   rL   r   rM   r)   r
   r   )rR   r   rL   r   rM   r)   r
   r   )Ú__doc__Ú
__future__r   rH   Útorchr   Útorch.nnr   r9   Z'monai.apps.reconstruction.complex_utilsr   r   Z!monai.networks.blocks.fft_utils_tr   r   r#   r%   r'   r,   r4   rB   rD   r8   rS   rT   r!   r!   r!   r"   Ú<module>   s$   





)ÿ
>
