
     i\              	          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mZm	Z	 ddl
mZ ddlmZmZ ddlmZ dd	lmZmZmZmZ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!  ej"        d          Z# e$g d          Z% e&e%          D ]PZ' e(e')                                          dk    r-e%*                    e')                                d                    Q e$g d          Z+ G d de          Z,edej-        deegde.dede/dedej0        dede/dedej1        ddZ2 G d de          Z3ej4         G d de/                      Z5dS )a  
LAMMPSParser
============

Parses data_ or dump_ files produced by LAMMPS_.

.. note::

    By default, masses will be guessed on Universe creation if they are not
    read from the input file. This may change in release 3.0.
    See :ref:`Guessers` for more information.

.. _LAMMPS: https://www.lammps.org/
.. _data: DATA file format: :https://docs.lammps.org/2001/data_format.html
.. _dump: https://docs.lammps.org/dump.html

.. versionchanged:: 1.0.0
   Deprecated :class:`LAMMPSDataConverter` has now been removed.


.. _atom_style_kwarg:

Atom styles
-----------

By default parsers and readers for Lammps data files expect either an
*atomic* or *full* `atom_style`_.  This can be customised by passing
the `atom_style` keyword argument.  This should be a space separated
string indicating the position of the `id`, `type`, `resid`, `charge`,
`x`, `y` and `z` fields.  The `resid` and `charge` fields are optional
and any other specified field will be ignored.

For example to read a file with the following format, where there is no resid::

  Atoms # atomic

  1 1 3.7151744275286681e+01 1.8684434743140471e+01 1.9285127961842125e+01 0 0 0


The following code could be used::

  >>> import MDAnalysis as mda
  >>>
  >>> u = mda.Universe('myfile.data', atom_style='id type x y z')


.. _`atom_style`: https://docs.lammps.org/atom_style.html

Classes
-------

.. autoclass:: DATAParser
   :members:
   :inherited-members:

.. autoclass:: LammpsDumpParser
   :members:


    N   )openany
conv_float)triclinic_box   )TopologyReaderBase	squash_by)Topology)	AtomtypesAtomidsAnglesBondsCharges	DihedralsElements	ImpropersMassesResidsResnumsSegids)SYMB2Z)masseszMDAnalysis.topology.LAMMPS)Atoms
Velocitiesr   
EllipsoidsLines	TrianglesBodiesr   r   r   r   PairzPair LJCoeffszPairIJ CoeffszBond CoeffszAngle CoeffszDihedral CoeffszImproper CoeffszBondBond CoeffszBondAngle CoeffszMiddleBondTorsion CoeffszEndBondTorsion CoeffszAngleTorsion CoeffszAngleAngleTorsion CoeffszBondBond13 CoeffszAngleAngle Coeffs)atomsbondsangles	dihedrals	impropersz
atom typesz
bond typeszangle typeszdihedral typeszimproper typeszextra bond per atomzextra angle per atomzextra dihedral per atomzextra improper per atomzextra special per atom
ellipsoidslines	trianglesbodiesxlo xhiylo yhizlo zhixy xz yzc                   n    e Zd ZdZdZd Zd Zed             Zd Z		 ddZ
d	 Zd
 Zd ZddZd Zd ZdS )
