
     i63                         d Z ddlZddl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  MOL2 file format --- :mod:`MDAnalysis.coordinates.MOL2`
========================================================

Classes to work with Tripos_ molecule structure format (MOL2_) coordinate and
topology files. Used, for instance, by the DOCK_ docking code.


Example for working with mol2 files
-----------------------------------

To open a mol2, remove all hydrogens and save as a new file, use the following::

  u = Universe("Molecule.mol2")
  gr = u.select_atoms("not name H*")
  print(len(u.atoms), len(gr))
  gr.write("Molecule_noh.mol2")

.. _MOL2: http://www.tripos.com/data/support/mol2.pdf
.. _Tripos: http://www.tripos.com/
.. _DOCK: http://dock.compbio.ucsf.edu/


See Also
--------

rdkit: rdkit_ is an open source cheminformatics toolkit with more mol2
       functionality


.. _rdkit: http://www.rdkit.org/docs/GettingStartedInPython.html


Classes
-------

.. autoclass:: MOL2Reader
   :members:

.. autoclass:: MOL2Writer
   :members:


Notes
-----

* The MDAnalysis :class:`MOL2Reader` and :class:`MOL2Writer` only handle the
  MOLECULE, SUBSTRUCTURE, ATOM, and BOND record types. Other records are not
  currently read or preserved on writing.
* As the CRYSIN record type is not parsed / written, MOL2 systems always have
  dimensions set to ``None`` and dimensionless MOL2 files are written.


MOL2 format notes
-----------------

* MOL2 Format Specification:  (http://www.tripos.com/data/support/mol2.pdf)
* Example file (http://www.tripos.com/mol2/mol2_format3.html)::

    #    Name: benzene
    #    Creating user name: tom
    #    Creation time: Wed Dec 28 00:18:30 1988

    #    Modifying user name: tom
    #    Modification time: Wed Dec 28 00:18:30 1988

    @<TRIPOS>MOLECULE
    benzene
    12 12 1  0   0
    SMALL
    NO_CHARGES


    @<TRIPOS>ATOM
    1   C1  1.207   2.091   0.000   C.ar    1   BENZENE 0.000
    2   C2  2.414   1.394   0.000   C.ar    1   BENZENE 0.000
    3   C3  2.414   0.000   0.000   C.ar    1   BENZENE 0.000
    4   C4  1.207   -0.697  0.000   C.ar    1   BENZENE 0.000
    5   C5  0.000   0.000   0.000   C.ar    1   BENZENE 0.000
    6   C6  0.000   1.394   0.000   C.ar    1   BENZENE 0.000
    7   H1  1.207   3.175   0.000   H   1   BENZENE 0.000
    8   H2  3.353   1.936   0.000   H   1   BENZENE 0.000
    9   H3  3.353   -0.542  0.000   H   1   BENZENE 0.000
    10  H4  1.207   -1.781  0.000   H   1   BENZENE 0.000
    11  H5  -0.939  -0.542  0.000   H   1   BENZENE 0.000
    12  H6  -0.939  1.936   0.000   H   1   BENZENE 0.000
    @<TRIPOS>BOND
    1   1   2   ar
    2   1   6   ar
    3   2   3   ar
    4   3   4   ar
    5   4   5   ar
    6   5   6   ar
    7   1   7   1
    8   2   8   1
    9   3   9   1
    10  4   10  1
    11  5   11  1
    12  6   12  1
   @<TRIPOS>SUBSTRUCTURE
    1   BENZENE 1   PERM    0   ****    ****    0   ROOT

    N   )base   )util)store_init_argumentsc                   Z     e Zd ZdZdZdddZe fd            Zd ZddZ	d	 Z
d
 Z xZS )
MOL2Readera  Reader for MOL2 structure format.

    .. versionchanged:: 0.11.0
       Frames now 0-based instead of 1-based.
       MOL2 now reuses the same Timestep object for every frame,
       previously created a new instance of Timestep each frame.
    .. versionchanged:: 0.20.0
       Allows for comments at top of file.
       Ignores status bit strings
    .. versionchanged:: 2.0.0
       Bonds attribute is not added if no bonds are present in MOL2 file
    .. versionchanged:: 2.2.0
       Read MOL2 files with optional columns omitted.
    MOL2NAngstromtimelengthc                     t          t          |           j        |fi | d| _        g }t	          j        |          5 }t          |          D ]Q\  }}d|v r|                    |g d           t          |          r!|d         d                             |           R	 ddd           n# 1 swxY w Y   t          |          | _	        || _
        |                     |d                   \  }}t          |          | _         | j        | j        fi | j        | _        |                     d          | _        dS )zRead coordinates from `filename`.


        Parameters
        ----------
        filename : str or NamedStream
             name of the mol2 file or stream
        Nz@<TRIPOS>MOLECULE)
