B
    b                 @   s  d Z ddlmZ ddlmZ ddiZy
ejZW n: ek
rh   e	eds\ddlmZ
 e
je_dd ZY nX xe D ]\ZZeee qtW d	ZG d
d deZdd Zdd ZedfddZdd Zdd Zed fddZdd ZefddZdd Zef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#G d/d0 d0Z$d1d2 Z%d3d4 Z&d>d6d7Z'd8d9 Z(G d:d; d;Z)d<S )?a  PhyloXML reader/parser, writer, and associated functions.

Instantiates tree elements from a parsed PhyloXML file, and constructs an XML
file from a ``Bio.Phylo.PhyloXML`` object.

About capitalization:
 - phyloXML means the file format specification
 - PhyloXML means the Biopython module ``Bio.Phylo.PhyloXML`` and its classes
 - Phyloxml means the top-level class used by ``PhyloXMLIO.read`` (but not
   ``Bio.Phylo.read``!), containing a list of Phylogenies (objects derived from
   ``BaseTree.Tree``)

    )ElementTree)PhyloXMLphyzhttp://www.phyloxml.org_namespace_mapc             C   s   | t j|< dS )z"Set the namespace for ElementTree.N)r   r   )prefixuri r   3lib/python3.7/site-packages/Bio/Phylo/PhyloXMLIO.pyregister_namespace(   s    r
   Zunicodec               @   s   e Zd ZdZdS )PhyloXMLErrorzException raised when PhyloXML object construction cannot continue.

    XML syntax errors will be found and raised by the underlying ElementTree
    module; this exception is for valid XML that breaks the phyloXML
    specification.
    N)__name__
__module____qualname____doc__r   r   r   r	   r   4   s   r   c             C   s   t |  S )zParse a phyloXML file or stream and build a tree of Biopython objects.

    The children of the root node are phylogenies and possibly other arbitrary
    (non-phyloXML) objects.

    :returns: a single ``Bio.Phylo.PhyloXML.Phyloxml`` object.

    )Parserread)filer   r   r	   r   C   s    	r   c             C   s   t |  S )a  Iterate over the phylogenetic trees in a phyloXML file.

    This ignores any additional data stored at the top level, but may be more
    memory-efficient than the ``read`` function.

    :returns: a generator of ``Bio.Phylo.PhyloXML.Phylogeny`` objects.

    )r   parse)r   r   r   r	   r   O   s    	r   Tc                s~   dd  t | tjrnTt | tjjtjjfr: |  } n0t| drbtji  fdd| D d} ntdt	| j
|||dS )	aR  Write a phyloXML file.

    :Parameters:
        obj
            an instance of ``Phyloxml``, ``Phylogeny`` or ``BaseTree.Tree``,
            or an iterable of either of the latter two. The object will be
            converted to a Phyloxml object before serialization.
        file
            either an open handle or a file name.

    c             S   sn   t | tjr| S t | tjr$|  S t | tjjr>tj| S t | tjjrbtjtjj| dS tdd S )N)rootz)iterable must contain Tree or Clade types)	
isinstancePX	PhylogenyCladeZto_phylogenyBaseTreeTreeZ	from_tree
ValueError)treer   r   r	   
fix_singleh   s    zwrite.<locals>.fix_single__iter__c             3   s   | ]} |V  qd S )Nr   ).0t)r   r   r	   	<genexpr>y   s    zwrite.<locals>.<genexpr>)phylogenieszXFirst argument must be a Phyloxml, Phylogeny, Tree, or iterable of Trees or Phylogenies.)encodingindent)r   r   Phyloxmlr   r   r   Zto_phyloxmlhasattrr   Writerwrite)objr   r#   r$   r   )r   r	   r(   [   s    
r(   c             C   s&   | d dkr"| |  dd d S | S )z;Extract the local tag from a namespaced tag name (PRIVATE).r   {}   N)index)tagr   r   r	   _local   s    r/   c             C   s2   y| dd  ddS  tk
r,   d| fS X dS )z;Split a tag into namespace and local tag strings (PRIVATE).r,   Nr+    )splitr   )r.   r   r   r	   _split_namespace   s    r2   c             C   s   d|| f S )z5Format an XML tag with the given namespace (PRIVATE).z{%s}%sr   )r.   	namespacer   r   r	   _ns   s    r4   c             C   s"   |  t|}|dk	r||S dS )z|Find a child node by tag, and pass it through a constructor (PRIVATE).

    Returns None if no matching child is found.
    N)findr4   )parentr.   	constructchildr   r   r	   _get_child_as   s    r9   c             C   s*   |  t|}|dk	r&|jr&||jS dS )z~Find a child node by tag; pass its text through a constructor (PRIVATE).

    Returns None if no matching child is found.
    N)r5   r4   text)r6   r.   r7   r8   r   r   r	   _get_child_text   s    r;   c                s    fdd|  t|D S )zFind child nodes by tag; pass each through a constructor (PRIVATE).

    Returns an empty list if no matching child is found.
    c                s   g | ]} |qS r   r   )r   r8   )r7   r   r	   
