o
    .win                     @   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 d dlmZ d dlmZ d d	lmZ d d
lmZmZ d dlmZ esNg dZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZ dS )    )Sequence)AnyCallableOptionalUnionN)Tensor)Literal)Metric)rank_zero_warn)dim_zero_cat)_MATPLOTLIB_AVAILABLE)_AX_TYPE_PLOT_OUT_TYPE)Running)SumMetric.plotMeanMetric.plotMaxMetric.plotMinMetric.plotc                       s   e Zd ZU dZdZdZdZeed< 		dde	e
ef de	eef d	e	ed
 ef dededdf fddZ	dde	eef dee	eef  deeef fddZde	eef ddfddZdefddZ  ZS )BaseAggregatorae  Base class for aggregation metrics.

    Args:
        fn: string specifying the reduction function
        default_value: default tensor value to use for the metric state
        nan_strategy: options:
            - ``'error'``: if any `nan` values are encountered will give a RuntimeError
            - ``'warn'``: if any `nan` values are encountered will give a warning and continue
            - ``'ignore'``: all `nan` values are silently removed
            - ``'disable'``: disable all `nan` checks
            - a float: if a float is provided will impute any `nan` values with this value

        state_name: name of the metric state
        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Raises:
        ValueError:
            If ``nan_strategy`` is not one of ``error``, ``warn``, ``ignore``, ``disable`` or a float

    NFfull_state_updateerrorvaluefndefault_valuenan_strategyr   warnignoredisable
state_namekwargsreturnc                    s^   t  jdi | d}||vrt|tstd| d| d|| _| j|||d || _d S )Nr   z6Arg `nan_strategy` should either be a float or one of z	 but got .defaultdist_reduce_fx )super__init__
isinstancefloat
ValueErrorr   	add_stater   )selfr   r   r   r   r    allowed_nan_strategy	__class__r&   U/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/aggregation.pyr(   :   s   
zBaseAggregator.__init__xweightc                 C   s<  t |tstj|| j| jd}|dur"t |ts"tj|| j| jd}| jdkrt|}|dur6t|}nt|	 }t
|}| sJ| r| jdkrStd| jdv rq| jdkrbtdt |||B   }|||B   }n!t | jtstd	| j | j|||B < d
|||B < nt
|}|| j|| jfS )z3Convert input ``x`` to a tensor and check for Nans.dtypedeviceNr   r   z"Encountered `nan` values in tensor)r   r   r   z4Encountered `nan` values in tensor. Will be removed.z+`nan_strategy` shall be float but you pass    )r)   r   torch	as_tensorr5   r6   r   isnan
zeros_likebool	ones_likeanyRuntimeErrorr
   UserWarningr*   r+   to)r-   r2   r3   nansnans_weightr&   r&   r1   _cast_and_nan_check_inputM   s2   








z(BaseAggregator._cast_and_nan_check_inputc                 C   s   dS )zOverwrite in child class.Nr&   )r-   r   r&   r&   r1   updaten   s    zBaseAggregator.updatec                 C   s   t | | jS zCompute the aggregated value.)getattrr   r-   r&   r&   r1   computeq      zBaseAggregator.compute)r   r   N)__name__
__module____qualname____doc__is_differentiablehigher_is_betterr   r<   __annotations__r   r   strr   listr   r*   r   r(   r   tuplerD   rE   rI   __classcell__r&   r&   r/   r1   r       s<   
 




!r   c                          e Zd ZU dZdZeed< eed< 	ddee	d e
f ded	d
f fddZdee
ef d	d
fddZ	
ddeeeee f  dee d	efddZ  ZS )	MaxMetrica}  Aggregate a stream of value into their maximum value.

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

    - ``value`` (:class:`~float` or :class:`~torch.Tensor`): a single float or an tensor of float values with
      arbitrary shape ``(...,)``.

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

    - ``agg`` (:class:`~torch.Tensor`): scalar float tensor with aggregated maximum value over all inputs received

    Args:
        nan_strategy: options:
            - ``'error'``: if any `nan` values are encountered will give a RuntimeError
            - ``'warn'``: if any `nan` values are encountered will give a warning and continue
            - ``'ignore'``: all `nan` values are silently removed
            - ``'disable'``: disable all `nan` checks
            - a float: if a float is provided will impute any `nan` values with this value

        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Raises:
        ValueError:
            If ``nan_strategy`` is not one of ``error``, ``warn``, ``ignore``, ``disable`` or a float

    Example:
        >>> from torch import tensor
        >>> from torchmetrics.aggregation import MaxMetric
        >>> metric = MaxMetric()
        >>> metric.update(1)
        >>> metric.update(tensor([2, 3]))
        >>> metric.compute()
        tensor(3.)

    Tr   	max_valuer   r   r   r    r!   Nc                    s4   t  jdtjtdt d |fddi| d S )Nmaxinfr5   r   rY   r'   r(   r8   tensorr*   get_default_dtyper-   r   r    r/   r&   r1   r(      s   
