o
    piY>                     @   sl  d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZ	d dl
Z
d dlmZ daetaejZdZd{ddZdd	 Zd
d Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Z d$d% Z!d&d' Z"d(d) Z#d*d+ Z$d,d- Z%d.d/ Z&d0d1 Z'G d2d3 d3Z(	d|d4d5Z)d6d7 Z*d8d9 Z+d}d;d<Z,d=d> Z-d?d@ Z.	A		d~dBdCZ/dDdE Z0dFdG Z1dHdI Z2dJdK Z3dLdM Z4ddOdPZ5dQdR Z6dSdT Z7ddUdVZ8ddWdXZ9G dYdZ dZZ:G d[d\ d\e
j;j<j=Z>d]d^ Z?d_d` Z@dadb ZAddcddZBddedfZCdgdh ZDdidj ZEdkdl ZFdmdn ZGdodp ZHdqdr ZIdsdt ZJdudv ZKdwdx ZLdydz ZMdS )    N)tqdmPMLF   c              
   C   s   t jt j| X}t|d:}t|jddd"}|| }r4|| |	t
| || }s!W d    n1 s>w   Y  W d    n1 sMw   Y  W d    d S W d    d S 1 sew   Y  d S )NwbBT)totalunit
unit_scale)urllibrequesturlopenRequestopenr   lengthreadwriteupdatelen)urlfilename
chunk_sizeresponsefhpbarchunk r   b/home/ubuntu/.local/lib/python3.10/site-packages/pytorch_metric_learning/utils/common_functions.py_urlretrieve   s    
 "r   c                 C   s   | a tt ad S N)LOGGER_NAMElogging	getLoggerLOGGER)namer   r   r   set_logger_name   s   r$   c                 C      t | jS r   )torchfinfomaxdtyper   r   r   pos_inf&      r+   c                 C   r%   r   )r&   r'   minr)   r   r   r   neg_inf*   r,   r.   c                 C   r%   r   )r&   r'   tinyr)   r   r   r   	small_val.   r,   r0   c                 C   s   t | ttfS r   )
isinstancelisttuplexr   r   r   is_list_or_tuple2      r6   c                 C   s6   z| t | fW S  ty   t|} | t | f Y S w r   )nextStopIterationiter)geniterabler   r   r   try_next_on_generator6   s   r=   c                 C   s$   zt | W S  ty   |  Y S w r   )r&   
from_numpy	TypeErrorvr   r   r   numpy_to_torch>   s
   rB   c                 C   s&   z|    W S  ty   |  Y S w r   )cpunumpyAttributeErrorr@   r   r   r   to_numpyE   s
   rF   c                 C   sd   |dkr| S t |rt|}n|}|dkr#| jdkr!| jd |ks#J | jdkr0| d d |f } | S )Nallr         )r6   r(   ndimshape)batch_labelshierarchy_levelmax_hierarchy_levelr   r   r   get_hierarchy_labelL   s   

rO   c                 C   s   t |rtjdd |D dd}nt|}|jdkr?tj|jtd}t|jd D ]}| |d d |f ||d d |f< q)|S | |d}|S )Nc                 S   s   g | ]}t |qS r   )rF   ).0subr   r   r   
<listcomp>\       zmap_labels.<locals>.<listcomp>rI   )axisrH   r)   r   )	r6   npstackrF   rJ   zerosrK   intrange)	label_maplabels
new_labelshr   r   r   
map_labelsZ   s   
$
r^   c                 C   s    t || } t| |} t| } | S r   )r^   rO   rB   )r[   rM   rZ   r   r   r   process_labelh   s   

r_   c                 C   s   |   D ]}||_qd S r   )
parametersrequires_grad)modelra   paramr   r   r   set_requires_grado   s   rd   c                    sb   t | dkr| d ft fdd| dd D  } | S t | dkr/t fddt| D } | S )	a;  
    Shifts indices of positives and negatives of pairs or triplets by batch_size

    if len(indices_tuple) != 3 or len(indices_tuple) != 4, it will return indices_tuple
    Args:
        indices_tuple is a tuple with torch.Tensor
        batch_size is an int
    Returns:
        A tuple with shifted indices
       r   c                    s$   g | ]}t |d kr|  n|qS r   r   rP   r5   
batch_sizer   r   rR      s   $ z'shift_indices_tuple.<locals>.<listcomp>rI   N   c                    s4   g | ]\}}t |d kr|d dkr|  n|qS )r   rH   rI   rg   )rP   ir5   ri   r   r   rR      s    ")r   r3   	enumerate)indices_tuplerj   r   ri   r   shift_indices_tuplet   s   


ro   c                 C   s   t | |k }tj| ||dS )a  
    Randomly samples without replacement from a sequence. It is "safe" because
    if len(input_data) < size, it will randomly sample WITH replacement
    Args:
        input_data is a sequence, like a torch tensor, numpy array,
                        python list, tuple etc
        size is the number of elements to randomly sample from input_data
    Returns:
        An array of size "size", randomly sampled from input_data
    )sizereplace)r   NUMPY_RANDOMchoice)
input_datarp   rq   r   r   r   safe_random_choice   s   ru   c                 C   sX   t | }| d  \}}tj|| |f| d jd}t|D ]}| | ||d |< q|S )Nr   device)r   rp   r&   rW   rw   rY   )input_tensorsnrowscolsoutputrl   r   r   r   unslice_by_n   s   r}   c                    s    fdd}|S )Nc                    s&   | j j}| dkr|   d S d S )N)	__class____name__findeval)m	classname
layer_namer   r   set_to_eval   s   z'set_layers_to_eval.<locals>.set_to_evalr   )r   r   r   r   r   set_layers_to_eval   s   r   c              
   C   sN   t |tjjjrtjjj| |||ddS tjjj| t||d|||d u ddS )NF)batch_samplernum_workers
collate_fn
pin_memoryT)rj   sampler	drop_lastr   r   shuffler   )r1   r&   utilsdataBatchSampler
DataLoaderrX   )datasetrj   r   r   r   r   r   r   get_train_dataloader   s$   r   c              	   C   s    t jjj| t|d||dddS )NF)rj   r   r   r   r   r   )r&   r   r   r   rX   )r   rj   r   r   r   r   r   get_eval_dataloader   s   r   c                 C   sh   t | r|   } tt}t| D ]\}}|| | q|	 D ]\}}t
j|td||< q$|S )z
    Creates labels_to_indices, which is a dictionary mapping each label
    to a numpy array of indices that will be used to index into self.dataset
    r)   )r&   	is_tensorrC   rD   collectionsdefaultdictr2   rm   appenditemsrU   arrayrX   )r[   labels_to_indicesrl   labelkrA   r   r   r   get_labels_to_indices   s   

r   c                 C   sF   t t| t | krtdtj| td }dd t| |D S )z
    Args:
        label_set: type sequence, a set of integer labels
                    (no duplicates in the sequence)
    Returns:
        A dictionary mapping each label to its numeric rank in the original set
    z"label set must not have duplicatesrI   c                 S   s   i | ]\}}||qS r   r   )rP   r   rA   r   r   r   
<dictcomp>       z+make_label_to_rank_dict.<locals>.<dictcomp>)	r   set
ValueErrorscipystatsrankdataastyperX   zip)	label_setrankedr   r   r   make_label_to_rank_dict   s   r   c                 C   sd   t | } | jdkr(i }t| jd D ]}ttt| d d |f ||< q|S dttt| iS )NrH   rI   r   )rU   r   rJ   rY   rK   r   r2   r   )r[   rZ   rM   r   r   r   get_label_map   s   


r   c                   @   s   e Zd ZdddZdd ZdS )LabelMapperFNc                 C   s    || _ |d urt|| _d S d S r   )set_min_label_to_zeror   rZ   )selfr   dataset_labelsr   r   r   __init__   s   zLabelMapper.__init__c                    s(   j s|S tj fdd|D tdS )Nc                    s   g | ]	}j   | qS r   )rZ   rh   rM   r   r   r   rR         z#LabelMapper.map.<locals>.<listcomp>r)   )r   rU   r   rX   )r   r[   rM   r   r   r   map  s
   zLabelMapper.map)FN)r   
__module____qualname__r   r   r   r   r   r   r      s    
r   c                 C   s   |rd}nd}t | |st| |g  t| |}|d ur/||vr$|| t | |s/t| |d |d urCt|rE|D ]}t| ||d q9d S d S d S )N_record_these_stats_record_theser   )r#   is_stat)hasattrsetattrgetattrr   r6   add_to_recordable_attributes)	input_objr#   list_of_namesr   attr_name_list_nameattr_name_listry   r   r   r   r     s    



r   c                 C   s,   dD ]}t | |g D ]}t| |d q
qd S )N)r   r   )r   r   )r   	attr_listrr   r   r   reset_stats  s
   r   c                   C   s   ddgS )Nr   r   r   r   r   r   r   (list_of_recordable_attributes_list_names%  s   r   .pthc                 C   s6   |d u rt j| || S t j| d|t||f S )Nz%s_%s%s)ospathjoinstr)folderbasename
identifier	extensionr   r   r   modelpath_creator)  s   r   c                    sN   t  fddtjjtjjjfD rt j | d S t  | d S )Nc                 3   s    | ]}t  |V  qd S r   )r1   rh   rb   r   r   	<genexpr>1  s
    
zsave_model.<locals>.<genexpr>)	anyr&   nnDataParallelparallelDistributedDataParallelsavemodule
state_dict)rb   filepathr   r   r   
save_model0  s
   r   c           	      C   s|   z|  tj||d W d S  ty=   t|}ddlm} | }| D ]\}}|dd  }|||< q&|  | Y d S w )N)map_locationr   )OrderedDict   )load_state_dictr&   loadKeyErrorr   r   r   )		model_defmodel_filenamerw   r   r   new_state_dictr   rA   r#   r   r   r   
load_model:  s   

r    c           
   	   C   sr   |   D ]2\}}t|||}	z|||	 |rtd||	f  W q ty6   td||	f  |r4tY qw d S )Nz%s %szCould not %s %s)r   r   r"   infoIOErrorwarning)

input_dictsuffixr   	operationlogging_stringlog_if_successfulassert_successr   rA   
model_pathr   r   r   operate_on_dict_of_modelsK  s   	
r   c                 K   $   dd }t | |||dfi | d S )Nc                 S   s   t | | d S r   )r   rA   r   r   r   r   r   a  r7   z&save_dict_of_models.<locals>.operationSAVEr   r   r   r   kwargsr   r   r   r   save_dict_of_models`  s   r   c                    s(    fdd}t | |||dfi | d S )Nc                    s   t | |  d S r   )r   r   rv   r   r   r   h  s   z&load_dict_of_models.<locals>.operationLOADr   )r   r   r   rw   r   r   r   rv   r   load_dict_of_modelsg  s   r   c                 K   r   )Nc                 S   s   t j|rt | d S d S r   )r   r   existsremover   r   r   r   r   o  s   z(delete_dict_of_models.<locals>.operationDELETEr   r   r   r   r   delete_dict_of_modelsn  s   r   c                 C   s"   t | trdd | D S t| S )Nc                 S   s   g | ]}t |qS r   )recompile)rP   zr   r   r   rR   x  r   z!regex_wrapper.<locals>.<listcomp>)r1   r2   r   r  r4   r   r   r   regex_wrapperv  s   

r  c                 C   s   t | ||S r   )r   rQ   )searchrq   contentsr   r   r   regex_replace|  r7   r  trunk_*.pthc                    s   t  tj| |}|g krdS |rtdntdtd fdd|D } fdd|D }t|}|r:d| n|}||fS )N)r   Nzbest[0-9]+\.pth$z[0-9]+\.pth$c                    s   g | ]	}  |r|qS r   )r  rh   )model_regexr   r   rR     r   z"latest_version.<locals>.<listcomp>c                    s(   g | ]}t  |d  dd qS )r~   .r   )rX   findallsplitrh   )epoch_regexr   r   rR        ( zbest%d)globr   r   r   r  r(   )r   string_to_globbestr   versionresume_epochr   r   )r  r  r   latest_version  s   r  c                 C   s   | S r   r   r4   r   r   r   return_input  s   r  c                 C   sF   |d ur| j d |j d krtd|d ur|jdkr!tdd S d S )Nr   z0Number of embeddings must equal number of labelsrI   z1labels must be a 1D tensor of shape (batch_size,))rK   r   rJ   
embeddingsr[   r   r   r   check_shapes  s
   r  c                 K   s   |d ur,t |rddd |D }d| }n|j}| jj}t| j|s,J d||| D ]\}}t| j||ksEJ d|||q0d S )Nz, c                 s   s    | ]}|j V  qd S r   )r   rh   r   r   r   r     s    z'assert_distance_type.<locals>.<genexpr>zone of z({} requires the distance metric to be {}z {} requires distance.{} to be {})	r6   r   r   r   r1   distanceformatr   r   )objdistance_typer   distance_type_strobj_namer   rA   r   r   r   assert_distance_type  s$   
