
    iLL                         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sddgZ G d de      Z G d de      Zy)    )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_TYPEz%StructuralSimilarityIndexMeasure.plotz/MultiScaleStructuralSimilarityIndexMeasure.plotc                   t    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ZdededdfdZdeeeeef   f   fdZ	 d!deeeee   f      dee   defdZ x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targetNgaussian_kernelsigmakernel_size	reductionelementwise_meansumnoneN
data_rangek1k2return_full_imagereturn_contrast_sensitivitykwargsreturnc
                    t        |   di |
 d}||vrt        d| d|       |dv r(| j                  dt	        j
                  d      d       n| j                  dg d        | j                  d	t	        j
                  d      d       |	s|r| j                  d
g d       || _        || _        || _        || _	        || _
        || _        || _        || _        |	| _        y )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__s               l/Volumes/fast/ai/experiments/voice-extract-mac/.venv/lib/python3.12/site-packages/torchmetrics/image/ssim.pyr9   z)StructuralSimilarityIndexMeasure.__init__Z   s     	"6"CO+COCTT^_h^ijkk33NN<c1BSXNYNN<DNIwS(9%P&*;NN>2eNL.
&"$!2+F(    c                    t        ||      \  }}t        ||| j                  | j                  | j                  | j
                  | j                  | j                  | j                  | j                  
      }t        |t              r|\  }}n|}| j                  s| j                  r@t        | j                  t              st        d      | j                  j                         | j                   dv rt        | j"                  t$        j&                        st        d      | xj"                  |j)                         z  c_        t        | j*                  t$        j&                        st        d      | xj*                  |j,                  d   z  c_        yt        | j"                  t              st        d      | j"                  j                  |       y)*Update state with predictions and targets.@Expected `self.image_return` to be a list when returning images.r/   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tupler5   list	TypeErrorappendr    r0   r<   r   r#   r4   shape)r>   r   r   similarity_packr0   images         rA   updatez'StructuralSimilarityIndexMeasure.update   s^   *5&9v&  JJOOGGGG"",,
 ou- /J(J++t/E/Ed//6 bcc$$U+>>88doou||< [\\OOz~~//Odjj%,,7 GHHJJ%++a.(Jdoot4 `aaOO"":.rB   c                 z   | j                   dk(  rYt        | j                  t              r4t        | j                  t              r| j                  | j                  z  }nt        d      | j                   dk(  r2t        | j                  t              st        d      | j                  }n;t        | j                  t              rt        | j                        }nt        d      | j                  s| j                  r>t        | j                  t              rt        | 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'.rE   )r    rG   r0   r   r4   rJ   rI   r   r)   r(   r5   )r>   r0   r5   s      rA   computez(StructuralSimilarityIndexMeasure.compute   s    >>//$//62z$**f7U!__tzz9
u  ^^u$doov6 ^__J$//40)$//:
 _``++t/E/E$++T2+D,=,=> |++   bcc rB   valaxc                 &    | j                  ||      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r>   rT   rU   s      rA   plotz%StructuralSimilarityIndexMeasure.plot       X zz#r""rB   )	T      ?   r"   N{Gz?Q?FFNN)__name__
__module____qualname____doc__r   bool__annotations__r   r   r   floatr   r   r   r   r   intr	   r   rH   r   r9   rO   rS   r   r   rZ   __classcell__r@   s   @rA   r   r      s   /b "d!"t"#t#!e!!e!<L !%/213FXBF"',1%G%G UHUO+,%G 3-.	%G
 BC%G U5%u*=#=>?%G %G %G  %G &*%G %G 
%GN$/F $/F $/t $/LvuVV^'<<= : _c,#E&(6*:":;<,#IQRZI[,#	,#rB   r   c                   p    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ZdededdfdZdefdZ	 d#deeeee   f      d ee   defd!Z x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   Nr   r   r   r    r!   r%   r&   r'   betas.	normalize)relusimpleNr*   r+   c
                    t        |   di |
 d}||vrt        d| d|       |dv r(| j                  dt	        j
                  d      d       n| j                  dg d        | j                  d	t	        j
                  d      d       t        |t        t        f      st        d
|       t        |t              r-t        |      dvst        d |D              st        d|       || _        || _        || _        || _        || _        || _        || _        t        |t$              st        d      t        |t$              rt        d |D              st        d      || _        |	r|	dvrt        d      |	| _        y )Nr!   r-   r.   r/   r0   r   r#   r1   r4   zRArgument `kernel_size` expected to be an sequence or an int, or a single int. Got )      c              3   <   K   | ]  }t        |t                y wN)rG   rh   ).0kss     rA   	<genexpr>zFMultiScaleStructuralSimilarityIndexMeasure.__init__.<locals>.<genexpr>W  s     5`T_bjS6IT_   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              3   <   K   | ]  }t        |t                y wru   )rG   rg   )rv   betas     rA   rx   zFMultiScaleStructuralSimilarityIndexMeasure.__init__.<locals>.<genexpr>g  s     /ZTYD
40GTYry   z5Argument `betas` is expected to be a tuple of floats.)ro   rp   zNArgument `normalize` to be expected either `None` or one of 'relu' or 'simple'r7   )r8   r9   r:   r;   r<   r=   rG   r   rh   lenallr   r   r   r    r%   r&   r'   rH   rm   rn   )r>   r   r   r   r    r%   r&   r'   rm   rn   r*   r?   r@   s               rA   r9   z3MultiScaleStructuralSimilarityIndexMeasure.__init__8  s    	"6"CO+COCTT^_h^ijkk33NN<c1BSXNYNN<DNIwS(9%P;38depdqr  k8,F*#5`T_5`2`((3}6 
  /
&"$%'RSSeU#C/ZTY/Z,ZTUU
*<<mnn"rB   c                 "   t        ||      \  }}t        ||| j                  | j                  | j                  | j
                  | j                  | j                  | j                  | j                  
      }| j                  dv rAt        | j                  t              st        d      | j                  j                  |       nHt        | j                  t               st        d      | xj                  |j#                         z  c_        t        | j$                  t               st        d      | xj$                  t'        j(                  |j*                  d   | j$                  j,                  | j$                  j.                        z  c_        y)rD   r$   NrR   zPExpected `self.similarity` to be a Tensor for elementwise_mean or sum reduction.rF   r   )dtypedeviceN)r   r
   r   r   r   r%   r&   r'   rm   rn   r    rG   r0   rI   rJ   rK   r   r#   r4   r<   r=   rL   r   r   )r>   r   r   r0   s       rA   rO   z1MultiScaleStructuralSimilarityIndexMeasure.updaten  s   *5&9v,  JJOOGGGGJJNN

 >>^+doot4 _``OO"":.doov6 rssOOz~~//O$**f-CDD

