o
    ߥil                     @   s  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 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 dlm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"  m#Z$ d dl%m&Z' d dl(m)Z) d dl*m+Z+ d dl,m-Z- d dl.m/Z/ e/ Z0g dZ1da2dqddZ3dd Z4dd Z5e 6 dd Z7dd Z8de9d9e:e;<ddd dfddZ=dd Z>i e>_?dd Z@drd d!ZAdsd"d#ZBdsd$d%ZCdsd&d'ZDd(d) ZEdtd+d,ZFdsd-d.ZGdsd/d0ZHdsd1d2ZIdsd3d4ZJdsd5d6ZKe 6 			7	8	dud9d:ZLe 6 dvd<d=ZMe 6 g d>g d>d	dfd?d@ZNe 6 g d>g d>d	dd7dd;fdAdBZOe 6 g d>g d>d	dfdCdDZPe 6 g d>g d>d	dfdEdFZQe 6 g d>g d>dddfdGdHZRe 6 dwdIdJZSe 6 dsdKdLZTe 6 dtdMdNZUdxdPdQZVdRdS ZWdydTdUZXdzdVdWZYd{dXdYZZdZd[ Z[d|d]d^Z\G d_d` d`e]Z^dsdadbZ_dcdd Z`dedf ZadzdgdhZbdidj Zcd}dldmZdd~dodpZedS )    N)BytesIO)
ThreadPool	rearrange)Image)DiagonalGaussianDistribution)
get_logger)$parse_oss_urlparse_bucketread
read_image	read_gzipceil_divide	to_device
put_objectput_torch_objectput_object_from_file
get_objectget_object_to_file	rand_name
save_image
save_videosave_video_vs_conditions(save_video_multiple_conditions_with_datasave_video_multiple_conditionsdownload_video_to_filesave_video_grid_mp4	save_capsemaparallelexistsdownloadunzipload_state_dictinverse_indicesdetect_duplicatesread_tfsmd5ropeformat_statebreakup_gridhuggingface_tokenizerhuggingface_model    c                 C   s8   t t| d}|r|dsd| }||7 }|S )Nutf-8.)binasciib2a_hexosurandomdecode
startswith)lengthsuffixname r:   i/home/ubuntu/.local/lib/python3.10/site-packages/modelscope/models/multi_modal/videocomposer/ops/utils.pyr   7   s   
r   c
                 C   s  d}
d|
 | }|j d }t|d}td|j d }tj||j d | dd}g }|D ]}||}|| q+tj|dd}t|d|d}|d | }tj	
|jd	}t
|jd
}tj	|jsht|j z>| d t| d  d = | d t| d  d = t||| |||j|jd|j|	d
 d
|d | }t|d| W n ty } ztd|  W Y d }~nd }~ww td|  d S )N{P?      ?r   zb c f h w -> (b f) c h w   dimz(b f) c h w -> b c f h w)bzrank.gifztext_description.txt   )nrowsave_origin_videoduration
wzSave text or video error. zSave videos to )shaper   mintorchchunkr5   appendcatr3   pathjoinlog_dirospr    mkdirlistkeysr   meanstdrD   open
writelines	Exceptionloggererrorinfo)model_kwargs
video_dataautoencoder	ori_videoviz_numstepcapspalettecfgrE   scale_factorbs_vd
chunk_sizevideo_data_listdecode_datavd_datatmposs_keytext_keytextser:   r:   r;   save_with_model_kwargs@   sR   


rq   c                 C   sf   | D ]}|dv s
J q|du r|  d i i g}| D ]}|d | |d |< |d | |d |< q|S )N)	ydepthcannymaskedsketchimagemotionlocal_imagesingle_sketchTfpsr   rB   )rL   )partial_keysfull_model_kwargsuse_fps_conditionpartial_keypartial_model_kwargsr:   r:   r;   prepare_model_kwargsq   s   
r   c                 C   sJ   d}t | tr|  }|| S t | tjr| }|| S tdt|  d)Nr<   zencoder_posterior of type 'z' not yet implemented)
isinstancer   samplerJ   TensorNotImplementedErrortype)encoder_posteriorrf   zr:   r:   r;   get_first_stage_encoding   s   
r   c                 C   sL   g }t |D ]\}}|tj| | d|  d| gdd qtj|ddS )NrB   r?   r   )	enumeraterL   rJ   rM   stack)imgsmasksmasked_imgsimaskr:   r:   r;   make_masked_images   s    r   /model_weightsc                 C   s   t ||p	t | }|S )zDownload OSS [file or folder] to the cache folder.
        Only the 0th process on each node will run the downloading.
        Barrier all processes until the downloading is completed.
    )rQ   rO   basename)rm   file_or_dirname	cache_dir	base_pathr:   r:   r;   DOWNLOAD_TO_CACHE   s   