DATAParserap  Parse a LAMMPS DATA file for topology and coordinates.

    Note that LAMMPS DATA files can be used standalone.

    Both topology and coordinate parsing functionality is kept in this
    class as the topology and coordinate reader share many common
    functions

    By default the parser expects either *atomic* or *full* `atom_style`
    however this can be by passing an `atom_style` keyword argument,
    see :ref:`atom_style_kwarg`.

    .. versionadded:: 0.9.0
    .. versionchanged:: 2.8.0
        Removed mass guessing (attributes guessing takes place now
        through universe.guess_TopologyAttrs() API).

    DATAc              #      K   t          | j                  5 }|D ]5}|                    d          d                                         }|r|V  6	 d d d            d S # 1 swxY w Y   d S )N#r   )r   filename	partitionstrip)selfflines      j/srv/www/vhosts/g4struct/public_html/venv/lib/python3.11/site-packages/MDAnalysis/topology/LAMMPSParser.pyiterdatazDATAParser.iterdata   s      T]## 	q  ~~c**1-3355 JJJ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	s   9AA"%A"c                 |   t          |                                           d t                    D             dgz  i }dd                  D ]@}t          D ]6}|                    |          r|                    |          d         ||<   67Afdt          dd                   D             }||fS )zSplit a data file into dict of header and sections

        Returns
        -------
        header - dict of header section: value
        sections - dict of section name: content
        c                 Z    g | ](\  }}|                                 d          t          v &|)S )r   )splitSECTIONS).0ir7   s      r8   
<listcomp>z,DATAParser.grab_datafile.<locals>.<listcomp>   s2    OOO44::<<?h3N3N!3N3N3N    Nr   c                 P    i | ]"\  }}|         |d z   |d z                     #S )r    )r>   r?   lr6   startss      r8   
<dictcomp>z,DATAParser.grab_datafile.<locals>.<dictcomp>   sF     
 
 
/3q!AaD!AEF1q5M)*
 
 
rA   )listr9   	enumerateHEADERSendswithr<   )r5   headerr7   tokensectsr6   rE   s        @@r8   grab_datafilezDATAParser.grab_datafile   s     !!OO9Q<<OOO4&kq	kN 	 	D   =='' $(JJu$5$5a$8F5M

 
 
 
 
7@7M7M
 
 
 u}rA   c                 &   i |                                  } dD ]-}	 |                     |          }||<   # t          $ r Y *w xY wg d}fd|D             }|r5t          d                    d                    |                              S )aL  Transform a string description of atom style into a dict

        Required fields: id, type, x, y, z
        Optional fields: resid, charge

        eg: "id resid type charge x y z"
        {'id': 0,
         'resid': 1,
         'type': 2,
         'charge': 3,
         'x': 4,
         'y': 5,
         'z': 6,
        }
        )idtyperesidchargexyz)rQ   rR   rU   rV   rW   c                     g | ]}|v|	S rC   rC   )r>   attr
style_dicts     r8   r@   z4DATAParser._interpret_atom_style.<locals>.<listcomp>  s#    OOO$J8N8N8N8N8NrA   z/atom_style string missing required field(s): {}z, )r<   index
ValueErrorformatjoin)
atom_stylerY   location
reqd_attrsmissing_attrsrZ   s        @r8   _interpret_atom_stylez DATAParser._interpret_atom_style   s    " 
%%''
D 	, 	,D,%++D11 $,
4      
 322
OOOO*OOO 	6$))M2233  
 s   8
AAc                    	 |                      |d                   | _        n# t          $ r
 d| _        Y nw xY w|                                 \  }}	 |                     |d                   }n# t          $ r d}Y nw xY wd|vrt          d          	 |                     |d         |          }n # t          $ r d}t          |          dw xY wd t          |j	        j
                  D             }t          dd	ft          d
dft          ddft          ddffD ][\  }}	}
	 |                     ||	         |
