o
    i                     @   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	G dd de
Zzd dlmZ W n ey?   dZY n
w G dd dejZzd dlmZ W n ey\   dZY n
w G dd dejZd7d	d
Zd7ddZdd Zdd Zdd Zdd Ze	jdfddZdd Zd8ddZd7dd Zd!d" Zd#d$ Zd%d& Zd'd( Z d)d* Z!d+d, Z"d-d. Z#	/			0	0	0	1	0	0	0	1	2d9d3d4Z$d5d6 Z%dS ):    Nc                   @   s*   e Zd ZdZd
ddZdd Zdd Zd	S )CompareValueTriggera  Trigger invoked when key value getting bigger or lower than before.

    Args:
        key (str) : Key of value.
        compare_fn ((float, float) -> bool) : Function to compare the values.
        trigger (tuple(int, str)) : Trigger that decide the comparison interval.

       epochc                 C   s8   ddl m} || _d | _|j|| _|   || _d S )Nr   training)	chainerr   _key_best_valueutilget_trigger_interval_trigger_init_summary_compare_fn)selfkey
compare_fntriggerr    r   H/home/ubuntu/.local/lib/python3.10/site-packages/espnet/asr/asr_utils.py__init__   s   
zCompareValueTrigger.__init__c                 C   s   |j }| j}| j}||v r|||| i | |sdS | }t|| }|   | jdu r5|| _dS | 	| j|r>dS || _dS )z<Get value related to the key and compare with current value.FNT)
observation_summaryr	   addr   compute_meanfloatr   r
   r   )r   trainerr   summaryr   statsvaluer   r   r   __call__%   s"   

