o
    yi                      @   s  d dl mZmZmZmZ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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fddZ	d9d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
fd!d"Zdd#d$ed%eeef d&ed'ed(eeeef  d)edefd*d+Zde
de
fd,d-Zd$edefd.d/Zd9de
d0ee de
fd1d2Z de
de
fd3d4Z!d5e
d6e
de"fd7d8Z#dS )<    )AnyCallableDictListMappingOptionalSequenceUnionN)Tensor)_TORCH_GREATER_EQUAL_1_12_XLA_AVAILABLEgư>xreturnc                 C   s@   t | ttfr	| n| g} 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   O/home/ubuntu/.local/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listtuple
ValueErrortorch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_max+      r+   c                 C   r(   )zMin along the zero dimension.r   r   )r   minr*   r    r   r   r   dim_zero_min0   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   7   s    z_flatten.<locals>.<listcomp>r   r    r   r   r   _flatten5   r%   r1   c                 C   sH   i }|   D ]\}}t|tr|  D ]\}}|||< qq|||< q|S )z'Flatten dict of dicts into single dict.)itemsr   dict)r   new_dictkeyvaluekvr   r   r   _flatten_dict:   s   


r9   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  Converts 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)   detachr0   r   zerosshaper<   r=   longr   	expand_asscatter_)r:   r;   tensor_onehotindexr   r   r   	to_onehotF   s   rH   r   prob_tensortopkr   c                 C   sT   t | }|dkr||| j|ddd}| S ||| j||djd}| S )av  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   T)r   keepdimr>   )r7   r   )r   
zeros_likescatterargmaxrJ   indicesr?   )rI   rJ   r   rA   topk_tensorr   r   r   select_topkh   s   
rQ   
argmax_dimc                 C   s   t j| |dS )av  Converts 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   rN   )r   rR   r   r   r   to_categorical   s   rS   )wrong_dtypedatar<   functionargsrT   kwargsc                   s   t | }t| r|du st| |s| g R i S t| tr2| fdd|  D S t| trJt| drJ| fdd| D  S t| trbt| tsb| fdd| D S | S )	a  Recursively applies a function to all elements of a certain dtype.

    Args:
        data: the collection to apply the function to
        dtype: the given function will be applied to all elements of this dtype
        function: the function to apply
        *args: positional arguments (will be forwarded to call of ``function``)
        wrong_dtype: the given function won't be applied if this type is specified and the given collections is of
            the :attr:`wrong_type` even if it is of type :attr`dtype`
        **kwargs: keyword arguments (will be forwarded to call of ``function``)

    Returns:
        the resulting collection

    Example:
        >>> apply_to_collection(torch.tensor([8, 0, 2, 6, 7]), dtype=Tensor, function=lambda x: x ** 2)
        tensor([64,  0,  4, 36, 49])
        >>> apply_to_collection([8, 0, 2, 6, 7], dtype=int, function=lambda x: x ** 2)
        [64, 0, 4, 36, 49]
        >>> apply_to_collection(dict(abc=123), dtype=int, function=lambda x: x ** 2)
        {'abc': 15129}
    Nc                    s,   i | ]\}}|t |g R i qS r   apply_to_collection)r   r7   r8   rW   r<   rV   rX   r   r   
<dictcomp>   s   , z'apply_to_collection.<locals>.<dictcomp>_fieldsc                 3   s*    | ]}t |g R i V  qd S NrY   r   dr[   r   r   	<genexpr>   s   ( z&apply_to_collection.<locals>.<genexpr>c                    s&   g | ]}t |g R i qS r   rY   r_   r[   r   r   r      s   & z'apply_to_collection.<locals>.<listcomp>)typer   r   r2   r   hasattrr   str)rU   r<   rV   rT   rW   rX   	elem_typer   r[   r   rZ      s   
 rZ   c                 C   s   |   dkr
|  S | S )Nr   )r   squeezer    r   r   r   _squeeze_scalar_element_tensor   s   rg   c                 C   s   t | ttS r^   )rZ   r
   rg   )rU   r   r   r   _squeeze_if_scalar   s   rh   	minlengthc                 C   sp   |du rt t| }t ststr1| jr1tj|| jtj	d}t
|D ]
}| |k ||< q$|S tj| |dS )ag  PyTorch currently does not support``torch.bincount`` for:

        - deterministic mode on GPU.
        - MPS devices

    This implementation fallback to a for-loop counting occurrences in that case.

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

    Returns:
        Number of occurrences for each unique element in x
    N)r=   r<   ri   )lenr   unique$are_deterministic_algorithms_enabledr   r   is_mpsrA   r=   rC   ranger#   bincount)r   ri   outputir   r   r   	_bincount   s   rs   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   rj   )r-   r   rl   rs   r)   )r   unique_xrq   r   r   r   _flexible_bincount   s   
ru   tensor1tensor2c                 C   s&   | j |j kr|j| j d}t| |S )zBWrapper of torch.allclose that is robust towards dtype difference.)r<   )r<   tor   allclose)rv   rw   r   r   r   ry      s   ry   r^   )r   r   )r   )$typingr   r   r   r   r   r   r   r	   r   r
   torchmetrics.utilities.importsr   r   
METRIC_EPSr!   r$   r'   r+   r.   r   r1   r9   r?   rH   rQ   rS   rb   r   rZ   rg   rh   rs   ru   boolry   r   r   r   r   <module>   sV   (	
"

2