o
    .wi)&                     @   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
mZ d dlmZ d dlmZ d dlmZmZ es=d	gZ	
ddejdejdejdejdejdejdejdejdedeejejejejejejejejf fddZG dd deZdS )    )Sequence)AnyListOptionalUnionN)Tensor)_pearson_corrcoef_compute_pearson_corrcoef_update)Metric)_MATPLOTLIB_AVAILABLE)_AX_TYPE_PLOT_OUT_TYPEPearsonCorrCoef.plot绽|=means_xmeans_y
maxs_abs_x
maxs_abs_yvars_xvars_ycorrs_xynbsepsreturnc	           %   	   C   s  t | dkr | d |d |d |d |d |d |d |d fS | d }	|d }
|d }|d }|d }|d }|d }|d }tdt | D ]}| | }|| }|| }|| }|| }|| }|| }|| }tt|||| |}||	 ||  | }||
 ||  | }|| | }||	 }||
 }|| ||d   } || ||d   }!|| || |  }"t||}#t||}$|}	|}
|#}|$}| }|!}|"}|}qG|||#|$| |!|"|fS )a  Aggregate the statistics from multiple devices.

    Formula taken from here: `Parallel algorithm for calculating variance
    <https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Parallel_algorithm>`_

    We use `eps` to avoid division by zero when `n1` and `n2` are both zero. Generally, the value of `eps` should not
    matter, as if `n1` and `n2` are both zero, all the states will also be zero.

       r      )lenrangetorchwhere
logical_ormaximum)%r   r   r   r   r   r   r   r   r   mx1my1max1may1vx1vy1cxy1n1imx2my2max2may2vx2vy2cxy2n2nbmean_xmean_yn12_bdelta_xdelta_yvar_xvar_ycorr_xymax_abs_dev_xmax_abs_dev_y r>   \/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/regression/pearson.py_final_aggregation   sN   4r@   c                       s  e Zd ZU dZdZeed< dZe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< eed< eed< eed< eed< eed< eed< eed< eed< 	d#de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 )%PearsonCorrCoefa  Compute `Pearson Correlation Coefficient`_.

    .. math::
        P_{corr}(x,y) = \frac{cov(x,y)}{\sigma_x \sigma_y}

    Where :math:`y` is a tensor of target values, and :math:`x` is a tensor of predictions.

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

    - ``preds`` (:class:`~torch.Tensor`): either single output float tensor with shape ``(N,)``
      or multioutput float tensor of shape ``(N,d)``
    - ``target`` (:class:`~torch.Tensor`): either single output tensor with shape ``(N,)``
      or multioutput tensor of shape ``(N,d)``

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

    - ``pearson`` (:class:`~torch.Tensor`): A tensor with the Pearson Correlation Coefficient

    Args:
        num_outputs: Number of outputs in multioutput setting
        kwargs: Additional keyword arguments, see :ref:`Metric kwargs` for more info.

    Example (single output regression):
        >>> from torchmetrics.regression import PearsonCorrCoef
        >>> target = torch.tensor([3, -0.5, 2, 7])
        >>> preds = torch.tensor([2.5, 0.0, 2, 8])
        >>> pearson = PearsonCorrCoef()
        >>> pearson(preds, target)
        tensor(0.9849)

    Example (multi output regression):
        >>> from torchmetrics.regression import PearsonCorrCoef
        >>> target = torch.tensor([[3, -0.5], [2, 7]])
        >>> preds = torch.tensor([[2.5, 0.0], [2, 8]])
        >>> pearson = PearsonCorrCoef(num_outputs=2)
        >>> pearson(preds, target)
        tensor([1., 1.])

    Tis_differentiableNhigher_is_betterfull_state_updateg      plot_lower_boundg      ?plot_upper_boundpredstargetr4   r5   r<   r=   r9   r:   r;   n_totalr   num_outputskwargsr   c                    s   t  jdi | t|ts|dk rtd|| _| jdt| jd d | jdt| jd d | jdt| jd d | jdt| jd d | jdt| jd d | jd	t| jd d | jd
t| jd d | jdt| jd d d S )Nr   zQExpected argument `num_outputs` to be an int larger than 0, but got {num_outputs}r4   )defaultdist_reduce_fxr5   r<   r=   r9   r:   r;   rI   r>   )	super__init__
isinstanceint
ValueErrorrJ   	add_stater   zeros)selfrJ   rK   	__class__r>   r?   rO      s   zPearsonCorrCoef.__init__c                 C   sT   t ||| j| j| j| j| j| j| j| j| j	d\| _| _| _| _| _| _| _| _dS )z*Update state with predictions and targets.)rG   rH   r4   r5   r<   r=   r9   r:   r;   	num_priorrJ   N)
r	   r4   r5   r<   r=   r9   r:   r;   rI   rJ   )rU   rG   rH   r>   r>   r?   update   s,   zPearsonCorrCoef.updatec              
   C   s   | j dkr| j dks| j dkr4| jjdkr4t| j| j| j| j| j| j	| j
| jd\}}}}}}}}n| j}| j}| j}| j	}| j
}| j}t||||||S )z3Compute pearson correlation coefficient over state.r   )r   r   r   r   r   r   r   r   )rJ   r4   numelndimr@   r5   r<   r=   r9   r:   r;   rI   r   )rU   _r<   r=   r9   r:   r;   rI   r>   r>   r?   compute   s$   .zPearsonCorrCoef.computevalaxc                 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

            >>> from torch import randn
            >>> # Example plotting a single value
            >>> from torchmetrics.regression import PearsonCorrCoef
            >>> metric = PearsonCorrCoef()
            >>> metric.update(randn(10,), randn(10,))
            >>> fig_, ax_ = metric.plot()

        .. plot::
            :scale: 75

            >>> from torch import randn
            >>> # Example plotting multiple values
            >>> from torchmetrics.regression import PearsonCorrCoef
            >>> metric = PearsonCorrCoef()
            >>> values = []
            >>> for _ in range(10):
            ...     values.append(metric(randn(10,), randn(10,)))
            >>> fig, ax = metric.plot(values)

        )_plot)rU   r^   r_   r>   r>   r?   plot   s   (r   )r   )NN)__name__
__module____qualname____doc__rB   bool__annotations__rC   r   rD   rE   floatrF   r   r   rQ   r   rO   rY   r]   r   r   r   r   ra   __classcell__r>   r>   rV   r?   rA   d   sF   
 (rA   )r   )collections.abcr   typingr   r   r   r   r   r   *torchmetrics.functional.regression.pearsonr   r	   torchmetrics.metricr
   torchmetrics.utilities.importsr   torchmetrics.utilities.plotr   r   __doctest_skip__rh   tupler@   rA   r>   r>   r>   r?   <module>   sF   	
"
G