start_linelinesr   r   )superr	   __init__n_atomsr   openany	enumerateappendlenn_framesframesparse_block	_Timestep
_ts_kwargsts_read_frame)
selffilenamekwargsblocksfilinesectionscoords	__class__s
            e/srv/www/vhosts/g4struct/public_html/venv/lib/python3.11/site-packages/MDAnalysis/coordinates/MOL2.pyr   zMOL2Reader.__init__   s~    	)j$(<<V<<<\(## 	5q$Q<< 5 54&$..MMR"@"@AAAv;; 52Jw'..t4445	5 	5 	5 	5 	5 	5 	5 	5 	5 	5 	5 	5 	5 	5 	5 F++F1I66&6{{ $.AAAA""1%%s    A"B//B36B3c                 N   i }d }|d         D ]}d|v rE|                     d          d                                                                         }g ||<   K|                    d          s|dk    rg||                             |           |d         }t          |          s(t          d                    |d                             | j        t          |          | _        nMt          |          | j        k    r5t          d	                    | j        t          |                              t          j        | j        d
ft          j                  }t          |          D ]4\  }}|                                 d d         \  }	}
}}}}|||f||d d f<   5||fS )Nr   z	@<TRIPOS>r   #
atomz2The mol2 (starting at line {0}) block has no atomsr   zMOL2Reader assumes that the number of atoms remains unchanged between frames; the current frame has {0}, the next frame has {1} atoms   dtype   )splitstriplower
startswithr   r   	Exceptionformatr   
ValueErrornpzerosfloat32r   )r!   blockr(   cursorr'   
atom_linesr)   r&   aaidnamexyz	atom_types                  r+   r   zMOL2Reader.parse_block   s   'N 	* 	*Dd""K00399;;AACC#% %% V##D))))f%
: 	6%-..   \!z??DLL__,, 6$,J88	   4<+2:>>>j)) 	# 	#DAq,-GGIIbqbM)Cq!Q	 a7F1aaa4LL    c                 r    || j         }nt          d          | j        dz   }|                     |          S )Nz&MOL2Reader cannot assign to a timestepr   )r   NotImplementedErrorframer    )r!   r   rK   s      r+   _read_next_timestepzMOL2Reader._read_next_timestep   s@    :BB &&NOOO
Q&&&rH   c                    	 | j         |         }n3# t          $ r& d| dt          |            }t          |          d w xY w|                     |          \  }}dD ](}	 ||         | j        j        |<   # t          $ r Y %w xY wt          j	        |t          j
                  | j        _        | j        r|                     | j        j                   || j        _        | j        S )NzInvalid frame z for trajectory with length )moleculesubstructurer1   )r   
IndexErrorr   IOErrorr   r   dataKeyErrorr;   arrayr=   	positionsconvert_unitsconvert_pos_from_native_posrK   )r!   rK   r>   errmsgr(   r)   sects          r+   r    zMOL2Reader._read_frame   s   	,K&EE 	, 	, 	,  t99   &//t+	,  ++E22&0 	 	D%-d^T""    HV2:>>> 	7((666ws    0A  A66
BBc                     d| j         _        d S )Nr   )r   rK   r!   s    r+   _reopenzMOL2Reader._reopen  s     rH   N)__name__
__module____qualname____doc__r9   unitsr   r   r   rL   r    r]   __classcell__)r*   s   @r+   r	   r	      s          FZ00E& & & & &@$  $  $ L' ' ' '  6      rH   r	   c                   >    e Zd ZdZdZdZdddZddZd Zd	 Z	d
 Z
dS )
MOL2Writeraq  mol2 format writer

    Write a file in the Tripos_ molecule structure format (MOL2_).

    Note
    ----
    :class:`MOL2Writer` can only be used to write out previously loaded MOL2 files.
    If you're trying to convert, for example, a PDB file to MOL you should
    use other tools, like rdkit_.

    Here is an example how to use rdkit_ to convert a PDB to MOL::

      from rdkit import Chem
      mol = Chem.MolFromPDBFile("molecule.pdb", removeHs=False)
      Chem.MolToMolFile(mol, "molecule.mol" )

    MOL2 writer is currently not available for rdkit master. It requires SYBYL
    atomtype generation.
    See page 7 for list of SYBYL atomtypes
    (http://tripos.com/tripos_resources/fileroot/pdfs/mol2_format2.pdf).


    .. _rdkit: http://www.rdkit.org/docs/GettingStartedInPython.html

    .. versionchanged:: 0.11.0
       Frames now 0-based instead of 1-based

    r
   TNr   r   c                 n    || _         || _        d| _        t          j        | j         d          | _        dS )zCreate a new MOL2Writer

        Parameters
        ----------
        filename: str
            name of output file
        convert_units: bool (optional)
            units are converted to the MDAnalysis base format; [``True``]
        r   wN)r"   rV   frames_writtenr   anyopenfile)r!   r"   r   rV   s       r+   r   zMOL2Writer.__init__+  s9     ! 	  L44			rH   c                 8    | j                                          d S r^   )rk   closer\   s    r+   rm   zMOL2Writer.close>  s    	rH   c                 
   	 |j         }n # t          $ r d}t          |          dw xY w|j        j        }|j        }	 |j        d         }n # t          $ r d}t          |          dw xY wd t          |j         d          D             t          |d          r|j        }t          d	 |D                       }d