zCompareValueTrigger.__call__c                 C   s   dd l }|j | _d S )Nr   )r   reporterDictSummaryr   )r   r   r   r   r   r   >   s   z!CompareValueTrigger._init_summaryN)r   )__name__
__module____qualname____doc__r   r    r   r   r   r   r   r      s
    
		r   	extensionc                   @   s`   e Zd 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dZdS )PlotAttentionReporta  Plot attention reporter.

        Args:
            att_vis_fn (espnet.nets.*_backend.e2e_asr.E2E.calculate_all_attentions):
                Function of attention visualization.
            data (list[tuple(str, dict[str, list[Any]])]): List json utt key items.
            outdir (str): Directory to save figures.
            converter (espnet.asr.*_backend.asr.CustomConverter):
                Function to convert data.
            device (int | torch.device): Device.
            reverse (bool): If True, input and output length are reversed.
            ikey (str): Key to access input
                (for ASR/ST ikey="input", for MT ikey="output".)
            iaxis (int): Dimension to access input
                (for ASR/ST iaxis=0, for MT iaxis=1.)
            okey (str): Key to access output
                (for ASR/ST okey="input", MT okay="output".)
            oaxis (int): Dimension to access output
                (for ASR/ST oaxis=0, for MT oaxis=0.)
            subsampling_factor (int): subsampling factor in encoder

        Finputr   outputr   c                 C      || _ t|| _dd t|D | _|| _|| _|| _|| _|| _	|| _
|	| _|
| _|| _|| _tj| jsAt| j d S d S )Nc                 S      i | ]\}}||qS r   r   .0kvr   r   r   
<dictcomp>s       z0PlotAttentionReport.__init__.<locals>.<dictcomp>)
att_vis_fncopydeepcopydata	data_dictoutdir	converter	transformdevicereverseikeyiaxisokeyoaxisfactorospathexistsmakedirs)r   r4   r7   r9   r:   r;   r<   r=   r>   r?   r@   rA   subsampling_factorr   r   r   r   b       zPlotAttentionReport.__init__c           
      C   s  |   \}}t|trt|d }t|D ]?}t|| D ]6\}}d| j|| |d f }| || |}d| j|| |d f }	t	|	
|| | ||
| qqt|| D ]2\}}d| j|| f }| || |}d| j|| f }	t	|	
|| | j||
|dd q[d
S t|D ]0\}}d| j|| f }| || |}d	| j|| f }	t	|	
|| | ||
| qd
S )z*Plot and save image file of att_ws matrix.r   z#%s/%s.ep.{.updater.epoch}.att%d.pngz#%s/%s.ep.{.updater.epoch}.att%d.npyz!%s/%s.ep.{.updater.epoch}.han.pngz!%s/%s.ep.{.updater.epoch}.han.npyT)han_mode%s/%s.ep.{.updater.epoch}.png%s/%s.ep.{.updater.epoch}.npyN)get_attention_weights
isinstancelistlenrange	enumerater9   trim_attention_weightnpsaveformat_plot_and_save_attention)
r   r   att_ws
uttid_listnum_encsiidxatt_wfilenamenp_filenamer   r   r   r       s^   
zPlotAttentionReport.__call__c           
      C   s  |   \}}t|trht|d }t|D ]+}t|| D ]"\}}| || |}| |}	|d|| |d f |		 | qqt|| D ]\}}| || |}| 
|}	|d||  |		 | qGdS t|D ]\}}| || |}| |}	|d||  |		 | qldS )z4Add image files of att_ws matrix to the tensorboard.r   z%s_att%dz%s_han%sN)rL   rM   rN   rO   rP   rQ   rR   draw_attention_plot
add_figuregcfdraw_han_plot)
r   loggersteprW   rX   rY   rZ   r[   r\   plotr   r   r   log_attentions   s6   

	

	
z"PlotAttentionReport.log_attentionsc                 C   X   | j | jdd\}}| |g| j}t|tr | j| }||fS | jdi |}||fS )ad  Return attention weights.

            Returns:
                numpy.ndarray: attention weights. float. Its shape would be
                    differ from backend.
                    * pytorch-> 1) multi-head case => (B, H, Lmax, Tmax), 2)
                      other case => (B, Lmax, Tmax).
                    * chainer-> (B, Lmax, Tmax)

            Treturn_uttidNr   )r;   r7   r:   r<   rM   tupler4   )r   return_batchrX   batchrW   r   r   r   rL      s   

z)PlotAttentionReport.get_attention_weightsc           	      C   s   | j r| j| j}}| j| j}}n| j| j}}| j| j}}t| j| | | d d }t| j| | | d d }| jdkrH|| j }t|j	dkr^|ddd|d|f }|S |d|d|f }|S )z7Transform attention matrix with regard to self.reverse.shaper   r      N)
r=   r@   rA   r>   r?   intr8   rB   rO   rn   )	r   uttidr\   enc_keyenc_axisdec_keydec_axisdec_lenenc_lenr   r   r   rR      s   

z)PlotAttentionReport.trim_attention_weightc                 C   s   ddl }|d ddlm} |  |tj}t|j	dkrEt
|dD ]\}}|dt|| |j|dd |d |d	 q%n|j|dd |d |d	 |  |S )
zPlot the att_w matrix.

            Returns:
                matplotlib.pyplot: pyplot object with attention matrix image.

            r   NAggro   r   auto)aspectzEncoder IndexDecoder Index)
matplotlibusematplotlib.pyplotpyplotclfastyperS   float32rO   rn   rQ   subplotimshowxlabelylabeltight_layout)r   r\   r|   plthawr   r   r   r`      s"   



z'PlotAttentionReport.draw_attention_plotc                 C   sx  ddl }|d ddlm} |  t|jdkrrt|dD ]Q\}}g }|dt|| t	|jd D ]}|
|dd|f  |d| q5|ddg |d|jd g |d |d	 |d
 || qnDg }t	|jd D ]}|
|dd|f  |d| q{|ddg |d|jd g |d |d	 |d
 || |  |S )zPlot the att_w matrix for hierarchical attention.

            Returns:
                matplotlib.pyplot: pyplot object with attention matrix image.

            r   Nrx   ro   r   zAtt{}      ?TzAttention Weightr{   )r|   r}   r~   r   r   rO   rn   rQ   r   rP   rf   appendrU   ylimxlimgridr   r   legendr   )r   r\   r|   r   r   r   legendsrZ   r   r   r   rc     s<   