<listcomp>   s    z$_get_children_as.<locals>.<listcomp>)findallr4   )r6   r.   r7   r   )r7   r	   _get_children_as   s    r>   c                s    fdd|  t|D S )zFind child nodes by tag; pass each node's text through a constructor (PRIVATE).

    Returns an empty list if no matching child is found.
    c                s   g | ]}|j r |j qS r   )r:   )r   r8   )r7   r   r	   r<      s    z&_get_children_text.<locals>.<listcomp>)r=   r4   )r6   r.   r7   r   )r7   r	   _get_children_text   s    r?   c             C   s   d|d  }t | r|| jr$| j s.|d | _x4| D ],}t||d  |jrV|j s4|d |_q4W |jrt|j s||_n|r| jr| j s|| _dS )zAdd line breaks and indentation to ElementTree in-place (PRIVATE).

    Sources:
     - http://effbot.org/zone/element-lib.htm#prettyprint
     - http://infix.se/2007/02/06/gentlemen-indent-your-xml

    
z  r,   N)lenr:   strip_indenttail)elemlevelier   r   r	   rC      s    

rC   c             C   s8   | dks| dkrdS | dks$| dkr(dS t d|  dS )	z$Convert string to boolean (PRIVATE).true1TZfalse0Fz*String could not be converted to boolean: N)r   )r:   r   r   r	   	_str2bool   s
    rL   c             C   s2   |   }x$|D ]}||krt|| ||< qW |S )zQReturn a new dictionary where string values are replaced with booleans (PRIVATE).)copyrL   )Zdctkeysoutkeyr   r   r	   _dict_str2bool   s
    
rQ   c             C   s*   | dk	r&yt | S  tk
r$   dS X dS )z$Return text as an integer (PRIVATE).N)int	Exception)r:   r   r   r	   _int   s
    rT   c             C   s*   | dk	r&yt | S  tk
r$   dS X dS )z!Return text as a float (PRIVATE).N)floatrS   )r:   r   r   r	   _float   s
    rV   c             C   s   | dk	rd |  S dS )a  Replace all spans of whitespace with a single space character (PRIVATE).

    Also remove leading and trailing whitespace. See "Collapse Whitespace
    Policy" in the phyloXML spec glossary:
    http://phyloxml.org/documentation/version_100/phyloxml.xsd.html#Glossary
    N )joinr1   )r:   r   r   r	   _collapse_wspace   s    rY   c             C   s&   x dD ]}|| kr|  |d} qW | S )zReplace tab, LF and CR characters with spaces, but don't collapse (PRIVATE).

    See "Replace Whitespace Policy" in the phyloXML spec glossary:
    http://phyloxml.org/documentation/version_100/phyloxml.xsd.html#Glossary
    )	r@   rW   )replace)r:   charr   r   r	   _replace_wspace
  s    
