
     iZ                         d Z ddlZddlZddlZddlm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 d
 Zd Zd Z G d dej                  ZdS )a-  ChainReader --- :mod:`MDAnalysis.coordinates.chain`
===================================================

The :class:`ChainReader` is used by MDAnalysis internally to represent multiple
trajectories as one virtual trajectory. Users typically do not need to use the
:class:`ChainReader` explicitly and the following documentation is primarily of
interest to developers.

.. autoclass:: ChainReader
   :members:

   .. automethod:: _get_local_frame
   .. automethod:: _apply
   .. automethod:: _get
   .. automethod:: _get_same
   .. automethod:: _read_frame

    N)Tuple   )util)
asiterablestore_init_arguments   )base)corec                 T    d t          t          |           d           D             S )a   Return indices to sort a multi value tuple. Sorting is done on the first
    value of the tuple.


    Parameters
    ----------
    l : list

    Returns
    -------
    indices

    Example
    -------
    >>> multi_level_argsort(((0, 2), (4, 9), (0, 4), (7, 9)))
    [0, 2, 1, 3]

    c                     g | ]
}|d          S )r    ).0els     f/srv/www/vhosts/g4struct/public_html/venv/lib/python3.11/site-packages/MDAnalysis/coordinates/chain.py
<listcomp>z'multi_level_argsort.<locals>.<listcomp>K   s    HHHbBqEHHH    c                     | d         d         S )Nr   r   r   )xs    r   <lambda>z%multi_level_argsort.<locals>.<lambda>K   s    qtAw r   )key)sorted	enumerate)ls    r   multi_level_argsortr   8   s0    & IHF9Q<<5F5FGGGHHHHr   c           	         t          |           dk    rdgS t          |           dk    rU| d         d         | d         d         k     rddgS t          j        | d         d         | d         d                   rdgS dgS t          j        |           j        dk    rt          |           dz
  gS dg}t          t          | dd         | dd         | dd                   d          D ]\  }\  }}}t          j        |d         |d                   r||d<   0t          j        |d         |d         z
  |          s:|d         |d         k    r'|d         |d         k    r|                    |           |d         |d         k    r|                    |           | d         d         | d         d         k    r%|                    t          |           dz
             |S )aB  Given a list of start and end times this function filters out any duplicate
    time steps preferring the last tuple.

    Parameters
    ----------
    times : list
        sorted list of times
    dt : float
        timestep between two frames

    Returns
    -------
    list:
        indices of times to be used with overlaps removed

    Example
    -------
    >>> filter_times(((0, 3), (0, 3)))
    [1, ]
    >>> filter_times(((0, 3), (0, 4)))
    [1, ]
    >>> filter_times(((0, 3), (3, 4)))
    [0, 1]
    >>> filter_times(((0, 3), (2, 5), (4, 9)))
    [1, 2, 3]

    r   r   r   N)start)lennpallcloseuniquesizer   zipappend)timesdtused_idxifirstmiddlelasts          r   filter_timesr-   N   s   : 5zzQ
 	
 
