U
    ¯Ê¹j"b  ã                   @   s¸  d Z ddlZddlmZ ddlmZmZmZ ddlZddl	m
Z
 ddlm
  mZ ddlZddlmZ ddlmZmZmZmZ ddlmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z"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gZ-e .e/¡Z0e1e1ej2ej2dœdd„Z3e,e3ƒ ej2ej2ej2ee1e1f ee1e1f ej2dœdd„Z4G dd„ de
j5ƒZ6G dd„ de
j5ƒZ7G dd„ de
j5ƒZ8ej2e1eej2ee1e1f f dœdd„Z9d?ej2e1ee1e1f eee1e1f  ej2dœdd„Z:G d d„ de
j5ƒZ;d!d"„ Z<d@d$d%„Z=e)e=d&d'd(eedd)d*d+�e=d,d'd(eedd)d*d+�e=d-d'd(eedd)d*d+�e=eed.d/d0d1�d2œƒZ>dAd4d5„Z?e*dBe;d6œd7d8„ƒZ@e*dCe;d6œd9d:„ƒZAe*dDe;d6œd;d<„ƒZBe*dEe;d6œd=d>„ƒZCdS )Fa+   Vision Transformer (ViT) in PyTorch

A PyTorch implement of Vision Transformers as described in:

'Exploring Plain Vision Transformer Backbones for Object Detection'
    - https://arxiv.org/abs/2203.16527

'Segment Anything Model (SAM)'
    - https://github.com/facebookresearch/segment-anything/

é    N)Úpartial)ÚCallableÚOptionalÚTuple)ÚFinal)ÚIMAGENET_DEFAULT_MEANÚIMAGENET_DEFAULT_STDÚIMAGENET_INCEPTION_MEANÚIMAGENET_INCEPTION_STD)Ú
PatchEmbedÚMlpÚDropPathÚPatchDropoutÚLayerNorm2dÚClassifierHeadÚNormMlpClassifierHeadÚFormatÚresample_abs_pos_embed_nhwcÚRotaryEmbeddingCatÚapply_rot_embed_catÚ	to_2tupleÚuse_fused_attné   )Úbuild_model_with_cfg)Úcheckpoint_seq)Úgenerate_default_cfgsÚregister_model)Úregister_notrace_functionÚVisionTransformerSAM)Úq_sizeÚk_sizeÚrel_posÚreturnc                 C   sÚ   t dt| |ƒ d ƒ}|jd |krdtj| d|jd d¡ ddd¡|dd�}| d|¡ dd¡}n|}t | ¡dd…df t||  dƒ }t |¡ddd…f t| | dƒ }|| |d t| | dƒ  }|| 	¡  S )	a\  
    Get relative positional embeddings according to the relative positions of
        query and key sizes.
    Args:
        q_size (int): size of query q.
        k_size (int): size of key k.
        rel_pos (Tensor): relative position embeddings (L, C).

    Returns:
        Extracted positional embeddings according to relative positions.
    é   r   r   éÿÿÿÿZlinear)ÚsizeÚmodeNç      ð?)
ÚintÚmaxÚshapeÚFZinterpolateÚreshapeÚpermuteÚtorchZarangeÚlong)r   r    r!   Zmax_rel_distZrel_pos_resizedZq_coordsZk_coordsZrelative_coords© r0   úa/var/www/html/bwave/python/venv/lib/python3.8/site-packages/timm/models/vision_transformer_sam.pyÚget_rel_pos%   s    ý$$r2   )ÚqÚ	rel_pos_hÚ	rel_pos_wr   r    r"   c                 C   sº   |\}}|\}}t |||ƒ}	t |||ƒ}
| j\}}}|  ||||¡}t d||	¡}t d||
¡}|dd…dd…dd…dd…df |dd…dd…dd…ddd…f  }| d|| || ¡S )a£  
    Calculate decomposed Relative Positional Embeddings from :paper:`mvitv2`.
    https://github.com/facebookresearch/mvit/blob/19786631e330df9f3622e5402b4a419a263a2c80/mvit/models/attention.py
    Args:
        q (Tensor): query q in the attention layer with shape (B, q_h * q_w, C).
        rel_pos_h (Tensor): relative position embeddings (Lh, C) for height axis.
        rel_pos_w (Tensor): relative position embeddings (Lw, C) for width axis.
        q_size (Tuple): spatial sequence size of query q with (q_h, q_w).
        k_size (Tuple): spatial sequence size of key k with (k_h, k_w).

    Returns:
        bias (Tensor): attention bias to add to attention map
    zbhwc,hkc->bhwkzbhwc,wkc->bhwkNr$   )r2   r*   r,   r.   Zeinsum)r3   r4   r5   r   r    Zq_hZq_wZk_hZk_wZRhZRwÚBÚ_ÚdimZr_qZrel_hZrel_wÚ	attn_biasr0   r0   r1   Úget_decomposed_rel_pos_biasH   s    Dr:   c                	       sd   e Zd ZU ee ed< dddddejdddf	eee	e