z!PlotAttentionReport.draw_han_plotc                 C   s0   |r|  |}n| |}|| |  d S N)rc   r`   savefigclose)r   r\   r]   rI   r   r   r   r   rV   :  s
   

z,PlotAttentionReport._plot_and_save_attentionNFr*   r   r+   r   r   )F)r#   r$   r%   r&   r   r    rg   rL   rR   r`   rc   rV   r   r   r   r   r)   J   s     
 2(r)   c                   @   sV   e Zd 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S )PlotCTCReporta  Plot CTC reporter.

        Args:
            ctc_vis_fn (espnet.nets.*_backend.e2e_asr.E2E.calculate_all_ctc_probs):
                Function of CTC visualization.
            data (list[tuple(str, dict[str, list[Any]])]): List json utt key items.
            outdir (str): Directory to save figures.
            converter (espnet.asr.*_backend.asr.CustomConverter):
                Function to convert data.
            device (int | torch.device): Device.
            reverse (bool): If True, input and output length are reversed.
            ikey (str): Key to access input
                (for ASR/ST ikey="input", for MT ikey="output".)
            iaxis (int): Dimension to access input
                (for ASR/ST iaxis=0, for MT iaxis=1.)
            okey (str): Key to access output
                (for ASR/ST okey="input", MT okay="output".)
            oaxis (int): Dimension to access output
                (for ASR/ST oaxis=0, for MT oaxis=0.)
            subsampling_factor (int): subsampling factor in encoder

        Fr*   r   r+   r   c                 C   r,   )Nc                 S   r-   r   r   r.   r   r   r   r2   r  r3   z*PlotCTCReport.__init__.<locals>.<dictcomp>)
ctc_vis_fnr5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rF   )r   r   r7   r9   r:   r;   r<   r=   r>   r?   r@   rA   rG   r   r   r   r   a  rH   zPlotCTCReport.__init__c           
      C   s  |   \}}t|trWt|d }t|D ]?}t|| D ]6\}}d| j|| |d f }| || |}d| j|| |d f }	t	|	
|| | ||
| qqdS t|D ]0\}}d| j|| f }| || |}d| j|| f }	t	|	
|| | ||
| q[dS )z%Plot and save image file of ctc prob.r   z#%s/%s.ep.{.updater.epoch}.ctc%d.pngz#%s/%s.ep.{.updater.epoch}.ctc%d.npyrJ   rK   N)get_ctc_probsrM   rN   rO   rP   rQ   r9   trim_ctc_probrS   rT   rU   _plot_and_save_ctc)
r   r   	ctc_probsrX   rY   rZ   r[   ctc_probr]   r^   r   r   r   r      sB   
zPlotCTCReport.__call__c           
      C   s   |   \}}t|trCt|d }t|D ]+}t|| D ]"\}}| || |}| |}	|d|| |d f |		 | qqdS t|D ]\}}| || |}| |}	|d||  |		 | qGdS )z0Add image files of ctc probs to the tensorboard.r   z%s_ctc%dr_   N)
r   rM   rN   rO   rP   rQ   r   draw_ctc_plotra   rb   )
r   rd   re   r   rX   rY   rZ   r[   r   rf   r   r   r   log_ctc_probs  s&   



zPlotCTCReport.log_ctc_probsc                 C   rh   )zReturn CTC probs.

            Returns:
                numpy.ndarray: CTC probs. float. Its shape would be
                    differ from backend. (B, Tmax, vocab).

            Tri   Nr   )r;   r7   r:   r<   rM   rk   r   )r   rl   rX   rm   probsr   r   r   r     s   

zPlotCTCReport.get_ctc_probsc                 C   sF   t | j| | j | j d d }| jdkr|| j }|d| }|S )z.Trim CTC posteriors accoding to input lengths.rn   r   r   N)rp   r8   r>   r?   rB   )r   rq   probrw   r   r   r   r     s
   "

zPlotCTCReport.trim_ctc_probc           	      C   s  ddl }|d ddlm} |tj}|  tj|dd}|j	\}}t
|}|jdd t|d D ]#}|dkrP|j||dddf d	d
dd q9|||dd|f  q9|jddd |jddd |ttdt|d d |ttddd |  |S )zPlot the ctc_prob matrix.

            Returns:
                matplotlib.pyplot: pyplot object with CTC prob matrix image.

            r   Nrx   r   )axis)      )figsize:z<blank>grey)labelcolorzInput [frame]   )fontsize
