o
    9i!                     @   s@  d dl Z d dlZd dlZd dl mZ d dlmZ d dlZd dlZd dl	Z	d dl
mZmZmZ d dlmZ d:ddZd	d
 Zdd Zd:ddZd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)d*Z!d+d, Z"d=d-d.Z#d/d0 Z$d1d2 Z%d>d3d4Z&d5e'fd6d7Z(d?d8d9Z)dS )@    N)partial)
isfunction)Image	ImageDraw	ImageFont)	load_fileTc                 C   s   | S )zbOverwrite model.train with this function to make sure train/eval mode
    does not change anymore. )selfmoder   r   2/data/cameron/vidgen/generative-models/sgm/util.pydisabled_train   s   r   c                 C   sX   z%| d dkr | d dkr#t | }t|tkr|d W S 	 W | S W | S W | S    Y | S )Nr   ())evaltypetuple)str   r   r   get_string_from_tuple   s   


r   c                 C   s   | dkrdS | | d @ dkS )a  
    chat.openai.com/chat
    Return True if n is a power of 2, otherwise return False.

    The function is_power_of_two takes an integer n as input and returns True if n is a power of 2, otherwise it returns False.
    The function works by first checking if n is less than or equal to 0. If n is less than or equal to 0, it can't be a power of 2, so the function returns False.
    If n is greater than 0, the function checks whether n is a power of 2 by using a bitwise AND operation between n and n-1. If n is a power of 2, then it will have only one bit set to 1 in its binary representation. When we subtract 1 from a power of 2, all the bits to the right of that bit become 1, and the bit itself becomes 0. So, when we perform a bitwise AND between n and n-1, we get 0 if n is a power of 2, and a non-zero value otherwise.
    Thus, if the result of the bitwise AND operation is 0, then n is a power of 2 and the function returns True. Otherwise, the function returns False.

    r   F   r   )nr   r   r   is_power_of_two$   s   r   c                    s    fdd}|S )Nc                     sN   t jjj t  t  d | i |W  d    S 1 s w   Y  d S )N)enableddtypecache_enabled)torchcudaampautocastget_autocast_gpu_dtypeis_autocast_cache_enabled)argskwargsr   fr   r   do_autocast5   s   $zautocast.<locals>.do_autocastr   )r%   r   r&   r   r$   r   r   4   s   r   c                 C   s"   t t| d fi | dt S )Ntargetparams)r   get_obj_from_strgetdictconfigr   r   r   load_partial_from_config@   s   "r.   
   c           
   	      s  t |}t }t|D ]q}tjd| dd}t|}tjd|d}t	d| d d   t
|| tr9|| d n|| d	 fd
dtdt  D }	z|jd|	d|d W n tyh   td Y nw t|dddd d }|| qt|}t|}|S )NRGBwhite)colorzdata/DejaVuSans.ttf)size(   r      
c                 3   s     | ]}||   V  qd S Nr   ).0startnctext_seqr   r   	<genexpr>R   s    
z!log_txt_as_img.<locals>.<genexpr>)r   r   black)fillfontz)Cant encode string for logging. Skipping.   r   g     _@g      ?)lenlistranger   newr   Drawr   truetypeint
isinstancejointextUnicodeEncodeErrorprintnparray	transposeappendstackr   tensor)
whxcr3   btxtsbitxtdrawr@   linesr   r:   r   log_txt_as_imgD   s.   