Uq8A;q!$$q6M[q!eAhqk22 	 
   
y!!JJN
 	
 	
H %.E#2#JadU122Y//q% % % 	 	  E64 ;uQx++ 	HRLLVAY2B77 	q	U1X%%DGvay,@,@"""AY%(""OOA Ry|uRy|##E

Q'''Or   c                 4   t          | d                   t          j        fd| D                       }|s.d | D             }t          d                    |                    | d         j        |vr"t          d                    |                    dS )z
    Make a check that  all readers have the same filetype and are  of the
    allowed files types. Throws Exception on failure.

    Parameters
    ----------
    readers : list of MDA readers
    allowed : list of allowed formats
    r   c                 0    g | ]}t          |          S r   )
isinstance)r   r	classnames     r   r   z+check_allowed_filetypes.<locals>.<listcomp>   s#    HHH1jI66HHHr   c                 ,    g | ]}t          |          S r   )type)r   r1   s     r   r   z+check_allowed_filetypes.<locals>.<listcomp>   s    0001tAww000r   z_ChainReader: continuous=true only supported when all files are using the same reader. Found: {}z;ChainReader: continuous=True only supported for formats: {}N)r4   r    all
ValueErrorformatNotImplementedError)readersallowedonly_one_readerreadernamesr2   s       @r   check_allowed_filetypesr=      s     WQZ  IfHHHHHHHIIO 
00000{++
 
 	

 qz''!((.w
 
 	
 ('r   c                   ~    e Zd ZdZdZe	 	 	 	 d" fd	            Zed             Zd	e	e
e
f         fd
Zd Zd Zd Zd Zd Zd Zed             Zed             Zed             Zed             Zed             Zed             Zed             Zd Zd Zd Zd Zed             Zd Zd#dZ d Z!d  Z"d! Z# xZ$S )$ChainReadera;	  Reader that concatenates multiple trajectories on the fly.

    The :class:`ChainReader` is used by MDAnalysis internally to
    represent multiple trajectories as one virtual trajectory. Users
    typically do not need to use the :class:`ChainReader` explicitly.

    Chainreader can also handle a continuous trajectory split over several
    files. To use this pass the ``continuous == True`` keyword argument.
    Setting ``continuous=True`` will make the reader choose frames from the set
    of trajectories in such a way that the trajectory appears to be as
    continuous in time as possible, i.e. that time is strictly monotonically
    increasing. This means that there will be no duplicate time frames and no
    jumps backwards in time. However, there can be gaps in time (e.g., multiple
    time steps can appear to be missing). Ultimately, it is the user's
    responsibility to ensure that the input trajectories can be virtually
    stitched together in a meaningful manner. As an example take the following
    trajectory that is split into three parts. The column represents the time
    and the trajectory segments overlap. With the continuous chainreader only
    the frames marked with a + will be read.

    ::

        part01:  ++++--
        part02:      ++++++-
        part03:            ++++++++

    .. warning::

        The order in which trajectories are given to the chainreader can change
        what frames are used with the continuous option.

    The default chainreader will read all frames. The continuous option is
    currently only supported for XTC, TRR, and LAMMPSDUMP files.

    Notes
    -----
    The trajectory API attributes exist but most of them only reflect the first
    trajectory in the list; :attr:`ChainReader.n_frames`,
    :attr:`ChainReader.n_atoms`, and :attr:`ChainReader.fixed` are properly
    set, though


    .. versionchanged:: 0.11.0
       Frames now 0-based instead of 1-based
    .. versionchanged:: 0.13.0
       :attr:`time` now reports the time summed over each trajectory's
       frames and individual :attr:`dt`.
    .. versionchanged:: 0.19.0
       added ``continuous`` trajectory option
    .. versionchanged:: 0.19.0
       limit output of __repr__
    .. versionchanged:: 2.0.0
       Now ChainReader can be (un)pickled. Upon unpickling,
       current timestep is retained.

    CHAINr   NFTc                 v	     t          t                     j        dd||d t          |          }||d<   fd|D              _        g  _        |D ]}t          |t          j                  r j        	                    d           7t          |t                    r! j        	                    |d                    m j        	                    |           t          j         j                   _        d _        | _                             d           _                             d          }t          j        dg|z              _        t          j        |           _        t          j                             d                     _         j        |z   _        |rt/           j        g d	           t          j        t          j        |          d
k              rt3          d                               d          }t          j                             d                    }t          j         j        j                  |z   _        g }	 j        D ]A}
|
d          |
j        j        }|
d          |
j        j        }|		                    ||f           Bt?          |	          } fd|D              _         j        |          _         j        ||         z   _        tA           j                  d
k    rhtC          t          j        |	          |         |          } fd|D              _         j        |          _         j        |         ||         z   _        dg}d}tE           j        dd          j        d
d                   D ]\  }}|d         |d         f |j        }|j        }|d          |j        |k     rtG          j$        dtJ                     |d
          ||cxk     r|j        k     rn nt3          d          |ddd         D ]}|j        |k     r n|	                    |d         |j&        z   d
z              ||j&        d
z   z  }| j        d         j        z  }| _        | _        | _'        d _         (                                 dS )a  Set up the chain reader.

        Parameters
        ----------
        filenames : str or list or sequence
            file name or list of file names; the reader will open all file names
            and provide frames in the order of trajectories from the list. Each
            trajectory must contain the same number of atoms in the same order
            (i.e. they all must belong to the same topology). The trajectory
            format is deduced from the extension of each file name.

            Extension: `filenames` are either a single file name or list of file
            names in either plain file names format or ``(filename, format)``
            tuple combination. This allows explicit setting of the format for
            each individual trajectory file.
        skip : int (optional)
            skip step (also passed on to the individual trajectory readers);
            must be same for all trajectories
        dt : float (optional)
            Passed to individual trajectory readers to enforce a common time
            difference between frames, in MDAnalysis time units. If not set, each
            reader's `dt` will be used (either inferred from the trajectory
            files, or set to the reader's default) when reporting frame times;
            note that this might lead an inconsistent time difference between
            frames.
        continuous : bool (optional)
            treat all trajectories as one single long trajectory. Adds several
            checks; all trajectories have the same dt, they contain at least 2
            frames, and they are all of the same file-type. Not implemented for
            all trajectory formats! This can be used to analyze GROMACS
            simulations without concatenating them prior to analysis.
        **kwargs : dict (optional)
            all other keyword arguments are passed on to each trajectory reader
            unchanged

        r@   )filenameskipconvert_unitsr'   Nr'   c                 8    g | ]}t          j        |fd iS )rD   )r
   reader)r   rB   rD   kwargss     r   r   z(ChainReader.__init__.<locals>.<listcomp>(  s@     
 
 
 KHHHHH
 
 
r   r   n_atomsn_frames)XTCTRR
LAMMPSDUMPTRCr   zNChainReader: Need at least two frames in every trajectory with continuous=Truer   c                 *    g | ]}j         |         S r   r9   r   r)   selfs     r   r   z(ChainReader.__init__.<locals>.<listcomp>p  s    >>>DLO>>>r   c                 *    g | ]}j         |         S r   rO   rP   s     r   r   z(ChainReader.__init__.<locals>.<listcomp>x  s    BBBAQBBBr   z!Missing frame in continuous chainz=ChainReader: Interleaving not supported with continuous=True.r   ))superr?   __init__r   r9   	filenamesr0   r    ndarrayr%   tuplearray!_ChainReader__active_reader_indexrC   	_get_samerH   _getcumsum_start_framessumrI   dtstotal_timesr=   anyRuntimeErrorasarrayonesshapetstimer   r   r-   r$   warningswarnUserWarningframe_sfrewind)rQ   rU   rC   r'   
continuousrD   rG   fnrI   r&   r1   r   endsort_idxr(   sfr1r2r1_start_time
start_timerf   	__class__s   `    ``              r   rT   zChainReader.__init__   s	   \ 	*k4  ) 	
'		
 	

 	
 	
 	
 y))	 >F4L
 
 
 
 
%
 
 

  	* 	*B"bj)) *%%d++++B&& *%%be,,,,%%b))))$.11 &'"	~~i00 99Z((  YsX~66x((8DIIdOO,,8h.  L	#AAA   vbhx((A-.. "<  
 %%Bz$))J"7"788Hwtx~..3DH E\ + +!	"dieS\*****511H>>>>X>>>DL!^H5DN#x(8*<<D 4<  1$$'(A2FFBBBBBBB!%!9#'8H#58J#J  B Hdl3B3/abb1ABB ) )B1r!u "W
27Z''M;[  
 1 :777777777&0   TTrT(  Bw++ ,		"R&28+a/000BHqL(R(11H!#D$DMDH r   c                     t          | t          j                   o(t          j        |           ot          j        |            S )zQCan ChainReader read the object *thing*

        .. versionadded:: 1.0.0
        )r0   r    rV   r   iterableisstream)things    r   _format_hintzChainReader._format_hint  sB     5"*--- )e$$)M%(((	
r   returnc                     |dk     rt          d          t          j        | j        |          dz
  }|dk     r"t          d                    |                    || j        |         z
  }||fS )a  Find trajectory index and trajectory frame for chained frame `k`.

        Parameters
        ----------

        k : int
           Frame `k` in the chained trajectory can be found in the trajectory at
           index *i* and frame index *f*.

           Frames are internally treated as 0-based indices into the trajectory.

        Returns
        -------
        i : int
            trajectory
        f : int
            frame in trajectory i


        Raises
        ------
        IndexError for `k<0` or `i<0`.


        Note
        ----
        Does not check if `k` is larger than the maximum number of frames in
        the chained trajectory.

        r   z%Virtual (chained) frames must be >= 0r   z.Cannot find trajectory for virtual frame {0:d})
IndexErrorbisectbisect_rightr]   r7   )rQ   kr)   fs       r   _get_local_framezChainReader._get_local_frame  s    > q55DEEE 2A66:q55@GGJJ   "1%%!tr   c                     | j                                         }| j                                        |d<   |d         d | j        dz            D ]}|                                 |d         | _        |S )Nrf   r9   r   )__dict__copyrf   __deepcopy__rY   rm   )rQ   staterF   s      r   __getstate__zChainReader.__getstate__  sv    ""$$g**,,d
 I&'G)Ca)G'GH 	 	FMMOOOO +r   c                 \    | j                             |           | j        | j        _        d S N)r   update_ChainReader__current_framerf   rk   )rQ   r   s     r   __setstate__zChainReader.__setstate__  s(    U###,r   c                 6    | j                             |          S r   )active_readerconvert_time_from_nativerQ   ts     r   r   z$ChainReader.convert_time_from_native  s    !::1===r   c                 6    | j                             |          S r   )r   convert_time_to_nativer   s     r   r   z"ChainReader.convert_time_to_native  s    !88;;;r   c                 6    | j                             |          S r   )r   convert_from_nativerQ   r   s     r   convert_pos_from_nativez#ChainReader.convert_pos_from_native  s    !55a888r   c                 6    | j                             |          S r   )r   convert_pos_to_nativer   s     r   r   z!ChainReader.convert_pos_to_native  s    !77:::r   c                     | j         j        S r   )r   skip_timesteprQ   s    r   r   zChainReader.skip_timestep  s    !//r   c                     | j         j        S r   )r   deltar   s    r   r   zChainReader.delta  s    !''r   c                     | j         j        S )z;:attr:`periodic` attribute of the currently read trajectory)r   periodicr   s    r   r   zChainReader.periodic  s     !**r   c                     | j         j        S )z8:attr:`units` attribute of the currently read trajectory)r   unitsr   s    r   r   zChainReader.units  s     !''r   c                 >    	 | j         j        S # t          $ r Y dS w xY w)z=:attr:`compressed` attribute of the currently read trajectoryN)r   
compressedAttributeErrorr   s    r   r   zChainReader.compressed  s5    	%00 	 	 	44	s    
c                     | j         j        S )z1Cumulative frame number of the current time step.)rf   rk   r   s    r   rk   zChainReader.frame  s     w}r   c                     |                      | j                  \  }}| j        d|                                         || j        |         z  z   S )zMCumulative time of the current frame in MDAnalysis time units (typically ps).N)r   rk   r`   r^   r_   )rQ   	trajindexsubframes      r   rg   zChainReader.time  sO     #33DJ??	8ZiZ(,,..DHY<O1OO	
r   c                 .    fd| j         D             S )z/Execute `method` with `kwargs` for all readers.c                 F    g | ]} |                               d i S )r   __getattribute__)r   rF   rG   methods     r   r   z&ChainReader._apply.<locals>.<listcomp>,  sG     
 
 
 ,F##F++55f55
 
 
r   rO   )rQ   r   rG   s    ``r   _applyzChainReader._apply*  s6    
 
 
 
 
,
 
 
 	
r   c                 *    fd| j         D             S )z$Get value of `attr` for all readers.c                 :    g | ]}|                               S r   r   )r   rF   attrs     r   r   z$ChainReader._get.<locals>.<listcomp>3  s'    III&''--IIIr   rO   )rQ   r   s    `r   r[   zChainReader._get1  s    IIIIDLIIIIr   c                    t          j        |                     |                    }|d         }t          j        ||          sGt          j        | j                  ||k             }t          d                    |||                    |S )ax  Verify that `attr` has the same value for all readers and return value.

        Parameters
        ----------
        attr : str
            attribute name

        Returns
        -------
        value : int or float or str or object
            common value of the attribute

        Raises
        ------
        ValueError if not all readers have the same value

        r   zBThe following trajectories do not have the correct {0}  ({1}):
{2})r    rX   r[   r!   rU   r6   r7   )rQ   r   valuesvaluebad_trajs        r   rZ   zChainReader._get_same5  s    $ $))D//**q	{65)) 	x//%@H%vdE8<<   r   c                     d|cxk    rt          | j                  k     s6n t          d                    t          | j                                      || _        | j        |         | _        dS )z"Make reader `i` the active reader.r   z#Reader index must be 0 <= i < {0:d}N)r   r9   r   r7   rY   rU   rB   )rQ   r)   s     r   __activate_readerzChainReader.__activate_readerQ  sv     Q****T\******5<<S=N=NOO   &'"q)r   c                 &    | j         | j                 S )z;Reader instance from which frames are currently being read.)r9   rY   r   s    r   r   zChainReader.active_reader[  s     |D677r   c                     |                      |          \  }}|                     |           | j        |          | j        j        | _        || j        _        || _        | j        S )a   Position trajectory at frame index `frame` and
        return :class:`~MDAnalysis.coordinates.timestep.Timestep`.

        The frame is translated to the corresponding reader and local
        frame index and the :class:`Timestep` instance in
        :attr:`ChainReader.ts` is updated.

        Notes
        -----
        `frame` is 0-based, i.e. the first frame in the trajectory is
        accessed with ``frame = 0``.

        See Also
        --------
        :meth:`~ChainReader._get_local_frame`

        )r   _ChainReader__activate_readerr   rf   rk   r   )rQ   rk   r)   r   s       r   _read_framezChainReader._read_frame`  sb    $ $$U++1q!!!1$'$wr   c                 :   || j         }| j        | j        dz
  k     rr|                     | j        dz             \  }}|                     |           | j        |         | _         | j        dz   | j         _        | xj        dz  c_        | j         S t                      )Nr   )rf   r   rI   r   r   r   rk   StopIteration)rQ   rf   jr   s       r   _read_next_timestepzChainReader._read_next_timestep|  s    :B$-!"333(()=)ABBDAq""1%%%(+DG 014DGM  A%  7N//!r   c                 >    d| _         |                     d           dS )z@Internal method: Rewind trajectories themselves and trj pointer.r   rm   N)r   r   r   s    r   _reopenzChainReader._reopen  s"    !Hr   c                 0    |                      d           d S )Nclose)r   r   s    r   r   zChainReader.close  s    Gr   c                    t          | j                  dk    rf| j        d         r*t          j                            | j        d                   nd}d                    |t          | j                  dz
            }n$d                    d | j        D                       }d	                    | j        j        || j	        | j
        
          S )N   r   numpy.ndarrayz{fname} and {nfnames} morer   )fnamenfnamesz, c                 T    g | ]%}|rt           j                            |          nd &S )r   )ospathbasename)r   ro   s     r   r   z(ChainReader.__repr__.<locals>.<listcomp>  sB        -/CBG$$R(((O  r   zF<{clsname} containing {fname} with {nframes} frames of {natoms} atoms>)clsnamer   nframesnatoms)r   rU   r   r   r   r7   joinrw   __name__rI   rH   )rQ   r   fnamess      r   __repr__zChainReader.__repr__  s    t~"" >!$%  !2333$ 
 288S%8%81%< 9  FF YY "n   Fv/|	   	
r   )r   NFTr   )%r   
__module____qualname____doc__r7   r   rT   staticmethodr|   r   intr   r   r   r   r   r   r   propertyr   r   r   r   r   rk   rg   r   r[   rZ   r   r   r   r   r   r   r   __classcell__)rw   s   @r   r?   r?      so       7 7r F u u u u u un 	
 	
 \	
)U38_ ) ) ) )V  - - -
> > >< < <9 9 9; ; ; 0 0 X0 ( ( X( + + X+ ( ( X(   X   X 	
 	
 X	

 
 
J J J  8* * * 8 8 X8  8" " " "  
  
 
 
 
 
 
 
r   r?   )r   rh   os.pathr   r   typingr   numpyr    libr   lib.utilr   r    r	   r
   r   r-   r=   
ReaderBaser?   r   r   r   <module>r      s  0 &                    7 7 7 7 7 7 7 7            I I I,F F FR
 
 
4z
 z
 z
 z
 z
$/ z
 z
 z
 z
 z
r   