Posteriors
      )r|   r}   r~   r   r   rS   r   r   argsortrn   arangefiguresetreshapetolistrf   r   r   xticksrN   rP   rp   yticksr   )	r   r   r|   r   topk_idsn_framesvocabtimes_probsr[   r   r   r   r     s*   


zPlotCTCReport.draw_ctc_plotc                 C   s    |  |}|| |  d S r   )r   r   r   )r   r   r]   r   r   r   r   r     s   

z PlotCTCReport._plot_and_save_ctcNr   )r#   r$   r%   r&   r   r    r   r   r   r   r   r   r   r   r   r   I  s    
 "$r   c                    sD   ddl }ddl m}  du r|jj |jdd fdd}|S )zQExtension to restore snapshot.

    Returns:
        An extension function.

    r   Nr   r   r   c                    s   t   d S r   )_restore_snapshotr   load_fnmodelsnapshotr   r   restore_snapshot  s   z*restore_snapshot.<locals>.restore_snapshot)r   r   serializersload_npzmake_extension)r   r   r   r   r   r   r   r   r   r     s   
r   c                 C   s8   |d u rdd l }|jj}|||  tdt|  d S )Nr   zrestored from )r   r   r   logginginfostr)r   r   r   r   r   r   r   r     s
   
r   c                    (   ddl m} |jdd fdd}|S )zExtension to perform adadelta eps decay.

    Args:
        eps_decay (float): Decay rate of eps.

    Returns:
        An extension function.

    r   r   r   r   c                       t |   d S r   )_adadelta_eps_decayr   	eps_decayr   r   adadelta_eps_decay#     z.adadelta_eps_decay.<locals>.adadelta_eps_decayr   r   r   )r   r   r   r   r   r   r        

r   c                 C   z   | j d}t|dr"|j}t|d||  tdt|j  d S |jD ]}|d  |9  < tdt|d   q%d S )Nmainepszadadelta eps decayed to )	updaterget_optimizerhasattrr   setattrr   r   r   param_groups)r   r   	optimizercurrent_epspr   r   r   r   *     

r   c                    r   )zExtension to perform adam lr decay.

    Args:
        eps_decay (float): Decay rate of lr.

    Returns:
        An extension function.

    r   r   r   r   c                    r   r   )_adam_lr_decayr   r   r   r   adam_lr_decayD  r   z$adam_lr_decay.<locals>.adam_lr_decayr   )r   r   r   r   r   r   r   8  r   r   c                 C   r   )Nr   lrzadam lr decayed to )	r   r   r   r   r   r   r   r   r   )r   r   r   
current_lrr   r   r   r   r   K  r   r   zsnapshot.ep.{.updater.epoch}c                    ,   ddl m} |jddd fdd}|S )ziExtension to take snapshot of the trainer for pytorch.

    Returns:
        An extension function.

    r   r'   r   r   priorityc                    s   t | |  |  d S r   )_torch_snapshot_objectrU   r   r]   savefunr   r   torch_snapshotb  s   z&torch_snapshot.<locals>.torch_snapshotchainer.trainingr(   r   )r   r]   r(   r   r   r   r   r   Y  s   r   c              	   C   s  ddl m} | }||  t| jjdr.t| jjjdr&| jjjj }n| jjj }nt| jjdr=| jjj }n| jj }|j|| j	d d}|
| }d| }	tj|	| jd}
tj|
|}z||| t|tj| j| W t|
 d S t|
 w )	Nr   )DictionarySerializerr   moduler   )r   r   r   tmp)prefixdir)chainer.serializersr   rT   r   r   r   r   
state_dicttargetr   rU   tempfilemkdtempoutrC   rD   joinshutilmovermtree)r   r   r]   r   r   smodel_state_dictsnapshot_dictfnr   tmpdirtmppathr   r   r   r   i  s,   


r   d   r   皙?c           
      C   sb   || d }|||  }|   D ]}|jdur.|j }|t||j }	| j|	7  _qdS )a'  Adds noise from a standard normal distribution to the gradients.

    The standard deviation (`sigma`) is controlled by the three hyper-parameters below.
    `sigma` goes to zero (no noise) with more iterations.

    Args:
        model (torch.nn.model): Model.
        iteration (int): Number of iterations.
        duration (int) {100, 1000}:
            Number of durations to control the interval of the `sigma` change.
        eta (float) {0.01, 0.3, 1.0}: The magnitude of `sigma`.
        scale_factor (float) {0.55}: The scale of `sigma`.
    r   N)