r\   c                    s   G  fddd}|S )Nc                       s&   e Zd Zejjg R i ZdS )zpartialclass.<locals>.NewClsN)__name__
__module____qualname__	functoolspartialmethod__init__r   r"   clsr#   r   r   NewClsc   s    re   r   )rd   r"   r#   re   r   rc   r   partialclassb   s   rf   c                 C   s*   t j| \}}|jdkrtj|S | S )Nfile)fsspeccore	url_to_fsprotocolospathabspath)rm   fspr   r   r   make_path_absolutei   s   
rq   c                 C   s,   t | tjsdS t| jdko| jd dkS NF   r      rI   r   TensorrB   shapexr   r   r   ismapp   s   rz   c                 C   s:   t | tjsdS t| jdko| jd dkp| jd dkS rr   ru   rx   r   r   r   isimagev   s   *r{   c                 C   s   t | tjsdS | jdkS )NFrA   )rI   r   rv   ndimrx   r   r   r   	isheatmap|   s   
r}   c                 C   s6   t | tjsdS | jdko| jd dkp| jd dkS )NF   rA   rt   r   )rI   r   rv   r|   rw   rx   r   r   r   isneighbors   s   &r   c                 C   s   | d uS r7   r   rx   r   r   r   exists   s   r   c                 C   s.   |   |  kr| d} |   |  ks| S )Nr   )dim	unsqueeze)ry   yr   r   r   expand_dims_like   s   
r   c                 C   s   t | r| S t|r| S |S r7   )r   r   )valdr   r   r   default   s   r   c                 C   s   | j ttdt| jdS )z
    https://github.com/openai/guided-diffusion/blob/27c20a8fab9cb472df5d6bdd6c8d11c8f430b924/guided_diffusion/nn.py#L86
    Take the mean over all non-batch dimensions.
    r   )r   )meanrC   rD   rB   rw   )rS   r   r   r   	mean_flat   s   r   Fc                 C   s<   t dd |  D }|rt| jj d|d dd |S )Nc                 s   s    | ]}|  V  qd S r7   )numel)r8   rp   r   r   r   r=      s    zcount_params.<locals>.<genexpr>z has gư>z.2fz
 M params.)sum
parametersrM   	__class__r]   )modelverbosetotal_paramsr   r   r   count_params   s   r   c                 C   sH   d| vr| dkr
d S | dkrd S t dt| d di | dt S )Nr'   __is_first_stage____is_unconditional__z%Expected key `target` to instantiate.r(   r   )KeyErrorr)   r*   r+   r,   r   r   r   instantiate_from_config   s    r   c                 C   sH   |  dd\}}|rt  |rt|}t| ttj|d d|S )N.r   )package)rsplit	importlibinvalidate_cachesimport_modulereloadgetattr)stringr   invalidate_cachemodulerd   
module_impr   r   r   r)      s   

r)   c                 C   s   t | | dggS )Nr   )r   cat	new_zerosrx   r   r   r   append_zero   s   r   c                 C   s:   || j  }|dk rtd| j  d| d| dd|   S )zNAppends dimensions to the end of a tensor until it has target_dims dimensions.r   z
input has z dims but target_dims is z, which is less).r7   )r|   
ValueError)ry   target_dimsdims_to_appendr   r   r   append_dims   s   
r   c           
      C   s   t d|  |dr%tj|dd}d|v r t d|d   |d }n|dr/t|}ntt| j}|j|d	d
\}}t	|dkrO|rOt d t | t	|dkr_|r_t d t | |rk|
 D ]}	d	|	_qe|  |S )NzLoading model from ckptcpu)map_locationglobal_stepzGlobal Step: 
state_dictsafetensorsF)strictr   zmissing keys:zunexpected keys:)rM   endswithr   loadload_safetensorsNotImplementedErrorr   r   load_state_dictrB   r   requires_gradr   )
r-   r   r   freezepl_sdsdr   muparamr   r   r   load_model_from_config   s,   




r   returnc                  C   sb   t jt} t j| dt j| ddf}|D ]}t j|}t j|r)|  S qtd| )z
    Get the `configs` directory.
    For a working copy, this is the one in the root of the repository,
    but for an installed copy, it's in the `sgm` package (see pyproject.toml).
    configsz..zCould not find SGM configs in )rl   rm   dirname__file__rJ   rn   isdirFileNotFoundError)this_dir
candidates	candidater   r   r   get_configs_path   s   r   c           
   	   C   s   | d}|dur|dkr|d| }t|dksJ d| }d}t|D ]'\}}d|d|d  }z
t|}	||	 }W q% tyL   t||}Y q%w |rS||fS |S )a&  
    Will return the result of a recursive get attribute call.
    E.g.:
        a.b.c
        = getattr(getattr(a, "b"), "c")
        = get_nested_attribute(a, "b.c")
    If any part of the attribute call is an integer x with current obj a, will
    try to call a[x] instead of a.x first.
    r   Nr   z)At least one attribute should be selectedr   )splitrB   	enumeraterJ   rH   r   r   )
objattribute_pathdepth
return_key
attributescurrent_attributecurrent_keylevel	attributeid_r   r   r   get_nested_attribute   s   

r   )T)r/   )F)FT)TT)NF)*r`   r   rl   r   inspectr   rh   numpyrN   r   PILr   r   r   safetensors.torchr   r   r   r   r   r   r.   r\   rf   rq   rz   r{   r}   r   r   r   r   r   r   r   r)   r   r   r   strr   r   r   r   r   r   <module>   sD    








