
     iM                         d Z ddlZddlZddlZddlmZmZmZ ddl	m
Z
 d Z G d d	e          Z G d
 de          ZdS )a  Core Topology object --- :mod:`MDAnalysis.core.topology`
========================================================

.. versionadded:: 0.16.0

:class:`Topology` is the core object that holds all topology information.

TODO: Add in-depth discussion.

Notes
-----
For developers: In MDAnalysis 0.16.0 this new topology system was
introduced and discussed as issue `#363`_; this issue contains key
information and discussions on the new system. The issue number *363*
is also being used as a short-hand in discussions to refer to the new
topology system.


.. _`#363`: https://github.com/MDAnalysis/mdanalysis/issues/363

Classes
-------

.. autoclass:: Topology
   :members:
.. autoclass:: TransTable
   :members:

Helper functions
----------------

.. autofunction:: make_downshift_arrays

    N   )Atomindices
Resindices
Segindices   )NoDataErrorc                    t          |           st          j        g t                    S t          j        | d          }| |         }t          j        |d          \  }}t          j        ||                                dz   g          }t          j        |t                    }t          j	        t          j
        t          j        |          |                    }t          j        ||j        d                   }|dd         ||<   |D ]}|dk    rd||<   ||dz
           ||<   t          j        ||dd	                   }	|	                    d           t          j        |	t                    S )
a  From an upwards translation table, create the opposite direction

    Turns a many to one mapping (eg atoms to residues) to a one to many mapping
    (residues to atoms)

    Parameters
    ----------
    upshift : array_like
        Array of integers describing which parent each item belongs to
    nparents : integer
        Total number of parents that exist.

    Returns
    -------
    downshift : array_like (dtype object)
        An array of arrays, each containing the indices of the children
        of each parent.  Length `nparents` + 1

    Examples
    --------

    To find the residue to atom mappings for a given atom to residue mapping:

    >>> import numpy as np
    >>> import MDAnalysis as mda
    >>> from MDAnalysis.core.topology import make_downshift_arrays
    >>> atom2res = np.array([0, 1, 0, 2, 2, 0, 2])
    >>> make_downshift_arrays(atom2res, 3)
    array([array([0, 2, 5]), array([1]), array([3, 4, 6]), None], dtype=object)

    Entry 0 corresponds to residue 0 and says that this contains atoms 0, 2 & 5

    Notes
    -----
    The final entry in the return array will be ``None`` to ensure that the
    dtype of the array is :class:`object`.

    .. warning:: This means negative indexing should **never**
                 be used with these arrays.
    dtype	mergesort)kindT)return_indexr   r   N)lennparrayobjectargsortuniquemaxzerosintsort	setdiff1darangeappendshapesplit)
upshiftnparentsorderupshift_sortedu_valuesindicesresidue_indicesmissing_residsmissing_resid	downshifts
             b/srv/www/vhosts/g4struct/public_html/venv/lib/python3.11/site-packages/MDAnalysis/core/topology.pymake_downshift_arraysr*   D   sl   R w<< *x&)))) Jw[111EU^N	.tDDDHg vx!!3455Hhxs333OWR\")H*=*=xHHIINi!5a!899G 'OH' P PA-.OM**-<]Q=N-OOM** 455I T8IV,,,,    c                       e Zd ZdZ	 	 ddZd Zed             Zed             Zed             Z	d Z
d	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd ZdS )
TransTablea;  Membership tables with methods to translate indices across levels.

    There are three levels; Atom, Residue and Segment.  Each Atom **must**
    belong in a Residue, each Residue **must** belong to a Segment.

    When translating upwards, eg finding which Segment a Residue belongs in,
    a single numpy array is returned.  When translating downwards, two options
    are available; a concatenated result (suffix `_1`) or a list for each parent
    object (suffix `_2d`).

    Parameters
    ----------
    n_atoms : int
        number of atoms in topology
    n_residues : int
        number of residues in topology
    n_segments : int
        number of segments in topology
    atom_resindex : 1-D array
        resindex for each atom in the topology; the number of unique values in
        this array must be <= `n_residues`, and the array must be length
        `n_atoms`; giving None defaults to placing all atoms in residue 0
    residue_segindex : 1-D array
        segindex for each residue in the topology; the number of unique values
        in this array must be <= `n_segments`, and the array must be length
        `n_residues`; giving None defaults to placing all residues in segment 0


    Attributes
    ----------
    n_atoms : int
        number of atoms in topology
    n_residues : int
        number of residues in topology
    n_segments : int
        number of segments in topology
    size : tuple
        tuple ``(n_atoms, n_residues, n_segments)`` describing the shape of
        the TransTable

    .. versionchanged:: 2.3.0
        Lazy building RA and SR.
    Nc                 d   || _         || _        || _        |&t          j        |t          j                  | _        n^t          j        |t          j                                                  | _        t          | j                  |k    st          d          d | _        |&t          j        |t          j                  | _        n^t          j        |t          j                                                  | _        t          | j                  |k    st          d          d | _        d S )Nr
   z!atom_resindex must be len n_atomsz'residue_segindex must be len n_residues)n_atoms
