
     iE                       d Z ddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlmZmZ ddlmZ ddlmZ ddlmZ ddlmZmZmZ dd	lmZ d
dlmZ d
dlmZmZ d
dlm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z' d
dl(m)Z) d
dl*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4 d
dl5m6Z6 ddl7m8Z8  ej9        d          Z:d Z;d Z<ddZ=ddddZ>ddddZ?d Z@ G d deA          ZBd ZCdS ) a  =========================================================
Core object: Universe --- :mod:`MDAnalysis.core.universe`
=========================================================

The :class:`~MDAnalysis.core.universe.Universe` class ties a topology
and a trajectory together. Almost all code in MDAnalysis starts with a
``Universe``.

Normally, a ``Universe`` is created from files::

  import MDAnalysis as mda
  u = mda.Universe("topology.psf", "trajectory.dcd")

In order to construct new simulation system it is also convenient to
construct a ``Universe`` from existing
:class:`~MDAnalysis.core.group.AtomGroup` instances with the
:func:`Merge` function.


Classes
=======

.. autoclass:: Universe
   :members:

Functions
=========

.. autofunction:: Merge

    N   )_TOPOLOGY_ATTRS_PARSERS)NoDataError)util)ProgressBar)cachedNamedStreamisstream)find_fragments   )groups)get_reader_forget_parser_for)ComponentBase	GroupBaseAtomResidueSegment	AtomGroupResidueGroupSegmentGroup)Topology)
AtomAttrResidueAttrSegmentAttr
SegindicesSegids
ResindicesResidsAtomindicesBFACTOR_WARNING_Connection)TopologyObject)get_guesserzMDAnalysis.core.universec                 N    ddl m}  j        d t          j                  D             }fd|D             }d t          j                  D             }||g fd|D             z   }||g fd|D             z   } |||          \  }	}
|
d         }|
d	         }t          |          }|
dd
         t          |          gfdt          |          D             z   }|                    |            ||f|f          \  }\  }t          |          }|                    t          |                     d j        D             }t           j        j        ||||	|          t          |          dk    r|D ]}                    |            _        d
S )a>  Update the topology of a Universe with new atomwise resids and segids.

    Parameters
    ----------
    universe : Universe
        The universe to update.
    atomwise_resids : numpy.ndarray
        The new atomwise residue indices.
    atomwise_segids : numpy.ndarray
        The new atomwise segment indices.
    r   )change_squashc                 ^    g | ]*\  }}t           |j        vt          |t                    (|+S  )r   target_classes
isinstancer!   .0idx	each_attrs      b/srv/www/vhosts/g4struct/public_html/venv/lib/python3.11/site-packages/MDAnalysis/core/universe.py
<listcomp>z+_update_topology_by_ids.<locals>.<listcomp>   sF       C9333I{33 4 	333    c                 *    g | ]}j         |         S r)   attrs)r-   r/   tops     r0   r1   z+_update_topology_by_ids.<locals>.<listcomp>   s     DDDiSYy!DDDr2   c                     g | ]M\  }}t           |j        v r:t          |j        v!t          |t                    6t          |t
                    K|NS r)   )r   r*   r   r+   r    r   r,   s      r0   r1   z+_update_topology_by_ids.<locals>.<listcomp>   sh     	 	 	C	000	 888	622 9	:66 9	 	 988r2   c                     g | ]=}j         |         j        d k    t          j        j         |         j                  >S )resnums)r5   attrnamegetattratomsr-   r/   r6   universes     r0   r1   z+_update_topology_by_ids.<locals>.<listcomp>   sN     9 9 99Y(I55 		) 4 =>>555r2   c                 Z    g | ]'}t          j        j        |         j                  (S r)   )r;   r<   r5   r:   r=   s     r0   r1   z+_update_topology_by_ids.<locals>.<listcomp>   s?     : : : 		) 4 =>>: : :r2   r   r   Nc                 b    g | ]+\  }}j         |                             |                   ,S r)   )r5   	__class__)r-   r.   r/   res_squashed_res_attrsr6   s      r0   r1   z+_update_topology_by_ids.<locals>.<listcomp>   sJ     $ $ $ C 		)&&'=c'BCC$ $ $r2   c                     g | ]f}t           |j        v t          |t                    %t          |t                    :t          |t
                    Ot          |t                    d|gS r)   )r   r*   r+   r   r!   r   r   )r-   r/   s     r0   r1   z+_update_topology_by_ids.<locals>.<listcomp>   s~     
 
 
	000	622 1	;77 1  	:66 1  	:66	 1 	 100r2   r5   atom_resindexresidue_segindex)topology.baser'   	_topology	enumerater5   lenr    extendappendr   r   r<   n_atomsadd_TopologyAttr)r>   atomwise_residsatomwise_segidsr'   atom_attrindicesr5   residue_attrindicesres_criteriares_to_squashresidxres_squashedresidsres_squashed_segids
n_residues	res_attrssegidxsegids
n_segmentsother_attrseach_otherattrrB   r6   s   `                   @@r0   _update_topology_by_idsr`   p   s    .----- 
C '	22   EDDD3CDDDE	 	'	22	 	 	 $_5 9 9 9 9 9,9 9 9 L %o6 : : : : :,: : : M
 )=}EEFL!_F&q/VJ)!""-  $ $ $ $ $ ((;<<$ $ $ I
 
LL &	!4 6 FIV VJ	LL   
 

 
 
K   C ;!) 	1 	1N  0000 Hr2   c                 x    t          |           r*t          | d          r| j        }nd }t          | |          S | S )Nname)r   hasattrrb   r
   )topology_names     r0   _check_file_likerf      sG     ,8V$$ 	MEEE8U+++Or2   c                    t          | |          }	  ||           5 } |j        di |}d d d            n# 1 swxY w Y   n# t          t          f$ rc}|j        3t          j        |j                 dv rt          j                    d         |t          d                    | ||                    d }~wt          t          f$ r)}t          d                    | ||                    d }~ww xY w|S )Nformat)ENOENTEACCESr   zEFailed to load from the topology file {0} with parser {1}.