g}fdt          |d          D             }	|                    |	           |                    d           d                    |          }ng }d}dg}
|
                    fd|j         D                        |
                    d           d                    |
          }
	 dg|j        d         z   }n# t          $ r d}Y nw xY w|d                                         }t#          t%          |j                             t#          t%          |                    c|d<   |d<   |d         }|d         }d                    d                    |                    |d<   |                    dd           d                    |          |
z   |z   d                    |          z   }||d<   ||d<   |S )zS
        Parameters
        ----------
        obj : AtomGroup or Universe
        z-Input obj is neither an AtomGroup or UniverseNrN   z/MOL2Writer cannot currently write non MOL2 datac                     i | ]\  }}||	S  rp   ).0r&   rA   s      r+   
<dictcomp>z+MOL2Writer.encode_block.<locals>.<dictcomp>X  s    BBBDAq1aBBBrH   r   )startbondsc              3   B   K   | ]}|d          |d         |j         fV  dS )r   r   N)order)rq   bs     r+   	<genexpr>z*MOL2Writer.encode_block.<locals>.<genexpr>_  s3      DDQAaD!A$0DDDDDDrH   z@<TRIPOS>BONDc                 f    g | ]-\  }\  }}}d                      ||         |         |          .S )z{0:>5} {1:>5} {2:>5} {3:>2})r9   )rq   bidatom1atom2rv   mappings        r+   
<listcomp>z+MOL2Writer.encode_block.<locals>.<listcomp>a  sW        /C.% .44   rH   r.    z@<TRIPOS>ATOMc              3      K   | ]a}d                      |         |j        |j        d         |j        d         |j        d         |j        |j        |j        |j        	  	        V  bdS )zE{0:>4} {1:>4} {2:>13.4f} {3:>9.4f} {4:>9.4f} {5:>4} {6} {7} {8:>7.4f}r   r   r   N)r9   rC   positiontyperesidresnamecharge)rq   rA   r}   s     r+   rx   z*MOL2Writer.encode_block.<locals>.<genexpr>o  s       
 
 v

1
1
1	
 

 
 
 
 
 
rH   z@<TRIPOS>SUBSTRUCTURE
rO   r   z{0}
 z@<TRIPOS>MOLECULE
)atomsAttributeError	TypeErroruniverse
trajectoryr   rR   rS   rJ   r   hasattrintra_bondssortedextendr   joinr4   strr   r9   insert)r!   objrY   trajr   rN   	bondgrouprt   
bond_linesblsr@   rO   
check_sumsmolecule_0_storemolecule_1_store
return_valr}   s                   @r+   encode_blockzMOL2Writer.encode_blockA  s   	.)CC 	. 	. 	.DFF##-	. |&W	8wz*HH 	8 	8 	8FF%f--47	8
 CBIciq$A$A$ABBB 3   	 IDD)DDDDDE)*J    3<E2K2K2K	  C c"""d###:..JJIJ%&
 
 
 
 
 Y
 
 
 	
 	
 	
  	$YYz**
	56: LL  	 	 	LLL	 a[&&((
'*3sy>>':':CI<O<O$
1z!} $A;#A;nnSXXj%9%9::0111 GGH
*Z7"'',:O:OO 	 '&s%    (A A*5F FFc                 d    |                      |          }| j                            |           dS )zWrite a new frame to the MOL2 file.

        Parameters
        ----------
        obj : AtomGroup or Universe


        .. versionchanged:: 1.0.0
            Renamed from `write_next_timestep` to `_write_next_frame`.
        N)r   rk   
writelines)r!   r   r>   s      r+   _write_next_framezMOL2Writer._write_next_frame  s3     !!#&&	U#####rH   )NT)r_   r`   ra   rb   r9   
multiframerc   r   rm   r   r   rp   rH   r+   rf   rf   	  s|         : FJZ00E5 5 5 5&  Y Y Yv$ $ $ $ $rH   rf   )rb   numpyr;   r   r   libr   MDAnalysis.lib.utilr   
ReaderBaser	   
WriterBaserf   rp   rH   r+   <module>r      s   0e eL                 4 4 4 4 4 4A A A A A A A AH_$ _$ _$ _$ _$ _$ _$ _$ _$ _$rH   