
     i%D                         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 ej        d          Z	ddl
mZ ddlmZ ddlmZ dd	lmZmZ dd
lmZ ddlmZ  G d dej                  Z G d dej                  ZdS )a  XYZ trajectory reader --- :mod:`MDAnalysis.coordinates.XYZ`
==============================================================

The :ref:`XYZ format <xyz-format>` is a loosely defined, simple
coordinate trajectory format. The implemented format definition was
taken from the `VMD xyzplugin`_ and is therefore compatible with VMD.

Note the following:

* Comments are not allowed in the XYZ file (we neither read nor write
  them to remain compatible with VMD).
* The atom name (first column) is ignored during reading.
* The coordinates are assumed to be space-delimited rather than fixed
  width (this may cause issues - see below).
* All fields to the right of the z-coordinate are ignored.
* The unitcell information is all zeros since this is not recorded in
  the XYZ format.

.. rubric:: Units

* Coordinates are in Angstroms.
* The length of a timestep can be set by passing the *dt* argument,
  it's assumed to be in ps (default: 1 ps).

There appears to be no rigid format definition so it is likely users
will need to tweak this class.

.. _xyz-format:

XYZ File format
---------------

Definition used by the :class:`XYZReader` and :class:`XYZWriter` (and
the `VMD xyzplugin`_ from whence the definition was taken)::

    [ comment line            ] !! NOT IMPLEMENTED !! DO NOT INCLUDE
    [ N                       ] # of atoms, required by this xyz reader plugin  line 1
    [ molecule name           ] name of molecule (can be blank)                 line 2
    atom1 x y z [optional data] atom name followed by xyz coords                line 3
    atom2 x y z [ ...         ] and (optionally) other data.
    ...
    atomN x y z [ ...         ]                                                 line N+2


Note
----
* comment lines not implemented (do not include them)
* molecule name: the line is required but the content is ignored
  at the moment
* optional data (after the coordinates) are presently ignored


.. Links
.. _`VMD xyzplugin`: http://www.ks.uiuc.edu/Research/vmd/plugins/molfile/xyzplugin.html

Classes
-------

    NzMDAnalysis.coordinates.XYZ   )base)Timestep   )util)cachedstore_init_arguments)NoDataError)__version__c                   N    e Zd ZdZdZdZdddZ	 	 	 	 dd	Zd
 Zd Z	d Z
