a
    d                     @   s  d dl Z d dl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 d dlmZ d dlmZmZ d dlmZ dZeeee f ed	d
dZeed	ddZeed	ddZeed	ddZeed	ddZeed	ddZeeeef d	ddZd2eee edddZd3eeeedddZ d4eeedd d!Z!eed	d"d#Z"eed$d%d&Z#d5eee ed'd(d)Z$d6eee ee	j% ed*d+d,Z&eed	d-d.Z'eeed/d0d1Z(dS )7    N)AnyDictListOptionalSequenceTupleUnion)apply_to_collection)Tensor)TorchMetricsUserWarning)_TORCH_GREATER_EQUAL_1_12_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   d/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torchmetrics/utilities/data.py
<listcomp>        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   s   t j| ddS )z#Summation along the zero dimension.r   r   )r   sumr!   r   r   r   dim_zero_sum&   s    r$   c                 C   s   t j| ddS )z!Average along the zero dimension.r   r   )r   meanr!   r   r   r   dim_zero_mean+   s    r&   c                 C   s   t j| ddjS )zMax along the zero dimension.r   r   )r   maxvaluesr!   r   r   r   dim_zero_max0   s    r)   c                 C   s   t j| ddjS )zMin along the zero dimension.r   r   )r   minr(   r!   r   r   r   dim_zero_min5   s    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   Zsublistitemr   r   r   r   <   r   z_flatten.<locals>.<listcomp>r   r!   r   r   r   _flatten:   s    r-   c                 C   sh   i }d}|   D ]N\}}t|trJ|  D ]\}}||v r>d}|||< q*q||v rVd}|||< q||fS )zYFlatten dict of dicts into single dict and checking for duplicates in keys along the way.FT)itemsr   dict)r   Znew_dict
duplicateskeyvaluekvr   r   r   _flatten_dict?   s    

r5   )label_tensornum_classesr   c                 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shaper8   r9   longr   Z	expand_asZscatter_)r6   r7   Ztensor_onehotindexr   r   r   	to_onehotP   s    rA   r   )prob_tensortopkr   r   c                 C   sN   t | }|dkr,||| j|ddd}n||| j||dj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   T)r   Zkeepdimr:   )r3   r   )r   Z
zeros_likeZscatterargmaxrC   indicesr;   )rB   rC   r   r=   Ztopk_tensorr   r   r   select_topks   s
    
rF   )r   
argmax_dimr   c                 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   rD   )r   rG   r   r   r   to_categorical   s    rH   c                 C   s   |   dkr|  S | S )Nr   )r   Zsqueezer!   r   r   r   _squeeze_scalar_element_tensor   s    rI   )datar   c                 C   s   t | ttS )N)r	   r
   rI   )rJ   r   r   r   _squeeze_if_scalar   s    rK   )r   	minlengthr   c                 C   sp   |du rt t| }t s,ts,trb| jrbtj|| jtj	d}t
|D ]}| |k ||< qH|S tj| |dS )a	  Implement custom bincount.

    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

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

    N)r9   r8   rL   )lenr   unique$are_deterministic_algorithms_enabledr   r   Zis_mpsr=   r9   r?   ranger#   Zbincount)r   rL   outputir   r   r   	_bincount   s    rT   )r   r   r8   r   c                 C   sP   t  r@| jr@|  r@tjdkr@tdt |  j	||d
 S t j	| ||dS )N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   r8   )r   rP   Zis_cudaZis_floating_pointsysplatformr   r   cpuZcumsumZcuda)r   r   r8   r   r   r   _cumsum   s     rY   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   rM   )r*   r   rO   rT   r'   )r   Zunique_xrR   r   r   r   _flexible_bincount   s    
rZ   )tensor1tensor2r   c                 C   s&   | j |j kr|j| j d}t| |S )z:Wrap torch.allclose to be robust towards dtype difference.)r8   )r8   tor   allclose)r[   r\   r   r   r   r^      s    r^   )N)r   r   )r   )N)r   N))rV   typingr   r   r   r   r   r   r   r   Zlightning_utilitiesr	   r
   Z!torchmetrics.utilities.exceptionsr   Ztorchmetrics.utilities.importsr   r   Ztorchmetrics.utilities.printsr   Z
METRIC_EPSr"   r$   r&   r)   r+   listr-   boolr5   r;   rA   rF   rH   rI   rK   rT   r8   rY   rZ   r^   r   r   r   r   <module>   s:   $
 #! 