ell5;;q>9I9IRVR\R\RcRcdd
rB   c                    | j                   dv r:t        | j                  t              rt	        | j                        S t        d      | j                   dk(  r1t        | j                  t              r| j                  S t        d      t        | j                  t              r3t        | j                  t              r| j                  | j                  z  S t        d      )zCompute MS-SSIM over state.r   rR   r#   rQ   zYExpected `self.similarity` and `self.total` to be Tensors for elementwise_mean reduction.)r    rG   r0   rI   r   rJ   r   r4   )r>   s    rA   rS   z2MultiScaleStructuralSimilarityIndexMeasure.compute  s    >>^+$//40#DOO44[\\>>U"$//62&Z[[doov.:djj&3Q??TZZ//sttrB   rT   rU   c                 &    | j                  ||      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
            >>> 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)

        rW   rY   s      rA   rZ   z/MultiScaleStructuralSimilarityIndexMeasure.plot  r[   rB   )	Tr]   r\   r"   Nr^   r_   )gǺ?g48EG?ga4?g??g9EGr?ro   r`   )ra   rb   rc   rd   r   re   rf   r   r   r   rg   r   r   r   r   rh   r   r	   r   rH   r   r9   rO   rS   r   r   rZ   ri   rj   s   @rA   rl   rl      s   :x "d!"t"#t#!e!!e!<L !%13/2FXBF#K5;4#4# 3-.4# UHUO+,	4#
 BC4# U5%u*=#=>?4# 4# 4# UCZ 4# 124# 4# 
4#leF eF et e:u u _c,#E&(6*:":;<,#IQRZI[,#	,#rB   rl   )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   rl   r7   rB   rA   <module>r      sW    % - -   % h h & 4 @ @?ArsP#v P#fS# S#rB   