zMaxMetric.__init__r   c                 C   4   |  |\}}| rt| jt|| _dS dS zUpdate state with data.

        Args:
            value: Either a float or tensor containing data. Additional tensor
                dimensions will be flattened

        N)rD   numelr8   rZ   rY   r-   r   _r&   r&   r1   rE         zMaxMetric.update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
            >>> from torchmetrics.aggregation import MaxMetric
            >>> metric = MaxMetric()
            >>> metric.update([1, 2, 3])
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> from torchmetrics.aggregation import MaxMetric
            >>> metric = MaxMetric()
            >>> values = [ ]
            >>> for i in range(10):
            ...     values.append(metric(i))
            >>> fig_, ax_ = metric.plot(values)

        _plotr-   rg   rh   r&   r&   r1   plot      &r   r   NNrL   rM   rN   rO   r   r<   rR   r   r   r   r*   r   r(   rE   r   r   r   r   rm   rV   r&   r&   r/   r1   rX   v   *   
 $rX   c                       rW   )	MinMetrica}  Aggregate a stream of value into their minimum value.

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

    - ``value`` (:class:`~float` or :class:`~torch.Tensor`): a single float or an tensor of float values with
      arbitrary shape ``(...,)``.

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

    - ``agg`` (:class:`~torch.Tensor`): scalar float tensor with aggregated minimum value over all inputs received

    Args:
        nan_strategy: options:
            - ``'error'``: if any `nan` values are encountered will give a RuntimeError
            - ``'warn'``: if any `nan` values are encountered will give a warning and continue
            - ``'ignore'``: all `nan` values are silently removed
            - ``'disable'``: disable all `nan` checks
            - a float: if a float is provided will impute any `nan` values with this value

        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Raises:
        ValueError:
            If ``nan_strategy`` is not one of ``error``, ``warn``, ``ignore``, ``disable`` or a float

    Example:
        >>> from torch import tensor
        >>> from torchmetrics.aggregation import MinMetric
        >>> metric = MinMetric()
        >>> metric.update(1)
        >>> metric.update(tensor([2, 3]))
        >>> metric.compute()
        tensor(1.)

    Tr   	min_valuer   r   r   r    r!   Nc                    s2   t  jdtjtdt d|fddi| d S )Nminr[   r\   r   rt   r]   r`   r/   r&   r1   r(     s   
zMinMetric.__init__r   c                 C   ra   rb   )rD   rc   r8   ru   rt   rd   r&   r&   r1   rE     rf   zMinMetric.updaterg   rh   c                 C   ri   )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 torchmetrics.aggregation import MinMetric
            >>> metric = MinMetric()
            >>> metric.update([1, 2, 3])
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> from torchmetrics.aggregation import MinMetric
            >>> metric = MinMetric()
            >>> values = [ ]
            >>> for i in range(10):
            ...     values.append(metric(i))
            >>> fig_, ax_ = metric.plot(values)

        rj   rl   r&   r&   r1   rm   !  rn   r   ro   rp   rq   r&   r&   r/   r1   rs      rr   rs   c                       s   e Zd ZU dZeed< 	ddeed ef de	ddf fd	d
Z
deeef ddfddZ	ddeeeee f  dee defddZ  ZS )	SumMetricai  Aggregate a stream of value into their sum.

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

    - ``value`` (:class:`~float` or :class:`~torch.Tensor`): a single float or an tensor of float values with
      arbitrary shape ``(...,)``.

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

    - ``agg`` (:class:`~torch.Tensor`): scalar float tensor with aggregated sum over all inputs received

    Args:
        nan_strategy: options:
            - ``'error'``: if any `nan` values are encountered will give a RuntimeError
            - ``'warn'``: if any `nan` values are encountered will give a warning and continue
            - ``'ignore'``: all `nan` values are silently removed
            - ``'disable'``: disable all `nan` checks
            - a float: if a float is provided will impute any `nan` values with this value

        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Raises:
        ValueError:
            If ``nan_strategy`` is not one of ``error``, ``warn``, ``ignore``, ``disable`` or a float

    Example:
        >>> from torch import tensor
        >>> from torchmetrics.aggregation import SumMetric
        >>> metric = SumMetric()
        >>> metric.update(1)
        >>> metric.update(tensor([2, 3]))
        >>> metric.compute()
        tensor(6.)

    	sum_valuer   r   r   r    r!   Nc                    s.   t  jdtjdt d|fddi| d S )Nsum        r\   r   rw   )r'   r(   r8   r^   r_   r`   r/   r&   r1   r(   q  s   
zSumMetric.__init__r   c                 C   s0   |  |\}}| r|  j| 7  _dS dS rb   )rD   rc   rw   rx   rd   r&   r&   r1   rE   ~  s   zSumMetric.updaterg   rh   c                 C   ri   )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 torchmetrics.aggregation import SumMetric
            >>> metric = SumMetric()
            >>> metric.update([1, 2, 3])
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> from torch import rand, randint
            >>> from torchmetrics.aggregation import SumMetric
            >>> metric = SumMetric()
            >>> values = [ ]
            >>> for i in range(10):
            ...     values.append(metric([i, i+1]))
            >>> fig_, ax_ = metric.plot(values)

        rj   rl   r&   r&   r1   rm     s   'r   ro   rp   )rL   rM   rN   rO   r   rR   r   r   r*   r   r(   rE   r   r   r   r   rm   rV   r&   r&   r/   r1   rv   J  s(   
 $rv   c                       sp   e Zd ZU dZeed< 	ddeed ef de	ddf fd	d
