o
    RŀgVO                     @   s   d Z ddlmZ ddlZdd Zdd Zdd	 ZeZd
d Z	dd Z
dd Zdd ZG dd dZ	 dededejfddZdedejfddZdedejfddZdedejfddZd ed!ed"edejfd#d$Zd ed!ed"edejfd%d&Zd'edejfd(d)Zd ed!edefd*d+Zd,ejdeeeef fd-d.Zejd/ejd0aejd/ejd0aejd/ejd0aejd/ejd0a 	1d@d2ejd3ejd4ejd5e!deejeej f f
d6d7Z"dejdejfd8d9Z#dejdejfd:d;Z$d@d<ejd=e%d5e!dejfd>d?Z&dS )Az3Vector class, including rotation-related functions.    )OptionalNc                 C   sd  d}t | d | d  |k rct | d | d  |k rct | d | d  |k rct | d | d  |k r_t | d | d  |k r_t | d | d  |k r_t | d | d	  | d
  d |k r_d}ntj}ndt| d  }td|}td|}t|}|dk rdtdddfS |tjk r| d | d  }| d | d  }| d | d  }t|||}|  ||fS | d }| d	 }	| d
 }
||	kr||
krt	||	 |
 d }| d d|  }| d d|  }nA|	|kr|	|
krt	|	| |
 d }| d d|  }| d d|  }nt	|
| |	 d }| d d|  }| d d|  }t|||}|  tj|fS )zReturn angles, axis pair that corresponds to rotation matrix m.

    The case where ``m`` is the identity matrix corresponds to a singularity
    where any rotation axis is valid. In that case, ``Vector([1, 0, 0])``,
    is returned.
    h㈵>r      r   r   r      r   r   r   r   r   r   r   r   r   r   r   r      r   g      ?r   gV瞯<        r   )
absnppitracemaxminarccosVector	normalizesqrt)mepsangletxyzaxism00m11m22 r'   C/var/www/html/myenv/lib/python3.10/site-packages/Bio/PDB/vectors.py	m2rotaxis   sP   $




r)   c                 C   s0   |   } | }| |}|| |||   S )a2  Vector to axis method.

    Return the vector between a point and
    the closest point on a line (ie. the perpendicular
    projection of the point on the line).

    :type line: L{Vector}
    :param line: vector defining a line

    :type point: L{Vector}
    :param point: vector defining the point
    )
normalizednormr   cos)linepointr   r   r'   r'   r(   vector_to_axisR   s   
r/   c           	      C   s  |  }t| }t| }d| }| \}}}td}|| | | |d< || | ||  |d< || | ||  |d< || | ||  |d< || | | |d< || | ||  |d< || | ||  |d	< || | ||  |d
< || | | |d< |S )aG  Calculate left multiplying rotation matrix.

    Calculate a left multiplying rotation matrix that rotates
    theta rad around vector.

    :type theta: float
    :param theta: the rotation angle

    :type vector: L{Vector}
    :param vector: the rotation axis

    :return: The rotation matrix, a 3x3 NumPy array.

    Examples
    --------
    >>> from numpy import pi
    >>> from Bio.PDB.vectors import rotaxis2m
    >>> from Bio.PDB.vectors import Vector
    >>> m = rotaxis2m(pi, Vector(1, 0, 0))
    >>> Vector(1, 2, 3).left_multiply(m)
    <Vector 1.00, -2.00, -3.00>

    r   )r   r   r   r   r   r   r   r
   r	   r   r   )r*   r   r,   sin	get_arrayzeros)	thetavectorcsr   r    r!   r"   rotr'   r'   r(   	rotaxis2me   s    