|          \  }}n# t          $ r g g }}Y nw xY w|                     |||                     \|S )ziParses a LAMMPS_ DATA file.

        Returns
        -------
        MDAnalysis Topology object.
        r_   Nr   r   z#Data file was missing Atoms sectionzFailed to parse atoms section.  You can supply a description of the atom_style as a keyword argument, eg mda.Universe(..., atom_style='id resid x y z')c                     i | ]\  }}||	S rC   rC   )r>   r?   atom_ids      r8   rF   z$DATAParser.parse.<locals>.<dictcomp>7  s    JJJ*!W7AJJJrA   r   r   r      r      r   )rc   rZ   KeyErrorrO   _parse_massesr\   _parse_atoms	ExceptionrI   idsvaluesr   r   r   r   _parse_bond_sectionadd_TopologyAttr)r5   kwargsheadrN   r   toperrmsgmappingrY   LnentriesrR   sects                r8   parsezDATAParser.parse  s   	#"889MNNDOO 	# 	# 	#"DOOO	# ((**e	''h88FF 	 	 	FFF	 %BCCC	/##E'NF;;CC 	/ 	/ 	/D 
 V$$$.	/ KJ	#'.0I0IJJJ GQXq!Q'Q'	"
 	3 	3D!X$!55!Hh 
dd  $ $ $d$   dD!1!12222
s<    # 77A. .A=<A=B1 1C! EEENc                    |d| _         n|                     |          | _         |                                 \  }}|                     |          }	 |                     |d                   \  }}	n'# t
          $ r}
d|
 }t          |          dd}
~
ww xY wd|v r|                     |d         |	          }nd} |j        |fd|i|}||_	        |S )a)  Read a DATA file and try and extract x, v, box.

        - positions
        - velocities (optional)
        - box information

        Fills this into the Timestep object and returns it

        .. versionadded:: 0.9.0
        .. versionchanged:: 0.18.0
           Added atom_style kwarg
        Nr   z Position information not found: r   
velocities)
rZ   rc   rO   
_parse_box
_parse_posri   IOError
_parse_velfrom_coordinates
dimensions)r5   n_atomsTS_class	TS_kwargsr_   rL   rN   unitcell	positionsorderingerrrt   r{   tss                 r8   read_DATA_timestepzDATAParser.read_DATA_timestepJ  s    "DOO"88DDDO**,,??6**	,"&//%."A"AIxx 	, 	, 	,===F&//t+	, 5  |)<hGGJJJ&X&
 
",
09
 
 !	s   A1 1
B;BBc                 \   t          j        t          |          dft           j                  }t          j        t          |          t           j                  }| j        9t          |d                                                   dv rddddd	}nddddd	}n| j        }t          |          D ]Z\  }}|                                }||d
                  ||<   ||d                  ||d                  ||d                  g||ddf<   [t          j        |          }||         }||fS )z#Strip coordinate info into np arrayrg   dtypeNr      
   rh         )rQ   rU   rV   rW   rQ   rU   rV   rW   )	npzeroslenfloat32int32rZ   r<   rI   argsort)r5   	datalinesposrm   rZ   r?   r7   orders           r8   r}   zDATAParser._parse_post  s3   hI*"*=== hs3xxrx000?"9Q<%%''((G33$%AAA>>

$%AAA>>

J ++ 		 		GAt::<<D*T*+CF Z_%Z_%Z_%C111II 
3%j EzrA   c                     t          j        t          |          dft           j                  }t	          |          D ]&\  }}|                                }|dd         ||<   '||         }|S )aP  Strip velocity info into np array

        Parameters
        ----------
        datalines : list
          list of strings from file
        order : np.array
          array which rearranges the velocities into correct order
          (from argsort on atom ids)

        Returns
        -------
        velocities : np.ndarray
        rg   r   r   rh   )r   r   r   r   rI   r<   )r5   r   r   velr?   r7   s         r8   r   zDATAParser._parse_vel  sn     hI*"*=== ++ 	 	GAt::<<D!A#YCFF%j
