o
    {i&                     @   s   d Z ddlZddlmZmZ ddlmZ ddlZddlmZ	 ddl
mZ ddlm  mZ ddlZddlmZ d&ddZdd	 Zd
d Zdee fddZG dd deZe d'ddZd(ddZd)ddZd*ddZdd Zd+d d!Zd"d# Zd$d% ZdS ),z`
Misc functions, including distributed helpers.

Mostly copy-paste from torchvision references.
    N)ListOptional)TensorTc                 C   s   t  }|dk r
| S t > g }g }t|  D ]}|| || |  qtj|dd}t	| |r:|| }dd t
||D }W d   |S 1 sOw   Y  |S )a6  
    Args:
        input_dict (dict): all the values will be reduced
        average (bool): whether to do average or sum
    Reduce the values in the dictionary from all processes so that all processes
    have the averaged results. Returns a dict with the same fields as
    input_dict, after reduction.
       r   )dimc                 S   s   i | ]\}}||qS  r   ).0kvr   r   K/data/cameron/keygrip/volume_dino_tracks/dinov3/eval/detection/util/misc.py
<dictcomp>=       zreduce_dict.<locals>.<dictcomp>N)distributedget_world_sizetorchno_gradsortedkeysappendstackdist
all_reducezip)
input_dictaverage
world_sizenamesvaluesr	   Zreduced_dictr   r   r   reduce_dict&   s$   	



r   c                 C   s$   t t|  } t| d | d< t| S )Nr   )listr   nested_tensor_from_tensor_listtuple)batchr   r   r   
collate_fnA   s   r#   c                 C   sB   | d }| dd  D ]}t |D ]\}}t|| |||< qq
|S )Nr      )	enumeratemax)the_listmaxessublistindexitemr   r   r   _max_by_axisG   s   r,   tensor_listc                 C   s   | d j dkrqtdd | D }t| g| }|\}}}}| d j}| d j}tj|||d}	tj|||ftj|d}
t	| |	|
D ].\}}}|d |j
d d |j
d d |j
d f | d|d |j
d d |j
d f< qAntd	t|	|
S )
Nr      c                 S   s   g | ]}t |jqS r   )r   shape)r   imgr   r   r   
<listcomp>T   r   z2nested_tensor_from_tensor_list.<locals>.<listcomp>)dtypedevicer$   r   Fznot supported)ndimr,   lenr2   r3   r   zerosonesboolr   r/   copy_
ValueErrorNestedTensor)r-   max_sizebatch_shapebchwr2   r3   tensormaskr0   Zpad_imgmr   r   r   r    P   s   

2"
r    c                   @   sH   e Zd Zdee fddZdddZdd Zd	d
 Zdd Z	dd Z
dS )r;   rC   c                 C   s   || _ || _d S NtensorsrC   )selfrG   rC   r   r   r   __init__e   s   
zNestedTensor.__init__Fc                 C   sH   | j j||d}| j}|d ur|d usJ |j||d}nd }t||S )N)non_blocking)rG   torC   r;   )rH   r3   rJ   Zcast_tensorrC   Z	cast_maskr   r   r   rK   i   s   
zNestedTensor.toc                 O   s6   | j j|i | | jd ur| jj|i | d S d S rE   )rG   record_streamrC   )rH   argskwargsr   r   r   rL   s   s   
zNestedTensor.record_streamc                 C   s   | j | jfS rE   rF   rH   r   r   r   	decomposex   s   zNestedTensor.decomposec                 C   
   t | jS rE   )strrG   rO   r   r   r   __repr__{      
zNestedTensor.__repr__c                 C   rQ   rE   )r5   rG   rO   r   r   r   __len__~   rT   zNestedTensor.__len__N)F)__name__
__module____qualname__r   r   rI   rK   rL   rP   rS   rU   r   r   r   r   r;   d   s    

