o
    .wi#                  	   @   s$  d dl Z 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mZ d dlmZ d	Zd
eeee f defddZd
edefddZd
edefddZd
edefddZd
edefddZd
edefddZd
edeeef fddZ	d?dedee defddZ d@d
eded edefd!d"Z!d@d#ed$ed edefd%d&Z"dAd
ed'edefd(d)Z#d
edefd*d+Z$d,edefd-d.Z%d?d
ed/ee defd0d1Z&dBd
ed ee d2eej' defd3d4Z(d
edefd5d6Z)d7ed8edefd9d:Z*d
ed;ed<edefd=d>Z+dS )C    N)Sequence)AnyListOptionalUnion)apply_to_collection)Tensor)TorchMetricsUserWarning)_TORCH_LESS_THAN_2_6_XLA_AVAILABLE)rank_zero_warngư>xreturnc                 C   s8   t | tjr| S dd | D } | stdtj| ddS )z'Concatenation along the zero dimension.c                 S   s0   g | ]}|  d kr|jdkr|dn|qS )   r   )numelndim	unsqueeze).0y r   X/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/utilities/data.py
<listcomp>!   s   0 z dim_zero_cat.<locals>.<listcomp>zNo samples to concatenater   dim)
isinstancetorchr   
ValueErrorcatr   r   r   r   dim_zero_cat   s   r   c                 C      t j| ddS )z#Summation along the zero dimension.r   r   )r   sumr   r   r   r   dim_zero_sum'      r"   c                 C   r    )z!Average along the zero dimension.r   r   )r   meanr   r   r   r   dim_zero_mean,   r#   r%   c                 C      t j| ddjS )zMax along the zero dimension.r   r   )r   maxvaluesr   r   r   r   dim_zero_max1      r)   c                 C   r&   )zMin along the zero dimension.r   r   )r   minr(   r   r   r   r   dim_zero_min6   r*   r,   c                 C   s   dd | D S )z&Flatten list of list into single list.c                 S   s   g | ]	}|D ]}|qqS r   r   )r   sublistitemr   r   r   r   =   s    z_flatten.<locals>.<listcomp>r   r   r   r   r   _flatten;   r#   r/   c                 C   sh   i }d}|   D ]'\}}t|tr%|  D ]\}}||v rd}|||< qq||v r+d}|||< q||fS )zYFlatten dict of dicts into single dict and checking for duplicates in keys along the way.FT)itemsr   dict)r   new_dict
duplicateskeyvaluekvr   r   r   _flatten_dict@   s   


r8   label_tensornum_classesc                 C   sr   |du rt |    d }tj| jd |g| jdd R | j| jd}| 	 
d|}|d|dS )a  Convert  a dense label tensor to one-hot format.

    Args:
        label_tensor: dense label tensor, with shape [N, d1, d2, ...]
        num_classes: number of classes C

    Returns:
        A sparse label tensor with shape [N, C, d1, d2, ...]

    Example:
        >>> x = torch.tensor([1, 2, 3])
        >>> to_onehot(x)
        tensor([[0, 1, 0, 0],
                [0, 0, 1, 0],
                [0, 0, 0, 1]])

    Nr   r   )dtypedevice      ?)intr'   detachr.   r   zerosshaper;   r<   longr   	expand_asscatter_)r9   r:   tensor_onehotindexr   r   r   	to_onehotQ   s   rG   r   r6   r   c                 C   sF   | j tjkr| jstj| |dd|}||d|S | j||djS )z3torch.top_k does not support half precision on CPU.T)r   stabler   r6   r   )	r;   r   halfis_cudaargsortflipnarrowtopkindices)r   r6   r   idxr   r   r   "_top_k_with_half_precision_supportt   s   rR   prob_tensorrO   c                 C   sX   t j| t jd}|dkr||| j|ddd | S ||t| ||dd | S )aw  Convert a probability tensor to binary by selecting top-k the highest entries.

    Args:
        prob_tensor: dense tensor of shape ``[..., C, ...]``, where ``C`` is in the
            position defined by the ``dim`` argument
        topk: number of the highest entries to turn into 1s
        dim: dimension on which to compare entries

    Returns:
        A binary tensor of the same shape as the input tensor of type ``torch.int32``

    Example:
        >>> x = torch.tensor([[1.1, 2.0, 3.0], [2.0, 1.0, 0.5]])
        >>> select_topk(x, topk=2)
        tensor([[0, 1, 1],
                [1, 1, 0]], dtype=torch.int32)

    r;   r   T)r   keepdimr=   rI   )r   