Error: {2}zFFailed to construct topology from file {0} with parser {1}.
Error: {2}r)   )r   parseIOErrorOSErrorerrno	errorcodesysexc_infori   
ValueErrorNotImplementedError)topology_filetopology_formatkwargsparserprd   errs          r0   _topology_from_file_liker{      sh   M/BBBF
VM"" 	)aqw((((H	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	)W    9 U_SY%? D
 &
 &

 ,..#, #VM63??  
 +, 
 
 
vs;;
 
 	

 Os@   A 8A <A < A C0AB33C0$C++C0ri   rv   c                      |s	| |} n|| }| |fS Nr)   )ri   rv   coordinatess      r0   _resolve_formatsr      s,     %>$FF$$O?""r2   Fri   all_coordinatesc                    |s|sY| W	 t          | |           | f|z   }n># t          t          f$ r* t          j        d                    |                      Y nw xY w|S )Nrh   z6No coordinate reader found for {}. Skipping this file.)r   rs   	TypeErrorwarningswarnri   )filenameri   r   r   s       r0   _resolve_coordinatesr   	  s      	4k 	4h.B	48F3333 $+3KK I& 	 	 	M#VH--    	 s     8AAc                    t          j                    \  | _        | _        | j        j        D ]}|                     |           t          t          j	        | j        j
                  |           | _        t          t          j	        | j        j                  |           | _        t          t          j	        | j        j                  |           | _        d S r~   )r   make_classes_class_bases_classesrH   r5   _process_attrr   nparangerM   r<   r   rY   residuesr   r]   segments)r>   attrs     r0   _generate_from_topologyr     s     06/B/D/D,H8, "( % %t$$$$ ry);)CDDhOOHN$
	($/00( H %
	($/00( Hr2   c                      e Zd ZdZ	 d6ddddddddddddd	d
dZd Ze	 	 	 	 	 	 	 	 d7d            Zed             Z		 	 	 d8dZ
	 d9dZd Zed             Zed             Zed             Zed             Zd Zed             Zd Zed             Zej        d             Zed             Zed             Zed             Zej        d             Zd6dZd  Zd! Zd" Zd6d#Zd$ Z	 d:d%Zd:d&Z d' Z!d;d(Z"d;d)Z#d;d*Z$d+ Z%d, Z&d- Z'd. Z(d/ Z)e e*d0          d1                         Z+e	 	 	 	 	 d<d3            Z,	 	 	 	 d=d4Z-d>d5Z.dS )?Universea*  The MDAnalysis Universe contains all the information describing the system.

    The system always requires a *topology file* --- in the simplest case just
    a list of atoms. This can be a CHARMM/NAMD PSF file or a simple coordinate
    file with atom informations such as XYZ, PDB, GROMACS GRO or TPR, or CHARMM
    CRD. See :ref:`Supported topology formats` for what kind of topologies can
    be read.

    A *trajectory file* provides coordinates; the coordinates have to be
    ordered in the same way as the list of atoms in the topology. A trajectory
    can be a single frame such as a PDB, CRD, or GRO file, or it can be a MD
    trajectory (in CHARMM/NAMD/LAMMPS DCD, GROMACS XTC/TRR, AMBER nc, generic
    XYZ format, ...).  See :ref:`Supported coordinate formats` for what can be
    read as a "trajectory".

    As a special case, when the topology is a file that contains atom
    information *and* coordinates (such as XYZ, PDB, GRO or CRD, see
    :ref:`Supported coordinate formats`) then the coordinates are immediately
    loaded from the "topology" file unless a trajectory is supplied.

    Parameters
    ----------
    topology: str, stream, Topology, numpy.ndarray, None
        A CHARMM/XPLOR PSF topology file, PDB file or Gromacs GRO file; used to
        define the list of atoms. If the file includes bond information,
        partial charges, atom masses, ... then these data will be available to
        MDAnalysis. Alternatively, an existing
        :class:`MDAnalysis.core.topology.Topology` instance may be given,
        numpy coordinates, or ``None`` for an empty universe.
    coordinates: str, stream, list of str, list of stream (optional)
        Coordinates can be provided as files of
        a single frame (eg a PDB, CRD, or GRO file); a list of single
        frames; or a trajectory file (in CHARMM/NAMD/LAMMPS DCD, Gromacs
        XTC/TRR, or generic XYZ format). The coordinates must be
        ordered in the same way as the list of atoms in the topology.
        See :ref:`Supported coordinate formats` for what can be read
        as coordinates. Alternatively, streams can be given.
    topology_format: str, ``None``, default ``None``
        Provide the file format of the topology file; ``None`` guesses it from
        the file extension. Can also pass a subclass of
        :class:`MDAnalysis.topology.base.TopologyReaderBase` to define a custom
        reader to be used on the topology file.
    format: str, ``None``, default ``None``
        Provide the file format of the coordinate or trajectory file; ``None``
        guesses it from the file extension. Note that this keyword has no
        effect if a list of file names is supplied because the "chained" reader
        has to guess the file format for each individual list member.
        Can also pass a subclass of :class:`MDAnalysis.coordinates.base.ProtoReader`
        to define a custom reader to be used on the trajectory file.
    all_coordinates: bool, default ``False``
        If set to ``True`` specifies that if more than one filename is passed
        they are all to be used, if possible, as coordinate files (employing a
        :class:`MDAnalysis.coordinates.chain.ChainReader`). The
        default behavior is to take the first file as a topology and the
        remaining as coordinates. The first argument will always always be used
        to infer a topology regardless of *all_coordinates*.
    guess_bonds: bool, default ``False``
        Once Universe has been loaded, attempt to guess the connectivity
        between atoms.  This will populate the .bonds, .angles, and .dihedrals
        attributes of the Universe.

        .. deprecated:: 2.8.0
           This keyword is deprecated and will be removed in MDAnalysis 3.0.
           Please pass ("bonds", "angles", "dihedrals") into
           `to_guess` or `force_guess` instead to guess bonds, angles,
           and dihedrals respectively.

    vdwradii: dict, ``None``, default ``None``
        For use with *guess_bonds*. Supply a dict giving a vdwradii for each
        atom type which are used in guessing bonds.

        .. deprecated:: 2.8.0
           This keyword is deprecated and will be removed in MDAnalysis 3.0.
           Please pass it into Guesser creation (:mod:`~MDAnalysis.guesser`),
           or to :meth:`~MDAnalysis.core.universe.Universe.guess_TopologyAttrs`
           method instead. If passed into `guess_TopologyAttrs`, it will
           override the values set during Guesser creation.

    context: str or :mod:`Guesser<MDAnalysis.guesser>`, default ``'default'``
        Type of the Guesser to be used in guessing TopologyAttrs
    to_guess: list[str] (optional, default ``['types', 'masses']``)
        TopologyAttrs to be guessed. These TopologyAttrs will be wholly
        guessed if they don't exist in the Universe. If they already exist in
        the Universe, only empty or missing values will be guessed.

        .. warning::
            In MDAnalysis 2.x, types and masses are being automatically guessed
            if they are missing (``to_guess=('types, 'masses')``).
            However, starting with release 3.0 **no guessing will be done
            by default** and it will be up to the user to request guessing
            using ``to_guess`` and ``force_guess``.

    force_guess: list[str], (optional)
        TopologyAttrs in this list will be force guessed. If the TopologyAttr
        does not already exist in the Universe, this has no effect. If the
        TopologyAttr does already exist, all values will be overwritten
        by guessed values.
    fudge_factor: float, default [0.55]
        For use with *guess_bonds*. Supply the factor by which atoms must
        overlap each other to be considered a bond.

        .. deprecated:: 2.8.0
           This keyword is deprecated and will be removed in MDAnalysis 3.0.
           Please pass it into Guesser creation (:mod:`~MDAnalysis.guesser`),
           or to :meth:`~MDAnalysis.core.universe.Universe.guess_TopologyAttrs`
           method instead. If passed into `guess_TopologyAttrs`, it will
           override the values set during Guesser creation.

    lower_bound: float, default [0.1]
        For use with *guess_bonds*. Supply the minimum bond length.

        .. deprecated:: 2.8.0
           This keyword is deprecated and will be removed in MDAnalysis 3.0.
           Please pass it into Guesser creation (:mod:`~MDAnalysis.guesser`),
           or to :meth:`~MDAnalysis.core.universe.Universe.guess_TopologyAttrs`
           method instead. If passed into `guess_TopologyAttrs`, it will
           override the values set during Guesser creation.


    transformations: function or list, ``None``, default ``None``
        Provide a list of transformations that you wish to apply to the
        trajectory upon reading. Transformations can be found in
        :mod:`MDAnalysis.transformations`, or can be user-created.
    in_memory: bool, default ``False``
        After reading in the trajectory, transfer it to an in-memory
        representations, which allow for manipulation of coordinates.
    in_memory_step: int, default 1
        Only read every nth frame into in-memory representation.
    continuous: bool, default ``False``
        The `continuous` option is used by the
        :mod:`ChainReader<MDAnalysis.coordinates.chain>`, which contains the
        functionality to treat independent trajectory files as a single virtual
        trajectory.
    **kwargs: extra arguments are passed to the topology parser.
        For instance, when reading a PDB file
        (:class:`PDBReader<MDAnalysis.coordinates.PDB>`,
        :class:`PDBParser<MDAnalysis.topology.PDBParser>`), set
        ``force_chainids_to_segids=True`` to make the universe use the
        chainIDs (column 22) instead of the segmentIDs (column 73-76) as the
        `segids` in the universe and select the corresponding SegmentGroup.

    Attributes
    ----------
    trajectory : base.ReaderBase or base.SingleFrameReaderBase
        currently loaded trajectory reader; readers are described in
        :ref:`Coordinates`
    dimensions : numpy.ndarray
        system dimensions (simulation unit cell, if set in the
        trajectory) at the *current time step*
        (see :attr:`MDAnalysis.coordinates.base.Timestep.dimensions`).
        The unit cell can be set for the current time step (but the change is
        not permanent unless written to a file).
    atoms : AtomGroup
        all particles (:class:`~MDAnalysis.core.groups.Atom`) in the system,
        as read from the `topology` file
    residues : ResidueGroup
        all residues (:class:`~MDAnalysis.core.groups.Residue`) in the system
    segments : SegmentGroup
        all segments (:class:`~MDAnalysis.core.groups.Segment`) in the system
    bonds : topologyattrs.Bonds
        all bonds (if defined in the `topology`) as provided by
        :attr:`Universe.atoms.bonds`
    angles : topologyattrs.Angles
        all angles (if defined in the `topology`), same as
        :attr:`Universe.atoms.angles`
    dihedrals : topologyattrs.Dihedrals
        all dihedral angles (if defined in the `topology`), same as
        :attr:`Universe.atoms.dihedrals`
    impropers : topologyattrs.Impropers
        all improper dihedral angles (if defined in the `topology`), same as
        :attr:`Universe.atoms.impropers`

    Examples
    --------
    Examples for setting up a :class:`Universe`::

       u = Universe(topology, trajectory)          # read system from file(s)
       u = Universe(pdbfile)                       # read atoms and coordinates from PDB or GRO
       u = Universe(topology, [traj1, traj2, ...]) # read from a list of trajectories
       u = Universe(topology, traj1, traj2, ...)   # read from multiple trajectories

    Load new data into a universe (replaces old trajectory and does *not* append)::

       u.load_new(trajectory)                      # read from a new trajectory file

    Selecting atoms with :meth:`~Universe.select_atoms` ::

       ag = u.select_atoms(...)

    returns an :class:`~MDAnalysis.core.groups.AtomGroup`.


    .. versionchanged:: 1.0.0
        Universe() now raises an error. Use Universe(None) or :func:`Universe.empty()` instead.
        Removed instant selectors.

    .. versionchanged:: 2.0.0
        Universe now can be (un)pickled.
        ``topology`` and ``trajectory`` are reserved upon unpickle.
    .. versionchanged:: 2.5.0
        Added fudge_factor and lower_bound parameters for use with
        *guess_bonds*.

    .. versionchanged:: 2.8.0
        Added :meth:`~MDAnalysis.core.universe.Universe.guess_TopologyAttrs` API
        guessing masses and atom types after topology
        is read from a registered parser.

    .. versionchanged:: 2.10.0
        Added :meth: `~MDAnalysis.core.universe.Universe.set_groups`
        API to set residues/segments based on the atomwise resids/segids.

    NFg?g?default)typesmassesr)   r   )r   ri   rv   transformationsguess_bondsvdwradiifudge_factorlower_bound	in_memorycontextto_guessforce_guessin_memory_stepc                   d | _         di i| _        d | _        d | _        d | _        d | _        t          |          | _        |||||	|
||||d
| _        | j        	                    |           t          |||d\  }}t          |t                    s*|(t          |          | _        t          | j        fd|i|}||| _        nt!          d          t#          |            t%          | j        g|R ||d}|r | j        |f||
|d| |r!t)          |          r|g} | j         j        |  |r.t-          j        dt0                     t3          |          g d	z   }|                     |||d
           d S )N_valid)
