
    i@!                         d dl mZ d dlmZ d dlmZmZmZ d dlZd dlm	Z	m
Z
 d dl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 dlmZmZ esdgZ G d de      Zy)    )Sequence)partial)AnyOptionalUnionN)Tensortensor)Literal)_psnr_compute_psnr_update)Metric)rank_zero_warn)_MATPLOTLIB_AVAILABLE)_AX_TYPE_PLOT_OUT_TYPEzPeakSignalNoiseRatio.plotc                       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<   eed	<   	 	 	 dd	ee
ee
e
f   f   de
ded   deeeeedf   f      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 )PeakSignalNoiseRatioa4  `Compute Peak Signal-to-Noise Ratio`_ (PSNR).

    .. math:: \text{PSNR}(I, J) = 10 * \log_{10} \left(\frac{\max(I)^2}{\text{MSE}(I, J)}\right)

    Where :math:`\text{MSE}` denotes the `mean-squared-error`_ function.

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

    - ``preds`` (:class:`~torch.Tensor`): Predictions from model of shape ``(N,C,H,W)``
    - ``target`` (:class:`~torch.Tensor`): Ground truth values of shape ``(N,C,H,W)``

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

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

    Args:
        data_range:
            the range of the data. If a tuple is provided, then the range is calculated as the difference and
            input is clamped between the values.
        base: a base of a logarithm to use.
        reduction: a method to reduce metric score over labels.

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

        dim:
            Dimensions to reduce PSNR scores over, provided as either an integer or a list of integers. Default is
            None meaning scores will be reduced across all dimensions and all batches.
        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Example:
        >>> from torchmetrics.image import PeakSignalNoiseRatio
        >>> psnr = PeakSignalNoiseRatio(data_range=3.0)
        >>> preds = torch.tensor([[0.0, 1.0], [2.0, 3.0]])
        >>> target = torch.tensor([[3.0, 2.0], [1.0, 0.0]])
        >>> psnr(preds, target)
        tensor(2.5527)

    Tis_differentiablehigher_is_betterFfull_state_update        plot_lower_bound
data_rangeNbase	reduction)elementwise_meansumnoneNdim.kwargsreturnc                    t        |   di | ||dk7  rt        d| d       |;| j                  dt	        d      d       | j                  dt	        d	      d       n(| j                  dg d
       | j                  dg d
       d | _        t        |t              rN| j                  dt	        |d   |d	   z
        d       t        t        j                  |d	   |d         | _        n&| j                  dt	        t        |            d       || _        || _        t        |t              rt        |      | _        y || _        y )Nr   zThe `reduction=z.` will not have any effect when `dim` is None.sum_squared_errorr   r   )defaultdist_reduce_fxtotalr   catr      mean)minmax )super__init__r   	add_stater	   clamping_fn
isinstancetupler   torchclampfloatr   r   r   r   )selfr   r   r   r   r    	__class__s         l/Volumes/fast/ai/experiments/voice-extract-mac/.venv/lib/python3.12/site-packages/torchmetrics/image/psnr.pyr.   zPeakSignalNoiseRatio.__init__Q   s'    	"6";9(::_YK7efg;NN.sTYNZNN7F1IeNLNN.5NQNN7BuNEj%(NN<
1
ST8U1VgmNn&u{{
1:VW=YDNN<j8I1J[aNb	"!+C!:5:    predstargetc                 H   | j                   "| j                  |      }| j                  |      }t        ||| j                        \  }}| j                  t        | j                  t
              s!t        dt        | j                               t        | j                  t
              s!t        dt        | j                               | xj                  |z  c_        | xj                  |z  c_        yt        | j                  t              s!t        dt        | j                               t        | j                  t              s!t        dt        | j                               | j                  j                  |       | j                  j                  |       y)z*Update state with predictions and targets.N)r   z:Expected `self.sum_squared_error` to be a Tensor, but got z.Expected `self.total` to be a Tensor, but got z8Expected `self.sum_squared_error` to be a list, but got z,Expected `self.total` to be a list, but got )r0   r   r   r1   r#   r   	TypeErrortyper&   listappend)r6   r:   r;   r#   num_obss        r8   updatezPeakSignalNoiseRatio.updatep   sa   '$$U+E%%f-F%1%TXX%N"788d44f=PQUVZVlVlQmPno  djj&1"PQUVZV`V`QaPb cdd""&77"JJ'!Jd44d;NtTXTjTjOkNlm  djj$/"NtTXT^T^O_N` abb""))*;<JJg&r9   c                    t        | j                  t        j                        r| j                  }nat        | j                  t              r<t        j
                  | j                  D cg c]  }|j                          c}      }nt        d      t        | j                  t        j                        r| j                  }nat        | j                  t              r<t        j
                  | j                  D cg c]  }|j                          c}      }nt        d      t        ||| j                  | j                  | j                        S c c}w c c}w )z.Compute peak signal-to-noise ratio over state.z>Expected sum_squared_error to be a Tensor or a list of Tensorsz2Expected total to be a Tensor or a list of Tensors)r   r   )r1   r#   r3   r   r?   r'   flattenr=   r&   r   r   r   r   )r6   r#   valuer&   s       r8   computezPeakSignalNoiseRatio.compute   s    d,,ell; $ 6 6..5 %		H^H^*_H^u5==?H^*_ `\]]djj%,,/JJE

D)IIDJJGJ5u}}JGHEPQQ.tTYYbfbpbpqq +` Hs   )E;E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 PeakSignalNoiseRatio
            >>> metric = PeakSignalNoiseRatio(data_range=1.0)
            >>> preds = torch.tensor([[0.0, 1.0], [2.0, 3.0]])
            >>> target = torch.tensor([[3.0, 2.0], [1.0, 0.0]])
            >>> metric.update(preds, target)
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> import torch
            >>> from torchmetrics.image import PeakSignalNoiseRatio
            >>> metric = PeakSignalNoiseRatio(data_range=1.0)
            >>> preds = torch.tensor([[0.0, 1.0], [2.0, 3.0]])
            >>> target = torch.tensor([[3.0, 2.0], [1.0, 0.0]])
            >>> values = [ ]
            >>> for _ in range(10):
            ...     values.append(metric(preds, target))
            >>> fig_, ax_ = metric.plot(values)

        )_plot)r6   rG   rH   s      r8   plotzPeakSignalNoiseRatio.plot   s    X zz#r""r9   )g      $@r   N)NN)__name__
__module____qualname____doc__r   bool__annotations__r   r   r   r5   r   r   r2   r
   r   intr   r.   rB   rF   r   r   r   rK   __classcell__)r7   s   @r8   r   r       s$   (T #t"!d!#t#!e!
 FX59D%ue|!445D D BC	D
 eCsCx012D D 
D>'F 'F 't '6r r& _c,#E&(6*:":;<,#IQRZI[,#	,#r9   r   )collections.abcr   	functoolsr   typingr   r   r   r3   r   r	   typing_extensionsr
   "torchmetrics.functional.image.psnrr   r   torchmetrics.metricr   torchmetrics.utilitiesr   torchmetrics.utilities.importsr   torchmetrics.utilities.plotr   r   __doctest_skip__r   r,   r9   r8   <module>r^      sE    %  ' '    % J & 1 @ @34i#6 i#r9   