zeros_liker>   rD   argmaxrR   )rS   rO   r   topk_tensorr   r   r   select_topk|   s   rY   
argmax_dimc                 C   s   t j| |dS )aw  Convert  a tensor of probabilities to a dense label tensor.

    Args:
        x: probabilities to get the categorical label [N, d1, d2, ...]
        argmax_dim: dimension to apply

    Return:
        A tensor with categorical labels [N, d2, ...]

    Example:
        >>> x = torch.tensor([[0.2, 0.5], [0.9, 0.1]])
        >>> to_categorical(x)
        tensor([1, 0])

    r   )r   rW   )r   rZ   r   r   r   to_categorical   s   r[   c                 C   s   |   dkr
|  S | S )Nr   )r   squeezer   r   r   r   _squeeze_scalar_element_tensor   s   r]   datac                 C   s   t | ttS N)r   r   r]   )r^   r   r   r   _squeeze_if_scalar   s   r`   	minlengthc                 C   sn   |du rt t| }t sts| jr0tj|| jdt | d}t	| 
dd|jddS tj| |dS )a   Implement custom bincount.

    PyTorch currently does not support ``torch.bincount`` when running in deterministic mode on GPU or when running
    MPS devices or when running on XLA device. This implementation therefore falls back to using a combination of
    `torch.arange` and `torch.eq` in these scenarios. A small performance hit can expected and higher memory consumption
    as `[batch_size, mincount]` tensor needs to be initialized compared to native ``torch.bincount``.

    Args:
        x: tensor to count
        minlength: minimum length to count

    Returns:
        Number of occurrences for each unique element in x

    Example:
        >>> x = torch.tensor([0,0,0,1,1,2,2,2,2])
        >>> _bincount(x, minlength=3)
        tensor([3, 2, 4])

    N)r<   r   r   r   ra   )lenr   unique$are_deterministic_algorithms_enabledr   is_mpsaranger<   repeateqreshaper!   bincount)r   ra   meshr   r   r   	_bincount   s   rn   r;   c                 C   s\   t  o
| jo
|  }tr&|r&tjdkr&tdt | 	 j
||d| jS t j
| ||dS )z\Implement custom cumulative summation for Torch versions which does not support it natively.win32zYou are trying to use a metric in deterministic mode on GPU that uses `torch.cumsum`, which is currently not supported. The tensor will be copied to the CPU memory to compute it and then copied back to GPU. Expect some slowdowns.)r   r;   )r   rf   rK   is_floating_pointr
   sysplatformr   r	   cpucumsumtor<   )r   r   r;   is_cuda_fp_deterministicr   r   r   _cumsum   s   rw   c                 C   s4   | |    } t| }t| t|d d}|| S )zSimilar to `_bincount`, but works also with tensor that do not contain continuous values.

    Args:
        x: tensor to count

    Returns:
        Number of occurrences for each unique element in x

    r   rc   )r+   r   re   rn   r'   )r   unique_xoutputr   r   r   _flexible_bincount   s   
rz   tensor1tensor2c                 C   s&   | j |j kr|j| j d}t| |S )z:Wrap torch.allclose to be robust towards dtype difference.rT   )r;   ru   r   allclose)r{   r|   r   r   r   r}      s   r}   xpfpc                 C   s   t |}|| }|| }|dd |dd  |dd |dd   }t || d }t |dt|d }|| || | ||    S )zInterpolation function comparable to numpy.interp.

    Args:
        x: x-coordinates where to evaluate the interpolated values
        xp: x-coordinates of the data points
        fp: y-coordinates of the data points

    r   Nrb   r   )r   rL   searchsortedclamprd   )r   r~   r   sorted_indicesslopesrP   r   r   r   interp   s   

0r   r_   )r   r   )r   )r   N),rq   collections.abcr   typingr   r   r   r   r   lightning_utilitiesr   r   !torchmetrics.utilities.exceptionsr	   torchmetrics.utilities.importsr
   r   torchmetrics.utilities.printsr   
METRIC_EPSr   r"   r%   r)   r,   listr/   r1   tupleboolr8   r>   rG   rR   rY   r[   r]   r`   rn   r;   rw   rz   r}   r   r   r   r   r   <module>   sF   

#&