ddZdS )	XYZWritera  Writes an XYZ file

    The XYZ file format is not formally defined. This writer follows
    the VMD implementation for the molfile `xyzplugin`_.


    Notes
    -----
    By default, the XYZ writer will attempt to use the input
    :class:`~MDAnalysis.core.groups.AtomGroup` or
    :class:`~MDAnalysis.core.universe.Universe` ``elements`` record to assign
    atom names in the XYZ file. If the ``elements`` record is missing, then
    the ``name`` record will be used. In the event that neither of these are
    available, the atoms will all be named ``X``. Please see, the
    `User Guide`_ for more information on how to add topology attributes if
    you wish to add your own elements / atom names to a
    :class:`~MDAnalysis.core.universe.Universe`.


    .. Links

    .. _xyzplugin:
           http://www.ks.uiuc.edu/Research/vmd/plugins/molfile/xyzplugin.html
    .. _User Guide:
           https://userguide.mdanalysis.org/examples/constructing_universe.html#Adding-topology-attributes


    .. versionchanged:: 1.0.0
       Use elements attribute instead of names attribute, if present.
    .. versionchanged:: 2.0.0
       Support for passing timestep to the writer was deprecated in 1.0 and
       has now been removed. As a consequence, custom names can no longer be
       passed to the writer, these should be added to the
       :class:`~MDAnalysis.core.universe.Universe`, or
       :class:`~MDAnalysis.core.groups.AtomGroup` before invoking the writer.
    XYZTpsAngstromtimelengthN   c                     || _         || _        || _        || _        || _        t          j        | j         d          | _        dS )a  Initialize the XYZ trajectory writer

        Parameters
        ----------
        filename: str
            filename of trajectory file. If it ends with "gz" then the file
            will be gzip-compressed; if it ends with "bz2" it will be bzip2
            compressed.
        n_atoms: int (optional)
            Number of atoms in trajectory. By default assume that this is None
            and that this file is used to store several different models
            instead of a single trajectory. If a number is provided each
            written TimeStep has to contain the same number of atoms.
        convert_units : bool (optional)
            convert quantities to default MDAnalysis units of Angstrom upon
            writing  [``True``]
        remark: str (optional)
            single line of text ("molecule name"). By default writes MDAnalysis
            version and frame
        precision: int (optional)
            set precision of saved trjactory to this number of decimal places.

            .. versionadded:: 2.9.0


        .. versionchanged:: 1.0.0
           Removed :code:`default_remark` variable (Issue #2692).
        .. versionchanged:: 2.0.0
           Due to the removal of timestep as an input for writing, the atoms
           parameter is no longer relevant and has been removed. If passing
           an empty universe, please use ``add_TopologyAttr`` to add in the
           required elements or names.
        wtN)filenameremarkn_atomsconvert_units	precisionr   anyopen_xyz)selfr   r   r   r   r   kwargss          d/srv/www/vhosts/g4struct/public_html/venv/lib/python3.11/site-packages/MDAnalysis/coordinates/XYZ.py__init__zXYZWriter.__init__   sD    T !*" L55			    c                     	 |j         j        S # t          t          f$ rS 	 |j         j        cY S # t          t          f$ r/ d}t          j        |           t          j        d          cY cY S w xY ww xY w)zEReturn a list of atom elements (if present) or fallback to atom nameszrInput AtomGroup or Universe does not have atom elements or names attributes, writer will default atom names to 'X')X)	atomselementsAttributeErrorr
   nameswarningswarn	itertoolscycle)r   r%   wmsgs      r    _get_atoms_elements_or_namesz&XYZWriter._get_atoms_elements_or_names   s    	/;'', 
	/ 
	/ 
	/	/{(((("K0 / / /( 
 d### v......./
	/s)    A2.A2;A.)A2-A..A2c                     | j         3| j                             d           | j                                          d| _         dS )z2Close the trajectory file and finalize the writingN
)r   writecloser   s    r    r2   zXYZWriter.close   s;    9 IOOD!!!IOO			r"   c                    	 |j         }t          |d          r?|j        j        j        }|j        |j        k    r|}n7|                    |j                  }nt          |d          r|j        j        }|                     |          | _	        n # t          $ r d}t          |          dw xY w|                     |           dS )ak  Write object `obj` at current trajectory frame to file.

        Atom elements (or names) in the output are taken from the `obj` or
        default to the value of the `atoms` keyword supplied to the
        :class:`XYZWriter` constructor.

        Parameters
        ----------
        obj : Universe or AtomGroup
            The :class:`~MDAnalysis.core.groups.AtomGroup` or
            :class:`~MDAnalysis.core.universe.Universe` to write.


        .. versionchanged:: 2.0.0
           Deprecated support for Timestep argument has now been removed.
           Use AtomGroup or Universe as an input instead.
        universe
trajectoryz-Input obj is neither an AtomGroup or UniverseN)r%   hasattrr5   r6   tsr   
copy_sliceindicesr.   	atomnamesr'   	TypeError_write_next_frame)r   objr%   ts_fullr8   errmsgs         r    r1   zXYZWriter.write   s    ,	FIE
 sJ'' 