r^   c               @   s"  e Zd ZdZdd Zdd Zdd Zdd	 Zd
dddgZdddddZ	e
ee	 ddddg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/d0 Zd1d2 Zd3d4 Zd5d6 Zd7d8 Zd9d: Zd;d< Z d=d> Z!d?d@ Z"dAdB Z#dCdD Z$dES )Fr   a  Methods for parsing all phyloXML nodes from an XML stream.

    To minimize memory use, the tree of ElementTree parsing events is cleared
    after completing each phylogeny, clade, and top-level 'other' element.
    Elements below the clade level are kept in memory until parsing of the
    current clade is finished -- this shouldn't be a problem because clade is
    the only recursive element, and non-clade nodes below this level are of
    bounded size.
    c             C   s.   t tj|dd}t|\}}|| _|| _dS )zInitialize the class.)startend)eventsN)iterr   Z	iterparsenextr   context)selfr   rd   eventr   r   r   r	   __init__!  s    zParser.__init__c       	      C   s   t dd | j D }d}x| jD ]\}}t|j\}}|dkrx|td krZ|d7 }q&|dkrx| |}|j	
| |dkr&|td kr&|d8 }|dkr&| |||}|j
| | j  q&W |S )	z<Parse the phyloXML file and create a single Phyloxml object.c             S   s   i | ]\}}|t |qS r   )r/   )r   rP   valr   r   r	   
<dictcomp>+  s    zParser.read.<locals>.<dictcomp>r   r_   r   r,   	phylogenyr`   )r   r%   r   itemsrd   r2   r.   
NAMESPACES_parse_phylogenyr"   appendotherclear)	re   phyloxmlZother_depthrf   rE   r3   localtagrj   otrr   r   r	   r   )  s$    
zParser.readc             c   s>   t d}x0| jD ]&\}}|dkr|j|kr| |V  qW dS )z@Parse the phyloXML file incrementally and return each phylogeny.rj   r_   N)r4   rd   r.   rm   )re   Zphytagrf   rE   r   r   r	   r   @  s    zParser.parsec             C   s8  t jf t|jddg}ddddd}x
| jD  ]\}}t|j\}}|dkrx|d	krx|jd
k	rjtd| 	||_q0|dkr0|dkr|
  P ||krt||| t| || q0|dkrt||t| || q0|dkrt||t|j q0|td kr$|j| ||| |
  q0td| q0W |S )a  Parse a single phylogeny within the phyloXML tree (PRIVATE).

        Recursively builds a phylogenetic tree with help from parse_clade, then
        clears the XML event history for the phylogeny element and returns
        control to the top-level parsing function.
        rooted
rerootableconfidences
propertiesclade_relationssequence_relations)
confidencepropertyclade_relationsequence_relationr_   cladeNz)Phylogeny object should only have 1 clader`   rj   )dateid)namedescriptionr   zMisidentified tag: )r   r   rQ   attribrd   r2   r.   r   r   _parse_claderp   getattrrn   setattrrY   r:   rl   ro   r   )re   r6   rj   Z
list_typesrf   rE   r3   r.   r   r   r	   rm   I  s8    
 
