o
    .wi                     @   s   d dl Z d dl mZ d dlmZ d dlmZ d dlmZ dededeeef fd	d
Z			ddedede
ded def
ddZ		ddedede
ded def
ddZdS )    N)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r'td| j d|j d| jdd |jdd krBt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: )dtype	TypeErrorlenshape
ValueErrorr   r    r   c/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/functional/image/d_lambda.py!_spectral_distortion_index_update   s"   r      elementwise_meanp	reduction)r   sumnonec                    s   j d }tj||f jd}tj||f jd}t|D ]}||d  }|dkr*q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:
        >>> from torch import rand
        >>> preds = rand([16, 3, 16, 16])
        >>> target = 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                    0   g | ]} d d ||d d d d d f qS Nr   r   .0r)r   r   r   
<listcomp>U      0 z6_spectral_distortion_index_compute.<locals>.<listcomp>)dimc                 S      g | ]}|  qS r   meanr   sr   r   r   r!   V       r   )r   c                    r   r   r   r   )r   r   r   r!   \   r"   c                 S   r$   r   r%   r'   r   r   r   r!   ]   r)   g      ?)r   torchzerosr   rangerepeatcatr   splitstackTpowabsr   r   )r   r   r   r   lengthm1m2knumstack1stack2scorediffoutputr   r   r   "_spectral_distortion_index_compute0   s4   
0&0&

&
r>   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 torch import rand
        >>> from torchmetrics.functional.image import spectral_distortion_index
        >>> preds = rand([16, 3, 16, 16])
        >>> target = 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   r>   )r   r   r   r   r   r   r   spectral_distortion_indexm   s   (rA   )r   r   )r*   r   typing_extensionsr   !torchmetrics.functional.image.uqir   "torchmetrics.utilities.distributedr   tupler   r@   r>   rA   r   r   r   r   <module>   s@   
@