a
    d.!                     @   s   d dl mZ d dlmZmZ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sdgZG dd deZdS )    )partial)AnyOptionalSequenceTupleUnionN)Tensortensor)Literal)_psnr_compute_psnr_update)Metric)rank_zero_warn)_MATPLOTLIB_AVAILABLE)_AX_TYPE_PLOT_OUT_TYPEPeakSignalNoiseRatio.plotc                
       s   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	< eed
< deee
ee
e
f f  e
ed eeeeedf f  edd fddZeeddddZedddZdeeeee f  ee edddZ  ZS )PeakSignalNoiseRatioa
  `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 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.
        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.

    Raises:
        ValueError:
            If ``dim`` is not ``None`` and ``data_range`` is not given.

    Example:
        >>> from torchmetrics.image import PeakSignalNoiseRatio
        >>> psnr = PeakSignalNoiseRatio()
        >>> 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
min_target
max_targetN      $@elementwise_mean)r   sumnoneN.)
data_rangebase	reductiondimkwargsreturnc                    s`  t  jf i | |d u r2|dkr2td| d |d u rd| jdtddd | jdtd	dd n | jdg d
d | jdg d
d d | _|d u r|d urtdd | _| jdtdtj	d | jdtdtj
d n`t|tr| jdt|d |d	  dd ttj|d	 |d d| _n| jdtt|dd || _|| _t|trVt|n|| _d S )Nr   zThe `reduction=z.` will not have any effect when `dim` is None.sum_squared_errorr   r   )defaultZdist_reduce_fxtotalr   catz6The `data_range` must be given when `dim` is not None.r   r   r      mean)minmax)super__init__r   Z	add_stater	   clamping_fn
ValueErrorr   torchr+   r,   
isinstancetupler   clampfloatr    r!   r   r"   )selfr   r    r!   r"   r#   	__class__ `/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torchmetrics/image/psnr.pyr.   V   s,     zPeakSignalNoiseRatio.__init__)predstargetr$   c                 C   s   | j dur|  |}|  |}t||| jd\}}| jdu r| jdu rnt| | j| _t|	 | j
| _
|  j|7  _|  j|7  _n| j| | j| dS )z*Update state with predictions and targets.N)r"   )r/   r   r"   r   r1   Zminimumr+   r   maximumr,   r   r%   r'   append)r6   r;   r<   r%   Zn_obsr9   r9   r:   update}   s    




zPeakSignalNoiseRatio.update)r$   c                 C   sv   | j dur| j n
| j| j }| jdu r4| j}| j}n,tdd | jD }tdd | jD }t|||| j	| j
dS )z.Compute peak signal-to-noise ratio over state.Nc                 S   s   g | ]}|  qS r9   flatten.0valuesr9   r9   r:   
<listcomp>       z0PeakSignalNoiseRatio.compute.<locals>.<listcomp>c                 S   s   g | ]}|  qS r9   r@   rB   r9   r9   r:   rE      rF   )r    r!   )r   r   r   r"   r%   r'   r1   r(   r   r    r!   )r6   r   r%   r'   r9   r9   r:   compute   s    
zPeakSignalNoiseRatio.compute)valaxr$   c                 C   s   |  ||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()
            >>> 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()
            >>> 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)

        )Z_plot)r6   rH   rI   r9   r9   r:   plot   s    ,r   )Nr   r   N)NN)__name__
__module____qualname____doc__r   bool__annotations__r   r   r   r5   r   r   r   r   r
   intr   r.   r?   rG   r   r   r   rJ   __classcell__r9   r9   r7   r:   r      s4   
.    ' r   )	functoolsr   typingr   r   r   r   r   r1   r   r	   Ztyping_extensionsr
   Z"torchmetrics.functional.image.psnrr   r   Ztorchmetrics.metricr   Ztorchmetrics.utilitiesr   Ztorchmetrics.utilities.importsr   Ztorchmetrics.utilities.plotr   r   Z__doctest_skip__r   r9   r9   r9   r:   <module>   s   