Z
deeef ddfddZdefddZ  ZS )	CatMetricak  Concatenate a stream of values.

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

    - ``value`` (:class:`~float` or :class:`~torch.Tensor`): a single float or an tensor of float values with
      arbitrary shape ``(...,)``.

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

    - ``agg`` (:class:`~torch.Tensor`): scalar float tensor with concatenated values over all input received

    Args:
        nan_strategy: options:
            - ``'error'``: if any `nan` values are encountered will give a RuntimeError
            - ``'warn'``: if any `nan` values are encountered will give a warning and continue
            - ``'ignore'``: all `nan` values are silently removed
            - ``'disable'``: disable all `nan` checks
            - a float: if a float is provided will impute any `nan` values with this value

        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Raises:
        ValueError:
            If ``nan_strategy`` is not one of ``error``, ``warn``, ``ignore``, ``disable`` or a float

    Example:
        >>> from torch import tensor
        >>> from torchmetrics.aggregation import CatMetric
        >>> metric = CatMetric()
        >>> metric.update(1)
        >>> metric.update(tensor([2, 3]))
        >>> metric.compute()
        tensor([1., 2., 3.])

    r   r   r   r   r    r!   Nc                    s   t  jdg |fi | d S )Ncat)r'   r(   r`   r/   r&   r1   r(     s   zCatMetric.__init__c                 C   s*   |  |\}}| r| j| dS dS rb   )rD   rc   r   appendrd   r&   r&   r1   rE     s   zCatMetric.updatec                 C   s"   t | jtr| jrt| jS | jS rF   )r)   r   rT   r   rH   r&   r&   r1   rI     s   