parametersgradsizetorchrandntor<   )
r   	iterationdurationetascale_factorintervalsigmaparam_shapenoiser   r   r   add_gradient_noise  s   

r  c                 C   s   |du rt j| d }n|}t|d}td|  t|}W d   n1 s+w   Y  t|t	r?|}t
jdi |S |\}}}||t
jdi |fS )a  Get model config information by reading a model config file (model.json).

    Args:
        model_path (str): Model path.
        conf_path (str): Optional model config path.

    Returns:
        list[int, int, dict[str, Any]]: Config information loaded from json file.

    Nz/model.jsonrbzreading a config file from r   )rC   rD   dirnameopenr   r   jsonloadrM   dictargparse	Namespace)
model_path	conf_path
model_conffconfsargsidimodimr   r   r   get_model_conf  s   

r#  c                 C   s@   ddl }dtj| v r|jj| |dd dS |j| | dS )zLoad chainer model parameters.

    Args:
        path (str): Model path or snapshot file path to be loaded.
        model (chainer.Chain): Chainer model.

    r   Nr   zupdater/model:main/)rD   )r   rC   rD   basenamer   r   )rD   r   r   r   r   r   chainer_load  s   r%  c                 C   s4   t |drt|j |  dS t| |  dS )zSave torch model states.

    Args:
        path (str): Model path to be saved.
        model (torch.nn.Module): Torch model.

    r   N)r   r  rT   r   r   )rD   r   r   r   r   
torch_save  s   
r&  c                    r   )a  Returns a trainer extension to take snapshots of a given object.

    Args:
        target (model): Object to serialize.
        filename (str): Name of the file into which the object is serialized.It can
            be a format string, where the trainer object is passed to
            the :meth: `str.format` method. For example,
            ``'snapshot_{.updater.iteration}'`` is converted to
            ``'snapshot_10000'`` at the 10,000th iteration.

    Returns:
        An extension function.

    r   r'   r   r   r   c                    s    t tj| j |  d S r   )r&  rC   rD   r   r   rU   r   r]   r   r   r   snapshot_object  s    z(snapshot_object.<locals>.snapshot_objectr   )r   r]   r(   r(  r   r'  r   r(    s   r(  c                 C   sf   dt j| v rtj| dd dd }n	tj| dd d}t|dr+|j| ~dS || ~dS )	zLoad torch model states.

    Args:
        path (str): Model path or snapshot file path to be loaded.
        model (torch.nn.Module): Torch model.

    r   c                 S      | S r   r   storagelocr   r   r   <lambda>       ztorch_load.<locals>.<lambda>map_locationr   c                 S   r)  r   r   r*  r   r   r   r-    r.  r   N)rC   rD   r$  r  r  r   r   load_state_dict)rD   r   r   r   r   r   
torch_load  s   

r2  c                 C   s   ddl m} tj| dd d}||d }|| t|jjdr@t|jjjdr5|jjjj|d  n&|jjj|d  nt|jjdrR|jjj|d  n	|jj|d  |j	d	|d
  ~dS )zResume from snapshot for pytorch.

    Args:
        snapshot_path (str): Snapshot file path.
        trainer (chainer.training.Trainer): Chainer's trainer instance.

    r   )NpzDeserializerc                 S   r)  r   r   r*  r   r   r   r-    r.  ztorch_resume.<locals>.<lambda>r/  r   r   r   r   r   N)
r   r3  r  r  r   r   r   r   r1  r   )snapshot_pathr   r3  r   dr   r   r   torch_resume  s   
r6  c                    st   t tt| d dd } fdd|D }t| d }ddd |D }d|}d	|d
d}||||fS )zParse hypothesis.

    Args:
        hyp (list[dict[str, Any]]): Recognition hypothesis.
        char_list (list[str]): List of characters.

    Returns:
        tuple(str, str, str, float)

    yseqr   Nc                    s   g | ]} | qS r   r   r/   r[   	char_listr   r   
<listcomp>B      z$parse_hypothesis.<locals>.<listcomp>score c                 S   s   g | ]}t |qS r   )r   r8  r   r   r   r;  F  r<   z<space>)rN   maprp   r   r   replace)hypr:  tokenid_as_listtoken_as_listr=  tokenidtokentextr   r9  r   parse_hypothesis5  s   
rH  c                 C   s   t  }| d |d< g |d< t|dD ]a\}}t||\}}}}	t| d dkr2t | d d  }
nddi}
|
d  d| 7  < ||
d< ||
d	< ||
d
< |	|
d< |d |
 |dkrsd|
 v rjtd|