n_residues
n_segmentsr   r   intp_ARasarraycopyr   
ValueError_RA_RS_SR)selfr/   r0   r1   atom_resindexresidue_segindexs         r)   __init__zTransTable.__init__   s     $$  xrw777DHHz-rw???DDFFDHtx==G++ !DEEE #x
"':::DHHz"2"'BBBGGIIDHtx==J.. !JKKKr+   c                 h    |                      | j        | j        | j        | j        | j                  S )z$Return a deepcopy of this Transtabler;   r<   )	__class__r/   r0   r1   r3   r8   r:   s    r)   r5   zTransTable.copy   s6    ~~LOO(!X  
 
 	
r+   c                 \    | j         t          | j        | j                  | _         | j         S N)r7   r*   r3   r0   rA   s    r)   RAzTransTable.RA   &    8,TXtGGDHxr+   c                 \    | j         t          | j        | j                  | _         | j         S rC   )r9   r*   r8   r1   rA   s    r)   SRzTransTable.SR   rE   r+   c                 *    | j         | j        | j        fS )z_The shape of the table, ``(n_atoms, n_residues, n_segments)``.

        :meta private:
        )r/   r0   r1   rA   s    r)   sizezTransTable.size   s     dot??r+   c                     | j         |         S )zGet residue indices for each atom.

        Parameters
        ----------
        aix : array
            atom indices

        Returns
        -------
        rix : array
            residue index for each atom

        )r3   )r:   aixs     r)   atoms2residueszTransTable.atoms2residues        x}r+   c                     | j         }	 t          j        ||                   S # t          $ r* ||                             t          j        d          cY S w xY w)a  Get atom indices collectively represented by given residue indices.

        Parameters
        ----------
        rix : array
            residue indices

        Returns
        -------
        aix : array
            indices of atoms present in residues, collectively

        Tr5   )rD   r   concatenater6   astyper2   r:   rixrD   s      r)   residues2atoms_1dzTransTable.residues2atoms_1d  a     W	6>"S'*** 	6 	6 	6c7>>"'>55555	6   # 1AAc                     | j         	 fd|D             S # t          $ r |                                         gcY S w xY w)a  Get atom indices represented by each residue index.

        Parameters
        ----------
        rix : array
            residue indices

        Returns
        -------
        raix : list
            each element corresponds to a residue index, in order given in
            `rix`, with each element being an array of the atom indices present
            in that residue

        c                 D    g | ]}|                                          S  rO   ).0rrD   s     r)   
