o
    .wiLL                     @   s   d dl mZ d dlmZmZmZmZ d dlZd dlmZ d dl	m
Z
 d dlmZ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 esLddgZG dd deZG dd deZdS )    )Sequence)AnyListOptionalUnionN)Tensor)Literal)_multiscale_ssim_update_ssim_check_inputs_ssim_update)Metric)dim_zero_cat)_MATPLOTLIB_AVAILABLE)_AX_TYPE_PLOT_OUT_TYPE%StructuralSimilarityIndexMeasure.plot/MultiScaleStructuralSimilarityIndexMeasure.plotc                       sJ  e Zd ZU dZdZeed< dZeed< dZeed< dZ	e
ed< d	Ze
ed
< ee ed< ee ed< 									d)dedee
ee
 f deeee f ded deee
ee
e
f f  de
de
dedededdf fdd Zdededdfd!d"Zdeeeeef f fd#d$Z	d*d%eeeee f  d&ee defd'd(Z  ZS )+ StructuralSimilarityIndexMeasurea4	  Compute Structural Similarity Index Measure (SSIM_).

    As input to ``forward`` and ``update`` the metric accepts the following input

    - ``preds`` (:class:`~torch.Tensor`): Predictions from model
    - ``target`` (:class:`~torch.Tensor`): Ground truth values

    As output of `forward` and `compute` the metric returns the following output

    - ``ssim`` (:class:`~torch.Tensor`): if ``reduction!='none'`` returns float scalar tensor with average SSIM value
      over sample else returns tensor of shape ``(N,)`` with SSIM values per sample

    Args:
        preds: estimated image
        target: ground truth image
        gaussian_kernel: If ``True`` (default), a gaussian kernel is used, if ``False`` a uniform kernel is used
        sigma: Standard deviation of the gaussian kernel, anisotropic kernels are possible.
            Ignored if a uniform kernel is used
        kernel_size: the size of the uniform kernel, anisotropic kernels are possible.
            Ignored if a Gaussian kernel is used
        reduction: a method to reduce metric score over individual batch scores

            - ``'elementwise_mean'``: takes the mean
            - ``'sum'``: takes the sum
            - ``'none'`` or ``None``: no reduction will be applied

        data_range:
            the range of the data. If None, it is determined from the data (max - min). If a tuple is provided then
            the range is calculated as the difference and input is clamped between the values.
        k1: Parameter of SSIM.
        k2: Parameter of SSIM.
        return_full_image: If true, the full ``ssim`` image is returned as a second argument.
            Mutually exclusive with ``return_contrast_sensitivity``
        return_contrast_sensitivity: If true, the constant term is returned as a second argument.
            The luminance term can be obtained with luminance=ssim/contrast
            Mutually exclusive with ``return_full_image``
        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Example:
        >>> import torch
        >>> from torchmetrics.image import StructuralSimilarityIndexMeasure
        >>> preds = torch.rand([3, 3, 256, 256])
        >>> target = preds * 0.75
        >>> ssim = StructuralSimilarityIndexMeasure(data_range=1.0)
        >>> ssim(preds, target)
        tensor(0.9219)

    Thigher_is_betteris_differentiableFfull_state_update        plot_lower_bound      ?plot_upper_boundpredstarget      ?   elementwise_meanN{Gz?Q?gaussian_kernelsigmakernel_size	reductionr   sumnoneN
data_rangek1k2return_full_imagereturn_contrast_sensitivitykwargsreturnc
                    s   t  jdi |
 d}||vrtd| d| |dv r)| jdtddd n| jdg d d | jd	tddd |	s@|rH| jd
g dd || _|| _|| _|| _	|| _
|| _|| _|| _|	| _d S )Nr&   $Argument `reduction` must be one of 
, but got r   r'   
similarityr   r'   defaultdist_reduce_fxtotalimage_returncat )super__init__
ValueError	add_statetorchtensorr"   r#   r$   r%   r)   r*   r+   r,   r-   )selfr"   r#   r$   r%   r)   r*   r+   r,   r-   r.   valid_reduction	__class__r:   T/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/image/ssim.pyr<   Z   s&   
z)StructuralSimilarityIndexMeasure.__init__c                 C   s   t ||\}}t||| j| j| j| j| j| j| j| j	
}t
|tr&|\}}n|}| j	s.| jr>t
| jts8td| j| | jdv rnt
| jtjsNtd|  j| 7  _t
| jtjsbtd|  j|jd 7  _dS t
| jtsxtd| j| dS )*Update state with predictions and targets.@Expected `self.image_return` to be a list when returning images.r2   z9Expected `self.similarity` to be a Tensor for reductions.%Expected `self.total` to be a Tensor.r   z>Expected `self.similarity` to be a list when reduction='none'.N)r
   r   r"   r#   r$   r)   r*   r+   r,   r-   
isinstancetupler8   list	TypeErrorappendr%   r3   r?   r   r'   r7   shape)rA   r   r   similarity_packr3   imager:   r:   rE   update   s<   