r   r   r   r   r   r   r   ri   rv   r   r|   rv   zmTopology argument required to make Universe. Try Universe.empty(n_atoms, ...) to construct your own Universe.r   )ri   r   r   a  Bond guessing through the `guess_bonds` keyword is deprecated and will be removed in MDAnalysis 3.0. Instead, pass 'bonds', 'angles', and 'dihedrals' to the `to_guess` keyword in Universe for guessing these if they are not present, or `force_guess` if they are and you wish to replace these bonds with guessed values. The kwargs `fudge_factor`, `vdwradii`, and `lower_bound` are also deprecated and will be removed in MDAnalysis 3.0, where they should be passed into the Context for guessing on Universe instantiation. If using guess_TopologyAttrs, pass these kwargs to the method instead, as they will override the previous Context values.)bondsangles	dihedralsF)error_if_missing)_trajectory_cacher<   r   r   r   r%   _context_kwargsupdater   r+   r   rf   r{   rH   r   r   r   load_newcallableadd_transformationsr   r   DeprecationWarninglistguess_TopologyAttrs)selfrd   r   ri   rv   r   r   r   r   r   r   r   r   r   r   r   rw   s                    r0   __init__zUniverse.__init__
  sJ   (  n
#G,,.& (&",..
 
 	F###"2#
 #
 #
 (H-- 	h6F,X66DM/ />BH H %DNN %   	 %%%*M

 
 +	
 
 
  	DM#-	 
     	C(( 4#2"30D0/BB 	IM/ #  $ H~~(H(H(HHH  X{U 	! 	
 	
 	
 	
 	
r2   c                     | j                                         }|                     | j                                        d|          }| j                                        |_        |S )z+Return an independent copy of this Universer)   r   r   )r   copyrA   rH   
trajectory)r   r   news      r0   r   zUniverse.copyw  s^    -$$&&nnN!!B  
 
 --//
r2   c
                    |sd}d}| |dk    rt          j        dt                     | |dk    rt          j        dt                     t          |||||          }
 | |
d          }|dk    s|rut	          j        ||d	ft          j        
          }|rt	          j        |          nd}|	rt	          j        |          nd}	 t          |          |d|||	          |_	        |S )a  Create a blank Universe

        Useful for building a Universe without requiring existing files,
        for example for system building.

        If `trajectory` is set to ``True``, a
        :class:`MDAnalysis.coordinates.memory.MemoryReader` will be
        attached to the Universe.

        Parameters
        ----------
        n_atoms: int
          number of Atoms in the Universe
        n_residues: int, default 1
          number of Residues in the Universe, defaults to 1
        n_segments: int, default 1
          number of Segments in the Universe, defaults to 1
        n_frames: int, default 1
          number of Frames in the Universe, defaults to 1
        atom_resindex: array like, optional
          mapping of atoms to residues, e.g. with 6 atoms,
          `atom_resindex=[0, 0, 1, 1, 2, 2]` would put 2 atoms
          into each of 3 residues.
        residue_segindex: array like, optional
          mapping of residues to segments
        trajectory: bool, optional
          if ``True``, attaches a
          :class:`MDAnalysis.coordinates.memory.MemoryReader` allowing
          coordinates to be set and written.
        velocities: bool, optional
          include velocities in the
          :class:`MDAnalysis.coordinates.memory.MemoryReader`
        forces: bool, optional
          include forces in the
          :class:`MDAnalysis.coordinates.memory.MemoryReader`

        Returns
        -------
        Universe
          :class:`~MDAnalysis.core.universe.Universe` instance with dummy
          values for atoms and undefined coordinates/velocities/forces

        Examples
        --------
        For example to create a new Universe with 6 atoms in 2 residues, with
        positions for the atoms and a mass attribute::

          u = mda.Universe.empty(6, 2,
                                 atom_resindex=np.array([0, 0, 0, 1, 1, 1]),
                                 trajectory=True,
                )
          u.add_TopologyAttr('masses')

        .. versionadded:: 0.17.0
        .. versionchanged:: 0.19.0
           The attached Reader when trajectory=True is now a MemoryReader
        .. versionchanged:: 1.0.0
           Universes can now be created with 0 atoms

        r   Nr   zZResidues specified but no atom_resindex given.  All atoms will be placed in first Residue.z_Segments specified but no segment_resindex given.  All residues will be placed in first Segment)rE   rF   r)   )r      dtypefac)orderrM   
velocitiesforces)
r   r   UserWarningr   r   zerosfloat32
zeros_liker   r   )clsrM   rY   r]   n_framesrE   rF   r   r   r   r6   ucoordsvelss                 r0   emptyzUniverse.empty  s<   R  	JJ Z!^^M=   #
QM?   '-
 
 
 Cb!!!a<<:<Xx!4BJGGGF,6@2=(((DD.4>R]6***$F 2>&11  AL r2   c                     | S r~   r)   r   s    r0   r>   zUniverse.universe  s	     r2   c                    || S t          t          j        |                    dk    rt          j        |          d         }t                              d                    |                     	 t          ||          }n5# t          $ r(}t          d                    ||                    d}~ww xY w| j	        j
        |d<    ||fd|i|| _        | j        j
        t          | j	                  k    rLt          d	                    | j        j        t          | j	                  || j        j
        
                    |r | j        dd|i| | S )a	  Load coordinates from `filename`.

        The file format of `filename` is autodetected from the file name suffix
        or can be explicitly set with the `format` keyword. A sequence of files
        can be read as a single virtual trajectory by providing a list of
        filenames.


        Parameters
        ----------
        filename: str or list
            the coordinate file (single frame or trajectory) *or* a list of
            filenames, which are read one after another.
        format: str or list or object (optional)
            provide the file format of the coordinate or trajectory file;
            ``None`` guesses it from the file extension. Note that this
            keyword has no effect if a list of file names is supplied because
            the "chained" reader has to guess the file format for each
            individual list member [``None``]. Can also pass a subclass of
            :class:`MDAnalysis.coordinates.base.ProtoReader` to define a custom
            reader to be used on the trajectory file.
        in_memory: bool (optional)
            Directly load trajectory into memory with the
            :class:`~MDAnalysis.coordinates.memory.MemoryReader`

            .. versionadded:: 0.16.0

        **kwargs: dict
            Other kwargs are passed to the trajectory reader (only for
            advanced use)

        Returns
        -------
        universe: Universe

        Raises
        ------
        TypeError
             if trajectory format can not be determined or no appropriate
             trajectory reader found


        .. versionchanged:: 0.8
           If a list or sequence that is provided for `filename` only contains
           a single entry then it is treated as single coordinate file. This
           has the consequence that it is not read by the
           :class:`~MDAnalysis.coordinates.chain.ChainReader` but directly by
           its specialized file format reader, which typically has more
           features than the
           :class:`~MDAnalysis.coordinates.chain.ChainReader`.

        .. versionchanged:: 0.17.0
           Now returns a :class:`Universe` instead of the tuple of file/array
           and detected file type.
        .. versionchanged:: 2.4.0
           Passes through kwargs if `in_memory=True`.

        Nr   r   z#Universe.load_new(): loading {0}...rh   zKCannot find an appropriate coordinate reader for file '{0}'.
           {1}rM   ri   zThe topology and {form} trajectory files don't have the same number of atoms!
Topology number of atoms {top_n_atoms}
Trajectory: {fname} Number of atoms {trj_n_atoms})formtop_n_atomsfnametrj_n_atomsstepr)   )rJ   r   
asiterableloggerdebugri   r   rs   r   r<   rM   r   transfer_to_memory)r   r   ri   r   r   rw   readerrz   s           r0   r   zUniverse.load_new  s   F Ktx(())Q..x003H:AA(KKLLL	#HV<<<FF 	 	 	!!'#!6!6  	 !J.y &CC&CFCC?"c$*oo55D EKF/ #DJ" $ 7	 EK E E	
 
 
  	C#D#BBB6BBBs   2B 
B6#B11B6c           	         ddl m} t          | j        |          st	          t          | j                            |||                     }t	          | j                  }t          j	        ||dft          j
                  }	| j        j        }
|
j        }|
j        }|
j        du}|rt          j        |	          nd}|rt          j        |	          nd}|r"t          j	        |dft          j
                  nd}t!          t#          | j        |||         |d                    D ]\  }}
