o
    Rŀg                     @   sN   d Z ddl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Z	dS )	z=Fast atom neighbor lookup using a KD tree (implemented in C).    N)PDBException)entity_levels)unfold_entities)	uniqueifyc                   @   s6   e Zd ZdZdddZdd Zddd	Zdd
dZdS )NeighborSearcha  Class for neighbor searching.

    This class can be used for two related purposes:

     1. To find all atoms/residues/chains/models/structures within radius
        of a given query position.
     2. To find all atoms/residues/chains/models/structures that are within
        a fixed radius of each other.

    NeighborSearch makes use of the KDTree class implemented in C for speed.
    
   c                 C   sb   ddl m} || _dd |D }tj|dd| _|dksJ | jjd dks(J || j|| _d	S )
a4  Create the object.

        Arguments:
         - atom_list - list of atoms. This list is used in the queries.
           It can contain atoms from different structures.
         - bucket_size - bucket size of KD tree. You can play around
           with this to optimize speed if you feel like it.

        r   )KDTreec                 S   s   g | ]}|  qS  )	get_coord).0ar	   r	   J/var/www/html/myenv/lib/python3.10/site-packages/Bio/PDB/NeighborSearch.py
<listcomp>.   s    z+NeighborSearch.__init__.<locals>.<listcomp>d)dtype      N)Bio.PDB.kdtreesr   	atom_listnparraycoordsshapekdt)selfr   bucket_sizer   
coord_listr	   r	   r   __init__    s   
zNeighborSearch.__init__c                 C   sZ   g }|D ]$\}}|  }|  }||krq||k r!|||f q|||f qt|S )N)
get_parentappendr   )r   	pair_listparent_pair_liste1e2p1p2r	   r	   r   _get_unique_parent_pairs7   s   z'NeighborSearch._get_unique_parent_pairsAc                    sn   |t vrt| dtj|ddd}|jdkrtd j||} fdd|D }|d	kr2|S t||S )
a  Neighbor search.

        Return all atoms/residues/chains/models/structures
        that have at least one atom within radius of center.
        What entity level is returned (e.g. atoms or residues)
        is determined by level (A=atoms, R=residues, C=chains,
        M=models, S=structures).

        Arguments:
         - center - NumPy array
         - radius - float
         - level - char (A, R, C, M, S)

        : Unknown levelr   C)r   requirements)r   z$Expected a 3-dimensional NumPy arrayc                    s   g | ]} j |j qS r	   )r   index)r   pointr   r	   r   r   `   s    z)NeighborSearch.search.<locals>.<listcomp>r'   )	r   r   r   requirer   	Exceptionr   searchr   )r   centerradiuslevelpointsr   r	   r-   r   r0   K   s   

zNeighborSearch.searchc                 C   s   |t vrt| d| j|}| j}g }|D ]}|j}|j}|| }	|| }
||	|
f q|dkr6|S |}dD ]}| |}||krI|  S q:dS )zAll neighbor search.

        Search all entities that have atoms pairs within
        radius.

        Arguments:
         - radius - float
         - level - char (A, R, C, M, S)

        r(   r'   )Rr)   MSN)	r   r   r   neighbor_searchr   index1index2r   r&   )r   r2   r3   	neighborsr   atom_pair_listneighbori1i2a1a2next_level_pair_list
next_levelr	   r	   r   
search_allf   s(   
zNeighborSearch.search_allN)r   )r'   )__name__
__module____qualname____doc__r   r&   r0   rD   r	   r	   r	   r   r      s    

r   )
rH   numpyr   Bio.PDB.PDBExceptionsr   Bio.PDB.Selectionr   r   r   r   r	   r	   r	   r   <module>   s   