r   c                 C   s   |  dr| tdd  } tdd tdd tdd tdd d}| jddd	\}} d
|v rO|jd
dd	\}}|dD ]}|jddd	\}}|||< q?tj| dt  t	
 }t	jt	|d |d |d ||d}|| fS )Noss://OSS_ENDPOINTOSS_ACCESS_KEY_IDOSS_ACCESS_KEY_SECRETOSS_SECURITY_TOKEN)endpointaccessKeyIDaccessKeySecretsecurityTokenr   rB   )maxsplit?&=@r   r   r   )authr   bucket_namesession)r6   lenr3   getenvsplitr	   	_sessions
setdefaultgetpidossSessionBucketAuth)rN   configsbucketconfigpairkvr   r:   r:   r;   r	      s.   





r	   c                 C   s   t t| dd S )N_placeholderr   )r	   rQ   rO   )urlr:   r:   r;   r
      s   r
   r   c           
      C   s   |dv sJ d }t |D ]f}zP| dr+t| \}}|| }|dkr*|d}n/| dr@t| j}|dkr?|d}nt	| |d}| }W d    n1 sUw   Y  |W   S  t
yr }	 z|	}W Y d }	~	qd }	~	ww |)N)r   rbr   r   r/   http)mode)ranger6   r	   r   r   r5   requestsgetcontentrW   rY   )
filenamer   retry	exception_r   rN   r   frp   r:   r:   r;   r      s2   





r   c                 C   s\   d }t |D ]%}zttt| d|dW   S  ty+ } z|}W Y d }~qd }~ww |)Nr   )r   r   )r   r   rW   r   r   rY   )r   r   r   r   rp   r:   r:   r;   r      s   r   c                 C   s^   d }t |D ]&}zt| \}}||| W  d S  ty, } z|}W Y d }~qd }~ww |N)r   r	   r   rY   )r   
local_filer   r   r   r   rN   rp   r:   r:   r;   r      s   r   c           
      C   s   d }t |D ]Z}zDd}| dr(t| \}}tt| d d} |||  d}t| }|	 }W d    n1 s<w   Y  |rHt