e
f  eej dœ‡ fdd	„Zd
d„ Z‡  ZS )Ú	AttentionÚ
fused_attné   TFç        N)Úuse_rel_posÚ
input_sizeÚropec                    s&  t ƒ  ¡  || dkstdƒ‚|| _|| | _| jd | _tƒ | _tj	||d |d�| _
|rf|| jƒnt ¡ | _|r~|| jƒnt ¡ | _t |¡| _t 	||¡| _t |¡| _|| _| j�r|
d ksÈt‚|	d k	sØtdƒ‚t t d|	d  d | j¡¡| _t t d|	d  d | j¡¡| _|
| _d S )	Nr   z$dim should be divisible by num_headsg      à¿é   )ÚbiaszBInput size must be provided if using relative positional encoding.r#   r   )ÚsuperÚ__init__ÚAssertionErrorÚ	num_headsZhead_dimÚscaler   r<   ÚnnZLinearÚqkvÚIdentityÚq_normÚk_normÚDropoutÚ	attn_dropÚprojÚ	proj_dropr?   Ú	Parameterr.   Úzerosr4   r5   rA   )Úselfr8   rG   Úqkv_biasÚqk_normrO   rQ   Ú
norm_layerr?   r@   rA   ©Ú	__class__r0   r1   rE   m   s8    

ÿþ ÿ ÿzAttention.__init__c                 C   sž  |j \}}}}|| }| ||d¡}|  |¡ ||d| jd¡ ddddd¡}| d|| j |d¡ d¡\}}	}
|  |¡|  |	¡ }}	| j	r¨t
|| j| j||f||fƒ}n8d }| jd k	rà| j ¡ }t||ƒ |
¡}t|	|ƒ |
¡}	| j�rtjjj||	|
|| j�r| jjndd�}nJ|| j }||	 d	d¡ }|d k	�r>|| }|jdd
�}|  |¡}||
 }| || j|d¡ dd¡ ||d¡}|  |¡}| |||d¡}|S )Nr$   rB   r#   r   r   é   r>   )Z	attn_maskZ	dropout_péþÿÿÿ)r8   )r*   r,   rJ   ÚviewrG   r-   ZunbindrL   rM   r?   r:   r4   r5   rA   Z	get_embedr   Ztype_asr<   r.   rI   Ú
functionalZscaled_dot_product_attentionZtrainingrO   ÚprH   Z	transposeZsoftmaxrP   )rT   Úxr6   ÚHÚWr7   ÚNrJ   r3   ÚkÚvr9   rA   Úattnr0   r0   r1   Úforward”   s@    ("

  ý


$
zAttention.forward)Ú__name__Ú
__module__Ú__qualname__r   ÚboolÚ__annotations__rI   Ú	LayerNormr   r   r(   ÚModulerE   rf   Ú__classcell__r0   r0   rX   r1   r;   j   s    
õ	õ'r;   c                       s&   e Zd Zd‡ fdd„	Zdd„ Z‡  ZS )Ú
LayerScaleçñhãˆµøä>Fc                    s*   t ƒ  ¡  || _t |t |¡ ¡| _d S ©N)rD   rE   ÚinplacerI   rR   r.   ZonesÚgamma)rT   r8   Úinit_valuesrr   rX   r0   r1   rE   ½   s    
zLayerScale.__init__c                 C   s   | j r| | j¡S || j S rq   )rr   Zmul_rs   ©rT   r_   r0   r0   r1   rf   Â   s    zLayerScale.forward)rp   F)rg   rh   ri   rE   rf   rn   r0   r0   rX   r1   ro   ¼   s   ro   c                       sF   e Zd Zdddddddejejeddddf‡ fdd„	Zd	d
„ Z‡  Z	S )ÚBlockç      @TFr>   Nr   c                    sØ   t ƒ  ¡  || _||ƒ| _t|||||||||dkr8|n||f|d�
| _|rXt||d�nt ¡ | _	|	dkrrt
|	ƒnt ¡ | _||ƒ| _||t|| ƒ|
|d�| _|r°t||d�nt ¡ | _|	dkrÊt
|	ƒnt ¡ | _d S )Nr   )	rG   rU   rV   rO   rQ   rW   r?   r@   rA   )rt   r>   )Zin_featuresZhidden_featuresÚ	act_layerZdrop)rD   rE   Úwindow_sizeÚnorm1r;   re   ro   rI   rK   Úls1r   Ú
drop_path1Únorm2r(   ÚmlpÚls2Ú
drop_path2)rT   r8   rG   Ú	mlp_ratiorU   rV   rQ   rO   rt   Ú	drop_pathrx   rW   Ú	mlp_layerr?   ry   r@   rA   rX   r0   r1   rE   È   s4    

