
     i                         d Z ddlZddlZddlZddlmZ ddlm	Z	m
Z
 ddlmZ ddlmZmZmZ  ej        d          Zdd
Zd Z G d de	          Z G d de	          ZdS )u  
Calculating root mean square quantities --- :mod:`MDAnalysis.analysis.rms`
==========================================================================

:Author: Oliver Beckstein, David L. Dotson, John Detlefs
:Year: 2016
:Copyright: Lesser GNU Public License v2.1+

.. versionadded:: 0.7.7
.. versionchanged:: 0.11.0
   Added :class:`RMSF` analysis.
.. versionchanged:: 0.16.0
   Refactored RMSD to fit AnalysisBase API

The module contains code to analyze root mean square quantities such
as the coordinat root mean square distance (:class:`RMSD`) or the
per-residue root mean square fluctuations (:class:`RMSF`).

This module uses the fast QCP algorithm [Theobald2005]_ to calculate
the root mean square distance (RMSD) between two coordinate sets (as
implemented in
:func:`MDAnalysis.lib.qcprot.CalcRMSDRotationalMatrix`).

When using this module in published work please cite [Theobald2005]_.


See Also
--------
:mod:`MDAnalysis.analysis.align`
   aligning structures based on RMSD
:mod:`MDAnalysis.lib.qcprot`
   implements the fast RMSD algorithm.


Example applications
--------------------

Calculating RMSD for multiple domains
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In this example we will globally fit a protein to a reference
structure and investigate the relative movements of domains by
computing the RMSD of the domains to the reference. The example is a
DIMS trajectory of adenylate kinase, which samples a large
closed-to-open transition. The protein consists of the CORE, LID, and
NMP domain.

* superimpose on the closed structure (frame 0 of the trajectory),
  using backbone atoms

* calculate the backbone RMSD and RMSD for CORE, LID, NMP (backbone atoms)

The trajectory is included with the test data files. The data in
:attr:`RMSD.results.rmsd` is plotted with :func:`matplotlib.pyplot.plot` (see Figure :ref:`RMSD plot figure <figure-RMSD>`)::

   import MDAnalysis
   from MDAnalysis.tests.datafiles import PSF,DCD,CRD
   u = MDAnalysis.Universe(PSF,DCD)
   ref = MDAnalysis.Universe(PSF,DCD)     # reference closed AdK (1AKE) (with the default ref_frame=0)
   #ref = MDAnalysis.Universe(PSF,CRD)    # reference open AdK (4AKE)

   import MDAnalysis.analysis.rms

   R = MDAnalysis.analysis.rms.RMSD(u, ref,
              select="backbone",             # superimpose on whole backbone of the whole protein
              groupselections=["backbone and (resid 1-29 or resid 60-121 or resid 160-214)",   # CORE
                               "backbone and resid 122-159",                                   # LID
                               "backbone and resid 30-59"])                                    # NMP
   R.run()

   import matplotlib.pyplot as plt
   rmsd = R.results.rmsd.T   # transpose makes it easier for plotting
   time = rmsd[1]
   fig = plt.figure(figsize=(4,4))
   ax = fig.add_subplot(111)
   ax.plot(time, rmsd[2], 'k-',  label="all")
   ax.plot(time, rmsd[3], 'k--', label="CORE")
   ax.plot(time, rmsd[4], 'r--', label="LID")
   ax.plot(time, rmsd[5], 'b--', label="NMP")
   ax.legend(loc="best")
   ax.set_xlabel("time (ps)")
   ax.set_ylabel(r"RMSD ($\AA$)")
   fig.savefig("rmsd_all_CORE_LID_NMP_ref1AKE.pdf")

.. _figure-RMSD:

.. figure:: /images/RSMD_plot.png
      :scale: 50 %
      :alt: RMSD plot

      RMSD plot for backbone and CORE, LID, NMP domain of the protein.


Functions
---------

.. autofunction:: rmsd

Analysis classes
----------------