rA   c           
      "   g }g }|D ]j}|                                 }|                    t          fd|dd|z            D                                  |                    |d                    kt          |          t          |          fS )a  Read lines and strip information

        Arguments
        ---------
        datalines : list
          the raw lines from the data file
        nentries : int
          number of integers per line
        mapping : dict
          converts atom_ids to index within topology

        Returns
        -------
        types : tuple of strings
          type of the bond/angle/dihedral/improper
        indices : tuple of ints
          indices of atoms involved
        c                 :    g | ]}t          |                   S rC   )int)r>   rU   ru   s     r8   r@   z2DATAParser._parse_bond_section.<locals>.<listcomp>  s#    GGG1ws1vvGGGrA   r   r   )r<   appendtuple)r5   r   rw   ru   sectionrR   r7   s      `   r8   ro   zDATAParser._parse_bond_section  s    &  	! 	!D::<<DNNGGGGQX5E0FGGGHH   KKQ    T{{E'NN**rA   c                    t                               d           t          |          }| j        7dddd}t          |d                                                   }|dv rd|d	<   n| j        }d	|v }d
|v }t          j        |t
          j                  }t          j        |t                    }	|r!t          j        |t
          j                  }
n t          j	        |t
          j                  }
|r t          j        |t
          j
                  }t          |          D ]a\  }}|                                }||d                  ||<   |r||d
                  |
|<   ||d                  |	|<   |r||d	                  ||<   bt          j        |          }||         }|	|         }	|r|
|         }
|r||         }g }|                    t          |	                     |r"|                    t          |                     |bt          j        |t
          j                  }t          |	          D ]\  }}||         ||<   |                    t#          |                     t%          |
          dd         \  }}
t          |
          }|                    t'          |                     |                    t)          |
                     |                    t+          |
                                                     |                    t/          t          j        dgt                                         t3          ||d||          }|S )a  Creates a Topology object

        Adds the following attributes
         - resid
         - type
         - masses (optional)
         - charge (optional)

        Lammps atoms can have lots of different formats,
        and even custom formats

        https://docs.lammps.org/atom_style.html

        Treated here are
        - atoms with 7 fields (with charge) "full"
        - atoms with 6 fields (no charge) "molecular"

        Arguments
        ---------
        datalines - the relevent lines from the data file
        massdict - dictionary relating type to mass

        Returns
        -------
        top - Topology object
        zDoing Atoms sectionNr   r   r   )rQ   rS   rR   r   rg   rT   rS   r   rQ   rR   SYSTEMattrsatom_resindex)loggerinfor   rZ   r<   r   r   r   objectonesr   rI   r   r   r   r   float64r   r	   r   r   r   copyr   arrayr
   )r5   r   massdictr   sdn
has_charge	has_residatom_idstypesresidschargesr?   r7   r   r   r   atresidx
n_residuesrs   s                        r8   rk   zDATAParser._parse_atoms  s2   6 	)***i..?"Aq11BIaL&&(())AG|| 8B^
rM	 8G28444/// 	6XgRX666FFWWBH555F 	:hwbj999G ++ 	0 	0GAt::<<D
 r$x.HQK . G-q	BvJ'E!H 0!"X,/
 