zParser._parse_phylogenycolorra   binary_charactersr   rv   distributions
referencesrw   )rz   distribution	referencer{   branch_lengthr   node_idwidthc             C   s  t jf |j}|jdk	r$t|j|_g }x| jD ]\}}t|j\}}|dkr|dkrn|j	| 
| q2|dkr|j	| | q2|dkr|j	| | q2|| jkr|	| |dkr2|dkr|  P ||d krq2|  || jkrt|| j| 	t| || q2|| jkr<t||t| || q2|dkrh|jdk	rZtd	t|j|_q2|d
krt|j|_q2|dkrt|j|_q2|dkrt |j |jd|_q2|t d kr|j!	| !||| |  q2td| q2W |S )z;Parse a Clade node and its children, recursively (PRIVATE).Nr_   r~   taxonomysequencer`   r   z7Attribute branch_length was already set for this Clade.r   r   r   providerr   zMisidentified tag: )"r   r   r   r   rU   rd   r2   r.   cladesrn   r   
taxonomies_parse_taxonomy	sequences_parse_sequence_clade_tracked_tagsrp   pop_clade_list_typesr   _clade_complex_typesr   r   rV   r:   r   rY   r   IdrB   getr   rl   ro   )re   r6   r~   Z	tag_stackrf   rE   r3   r.   r   r   r	   r     s^    







zParser._parse_cladec             C   s   t jf |j}x| jD ]\}}t|j\}}|dkr|dkrF|  P |dkrft||t| || q|dkr|j	
| | q|dkrt|j|_q|dkrt|||j q|td kr|j
| ||| |  qW |S )z%Parse a molecular sequence (PRIVATE).r`   r   )	accessionmol_seqr   domain_architecture
annotationr   )symbollocationr   )r   Sequencer   rd   r2   r.   rp   r   r   annotationsrn   r   rY   r:   r   rl   ro   )re   r6   r   rf   rE   r3   r.   r   r   r	   r     s&    zParser._parse_sequencec             C   s   t jf |j}x| jD ]\}}t|j\}}|dkr|dkrF|  P |dkrft||t| || q|dkr|j	
t|j q|dkr|j
|j q|dkrt|||j q|td kr|j
| ||| |  qW |S )z2Parse taxonomic information for a clade (PRIVATE).r`   r   )r   r   common_namesynonym)codescientific_name	authorityrankr   )r   ZTaxonomyr   rd   r2   r.   rp   r   r   common_namesrn   rY   r:   synonymsrl   ro   )re   r6   r   rf   rE   r3   r.   r   r   r	   r     s&    zParser._parse_taxonomyc                s4   t j|||j|jr|j pd fdd|D dS )z/Create an Other object, a non-phyloXML element.Nc                s"   g | ]} j |ft|j qS r   )ro   r2   r.   )r   r8   )re   r   r	   r<     s    z Parser.other.<locals>.<listcomp>)valuechildren)r   ZOtherr   r:   rB   )re   rE   r3   rr   r   )re   r	   ro     s    zParser.otherc             C   s   t |j |dS )zCreate accession object.source)r   Z	Accessionr:   rB   r   )re   rE   r   r   r	   r     s    zParser.accessionc          	   C   sD   t jf tt|dt|d| jt|d| jt|d| jd|j	S )zCreate annotation object.descrz   r{   r   )r   rz   rw   r   )
r   Z
AnnotationrY   r;   r9   rz   r>   r{   r   r   )re   rE   r   r   r	   r     s    zParser.annotationc             C   sr   dd }t j|dt|dt|dt|dt|dt|d|t|d	|t|d
|t|d|d	S )z Create binary characters object.c             S   s
   t | dS )z$Get binary characters from subnodes.bc)r?   )rE   r   r   r	   	bc_getter	  s    z+Parser.binary_characters.<locals>.bc_gettertypegained_count
lost_countpresent_countabsent_countgainedlostpresentabsent)	r   r   r   r   r   r   r   r   r   )r   ZBinaryCharactersr   rT   r9   )re   rE   r   r   r   r	   r     s    


zParser.binary_charactersc          	   C   s6   t j|d|d|d|dt|d| jdS )z!Create clade relationship object.r   id_ref_0id_ref_1distancerz   )r   rz   )r   ZCladeRelationr   r9   rz   )re   rE   r   r   r	   r|     s    zParser.clade_relationc                s&    fdddD \}}}t |||S )zCreate branch color object.c             3   s   | ]}t  |tV  qd S )N)r;   rR   )r   r   )rE   r   r	   r!   '  s    zParser.color.<locals>.<genexpr>)redgreenblue)r   ZBranchColor)re   rE   r   r   r   r   )rE   r	   r   $  s    zParser.colorc             C   s   t t|j|dS )zCreate confidence object.r   )r   Z
ConfidencerV   r:   r   )re   rE   r   r   r	   rz   +  s    zParser.confidencec          	   C   s<   t j|dtt|dt|dtt|dtt|dtdS )zCreate date object.unitr   r   minimummaximum)r   r   r   r   r   )r   ZDater   rY   r;   rU   )re   rE   r   r   r	   r   /  s    

zParser.datec             C   s.   t jtt|dt|d| jt|d| jdS )z&Create geographic distribution object.r   pointpolygon)r   pointspolygons)r   ZDistributionrY   r;   r>   r   r   )re   rE   r   r   r	   r   9  s    zParser.distributionc             C   sB   t j|j t|dd t|dt|d|ddS )zCreate protein domain object.fromr,   torz   r   )rz   r   )r   ZProteinDomainr:   rB   rR   r   rV   )re   rE   r   r   r	   domainA  s    zParser.domainc             C   s"   t jt|dt|d| jdS )z"Create domain architecture object.lengthr   )r   domains)r   ZDomainArchitecturerR   r   r>   r   )re   rE   r   r   r	   r   K  s    zParser.domain_architecturec          	   C   s<   t jt|dt|dtt|dtt|dtt|d| jdS )zCreate events object.r   duplicationsspeciationslossesrz   )r   r   r   r   rz   )r   ZEventsr;   rR   r9   rz   )re   rE   r   r   r	   ra   R  s    


zParser.eventsc             C   s&   | dp| d}t|j |S )zCreate identifier object.r   r   )r   r   r   r:   rB   )re   rE   r   r   r   r	   r   \  s    z	Parser.idc             C   s.   | d}|dk	rt|}tj|j |dS )z!Create molecular sequence object.
is_alignedN)r   )r   rL   r   ZMolSeqr:   rB   )re   rE   r   r   r   r	   r   a  s    
zParser.mol_seqc             C   s8   t j|dt|dtt|dtt|dt|ddS )z,Create point object, coordinates of a point.geodetic_datumlatlongaltalt_unit)r   r   )r   ZPointr   r;   rU   )re   rE   r   r   r	   r   h  s    


zParser.pointc             C   s   t jt|d| jdS )z&Create polygon object, list of points.r   )r   )r   ZPolygonr>   r   )re   rE   r   r   r	   r   r  s    zParser.polygonc          	   C   s:   t j|j |d|d|d|d|ddS )z*Create properties from external resources.ref
applies_todatatyper   id_ref)r   r   )r   ZPropertyr:   rB   r   )re   rE   r   r   r	   r{   v  s    zParser.propertyc             C   s   t j|dt|ddS )z#Create literature reference object.doir   )r   r   )r   Z	Referencer   r;   )re   rE   r   r   r	   r     s    zParser.referencec          	   C   s:   t j|d|d|dt|dt|d| jdS )zHCreate sequence relationship object, relationship between two sequences.r   r   r   r   rz   )r   rz   )r   ZSequenceRelationr   rV   r9   rz   )re   rE   r   r   r	   r}     s    zParser.sequence_relationc             C   s&   t j|j t|d|ddS )z(Create uri object, expected to be a url.r   r   )r   r   )r   ZUrir:   rB   rY   r   )re   rE   r   r   r	   r     s    z
Parser.uriN)%r   r   r   r   rg   r   r   rm   r   r   setunionrN   r   r   r   r   ro   r   r   r   r|   r   rz   r   r   r   r   ra   r   r   r   r   r{   r   r}   r   r   r   r   r	   r     sH   		.
9






r   c             C   s4   t | trt|  S t | tr,t|  S t| S )zEConvert a Python primitive to a phyloXML-compatible string (PRIVATE).)r   rU   strupperboollower)r   r   r   r	   
_serialize  s
    

r   c             C   s4   i }x*|D ]"}t | |}|dk	r
t|||< q
W |S )zNCreate a dictionary from an object's specified, non-None attributes (PRIVATE).N)r   r   )r)   ZattrsrO   rP   rh   r   r   r	   _clean_attrib  s    

r   Fc                s     fdd}d |_ |S )z2Handle to serialize nodes with subnodes (PRIVATE).c                s   t t| }xpD ]h}t|trPt||dk	r|t| |t|| q|\}}x&t||D ]}|t| || qdW qW rt|j|_	|S )z$Wrap nodes and subnodes as elements.N)
r   Elementr   r   r   r   rn   r   r   r:   )re   r)   rE   subnmethodZpluralitem)attribshas_textsubnodesr.   r   r	   wrapped  s    

z _handle_complex.<locals>.wrappedz*Serialize a %s and its subnodes, in order.)r   )r.   r   r   r   r   r   )r   r   r   r.   r	   _handle_complex  s    
r   c                s    fdd}d  |_ |S )z+Handle to serialize simple nodes (PRIVATE).c                s   t  }t||_|S )zWrap node as element.)r   r   r   r:   )re   r)   rE   )r.   r   r	   r     s    

z_handle_simple.<locals>.wrappedzSerialize a simple %s node.)r   )r.   r   r   )r.   r	   _handle_simple  s    
r   c               @   s:  e Zd ZdZdd ZedfddZdd Zd	d
 Ze	dddZ
e	dddZe	dddddZe	dddZdd Ze	dddZe	dddZe	dd dddZe	d!d"d#Ze	d$dd%Zd&d' Ze	d(d)d*Ze	d+dd,Ze	d-d.dddZe	d/d0dddZe	d1d.dddZe	d2d3d4Ze	d5dd6Ze	d7d8dddZe	d9d:d;Ze	d<d=d>Ze	d?ddZe	d@ddAZ e	dBdCdddZ!e"dDZ#e"dEZ$e"dFZ%e"dGZ&e"dHZ'e"dIZ(e"dJZ)e"dKZ*e"dLZ+e"dMZ,e"dNZ-e"dOZ.e"dPZ/e"dQZ0e"dRZ1e"dSZ2e"dTZ3e"dUZ4e"dVZ5e"dWZ6e"dXZ7e"dYZ8e"dZZ9e"d[Z:e"d\Z;e"d]Z<d^S )_r'   z1Methods for serializing a PhyloXML object to XML.c             C   s*   t |tjstdt| || _dS )z,Build an ElementTree from a PhyloXML object.zNot a Phyloxml objectN)r   r   r%   AssertionErrorr   rq   _tree)re   rq   r   r   r	   rg     s    zWriter.__init__Tc             C   s.   |rt | j  | j|| t| j S )zWrite PhyloXML to a file.)rC   r   Zgetrootr(   rA   )re   r   r#   r$   r   r   r	   r(     s    zWriter.writec             C   sR   t d|j}x|jD ]}|| | qW x|jD ]}|| | q6W |S )z"Convert phyloxml to Etree element.rq   )r   r   
attributesr"   rn   rj   ro   )re   r)   rE   r   rs   r   r   r	   rq     s    zWriter.phyloxmlc             C   sD   t t|j|j|j}|j|_x|jD ]}|	| 
| q(W |S )zConvert other to Etree element.)r   r   r4   r.   r3   r   r   r:   r   rn   ro   )re   r)   rE   r8   r   r   r	   ro     s
    zWriter.otherrj   )rt   ru   Zbranch_length_unitr   )
r   r   r   r   )rz   rv   r~   )r|   rx   )r}   ry   )r{   rw   )ro   ro   r~   )	id_source)r   r   )rz   rv   r   r   r   )r   r   )r   r   ra   r   )r   r   r   )r   r   )r{   rw   )r~   r   )ro   ro   r   )r   r   )r   r   )r   r   Zevidencer   )r   rz   )r{   rw   r   c             C   s\   t dt|d}xDdD ]<}t |}x"t||D ]}|| | q2W || qW |S )z4Serialize a binary_characters node and its subnodes.r   )r   r   r   r   r   )r   r   r   r   )r   r   r   r   rn   r   )re   r)   rE   r   Zsubelemtokenr   r   r	   r   '  s    

zWriter.binary_charactersr|   )r   r   r   r   )rz   r   )r   r   r   rz   )r   r   )r   )r   r   r   r   r   )r   )r   r   )r   r   c             C   sf   t dt|jd t|jd}|jdk	r>|dt|j |jdk	rV|d|j t|j	|_
|S )zSerialize a domain node.r   r,   )r   r   Nrz   r   )r   r   r   r_   r`   rz   r   r   r   r   r:   )re   r)   rE   r   r   r	   r   E  s    

zWriter.domainr   )r   ))r   r   ra   )r   r   r   r   rz   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   r   r   r   r   r   )r   r   r   )ro   ro   r}   r   )	r   r   r   r   )r   r   )r   r   r   r   )ro   ro   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   r   N)=r   r   r   r   rg   DEFAULT_ENCODINGr(   rq   ro   r   rj   r~   r   r   r   r|   r   rz   r   r   r   r   ra   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   r   r   r   r   r   r   r   r   r   r   r   r   r   r	   r'     s   		




r'   N)r   )F)*r   Z	xml.etreer   Z	Bio.Phylor   r   rl   r
   AttributeErrorr&   ZET_pyr   rk   r   r   r   rS   r   r   r   r(   r/   r2   r4   r9   r   r;   r>   r?   rC   rL   rQ   rT   rV   rY   r^   r   r   r   r   r   r'   r   r   r   r	   <module>   sP   

+


				   
	

