o
    Rŀg9!                     @   s   U d Z ddlZddlZddlmZ ddlZddlmZ dgZ	ddddd	d
Z
edd Zeeef ed< ei ddddddddddddddddddd dd!d"d#d$d%d&d'd(d)dd*d+d,d-d.d/d0dd1 G d2d dZdS )3a  Calculation of solvent accessible surface areas for Bio.PDB entities.

Uses the "rolling ball" algorithm developed by Shrake & Rupley algorithm,
which uses a sphere (of equal radius to a solvent molecule) to probe the
surface of the molecule.

Reference:
    Shrake, A; Rupley, JA. (1973). J Mol Biol
    "Environment and exposure to solvent of protein atoms. Lysozyme and insulin".
    N)MutableMapping)KDTreeShrakeRupley            )ARCMSc                   C   s   dS )N       @ r   r   r   @/var/www/html/myenv/lib/python3.10/site-packages/Bio/PDB/SASA.py<lambda>-   s    r   ATOMIC_RADIIHg333333?HEffffff?r   g333333?Ng?OgRQ?FgQ?NAg)\(@MGgGz?Pg?r   CLg      ?Kg      @CAg{Gz@NIgGz?CUZNg=
ףp=?SEgffffff?g?gHzG?gGz?)BRCDIHGc                   @   s,   e Zd ZdZdddZdd Zdd
dZdS )r   z3Calculates SASAs using the Shrake-Rupley algorithm.r   d   Nc                 C   sj   |dkrt d| dt|| _|dk rt d| || _t | _|dur.| j| |  | _	dS )a  Initialize the class.

        :param probe_radius: radius of the probe in A. Default is 1.40, roughly
            the radius of a water molecule.
        :type probe_radius: float

        :param n_points: resolution of the surface of each atom. Default is 100.
            A higher number of points results in more precise measurements, but
            slows down the calculation.
        :type n_points: int

        :param radii_dict: user-provided dictionary of atomic radii to use in
            the calculation. Values will replace/complement those in the
            default ATOMIC_RADII dictionary.
        :type radii_dict: dict

        >>> sr = ShrakeRupley()
        >>> sr = ShrakeRupley(n_points=960)
        >>> sr = ShrakeRupley(radii_dict={"O": 3.1415})
        g        z(Probe radius must be a positive number: z <= 0r   z/Number of sphere points must be larger than 1: N)

ValueErrorfloatprobe_radiusn_pointsr   copy
radii_dictupdate_compute_sphere_sphere)selfr*   r+   r-   r   r   r   __init__L   s   


zShrakeRupley.__init__c           	      C   s   | j }tjd }d| }d}d|d  }tj|dftjd}t|D ].}d||  d }t|| ||df< t|| ||df< |||df< ||8 }||7 }q"|S )	a  Return the 3D coordinates of n points on a sphere.

        Uses the golden spiral algorithm to place points 'evenly' on the sphere
        surface. We compute this once and then move the sphere to the centroid
        of each atom as we compute the ASAs.
        g`-!r?r   r   r   r   r   dtypeg      ?)	r+   nppizerosfloat32rangemathcossin)	r1   ndldz	longitudezcoordskrr   r   r   r/   v   s   

zShrakeRupley._compute_spherer	   c              	      s  t |do	|jdv }|stdt| d|tvr"td| dt| t|j kr6td| d|j t| }t|}|sFtd	tj	d
d |D tj
d}t|d}| jtj	fdd|D tj
d}|| j7 }t|d }	tj|dftjd}
tt| j}t|D ]P}|| }tj	| jdd| ||  }| }t|d}||| |	D ]$}|j}||krq|j|||  k r|dd ||| || D 8 }qt||
|< q|| dtj | j  }|
|ddtjf  }
t|D ]\}}|
|df |_q|dkr@t|}t| }t|D ]
}dd |D }qdd t|D  |D ]} fdd| D }|
|  |_q*dS dS )a
  Calculate surface accessibility surface area for an entity.

        The resulting atomic surface accessibility values are attached to the
        .sasa attribute of each entity (or atom), depending on the level. For
        example, if level="R", all residues will have a .sasa attribute. Atoms
        will always be assigned a .sasa attribute with their individual values.

        :param entity: input entity.
        :type entity: Bio.PDB.Entity, e.g. Residue, Chain, ...

        :param level: the level at which ASA values are assigned, which can be
            one of "A" (Atom), "R" (Residue), "C" (Chain), "M" (Model), or
            "S" (Structure). The ASA value of an entity is the sum of all ASA
            values of its children. Defaults to "A".
        :type entity: Bio.PDB.Entity

        >>> from Bio.PDB import PDBParser
        >>> from Bio.PDB.SASA import ShrakeRupley
        >>> p = PDBParser(QUIET=1)
        >>> # This assumes you have a local copy of 1LCD.pdb in a directory called "PDB"
        >>> struct = p.get_structure("1LCD", "PDB/1LCD.pdb")
        >>> sr = ShrakeRupley()
        >>> sr.compute(struct, level="S")
        >>> print(round(struct.sasa, 2))
        7053.43
        >>> print(round(struct[0]["A"][11]["OE1"].sasa, 2))
        9.64
        level>   r   r   r
   r   zInvalid entity type 'z.'. Must be Residue, Chain, Model, or StructurezInvalid level 'z'. Must be A, R, C, M, or S.zLevel 'z.' must be equal or smaller than input entity: zEntity has no child atoms.c                 S   s   g | ]}|j qS r   )coord.0ar   r   r   
<listcomp>       z(ShrakeRupley.compute.<locals>.<listcomp>r3   
   c                       g | ]} |j  qS r   )elementrG   )r-   r   r   rJ          r   r   T)r,   c                 S      h | ]}|j qS r   )index)rH   ptr   r   r   	<setcomp>   s    z'ShrakeRupley.compute.<locals>.<setcomp>r   Nr   r	   c                 S   rP   r   )parent)rH   er   r   r   rS      rK   c                 S   s   i | ]\}}|j |qS r   full_id)rH   idxrI   r   r   r   
<dictcomp>   s    z(ShrakeRupley.compute.<locals>.<dictcomp>c                    rM   r   rV   rG   )atomdictr   r   rJ      rO   )hasattrrE   r(   type_ENTITY_HIERARCHYlist	get_atomslenr5   arrayfloat64r   r-   r*   maxr7   int64setr9   r+   r0   r,   searchrQ   radiusr6   newaxis	enumeratesasasum)r1   entityrE   is_validatomsn_atomsrB   kdtradiitwice_maxradii	asa_arrayptsetir_is_on_iavailable_set
kdt_spherejjjfatomentitiestarget_rU   e_atomsr   )rZ   r-   r   compute   sj   



zShrakeRupley.compute)r   r'   N)r	   )__name__
__module____qualname____doc__r2   r/   r   r   r   r   r   r   I   s
    
*)r   collectionsr:   collections.abcr   numpyr5   Bio.PDB.kdtreesr   __all__r]   defaultdictr   strr)   __annotations__r.   r   r   r   r   r   <module>   sr   	
