o
    Rŀgp                     @   s   d Z 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 W n ey3   ddl	m
Z
 e
dw G d	d
 d
ZedkrLddlmZ edd dS dS )a;  Align on protein structure onto another using SVD alignment.

SVDSuperimposer finds the best rotation and translation to put
two point sets on top of each other (minimizing the RMSD). This is
eg. useful to superimpose crystal structures. SVD stands for singular
value decomposition, which is used in the algorithm.
    )dot)sqrt)	transpose)det)svd)MissingPythonDependencyErrorz5Install NumPy if you want to use Bio.SVDSuperimposer.c                   @   sX   e Zd Z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 )SVDSuperimposera  Class to run SVD alignment.

    SVDSuperimposer finds the best rotation and translation to put
    two point sets on top of each other (minimizing the RMSD). This is
    eg. useful to superimpose crystal structures.

    SVD stands for Singular Value Decomposition, which is used to calculate
    the superposition.

    Reference:

    Matrix computations, 2nd ed. Golub, G. & Van Loan, CF., The Johns
    Hopkins University Press, Baltimore, 1989

    start with two coordinate sets (Nx3 arrays - float)

    >>> from Bio.SVDSuperimposer import SVDSuperimposer
    >>> from numpy import array, dot, set_printoptions
    >>>
    >>> x = array([[51.65, -1.90, 50.07],
    ...      [50.40, -1.23, 50.65],
    ...      [50.68, -0.04, 51.54],
    ...      [50.22, -0.02, 52.85]], 'f')
    >>>
    >>> y = array([[51.30, -2.99, 46.54],
    ...      [51.09, -1.88, 47.58],
    ...      [52.36, -1.20, 48.03],
    ...      [52.71, -1.18, 49.38]], 'f')

    start

    >>> sup = SVDSuperimposer()

    set the coords y will be rotated and translated on x

    >>> sup.set(x, y)

    do the lsq fit

    >>> sup.run()

    get the rmsd

    >>> rms = sup.get_rms()

    get rotation (right multiplying!) and the translation

    >>> rot, tran = sup.get_rotran()

    rotate y on x

    >>> y_on_x1 = dot(y, rot) + tran

    same thing

    >>> y_on_x2 = sup.get_transformed()

    >>> set_printoptions(precision=2)
    >>> print(y_on_x1)
    [[ 5.17e+01 -1.90e+00  5.01e+01]
     [ 5.04e+01 -1.23e+00  5.06e+01]
     [ 5.07e+01 -4.16e-02  5.15e+01]
     [ 5.02e+01 -1.94e-02  5.29e+01]]
    >>> print(y_on_x2)
    [[ 5.17e+01 -1.90e+00  5.01e+01]
     [ 5.04e+01 -1.23e+00  5.06e+01]
     [ 5.07e+01 -4.16e-02  5.15e+01]
     [ 5.02e+01 -1.94e-02  5.29e+01]]
    >>> print("%.2f" % rms)
    0.00

    c                 C   s   |    dS )zInitialize the class.N)_clearself r   P/var/www/html/myenv/lib/python3.10/site-packages/Bio/SVDSuperimposer/__init__.py__init__g   s   zSVDSuperimposer.__init__c                 C   s.   d | _ d | _d | _d | _d | _d | _d | _d S )N)reference_coordscoordstransformed_coordsrottranrmsinit_rmsr
   r   r   r   r	   m   s   
zSVDSuperimposer._clearc                 C   s&   || }t tt|| |jd  S )z<Return rms deviations between coords1 and coords2 (PRIVATE).r   )r   sumshape)r   coords1coords2diffr   r   r   _rmsv   s   zSVDSuperimposer._rmsc                 C   sb   |    || _|| _|j}|j}||ks&|d |d   kr%dks*td td|d | _dS )a  Set the coordinates to be superimposed.

        coords will be put on top of reference_coords.

        - reference_coords: an NxDIM array
        - coords: an NxDIM array

        DIM is the dimension of the points, N is the number
        of points to be superimposed.
              z%Coordinate number/dimension mismatch.r   N)r	   r   r   r   	Exceptionn)r   r   r   r   mr   r   r   set}   s   "zSVDSuperimposer.setc           	      C   s   | j du s
| jdu rtd| j }| j}t|| j }t|| j }|| }|| }tt||}t|\}}}ttt|t|| _t	| jdk r^|d  |d< ttt|t|| _|t|| j | _
dS )z Superimpose the coordinate sets.NNo coordinates set.r      )r   r   r   r   r   r   r   r   r   r   r   )	r   r   r   av1av2audvtr   r   r   run   s   zSVDSuperimposer.runc                 C   sT   | j du s
| jdu rtd| jdu rtd| jdu r't| j | j| j | _| jS )z#Get the transformed coordinate set.Nr"   Nothing superimposed yet.)r   r   r   r   r   r   r   r
   r   r   r   get_transformed   s   

zSVDSuperimposer.get_transformedc                 C   s   | j du r	td| j | jfS )z2Right multiplying rotation matrix and translation.Nr+   )r   r   r   r
   r   r   r   
get_rotran   s   
zSVDSuperimposer.get_rotranc                 C   s4   | j du r	td| jdu r| | j | j| _| jS )z8Root mean square deviation of untransformed coordinates.NzNo coordinates set yet.)r   r   r   r   r   r
   r   r   r   get_init_rms   s
   

zSVDSuperimposer.get_init_rmsc                 C   s(   | j du r|  }| || j| _ | j S )z7Root mean square deviation of superimposed coordinates.N)r   r,   r   r   )r   r   r   r   r   get_rms   s   
zSVDSuperimposer.get_rmsN)__name__
__module____qualname____doc__r   r	   r   r!   r*   r,   r-   r.   r/   r   r   r   r   r      s    I	
r   __main__)run_doctest)verboseN)r3   numpyr   r   r   numpy.linalgr   r   ImportErrorBior   r   r0   
Bio._utilsr5   r   r   r   r   <module>   s&    ,