a
    d.                     @   s   d dl mZ d dlZd dlmZ d dlmZ d dlmZ d dlm	Z	 eeeeef ddd	Z
deeeed edddZdeeeed edddZdS )    )TupleN)Tensor)Literal)universal_image_quality_index)reduce)predstargetreturnc                 C   s   | j |j kr&td| j  d|j  dt| jdkrNtd| j d|j d| jdd |jdd krtd	| j d|j d| |fS )
zUpdate and returns variables required to compute Spectral Distortion Index.

    Args:
        preds: Low resolution multispectral image
        target: High resolution fused image

    z>Expected `ms` and `fused` to have the same data type. Got ms: z and fused: .   z@Expected `preds` and `target` to have BxCxHxW shape. Got preds: z and target: N   zNExpected `preds` and `target` to have same batch and channel sizes.Got preds: )Zdtype	TypeErrorlenshape
ValueErrorr   r    r   o/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torchmetrics/functional/image/d_lambda.py!_spectral_distortion_index_update   s"    r      elementwise_mean)r   sumnone)r   r   p	reductionr	   c                    s   j d }tj||f jd}tj||f jd}t|D ]F}||d  }|dkrVq:dd||d ddddf |ddd}	tjfddt|d |D dd}
dd t|	|
d	d
 j d D }t	|d|||d df<  dd||d ddddf |ddd}	tj fddt|d |D dd}
dd t|	|
d	d
 j d D }t	|d|||d df< q:||j
 }||j
 }tt|| |}|dkrt|d| }n&td||d   t| d| }t||S )a  Compute Spectral Distortion Index (SpectralDistortionIndex_).

    Args:
        preds: Low resolution multispectral image
        target: High resolution fused image
        p: a parameter to emphasize large spectral difference
        reduction: a method to reduce metric score over labels.

            - ``'elementwise_mean'``: takes the mean (default)
            - ``'sum'``: takes the sum
            - ``'none'``: no reduction will be applied

    Example:
        >>> _ = torch.manual_seed(42)
        >>> preds = torch.rand([16, 3, 16, 16])
        >>> target = torch.rand([16, 3, 16, 16])
        >>> preds, target = _spectral_distortion_index_update(preds, target)
        >>> _spectral_distortion_index_compute(preds, target)
        tensor(0.0234)

    r   )devicer   Nc                    s0   g | ](} d d ||d d d d d f qS Nr   r   .0r)r   r   r   
<listcomp>V       z6_spectral_distortion_index_compute.<locals>.<listcomp>)Zdimc                 S   s   g | ]}|  qS r   meanr   sr   r   r   r    W   s   r   )r   c                    s0   g | ](} d d ||d d d d d f qS r   r   r   )r   r   r   r    ]   r!   c                 S   s   g | ]}|  qS r   r"   r$   r   r   r   r    ^   s   g      ?)r   torchzerosr   rangerepeatcatr   splitstackTpowabsr   r   )r   r   r   r   lengthm1m2knumZstack1Zstack2Zscorediffoutputr   r   r   "_spectral_distortion_index_compute1   s4    
0&0&


&r7   c                 C   s>   t |tr|dkr"td| dt| |\} }t| |||S )a  Calculate `Spectral Distortion Index`_ (SpectralDistortionIndex_) also known as D_lambda.

    Metric is used to compare the spectral distortion between two images.

    Args:
        preds: Low resolution multispectral image
        target: High resolution fused image
        p: Large spectral differences
        reduction: a method to reduce metric score over labels.

            - ``'elementwise_mean'``: takes the mean (default)
            - ``'sum'``: takes the sum
            - ``'none'``: no reduction will be applied

    Return:
        Tensor with SpectralDistortionIndex score

    Raises:
        TypeError:
            If ``preds`` and ``target`` don't have the same data type.
        ValueError:
            If ``preds`` and ``target`` don't have ``BxCxHxW shape``.
        ValueError:
            If ``p`` is not a positive integer.

    Example:
        >>> from torchmetrics.functional.image import spectral_distortion_index
        >>> _ = torch.manual_seed(42)
        >>> preds = torch.rand([16, 3, 16, 16])
        >>> target = torch.rand([16, 3, 16, 16])
        >>> spectral_distortion_index(preds, target)
        tensor(0.0234)

    r   z.Expected `p` to be a positive integer. Got p: r
   )
isinstanceintr   r   r7   )r   r   r   r   r   r   r   spectral_distortion_indexn   s    (r:   )r   r   )r   r   )typingr   r&   r   Ztyping_extensionsr   Z!torchmetrics.functional.image.uqir   Z"torchmetrics.utilities.distributedr   r   r9   r7   r:   r   r   r   r   <module>   s0     @  