|  |W   S  ty` }	 z|	}W Y d }	~	qd }	~	ww |)NFr   rB   r8   T)r   r6   r	   r   rQ   splitextr   gziprW   r   r3   removerY   )
r   r   r   r   r   r   rN   r   r   rp   r:   r:   r;   r     s*   



r   c                 C   s   t t| | S r   )intmathceil)arA   r:   r:   r;   r     s   r   Fc                    s|   t | ttfrt|  fdd| D S t | tr*t|  fdd|  D S t | tjr<| j kr<| j	 d} | S )Nc                    s   g | ]}t | qS r:   r   .0udevicenon_blockingr:   r;   
<listcomp>       zto_device.<locals>.<listcomp>c                    s    g | ]\}}|t | fqS r:   r   r   r   r   r   r:   r;   r   "  s    )r   )
r   rS   tupler   dictitemsrJ   r   r   to)batchr   r   r:   r   r;   r     s   
r   c                 C   j   d }t |D ]}z	| ||W   S  ty% } z|}W Y d }~qd }~ww tjd| d| dd d S )Nzput_object to  failed with error: Tflush)r   r   rY   rZ   r\   )r   rm   datar   r   r   rp   r:   r:   r;   r   )     
r   c                 C   s   d }t |D ]*}zt }t|| | || W   S  ty0 } z|}W Y d }~qd }~ww tjd| d| dd d S )Nzput_torch_object to r   Tr   )	r   r   rJ   saver   getvaluerY   rZ   r\   )r   rm   r   r   r   r   bufferrp   r:   r:   r;   r   7  s   
r   c                 C   r   )Nzput_object_from_file to r   Tr   )r   r   rY   rZ   r[   r   rm   r   r   r   r   rp   r:   r:   r;   r   G  r   r   c                 C   sl   d }t |D ] }z
| | W   S  ty& } z|}W Y d }~qd }~ww tjd| d| dd d S )Nzget_object from r   Tr   )r   r   r   rY   rZ   r[   )r   rm   r   r   r   rp   r:   r:   r;   r   U  s   
r   c                 C   r   )Nzget_object_to_file from r   Tr   )r   r   rY   rZ   r[   r   r:   r:   r;   r   c  r   r   TrB   c                 C   s   t dd}d g| D ]+}ztj|||||d | || d }	W  n ty5 }
 z|
}	W Y d }
~
q
d }
~
ww t|r@t| |	d urQt	j
d||	dd d S d S )Nz.jpgr   )rC   	normalizer   z"save image to {} failed, error: {}Tr   )r   tvutilsr   r   rY   rQ   r    r3   r   rZ   r[   format)r   rm   tensorrC   r   r   r   r   r   r   rp   r:   r:   r;   r   q  s,   





r      c                 C   s>   |  dddd} | jdd}dd |D }tj|||d |S )	NrB         r   r?   c                 S   s   g | ]}|  d  dqS )   uint8)numpyastype)r   rw   r:   r:   r;   r     s    z'video_tensor_to_gif.<locals>.<listcomp>rE   )permuteunbindimageiomimwrite)r   rN   rE   loopoptimizeimagesr:   r:   r;   video_tensor_to_gif  s
   r  )      ?r  r  c                 C   s  t j||jdddddd}t j||jdddddd}|||}|dd tdd}d g| D ]-}zt|d|d}	t	|	| | 
|| d }
W  n tyc } z|}
W Y d }~q6d }~ww t|rnt| |
d urtjd	||
d
d d S d S )Nr   rB   r   r   .gifr    (i j) c f h w -> c f (i h) (j w)r   "save video to {} failed, error: {}Tr   )rJ   r   r   viewmul_add_clamp_r   r   r  r   rY   rQ   r    r3   r   rZ   r[   r   )r   rm   r   rU   rV   rC   r   r   r   one_gifr   rp   r:   r:   r;   r     s6   





r   c                     sp  t j||jdddddd}t j||jdddddd}|||}z|dd W n tyM } zt	| |
 dd}W Y d }~nd }~ww | }|j\}}}}}t||||f}| }i }|d  D ]\}}|jd dkr{qot|jdkr|  }g }|D ]}g }|D ]}||j|dddd	 q|t| qt t|}t|d
}n|ddkrt j|||gdd}t||||f}|ddkrt j||d d d df gdd}t||||f}nE|ddkrt||||f}n3|ddkr9|d d ddf d d }|d d ddf }|| dd|   }t||||f}|jrA| n|||< qo| }d g| D ]X}z@t|d d} fdd| D }t|d d}|	rzt j|g| |g dd}n
t j||g dd}t|||d d }W  n ty } z	|}W Y d }~qMd }~ww |d urtd| | d S d S )Nr  rB   r   r   i   r   Z      
percentilewidthheightb n h w c -> b c n h wr?   r      r=          @r  r  c                       g | ]\}}t |d  dqS )r  r  r   r   r   conrC   r:   r;   r         z2save_video_multiple_conditions.<locals>.<listcomp>r   r	  )rJ   r   r   r
  r  r  r  rY   rZ   r[   floatcpurH   Fadaptive_avg_pool3dr   r   r   rL   get_palette_imagenpr   
from_numpyr   sizerM   is_cudar  loggingr\   r   ) rm   video_tensorr]   source_imgsrd   rU   rV   rC   r   rD   r   rE   rp   rA   cnhrG   model_kwargs_channel3key
conditionsconditions_npr   vis_ijcoloralphar   r   vid_gif	cons_listr   r:   r  r;   r     s   



r   c           &         sf  t j||jdddddd}t j|	|jdddddd}	||	|}|dd |j\}}}}}t	||||f}|
 }i }|d  D ]\}}t|jdkr|
  }g }|D ]}g }|D ]}||j|dddd qd|t| q^t t|}t|d	}n|ddkrt j|||gdd
}t	||||f}|ddkrt j||d d d df gdd
}t	||||f}nD|ddkrt	||||f}n3|ddkr
|d d ddf d d }|d d ddf }|| dd|   }t	||||f}|jr|
 n|||< qI| }| }tdd}d g| D ]N}z6t|d d} fdd| D }t|d d}t j|g| |g dd
}t|| | || d } W  n tyw }! z	|!} W Y d }!~!q)d }!~!ww t|rt| tdd}"d g| D ]8}z| d  d}#t!"|#t#|"d | ||" W  n ty }! zt$%d||! W Y d }!~!qd }!~!ww t|"rt|" tdd}$d g| D ]8}z| d  d}%t!"|%t#|$d | ||$ W  n ty }! zt$%d||! W Y d }!~!qd }!~!ww t|$rt|$ | d ur1t$j%d&|| dd d S d S )Nr  rB   r   r   r   r  r  r  r  r?   r   r  r=   r  r  r   r  r  c                    r  )r  )r1  r   r  r  r:   r;   r   \  r  z<save_video_multiple_conditions_with_data.<locals>.<listcomp>z.pklr   r   wbzerror! r	  Tr   )'rJ   r   r   r
  r  r  r  rH   r  r   r  r   r   r   rL   r!  r"  r   r#  r   r$  rM   r%  cloner   r  r   rY   rQ   r    r3   r   r   pickledumprW   rZ   r[   r   )&r   video_save_keygt_video_save_keyvis_oss_keyr'  r]   r(  rd   rU   rV   rC   r   rA   r)  r*  r+  rG   r,  r-  r.  r/  r   r0  r1  r2  r3  copy_video_tensorcopy_source_imgsr   r   r4  r5  r   rp   filename_predcopy_video_npfilename_gtcopy_source_npr:   r  r;   r     s   









r   c	                 C   s  t j||jdddddd}t j||jdddddd}|||}|dd |j\}	}
}}}t	||||f}|
 }|ddkr[t j|||gdd}t	||||f}tdd}d g| D ]J}z/t|d|d	}t|d|d	}t|d|d	}t j|||gd
d}t|| | || d }W  n ty } z|}t| W Y d }~qed }~ww t|rt| |d urtjd||dd d S d S )Nr  rB   r   r   r?   r  r   r  r  r   r	  Tr   )rJ   r   r   r
  r  r  r  rH   r  r   r  r$  rM   r   r   r  r   rY   rZ   r[   rQ   r    r3   r   r   )r   rm   r'  r.  r(  rU   rV   rC   r   rA   r)  r*  r+  rG   r   r   r4  con_gifr   rp   r:   r:   r;   r     sR   







r   c                 C   s  t j||jdddddd}t j||jdddddd}|||}|dd |j\}}	}
}}|ddddd}|	 
 d d	}td
d}d g| D ]}zr|d u ratt|}t|| }d}tj|
|| | | || | | |	fd	d}t|D ])}|| }|| }|| | }|| | }|| |d d ||| ||| f< qtjj||dt|id | || d }W  n ty } z|}t| W Y d }~qRd }~ww t|rt| |d urtjd||dd d S d S )Nr  rB   r   r   r   r   r  r   r   z.mp4r   )dtypez-r)	inputdictr	  Tr   ) rJ   r   r   r
  r  r  r  rH   r   r  r   r   r   r   r   sqrtr"  zerosr   skvideoiovwritestrr   rY   rZ   r[   rQ   r    r3   r   r   )r   rm   r   rU   rV   rC   r{   r   rA   r)  tr+  rG   r   r   ncolpadding
video_gridr   r   c_start_rstart_cr   rp   r:   r:   r;   r     s\   	






r   c                 C   s   |j d }t|| }||| ksJ d}t|D ]}t|D ]}	t||| |	  }
||
d 7 }q|d7 }qd g| D ]&}z| || d }W  n tyb } z|}t| W Y d }~q<d }~ww |d urttjd||dd d S d S )Nr   r.   rF   r	  Tr   )	rH   r   r   dec_bytes2objr   rY   rZ   r[   r   )r   rm   r   rC   r   r   num_per_rowro   r   r1  textr   r   rp   r:   r:   r;   	save_text  s4   




rV  c           	      C   s   d}|D ]
}||7 }|d7 }qd g| D ]&}z|  || d }W  n ty: } z|}t| W Y d }~qd }~ww |d urLtjd||dd d S d S )Nr.   rF   r	  Tr   )r   rY   rZ   r[   r   )	r   rm   rc   r   ro   capr   r   rp   r:   r:   r;   r     s*   



r   c                 C   s|   d|  krdksJ  J t |  | D ]\}}|||| q|r:t |  | D ]\}}|| q0d S d S )Ng        r=   )zip
parameterscopy_lerpbuffers)net_emanetbetacopy_bufferp_emapb_emarA   r:   r:   r;   r   5  s   r       c                    s   t |tsJ t |d tsdd |D }|dkr" fdd|D S t|d fdd|D }fdd|D }W d    |S 1 sFw   Y  |S )Nr   c                 S   s   g | ]}|fqS r:   r:   r   argsr:   r:   r;   r   B  s    zparallel.<locals>.<listcomp>c                    s   g | ]} | qS r:   r:   re  )funcr:   r;   r   D  s    )	processesc                    s   g | ]}  |qS r:   )apply_asyncre  )rg  poolr:   r;   r   F  r   c                    s   g | ]}|j  d qS )timeout)r   )r   resrk  r:   r;   r   G  r   )r   rS   r   Pool)rg  	args_listnum_workersrl  resultsr:   )rg  rj  rl  r;   r   ?  s   
r   c                 C   s*   |  drt| \}}||S t| S )Nr   )r6   r	   object_existsrQ   r    )r   r   rN   r:   r:   r;   r    K  s   


r    c              
   C   s   |d u r	t | }t |r|rQz*| dr#t| \}}||| ntj| | |s9t	j
d|  d| dd W n tyP } z
td| d| d }~ww t |S )Nr   zDownloaded z to Tr   zDownloading z failed with error )rQ   r   r    r6   r	   r   urllibrequesturlretrieverZ   r[   rY   
ValueErrorabspath)r   r   replacequietr   rm   rp   r:   r:   r;   r!   S  s    


r!   c                 C   sN   |d u r	t | }t| d}|| W d    d S 1 s w   Y  d S )Nr   )rQ   dirnamezipfileZipFile
extractall)r   dst_dirzip_refr:   r:   r;   r"   d  s
   
"r"   c                    s   ||    rt fdd D fddD }fddD }fdd  @ D }t|| tfdd D | jdd t|d	krhtjd
d	| dd t|d	krztjdd	| dd t|d	krtjdd	| dd d S d S )Nc                    s2   g | ]\}}|  r|t d  n||fqS r   )r6   r   r   )drop_prefixr:   r;   r   o  s     z#load_state_dict.<locals>.<listcomp>c                       g | ]}| vr|qS r:   r:   r   r   )srcr:   r;   r   s  r   c                    r  r:   r:   r  )dstr:   r;   r   t  r   c                    s$   g | ]}| j  | j kr|qS r:   )rH   r  )r  r  r:   r;   r   u  s    c                    s    g | ]\}}| vr||fqS r:   r:   r   )incompatibler:   r;   r   {  s     F)strictr   z  Missing: z, Tr   z  Unexpected: z  Shape unmatched: )

state_dictr   r   rT   setr#   r   rZ   r\   rO   )moduler  r  missing
unexpected	unmatchedr:   )r  r  r  r  r;   r#   k  s(   r#   c                 C   s&   t | }t t| | || < |S )zXInverse map of indices.
        E.g., if A[indices] == B, then B[inv_indices] == A.
    )rJ   
empty_likearanger   r   )indicesinv_indicesr:   r:   r;   r$     s   
r$   ?c                 C   sb   | j dksJ tj| ddd} t| | j}|d tj  |	|j
dd }t|d S )Nr   rB   )rb  r@   r   r?   )ndimr  r   rJ   mmTtriu_cudasynchronizegtanywhere)featsthrsimmatr   r:   r:   r;   r%     s   

r%   c                   @   s.   e Zd Z		d
ddZedd Zdd Zd	S )	TFSClient!restful-store.vip.tbsite.net:38005354c9fae75f5c                 C   sV   || _ || _dd td| d ddd  D | _t| jdks&J d| _d S )Nc                 S   s   g | ]}d |v r|qS ):r:   r   r:   r:   r;   r     s
    z&TFSClient.__init__.<locals>.<listcomp>http://z	/url.listrF   rB   r   )hostapp_keyr   stripr   serversr   _TFSClient__server_id)selfr  r  r:   r:   r;   __init__  s    
zTFSClient.__init__c                 C   s"   | j d t| j | _ | j| j  S )NrB   )r  r   r  )r  r:   r:   r;   server  s   zTFSClient.serverc                 C   sh   t |}ttd| j d| j d| d}tt	td| j d| j d| d|d  d}|S )	Nr  z/v1/z
/metadata/z?force=0r   z?offset=0&size=SIZEr   )
rQ   r   jsonloadsr   r  r  r   rW   r   )r  tfsmetaimgr:   r:   r;   r     s   
"zTFSClient.readN)r  r  )__name__
__module____qualname__r  propertyr  r   r:   r:   r:   r;   r    s    

r  c                 C   s\   d }t |D ]%}ztd u rt at| W   S  ty+ } z|}W Y d }~qd }~ww |r   )r   
TFS_CLIENTr  r   rY   )r  r   r   r   rp   r:   r:   r;   r&     s   r&   c                 C   s@   t | d}t|  W  d    S 1 sw   Y  d S )Nr   )rW   hashlibr'   r   	hexdigest)r   r   r:   r:   r;   r'     s   $r'   c           
   	   C   s   | j }| | dd| d} | j dd \}}|d dks!J |d }tt|| tdt|| | }t	|t
|}}| jddd\}}	tj|| |	|  |	| ||  gdd} | |S )zQApply rotary position embedding on x of shape [B, *(spatial dimensions), C].
    r   r   r   Nr   i'  r?   )rH   r
  r$  rJ   outerr  r   powdivsincosrK   rM   )
xrH   lr)  halfsinusoidr  r  x1x2r:   r:   r;   r(     s   *
r(   c                 C   sZ   d dd |  D }|r+t|d}|| W d   dS 1 s$w   Y  dS dS )z'For comparing/aligning state_dict.
    rF   c                 S   s$   g | ]\}}| d t |j qS )	)r   rH   r   r:   r:   r;   r     s   $ z format_state.<locals>.<listcomp>rG   N)rO   r   rW   write)stater   r   r   r:   r:   r;   r)     s   "r)   c                 C   s   | j | }| j| }d }}g }t|D ]-}t|D ]&}|| |d |  }	|| |d |  }
|| |	|
|	| |
| f qq|S )z=The inverse operator of ``torchvision.utils.make_grid``.
    r   rB   )r  r  r   rL   crop)r  	grid_sizerC   rM  wrowwcolgridsr   r1  r  y1r:   r:   r;   r*     s   

"r*   google/mt5-xxlc                 K   s*   ddl m} |jtd|  | fi |S )Nr   )AutoTokenizerzhuggingface/tokenizers/)transformersr  from_pretrainedr   )r9   kwargsr  r:   r:   r;   r+     s   r+   	AutoModelc                 K   s,   dd l }t||jtd|  | fi |S )Nr   zhuggingface/models/)r  getattrr  r   )r9   
model_typer  r  r:   r:   r;   r,     s   
r,   )r-   r.   )r   r   )r   )F)r-   Tr   r   )r   r   T)r-   r   )rd  N)NFFr   )r.   )r  )r  )r  r  )fbase64r1   copyglobr   r  r&  r   r3   os.pathrN   rQ   r8  systimeurllib.requestrs  r{  rI  r   multiprocessing.poolr   rn  r   r  r   r"  oss2r   r   
skvideo.iorH  rJ   torch.nn.functionalnn
functionalr  torchvision.utilsutilsr   einopsr   PILr   7modelscope.models.multi_modal.videocomposer.autoencoderr   modelscope.utils.loggerr   rZ   __all__r  r   rq   r   no_gradr   r   rO   rw  __file__r   r   r	   r   r
   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r   r   r   r   rV  r   r   r   r    r!   r"   r#   r$   r%   objectr  r&   r'   r(   r)   r*   r+   r,   r:   r:   r:   r;   <module>   s   
	1












"b	|35
	



	
#
	