',14?em33 BB !++EM::BBl++ '^&!>>uEEDNN!  	. 	. 	.DFF##-	.$ 	r"""""s   B B,c           
         |&t          | d          st          d          | j        }| j        >| j        |j        k    r-t	          d                    |j        | j                            nt          | j        t          j	                  st          | j                  |j        k    rrt                              d                    t          | j                  |j                             t          j        | j        d         g|j        z            | _        | j        r|                     |j        d          }n|j        }| j                            d	                    |j                             | j        Fd
                    |j        | j        j        t0                    }| j                            |           n4| j                            | j                                        dz              t5          | j        |          D ]@\  }\  }}}| j                            d                    ||||| j                             AdS )a  
        Write coordinate information in *ts* to the trajectory

        .. versionchanged:: 1.0.0
           Print out :code:`remark` if present, otherwise use generic one
           (Issue #2692).
           Renamed from `write_next_timestep` to `_write_next_frame`.
        Nr8   z9XYZWriter: no coordinate data to write to trajectory filezn_atoms keyword was specified indicating that this should be a trajectory of the same model. But the provided TimeStep has a different number ({}) then expected ({})zTrying to write a TimeStep with unknown atoms. Expected {} atoms, got {}. Try using "write" if you are using "_write_next_frame" directlyr   F)inplacez{0:d}
z1frame {} | Written by MDAnalysis {} (release {})
r0   z.{0!s:>8}  {1:10.{p}f} {2:10.{p}f} {3:10.{p}f}
)p)r7   r
   r8   r   
ValueErrorformat
isinstancer;   r+   r,   lenloggerinfonparrayr   convert_pos_to_native	positionsr   r1   r   frame	__class____name__r   stripzipr   )r   r8   coordinatesr   atomxyzs           r    r=   zXYZWriter._write_next_frame  sK    :4&& !&  
 W<#|rz))  vbj$,77   * t~y??L''2:5599?DN++RZ: :   "$4>!+<*=
*J!K!K 	'44e 5  KK ,K 			((44555 ;DKKHdn5{   IOOF####IOODK--//$6777  #4>;?? 	 	OD)1aIOO6$1a4>6::   	 	r"   )NTNr   N)rP   
__module____qualname____doc__rE   
multiframeunitsr!   r.   r2   r1   r=    r"   r    r   r   e   s        # #J FJZ00E
 16 16 16 16f/ / /   *# *# *#XD D D D D Dr"   r   c                        e Zd ZdZdZdddZeZe fd            Z	e
 ed          d                         Ze
 ed	          d
                         Zd Zd ZddZd Zd ZddZd Z xZS )	XYZReadera  Reads from an XYZ file

    :Data:
        :attr:`ts`
          Timestep object containing coordinates of current frame

    :Methods:
        ``len(xyz)``
          return number of frames in xyz
        ``for ts in xyz:``
          iterate through trajectory

    .. Note: this can read both compressed (foo.xyz) and compressed
          (foo.xyz.bz2 or foo.xyz.gz) files; uncompression is handled
          on the fly and also reads streams via
          :class:`~MDAnalysis.lib.util.NamedStream`.

    The XYZ file format follows VMD's xyzplugin_ and is also described
    under :ref:`XYZ format <xyz-format>`.

    .. versionchanged:: 0.11.0
       Frames now 0-based instead of 1-based. Added *dt* and
       *time_offset* keywords (passed to :class:`Timestep`)
    r   r   r   r   c                     t          t          |           j        |fi | t          j                            | j                  \  }}t          j        | j                  | _	        |dd          dk    r
