
     i                     ^    d 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	  G d d	e          Z
dS )
aY  No Jump Trajectory Unwrapping --- :mod:`MDAnalysis.transformations.nojump`
=======================================================================================

Unwraps the trajectory such that atoms never move more than half a periodic box length.
The consequence of this is that particles will diffuse across periodic boundaries when
needed. This unwrapping method is suitable as a preprocessing step to calculate
molecular diffusion, or more commonly to keep multi-domain proteins whole during trajectory
analysis.
The algorithm used is based on :footcite:p:`Kulke2022`.

.. autoclass:: NoJump

    N   )TransformationBase   )dueDoi)NoDataErrorc                   r     e Zd ZdZ ej         ed          de           	 	 d	 fd	            Zd Z xZ	S )
NoJumpa  
    Returns transformed coordinates for the given timestep so that an atom
    does not move more than half the periodic box size between two timesteps, and will move
    across periodic boundary edges. The algorithm used is based on :footcite:p:`Kulke2022`,
    equation B6 for non-orthogonal systems, so it is general to most applications where
    molecule trajectories should not "jump" from one side of a periodic box to another.

    Note that this transformation depends on a periodic box dimension being set for every
    frame in the trajectory, and that this box dimension can be transformed to an orthonormal
    unit cell. If not, an error is emitted. Since it is typical to transform all frames
    sequentially when unwrapping trajectories, warnings are emitted if non-sequential timesteps
    are transformed using NoJump.

    Example
    -------

    Suppose you had a molecular trajectory with a protein dimer that moved across a periodic
    boundary. This will normally appear to make the dimer split apart. This transformation
    uses the molecular motions between frames in a wrapped trajectory to create an unwrapped
    trajectory where molecules never move more than half a periodic box dimension between subsequent
    frames. Thus, the normal use case is to apply the transformation to every frame of a trajectory,
    and to do so sequentially.

    .. code-block:: python

        transformation = NoJump()
        u.trajectory.add_transformations(transformation)
        for ts in u.trajectory:
            print(ts.positions)

    In this case, ``ts.positions`` will return the NoJump unwrapped trajectory, which would keep
    protein dimers together if they are together in the inital timestep. The unwrapped trajectory may
    also be useful to compute diffusion coefficients via the Einstein relation.
    To reverse the process, wrap the coordinates again.

    Returns
    -------
    MDAnalysis.coordinates.timestep.Timestep

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

    z10.1021/acs.jctc.2c00327z[Works through the orthogonal case for unwrapping, and proposes the non-orthogonal approach.)descriptionpathTNc                     t                                          |d           d | _        d| _        d| _        || _        d S )NF)max_threadsparallelizabler   A)super__init__prev	old_frameolder_framecheck_c)selfcheck_continuityr   	__class__s      k/srv/www/vhosts/g4struct/public_html/venv/lib/python3.11/site-packages/MDAnalysis/transformations/nojump.pyr   zNoJump.__init__\   sC     	[GGG	'    c                 V   |j         }|d|j         }t          |          	 t          j                            |          }n1# t          j        j        $ r d|j         }t          |          w xY w|j        dk    r|j        |z  | _        d| _	        d| _
        |S | j        ri| j
        dk    r^| j	        | j
        z
  |j        | j	        z
  k    r>t          j        dt                     |j        |z  | _        |j        | _	        d| _
        |S | j        r?t          j        | j	        |j        z
            dk    rt          j        dt                     |j        |z  }| j        }|t          j        ||z
            z
  }||z  |_        || _        | j	        | _
        |j        | _	        |S )	Nz-Periodic box dimensions not provided at step z3Periodic box dimensions are not invertible at step r   r   zyNoJump detected that the interval between frames is unequal.We are resetting the reference frame to the current timestep.r   zNoJump transform is only accurate when positionsdo not move by more than half a box length.Currently jumping between frames with a step of more than 1.This might be fine, but depending on the trajectory stride,this might be inaccurate.)triclinic_dimensionsframer   nplinalginvLinAlgError	positionsr   r   r   r   warningswarnUserWarningabsround)r   tsLmsgLinversefcurrentfprevnewpositionss           r   
_transformzNoJump._transformo   s   #9L"(LLCc"""	#y}}Q''HHy$ 	# 	# 	#RRRCc"""	# 8q== x/DIDN!DIL	 C''$"224>)+ + MP  
 x/DIXDN"DI< 	BF4>BH#<==BBM,
    <(*I 	  "(8e+;"<"<<#a'  		  >	s   A .A2)TN)
__name__
__module____qualname____doc__r   dciter   r   r1   __classcell__)r   s   @r   r
   r
   .   s        + +Z SY&''4	   ( ( ( ( ( (A A A A A A Ar   r
   )r5   numpyr    r%   baser   r   r   
exceptionsr   r
    r   r   <module>r<      s   0       $ $ $ $ $ $         $ $ $ $ $ $B B B B B B B B B Br   