d   td|
d   q|S )aT  Add N-best results to json.

    Args:
        js (dict[str, Any]): Groundtruth utterance dict.
        nbest_hyps_sd (list[dict[str, Any]]):
            List of hypothesis for multi_speakers: nutts x nspkrs.
        char_list (list[str]): List of characters.

    Returns:
        dict[str, Any]: N-best results added utterance dict.

    utt2spkr+   r   r   namer?  z[%d]rec_text	rec_tokenrec_tokenidr=  rG  zgroundtruth: %szprediction : %s)	r  rQ   rH  rO   itemsr   keysr   r   )js
nbest_hypsr:  new_jsnrB  rK  rL  rM  r=  out_dicr   r   r   add_results_to_jsonM  s(   rU  dbTFinfernoc              
   C   s*  t |}|dkrdt |t |jj  }n|dkr|}nt||dur.|d }d}n|jd }d}|durI|durI|jd	 | | }d
}n|jd	 }d}d|d|f}| j|ddd ||d |	rm| 	d
| |
rw| d
| |  d
| | j|||||	|
||d | d dS )a  Plot spectrogram using matplotlib.

    Args:
        plt (matplotlib.pyplot): pyplot object.
        spec (numpy.ndarray): Input stft (Freq, Time)
        mode (str): db or linear.
        fs (int): Sample frequency. To convert y-axis to kHz unit.
        frame_shift (int): The frame shift of stft. To convert x-axis to second unit.
        bottom (bool):Whether to draw the respective ticks.
        left (bool):
        right (bool):
        top (bool):
        labelbottom (bool):Whether to draw the respective tick labels.
        labelleft (bool):
        labelright (bool):
        labeltop (bool):
        cmap (str): Colormap defined in matplotlib.

    rV  r   linearNi  kHzr   binr   r   framer   )cmapextentz	time [{}]z	freq [{}]z{})bottomleftrighttoplabelbottom	labelleft
labelrightlabeltopry   )rS   abslog10finfodtyper   
ValueErrorrn   r   r   rU   r   colorbar	set_labeltick_paramsr   )r   specmodefsframe_shiftr^  r_  r`  ra  rb  rc  rd  re  r\  xytopr   xtopr   r]  r   r   r   plot_spectrogram  sD   
#


ru  c                    s*  dddddddddd	d
d}|  D ]tt  trOtt   jkr?tdt  t  d j  t  d j t < qt  sh| t < td|  tdt   fddt	 jD   fddt	 jD t < q S )a  Format args for multi-encoder setup.

    It deals with following situations:  (when args.num_encs=2):
    1. args.elayers = None -> args.elayers = [4, 4];
    2. args.elayers = 4 -> args.elayers = [4, 4];
    3. args.elayers = [4, 4, 4] -> args.elayers = [4, 4].

    blstmp   i,  1g        doti@     r   r  )etypeelayerseunits	subsampledropout_rateatypeadimawinaheadsaconv_chansaconv_filtsz%Length mismatch {}: Convert {} to {}.Nz*{} is not specified, use default value {}.z#Type mismatch {}: Convert {} to {}.c                       g | ]}t   qS r   varsr/   _r   r0   r   r   r;        z&format_mulenc_args.<locals>.<listcomp>c                    r  r   r  r  r  r   r   r;    r  )
rO  rM   r  rN   rO   rY   r   warningrU   rP   )r   default_dictr   r  r   format_mulenc_args  sF     $$r  r   )r  r   r  )rV  NNTTTFTTTFrW  )&r  r5   r  r   rC   r   r   numpyrS   r  objectr   r   r(   ImportErrorr)   	Extensionr   r   r   r   r   r   r   rT   r   r   r  r#  r%  r&  r(  r2  r6  rH  rU  ru  r  r   r   r   r   <module>   sn   2 z 
1


$
'5
P