t          j        |	|         |
j                   |r t          j        ||         |
j                   |r t          j        ||         |
j                   |r t          j        ||         |
j                   |d	} ||	f|| j        j        j        |z  | j        j        ||d
|| _        dS dS )a
  Transfer the trajectory to in memory representation.

        Replaces the current trajectory reader object with one of type
        :class:`MDAnalysis.coordinates.memory.MemoryReader` to support in-place
        editing of coordinates.

        Parameters
        ----------
        start: int, optional
            start reading from the nth frame.
        stop: int, optional
            read upto and excluding the nth frame.
        step: int, optional
            Read in every nth frame. [1]
        verbose: bool, optional
            Will print the progress of loading trajectory to memory, if
            set to True. Default value is False.


        .. versionadded:: 0.16.0
        .. versionchanged:: 2.4.0
           Passes through kwargs to MemoryReader
        r   )MemoryReaderr   r   N   zLoading frames)verbosedescr   )
dimensionsdtr   r   r   )coordinates.memoryr   r+   r   rJ   rangecheck_slice_indicesr<   r   r   r   tshas_velocities
has_forcesr   r   rI   r   copyto	positionsr   r   r   r   )r   startstopr   r   rw   r   r   rM   r   r   has_velshas_forshas_dimsr   r   r   is                     r0   r   zUniverse.transfer_to_memoryg  s'   4 	655555$/<88 -	t::5$MMN H $*ooG(Hgq#9LLLK#B(H}H}D0H7?I{333TJ3;ER];///F=EO(Abj99994  #OE$tO4#)    < <2 	+a.",777 <IjmR];;; 4IfQi333 <IjmR];;;
 |*l%?%(4/1%   DOOOK-	 -	r2   c                 &     | j         j        |i |S )zwSelect atoms.

        See Also
        --------
        :meth:`MDAnalysis.core.groups.AtomGroup.select_atoms`
        )r<   select_atoms)r   argsrw   s      r0   r   zUniverse.select_atoms  s     'tz&7777r2   c                     | j         j        S )z5Bonds between atoms.

        :meta private:
        )r<   r   r   s    r0   r   zUniverse.bonds  s     zr2   c                     | j         j        S )z6Angles between atoms.

        :meta private:
        )r<   r   r   s    r0   r   zUniverse.angles  s     z  r2   c                     | j         j        S )z?Dihedral angles between atoms.

        :meta private:
        )r<   r   r   s    r0   r   zUniverse.dihedrals       z##r2   c                     | j         j        S )zHImproper dihedral angles between atoms.

        :meta private:
        )r<   	impropersr   s    r0   r   zUniverse.impropers  r   r2   c                 R    d                     t          | j                            S )Nz<Universe with {n_atoms} atoms>)rM   )ri   rJ   r<   r   s    r0   __repr__zUniverse.__repr__  s,    
 177
OO 8 
 
 	
r2   c                 0     | |d|          }||_         |S )z;Special method used by __reduce__ to deserialise a Universer)   r   )r   )r   r6   trajr   r   s        r0   _unpickle_UzUniverse._unpickle_U  s&     Cb'222r2   c                 \    | j         | j        | j        | j                                        ffS r~   )r   rH   r   r   r   r   s    r0   
__reduce__zUniverse.__reduce__  s1    
 ^T-t}/A/A/C/CD
 	
r2   c                     | j         j        S )zDCurrent dimensions of the unitcell.

        :meta private:
        coordr   r   s    r0   r   zUniverse.dimensions  s     z$$r2   c                     || j         _        dS )zTSet dimensions if the Timestep allows this

        .. versionadded:: 0.9.0
        Nr   )r   boxs     r0   r   zUniverse.dimensions  s     !$
r2   c                     | j         j        S )a|  Reference to current timestep and coordinates of universe.

        The raw trajectory coordinates are :attr:`Universe.coord.positions`,
        represented as a :class:`numpy.float32` array.

        Because :attr:`coord` is a reference to a
        :class:`~MDAnalysis.coordinates.timestep.Timestep`, it changes its contents
        while one is stepping through the trajectory.

        .. Note::

           In order to access the coordinates it is better to use the
           :meth:`AtomGroup.positions` method; for instance, all coordinates of
           the Universe as a numpy array: :meth:`Universe.atoms.positions`.

        )r   r   r   s    r0   r  zUniverse.coord  s    $ !!r2   c                 4    t          j        | j                  S )z2keyword arguments used to initialize this universe)r   deepcopyr   r   s    r0   rw   zUniverse.kwargs   s     }T\***r2   c                 <    | j         | j         S t          d          )zbReference to trajectory reader object containing trajectory data.

        :meta private:
        Nz"No trajectory loaded into Universe)r   AttributeErrorr   s    r0   r   zUniverse.trajectory%  s%     '## !EFFFr2   c                     | ` || _         d S r~   )r   )r   values     r0   r   zUniverse.trajectory0  s     r2   c           
      *   t          |t                    r|dv rt          j        t          t
                     	 t          |         }|                    | j        j	        | j        j
        | j        j        |          }ne# t          $ rX d                    |d                    t          t          j                                                  }t#          |          dw xY w| j                            |           |                     |           dS )a  Add a new topology attribute to the Universe

        Adding a TopologyAttribute to the Universe makes it available to
        all AtomGroups etc throughout the Universe.

        Parameters
        ----------
        topologyattr: TopologyAttr or string
          Either a MDAnalysis TopologyAttr object or the name of a possible
          topology attribute.
        values: np.ndarray, optional
          If initiating an attribute from a string, the initial values to
          use.  If not supplied, the new TopologyAttribute will have empty
          or zero values.

        Example
        -------
        For example to add bfactors to a Universe:

        >>> import MDAnalysis as mda
        >>> from MDAnalysis.tests.datafiles import PSF, DCD
        >>> u = mda.Universe(PSF, DCD)
        >>> u.add_TopologyAttr('tempfactors')
        >>> u.atoms.tempfactors
        array([0., 0., 0., ..., 0., 0., 0.])

        .. versionchanged:: 0.17.0
           Can now also add TopologyAttrs with a string of the name of the
           attribute to add (eg 'charges'), can also supply initial values
           using values keyword.

        .. versionchanged:: 1.1.0
            Now warns when adding bfactors to a Universe with
            existing tempfactors, or adding tempfactors to a
            Universe with existing bfactors.
            In version 2.0, MDAnalysis will stop treating
            tempfactors and bfactors as separate attributes. Instead,
            they will be aliases of the same attribute.
        )bfactorbfactors)rM   rY   r]   valueszUnrecognised topology attribute name: '{}'.  Possible values: '{}'