<listcomp>z0TransTable.residues2atoms_2d.<locals>.<listcomp>,  %    ...QBqEJJLL...r+   )rD   	TypeErrorr5   rR   s     @r)   residues2atoms_2dzTransTable.residues2atoms_2d  a      W	$....#.... 	$ 	$ 	$sGLLNN####	$    %A A c                     | j         |         S )zGet segment indices for each residue.

        Parameters
        ----------
        rix : array
            residue indices

        Returns
        -------
        six : array
            segment index for each residue

        )r8   )r:   rS   s     r)   residues2segmentszTransTable.residues2segments0  rM   r+   c                     | j         }	 t          j        ||                   S # t          $ r* ||                             t          j        d          cY S w xY w)a$  Get residue indices collectively represented by given segment indices

        Parameters
        ----------
        six : array
            segment indices

        Returns
        -------
        rix : array
            sorted indices of residues present in segments, collectively

        TrO   )rG   r   rP   r6   rQ   r2   r:   sixrG   s      r)   segments2residues_1dzTransTable.segments2residues_1d@  rU   rV   c                     | j         	 fd|D             S # t          $ r |                                         gcY S w xY w)a  Get residue indices represented by each segment index.

        Parameters
        ----------
        six : array
            residue indices

        Returns
        -------
        srix : list
            each element corresponds to a segment index, in order given in
            `six`, with each element being an array of the residue indices
            present in that segment

        c                 D    g | ]}|                                          S rY   rO   )rZ   srG   s     r)   r\   z3TransTable.segments2residues_2d.<locals>.<listcomp>g  r]   r+   )rG   r^   r5   re   s     @r)   segments2residues_2dzTransTable.segments2residues_2dU  r`   ra   c                 V    |                      |          }|                     |          S )zGet segment indices for each atom.

        Parameters
        ----------
        aix : array
            atom indices

        Returns
        -------
        rix : array
            segment index for each atom

        )rL   rc   r:   rK   rS   s      r)   atoms2segmentszTransTable.atoms2segmentsl  s+     !!#&&%%c***r+   c                 V    |                      |          }|                     |          S )a  Get atom indices collectively represented by given segment indices.

        Parameters
        ----------
        six : array
            segment indices

        Returns
        -------
        aix : array
            sorted indices of atoms present in segments, collectively

        )rg   rT   )r:   rf   rS   s      r)   segments2atoms_1dzTransTable.segments2atoms_1d}  s+     '',,%%c***r+   c                 J                           |          } fd|D             S )a  Get atom indices represented by each segment index.

        Parameters
        ----------
        six : array
            residue indices

        Returns
        -------
        saix : list
            each element corresponds to a segment index, in order given in
            `six`, with each element being an array of the atom indices present
            in that segment

        c                 :    g | ]}                     |          S rY   )rT   )rZ   rS   r:   s     r)   r\   z0TransTable.segments2atoms_2d.<locals>.<listcomp>  s'    <<<&&s++<<<r+   )rk   )r:   rf   rixss   `  r)   segments2atoms_2dzTransTable.segments2atoms_2d  s2    " ((--<<<<t<<<<r+   c                 (    || j         |<   d| _        dS )zMove aix to be in rixN)r3   r7   rm   s      r)   	move_atomzTransTable.move_atom      r+   c                 (    || j         |<   d| _        dS )zMove rix to be in sixN)r8   r9   )r:   rS   rf   s      r)   move_residuezTransTable.move_residue  rw   r+   c                     | xj         dz  c_         d | _        t          j        | j        t          j        |g          g          | _        d | _        | j         dz
  S Nr   )r0   r7   r   rP   r8   r   r9   )r:   segidxs     r)   add_ResiduezTransTable.add_Residue  sQ    1>48RXvh-?-?"@AA""r+   c                 D    | xj         dz  c_         d | _        | j         dz
  S r{   )r1   r9   rA   s    r)   add_SegmentzTransTable.add_Segment  s&    1""r+   c                 (    | j         }d |d<   d |d<   |S )Nr7   r9   )__dict__)r:   attrss     r)   __getstate__zTransTable.__getstate__  s     eer+   )NN)__name__
__module____qualname____doc__r=   r5   propertyrD   rG   rI   rL   rT   r_   rc   rg   rk   rn   rp   rt   rv   ry   r}   r   r   rY   r+   r)   r-   r-      sp       * *b    <
 
 
   X
   X
 @ @ X@   6 6 6*$ $ $,   6 6 6*$ $ $.+ + +"+ + +"= = =*  
  
# # ## # #
    r+   r-   c                       e Zd ZdZ	 	 	 	 	 	 ddZd Zed             Zed             Zed             Z	d	 Z
d
 Zed             Zed             Zd Zd ZdS )Topologyat  In-memory, array-based topology database.

    The topology model of MDanalysis features atoms, which must each be a
    member of one residue. Each residue, in turn, must be a member of one
    segment. The details of maintaining this heirarchy, and mappings of atoms
    to residues, residues to segments, and vice-versa, are handled internally
    by this object.

    r   Nc                     t          |||||          | _        |g }|                    t                      t	                      t                      f           g | _        |D ]}|                     |           dS )a  
        Parameters
        ----------
        n_atoms : int
            number of atoms in topology. Must be larger then 1 at each level
        n_residues : int
            number of residues in topology. Must be larger then 1 at each level
        n_segments : int
            number of segments in topology. Must be larger then 1 at each level
        attrs : TopologyAttr objects
            components of the topology to be included
        atom_resindex : array
            1-D array giving the resindex of each atom in the system
        residue_segindex : array
            1-D array giving the segindex of each residue in the system

        r?   N)r-   ttextendr   r   r   r   add_TopologyAttr)r:   r/   n_resn_segr   r;   r<   topologyattrs           r)   r=   zTopology.__init__  s    4 '-
 
 
 =EkmmZ\\:<<@AAA 
! 	0 	0L!!,////	0 	0r+   c                    |                      ddd          }| j                                        |_        | j        D ]L}t	          |t
          t          t          f          r%|                    |                                           M|S )z"Return a deepcopy of this Topologyr   )	r@   r   r5   r   