zCatMetric.computero   )rL   rM   rN   rO   r   rR   r   r   r*   r   r(   rE   rI   rV   r&   r&   r/   r1   rz     s   
 $rz   c                       s   e Zd ZU dZeed< eed< 	ddeed ef de	dd	f fd
dZ
ddeeef deeed	f 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 )
MeanMetrica-  Aggregate a stream of value into their mean value.

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

    - ``value`` (:class:`~float` or :class:`~torch.Tensor`): a single float or an tensor of float values with
      arbitrary shape ``(...,)``.
    - ``weight`` (:class:`~float` or :class:`~torch.Tensor`): a single float or an tensor of float value with
      arbitrary shape ``(...,)``. Needs to be broadcastable with the shape of ``value`` tensor.

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

    - ``agg`` (:class:`~torch.Tensor`): scalar float tensor with aggregated (weighted) mean over all inputs received

    Args:
        nan_strategy: options:
            - ``'error'``: if any `nan` values are encountered will give a RuntimeError
            - ``'warn'``: if any `nan` values are encountered will give a warning and continue
            - ``'ignore'``: all `nan` values are silently removed
            - ``'disable'``: disable all `nan` checks
            - a float: if a float is provided will impute any `nan` values with this value

        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Raises:
        ValueError:
            If ``nan_strategy`` is not one of ``error``, ``warn``, ``ignore``, ``disable`` or a float

    Example:
        >>> from torchmetrics.aggregation import MeanMetric
        >>> metric = MeanMetric()
        >>> metric.update(1)
        >>> metric.update(torch.tensor([2, 3]))
        >>> metric.compute()
        tensor(2.)

    
mean_valuer3   r   r   r   r    r!   Nc                    sL   t  jdtjdt d|fddi| | jdtjdt ddd d S )Nrx   ry   r\   r   r~   r3   r#   )r'   r(   r8   r^   r_   r,   r`   r/   r&   r1   r(     s   "zMeanMetric.__init__r   c                 C   s   t |tstj|| j| jd}|du rt|}nt |ts(tj|| j| jd}t||j}| 	||\}}|
 dkr?dS |  j||  7  _|  j| 7  _dS )a  Update state with data.

        Args:
            value: Either a float or tensor containing data. Additional tensor
                dimensions will be flattened
            weight: Either a float or tensor containing weights for calculating
                the average. Shape of weight should be able to broadcast with
                the shape of `value`. Default to None corresponding to simple
                harmonic average.

        r4   Nr   )r)   r   r8   r9   r5   r6   r=   broadcast_toshaperD   rc   r~   rx   r3   )r-   r   r3   r&   r&   r1   rE   ,  s   

zMeanMetric.updatec                 C   s   | j | j S rF   )r~   r3   rH   r&   r&   r1   rI   G  rJ   zMeanMetric.computerg   rh   c                 C   ri   )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 torchmetrics.aggregation import MeanMetric
            >>> metric = MeanMetric()
            >>> metric.update([1, 2, 3])
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> # Example plotting multiple values
            >>> from torchmetrics.aggregation import MeanMetric
            >>> metric = MeanMetric()
            >>> values = [ ]
            >>> for i in range(10):
            ...     values.append(metric([i, i+1]))
            >>> fig_, ax_ = metric.plot(values)

        rj   rl   r&   r&   r1   rm   K  rn   r   ro   rK   rp   )rL   rM   rN   rO   r   rR   r   r   r*   r   r(   rE   rI   r   r   r   r   rm   rV   r&   r&   r/   r1   r}     s,   
 %*r}   c                	       D   e Zd ZdZ		ddedeed ef dedd	f fd