ö

üzBlock.__init__c              
   C   s¼   |j \}}}}|}|  |¡}d }| jdkr:t|| jƒ\}}|  |  |  |¡¡¡}| jdkrnt|| j||f|ƒ}|| }| ||| d¡}||  	|  
|  |  |¡¡¡¡ }| |||d¡}|S )Nr   r$   )r*   rz   ry   Úwindow_partitionr|   r{   re   Úwindow_unpartitionr,   r€   r   r~   r}   )rT   r_   r6   r`   ra   r7   ZshortcutÚpad_hwr0   r0   r1   rf   ÷   s    


 zBlock.forward)
rg   rh   ri   rI   ÚGELUrl   r   rE   rf   rn   r0   r0   rX   r1   rv   Æ   s    ï/rv   )r_   ry   r"   c              	   C   s¤   | j \}}}}|||  | }|||  | }t | ddd|d|f¡} || ||  }}	|  ||| ||	| ||¡} |  dddddd¡ ¡  d|||¡}
|
||	ffS )aU  
    Partition into non-overlapping windows with padding if needed.
    Args:
        x (tensor): input tokens with [B, H, W, C].
        window_size (int): window size.

    Returns:
        windows: windows after partition with [B * num_windows, window_size, window_size, C].
        (Hp, Wp): padded height and width before partition
    r   r   rB   r#   rZ   é   r$   )r*   r+   Úpadr\   r-   Ú
contiguous)r_   ry   r6   r`   ra   ÚCZpad_hZpad_wÚHpÚWpÚwindowsr0   r0   r1   r„     s    $r„   )rŽ   ry   Úhwr†   r"   c           
      C   sž   |dk	r|n|\}}|\}}| j d || | |  }|  ||| || ||d¡}	|	 dddddd¡ ¡  |||d¡}	|	dd…d|…d|…dd…f  ¡ }	|	S )	a›  
    Window unpartition into original sequences and removing padding.
    Args:
        windows (tensor): input tokens with [B * num_windows, window_size, window_size, C].
        window_size (int): window size.
        pad_hw (Tuple): padded height and width (Hp, Wp).
        hw (Tuple): original height and width (H, W) before padding.

    Returns:
        x: unpartitioned sequences with [B, H, W, C].
    Nr   r$   r   rB   r#   rZ   rˆ   )r*   r\   r-   rŠ   )
