o
    RŀgC                     @   s~   d 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 ddl	m
Z
 G d	d
 d
eZedkr=ddlmZ e  dS dS )z3Bio.SearchIO object to model a single database hit.    )chain)allitems)getattr_str)optionalcascade   )_BaseSearchObject)HSPc                   @   s  e Zd 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 Zdd Zdd Zdd ZedddZeddd Zed!d"d#Zed$d%d&Zed'd(Zed)d* Zed+d, Zed-d. Zd/d0 Zd?d1d2Zd3d4 Zd?d5d6Zd@d8d9ZdAd<d=Z dS )BHita  Class representing a single database hit of a search result.

    Hit objects are the second-level container in the SearchIO module. They
    are the objects contained within a QueryResult (see QueryResult). They
    themselves are container for HSP objects and will contain at least one
    HSP.

    To have a quick look at a Hit and its contents, invoke ``print`` on it::

        >>> from Bio import SearchIO
        >>> qresult = next(SearchIO.parse('Blast/mirna.xml', 'blast-xml'))
        >>> hit = qresult[3]
        >>> print(hit)
        Query: 33211
               mir_1
          Hit: gi|301171322|ref|NR_035857.1| (86)
               Pan troglodytes microRNA mir-520c (MIR520C), microRNA
         HSPs: ----  --------  ---------  ------  ---------------  ---------------------
                  #   E-value  Bit score    Span      Query range              Hit range
               ----  --------  ---------  ------  ---------------  ---------------------
                  0   8.9e-20     100.47      60           [1:61]                [13:73]
                  1   3.3e-06      55.39      60           [0:60]                [13:73]

    You can invoke ``len`` on a Hit object to see how many HSP objects it contains::

        >>> len(hit)
        2

    Hit objects behave very similar to Python lists. You can retrieve the HSP
    object inside a Hit using the HSP's integer index. Hit objects can also be
    sliced, which will return a new Hit objects containing only the sliced HSPs::

        # HSP items inside the Hit can be retrieved using its integer index
        >>> hit[0]
        HSP(hit_id='gi|301171322|ref|NR_035857.1|', query_id='33211', 1 fragments)

        # slicing returns a new Hit
        >>> hit
        Hit(id='gi|301171322|ref|NR_035857.1|', query_id='33211', 2 hsps)
        >>> hit[:1]
        Hit(id='gi|301171322|ref|NR_035857.1|', query_id='33211', 1 hsps)
        >>> print(hit[1:])
        Query: 33211
               mir_1
          Hit: gi|301171322|ref|NR_035857.1| (86)
               Pan troglodytes microRNA mir-520c (MIR520C), microRNA
         HSPs: ----  --------  ---------  ------  ---------------  ---------------------
                  #   E-value  Bit score    Span      Query range              Hit range
               ----  --------  ---------  ------  ---------------  ---------------------
                  0   3.3e-06      55.39      60           [0:60]                [13:73]

    Hit objects provide ``filter`` and ``map`` methods, which are analogous to
    Python's built-in ``filter`` and ``map`` except that they return a new Hit
    object instead of a list.

    Here is an example of using ``filter`` to select for HSPs whose e-value is
    less than 1e-10::

        >>> evalue_filter = lambda hsp: hsp.evalue < 1e-10
        >>> filtered_hit = hit.filter(evalue_filter)
        >>> len(hit)
        2
        >>> len(filtered_hit)
        1
        >>> print(filtered_hit)
        Query: 33211
               mir_1
          Hit: gi|301171322|ref|NR_035857.1| (86)
               Pan troglodytes microRNA mir-520c (MIR520C), microRNA
         HSPs: ----  --------  ---------  ------  ---------------  ---------------------
                  #   E-value  Bit score    Span      Query range              Hit range
               ----  --------  ---------  ------  ---------------  ---------------------
                  0   8.9e-20     100.47      60           [1:61]                [13:73]

    There are also other methods which are counterparts of Python lists' methods
    with the same names: ``append``, ``index``, ``pop``, and ``sort``. Consult their
    respective documentations for more details and examples of their usage.

    _items Nc                    s   || _ g | _|| _d| _g | _d| _i | _g | _dD ] t fdd|D dkr/t	d  qg | _