.. autoclass:: RMSD
   :members:
   :inherited-members:

   .. attribute:: results.rmsd

       Contains the time series of the RMSD as an N×3 :class:`numpy.ndarray`
       array with content ``[[frame, time (ps), RMSD (A)], [...], ...]``.

       .. versionadded:: 2.0.0

   .. attribute:: rmsd

       Alias to the :attr:`results.rmsd` attribute.

       .. deprecated:: 2.0.0
          Will be removed in MDAnalysis 3.0.0. Please use :attr:`results.rmsd`
          instead.


.. autoclass:: RMSF
   :members:
   :inherited-members:

   .. attribute:: results.rmsf

      Results are stored in this N-length :class:`numpy.ndarray` array,
      giving RMSFs for each of the given atoms.

      .. versionadded:: 2.0.0

   .. attribute:: rmsf

      Alias to the :attr:`results.rmsf` attribute.

      .. deprecated:: 2.0.0
         Will be removed in MDAnalysis 3.0.0. Please use :attr:`results.rmsf`
         instead.

    N   )qcprot)AnalysisBaseResultsGroup)SelectionError)
asiterableiterableget_weightszMDAnalysis.analysis.rmsdFc                 8   t          j        | t           j                  } t          j        |t           j                  }|j        d         }| j        |j        k    rt	          d          |s|r4| t          j        | d|          z
  } |t          j        |d|          z
  }|dt          |          t          |           k    rt	          d          t          j        |t           j                  t          j        |          z  }|rt          j	        | ||d|          S |Ft          j
        t          j        |ddt           j        f         | |z
  dz  z            |z            S t          j
        t          j        | |z
  dz            |z            S )a	  Returns RMSD between two coordinate sets `a` and `b`.

    `a` and `b` are arrays of the coordinates of N atoms of shape
    :math:`N times 3` as generated by, e.g.,
    :meth:`MDAnalysis.core.groups.AtomGroup.positions`.

    Note
    ----
    If you use trajectory data from simulations performed under **periodic
    boundary conditions** then you *must make your molecules whole* before
    performing RMSD calculations so that the centers of mass of the mobile and
    reference structure are properly superimposed.


    Parameters
    ----------
    a : array_like
        coordinates to align to `b`
    b : array_like
        coordinates to align to (same shape as `a`)
    weights : array_like (optional)
        1D array with weights, use to compute weighted average
    center : bool (optional)
        subtract center of geometry before calculation. With weights given
        compute weighted average as center.
    superposition : bool (optional)
        perform a rotational and translational superposition with the fast QCP
        algorithm [Theobald2005]_ before calculating the RMSD; implies
        ``center=True``.

    Returns
    -------
    rmsd : float
        RMSD between `a` and `b`

    Notes
    -----
    The RMSD :math:`\rho(t)` as a function of time is calculated as

    .. math::

       \rho(t) = \sqrt{\frac{1}{N} \sum_{i=1}^N w_i \left(\mathbf{x}_i(t)
                                - \mathbf{x}_i^{\text{ref}}\right)^2}

    It is the Euclidean distance in configuration space of the current
    configuration (possibly after optimal translation and rotation) from a
    reference configuration divided by :math:`1/\sqrt{N}` where :math:`N` is
    the number of coordinates.

    The weights :math:`w_i` are calculated from the input weights
    `weights` :math:`w'_i` as relative to the mean:

    .. math::

       w_i = \frac{w'_i}{\langle w' \rangle}


    Example
    -------
    >>> import MDAnalysis as mda
    >>> from MDAnalysis.analysis.rms import rmsd
    >>> from MDAnalysis.tests.datafiles import PSF, DCD
    >>> u = mda.Universe(PSF, DCD)
    >>> bb = u.select_atoms('backbone')
    >>> A = bb.positions.copy()  # coordinates of first frame
    >>> _ = u.trajectory[-1]  # forward to last frame
    >>> B = bb.positions.copy()  # coordinates of last frame
    >>> rmsd(A, B, center=True)
    6.838544558398293


    .. versionchanged:: 0.8.1
       *center* keyword added
    .. versionchanged:: 0.14.0
       *superposition* keyword added

    dtyper   za and b must have same shape)axisweightsNz(weights must have same length as a and br   )npasarrayfloat64shape