8$$E?e 	#E]F 	%enGYu%%&&& 	+LL))***XgRZ888F"5)) ) )2$RLq		LL((("6**2A2.[[
WX&&'''VF^^$$$WV[[]]++,,,VBHhZv>>>??@@@Z%v
 
 
 
rA   c                     t                               d           i }|D ]4}|                                }t          |d                   ||d         <   5|S )zpLammps defines mass on a per atom type basis.

        This reads mass for each type and stores in dict
        zDoing Masses sectionr   r   )r   r   r<   float)r5   r   r   r7   s       r8   rj   zDATAParser._parse_masses3  sV    
 	*+++ 	- 	-D::<<D#DGnnF47OOrA   c                    t          j        |d                                                   \  }}||z
  }t          j        |d                                                   \  }}||z
  }t          j        |d                                                   \  }}	|	|z
  }
d|v rt          j        dt           j                  }t          j        |d                                                   \  }}}||d         d<   ||d         d<   ||d         d<   ||d	         d<   ||d	         d<   |
|d	         d	<   t	          | }n1t          j        d
t           j                  }|||
f|d d<   d|dd <   |S )Nr)   r*   r+   r,   )rg   rg   r   r   r   r   r   rg   )     V@r   r   )r   r   r<   r   r   )r5   rL   x1x2rU   y1y2rV   z1z2rW   r   xyxzyzs                  r8   r|   zDATAParser._parse_boxA  sg   F9-335566BGF9-335566BGF9-335566BGxbj999HF:$6$<$<$>$>??JBBHQKNHQKNHQKNHQKNHQKNHQKN$h/HH x444Ha7HRaRL+HQRRLrA   N)__name__
__module____qualname____doc__r]   r9   rO   staticmethodrc   ry   r   r}   r   ro   rk   rj   r|   rC   rA   r8   r.   r.      s         & F    4 $ $ \$L3 3 3l 8<( ( ( (T  B  2+ + +<e e e eN      rA   r.   )
attr_classdefaultr         ?)rQ   molrR   masselementqc                       e Zd ZdZdZd ZdS )LammpsDumpParsera$  Parses Lammps ascii dump files.

    id, mol, type, mass, element and q columns are read
    and used to set the corresponding topology attributes.

    All other columns are ignored.

    If masses are not provided they will attempt to be guessed
    from element names. If no element names are provided then all masses
    will be set to 1.0.


    .. versionadded:: 0.19.0
    .. versionchanged:: 2.0.0
       Allow for a more flexible column layout
    .. versionchanged:: 2.10.0
       Allow reading of mass, charge and element attributes
    
LAMMPSDUMPc                 	   t          | j                  5 }|                                 |                                 |                                 t          |                                          }|                                 |                                 |                                 |                                 |                                }|                                dd          }d t          |          D             }d|vrt          d          d|vr-d|v rt          j        d           nt          j        d           d	|vrt          j        d
           i }t          D ]}||v r+t          j        |t          |         d                   ||<   1t          |         d         <t          j        |t          |         d         t          |         d                   ||<   t          |          D ]S}	|                                                                }
|                                D ]\  }}|
|         ||         |	<   T	 d d d            n# 1 swxY w Y   d|v rg }|d         D ]t}|                                t           v r(|                    |                                           Ed| d}t          j        |           |                    d           ut          j        |t          d         d                   |d<   d|vrGt          |          D ]7\  }	}	 t&          |         |d         |	<   # t(          $ r d|d         |	<   Y 4w xY wt          j        |d                   }g }|                                D ]\  }}|dk    rdt-          ||                   d d         \  }}t/          |          }t          |         d         D ] }|                     ||                     !o|                    t          |         d         ||                              |                    t1          t          j        dgt2                                         t5          ||d||          S )Nr   c                 ,    i | ]\  }}|t           v ||S rC   )DUMP_HEADERS)r>   r?   rY   s      r8   rF   z*LammpsDumpParser.parse.<locals>.<dictcomp>  s/       #At4<;O;Oa;O;O;OrA   rQ   zNo id column found in dump filer   r   zJNo mass column found in dump file. Using guessed masses from element info.zGuessed all Masses to 1.0rR   zSet all atom types to 1r   r   r   zUnknown element zF found for some atoms. These have been given an empty element record.  r   r   r   r   r   r   )r   r2   readliner   r<   rI   r\   warningswarnr   r   r   fullrangeitems
capitalizer   r   r   
mass_tableri   r   r	   r   r   r   r
   )r5   rq   finnatomsatomliner   col_ids	atom_datarL   r?   fieldscol_idvalidated_elementselemwmsgr   keyvaluer   r   r   r   s                         r8   ry   zLammpsDumpParser.parse  s   T]## 0	:sLLNNNLLNNNLLNNN((FLLNNNLLNNNLLNNNLLNNN ||~~HNN$$QRR(E '0'7'7  G 7"" !BCCCW$$''MB   
 M"=>>>W$$7888I& 
 
W$$(*l6&:7&C) ) )If%% "&))4@(*$V,Y7*627;) ) )If% 6]] : :--//&-mmoo : :NFF+1&>If%a((::[0	: 0	: 0	: 0	: 0	: 0	: 0	: 0	: 0	: 0	: 0	: 0	: 0	: 0	: 0	:f !#!), 	2 	2??$$..&--doo.?.?@@@@K4 K K K  M$'''&--b1111#%8",y*A'*J$ $ $Ii  W$$();<< 3 3GAt3/9$/?	&)!,,# 3 3 3/2	&)!,,,3 
9T?++#//++ 		L 		LJCe|| "+5<!8!8!!< [[
".s"3L"A 5 5JLLF!3!344445 \#.|<U5\JJKKKKVBHhZv>>>??@@@Jf
 
 
 	