dZ	  Z
S )RunningMeanai	  Aggregate a stream of value into their mean over a running window.

    Using this metric compared to `MeanMetric` allows for calculating metrics over a running window of values, instead
    of the whole history of values. This is beneficial when you want to get a better estimate of the metric during
    training and don't want to wait for the whole training to finish to get epoch level estimates.

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

    - ``value`` (:class:`~float` or :class:`~torch.Tensor`): a single float or an tensor of float values with
      arbitrary shape ``(...,)``.

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

    - ``agg`` (:class:`~torch.Tensor`): scalar float tensor with aggregated sum over all inputs received

    Args:
        nan_strategy: options:
            - ``'error'``: if any `nan` values are encountered will give a RuntimeError
            - ``'warn'``: if any `nan` values are encountered will give a warning and continue
            - ``'ignore'``: all `nan` values are silently removed
            - ``'disable'``: disable all `nan` checks
            - a float: if a float is provided will impute any `nan` values with this value

        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Raises:
        ValueError:
            If ``nan_strategy`` is not one of ``error``, ``warn``, ``ignore``, ``disable`` or a float

    Example:
        >>> from torch import tensor
        >>> from torchmetrics.aggregation import RunningMean
        >>> metric = RunningMean(window=3)
        >>> for i in range(6):
        ...     current_val = metric(tensor([i]))
        ...     running_val = metric.compute()
        ...     total_val = tensor(sum(list(range(i+1)))) / (i+1)  # total mean over all samples
        ...     print(f"{current_val=}, {running_val=}, {total_val=}")
        current_val=tensor(0.), running_val=tensor(0.), total_val=tensor(0.)
        current_val=tensor(1.), running_val=tensor(0.5000), total_val=tensor(0.5000)
        current_val=tensor(2.), running_val=tensor(1.), total_val=tensor(1.)
        current_val=tensor(3.), running_val=tensor(2.), total_val=tensor(1.5000)
        current_val=tensor(4.), running_val=tensor(3.), total_val=tensor(2.)
        current_val=tensor(5.), running_val=tensor(4.), total_val=tensor(2.5000)

       r   windowr   r   r    r!   Nc                    "   t  jtdd|i||d d S Nr   )base_metricr   r&   )r'   r(   r}   r-   r   r   r    r/   r&   r1   r(        "zRunningMean.__init__r   r   rL   rM   rN   rO   intr   r   r*   r   r(   rV   r&   r&   r/   r1   r   t  s    1r   c                	       r   )
RunningSumay	  Aggregate a stream of value into their sum over a running window.

    Using this metric compared to `SumMetric` allows for calculating metrics over a running window of values, instead
    of the whole history of values. This is beneficial when you want to get a better estimate of the metric during
    training and don't want to wait for the whole training to finish to get epoch level estimates.

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

    - ``value`` (:class:`~float` or :class:`~torch.Tensor`): a single float or an tensor of float values with
      arbitrary shape ``(...,)``.

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

    - ``agg`` (:class:`~torch.Tensor`): scalar float tensor with aggregated sum over all inputs received

    Args:
        window: The size of the running window.
        nan_strategy: options:
            - ``'error'``: if any `nan` values are encountered will give a RuntimeError
            - ``'warn'``: if any `nan` values are encountered will give a warning and continue
            - ``'ignore'``: all `nan` values are silently removed
            - ``'disable'``: disable all `nan` checks
            - a float: if a float is provided will impute any `nan` values with this value

        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Raises:
        ValueError:
            If ``nan_strategy`` is not one of ``error``, ``warn``, ``ignore``, ``disable`` or a float

    Example:
        >>> from torch import tensor
        >>> from torchmetrics.aggregation import RunningSum
        >>> metric = RunningSum(window=3)
        >>> for i in range(6):
        ...     current_val = metric(tensor([i]))
        ...     running_val = metric.compute()
        ...     total_val = tensor(sum(list(range(i+1))))  # total sum over all samples
        ...     print(f"{current_val=}, {running_val=}, {total_val=}")
        current_val=tensor(0.), running_val=tensor(0.), total_val=tensor(0)
        current_val=tensor(1.), running_val=tensor(1.), total_val=tensor(1)
        current_val=tensor(2.), running_val=tensor(3.), total_val=tensor(3)
        current_val=tensor(3.), running_val=tensor(6.), total_val=tensor(6)
        current_val=tensor(4.), running_val=tensor(9.), total_val=tensor(10)
        current_val=tensor(5.), running_val=tensor(12.), total_val=tensor(15)

    r   r   r   r   r   r    r!   Nc                    r   r   )r'   r(   rv   r   r/   r&   r1   r(     r   zRunningSum.__init__r   r   r&   r&   r/   r1   r     s    2r   )!collections.abcr   typingr   r   r   r   r8   r   typing_extensionsr   torchmetrics.metricr	   torchmetrics.utilitiesr
   torchmetrics.utilities.datar   torchmetrics.utilities.importsr   torchmetrics.utilities.plotr   r   torchmetrics.wrappers.runningr   __doctest_skip__r   rX   rs   rv   rz   r}   r   r   r&   r&   r&   r1   <module>   s*   VjjjA9