|D ]}| | | | q5dS )a  Initialize a Hit object.

        :param hsps: HSP objects contained in the Hit object
        :type hsps: iterable yielding HSP
        :param id: hit ID
        :type id: string
        :param query_id: query ID
        :type query_id: string

        If multiple HSP objects are used for initialization, they must all
        have the same ``query_id``, ``query_description``, ``hit_id``, and
        ``hit_description`` properties.
        N)query_idquery_descriptionhit_idhit_descriptionc                    s   h | ]}t | qS r   )getattr).0hspattrr   K/var/www/html/myenv/lib/python3.10/site-packages/Bio/SearchIO/_model/hit.py	<setcomp>   s    zHit.__init__.<locals>.<setcomp>r   z6Hit object can not contain HSPs with more than one %s.)_id_id_alt	_query_id_description_description_alt_query_description
attributesdbxrefslen
ValueErrorr   _validate_hspappend)selfhspsidr   r   r   r   r   __init__g   s&   
zHit.__init__c                 C   s    d| j d| jdt| dS )z+Return string representation of Hit object.zHit(id=z, query_id=, z hsps))r&   r   r    r$   r   r   r   __repr__   s    zHit.__repr__c                 C   
   t | jS )zIterate over hsps.)iterr%   r)   r   r   r   __iter__      
zHit.__iter__c                 C   r+   )zReturn number of hsps.)r    r%   r)   r   r   r   __len__   r.   zHit.__len__c                 C   r+   )zReturn True if there are hsps.)boolr%   r)   r   r   r   __bool__   r.   zHit.__bool__c                 C   s
   || j v S )zReturn True if hsp in items.r
   r$   r   r   r   r   __contains__   r.   zHit.__contains__c              
   C   s@  g }d| j  }|| | jr)d| j }t|dkr"|dd d n|}|| d| j }z| j}W n	 ty<   Y nw |d| 7 }|| | jred| j }t|dkr^|dd d n|}|| t| j	
 D ]\}}|d	| d
|  ql| jr|dd| j  | js|d n|dd  d}||d  ||d  t| jD ]k\}	}
t|
ddd}t|
ddd}t|
d}t|
d}t|
d}d| d| d}t|dkr|dd d n|}t|
d }t|
d!}d| d| d}t|d"kr|dd# d n|}|||	|||||f  qd$|S )%z2Return a human readable summary of the Hit object.z	Query: %sz	       %sP   NM   z...z	  Hit: %sz (%i) z: zDatabase cross-references: r(   z HSPs: ?z HSPs: %s  %s  %s  %s  %s  %s)z----z--------z	---------z------z---------------z---------------------z%11s  %8s  %9s  %6s  %15s  %21s)#zE-valuez	Bit scoreSpanzQuery rangez	Hit rangeevaluez%.2g)fmtbitscorez%.2faln_spanquery_start	query_end[:]      z~]	hit_starthit_end      
)r   r#   r   r    r&   seq_lenAttributeErrordescriptionsortedr   itemsr   joinr%   	enumerater   )r$   linesqid_linelinehid_linerI   keyvaluepatternidxr   r9   r;   r<   r=   r>   query_rangerD   rE   	hit_ranger   r   r   __str__   sp   


 




 





"
zHit.__str__c                 C   s2   t |tr| | j| }| | |S | j| S )z)Return the HSP object at the given index.)
isinstanceslice	__class__r%   _transfer_attrsr   )r$   rW   objr   r   r   __getitem__   s
   


zHit.__getitem__c                 C   s<   t |ttfr|D ]}| | q	n| | || j|< dS )zAssign hsps to index idx.N)r[   listtupler"   r   )r$   rW   r%   r   r   r   r   __setitem__   s   
zHit.__setitem__c                 C   s   | j |= dS )zDelete item of index idx.Nr
   )r$   rW   r   r   r   __delitem__  s   zHit.__delitem__c                 C   s   t |ts	td| jrw| jdur"|j| jkr!td| j|jf n|j| _| jdur<|j| jkr;td| j|jf n|j| _| j	durV|j	| j	krUtd| j	|j	f n|j	| _	| j
durq|j
| j
krotd| j
|j
f dS |j
| _
dS dS )zValidate an HSP object (PRIVATE).

        Valid HSP objects have the same hit_id as the Hit object ID and the
        same query_id as the Hit object's query_id.

        z)Hit objects can only contain HSP objects.Nz.Expected HSP with hit ID %r, found %r instead.z7Expected HSP with hit description %r, found %r instead.z0Expected HSP with query ID %r, found %r instead.z9Expected HSP with query description %r, found %r instead.)r[   r   	TypeErrorr   r&   r   r!   rK   r   r   r   r2   r   r   r   r"     sP   








zHit._validate_hspr   r   zHit descriptionr   r   z.Description of the query that produced the hitr   r   zHit ID string.r   r   z,ID string of the query that produced the hitz HSP objects contained in the Hit)docc                 C      | j g| j S )zAlternative ID(s) of the Hit.)r&   r   r)   r   r   r   id_allK     z
Hit.id_allc                 C   rg   )z$Alternative descriptions of the Hit.)rK   r   r)   r   r   r   description_allP  ri   zHit.description_allc                 C   s   t t| j S )z4Access the HSPFragment objects contained in the Hit.)ra   r   r   r)   r   r   r   	fragmentsU  ri   zHit.fragmentsc                 C   s   |  | | j| dS )a0  Add a HSP object to the end of Hit.

        Parameters
        hsp -- HSP object to append.

        Any HSP object appended must have the same ``hit_id`` property as the
        Hit object's ``id`` property and the same ``query_id`` property as the
        Hit object's ``query_id`` property.

        N)r"   r   r#   r2   r   r   r   r#   [  s   