ValueErroraveragelenmeanqcpCalcRMSDRotationalMatrixsqrtsumnewaxis)abr   centersuperpositionNs         a/srv/www/vhosts/g4struct/public_html/venv/lib/python3.11/site-packages/MDAnalysis/analysis/rms.pyrmsdr#      s}   ^ 	
1BJ'''A

1BJ'''A	
Aw!'7888  7 7 
11g6666
11g6666w<<3q66!!GHHH*WBJ777"'':J:JJ 5+Aq!T7CCC726'!!!RZ-"8QUqL"IJJQNOOO7261q5Q,//!3444    c                    t          | t                    r t          |           t          |           d} nt          |           t          u r1	 | d         | d         d} ns# t          $ r t	          d          dw xY wt          |           t
          u r0	 | d          | d          n-# t          $ r t          d	          dw xY wt          d
          t          | d                   | d<   t          | d                   | d<   | S )aM  Return a canonical selection dictionary.

    Parameters
    ----------
    select : str or tuple or dict

        - `str` -> Any valid string selection
        - `dict` -> ``{'mobile':sel1, 'reference':sel2}``
        - `tuple` -> ``(sel1, sel2)``

    Returns
    -------
    dict
        selections for 'reference' and 'mobile'. Values are guarenteed to be
        iterable (so that one can provide selections to retain order)

    Notes
    -----
    The dictionary input for `select` can be generated by
    :func:`fasta2select` based on a ClustalW_ or STAMP_ sequence alignment.
    	referencemobiler      )r(   r'   z=select must contain two selection strings (reference, mobile)Nr(   r'   zIselect dictionary must contain entries for keys 'mobile' and 'reference'.z2'select' must be either a string, 2-tuple, or dict)	
isinstancestrtypetuple
IndexErrordictKeyError	TypeErrorr   )selects    r"   process_selectionr3     sB   . &# N"6{{c&kkBB	f			 &q	q	BBFF 	 	 	&  	
 
f			8; 	 	 	,  	 LMMM!&"233F8$VK%899F;Ms   A A:B% %C c                   t     e Zd ZdZdZed             Z	 	 	 	 	 	 	 d fd		Zd
 Zd Z	d Z
ed             Z xZS )RMSDa  Class to perform RMSD analysis on a trajectory.

    The RMSD will be computed for two groups of atoms and all frames in the
    trajectory belonging to `atomgroup`. The groups of atoms are obtained by
    applying the selection selection `select` to the changing `atomgroup` and
    the fixed `reference`.

    Note
    ----
    If you use trajectory data from simulations performed under **periodic
    boundary conditions** then you *must make your molecules whole* before
    performing RMSD calculations so that the centers of mass of the selected
    and reference structure are properly superimposed.


    Run the analysis with :meth:`RMSD.run`, which stores the results
    in the array :attr:`RMSD.results.rmsd`.


    .. versionchanged:: 1.0.0
       ``save()`` method was removed, use ``np.savetxt()`` on
       :attr:`RMSD.results.rmsd` instead.
    .. versionchanged:: 2.0.0
       :attr:`rmsd` results are now stored in a
       :class:`MDAnalysis.analysis.base.Results` instance.
    .. versionchanged:: 2.8.0
       introduced :meth:`get_supported_backends` allowing for parallel
       execution on ``multiprocessing`` and ``dask`` backends.
    Tc                     dS )N)serialmultiprocessingdask clss    r"   get_supported_backendszRMSD.get_supported_backendsp  s    
 
r$   NallF皙?r   c	                 &     t          t                     j        |j        j        fi |	 | _        ||n j         _        t          |          }|d |D             ng  _        | _	        | _
        | _        | _          j        j        |d           _          j        j        |d           _        t!           j                  t!           j                  k    rSd                     j        j         j        j                  }