s$   I I""I&)I&3M

M"!M"N)r   r   r   r   r]   ry   rC   rA   r8   r   r   l  s9         & F\
 \
 \
 \
 \
rA   r   c                   H     e Zd ZdZddZd Zd Zd Zd Z fd	Z	d
 Z
 xZS )
LAMMPSAtom)r[   namerR   chainidrT   r   
_positionsr   r   c                 t    || _         t          |          | _        || _        || _        || _        || _        d S r   )r[   reprr   rR   r   rT   r   )r5   r[   r   rR   chain_idrT   r   s          r8   __init__zLAMMPSAtom.__init__  s6    
JJ					rA   c                     dt          | j        dz             z   dz   t          | j                  z   dz   t          | j                  z   dz   S )Nz<LAMMPSAtom r   z: name z
 of chain >)r   r[   rR   r   r5   s    r8   __repr__zLAMMPSAtom.__repr__  sb    4:>""# 49oo 	
 4<  ! 	
rA   c                 "    | j         |j         k     S r   r[   r5   others     r8   __lt__zLAMMPSAtom.__lt__   s    zEK''rA   c                 "    | j         |j         k    S r   r   r   s     r8   __eq__zLAMMPSAtom.__eq__  s    zU[((rA   c                 *    t          | j                  S r   )hashr[   r   s    r8   __hash__zLAMMPSAtom.__hash__  s    DJrA   c                     |dk    r| j         | j                 S t          t          |                               |           d S )Nr   )r   r[   superr   __getattribute__)r5   rY   	__class__s     r8   __getattr__zLAMMPSAtom.__getattr__	  s?    5==?4:..*d##44T:::::rA   c                     | j         }t          | j        dz   | j        | j        | j        | j        |d         |d         |d         f          S )Nr   r   r   )r   iterr[   r   rR   rT   r   )r5   r   s     r8   __iter__zLAMMPSAtom.__iter__  sR    h
Q		AAA	
 
 	
rA   )r   r   )r   r   r   	__slots__r   r   r  r  r  r  r  __classcell__)r  s   @r8   r   r     s        I   	
 	
 	
( ( () ) )     ; ; ; ; ;
 
 
 
 
 
 
rA   r   )6r   numpyr   loggingstring	functoolsr   lib.utilr   r   lib.mdamathr   baser   r	   core.topologyr
   core.topologyattrsr   r   r   r   r   r   r   r   r   r   r   r   guesser.tablesr   r   r   	getLoggerr   setr=   rH   valr   r<   addrJ   r.   r   r   r   r   r   r   r   total_orderingr   rC   rA   r8   <module>r!     s  0; ;x            * * * * * * * * ' ' ' ' ' ' / / / / / / / / $ $ $ $ $ $                            $ # # # # # 1 1 1 1 1 1		7	8	8
 3   B 4>> % %C
s399;;!SYY[[^$$$ #   :f f f f f# f f fX !TBH
E
E!7+CHH$VDD!cBJGG&4&IID2:	F	F r
 r
 r
 r
 r
) r
 r
 r
j :
 :
 :
 :
 :
 :
 :
 :
 :
 :
rA   