o
    .wi!                     @   sZ  d dl Z d dlmZmZ d dlZd dlmZ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ed	ed
ededeeeef f
ddZdedeeeedf f defddZdededefddZdededefddZded	ededeeeef fddZded	ed
ededef
ddZ			d$ded	ed
ee ded eed!  defd"d#ZdS )%    N)OptionalUnion)Tensortensor)conv2dpad)Literal)_check_same_shape)reducepredstarget	hp_filterwindow_sizereturnc              	   C   s  | j |j kr|| j }t| | | jdvr#td| j d|j dt| jdkr4| d} |d}|dks@td| d|| d	ksN|| dkrbtd
| d| d	 d| d d| t	j
} |t	j
}|ddddf j| j | jd}| ||fS )a  Update and returns variables required to compute Spatial Correlation Coefficient.

    Args:
        preds: Predicted tensor
        target: Ground truth tensor
        hp_filter: High-pass filter tensor
        window_size: Local window size integer

    Return:
        Tuple of (preds, target, hp_filter) tensors

    Raises:
        ValueError:
            If ``preds`` and ``target`` have different number of channels
            If ``preds`` and ``target`` have different shapes
            If ``preds`` and ``target`` have invalid shapes
            If ``window_size`` is not a positive integer
            If ``window_size`` is greater than the size of the image

    )      zExpected `preds` and `target` to have batch of colored images with BxCxHxW shape  or batch of grayscale images of BxHxW shape. Got preds: z and target: .r      r   z5Expected `window_size` to be a positive integer. Got    z[Expected `window_size` to be less than or equal to the size of the image. Got window_size: z and image size: xN)dtypedevice)r   tor	   ndim
ValueErrorshapelen	unsqueezesizetorchfloat32r   )r   r   r   r    r!   ^/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/functional/image/scc.py_scc_update   s<   



 
r#   	input_imgr   .c                 C   s  t |tr||||f}t|dkrtdt| | ddddddd|d f jdgd}| dddddd|d  df jdgd}tj|| |gdd}|ddddd|d	 ddf jd	gd}|dddd|d  dddf jd	gd}tj|||gd	dS )
zlApplies symmetric padding to the 2D image tensor input using ``reflect`` mode (d c b a | a b c d | d c b a).r   z+Expected padding to have length 4, but got Nr   r   )dimsr   dimr   )
isinstanceintr   r   flipr   cat)r$   r   left_pad	right_padpaddedtop_pad
bottom_padr!   r!   r"   _symmetric_reflect_pad_2dL   s   
.0.0r1   kernelc                 C   s   t |dd d }t |dd d }t |dd d }t |dd d }t| ||||fd}|ddg}t||dddS )zHApplies 2D signal convolution to the input tensor with the given kernel.r   r   r   )r   r   stridepadding)mathfloorr   ceilr1   r*   r   )r$   r2   left_paddingright_paddingtop_paddingbottom_paddingr.   r!   r!   r"   _signal_convolve_2d\   s   r=   c                 C   s   t | |d S )zOApplies 2-D Laplace filter to the input tensor with the given high pass filter.g       @)r=   )r$   r2   r!   r!   r"   _hp_2d_laplacianh   s   r>   windowc           
      C   s   t |dd d }t |dd d }t| ||||f} t|||||f}t| |ddd}t||ddd}t| d |ddd|d  }t|d |ddd|d  }t||  |ddd||  }	|||	fS )z<Computes local variance and covariance of the input tensors.r   r   r   r   r3   )r6   r8   r   r7   r   r   )
r   r   r?   r9   r:   
preds_meantarget_mean	preds_var
target_vartarget_preds_covr!   r!   r"   _local_variance_covariancem   s   
rE   c                 C   s   | j }| j}tjdd||f||d|d  }t| |}t||}t|||\}	}
}d|	|	dk < d|
|
dk < t|
t|	 }|dk}d||dk< || }d||< |S )a[  Computes per channel Spatial Correlation Coefficient.

    Args:
        preds: estimated image of Bx1xHxW shape.
        target: ground truth image of Bx1xHxW shape.
        hp_filter: 2D high-pass filter.
        window_size: size of window for local mean calculation.

    Return:
        Tensor with Spatial Correlation Coefficient score

    r   )r   r   r   r   r   )r   r   r   onesr>   rE   sqrt)r   r   r   r   r   r   r?   preds_hp	target_hprB   rC   rD   denidxsccr!   r!   r"   _scc_per_channel_compute   s    

rM      mean	reduction)rO   noneNc                    s    du rt g dg dg dg |du rd}|dvr"td| t \  fddtd	D }|dkrOtjtj|d	d
g dd
S |dkr^ttj|d	d
ddS dS )a  Compute Spatial Correlation Coefficient (SCC_).

    Args:
        preds: predicted images of shape ``(N,C,H,W)`` or ``(N,H,W)``.
        target: ground truth images of shape ``(N,C,H,W)`` or ``(N,H,W)``.
        hp_filter: High-pass filter tensor. default: tensor([[-1,-1,-1],[-1,8,-1],[-1,-1,-1]])
        window_size: Local window size integer. default: 8,
        reduction: Reduction method for output tensor. If ``None`` or ``"none"``,
                   returns a tensor with the per sample results. default: ``"mean"``.

    Return:
        Tensor with scc score

    Example:
        >>> from torch import randn
        >>> from torchmetrics.functional.image import spatial_correlation_coefficient as scc
        >>> x = randn(5, 3, 16, 16)
        >>> scc(x, x)
        tensor(1.)
        >>> x = randn(5, 16, 16)
        >>> scc(x, x)
        tensor(1.)
        >>> x = randn(5, 3, 16, 16)
        >>> y = randn(5, 3, 16, 16)
        >>> scc(x, y, reduction="none")
        tensor([0.0223, 0.0256, 0.0616, 0.0159, 0.0170])

    N)rR   rR   )rR   rN   rR   rQ   )rO   rQ   z3Expected reduction to be 'mean' or 'none', but got c              
      sV   g | ]'}t d d |d d d d f dd d |d d d d f d qS )Nr   )rM   r   ).0ir   r   r   r   r!   r"   
<listcomp>   s    Dz3spatial_correlation_coefficient.<locals>.<listcomp>r   r&   )r   r   r   rO   elementwise_mean)rP   )	r   r   r#   ranger   r   rO   r+   r
   )r   r   r   r   rP   per_channelr!   rU   r"   spatial_correlation_coefficient   s   #rZ   )NrN   rO   )r6   typingr   r   r   r   r   torch.nn.functionalr   r   typing_extensionsr   torchmetrics.utilities.checksr	   "torchmetrics.utilities.distributedr
   r)   tupler#   r1   r=   r>   rE   rM   rZ   r!   r!   r!   r"   <module>   s<   (&2$(