t&                              |
           t+          |
          t&                              d                    t!           j                                       t/          j         j        j         j        j        z
             j
        k    }t/          j        |          rt&                              d           t9           j         j                  D ]}\  }}|j        |j        k    rht&                              d                    |j        |j        |j         |j        |j!        |j        |j        |j         |j        |j!        
  
                   ~d	                     j
                  }t&                              |           t+          |          ~ fd
 j        D              _"        tG          t9           j         j"                            D ]\  }\  }}t!          |d                   t!          |d                   k    rrt&                              d           t+          d                    ||d         |d         t!          |d                   t!          |d                                       t/          j$        d          t/          j$        d          f}d}tK           j	                  rg } j	        D ]I}tK          |          r#|&                    t!          |                     4|&                    d           Jt/          j'        |          j(        dk    rtS          |          t/          j*        |          j$        |vrtS          |          tK           j	                  s j	        dk    rtW           j         j	                    j        rt!           j                  t!           j                  k    rtY          d          t9           j         j"         j                  D ]w\  }}}	 tK          |          s|dk    rtW          |d         |           3# tZ          $ r6} t]          |          t_          |          d|d         z  z             d}~ww xY wdS dS )a  Parameters
        ----------
        atomgroup : AtomGroup or Universe
            Group of atoms for which the RMSD is calculated. If a trajectory is
            associated with the atoms then the computation iterates over the
            trajectory.
        reference : AtomGroup or Universe (optional)
            Group of reference atoms; if ``None`` then the current frame of
            `atomgroup` is used.
        select : str or dict or tuple (optional)
            The selection to operate on; can be one of:

            1. any valid selection string for
               :meth:`~MDAnalysis.core.groups.AtomGroup.select_atoms` that
               produces identical selections in `atomgroup` and `reference`; or

            2. a dictionary ``{'mobile': sel1, 'reference': sel2}`` where *sel1*
               and *sel2* are valid selection strings that are applied to
               `atomgroup` and `reference` respectively (the
               :func:`MDAnalysis.analysis.align.fasta2select` function returns such
               a dictionary based on a ClustalW_ or STAMP_ sequence alignment); or

            3. a tuple ``(sel1, sel2)``

            When using 2. or 3. with *sel1* and *sel2* then these selection strings
            are applied to `atomgroup` and `reference` respectively and should
            generate *groups of equivalent atoms*.  *sel1* and *sel2* can each also
            be a *list of selection strings* to generate a
            :class:`~MDAnalysis.core.groups.AtomGroup` with defined atom order as
            described under :ref:`ordered-selections-label`).

        groupselections : list (optional)
            A list of selections as described for `select`, with the difference
            that these selections are *always applied to the full universes*,
            i.e., ``atomgroup.universe.select_atoms(sel1)`` and
            ``reference.universe.select_atoms(sel2)``. Each selection describes
            additional RMSDs to be computed *after the structures have been
            superimposed* according to `select`. No additional fitting is
            performed.The output contains one additional column for each
            selection.

            .. Note:: Experimental feature. Only limited error checking
                      implemented.

        weights : {"mass", ``None``} or array_like (optional)
             1. "mass" will use masses as weights for both `select` and `groupselections`.

             2. ``None`` will weigh each atom equally for both `select` and `groupselections`.

             3. If 1D float array of the same length as `atomgroup` is provided,
             use each element of the `array_like` as a weight for the
             corresponding atom in `select`, and assumes ``None`` for `groupselections`.

        weights_groupselections : False or list of {"mass", ``None`` or array_like} (optional)
             1. ``False`` will apply imposed weights to `groupselections` from
             ``weights`` option if ``weights`` is either ``"mass"`` or ``None``.
             Otherwise will assume a list of length equal to length of
             `groupselections` filled with ``None`` values.

             2. A list of {"mass", ``None`` or array_like} with the length of `groupselections`
             will apply the weights to `groupselections` correspondingly.

        tol_mass : float (optional)
             Reject match if the atomic masses for matched atoms differ by more
             than `tol_mass`.
        ref_frame : int (optional)
             frame index to select frame from `reference`
        verbose : bool (optional)
             Show detailed progress of the calculation if set to ``True``; the
             default is ``False``.

        Raises
        ------
        SelectionError
             If the selections from `atomgroup` and `reference` do not match.
        TypeError
             If `weights` or `weights_groupselections` is not of the appropriate type;
             see also :func:`MDAnalysis.lib.util.get_weights`
        ValueError
             If `weights` are not compatible with `atomgroup` (not the same
             length) or if it is not a 1D array (see
             :func:`MDAnalysis.lib.util.get_weights`).

             A :exc:`ValueError` is also raised if the length of `weights_groupselections`
             are not compatible with `groupselections`.

        Notes
        -----
        The root mean square deviation :math:`\rho(t)` of a group of :math:`N`
        atoms relative to a reference structure as a function of time is
        calculated as

        .. math::

           \rho(t) = \sqrt{\frac{1}{N} \sum_{i=1}^N w_i \left(\mathbf{x}_i(t)
                                    - \mathbf{x}_i^{\text{ref}}\right)^2}

        The weights :math:`w_i` are calculated from the input weights `weights`
        :math:`w'_i` as relative to the mean of the input weights:

        .. math::

           w_i = \frac{w'_i}{\langle w' \rangle}

        The selected coordinates from `atomgroup` are optimally superimposed
        (translation and rotation) on the `reference` coordinates at each time step
        as to minimize the RMSD. Douglas Theobald's fast QCP algorithm
        [Theobald2005]_ is used for the rotational superposition and to calculate
        the RMSD (see :mod:`MDAnalysis.lib.qcprot` for implementation details).

        The class runs various checks on the input to ensure that the two atom
        groups can be compared. This includes a comparison of atom masses (i.e.,
        only the positions of atoms of the same mass will be considered to be
        correct for comparison). If masses should not be checked, just set
        `tol_mass` to a large value such as 1000.

        .. _ClustalW: http://www.clustal.org/
        .. _STAMP: http://www.compbio.dundee.ac.uk/manuals/stamp.4.2/


        See Also
        --------
        rmsd


        .. versionadded:: 0.7.7
        .. versionchanged:: 0.8
           `groupselections` added
        .. versionchanged:: 0.16.0
           Flexible weighting scheme with new `weights` keyword.
        .. deprecated:: 0.16.0
           Instead of ``mass_weighted=True`` (removal in 0.17.0) use new
           ``weights='mass'``; refactored to fit with AnalysisBase API
        .. versionchanged:: 0.17.0
           removed deprecated `mass_weighted` keyword; `groupselections`
           are *not* rotationally superimposed any more.
        .. versionchanged:: 1.0.0
           `filename` keyword was removed.

        Nc                 ,    g | ]}t          |          S r:   )r3   ).0ss     r"   