z
Hit.appendc                 C   s0   t t|| j}|r| |}| | |S dS )ae  Create new Hit object whose HSP objects pass the filter function.

        :param func: function for filtering
        :type func: callable, accepts HSP, returns bool

        ``filter`` is analogous to Python's built-in ``filter`` function, except
        that instead of returning a list it returns a ``Hit`` object. Here is an
        example of using ``filter`` to select for HSPs having bitscores bigger
        than 60::

            >>> from Bio import SearchIO
            >>> qresult = next(SearchIO.parse('Blast/mirna.xml', 'blast-xml'))
            >>> hit = qresult[3]
            >>> evalue_filter = lambda hsp: hsp.bitscore > 60
            >>> filtered_hit = hit.filter(evalue_filter)
            >>> len(hit)
            2
            >>> len(filtered_hit)
            1
            >>> print(filtered_hit)
            Query: 33211
                   mir_1
              Hit: gi|301171322|ref|NR_035857.1| (86)
                   Pan troglodytes microRNA mir-520c (MIR520C), microRNA
             HSPs: ----  --------  ---------  ------  ---------------  ---------------------
                      #   E-value  Bit score    Span      Query range              Hit range
                   ----  --------  ---------  ------  ---------------  ---------------------
                      0   8.9e-20     100.47      60           [1:61]                [13:73]

        N)ra   filterr%   r]   r^   r$   funcr%   r_   r   r   r   rl   i  s   

z
Hit.filterc                 C      | j |S )z{Return the index of a given HSP object, zero-based.

        :param hsp: object to look up
        :type hsp: HSP

        )r   indexr2   r   r   r   rp        z	Hit.indexc                    sT    dur fdd| j dd D }n| j dd }|r(| |}| | |S dS )aK  Create new Hit object, mapping the given function to its HSPs.

        :param func: function for mapping
        :type func: callable, accepts HSP, returns HSP

        ``map`` is analogous to Python's built-in ``map`` function. It is applied to
        all HSPs contained in the Hit object and returns a new Hit object.

        Nc                    s   g | ]} |qS r   r   )r   xrn   r   r   
<listcomp>  s    zHit.map.<locals>.<listcomp>)r%   r]   r^   rm   r   rs   r   map  s   


zHit.mapc                 C   ro   )zRemove and returns the HSP object at the specified index.

        :param index: index of HSP object to pop
        :type index: int

        )r   pop)r$   rp   r   r   r   rw     rq   zHit.popFTc                 C   sL   |r| j j||d dS | jdd }|j||d | |}| | |S )a&  Sort the HSP objects.

        :param key: sorting function
        :type key: callable, accepts HSP, returns key for sorting
        :param reverse: whether to reverse sorting results or no
        :type reverse: bool
        :param in_place: whether to do in-place sorting or no
        :type in_place: bool

        ``sort`` defaults to sorting in-place, to mimic Python's ``list.sort``
        method. If you set the ``in_place`` argument to False, it will treat
        return a new, sorted Hit object and keep the initial one unsorted

        )rT   reverseN)r   sortr%   r]   r^   )r$   rT   rx   in_placer%   r_   r   r   r   ry     s   

zHit.sort)r   NN)N)rv   )NFT)!__name__
__module____qualname____doc___NON_STICKY_ATTRSr'   r*   r-   r/   r1   r3   rZ   r`   rc   rd   r"   r   rK   r   r&   r   r   r%   propertyrh   rj   rk   r#   rl   rp   ru   rw   ry   r   r   r   r   r	      sN    R
+M	0




%
	
	r	   __main__)run_doctestN)r~   	itertoolsr   Bio.SearchIO._utilsr   r   r   _baser   r   r   r	   r{   
Bio._utilsr   r   r   r   r   <module>   s      >