r  c                 C   s   t j| || jdS )Nrv   )r&   arangerp   rw   )inputsize_dimr   r   r   torch_arange_from_size  s   r"  c                   @   s   e Zd Zdd Zdd ZdS )TorchInitWrapperc                 K      || _ || _d S r   	init_funcr   )r   r&  r   r   r   r   r        
zTorchInitWrapper.__init__c                 C   s   | j |fi | j d S r   r%  )r   tensorr   r   r   __call__     zTorchInitWrapper.__call__N)r   r   r   r   r)  r   r   r   r   r#    s    r#  c                   @   s$   e Zd Zdd Zdd Zdd ZdS )EmbeddingDatasetc                 C   r$  r   r  )r   r  r[   r   r   r   r     r'  zEmbeddingDataset.__init__c                 C   s
   t | jS r   )r   r  )r   r   r   r   __len__  s   
zEmbeddingDataset.__len__c                 C   s   | j | | j| fS r   r  )r   idxr   r   r   __getitem__  s   zEmbeddingDataset.__getitem__N)r   r   r   r   r,  r.  r   r   r   r   r+    s    r+  c                    s    fdd d   D S )Nc                    s    i | ]   fd dD qS )c                    s   g | ]}|  qS r   r   )rP   rowr   r   r   rR     rS   z1sqlite_obj_to_dict.<locals>.<dictcomp>.<listcomp>r   )rP   
sqlite_objr0  r   r     s     z&sqlite_obj_to_dict.<locals>.<dictcomp>r   )keysr1  r   r1  r   sqlite_obj_to_dict     r4  c                 C   s(   t j| jg | jd | dR  ddS )Nr~   dim)r&   rG   viewrK   )r5   r7  r   r   r   torch_all_from_dim_to_end  s   (r9  c                 C   s(   t j| dd}t j| dd}| | | S )Nr   r6  )r&   meanstd)r5   r:  r;  r   r   r   torch_standard_scaler  s   r<  c                 C   s2   t  s|d ur
|n|j}| j|kr| |} | S r   )r&   is_autocast_enabledr*   type)r5   r(  r*   dtr   r   r   to_dtype  s
   

r@  c                 C   s>   |d ur|n|j }| j |kr| |} |d urt| |d} | S )Nr)   )rw   tor@  )r5   r(  rw   r*   dvr   r   r   	to_device  s   

rC  c                 C   s8   |d ur|d urt ||}n| |}}t|| ||fS r   )rC  r  r  r[   ref_emb
ref_labelsr   r   r   set_ref_emb  s   


rG  c                 C   s   | d us|d urt dd S )Nz>labels are ref_labels are not supported for this loss functionr   )r[   rF  r   r   r   labels_not_supported  s
   rI  c                 C   s   || us||urt dd S )Nz/ref_emb is not supported for this loss functionrH  rD  r   r   r   ref_not_supported  s   rJ  c                 C   s   | d urt dd S )Nz5indices_tuple is not supported for this loss functionrH  )rn   r   r   r   indices_tuple_not_supported     rK  c                 C   s   | d u rt dd S )Nz*labels are required for this loss functionrH  )r[   r   r   r   labels_required   rL  rM  c                 C   s    | d u r|d u rt dd S d S )Nz,labels and indices_tuple cannot both be NonerH  )r[   rn   r   r   r    labels_or_indices_tuple_required  s   rN  c                 C   s   t dd t| |D S )Nc                 S   s(   g | ]\}}t j|t||gd dqS )r   r6  )r&   catrC  )rP   r5   yr   r   r   rR     r  z.concatenate_indices_tuples.<locals>.<listcomp>)r3   r   )it1it2r   r   r   concatenate_indices_tuples
  r*  rS  c                        fdd| D S )Nc                    s   g | ]}| vr|qS r   r   rh   targetsr   r   rR     s    zexclude.<locals>.<listcomp>r   )itrV  r   rU  r   exclude     rX  c                    rT  )Nc                    s   g | ]}|  qS r   r   rh   sufr   r   rR     rS   zappend_map.<locals>.<listcomp>r   )rW  r[  r   rZ  r   
append_map  rY  r\  c                   C   s   t t j r
dS dS )NcudarC   )r&   rw   r]  is_availabler   r   r   r   use_cuda_if_available  r5  r_  )r   )NNF)r   )r   FF)r  Fr   rf   )NN)NNN)Nr   r  r    r   r   r
   rD   rU   scipy.statsr   r&   r   r   r!   r"   randomrr   COLLECT_STATSr   r$   r+   r.   r0   r6   r=   rB   rF   rO   r^   r_   rd   ro   ru   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r  r  r"  r#  r   r   Datasetr+  r4  r9  r<  r@  rC  rG  rI  rJ  rK  rM  rN  rS  rX  r\  r_  r   r   r   r   <module>   s    


		






	

	