<listcomp>z!RMSD.__init__.<locals>.<listcomp>  s!    ;;;aq!!;;;r$   r'   r(   zkReference and trajectory atom selections do not contain the same number of atoms: N_ref={0:d}, N_traj={1:d}z RMS calculation for {0:d} atoms.zAtoms: reference | mobilezV{0!s:>4} {1:3d} {2!s:>3} {3!s:>3} {4:6.3f}|  {5!s:>4} {6:3d} {7!s:>3} {8!s:>3}{9:6.3f}z\Inconsistent selections, masses differ by more than{0:f}; mis-matching atomsare shown above.c                 z    g | ]7} j         j        j        |d            j        j        j        |d          d8S )r'   r(   r&   )r'   universeselect_atoms	atomgrouprB   rC   selfs     r"   rD   z!RMSD.__init__.<locals>.<listcomp>U  sd     '
 '
 '
  BT^4A{^ ?$.1>(L	 '
 '
 '
r$   zSelectionError: Group SelectionzGroup selection {0}: {1} | {2}: Reference and trajectory atom selections do not contain the same number of atoms: N_ref={3}, N_traj={4}r   int64ztweights should only be 'mass', None or 1D float array.For weights on groupselections, use **weight_groupselections**r)   masszLLength of weights_groupselections is not equal to length of groupselections z happens in selection %s)0superr5   __init__rF   
trajectoryrH   r'   r3   groupselectionsr   tol_mass	ref_frameweights_groupselectionsrG   	ref_atomsmobile_atomsr   formatn_atomslogger	exceptionr   infor   absolutemassesanyerrorzipnamesegidresidresnamerL   _groupselections_atoms	enumerater   r	   appenduniquesizer1   arrayr
   r   	Exceptionr,   r+   )rJ   rH   r'   r2   rP   r   rS   rQ   rR   kwargserrmass_mismatchesaraterrmsgigroupselatomsacceptable_dtypesmsgelement_lenselement	selectione	__class__s   `                       r"   rN   zRMSD.__init__x  s   p 	#dD"9#5#@KKFKKK"&/&;"6** * <;?;;;; 	
  "'>$44f[6IJ7DN79IJt~#d&7"8"888,,2FN*D,=,E- -  S!!! %%%188T^9L9LMM	
 	
 	
 K.1B1IIKKm 	
 6/"" 	)LL4555dnd.?@@  B7bg%%LL##)6HHJGGHHJGG$ $  "##)6$-#8#8 
 LL    ((('
 '
 '
 '
 )'
 '
 '
# %.$d&ABB%
 %
 	 	 FLS% 5?##s5+='>'>>>  !BCCC$,,2FK(HE+.//E(O,,- -
 
 
 ?  Xi00"(72C2CD- 	 DL!! 	%L< + +G$$ + ''G5555 ''****y&&+a//nn$x  &.???nn$DL!! 	9T\V%;%;)4<888' 	4/00C8L4M4MMM 1   .1,+$. .  )	
(( >Gv,=,=#E(OW===    !$q''A4y7JJK  	 	 s    +U
V1VVc                 R     j         j         _         j        sTt	           j                  s# j        gt           j                  z   _        nd gt           j                  z   _        t          t           j         j
                            D ]\  }\  }}t          |          dk    r|d         j         j        |<   |St          j         j        |         t          j                  t          j         j        |                   z   j        |<   t#           j          j                   _        t#           j         j                   _         j        t          j         j        t          j                  t          j         j                  z   _        t          j         j        t          j                  t          j         j                  z   _         j        j        j        j        j        }	  j        j        j         j                   j                             j                   _         j        j         j        z
   _         j
        r fd j        D              _         j        j        j        |          n#  j        j        j        |          w xY w j                             t          j                   _!         j
        rFt          j"        dt          j                   _#         j#        $                    dd           _%        nd  _#        t          j"         j&        dt           j
                  z   f           j'        _(         j         j        )                                                     t          j                   _*        d S )NrL   r(   r   c                 ~    g | ]9} j         j        |d           j                            t          j                  :S )r'   )r'   rG   	positionsastyper   r   rI   s     r"   rD   z!RMSD._prepare.<locals>.<listcomp>  sO     6 6 6 	 43{^#FF2:$6$6	6 6 6r$   	      )+rU   rW   _n_atomsrS   r	   r   r   rP   re   r_   rd   r+   r\   r   r   r   r   r
   weights_selectrT   weights_refr'   rF   rO   tsframerR   r   _ref_comr}   _ref_coordinates_groupselections_ref_coords64r~   _ref_coordinates64zeros_rotreshape_Rn_framesresultsr#   copy_mobile_coordinates64)rJ   rq   r   rs   current_frames   `    r"   _preparezRMSD._prepare  sm   )1+ 
	  	 15~(A A 0,, 15v(9 9 0, )2,d.IJJ)
 )
 	B 	B$F$We 7||v%%7<X7M,V4"79z08