z'StructuralSimilarityIndexMeasure.updatec                 C   s   | j dkrt| jtrt| jtr| j| j }n'td| j dkr/t| jts+td| j}nt| jtr;t| j}ntd| jsE| j	rXt| j
trTt| j
}||fS td|S )zCompute SSIM over state.r   z_Expected `self.similarity`and `self.total` to be of type Tensor for elementwise_mean reduction.r'   <Expected `self.similarity` to be a Tensor for sum reduction.=Expected `self.similarity` to be a list for reduction='none'.rG   )r%   rI   r3   r   r7   rL   rK   r   r-   r,   r8   )rA   r3   r8   r:   r:   rE   compute   s&   


z(StructuralSimilarityIndexMeasure.computevalaxc                 C      |  ||S )a  Plot a single or multiple values from the metric.

        Args:
            val: Either a single result from calling `metric.forward` or `metric.compute` or a list of these results.
                If no value is provided, will automatically call `metric.compute` and plot that result.
            ax: An matplotlib axis object. If provided will add plot to that axis

        Returns:
            Figure and Axes object

        Raises:
            ModuleNotFoundError:
                If `matplotlib` is not installed

        .. plot::
            :scale: 75

            >>> # Example plotting a single value
            >>> import torch
            >>> from torchmetrics.image import StructuralSimilarityIndexMeasure
            >>> preds = torch.rand([3, 3, 256, 256])
            >>> target = preds * 0.75
            >>> metric = StructuralSimilarityIndexMeasure(data_range=1.0)
            >>> metric.update(preds, target)
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> import torch
            >>> from torchmetrics.image import StructuralSimilarityIndexMeasure
            >>> preds = torch.rand([3, 3, 256, 256])
            >>> target = preds * 0.75
            >>> metric = StructuralSimilarityIndexMeasure(data_range=1.0)
            >>> values = [ ]
            >>> for _ in range(10):
            ...     values.append(metric(preds, target))
            >>> fig_, ax_ = metric.plot(values)

        _plotrA   rU   rV   r:   r:   rE   plot      ,r   )	Tr   r   r   Nr    r!   FFNN)__name__