|dd          nd | _
        t                      | _         | j        | j        fi | j        | _        |                                  d S )Nr   xyz)superr`   r!   ospathsplitextr   r   r   xyzfilecompressiondict_cache	_Timestepr   
_ts_kwargsr8   _read_next_timestep)r   r   r   rootextrO   s        r    r!   zXYZReader.__init__r  s    'i';;F;;;
 G$$T]33	c|DM22&)!""g&6&63qrr77Dff $.AAAA
 	  """""r"   r   c                     t          j        | j                  5 }|                                }ddd           n# 1 swxY w Y   t	          |          S )znumber of atoms in a frameN)r   r   r   readlineint)r   fns      r    r   zXYZReader.n_atoms  s     \$-(( 	A

A	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 1vvs   ;??n_framesc                 N    	 |                                  S # t          $ r Y dS w xY w)Nr   )_read_xyz_n_framesIOErrorr3   s    r    ru   zXYZReader.n_frames  s;    	**,,, 	 	 	11	s    
$$c                 L   | j         dz   }d}g }t          j        | j                  5 }d}|rG||z  s'|                    |                                           |                                }|dz  }|Gd d d            n# 1 swxY w Y   t          ||z            }|| _        |S )Nr   r   Tr   )	r   r   r   r   appendtellrq   rr   _offsets)r   linesPerFramecounteroffsetsrs   lineru   s          r    rw   zXYZReader._read_xyz_n_frames  s     q(\$-(( 	AD . -NN16688,,,zz||1	  	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 w.//s   AB  BBc                     | j                             | j        |                    |dz
  | j        _        |                                 S )Nr   )rg   seekr|   r8   rN   rm   )r   rN   s     r    _read_framezXYZReader._read_frame  s>    $-.///	'')))r"   Nc                    || j         }| j        }	 |                                 |                                 g }t          | j                  D ]C}|                    |                                                                dd                    D||_        |xj        dz  c_        |S # t          t          f$ r}t          |          d d }~ww xY w)Nr      )r8   rg   rq   ranger   rz   splitrM   rN   rD   
IndexErrorEOFError)r   r8   rs   tmp_bufierrs         r    rm   zXYZReader._read_next_timestep  s    :BL	*JJLLLJJLLLG4<(( : :qzz||1133AaC89999"BLHHMHHIJ' 	* 	* 	*3--T)	*s   BB- -C>CCc                 V    |                                   |                                  d S rX   )r2   open_trajectoryr3   s    r    _reopenzXYZReader._reopen  s'    

r"   c                     | j          t          t          j        d| j                  t          j        | j                  | _         | j        }d|_        | j         S )NzXYZ file already opened)	rg   rx   errnoEALREADYr   r   r   r8   rN   )r   r8   s     r    r   zXYZReader.open_trajectory  sU    <# 94=   |DM22 W|r"   c                 2    || j         }t          |fd|i|S )a>  Returns a XYZWriter for *filename* with the same parameters as this
        XYZ.

        Parameters
        ----------
        filename: str
            filename of the output trajectory
        n_atoms: int (optional)
            number of atoms. If none is given use the same number of atoms from
            the reader instance is used
        **kwargs:
            See :class:`XYZWriter` for additional kwargs

        Returns
        -------
        :class:`XYZWriter` (see there for more details)

        See Also
        --------
        :class:`XYZWriter`
        Nr   )r   r   )r   r   r   r   s       r    WriterzXYZReader.Writer  s+    , ?lG==7=f===r"   c                 X    | j         dS | j                                          d| _         dS )z)Close xyz trajectory file if it was open.N)rg   r2   r3   s    r    r2   zXYZReader.close  s.    <Fr"   rX   )rP   rY   rZ   r[   rE   r]   r   rk   r	   r!   propertyr   r   ru   rw   r   rm   r   r   r   r2   __classcell__)rO   s   @r    r`   r`   M  s9        > FZ00EI# # # # #$ VI   X VJ   X  (* * *
* * * **    > > > >4      r"   r`   )r[   r+   rd   r   numpyrJ   r)   logging	getLoggerrH    r   timestepr   libr   lib.utilr   r	   
exceptionsr
   versionr   
WriterBaser   
ReaderBaser`   r^   r"   r    <module>r      sH  2: :v     				       		7	8	8                   3 3 3 3 3 3 3 3 $ $ $ $ $ $ ! ! ! ! ! !e e e e e e e ePh h h h h h h h h hr"   