r8   c                 C   sp   |   } |  }| |  dk rtdS | | }|  | }d|_td}|dt|t|  }|S )a  Return a (left multiplying) matrix that mirrors p onto q.

    :type p,q: L{Vector}
    :return: The mirror operation, a 3x3 NumPy array.

    Examples
    --------
    >>> from Bio.PDB.vectors import refmat
    >>> p, q = Vector(1, 2, 3), Vector(2, 3, 5)
    >>> mirror = refmat(p, q)
    >>> qq = p.left_multiply(mirror)
    >>> print(q)
    <Vector 2.00, 3.00, 5.00>
    >>> print(qq)
    <Vector 1.21, 1.82, 3.03>

    r   r   )r   r   r   )	r*   r+   r   identityr   r1   shapedot	transpose)pqpqbirefr'   r'   r(   refmat   s   

rC   c                 C   s    t t||  t| |  }|S )a  Return a (left multiplying) matrix that rotates p onto q.

    :param p: moving vector
    :type p: L{Vector}

    :param q: fixed vector
    :type q: L{Vector}

    :return: rotation matrix that rotates p onto q
    :rtype: 3x3 NumPy array

    Examples
    --------
    >>> from Bio.PDB.vectors import rotmat
    >>> p, q = Vector(1, 2, 3), Vector(2, 3, 5)
    >>> r = rotmat(p, q)
    >>> print(q)
    <Vector 2.00, 3.00, 5.00>
    >>> print(p)
    <Vector 1.00, 2.00, 3.00>
    >>> p.left_multiply(r)
    <Vector 1.21, 1.82, 3.03>

    )r   r;   rC   )r=   r>   r7   r'   r'   r(   rotmat   s   rD   c                 C   s   | | } || }|  |S )zCalculate angle method.

    Calculate the angle between 3 vectors
    representing 3 connected points.

    :param v1, v2, v3: the tree points that define the angle
    :type v1, v2, v3: L{Vector}

    :return: angle
    :rtype: float
    )r   )v1v2v3r'   r'   r(   
calc_angle   s   
rH   c                 C   sp   | | }|| }|| }|| }|| }|| }	| |}
z| |	dkr+|
 }
W |
S W |
S  ty7   Y |
S w )a  Calculate dihedral angle method.

    Calculate the dihedral angle between 4 vectors
    representing 4 connected points. The angle is in
    ]-pi, pi].

    :param v1, v2, v3, v4: the four points that define the dihedral angle
    :type v1, v2, v3, v4: L{Vector}
    gMbP?)r   ZeroDivisionError)rE   rF   rG   v4abcbdbuvwr   r'   r'   r(   calc_dihedral   s"   

rQ   c                   @   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 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S ),r   z
3D vector.Nc                 C   sN   |du r|du rt |dkrtdt|d| _dS t|||fd| _dS )zInitialize the class.Nr   z0Vector: x is not a list/tuple/array of 3 numbersd)len
ValueErrorr   array_arselfr    r!   r"   r'   r'   r(   __init__   s
   zVector.__init__c                 C   s*   | j \}}}d|dd|dd|ddS )zReturn vector 3D coordinates.z<Vector z.2fz, >rV   rW   r'   r'   r(   __repr__  s   zVector.__repr__c                 C   s   | j  }t|S )zReturn Vector(-x, -y, -z).)rV   r   )rX   ar'   r'   r(   __neg__  s   zVector.__neg__c                 C   s6   t |tr| j|j }t|S | jt| }t|S )z%Return Vector+other Vector or scalar.