__module____qualname____doc__r   bool__annotations__r   r   r   floatr   r   r   r   r   intr   r   rJ   r   r<   rQ   rT   r   r   r[   __classcell__r:   r:   rC   rE   r      sf   
 1	
'&r   c                       sF  e Zd ZU dZdZeed< dZeed< dZeed< dZ	e
ed< d	Ze
ed
< ee ed< ee ed< 									d-dedeeee f dee
ee
 f ded deee
ee
e
f f  de
de
dee
df ded  d!ed"df fd#d$Zdeded"dfd%d&Zd"efd'd(Z	d.d)eeeee f  d*ee d"efd+d,Z  ZS )/*MultiScaleStructuralSimilarityIndexMeasureaF  Compute `MultiScaleSSIM`_, Multi-scale Structural Similarity Index Measure.

    This metric is is a generalization of Structural Similarity Index Measure by incorporating image details at
    different resolution scores.

    As input to ``forward`` and ``update`` the metric accepts the following input

    - ``preds`` (:class:`~torch.Tensor`): Predictions from model
    - ``target`` (:class:`~torch.Tensor`): Ground truth values

    As output of `forward` and `compute` the metric returns the following output

    - ``msssim`` (:class:`~torch.Tensor`): if ``reduction!='none'`` returns float scalar tensor with average MSSSIM
      value over sample else returns tensor of shape ``(N,)`` with SSIM values per sample

    Args:
        gaussian_kernel: If ``True`` (default), a gaussian kernel is used, if false a uniform kernel is used
        kernel_size: size of the gaussian kernel
        sigma: Standard deviation of the gaussian kernel
        reduction: a method to reduce metric score over labels.

            - ``'elementwise_mean'``: takes the mean
            - ``'sum'``: takes the sum
            - ``'none'`` or ``None``: no reduction will be applied

        data_range:
            the range of the data. If None, it is determined from the data (max - min). If a tuple is provided then
            the range is calculated as the difference and input is clamped between the values.
            The ``data_range`` must be given when ``dim`` is not None.
        k1: Parameter of structural similarity index measure.
        k2: Parameter of structural similarity index measure.
        betas: Exponent parameters for individual similarities and contrastive sensitivities returned by different image
            resolutions.
        normalize: When MultiScaleStructuralSimilarityIndexMeasure loss is used for training, it is desirable to use
            normalizes to improve the training stability. This `normalize` argument is out of scope of the original
            implementation [1], and it is adapted from https://github.com/jorge-pessoa/pytorch-msssim instead.
        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Return:
        Tensor with Multi-Scale SSIM score

    Raises:
        ValueError:
            If ``kernel_size`` is not an int or a Sequence of ints with size 2 or 3.
        ValueError:
            If ``betas`` is not a tuple of floats with length 2.
        ValueError:
            If ``normalize`` is neither `None`, `ReLU` nor `simple`.

    Example:
        >>> from torch import rand
        >>> from torchmetrics.image import MultiScaleStructuralSimilarityIndexMeasure
        >>> preds = torch.rand([3, 3, 256, 256])
        >>> target = preds * 0.75
        >>> ms_ssim = MultiScaleStructuralSimilarityIndexMeasure(data_range=1.0)
        >>> ms_ssim(preds, target)
        tensor(0.9628)

    Tr   r   Fr   r   r   r   r   r   r   r   r   r   Nr    r!   gǺ?g48EG?ga4?g??g9EGr?relur"   r$   r#   r%   r&   r)   r*   r+   betas.	normalize)ri   simpleNr.   r/   c
                    sN  t  jdi |
 d}||vrtd| d| |dv r)| jdtddd n| jdg d d | jd	tddd t|ttfsJtd
| t|tret	|dvs^t
dd |D setd| || _|| _|| _|| _|| _|| _|| _t|tstdt|trt
dd |D std|| _|	r|	dvrtd|	| _d S )Nr&   r0   r1   r2   r3   r   r'   r4   r7   zRArgument `kernel_size` expected to be an sequence or an int, or a single int. Got )      c                 s       | ]}t |tV  qd S N)rI   re   ).0ksr:   r:   rE   	<genexpr>W      zFMultiScaleStructuralSimilarityIndexMeasure.__init__.<locals>.<genexpr>ztArgument `kernel_size` expected to be an sequence of size 2 or 3 where each element is an int, or a single int. Got z3Argument `betas` is expected to be of a type tuple.c                 s   ro   rp   )rI   rd   )rq   betar:   r:   rE   rs   g  rt   z5Argument `betas` is expected to be a tuple of floats.)ri   rl   zNArgument `normalize` to be expected either `None` or one of 'relu' or 'simple'r:   )r;   r<   r=   r>   r?   r@   rI   r   re   lenallr"   r#   r$   r%   r)   r*   r+   rJ   rj   rk   )rA   r"   r$   r#   r%   r)   r*   r+   rj   rk   r.   rB   rC   r:   rE   r<   8  sD   


z3MultiScaleStructuralSimilarityIndexMeasure.__init__c                 C   s   t ||\}}t||| j| j| j| j| j| j| j| j	
}| j
dv r2t| jts+td| j| nt| jts<td|  j| 7  _t| jtsOtd|  jtj|jd | jj| jjd7  _dS )rF   r(   NrS   zPExpected `self.similarity` to be a Tensor for elementwise_mean or sum reduction.rH   r   )dtypedeviceN)r
   r	   r"   r#   r$   r)   r*   r+   rj   rk   r%   rI   r3   rK   rL   rM   r   r'   r7   r?   r@   rN   ry   rz   )rA   r   r   r3   r:   r:   rE   rQ   n  s.   
,z1MultiScaleStructuralSimilarityIndexMeasure.updatec                 C   sx   | j dv rt| jtrt| jS td| j dkr&t| jtr"| jS tdt| jtr8t| jtr8| j| j S td)zCompute MS-SSIM over state.rx   rS   r'   rR   zYExpected `self.similarity` and `self.total` to be Tensors for elementwise_mean reduction.)r%   rI   r3   rK   r   rL   r   r7   )rA   r:   r:   rE   rT     s   


z2MultiScaleStructuralSimilarityIndexMeasure.computerU   rV   c                 C   rW   )a"  Plot a single or multiple values from the metric.

        Args:
            val: Either a single result from calling `metric.forward` or `metric.compute` or a list of these results.
                If no value is provided, will automatically call `metric.compute` and plot that result.
            ax: An matplotlib axis object. If provided will add plot to that axis

        Returns:
            Figure and Axes object

        Raises:
            ModuleNotFoundError:
                If `matplotlib` is not installed

        .. plot::
            :scale: 75

            >>> # Example plotting a single value
            >>> from torch import rand
            >>> from torchmetrics.image import MultiScaleStructuralSimilarityIndexMeasure
            >>> preds = rand([3, 3, 256, 256])
            >>> target = preds * 0.75
            >>> metric = MultiScaleStructuralSimilarityIndexMeasure(data_range=1.0)
            >>> metric.update(preds, target)
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> from torch import rand
            >>> from torchmetrics.image import MultiScaleStructuralSimilarityIndexMeasure
            >>> preds = rand([3, 3, 256, 256])
            >>> target = preds * 0.75
            >>> metric = MultiScaleStructuralSimilarityIndexMeasure(data_range=1.0)
            >>> values = [ ]
            >>> for _ in range(10):
            ...     values.append(metric(preds, target))
            >>> fig_, ax_ = metric.plot(values)

        rX   rZ   r:   r:   rE   r[     r\   r   )	Tr   r   r   Nr    r!   rh   ri   r]   )r^   r_   r`   ra   r   rb   rc   r   r   r   rd   r   r   r   r   re   r   r   r   rJ   r   r<   rQ   rT   r   r   r[   rf   r:   r:   rC   rE   rg      sf   
 <
	
6rg   )collections.abcr   typingr   r   r   r   r?   r   typing_extensionsr   "torchmetrics.functional.image.ssimr	   r
   r   torchmetrics.metricr   torchmetrics.utilities.datar   torchmetrics.utilities.importsr   torchmetrics.utilities.plotr   r   __doctest_skip__r   rg   r:   r:   r:   rE   <module>   s    T