rŽ   ry   r�   r†   rŒ   r�   r`   ra   r6   r_   r0   r0   r1   r…   '  s    $$r…   c                '       s\  e Zd ZdZdddddddddd	d
d	dddddddeeejd	d�ej	ej
eedd	d	ddddd
d
f!eeeeeeeeeeee eeeeeeeeeee ee eeeeeeeedf eeee eeeeef eeef f  dœ!‡ fdd„Zejjdd„ ƒZejjd(dd„ƒZejjd)dd„ƒZejjdd„ ƒZd*dd „Zd!d"„ Zd+ed#œd$d%„Zd&d'„ Z‡  Z S ),r   zâ Vision Transformer for Segment-Anything Model(SAM)

    A PyTorch impl of : `Exploring Plain Vision Transformer Backbones for Object Detection` or `Segment Anything Model (SAM)`
        - https://arxiv.org/abs/2010.11929
    é   é   rB   é   é   rw   TFNr>   Ú )Z
output_fmtZstrict_img_sizeé   r0   é   Úavg.)!Úimg_sizeÚ
patch_sizeÚin_chansÚnum_classesÚ	embed_dimÚdepthrG   r�   rU   rV   rt   Úpre_normÚ	drop_rateÚpos_drop_rateÚpatch_drop_rateÚproj_drop_rateÚattn_drop_rateÚdrop_path_rateÚweight_initÚembed_layerrW   rx   Úblock_fnrƒ   Úuse_abs_posr?   Úuse_ropery   Úglobal_attn_indexesÚ
neck_chansÚglobal_poolÚhead_hidden_sizeÚref_feat_shapec"           $         sR  t ƒ  ¡  ˆ
pttjdd�‰
ˆ p$tj‰ |ˆ_|ˆ_ˆ ˆ_ˆ_	dˆ_
||||ˆ| d�ˆ_ˆjj‰|rˆt t dˆd ˆd ˆ¡¡ˆ_ndˆ_tj|d�ˆ_|dkr´t|dd	�ˆ_n
t ¡ ˆ_|rÊˆ
ˆƒnt ¡ ˆ_|�rVˆrætd
ƒ‚|!dk	�rt|!ƒdk�st‚t|!d ƒ}"t|!d ƒ}#nd }"}#tˆˆ dˆ|"d�ˆ_tˆˆ dtˆƒ|#d�ˆ_ndˆ_dˆ_dd„ t d||¡D ƒ‰tj‡ ‡‡‡‡‡‡‡‡‡	‡
‡‡‡‡‡‡‡fdd„t|ƒD ƒŽ ˆ_ |�r t tj!ˆ|ddd�t"|ƒtj!||dddd�t"|ƒ¡ˆ_#|ˆ_n | �rt ¡ ˆ_#n
t"ˆƒˆ_#ˆ}| �r<t$||| ||d�ˆ_%nt&||||d�ˆ_%dS )a×  
        Args:
            img_size: Input image size.
            patch_size: Patch size.
            in_chans: Number of image input channels.
            num_classes: Mumber of classes for classification head.
            global_pool: Type of global pooling for final sequence (default: 'token').
            embed_dim: Transformer embedding dimension.
            depth: Depth of transformer.
            num_heads: Number of attention heads.
            mlp_ratio: Ratio of mlp hidden dim to embedding dim.
            qkv_bias: Enable bias for qkv projections if True.
            init_values: Layer-scale init values (layer-scale enabled if not None).
            drop_rate: Head dropout rate.
            pos_drop_rate: Position embedding dropout rate.
            attn_drop_rate: Attention dropout rate.
            drop_path_rate: Stochastic depth rate.
            weight_init: Weight initialization scheme.
            embed_layer: Patch embedding layer.
            norm_layer: Normalization layer.
            act_layer: MLP activation layer.
            block_fn: Transformer block layer.
            use_abs_pos: If True, use absolute positional embeddings.
            use_rel_pos: If True, add relative positional embeddings to the attention map.
            use_rope: If True, add rotary position embeddings to q/k in attention block.
            window_size: Window size for window attention blocks. If 0, not use window attention.
            global_attn_indexes: Indexes for blocks using global attention. Used when window_size > 0.
            global_pool: Global pooling type.
            head_hidden_size: If set, use NormMlpHead
            ref_feat_shape: Tuple of reference feature shapes for ROPE, (global, local)
        g�íµ ÷Æ°>)ÚepsF)r˜   r™   rš   rœ   rC   r   r   N)r^   )Znum_prefix_tokenszCROPE and relative pos embeddings should not be enabled at same timer#   )Z	in_pixelsZ
feat_shaper®   c                 S   s   g | ]}|  ¡ ‘qS r0   )Úitem)Ú.0r_   r0   r0   r1   Ú
<listcomp>Ã  s     z1VisionTransformerSAM.__init__.<locals>.<listcomp>c                    sT   g | ]L}ˆˆˆˆ	ˆˆˆˆˆˆ| ˆ
ˆ ˆˆ|ˆkr4ˆnd ˆ|ˆkrFˆj nˆjd�‘qS )r   )r8   rG   r�   rU   rV   rt   rQ   rO   r‚   rW   rx   rƒ   r?   ry   r@   rA   )Úrope_windowÚrope_global)r±   Úi©rx   r£   r§   Zdprrœ   rª   Ú	grid_sizert   rƒ   r�   rW   rG   r¢   rV   rU   rT   r?   ry   r0   r1   r²   Ä  s&   îð)Úkernel_sizerC   rB   )r¸   ÚpaddingrC   )Zhidden_sizeÚ	pool_typerŸ   )rº   rŸ   )'rD   rE   r   rI   rl   r‡   r›   r¬   Znum_featuresrœ   Úgrad_checkpointingÚpatch_embedr·   rR   r.   rS   Ú	pos_embedrN   Úpos_dropr   Ú
patch_droprK   Únorm_prerF   Úlenr   r   r´   r³   ZlinspaceZ
SequentialÚrangeÚblocksZConv2dr   Úneckr   Úheadr   )$rT   r˜   r™   rš   r›   rœ   r�   rG   r�   rU   rV   rt   rž   rŸ   r    r¡   r¢   r£   r¤   r¥   r¦   rW   rx   r§   rƒ   r¨   r?   r©   ry   rª   r«   r¬   r­   r®   Zref_feat_shape_globalZref_feat_shape_windowrX   r¶   r1   rE   E  s°    D

û"þ


üü
0í
üûñ
û
üzVisionTransformerSAM.__init__c                 C   s   ddhS )Nr½   Z
dist_tokenr0   ©rT   r0   r0   r1   Úno_weight_decay  s    z$VisionTransformerSAM.no_weight_decayc                 C   s   t dddgd�S )Nz^pos_embed|patch_embed)z^blocks\.(\d+)N)z^norm)iŸ† )ÚstemrÃ   )Údict)rT   Zcoarser0   r0   r1   Úgroup_matcher	  s    þz"VisionTransformerSAM.group_matcherc                 C   s
   || _ d S rq   )r»   )rT   Úenabler0   r0   r1   Úset_grad_checkpointing  s    z+VisionTransformerSAM.set_grad_checkpointingc                 C   s   | j S rq   ©rÅ   rÆ   r0   r0   r1   Úget_classifier  s    z#VisionTransformerSAM.get_classifierr   c                 C   s   | j  ||¡ d S rq   )rÅ   Úreset)rT   r›   r¬   r0   r0   r1   Úreset_classifier  s    z%VisionTransformerSAM.reset_classifierc                 C   sŽ   |   |¡}| jd k	r.|t| j|jdd… ƒ }|  |¡}|  |¡}|  |¡}| jrjtj	 
¡ sjt| j|ƒ}n
|  |¡}|  | dddd¡¡}|S )Nr   rB   r   r#   )r¼   r½   r   r*   r¾   r¿   rÀ   r»   r.   ÚjitZis_scriptingr   rÃ   rÄ   r-   ru   r0   r0   r1   Úforward_features  s    





z%VisionTransformerSAM.forward_features©Ú
pre_logitsc                 C   s   |r| j |dd�S |   |¡S )NTrÓ   rÍ   )rT   r_   rÔ   r0   r0   r1   Úforward_head*  s    z!VisionTransformerSAM.forward_headc                 C   s   |   |¡}|  |¡}|S rq   )rÒ   rÕ   ru   r0   r0   r1   rf   -  s    

zVisionTransformerSAM.forward)F)T)r   N)F)!rg   rh   ri   Ú__doc__r   r   r   ZNHWCrI   rl   r‡   rv   r   r(   Úfloatrj   r   Ústrr   r   rE   r.   rÑ   ÚignorerÇ   rÊ   rÌ   rÎ   rÐ   rÒ   rÕ   rf   rn   r0   r0   rX   r1   r   >  s¬     ÿÝ
Ý A


c                 C   sT   d| k}i }|   ¡ D ]:\}}| d¡r@|dd… }| dd¡}n|rFq|||< q|S )z Remap SAM checkpoints -> timm z%image_encoder.patch_embed.proj.weightzimage_encoder.r•   Nzmlp.linzmlp.fc)ÚitemsÚ
startswithÚreplace)Z
state_dictÚmodelZsam_checkpointZout_dictrc   rd   r0   r0   r1   Úcheckpoint_filter_fn3  s    

rÞ   r”   c                 K   s    | ddd dddt tdddœ|–S )	Néè  ©rB   r�   r�   çÍÌÌÌÌÌì?ZbicubicTzpatch_embed.projzhead.fc)Úurlr›   r@   Z	pool_sizeÚcrop_pctÚinterpolationZfixed_input_sizeÚmeanÚstdZ
first_convÚ
classifier)r	   r
   )râ   Úkwargsr0   r0   r1   Ú_cfgE  s          ûúré   zDhttps://dl.fbaipublicfiles.com/segment_anything/sam_vit_b_01ec64.pthztimm/z
apache-2.0rà   r'   )râ   Z	hf_hub_idÚlicenserå   ræ   r›   r@   rã   zDhttps://dl.fbaipublicfiles.com/segment_anything/sam_vit_l_0b3195.pthzDhttps://dl.fbaipublicfiles.com/segment_anything/sam_vit_h_4b8939.pthrß   )rB   éà   rë   rá   )rå   ræ   r›   r@   rã   )zsamvit_base_patch16.sa1bzsamvit_large_patch16.sa1bzsamvit_huge_patch16.sa1bÚsamvit_base_patch16_224Fc                 K   s,   |  dd ¡rtdƒ‚tt| |fdti|—ŽS )NZfeatures_onlyz<features_only not implemented for Vision Transformer models.Zpretrained_filter_fn)ÚgetÚRuntimeErrorr   r   rÞ   )ÚvariantÚ
pretrainedrè   r0   r0   r1   Ú_create_vision_transformerl  s    ÿýüûrñ   )r"   c              
   K   s>   t ddddddddgdd	d
d�}tdd| it |f|Ž—Ž}|S )z# ViT-B/16 for Segment-Anything
    r‘   r’   r“   r#   rˆ   r=   é   r•   Tr�   ©r™   rœ   r�   rG   rª   ry   r?   r˜   Úsamvit_base_patch16rð   )rô   ©rÉ   rñ   ©rð   rè   Z
model_argsrÝ   r0   r0   r1   rô   z  s$        
  þ ÿÿ
ÿrô   c              
   K   s>   t ddddddddgdd	dd
�}tdd| it |f|Ž—Ž}|S )z# ViT-L/16 for Segment-Anything
    r‘   r�   é   rˆ   rò   é   é   r•   Tró   Úsamvit_large_patch16rð   )rú   rõ   rö   r0   r0   r1   rú   ‡  s$        
  þ ÿÿ
ÿrú   c              
   K   s>   t ddddddddgdd	d
d�}tdd| it |f|Ž—Ž}|S )z# ViT-H/16 for Segment-Anything
    r‘   i   é    é   é   rù   é   r•   Tr�   ró   Úsamvit_huge_patch16rð   )rÿ   rõ   rö   r0   r0   r1   rÿ   ”  s$        
  þ ÿÿ
ÿrÿ   c                 K   sB   t ddddddddgdd	d
ddd�
}tdd| it |f|Ž—Ž}|S )z# ViT-B/16 based on samvit arch
    r‘   r’   r“   r#   rˆ   r=   rò   r•   TFrë   N)
r™   rœ   r�   rG   rª   ry   r?   r¨   r˜   r«   rì   rð   )rì   rõ   rö   r0   r0   r1   rì   ¡  s(        
    þ ÿÿ
ÿrì   )N)r”   )F)F)F)F)F)DrÖ   ÚloggingÚ	functoolsr   Útypingr   r   r   r.   Ztorch.nnrI   Ztorch.nn.functionalr]   r+   Ztorch.utils.checkpointZ	torch.jitr   Z	timm.datar   r   r	   r
   Ztimm.layersr   r   r   r   r   r   r   r   r   r   r   r   r   Z_builderr   Z_manipulater   Ú	_registryr   r   Z_features_fxr   Ú__all__Ú	getLoggerrg   Z_loggerr(   ZTensorr2   r:   rm   r;   ro   rv   r„   r…   r   rÞ   ré   Zdefault_cfgsrñ   rô   rú   rÿ   rì   r0   r0   r0   r1   Ú<module>   s²   <
 

ú"R
J& ÿ  
 þ v
   û   û   û   þê