r;   r$   c                 C   s   |  dkrtjg | jdgS t|}|d}| |ddd\}}| }||	dd
|}g }|D ]}	|d|	 	d d}
||
d|  q6|S )z6Computes the precision@k for the specified values of kr   )r3   r$   TNg      Y@)numelr   r6   r3   r&   sizetopkteqview	expand_asfloatsumr   mul_)outputtargetr]   Zmaxk
batch_size_predcorrectresr	   Z	correct_kr   r   r   accuracy   s   
rl   nearestc                 C   s   t jj| ||||S )z
    Equivalent to nn.functional.interpolate, but with support for empty batch sizes.
    This will eventually be supported natively by PyTorch, and this
    class can go away.
    )torchvisionopsmiscinterpolate)inputr\   scale_factormodealign_cornersr   r   r   rq      s   rq   r   c                    sL   t tdd | } t| d jj tt fdd| D }|S )Nc                 S   s
   | j d uS rE   )grad)pr   r   r   <lambda>   s   
 z%get_total_grad_norm.<locals>.<lambda>r   c                    s$   g | ]}t |j  qS r   )r   normrv   detachrK   )r   rw   r3   	norm_typer   r   r1      s   $ z'get_total_grad_norm.<locals>.<listcomp>)r   filterrb   rv   r3   r   ry   r   )
parametersr|   
total_normr   r{   r   get_total_grad_norm   s   r   h㈵>c                 C   s8   | j ddd} | j |d}d|  j |d}t|| S )Nr   r$   )minr&   )r   )clampr   log)xepsx1x2r   r   r   inverse_sigmoid   s   r   c                 C   s$   d}|D ]}|| v rd} |S q|S )NFTr   )nZname_keywordsoutr>   r   r   r   match_name_keywords   s   r   Fc              	      s   |   D ]\}}t| jrt| jrtq fdd|   D  j jd fdd|   D  j jd fdd|   D  j j  jd fdd|   D  j j j	 d fdd|   D  j j j	 d fdd|   D  j j  j j	 dg}|S )	Nc                    sF   g | ]\}}t | jst | jst | js|jrs|n|qS r   r   lr_backbone_nameslr_linear_proj_namesZwd_norm_namesrequires_gradr   r   rw   rM   return_namer   r   r1          



z"get_param_dict.<locals>.<listcomp>)paramslrweight_decayc                    sF   g | ]\}}t | jrt | jst | js|jrs|n|qS r   r   r   r   r   r   r1      r   c                    sF   g | ]\}}t | jst | jrt | js|jrs|n|qS r   r   r   r   r   r   r1      r   c                    sF   g | ]\}}t | jst | jst | jr|jrs|n|qS r   r   r   r   r   r   r1      r   c                    sF   g | ]\}}t | jrt | jst | jr|jrs|n|qS r   r   r   r   r   r   r1      r   c                    sF   g | ]\}}t | jst | jrt | jr|jrs|n|qS r   r   r   r   r   r   r1      r   )
named_parametersr   r   r   r:   r   r   Zlr_backboneZlr_linear_proj_multZwd_norm_mult)modelrM   r   Zuse_layerwise_decayr   rw   Zparam_dictsr   r   r   get_param_dict   sT   




Jr   c                    s   t  fddt|D S )Nc                    s   g | ]}t  qS r   )copydeepcopy)r   imoduler   r   r1     r   z_get_clones.<locals>.<listcomp>)nn
ModuleListrange)r   Nr   r   r   _get_clones  s   r   c                 C   s:   | dkrt jS | dkrt jS | dkrt jS td|  d)z,Return an activation function given a stringrelugelugluz$activation should be relu/gelu, not .)Fr   r   r   RuntimeError)
activationr   r   r   _get_activation_fn  s   r   )T)rY   )NNrm   N)r   )r   )FF) __doc__r   typingr   r   Zdinov3.distributedr   r   torch.distributedr   torch.nnr   torch.nn.functional
functionalr   rn   r   r   r#   r,   r    objectr;   r   rl   rq   r   r   r   r   r   r   r   r   r   r   <module>   s0   
	




	S