isinstancer   r   r   r   )r:   newattrs      r)   r5   zTopology.copy  sy    nnQ1%%J 	. 	.D$j* EFF   ----
r+   c                     | j         j        S rC   )r   r/   rA   s    r)   r/   zTopology.n_atoms  s    wr+   c                     | j         j        S rC   )r   r0   rA   s    r)   r0   zTopology.n_residues
      w!!r+   c                     | j         j        S rC   )r   r1   rA   s    r)   r1   zTopology.n_segments  r   r+   c                 ~    | j                             |           | |_        |                     |j        |           dS )z|Add a new TopologyAttr to the Topology.

        Parameters
        ----------
        topologyattr : TopologyAttr

        N)r   r   top__setattr__attrnamer:   r   s     r)   r   zTopology.add_TopologyAttr  sA     	
,'''.=====r+   c                 n    |                      |j                   | j                            |           dS )zRemove a TopologyAttr from the Topology.

        If it is not present, nothing happens.

        Parameters
        ----------
        topologyattr : TopologyAttr


        .. versionadded:: 2.0.0
        N)__delattr__r   r   remover   s     r)   del_TopologyAttrzTopology.del_TopologyAttr  s7     	.///
,'''''r+   c                 .    t          d | j                  S )z1A list of the guessed attributes in this topologyc                 `    t          | j        t          j                  s| j        nd| j        v S )NTr   
is_guessedtyping	Containerxs    r)   <lambda>z-Topology.guessed_attributes.<locals>.<lambda>1  s.    "1<1ABB*Q\) r+   filterr   rA   s    r)   guessed_attributeszTopology.guessed_attributes-  '      
 J
 
 	
r+   c                 .    t          d | j                  S )z/A list of the attributes read from the topologyc                 b    t          | j        t          j                  s| j         nd| j        v S )NFr   r   s    r)   r   z*Topology.read_attributes.<locals>.<lambda>=  s2    "1<1ABB+AL  al* r+   r   rA   s    r)   read_attributeszTopology.read_attributes9  r   r+   c                    | j         D ]_}|j        dk    s|j        vrHfd| j         D             }t          d                    d                    |                              `| j                            |j                  }| j         D ]0}|j        dk    s|j                 }|	                    |           1|S )a+  
        Returns
        -------
        residx of the new Residue

        Raises
        ------
        NoDataError
          If not all data was provided.  This error is raised before any changes


        .. versionchanged:: 2.1.0
           Added use of _add_new to TopologyAttr resize
        residuec              3   N   K   | ]}|j         d k    r|j        v|j        V   dS )r   N
per_objectsingularrZ   r   	new_attrss     r)   	<genexpr>z'Topology.add_Residue.<locals>.<genexpr>Y  sM        944 M::	 M ;::: r+   z8Missing the following attributes for the new Residue: {}, )
r   r   r   r   formatjoinr   r}   segindex_add_new)r:   segmentr   r   missingresidxnewvals     `    r)   r}   zTopology.add_ResidueE  s      J 	 	D?i//}I--    $
   "##)6$))G*<*<#=#=   . $$W%566 J 	" 	"D?i//t}-FMM&!!!!r+   c                 v   | j         D ]^}|j        dk    rQ|j        vrHfd| j         D             }t          d                    d                    |                              _| j                                        }| j         D ]0}|j        dk    s|j                 }|                    |           1|S )a  Adds a new Segment to the Topology

        Parameters
        ----------
        new_attrs : dict
          the new attributes for the new segment, eg {'segid': 'B'}

        Raises
        -------
        NoDataError
          if an attribute wasn't specified.

        Returns
        -------
        ix : int
          the idx of the new segment


        .. versionchanged:: 2.1.0
           Added use of _add_new to resize topology attrs
        r   c              3   N   K   | ]}|j         d k    r|j        v|j        V   dS )r   Nr   r   s     r)   r   z'Topology.add_Segment.<locals>.<genexpr>  sM          Oy88 $Y > >	  !? > > > r+   z8Missing the following attributes for the new Segment: {}r   )	r   r   r   r   r   r   r   r   r   )r:   r   r   r   r|   r   s    `    r)   r   zTopology.add_Segmentr  s    , J 	 	D)++=	11   $(J  G &!6$))G"4"455   $$&&J 	" 	"D?i//t}-FMM&!!!!r+   )r   r   r   NNN)r   r   r   r   r=   r5   r   r/   r0   r1   r   r   r   r   r}   r   rY   r+   r)   r   r     s         *0 *0 *0 *0X
 
 
   X " " X" " " X"
> 
> 
>( ( ( 	
 	
 X	
 	
 	
 X	
+ + +Z/ / / / /r+   r   )r   
contextlibnumpyr   r   topologyattrsr   r   r   
exceptionsr   r*   r   r-   r   rY   r+   r)   <module>r      s   0" "F          > > > > > > > > > > $ $ $ $ $ $E- E- E-Pt t t t t t t tn	^ ^ ^ ^ ^v ^ ^ ^ ^ ^r+   