8 8 8GD8@AA8B,V4 *$*;T\JJ&t~t|DD*"$*#2:# # #+,,#-D  "z 
     ()) *D /:=C	> N#.t~>> N11$2BCCDM$(N$<t}$LD!* 6 6 6 6 "16 6 62 N#.}===DN#.}==="&"7">">rz"J"J& 		 "*555DIi''1--DGGDIH]AD$? @ @@A
 
 &*%6%@%E%E%G%G%N%NJ&
 &
"""s   A8J J-c                 :    t          dt           j        i          S )Nr#   )lookup)r   ndarray_vstackrJ   s    r"   _get_aggregatorzRMSD._get_aggregator  s    FL,G#HIIIIr$   c                 L   | j                             | j                                      t          j                  }| j         j        | j        d d <   | xj        |z  c_        | j        j	        | j
        j        f| j        j        | j        d df<   | j        rKt!          j        | j        | j        | j        | j        | j                  | j        j        | j        df<   | j                            dd          | j        d d d d f<   | j        j        d d xx         |z  cc<   t	          j        | j        j        | j                  | j        j        d d <   | j        xj        | j        z  c_        t3          t5          | j        | j                  d          D ]I\  }\  }}t          ||d         j        | j        |dz
           dd          | j        j        | j        |f<   Jd S t!          j        | j        | j        | j        d | j                  | j        j        | j        df<   d S )Nr   r   r(   F)r   r   r    )rU   r   r   r~   r   r   r}   r   _tsr   _trajectorytimer   r#   _frame_indexrd   r   r   r   r   r   r   r   dotr   re   r_   r   rS   )rJ   
mobile_comrq   refposrs   s        r"   _single_framezRMSD._single_frame  sW   &--d.ABBIIJ
 

 )-(9(C"111%""j0"" HN!4
$+RaR/0
 & 6	 ,+.MI'  Ld/23 !I--a33DGAAAqqqDM Hqqq!!!Z/!!! %'F48+=tw$G$GDHqqq!H$-/ ,56/  , ,  ' @D(O- 8!D "'@ @ @!$"3V";<< $ ,+.M'  Ld/2333r$   c                 R    d}t          j        |t                     | j        j        S )NzThe `rmsd` attribute was deprecated in MDAnalysis 2.0.0 and will be removed in MDAnalysis 3.0.0. Please use `results.rmsd` instead.)warningswarnDeprecationWarningr   r#   rJ   wmsgs     r"   r#   z	RMSD.rmsd1  ,    & 	
 	d.///|  r$   )Nr>   NNFr?   r   )__name__
__module____qualname____doc__%_analysis_algorithm_is_parallelizableclassmethodr=   rN   r   r   r   propertyr#   __classcell__rz   s   @r"   r5   r5   O  s         < -1)
 
 [
  %b b b b b bH	L
 L
 L
\J J JB B BH ! ! X! ! ! ! !r$   r5   c                   `     e Zd ZdZed             Z fdZd Zd Zd Z	e
d             Z xZS )RMSFa  Calculate RMSF of given atoms across a trajectory.

    Note
    ----
    No RMSD-superposition is performed; it is assumed that the user is
    providing a trajectory where the protein of interest has been structurally
    aligned to a reference structure (see the Examples section below). The
    protein also has be whole because periodic boundaries are not taken into
    account.


    Run the analysis with :meth:`RMSF.run`, which stores the results
    in the array :attr:`RMSF.results.rmsf`.

    c                     dS )N)r7   r:   r;   s    r"   r=   zRMSF.get_supported_backendsM  s    {r$   c                 l     t          t          |           j        |j        j        fi | || _        dS )a  Parameters
        ----------
        atomgroup : AtomGroup
            Atoms for which RMSF is calculated
        verbose : bool (optional)
             Show detailed progress of the calculation if set to ``True``; the
             default is ``False``.

        Raises
        ------
        ValueError
             raised if negative values are calculated, which indicates that a
             numerical overflow or underflow occured


        Notes
        -----
        The root mean square fluctuation of an atom :math:`i` is computed as the
        time average

        .. math::

          \rho_i = \sqrt{\left\langle (\mathbf{x}_i - \langle\mathbf{x}_i\rangle)^2 \right\rangle}

        No mass weighting is performed.

        This method implements an algorithm for computing sums of squares while
        avoiding overflows and underflows :footcite:p:`Welford1962`.


        Examples
        --------

        In this example we calculate the residue RMSF fluctuations by analyzing
        the :math:`\text{C}_\alpha` atoms. First we need to fit the trajectory
        to the average structure as a reference. That requires calculating the
        average structure first. Because we need to analyze and manipulate the
        same trajectory multiple times, we are going to load it into memory
        using the :mod:`~MDAnalysis.coordinates.MemoryReader`. (If your
        trajectory does not fit into memory, you will need to :ref:`write out
        intermediate trajectories <writing-trajectories>` to disk or
        :ref:`generate an in-memory universe
        <creating-in-memory-trajectory-label>` that only contains, say, the
        protein)::

           import MDAnalysis as mda
           from MDAnalysis.analysis import align

           from MDAnalysis.tests.datafiles import TPR, XTC

           u = mda.Universe(TPR, XTC, in_memory=True)
           protein = u.select_atoms("protein")

           # 1) the current trajectory contains a protein split across
           #    periodic boundaries, so we first make the protein whole and
           #    center it in the box using on-the-fly transformations
           import MDAnalysis.transformations as trans

           not_protein = u.select_atoms('not protein')
           transforms = [trans.unwrap(protein),
                         trans.center_in_box(protein, wrap=True),
                         trans.wrap(not_protein)]
           u.trajectory.add_transformations(*transforms)

           # 2) fit to the initial frame to get a better average structure
           #    (the trajectory is changed in memory)
           prealigner = align.AlignTraj(u, u, select="protein and name CA",
                                        in_memory=True).run()

           # 3) reference = average structure
           ref_coordinates = u.trajectory.timeseries(asel=protein).mean(axis=1)
           # make a reference structure (need to reshape into a 1-frame
           # "trajectory")
           reference = mda.Merge(protein).load_new(ref_coordinates[:, None, :],
                                                   order="afc")

        We created a new universe ``reference`` that contains a single frame
        with the averaged coordinates of the protein.  Now we need to fit the
        whole trajectory to the reference by minimizing the RMSD. We use
        :class:`MDAnalysis.analysis.align.AlignTraj`::

           aligner = align.AlignTraj(u, reference,
                                     select="protein and name CA",
                                     in_memory=True).run()

        The trajectory is now fitted to the reference (the RMSD is stored as
        `aligner.results.rmsd` for further inspection). Now we can calculate
        the RMSF::

           from MDAnalysis.analysis.rms import RMSF

           calphas = protein.select_atoms("name CA")
           rmsfer = RMSF(calphas, verbose=True).run()

        and plot::

           import matplotlib.pyplot as plt

           plt.plot(calphas.resnums, rmsfer.results.rmsf)



        References
        ----------
        .. footbibliography::


        .. versionadded:: 0.11.0
        .. versionchanged:: 0.16.0
           refactored to fit with AnalysisBase API
        .. deprecated:: 0.16.0
           the keyword argument `quiet` is deprecated in favor of `verbose`.
        .. versionchanged:: 0.17.0
           removed unused keyword `weights`
        .. versionchanged:: 1.0.0
           Support for the ``start``, ``stop``, and ``step`` keywords has been
           removed. These should instead be passed to :meth:`RMSF.run`.

        N)rM   r   rN   rF   rO   rH   )rJ   rH   rk   rz   s      r"   rN   zRMSF.__init__Q  s<    p 	#dD"9#5#@KKFKKK"r$   c                     t          j        | j        j        df          | _        | j                                        | _        d S )Nr   )r   r   rH   rW   
sumsquaresr   r   r   s    r"   r   zRMSF._prepare  s6    (DN$:A#>??O((**			r$   c                     | j         }| xj        ||dz   z  | j        j        | j        z
  dz  z  z  c_        || j        z  | j        j        z   |dz   z  | _        d S )Ng      ?r   r)   )r   r   rH   r}   r   rJ   ks     r"   r   zRMSF._single_frame  sf    ASMN$ty0.  	 ]T^%==!a%H			r$   c                     | j         }t          j        | j                            d          |dz   z            | j        _        | j        j        dk                                    st          d          d S )Nr)   )r   r   z9Some RMSF values negative; overflow or underflow occurred)	r   r   r   r   r   r   rmsfr>   r   r   s     r"   	_concludezRMSF._conclude  sy    GDO$7$7Q$7$?$?1q5$IJJ!Q&++-- 	*  	 	r$   c                 R    d}t          j        |t                     | j        j        S )NzThe `rmsf` attribute was deprecated in MDAnalysis 2.0.0 and will be removed in MDAnalysis 3.0.0. Please use `results.rmsd` instead.)r   r   r   r   r   r   s     r"   r   z	RMSF.rmsf  r   r$   )r   r   r   r   r   r=   rN   r   r   r   r   r   r   r   s   @r"   r   r   <  s             [y# y# y# y# y#v+ + +I I I   ! ! X! ! ! ! !r$   r   )NFF)r   numpyr   loggingr   libr   r   analysis.baser   r   
exceptionsr   lib.utilr   r	   r
   	getLoggerrX   r#   r3   r5   r   r:   r$   r"   <module>r      s;  .L LZ             6 6 6 6 6 6 6 6 ' ' ' ' ' ' 8 8 8 8 8 8 8 8 8 8 
	5	6	6h5 h5 h5 h5V/ / /dj! j! j! j! j!< j! j! j!Zm! m! m! m! m!< m! m! m! m! m!r$   