isinstancer   rV   r   rU   rX   otherr]   r'   r'   r(   __add__  
   
zVector.__add__c                 C   s6   t |tr| j|j }t|S | jt| }t|S )z%Return Vector-other Vector or scalar.r_   ra   r'   r'   r(   __sub__  rd   zVector.__sub__c                 C   s   t | j|j S )z#Return Vector.Vector (dot product).)sumrV   )rX   rb   r'   r'   r(   __mul__%  s   zVector.__mul__c                 C   s   | j t| }t|S )zReturn Vector(coords/a).)rV   r   rU   r   )rX   r    r]   r'   r'   r(   __truediv__)  s   zVector.__truediv__c                 C   s   t |trE| j\}}}|j\}}}tjt||f||ff}tjt||f||ff }	tjt||f||ff}
t||	|
S | jt| }t|S )z6Return VectorxVector (cross product) or Vectorxscalar.)r`   r   rV   r   linalgdetrU   )rX   rb   r]   r@   r5   rR   efc1c2c3r'   r'   r(   __pow__.  s   
 zVector.__pow__c                 C   s
   | j | S )zReturn value of array index i.r[   rX   rA   r'   r'   r(   __getitem__;     
zVector.__getitem__c                 C   s   || j |< dS )zAssign values to array index i.Nr[   )rX   rA   valuer'   r'   r(   __setitem__?  s   zVector.__setitem__c                 C   s
   || j v S )zValidate if i is in array.r[   rq   r'   r'   r(   __contains__C  rs   zVector.__contains__c                 C   s   t t| j| j S )zReturn vector norm.)r   r   rf   rV   rX   r'   r'   r(   r+   G  s   zVector.normc                 C   s   t t| j| j S )zReturn square of vector norm.)r   rf   rV   rw   r'   r'   r(   normsqK  s   zVector.normsqc                 C   s    |   r| j|    | _dS dS )zNormalize the Vector object.

        Changes the state of ``self`` and doesn't return a value.
        If you need to chain function calls or create a new object
        use the ``normalized`` method.
        N)r+   rV   rw   r'   r'   r(   r   O  s   zVector.normalizec                 C   s   |   }|  |S )zwReturn a normalized copy of the Vector.

        To avoid allocating new objects use the ``normalize`` method.
        )copyr   )rX   rO   r'   r'   r(   r*   Y  s   zVector.normalizedc                 C   s>   |   }|  }| | ||  }t|d}td|}t|S )z!Return angle between two vectors.r   r   )r+   r   r   r   r   )rX   rb   n1n2r5   r'   r'   r(   r   b  s   


zVector.anglec                 C   s   t | jS )z,Return (a copy of) the array of coordinates.)r   rU   rV   rw   r'   r'   r(   r1   l  s   zVector.get_arrayc                 C   s   t || j}t|S )zReturn Vector=Matrix x Vector.r   r;   rV   r   rX   matrixr]   r'   r'   r(   left_multiplyp     zVector.left_multiplyc                 C   s   t | j|}t|S )zReturn Vector=Vector x Matrix.r|   r}   r'   r'   r(   right_multiplyu  r   zVector.right_multiplyc                 C   s
   t | jS )z!Return a deep copy of the Vector.)r   rV   rw   r'   r'   r(   ry   z  rs   zVector.copy)NN)__name__
__module____qualname____doc__rY   r\   r^   rc   re   rg   rh   rp   rr   ru   rv   r+   rx   r   r*   r   r1   r   r   ry   r'   r'   r'   r(   r      s,    

	
r   
angle_radsr#   returnc                 C   s   t | }t | }d|kr#t j|| ddf||ddfddft jdS d|kr<t j|d|dfd| d|dfdft jdS t jdd|| dfd||dfdft jdS )	zGenerate a 4x4 single-axis NumPy rotation matrix.

    :param float angle_rads: the desired rotation angle in radians
    :param char axis: character specifying the rotation axis
    r"   r   )r   r   r   r   r   r   r   r   dtyper!   )r   r   r   r   )r   r   r   r   )r   r,   r0   rU   float64)r   r#   cosangsinangr'   r'   r(   homog_rot_mtx  s8   


	


r   mtxc                 C   J   t | }t | }| |d d< |d d< ||d d< | |d d< dS )z/Update existing Z rotation matrix to new angle.r   r   Nr   r,   r0   r   r   r   r   r'   r'   r(   set_Z_homog_rot_mtx  
   

r   c                 C   sJ   t | }t | }| |d d< |d d< ||d d< | |d d< dS )z/Update existing Y rotation matrix to new angle.r   r   Nr   r   r'   r'   r(   set_Y_homog_rot_mtx  r   r   c                 C   r   )z/Update existing X rotation matrix to new angle.r   r   Nr   r   r'   r'   r(   set_X_homog_rot_mtx  r   r   r    r!   r"   c                 C   s0   t jddd| fddd|fddd|fdft jdS )z[Generate a 4x4 NumPy translation matrix.

    :param x, y, z: translation in each axis
    r   r   r   r   r   rU   r   )r    r!   r"   r'   r'   r(   homog_trans_mtx  s   "r   c                 C   s(   | |d d< ||d d< ||d d< dS )z1Update existing translation matrix to new values.r   r   r   r   Nr'   )r    r!   r"   r   r'   r'   r(   set_homog_trans_mtx  s   r   scalec                 C   s4   t j| dddgd| ddgdd| dgg dgt jdS )zSGenerate a 4x4 NumPy scaling matrix.

    :param float scale: scale multiplier
    r   r   r   r   )r   r'   r'   r(   homog_scale_mtx  s   &r   c                 C   sd   |dk rdnd}| dk rdnd}d| krd|krt || S d|kr)t jd | S |dk r0t jS dS )Nr   g      g      ?r   g       @)r   arctan2r   )r    r!   sign_ysign_xr'   r'   r(   _get_azimuth  s   
r   xyzc                 C   sJ   t tj| }d|krdS t| d | d }t| d | }|||fS )zCompute spherical coordinates (r, azimuth, polar_angle) for X,Y,Z point.

    :param array xyz: column vector (3 row x 1 column NumPy array)
    :return: tuple of r, azimuth, polar_angle for input coordinate
    r   )r   r   r   r   r   )floatr   ri   r+   r   r   )r   razimuthpolar_angler'   r'   r(   get_spherical_coordinates  s   
r      r   Fa0a1a2revc                 C   s  t }t}t}t}t|d  |d  |d  | || }t|}	t|	d  | t|	d  | ttt }
|
| }t	|d |d }t| | t|
}
|sW|
dfS t|| t|	d | t|	d | t|d |d |d | t ttt}|
|fS )a  Generate transformation matrix to coordinate space defined by 3 points.

    New coordinate space will have:
        acs[0] on XZ plane
        acs[1] origin
        acs[2] on +Z axis

    :param NumPy column array x3 acs: X,Y,Z column input coordinates x3
    :param bool rev: if True, also return reverse transformation matrix
        (to return from coord_space)
    :returns: 4x4 NumPy array, x2 if rev=True
    r   r   r   N)
gtmgmrygmrzgmrz2r   r   r   r   r;   r   )r   r   r   r   tmmrymrzmrz2r=   scmtazimuth2mrr'   r'   r(   coord_space  s,    



r   c                 C   s   t | jd ddf}t d|d< t |  |ddddf< |ddddf< t | |ddddf< |ddddf  |ddddf< |S )zCreate [entries] NumPy Z rotation matrices for [entries] angles.

    :param entries: int number of matrices generated.
    :param angle_rads: NumPy array of angles
    :returns: entries x 4 x 4 homogeneous rotation matrices
    r   r   .Nr   r   emptyr:   r9   r,   r0   )r   rzr'   r'   r(   multi_rot_Z}  s   *"r   c                 C   s   t | jd ddf}t d|d< t |  |ddddf< |ddddf< t | |ddddf< |ddddf  |ddddf< |S )zCreate [entries] NumPy Y rotation matrices for [entries] angles.

    :param entries: int number of matrices generated.
    :param angle_rads: NumPy array of angles
    :returns: entries x 4 x 4 homogeneous rotation matrices
    r   r   .Nr   r   )r   ryr'   r'   r(   multi_rot_Y  s   *"r   a3dLenc                 C   s  t |ddf}t d|d< | dddddf  |dddddf< | dddf | dddf  }t jj|dd}t |dddf |dddf }t t j|dddf ||dkd	}t| }t	| }	t 
|	t 
||}
t 
|
| dddf d
ddd
d}t |dddf |dddf }t| }|st 
||
dd S t 
||
dd }
t|}t	|}t|}| dddddf |dddddf< || | | }t |
|gS )a  Generate [dLen] transform matrices to coord space defined by 3 points.

    New coordinate space will have:
        acs[0] on XZ plane
        acs[1] origin
        acs[2] on +Z axis

    :param NumPy array [entries]x3x3 [entries] XYZ coords for 3 atoms
    :param bool rev: if True, also return reverse transformation matrix
    (to return from coord_space)
    :returns: [entries] 4x4 NumPy arrays, x2 if rev=True

    r   .Nr   r   r   r   )r#   )wherer   )r   r   r9   ri   r+   r   r   divider   r   matmulreshaperU   )r   r   r   r   r=   r   r   r   r   r   r   r   rz2r   r   r   r   r'   r'   r(   multi_coord_space  s,   * $&

*$
(r   )F)'r   typingr   numpyr   r)   r/   r8   rotaxisrC   rD   rH   rQ   r   r   strndarrayr   r   r   r   r   r   r   r   tupler   r9   r   r   r   r   r   boolr   r   r   intr   r'   r'   r'   r(   <module>   sT   C- )



o$