To raise an issue go to: https://github.com/MDAnalysis/mdanalysis/issues, N)r+   strr   r   r"   r   r   
from_blankrH   rM   rY   r]   KeyErrorri   joinsortedkeysrs   rN   r   )r   topologyattrr  tclserrmsgs        r0   rN   zUniverse.add_TopologyAttr5  s   P lC(( 	666o/ABBB&|4  $ N2#~8#~8!	  /      
3 
3 
3 v$dii7K7M7M0N0N&O&O   !((d2
3$ 	''555<(((((s   A? ?A"C!c                 j   t          |t                    sS	 |j        }nJ# t          $ r= 	 |j        dz   }n.# t          $ r! t          dt          |                     dw xY wY nw xY w	 t          |         j        }nN# t          $ rA d	                    t          t                              }d| d| d}t          |          dw xY w	 t          | j        |          }n"# t          $ r t          d| d	          dw xY w| j                            |           |                     |           dS )
a]  Remove a topology attribute from the Universe

        Removing a TopologyAttribute from the Universe makes it unavailable to
        all AtomGroups etc throughout the Universe.

        Parameters
        ----------
        topologyattr: TopologyAttr or string
          Either a MDAnalysis TopologyAttr object or the name of a possible
          topology attribute.

        Example
        -------
        For example to remove bfactors to a Universe:

        >>> import MDAnalysis as mda
        >>> from MDAnalysis.tests.datafiles import PSF, DCD
        >>> u = mda.Universe(PSF, DCD)
        >>> u.add_TopologyAttr('tempfactors')
        >>> hasattr(u.atoms[:3], 'tempfactors')
        True
        >>>
        >>> u.del_TopologyAttr('tempfactors')
        >>> hasattr(u.atoms[:3], 'tempfactors')
        False


        .. versionadded:: 2.0.0
        szGTopology attribute must be str or TopologyAttr object or class. Given: Nr  z"Unrecognised topology attribute: 'z'.  Possible values: 'zJ'
To raise an issue go to: https://github.com/MDAnalysis/mdanalysis/issueszTopology attribute z not in Universe.)r+   r  r:   r  btypers   typer   r  r  r  r;   rH   del_TopologyAttr_unprocess_attr)r   r  r5   r  topattrs        r0   r  zUniverse.del_TopologyAttrw  s   > ,,, 	  +4!      	  $0#5#;LL%      $7"&|"4"47 7   	   !L 
	/*<8ALL 	/ 	/ 	/IIf_5566EB\ B B',B B B  V$$$.	/	dnl;;GG 	 	 	HlHHH 	 	''000W%%%%%s<    
A&
5A&+A  A&%A&*A= =ACC" "Dc           
         | j         j        | j         j        | j         j        d}t                              d                    |                     |j        ft          |          ||j                 k    rHt          d                    |j
        |j        ||j                 t          |                              |j        D ]"}| j        |                             |           #t          t          t           t"          t$          t&          t(          fD ]1}|j        |         D ]!\  }}t-          | j        |         ||           "2|j        d         D ]\  }}t-          | j        ||           dS )zSqueeze a topologyattr for its information

        Grabs:
         - Group properties (attribute access)
         - Component properties
         - Transplant methods
        )atomresiduesegmentz%_process_attr: Adding {0} to topologyNzKLength of {attr} does not match number of {obj}s.
Expect: {n:d} Have: {m:d})r   objnmr   )rH   rM   rY   r]   r   r   ri   
per_objectrJ   rs   r:   r*   r   	_add_propr   r   r   r   r   r   r   transplantssetattrrA   )r   r   n_dictr   funcnamemeths         r0   r   zUniverse._process_attr  s    N*~0~0
 

 	<CCDIIJJJO'D		VDO444,,2FT_-$ii	 -3 - -	 	 	 & 	3 	3Cc",,T2222
 
 
	@ 
	@C #'"23"7 @ @$)#.$????@ #.z: 	4 	4NHdDNHd3333	4 	4r2   c                 J   |j         D ]"}| j        |                             |           #|j                            dg           D ]\  }}t          | j        |           |j                                        D ](\  }}|D ] \  }}t          | j        |         |           !)dS )z
        Undo all the stuff in _process_attr.

        If the topology attribute is not present, nothing happens
        (silent fail).
        r   N)r*   r   	_del_propr)  popdelattrrA   items)r   r   r   r,  _r)  s         r0   r  zUniverse._unprocess_attr  s     & 	3 	3Cc",,T2222  +//
B?? 	. 	.KHaDNH---- $ 0 6 6 8 8 	: 	:C* : :!)#.9999:	: 	:r2   c                    t          | j                  dk    r| j        d         }|t          d           | j        j        |fi |}t          t          j        | j        j                  |           | _	        | j	        |         S )a  Add a new Residue to this Universe

        New Residues will not contain any Atoms, but can be assigned to Atoms
        as per usual.  If the Universe contains multiple segments, this must
        be specified as a keyword.

        Parameters
        ----------
        segment: MDAnalysis.Segment
          If there are multiple segments, then the Segment that the new
          Residue will belong in must be specified.
        attrs: dict
          For each Residue attribute, the value for the new Residue must be
          specified

        Returns
        -------
        A reference to the new Residue

        Raises
        ------
        NoDataError
          If any information was missing.  This happens before any changes have
          been made, ie the change is rolled back.


        Example
        -------

        Adding a new GLY residue, then placing atoms within it:

        >>> import MDAnalysis as mda
        >>> from MDAnalysis.tests.datafiles import PSF, DCD
        >>> u = mda.Universe(PSF, DCD)
        >>> newres = u.add_Residue(segment=u.segments[0], resid=42, resname='GLY', resnum=0)
        >>> u.atoms[[1, 2, 3]].residues = newres
        >>> u.select_atoms('resname GLY and resid 42 and resnum 0')
        <AtomGroup with 3 atoms>

        r   r   N )
rJ   r   r   rH   add_Residuer   r   r   rY   r   )r   r#  r5   rU   s       r0   r6  zUniverse.add_Residue  s    R t}""mA&G?b//!++G==u==$Idn/00$
 

 }V$$r2   c                      | j         j        di |}t          t          j        | j         j                  |           | _        | j        |         S )a  Add a new Segment to this Universe

        Parameters
        ----------
        attrs: dict
            For each Segment attribute as a key, give the value in the new
            Segment

        Returns
        -------
        A reference to the new Segment

        Raises
        ------
        NoDataError
            If any attributes were not specified as a keyword.

        r)   )rH   add_Segmentr   r   r   r]   r   )r   r5   r[   s      r0   r8  zUniverse.add_Segment5  sR    ( ,+44e44$Idn/00$
 
 }V$$r2   c                    t          d |D                       r8	 d |D             }n# t          $ r d}Y nw xY wd |D             }d |D             }g }|D ]{}t          |t          t          f          rH|j        | ur$d}t          |                    |                    |                    |j	                   f|                    |           |t          d |D                       }	|	t          | j        j	                  z
  }
|
rMd                    t          t          |
                    }d	}t          |                    ||                    	 t          | j        |          }n;# t          $ r. |                     |g            t          | j        |          }Y nw xY w|                    ||||
           dS )a  Add new TopologyObjects to this Universe

        Parameters
        ----------
        object_type : {'bonds', 'angles', 'dihedrals', 'impropers'}
            The type of TopologyObject to add.
        values : TopologyGroup or iterable of tuples, AtomGroups, or TopologyObjects
            An iterable of: tuples of atom indices, or AtomGroups,
            or TopologyObjects. If every value is a TopologyObject, all
            keywords are ignored.
            If AtomGroups or TopologyObjects are passed, they *must* be from the same
            Universe.
        types : iterable (optional, default None)
            None, or an iterable of hashable values with the same length as ``values``
        guessed : bool or iterable (optional, default False)
            bool, or an iterable of hashable values with the same length as ``values``
        order : iterable (optional, default None)
            None, or an iterable of hashable values with the same length as ``values``


        .. versionadded:: 1.0.0
        c              3   @   K   | ]}t          |t                    V  d S r~   )r+   r$   )r-   xs     r0   	<genexpr>z1Universe._add_topology_objects.<locals>.<genexpr>j  s,      ==z!^,,======r2   c                     g | ]	}|j         
S r)   )r  r-   ts     r0   r1   z2Universe._add_topology_objects.<locals>.<listcomp>l  s    000A000r2   Nc                     g | ]	}|j         
S r)   )
is_guessedr>  s     r0   r1   z2Universe._add_topology_objects.<locals>.<listcomp>o  s    444q|444r2   c                     g | ]	}|j         
S r)   )r   r>  s     r0   r1   z2Universe._add_topology_objects.<locals>.<listcomp>p  s    ---QW---r2   z'Cannot add {} from different Universes.c                     g | ]	}|D ]}|
S r)   r)   )r-   r$  r   s      r0   r1   z2Universe._add_topology_objects.<locals>.<listcomp>|  s%    =====A1====r2   r  z.Cannot add {} for nonexistent atom indices: {}r   guessedr   )allr  r+   r   r$   r>   rs   ri   rL   indicessetr<   r  mapr  r;   rH   rN   
_add_bonds)r   object_typer  r   rE  r   rG  r;  err_msgall_indicesnonexistentistrr   s                r0   _add_topology_objectszUniverse._add_topology_objectsQ  s   2 ==f===== 	.00000!   44V444G--f---E 	" 	"A!i899 ":T))GG$W^^K%@%@AAAqy))))q!!!!=====>>!C
(:$;$;; 	@99Sk2233DFGW^^K>>???	84>;77DD 	8 	8 	8!!+r2224>;77DDD	8 	ugUKKKKKs   ( 77E- -5F%$F%c                 b    |                      d||||           |                                  dS )a0  Add new Bonds to this Universe.

        Parameters
        ----------
        values : iterable of tuples, AtomGroups, or Bonds; or TopologyGroup
            An iterable of: tuples of 2 atom indices, or AtomGroups with 2 atoms,
            or Bonds. If every value is a Bond, all
            keywords are ignored.
            If AtomGroups, Bonds, or a TopologyGroup are passed,
            they *must* be from the same Universe.
        types : iterable (optional, default None)
            None, or an iterable of hashable values with the same length as ``values``
        guessed : bool or iterable (optional, default False)
            bool, or an iterable of hashable values with the same length as ``values``
        order : iterable (optional, default None)
            None, or an iterable of hashable values with the same length as ``values``


        Example
        -------

        Adding TIP4P water bonds with a list of AtomGroups::

            import MDAnalysis as mda
            from MDAnalysis.tests.datafiles import GRO
            u = mda.Universe(GRO)
            sol = u.select_atoms('resname SOL')
            ow_hw1 = sol.select_atoms('name OW or name HW1').split('residue')
            ow_hw2 = sol.select_atoms('name OW or name HW2').split('residue')
            ow_mw = sol.select_atoms('name OW or name MW').split('residue')
            u.add_bonds(ow_hw1 + ow_hw2 + ow_mw)

        You can only add bonds from the same Universe. If you would like to add
        AtomGroups, Bonds, or a TopologyGroup from a different Universe, convert
        them to indices first. ::

            from MDAnalysis.tests.datafiles import PSF
            u2 = mda.Universe(PSF)

            #  assuming you have already added bonds to u
            u2.add_bonds(u.bonds.to_indices())


        .. versionadded:: 1.0.0
        r   rD  N)rP  _invalidate_bond_related_caches)r   r  r   rE  r   s        r0   	add_bondszUniverse.add_bonds  sG    \ 	""V5' 	# 	
 	
 	
 	,,.....r2   c                     | j                             dd           | j         d                             dd           | j         d                             dd           dS )z
        Invalidate caches related to bonds and fragments.

        This should be called whenever the Universe's bonds are modified.

        .. versionadded: 2.8.0
        	fragmentsNr   fragindices)r   r0  r   s    r0   rR  z(Universe._invalidate_bond_related_caches  sZ     	T***H!!+t444H!!-66666r2   c                 8    |                      d|||           dS )a  Add new Angles to this Universe.

        Parameters
        ----------
        values : iterable of tuples, AtomGroups, or Angles; or TopologyGroup
            An iterable of: tuples of 3 atom indices, or AtomGroups with 3 atoms,
            or Angles. If every value is a Angle, all
            keywords are ignored.
            If AtomGroups, Angles, or a TopologyGroup are passed,
            they *must* be from the same Universe.
        types : iterable (optional, default None)
            None, or an iterable of hashable values with the same length as ``values``
        guessed : bool or iterable (optional, default False)
            bool, or an iterable of hashable values with the same length as ``values``

        .. versionadded:: 1.0.0
        r   r   rE  NrP  r   r  r   rE  s       r0   
add_angleszUniverse.add_angles  s4    $ 	""fE7 	# 	
 	
 	
 	
 	
r2   c                 8    |                      d|||           dS )a
  Add new Dihedrals to this Universe.

        Parameters
        ----------
        values : iterable of tuples, AtomGroups, or Dihedrals; or TopologyGroup
            An iterable of: tuples of 4 atom indices, or AtomGroups with 4 atoms,
            or Dihedrals. If every value is a Dihedral, all
            keywords are ignored.
            If AtomGroups, Dihedrals, or a TopologyGroup are passed,
            they *must* be from the same Universe.
        types : iterable (optional, default None)
            None, or an iterable of hashable values with the same length as ``values``
        guessed : bool or iterable (optional, default False)
            bool, or an iterable of hashable values with the same length as ``values``


        .. versionadded:: 1.0.0
        r   rX  NrY  rZ  s       r0   add_dihedralszUniverse.add_dihedrals  4    & 	""ug 	# 	
 	
 	
 	
 	
r2   c                 8    |                      d|||           dS )a  Add new Impropers to this Universe.

        Parameters
        ----------
        values : iterable of tuples, AtomGroups, or Impropers; or TopologyGroup
            An iterable of: tuples of 4 atom indices, or AtomGroups with 4 atoms,
            or Impropers. If every value is an Improper, all
            keywords are ignored.
            If AtomGroups, Impropers, or a TopologyGroup are passed,
            they *must* be from the same Universe.
        types : iterable (optional, default None)
            None, or an iterable of hashable values with the same length as ``values``
        guessed : bool or iterable (optional, default False)
            bool, or an iterable of hashable values with the same length as ``values``


        .. versionadded:: 1.0.0
        r   rX  NrY  rZ  s       r0   add_improperszUniverse.add_impropers  r^  r2   c                    g }|D ]{}t          |t          t          f          rH|j        | ur$d}t	          |                    |                    |                    |j                   f|                    |           |	 t          | j	        |          }n0# t          $ r# t	          d                    |                    w xY w|                    |           dS )a'  Delete TopologyObjects from this Universe

        Parameters
        ----------
        object_type : {'bonds', 'angles', 'dihedrals', 'impropers'}
            The type of TopologyObject to delete.
        values : iterable of tuples, AtomGroups, or TopologyObjects; or TopologyGroup
            An iterable of: tuples of atom indices, or AtomGroups,
            or TopologyObjects.
            If AtomGroups, TopologyObjects, or a TopologyGroup are passed,
            they *must* be from the same Universe.

        .. versionadded:: 1.0.0
        z*Cannot delete {} from different Universes.zThere are no {} to deleteN)r+   r   r$   r>   rs   ri   rL   rG  r;   rH   r  _delete_bonds)r   rK  r  rG  r;  rL  r   s          r0   _delete_topology_objectsz!Universe._delete_topology_objects  s      	" 	"A!i899 ":T))JG$W^^K%@%@AAAqy))))q!!!!	N4>;77DD 	N 	N 	N8??LLMMM	N7#####s   B -Cc                 Z    |                      d|           |                                  dS )a&  Delete Bonds from this Universe.

        Parameters
        ----------
        values : iterable of tuples, AtomGroups, or Bonds; or TopologyGroup
            An iterable of: tuples of 2 atom indices, or AtomGroups with 2 atoms,
            or Bonds.
            If AtomGroups, Bonds, or a TopologyGroup are passed,
            they *must* be from the same Universe.


        Example
        -------

        Deleting bonds from a Universe::

            import MDAnalysis as mda
            from MDAnalysis.tests.datafiles import PSF
            u = mda.Universe(PSF)

            #  delete first 5 bonds
            u.delete_bonds(u.bonds[:5])


        If you are deleting bonds in the form of AtomGroups, Bonds, or a
        TopologyGroup, they must come from the same Universe. If you want to
        delete bonds from another Universe, convert them to indices first. ::

            from MDAnalysis.tests.datafiles import PDB
            u2 = mda.Universe(PDB)

            u.delete_bonds(u2.bonds.to_indices())


        .. versionadded:: 1.0.0
        r   N)rc  rR  r   r  s     r0   delete_bondszUniverse.delete_bonds.  s3    J 	%%gv666,,.....r2   c                 2    |                      d|           dS )a  Delete Angles from this Universe.

        Parameters
        ----------
        values : iterable of tuples, AtomGroups, or Angles; or TopologyGroup
            An iterable of: tuples of 3 atom indices, or AtomGroups with 3 atoms,
            or Angles.
            If AtomGroups, Angles, or a TopologyGroup are passed,
            they *must* be from the same Universe.


        .. versionadded:: 1.0.0
        r   Nrc  re  s     r0   delete_angleszUniverse.delete_anglesV  s      	%%h77777r2   c                 2    |                      d|           dS )a  Delete Dihedrals from this Universe.

        Parameters
        ----------
        values : iterable of tuples, AtomGroups, or Dihedrals; or TopologyGroup
            An iterable of: tuples of 4 atom indices, or AtomGroups with 4 atoms,
            or Dihedrals.
            If AtomGroups, Dihedrals, or a TopologyGroup are passed,
            they *must* be from the same Universe.


        .. versionadded:: 1.0.0
        r   Nrh  re  s     r0   delete_dihedralszUniverse.delete_dihedralsf        	%%k6:::::r2   c                 2    |                      d|           dS )a  Delete Impropers from this Universe.

        Parameters
        ----------
        values : iterable of tuples, AtomGroups, or Impropers; or TopologyGroup
            An iterable of: tuples of 4 atom indices, or AtomGroups with 4 atoms,
            or Impropers.
            If AtomGroups, Angles, or a TopologyGroup are passed,
            they *must* be from the same Universe.


        .. versionadded:: 1.0.0
        r   Nrh  re  s     r0   delete_improperszUniverse.delete_impropersv  rl  r2   rU  c                 <     j         j        } j         j                                        }t	          ||          }t           fd|D                       }i }t          j        dd          }t          |          D ]\  }}|D ]}	 |||          ||	j        <   |S )a   
        .. versionadded:: 0.9.0
        .. versionchanged:: 0.16.0
           Fragment atoms are sorted by their index, and framgents are sorted
           by their first atom index so their order is predictable.
        .. versionchanged:: 0.19.0
           Uses faster C++ implementation
        .. versionchanged:: 0.20.0
           * _fragdict keys are now atom indices instead of Atoms
           * _fragdict items are now a namedtuple ``fraginfo(ix, fragment)``
             storing the fragindex ``ix`` along with the fragment.
        c                 T    g | ]$}t          t          j        |                    %S r)   )r   r   sort)r-   ixr   s     r0   r1   z&Universe._fragdict.<locals>.<listcomp>  s+    KKKyd33KKKr2   fraginfozix, fragment)	r<   rr  r   
to_indicesr   tuplecollections
namedtuplerI   )
r   r<   r   frag_indicesfragsfragdictrs  r   fas
   `         r0   	_fragdictzUniverse._fragdict  s     

 ++--%eU33KKKKlKKKLL)*nEEe$$ 	0 	0DAq 0 0!)!Q0 r2   Tc                 
   |i }	 ddl m} ddlm}	 n"# t          $ r}
t	          d          |
d}
~
ww xY w|                    ||          }|"t          d                    |                    |r|                    |          }|rs|st          d          |
                    d	|          }t          |t                    r|dk    s"t          d
                    |                     |	j        ||fi |  | |fi |S )a  Create a Universe from a SMILES string with rdkit

        Parameters
        ----------
        smiles : str
            SMILES string
        sanitize : bool (optional, default True)
            Toggle the sanitization of the molecule
        addHs : bool (optional, default True)
            Add all necessary hydrogens to the molecule
        generate_coordinates : bool (optional, default True)
            Generate 3D coordinates using RDKit's
            :func:`AllChem.EmbedMultipleConfs` function. Requires adding
            hydrogens with the `addHs` parameter
        numConfs : int (optional, default 1)
            Number of frames to generate coordinates for. Ignored if
            ``generate_coordinates=False``
        rdkit_kwargs : dict (optional)
            Other arguments passed to the RDKit :func:`EmbedMultipleConfs`
            function
        kwargs : dict
            Parameters passed on Universe creation

        Returns
        -------
        universe : Universe
            contains atom names and topology information (bonds) derived from
            the input SMILES string; coordinates are included if
            `generate_coordinates` was set to ``True``


        Examples
        --------
        To create a Universe with 10 conformers of ethanol:

        >>> from rdkit.Chem import AllChem
        >>> u = mda.Universe.from_smiles('CCO', numConfs=10)
        >>> u
        <Universe with 9 atoms>
        >>> u.trajectory
        <RDKitReader with 10 frames of 9 atoms>

        To use a different conformer generation algorithm, like ETKDGv3:

        >>> u = mda.Universe.from_smiles('CCO', rdkit_kwargs=dict(
        ...      params=AllChem.ETKDGv3()))
        >>> u.trajectory
        <RDKitReader with 1 frames of 9 atoms>


        .. versionadded:: 2.0.0

        Nr   )Chem)AllChemz^Creating a Universe from a SMILES string requires RDKit but it does not appear to be installed)sanitizezError while parsing SMILES {0}zBGenerating coordinates requires adding hydrogens with `addHs=True`numConfsz;numConfs must be a non-zero positive integer instead of {0})rdkitr  
rdkit.Chemr  ImportErrorMolFromSmilesSyntaxErrorri   AddHsrs   r0  r+   intEmbedMultipleConfs)r   smilesr  addHsgenerate_coordinatesr  rdkit_kwargsrw   r  r  emols               r0   from_smileszUniverse.from_smiles  s~   @ L	""""""******* 	 	 	5  	   ( ;;;>EEfMMNNN 	"**S//C 	F  2  
 $''
H==Hx-- (Q,,!--3VH-=-=   'G&sHEEEEEs3!!&!!!s    
2-2c                    |s| j         }i }|                    | j                   |                    |           t          || j        fi |}|| _         |g }|g }t          |          t          |          z   }t          t                              |                    }t          d t          j
                    D                       }	| j        j        dk    rd | j        j        D             }
t          |          t          |
          z  }d                    d |D                       }t          |          dk    rt                               d| d           |D ]L}|                    |          r!||v }	 |                    ||          }n># t(          $ r1}|s|r|t+          j        t/          |                     Y d}~kd}~ww xY w|v||	v ru|r@t1          | j        |          r+t5          | j        |          }|                     ||           |                     ||d	
           |dk    r|                                  n+t          |         |d	          }|                     |           t                               d| d           :t?          | d|           dS t+          j        d           dS )ai  
        Guess and add attributes through a specific context-aware guesser.

        Parameters
        ----------
        context: str or :mod:`Guesser<MDAanalysis.guesser>` class
            For calling a matching guesser class for this specific context
        to_guess: Optional[list[str]]
            TopologyAttrs to be guessed. These TopologyAttrs will be wholly
            guessed if they don't exist in the Universe. If they already exist in
            the Universe, only empty or missing values will be guessed.

            .. warning::
                In MDAnalysis 2.x, types and masses are being automatically guessed
                if they are missing (``to_guess=('types, 'masses')``).
                However, starting with release 3.0 **no guessing will be done
                by default** and it will be up to the user to request guessing
                using ``to_guess`` and ``force_guess``.

        force_guess: Optional[list[str]]
            TopologyAttrs in this list will be force guessed. If the
            TopologyAttr does not already exist in the Universe, this has no
            effect. If the TopologyAttr does already exist, all values will
            be overwritten by guessed values.
        error_if_missing: bool
            If `True`, raise an error if the guesser cannot guess the attribute
            due to missing TopologyAttrs used as the inputs for guessing.
            If `False`, a warning will be raised instead.
            Errors will always be raised if an attribute is in the
            ``force_guess`` list, even if this parameter is set to False.

        **kwargs: extra arguments to be passed to the guesser class

        Examples
        --------
        To guess ``masses`` and ``types`` attributes::

            u.guess_TopologyAttrs(context='default', to_guess=['masses', 'types'])

        .. versionadded:: 2.8.0

        Nc              3   N   K   | ] }t          |t                    |j        V  !d S r~   )
issubclassr#   r:   )r-   r  s     r0   r<  z/Universe.guess_TopologyAttrs.<locals>.<genexpr>W  sI       
 
';//

 
 
 
 
 
r2   r   c                     g | ]	}|j         
S r)   )r:   )r-   atts     r0   r1   z0Universe.guess_TopologyAttrs.<locals>.<listcomp>a  s'       !$  r2   r  c              3      K   | ]}|V  d S r~   r)   )r-   r   s     r0   r<  z/Universe.guess_TopologyAttrs.<locals>.<genexpr>f  s"      $C$CdT$C$C$C$C$C$Cr2   zThe attribute(s) z have already been read from the topology file. The guesser will only guess empty values for this attribute, if any exists. To overwrite it by completely guessed values, you can pass the attribute to the force_guess parameter instead of the to_guess oneT)rE  r   z
attribute z has been guessed successfully.z0 guesser can not guess the following attribute: z2Can not guess attributes for universe with 0 atoms) r   r   r   r%   r>   r   dictfromkeysrH  r   r  rH   rM   read_attributesr  rJ   r   infois_guessable
guess_attrr   r   r   r  rc   r<   r;   rc  rP  rR  rN   rs   )r   r   r   r   r   rw   guesser_kwargsguessertotal_guessobjectstopology_attrscommon_attrsr   fgr  r  groupguessed_attrs                     r0   r   zUniverse.guess_TopologyAttrs  so   d  	$mG dl+++f%%%gt}GGGGHK8nntK'8'88
 4==5566  
 
*133
 
 
 
 
 >!A%% (,(F  N x==3~+>+>>L99$C$Cl$C$C$CCCL<  1$$' ' ' '   $ # #''-- ",B%!(!3!3D"!=!=& % % %+ %r %"#G$M#a&&111$HHHH% ~ w G'$*d";"; G$+DJ$=$=E 99$FFF2242NNN7?? @@BBB'6t'<VT'J'J--l;;;KKMTMMM   
 %" 8 8158 8  A# #L MG    s   F
G$'GGc                    ||t          j        d           dS || j        j        }nWt	          |          | j        j        k    rt          d          | j        j        | _        t          	                    d           || j        j
        }nWt	          |          | j        j        k    rt          d          | j        j
        | _        t          	                    d           t          j        |t                    }t          j        |t                    }t!          | ||           t#          |            dS )	ab  Set the groups (`ResidueGroup`, `SegmentGroup`) of the Universe
        by atomwise resids/segids.

        The `topology` will also be updated based on the provided `atomwise_resids`
        and `atomwise_segids`. The original `resids` and `segids` will be stored
        in attributes `atomwise_resids_orig` and/or `atomwise_segids_orig` if
        they are modified.
        See notes for the logic of the function.

        Parameters
        ----------
        atomwise_resids:
            A list of residue IDs to be set for the Universe. The length
            of the list should be equal to the number of atoms in the Universe.
            If `None`, the original resids will be used.

        atomwise_segids:
            A list of segment IDs to be set for the Universe. The length
            of the list should be equal to the number of atoms in the Universe.
            If `None`, the original segids will be used.

        Raises
        ------
        AssertionError
            If the length of the provided atomwise_resids or atomwise_segids
            does not match the number of atoms in the Universe.

        Notes
        -----
        First, the function will check if resids or segids is provided.
        If both resids and segids are not provided (`None`), it will do nothing.
        If only one of them is provided, it will use the original values for the
        other one. If both are provided, it will use the provided values for
        both resids and segids.
        The function will then update the topology by a new generated topology
        with new values of the resids and segids.
        Finally, the corresponding new `ResidueGroup` and `SegmentGroup` will be
        created by the updated topology.

        Examples
        --------
        To set custom segment IDs for the segments of the Universe::

            atomwise_segids = ['A', 'A', 'B', 'B']
            u.set_groups(atomwise_segids=atomwise_segids)

            # Now the Universe has two segments with segIDs 'A' and 'B'
            u.segments
            >>> <SegmentGroup with 2 segments>

        .. versionadded:: 2.10.0
        NzFNot setting groups. Please provide atomwise_resids or atomwise_segids.zXThe length of atomwise_resids should be the same as the number of atoms in the universe.z_The new resids replaces the current one. The original resids is stored in atomwise_resids_orig.zXThe length of atomwise_segids should be the same as the number of atoms in the universe.z_The new resids replaces the current one. The original segids is stored in atomwise_segids_orig.r   )rO   rP   )r   r   r<   rW   rJ   rM   rs   atomwise_resids_origr   r  r\   atomwise_segids_origr   arrayr  objectr`   r   )r   rO   rP   s      r0   
set_groupszUniverse.set_groups  sn   j #/*AM#   F ""j/OO ?##tz'999 ;  
 )-
(9D%KK(   ""j/OO ?##tz'999 ;  
 )-
(9D%KK(   (?#>>>(?&AAA++	
 	
 	
 	

 	 %%%%%r2   r~   )r   r   r   NNFFF)NFr   )NNNF)NFN)NF)TTTr   N)NNNT)NN)/__name__
__module____qualname____doc__r   r   classmethodr   propertyr>   r   r   r   r   r   r   r   r   r   r   r   setterr  rw   r   rN   r  r   r  r6  r8  rP  rS  rR  r[  r]  r`  rc  rf  ri  rk  rn  r	   r}  r  r   r  r)   r2   r0   r   r   3  sb       T Tp k
 $!k
 k
 k
 k
 k
Z    r r r [rh   X g g g gT 9>I I I I^8 8 8     X  ! ! X! $ $ X$ $ $ X$
 
 
   [
 
 
 % % X% $ $ $ " " X"& + + X+ G G XG ! ! !@) @) @) @)DB& B& B&H/4 /4 /4b: : :$5% 5% 5% 5%n% % %: EI8L 8L 8L 8Lt1/ 1/ 1/ 1/f7 7 7
 
 
 
,
 
 
 
.
 
 
 
.$ $ $>&/ &/ &/P8 8 8 ; ; ; ; ; ;2 VK   X6  !^" ^" ^" [^"D N N N N`j& j& j& j& j& j&r2   r   c            	         ! ddl m} t          |           dk    rt          d          | D ];}t	          |t
          j                  st          t          |          dz             <| D ]$}t          |          dk    rt          d          %t          t          t          g                               }t          j        d | D              }t          g d	          }g }||z
  |z
  }|D ]v}| D ]7}	t          |	|          }
t          t          |	j        j        |                    }t#          |t$                    rnet#          |t&                    rt          |	j        |          }
n:t#          |t*                    rt          |	j        |          }
nt/          d
          t          |
          t0          j        k    r/t          d                    t          |
                              	 |                    |
           # t8          $ r t;          |
          }Y 5w xY w|                     |t1          j        ||
j                                        ~x||z  D ]p}d}g }g }| D ]}	d tC          |	|          D             |t          |	          z  }t          |	|          }t          t          |	j        j        |                    }|"                    |	d          }fd|j#        D             }|                    |           tI          |d          r|                    |j%                   |                    dgt          |          z             tM          d |D                       r |                     ||                     ;t1          j        |d          }|                     |||                     rtO          d | D                       }g }g }d}d}| D ]}	d tC          |	j        |          D              d tC          |	j        |          D             !|t          |	j                  z  }|t          |	j                  z  }|                     fd|	j(        D                        |                    !fd|	j)        D                        t1          j        |t0          j*                  }t1          j        |t0          j*                  } |||          \  }}\  }t          t          |                    }t          t          |                    }t          ||||||          }	 t1          j+        d | D                       }tY          ||dddddf         tZ          j.        j/        j0                  }n# tb          $ r tY          |          }Y nw xY w|S )a  Create a new new :class:`Universe` from one or more
    :class:`~MDAnalysis.core.groups.AtomGroup` instances.

    Parameters
    ----------
    *args: :class:`~MDAnalysis.core.groups.AtomGroup`
        One or more AtomGroups.

    Returns
    -------
    universe: :class:`Universe`

    Raises
    ------
    ValueError
        Too few arguments or an AtomGroup is empty and
    TypeError
        Arguments are not :class:`AtomGroup` instances.

    Notes
    -----
    The resulting :class:`Universe` will only inherit the common topology
    attributes that all merged universes share.

    :class:`AtomGroup` instances can come from different Universes, or can come
    directly from a :meth:`~Universe.select_atoms` call.

    :class:`Merge` can also be used with a single :class:`AtomGroup` if the
    user wants to, for example, re-order the atoms in the :class:`Universe`.

    If multiple :class:`AtomGroup` instances from the same :class:`Universe`
    are given, the merge will first simply "add" together the
    :class:`AtomGroup` instances.

    Merging does not create a full trajectory but only a single structure even
    if the input consists of one or more trajectories.  However, one can use
    the :class:`~MDAnalysis.coordinates.memory.MemoryReader` to construct a
    trajectory for the new Universe as described under
    :ref:`creating-in-memory-trajectory-label`.

    Example
    -------
    In this example, protein, ligand, and solvent were externally prepared in
    three different PDB files. They are loaded into separate :class:`Universe`
    objects (where they could be further manipulated, e.g. renumbered,
    relabeled, rotated, ...) The :func:`Merge` command is used to combine all
    of them together::

       u1 = Universe("protein.pdb")
       u2 = Universe("ligand.pdb")
       u3 = Universe("solvent.pdb")
       u = Merge(u1.select_atoms("protein"), u2.atoms, u3.atoms)
       u.atoms.write("system.pdb")

    The complete system is then written out to a new PDB file.


    .. versionchanged:: 0.9.0
       Raises exceptions instead of assertion errors.

    .. versionchanged:: 0.16.0
       The trajectory is now a
       :class:`~MDAnalysis.coordinates.memory.MemoryReader`.

    r   )	squash_byr   z'Need at least one AtomGroup for mergingz is not an AtomGroupzcannot merge empty AtomGroupr4   c                 Z    g | ](}t          t          |j        j                            )S r)   )rH  dirr>   rH   r-   ags     r0   r1   zMerge.<locals>.<listcomp>[  s-    	9	9	9b#c"+'((
)
)	9	9	9r2   )r   r   r   r   z`Don't know how to handle TopologyAttr not subclassed from AtomAttr, ResidueAttr, or SegmentAttr.z4Encountered unexpected topology attribute of type {}r   c                 $    i | ]\  }}|j         |S r)   )index)r-   r   r|  s      r0   
<dictcomp>zMerge.<locals>.<dictcomp>  s     JJJdaqwJJJr2   )r   T)strictc                 F    g | ]}t          fd |D                       S )c                      g | ]
}|         S r)   r)   )r-   r;  mappings     r0   r1   z$Merge.<locals>.<listcomp>.<listcomp>  s    111awqz111r2   )ru  )r-   entryr  s     r0   r1   zMerge.<locals>.<listcomp>  sC       7<1111511122  r2   
_bondtypesNc              3      K   | ]}|d u V  	d S r~   r)   r>  s     r0   r<  zMerge.<locals>.<genexpr>  s&      ((QqDy((((((r2   z|S8c                 ,    g | ]}t          |          S r)   )rJ   r  s     r0   r1   zMerge.<locals>.<listcomp>  s    ***r3r77***r2   c                 $    i | ]\  }}|j         |S r)   )resindexr-   r   rs      r0   r  zMerge.<locals>.<dictcomp>  -     
 
 
"aAJ
 
 
r2   c                 $    i | ]\  }}|j         |S r)   )segindexr  s      r0   r  zMerge.<locals>.<dictcomp>  r  r2   c                      g | ]
}|         S r)   r)   )r-   r;  res_mappings     r0   r1   zMerge.<locals>.<listcomp>      ===!{1~===r2   c                      g | ]
}|         S r)   r)   )r-   r;  seg_mappings     r0   r1   zMerge.<locals>.<listcomp>  r  r2   rD   c                     g | ]	}|j         
S r)   )r   )r-   r|  s     r0   r1   zMerge.<locals>.<listcomp>  s    666AAK666r2   rh   )2rG   r  rJ   rs   r+   r   r   r   reprrH  r  r   intersectionr;   r  r>   rH   r  r   r   r   r   r   rt   r   ndarrayri   rK   	NameErrorr   rL   r  r   rI   atomgroup_intersectionrG  rc   r  anysum
resindices
segindicesint32vstackr   
MDAnalysisr   memoryr   r  )"r   r  r|  blank_topology_attrsr  topsr5   common_array_attrsr:   r  r   
attr_class
attr_arrayr?  offsetbondidxr   tgbonds_classnew_idxrM   rU   r[   
res_offset
seg_offsetr3  rY   r]   r6   r   r   r  r  r  s"                                  @@@r0   Merger  
  su   D *)))))
4yyA~~BCCC > >!V-.. 	>DGG&<<===	> = =q66Q;;;<<<  s8"#5#5#56677#	9	9D	9	9	9L <<<==DE &(<<tC '   	( 	(B2x((Dgbk&;XFFGGJ*h// J44 
r{H55J44 r{H55)'   DzzRZ''++16$t**+=+=  (!!$'''' ( ( (!$ZZ


(ZZ4: F F FGGHHHJ L  6 6 	/ 	/BJJi&.I.I.IJJJGc"ggFQBwr{'<a@@AAK **2d*;;B   @B
  G NN7###r<(( /R]++++dVc"gg-....((%((((( 	6LLW--....HU%000ELLWe445555 **T***++GFFJJ ? ?
 
&/:&N&N&N
 
 

 
&/:&N&N&N
 
 
 	c"+&&&
c"+&&&
 	====r}===>>>====r}===>>>>XfBH---FXfBH---FYvv..NAq(6S[[!!JS[[!!J
  C
66666774AAA:)0=
 
 

    SMM Hs%   7HH+*H+AV1 1WWr~   )Dr  ro   numpyr   loggingr   r   
contextlibrv  r  rq   osuuidr5  r   r   
exceptionsr   libr   lib.logr   lib.utilr	   r
   r   lib.mdamathr   r   _get_readersr   r   r   r   r   r   r   r   r   r   rd   r   topologyattrsr   r   r   r   r   r   r    r!   r"   r#   topologyobjectsr$   guesser.baser%   	getLoggerr   r`   rf   r{   r   r   r   r  r   r  r)   r2   r0   <module>r     s+  0 @                     



 
			  ( ( ( ( ( ( ( ( $ $ $ $ $ $       ! ! ! ! ! ! 4 4 4 4 4 4 4 4 4 4 ( ( ( ( ( (       8 8 8 8 8 8 8 8	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	                              , + + + + + & & & & & &		5	6	6c c cL     @ +/ # # # # # $(       4T& T& T& T& T&v T& T& T&n6L L L L Lr2   