
     iy                        d Z ddl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mZmZ ddlZi Z ee          5  ddlmZ ddlmZ dd	lmZmZ ej        j        ej        j        ej        j        ej        j        ej        j        d
Ze                    d e                                D                         ej                     Z!ddd           n# 1 swxY w Y    ee          5  ddl"m#Z# ddd           n# 1 swxY w Y   	 dddde$ddfdZ%ddZ& ed           G d d                      Z' ed           G d d                      Z( ed           G d d                      Z)dS )a{  RDKit bond order inferring --- :mod:`MDAnalysis.converters.RDKitInferring`
=============================================================================
Bond order and formal charge inferring for RDKit molecules. Because most MD
file formats don't preserve bond order information directly (or formal charges
to some extent), the classes provided here give users different options to
either provide or infer this information to the RDKit molecule constructed from
the topology. Having bond orders and formal charges properly defined is a
requirement for almost all cheminformatics-related task, hence the different
approaches proposed here to cover most use cases. You can also defined your own
function if need be, see the :mod:`~MDAnalysis.converters.RDKit` module for an
example.

These classes are meant to be passed directly to the RDKit converter::

    >>> import MDAnalysis as mda
    >>> from rdkit import Chem
    >>> u = mda.Universe("aspirin.pdb")
    >>> template = Chem.MolFromSmiles("CC(=O)Oc1ccccc1C(=O)O")
    >>> inferrer = mda.converters.RDKitInferring.TemplateInferrer(template)
    >>> rdkit_mol = u.atoms.convert_to.rdkit(inferrer=inferrer)

Classes
-------

.. autoclass:: MDAnalysisInferrer
   :members:
   :private-members:

.. autoclass:: TemplateInferrer
   :members:

.. autoclass:: RDKitInferrer
   :members:

.. autofunction:: sanitize_mol

.. autofunction:: reorder_atoms

    N)defaultdict)suppress)	dataclass)ClassVarDictListOptionalTuple)Chem)AssignBondOrdersFromTemplate)ChemicalReactionReactionFromSmarts)   g      ?ar      c                 4    i | ]\  }}t          |          |S  )str).0keyvalues      n/srv/www/vhosts/g4struct/public_html/venv/lib/python3.11/site-packages/MDAnalysis/converters/RDKitInferring.py
<dictcomp>r   V   s$    NNNJCC%NNN    )DetermineBondOrders_MDAnalysis_indexmolChem.Molfieldreturnc                 p   t          t                    5  t          j        fd|                                 D                       }t          j        | |                    t                    	                                          cddd           S # 1 swxY w Y   t          j        d           | S )zReorder atoms based on the given field. Defaults to sorting in the same
    order as the input AtomGroup.

    Notes
    -----
    If the field is not found on the molecule, skips reordering.
    c                 :    g | ]}|                               S r   )
GetIntProp)r   atomr    s     r   
<listcomp>z!reorder_atoms.<locals>.<listcomp>j   s%    NNNtDOOE22NNNr   NzD not available on the input mol atoms, skipping reordering of atoms.)r   KeyErrornpargsortGetAtomsr   RenumberAtomsastypeinttolistwarningswarn)r   r    orders    ` r   reorder_atomsr2   _   s     
(		 C C
NNNNs||~~NNNOO!#u||C'8'8'?'?'A'ABBC C C C C C C C C C C C C C C C MXXX   Js   A1BBBc                 .    t          j        |            dS )zSanitizes the molecule.N)r   SanitizeMol)r   s    r   sanitize_molr5   s   s    Sr   T)frozenc                      e Zd ZU dZdddddddddddddddZeeeef                  ed<   g dZ	ee
e                  ed<   d	Zeed
<   dZeed<   ddZedddeeef         fd            Zedd            Zeddde
e         fd            Z	 dddd
ee         ddfdZede
d         ddddfd            Z	 dddd
ee         ddfdZdS ) MDAnalysisInferrera  Bond order and formal charge inferring as originally implemented for
    the RDKit converter. This algorithm only relies on the topology with
    explicit hydrogens to assign bond orders and formal charges.

    Attributes
    ----------
    max_iter : int
        Maximum number of iterations to standardize conjugated systems.
        See :meth:`~MDAnalysisInferrer._rebuild_conjugated_bonds`
    sanitize : bool
        Whether to sanitize the molecule or not.
    MONATOMIC_CATION_CHARGES : ClassVar[Dict[int, int]]
        Charges that should be assigned to monatomic cations. Maps atomic
        number to  their formal charge. Anion charges are directly handled by
        the code using the typical valence of the atom.
    STANDARDIZATION_REACTIONS : ClassVar[List[str]]
        Reactions uses by :meth:`~MDAnalysisInferrer._standardize_patterns` to
        fix challenging cases must have single reactant and product, and
        cannot add any atom.

    Notes
    -----
    There are some molecules containing specific substructures that this
    inferrer cannot currently tackle correctly. See
    `Issue #3339 <https://github.com/MDAnalysis/mdanalysis/issues/3339>`__ for
    more info.

    .. versionadded:: 2.10.0
    r   r   r   )r         %   /   7               &   8         MONATOMIC_CATION_CHARGES)z![C-;X2;H0:1]=[O:2]>>[C+0:1]=[O:2]z [N-;X2;H1;$(N-[*^3]):1]>>[N+0:1]z,[#6-:1]-[#6:2]=[O:3]>>[#6+0:1]=[#6:2]-[O-:3]z*[C-;v3:1]-[#7+0;v3;H2:2]>>[#6+0:1]=[#7+:2]zI[#6+0;H0:1]=[#6+0:2]-[#7;X3:3]-[#6-;X3:4]>>[#6:1]=[#6:2]-[#7+:3]=[#6+0:4]z%[S;D4;!v6:1]-[*-:2]>>[S;v6:1]=[*+0:2]z#[#7+0;X3:1]-[*-:2]>>[#7+:1]=[*+0:2]STANDARDIZATION_REACTIONS   max_iterTsanitizer   r   r!   c                     |                      |           |                     |          }t          |          }| j        rt	          |           |S )a  Infer bond orders and formal charges in the molecule.

        Parameters
        ----------
        mol : Chem.Mol
            The molecule to infer bond orders and charges for.

        Returns
        -------
        A new molecule with proper bond orders and charges.
        )_infer_bo_and_charges_standardize_patternsr2   rJ   r5   selfr   s     r   __call__zMDAnalysisInferrer.__call__   sU     	""3'''((--C  = 	
r   r%   z	Chem.Atomc                     t          d |                                D                       }|                     |          d          |fS )a  Sorts atoms in the molecule in a way that makes it easy for the bond
        order and charge infering code to get the correct state on the first
        try. Currently sorts by number of unpaired electrons, then by number of
        heavy atom neighbors (i.e. atoms at the edge first).c                 B    g | ]}|                                 d k    |S r   GetAtomicNum)r   neighbors     r   r&   z3MDAnalysisInferrer._atom_sorter.<locals>.<listcomp>   s9       ((**Q.. ...r   r   )lenGetNeighbors_get_nb_unpaired_electrons)clsr%   num_heavy_neighborss      r   _atom_sorterzMDAnalysisInferrer._atom_sorter   s`     "  $ 1 1 3 3  
 
 //55a88:MNNr   Nc           	          t          d |                                D              j                  }|D ]}|                                dk    rq|                     j                            |                                                     |          d                               |	                    d                                |          }t          |          dk    r>|d         dk     r2|                    |d                     |	                    d           t          |          dk    r|d         dk    rt          |                                d fd	          }|D ]}                     |          }t          d
 g ||D             d          }|dk    r|                    |                                |                                          }	|dz   }
|	                    t           |
                    |	                    d                                |          }t#          d |D                       r n                     |          }t#          d |D                       sG|                    |d                     |                    d           |	                    d           dS )aq  Infer bond orders and formal charges from a molecule.

        Since most MD topology files don't explicitly retain information on
        bond orders or charges, it has to be guessed from the topology. This
        is done by looping over each atom and comparing its expected valence
        to the current valence to get the Number of Unpaired Electrons (NUE).
        If an atom has a negative NUE, it needs a positive formal charge
        (-NUE). If two neighbouring atoms have UEs, the bond between them most
        likely has to be increased by the value of the smallest NUE.
        If after this process, an atom still has UEs, it needs a negative
        formal charge of -NUE.

        Parameters
        ----------
        mol : rdkit.Chem.rdchem.RWMol
            The molecule is modified inplace and must have all hydrogens added

        Notes
        -----
        This algorithm is order dependant. For example, for a carboxylate group
        ``R-C(-O)-O`` the first oxygen read will receive a double bond and the
        other one will be charged. It will also affect more complex conjugated
        systems.
        c                 B    g | ]}|                                 d k    |S rS   rT   )r   r%   s     r   r&   z<MDAnalysisInferrer._infer_bo_and_charges.<locals>.<listcomp>   s.    HHHd0A0A0C0Ca0G0GT0G0G0Gr   )r   r   Fstrictr   Tc                 :                         |           d         S )Nr   )rY   )arZ   s    r   <lambda>z:MDAnalysisInferrer._infer_bo_and_charges.<locals>.<lambda>  s    c<<Q??B r   )reverser   c                     g | ]
}|d k    |S r   r   )r   is     r   r&   z<MDAnalysisInferrer._infer_bo_and_charges.<locals>.<listcomp>  s    :::1166Q666r   )defaultc              3   "   K   | ]
}|d k    V  dS r   Nr   r   ns     r   	<genexpr>z;MDAnalysisInferrer._infer_bo_and_charges.<locals>.<genexpr>&  s&      //a16//////r   c              3   "   K   | ]
}|d k    V  dS rj   r   rk   s     r   rm   z;MDAnalysisInferrer._infer_bo_and_charges.<locals>.<genexpr>+  s&      ++!qAv++++++r   N)sortedr*   r\   	GetDegreeSetFormalChargerF   getrU   rY   UpdatePropertyCacherW   rX   minGetBondBetweenAtomsGetIdxSetBondTypeRDBONDORDERanySetNumRadicalElectrons)rZ   r   atomsr%   nue	neighborsnana_nue
common_nuebondr1   s   `          r   rL   z(MDAnalysisInferrer._infer_bo_and_charges   s   8 HHcllnnHHH 
 
 

  6	6 6	6D~~1$$$$044))++77==a@@    ''u'5550066C CACFQJJ$$c!fW---''u'555CACFaKK!!##BBBB  I    77;; ::#:::  

 ??224;;=="))++NND&NE$$[%7888++5+99988>>C//3/////  0066C++s+++++ 6$$c!fW---++A...''u'555m6	6 6	6r   c                     t                               |                                           }|                                 |                                 z
  fd|D             S )a;  Calculate the number of unpaired electrons (NUE) of an atom

        Parameters
        ----------
        atom: rdkit.Chem.rdchem.Atom
            The atom for which the NUE will be computed

        Returns
        -------
        nue : List[int]
            The NUE for each possible valence of the atom
        c                     g | ]}|z
  S r   r   )r   v	current_vs     r   r&   zAMDAnalysisInferrer._get_nb_unpaired_electrons.<locals>.<listcomp>A  s    333!I333r   )PERIODIC_TABLEGetValenceListrU   GetTotalValenceGetFormalCharge)r%   expected_vsr   s     @r   rY   z-MDAnalysisInferrer._get_nb_unpaired_electrons1  s`     %33D4E4E4G4GHH((**T-A-A-C-CC	3333{3333r   c                    || j         }nt          j        dt                     |                     ||           d | j        D             }t          t          j        |d| j	                            }|D ]}| 
                    ||           |                    d          }|D ]}t          j        ||          }|S )a,  Standardizes functional groups

        Uses :meth:`~MDAnalysisInferrer._rebuild_conjugated_bonds` to
        standardize conjugated systems, and SMARTS reactions for other
        functional groups.
        Due to the way reactions work, we first have to split the molecule by
        fragments. Then, for each fragment, we apply the standardization
        reactions. Finally, the fragments are recombined.

        Parameters
        ----------
        mol : rdkit.Chem.rdchem.RWMol
            The molecule to standardize
        max_iter : Optional[int]
            Maximum number of iterations to standardize conjugated systems.

            .. deprecated:: 2.10.0
                Will be removed in 3.0, use
                ``inferrer=MDAnalysisInferrer(max_iter=...)`` instead.

        Returns
        -------
        mol : rdkit.Chem.rdchem.Mol
            The standardized molecule

        Notes
        -----
        The following functional groups are transformed in this order:

        +---------------+------------------------------------------------------------------------------+
        | Name          | Reaction                                                                     |
        +===============+==============================================================================+
        | conjugated    | ``[*-:1]-[*:2]=[*:3]-[*-:4]>>[*+0:1]=[*:2]-[*:3]=[*+0:4]``                   |
        +---------------+------------------------------------------------------------------------------+
        | conjugated N+ | ``[N;X3;v3:1]-[*:2]=[*:3]-[*-:4]>>[N+:1]=[*:2]-[*:3]=[*+0:4]``               |
        +---------------+------------------------------------------------------------------------------+
        | conjugated O- | ``[O:1]=[#6+0,#7+:2]-[*:3]=[*:4]-[*-:5]>>[O-:1]-[*:2]=[*:3]-[*:4]=[*+0:5]``  |
        +---------------+------------------------------------------------------------------------------+
        | conjug. S=O   | ``[O-:1]-[S;D4;v4:2]-[*:3]=[*:4]-[*-:5]>>[O+0:1]=[*:2]=[*:3]-[*:4]=[*+0:5]`` |
        +---------------+------------------------------------------------------------------------------+
        | Cterm         | ``[C-;X2;H0:1]=[O:2]>>[C+0:1]=[O:2]``                                        |
        +---------------+------------------------------------------------------------------------------+
        | Nterm         | ``[N-;X2;H1;$(N-[*^3]):1]>>[N+0:1]``                                         |
        +---------------+------------------------------------------------------------------------------+
        | keto-enolate  | ``[#6-:1]-[#6:2]=[O:3]>>[#6+0:1]=[#6:2]-[O-:3]``                             |
        +---------------+------------------------------------------------------------------------------+
        | arginine      | ``[C-;v3:1]-[#7+0;v3;H2:2]>>[#6+0:1]=[#7+:2]``                               |
        +---------------+------------------------------------------------------------------------------+
        | histidine     | ``[#6+0;H0:1]=[#6+0:2]-[#7;X3:3]-[#6-;X3:4]>>[#6:1]=[#6:2]-[#7+:3]=[#6+0:4]``|
        +---------------+------------------------------------------------------------------------------+
        | sulfone       | ``[S;D4;!v6:1]-[*-:2]>>[S;v6:1]=[*+0:2]``                                    |
        +---------------+------------------------------------------------------------------------------+
        | charged N     | ``[#7+0;X3:1]-[*-:2]>>[#7+:1]=[*+0:2]``                                      |
        +---------------+------------------------------------------------------------------------------+

        NzSpecifying `max_iter` is deprecated and will be removed in a future update. Directly create an instance of `MDAnalysisInferrer` with `MDAnalysisInferrer(max_iter=...)` instead.c                 ,    g | ]}t          |          S r   )r   )r   rxns     r   r&   z<MDAnalysisInferrer._standardize_patterns.<locals>.<listcomp>  s.     
 
 
(+s##
 
 
r   T)asMolssanitizeFragsr   )rI   r/   r0   DeprecationWarning_rebuild_conjugated_bondsrG   listr   GetMolFragsrJ   _apply_reactionspopCombineMols)rO   r   rI   	reactions	fragmentsreactantnewmolfragments           r   rM   z(MDAnalysisInferrer._standardize_patternsC  s    v }HHM #   	&&sH555
 
/3/M
 
 
	
 ST]KKK
 
	 " 	7 	7H!!)X6666 q!!! 	8 	8H%fh77FFr   r   r   r   c                 8   |                     d           t          j        |           | D ]l}|                    |          r+|                     d           |                    |          +|                     d           t          j        |           mdS )a  Applies a series of unimolecular reactions to a molecule. The
        reactions must not add any atom to the product. The molecule is
        modified inplace.

        Parameters
        ----------
        reactions : List[rdkit.Chem.rdChemReactions.ChemicalReaction]
            Reactions from SMARTS. Each reaction is applied until no more
            transformations can be made.
        reactant : rdkit.Chem.rdchem.Mol
            The molecule to transform inplace

        Fr_   N)rs   r   KekulizeIfPossibleRunReactantInPlace)r   r   reactions      r   r   z#MDAnalysisInferrer._apply_reactions  s    " 	$$E$222)))! 	. 	.H--h77 ;,,E,::: --h77 ;(((666#H----		. 	.r   c                    || j         n|}|                    d           t          j        |           t          j        d          }t          j        d          }t          j        d          }t          d |                    |          D                       }|dk    rdS |d	k    r|}n|}g }d}	t          |          D ]}
|                    |          }|r}|\  }}}}|	                    |          }|
                                d
k    r|                                dk    s0|
                                dk    r|                                d	k    r|                                D ]}|                    ||                                          }|
                                dk    rS|                                dk    r;|                    t          j        j                   |                    d            nn|
                                dk    r|                                dk    r|                                D ]}|                    ||                                          }|
                                dk    rk|                                dk    rS|                                d	k    r;|                    t          j        j                   |                    d            nn*|                    |                                d	z              |	                    |          }|                    |                                d	z              |                    ||          }|                    t*          |                                d	z                       |                    ||          }|                    t*          |                                d	z
                      |                    ||          }|                    t*          |                                d	z                       |                    d           |                    |          }|r|D ]2}t-          |          }||v r|\  }}}|                    |            nK|	d	k    r|}n|	d	k    r|                    d            dS |d         }|\  }}}t-          |          g}|	d	z  }	|	                    |          }|                    |                                d	z              |	                    |          }|                    |                                d	z
             |                    ||          }|                    t*          |                                d	z                       |                    ||          }|                    t*          |                                d	z
                      |                    d           t          d |D                       }|d	k    r|}}|                    d            dS t1          j        d           dS )aI  Rebuild conjugated bonds without negatively charged atoms at the
        beginning and end of the conjugated system

        Depending on the order in which atoms are read during the conversion,
        the :meth:`~MDAnalysisInferrer._infer_bo_and_charges` function might
        write conjugated systems with a double bond less and both edges of the
        system as anions instead of the usual alternating single and double
        bonds. This function corrects this behaviour by using an iterative
        procedure.
        The problematic molecules always follow the same pattern:
        ``anion[-*=*]n-anion`` instead of ``*=[*-*=]n*``, where ``n`` is the
        number of successive single and double bonds. The goal of the
        iterative procedure is to make ``n`` as small as possible by
        consecutively transforming ``anion-*=*`` into ``*=*-anion`` until it
        reaches the smallest pattern with ``n=1``. This last pattern is then
        transformed ``anion-*=*-anion`` to ``*=*-*=*``.
        Since ``anion-*=*`` is the same as ``*=*-anion`` in terms of SMARTS,
        we can control that we don't transform the same triplet of atoms back
        and forth by adding their indices to a list.
        This function also handles conjugated systems with triple bonds.
        The molecule needs to be kekulized first to also cover systems
        with aromatic rings.

        Parameters
        ----------
        mol : rdkit.Chem.rdchem.RWMol
            The molecule to transform, modified inplace
        max_iter : Optional[int]
            Maximum number of iterations to standardize conjugated systems.

            .. deprecated:: 2.10.0
                Will be removed in 3.0, use
                ``inferrer=MDAnalysisInferrer(max_iter=...)`` instead.

        Notes
        -----
        The molecule is modified inplace
        NFr_   z[*-{1-2}]-,=[*+0]=,#[*+0]z%[*-{1-2}]-,=[*+0]=,#[*+0]-,=[*-{1-2}]zF[*-]-[*+0]=[*+0]-[*-,$([#7;X3;v3]),$([#6+0,#7+1]=O),$([S;D4;v4]-[O-])]c                     h | ]
}|d          S rf   r   r   matchs     r   	<setcomp>z?MDAnalysisInferrer._rebuild_conjugated_bonds.<locals>.<setcomp>  s    DDD%U1XDDDr   r   r            r      c                     h | ]
}|d          S rf   r   r   s     r   r   z?MDAnalysisInferrer._rebuild_conjugated_bonds.<locals>.<setcomp>n  s     ? ? ?eq ? ? ?r   zSThe standardization could not be completed within a reasonable number of iterations)rI   rs   r   r   MolFromSmartsrW   GetSubstructMatchesrangeGetSubstructMatchGetAtomWithIdxrU   r   rX   ru   rv   GetBondTypeAsDoublerw   BondTypeSINGLErq   DOUBLErx   setappendr/   r0   )rO   r   rI   patternbase_end_patternodd_end_pattern	n_matchesend_pattern	backtrackbacktrack_cycles_	end_matchanion1a1a2anion2	term_atomrV   r   rb   bmatchesr   ganions                            r   r   z,MDAnalysisInferrer._rebuild_conjugated_bonds  s   R %-$44==(u---$$$ $%@AA-3
 
 ,T
 
 DD3#:#:7#C#CDDD
 
	 >>F>> *KK
 +K	x s	 s	A--k::I <)2&B..v66	
 **,,11!1133q88**,,11!1133q88$-$:$:$<$< 
" 
""66"HOO$5$5    %1133q88 $ 8 8 : :a ? ? ,,T]-ABBB$44R888!E
 **,,22!1133q88$-$:$:$<$< " ""66"HOO$5$5    %1133q88 ( 8 8 : :b @ @ $ 8 8 : :a ? ? ,,T]-ABBB$44Q777!E --i.G.G.I.IA.MNNN &&v..!!!"3"3"5"5"9:::++FB77k!*?*?*A*AA*EFGGG++B33k!*?*?*A*AA*EFGGG++B77k!*?*?*A*AA*EFGGG''u'555 --g66G ,$ * *EE

AI~~ $)ME2r$$Q'''E (1,, '6)A-- //u/===#AJE$)ME2r!$UI$)$ &&u--!!!"3"3"5"5"9:::&&r**!!!"3"3"5"5"9:::++E266k!*?*?*A*AA*EFGGG++B33k!*?*?*A*AA*EFGGG''u'555 ? ?w ? ? ?@@	>>"1K ##5#111FF 	.	
 	
 	
 	
 	
r   r   r   r!   r   r   r   r!   NN)__name__
__module____qualname____doc__rF   r   r   r-   __annotations__rG   r   r   rI   rJ   boolrP   classmethodr
   r\   rL   staticmethodrY   r	   rM   r   r   r   r   r   r8   r8   x   s1         > : :htCH~6    	6 	6 	6xS	2 	 	 	 HcHd   & O Oc3h O O O [O V6 V6 V6 [V6p 4 4c 4 4 4 \4$ :>Z ZZ)1#Z	Z Z Z Zx .*+.7A.	. . . \.2 :>D
 D
D
)1#D
	D
 D
 D
 D
 D
 D
r   r8   c                   L    e Zd ZU dZded<   dZeed<   ddZ	 dddd
eddfdZ	dS )TemplateInferrera  Infer bond orders and charges by matching the molecule with a template
    molecule containing bond orders and charges.

    Attributes
    ----------
    template : rdkit.Chem.rdchem.Mol
        Molecule containing the bond orders and charges.
    adjust_hydrogens: bool, default = True
        If ``True``, temporarily removes hydrogens from the molecule to
        assign bond orders and charges from the template, then adds them
        back. Useful to avoid adding explicit hydrogens on the template which
        can prevent RDKit from finding a match between the template and the
        molecule. Setting this to ``False`` can be useful to speed things up
        for inorganic molecules that don't have any hydrogens.

    .. versionadded:: 2.10.0
    r   templateTadjust_hydrogensr   r!   c                 d    | j         r|                     |          S t          | j        |          S r   )r   ,assign_from_template_with_adjusted_hydrogensr   r   rN   s     r   rP   zTemplateInferrer.__call__  s4      	JDDSIII+DM3???r   r   index_fieldc                    t          j        |d          }t          | j        |          }t	          t
                    }|                                D ]`}|                                dk    rF||                                d         	                    |                   
                    |           ai }|                                D ]b}|	                    |          x}|v r2||         ||                                <   |                    d           |                    d           ct          j        |          }	|                                D ]E\  }
}|D ]=}|	                    |          }|	                    |
|t           j        j                   >F|	                                }|                                 t-          |           t/          ||          S )aZ  Temporarily removes hydrogens from the molecule before assigning
        bond orders and charges from the template, then adds them back.

        Parameters
        ----------
        mol : rdkit.Chem.rdchem.Mol
            Molecule to assign bond orders and charges to.
        index_field : str, default = "_MDAnalysis_index"
            Atom property corresponding to a unique integer that can used to
            put back the hydrogen atoms that were removed before matching,
            and sort them back to the original order. Must be accessible
            through ``atom.GetIntProp``.
        F)rJ   r   r   )r    )r   RemoveAllHsr   r   r   r   r*   rU   rX   r$   r   rv   SetNumExplicitHsrz   RWMolitemsAddAtomAddBondr   r   GetMolrs   r5   r2   )rO   r   r   mol_no_hnewatoms_with_hydrogensr%   reverse_mappingidxrwmolatom_idx	hydrogenshydrogenh_idxs                 r   r   z=TemplateInferrer.assign_from_template_with_adjusted_hydrogens  s   " #C%888*4=(CC*400LLNN 	 	D  ""a''$%%''*55kBB&,,, LLNN 	+ 	+D{3338LLL1Ec1J.%%a(((''****
3#2#8#8#:#: 	E 	EHi% E Eh//ht}/CDDDDE llnn!!!SS4444r   Nr   r   )
r   r   r   r   r   r   r   rP   r   r   r   r   r   r   r     s          $ !d!!!@ @ @ @ 3F/5 /5/5,//5	/5 /5 /5 /5 /5 /5r   r   c                   *    e Zd ZU dZdZeed<   d	dZdS )
RDKitInferrera  Uses RDKit's :func:`~rdkit.Chem.rdDetermineBonds.DetermineBondOrders`
    to infer bond orders and formal charges. This is the same algorithm used
    by the :ref:`xyz2mol <https://github.com/jensengroup/xyz2mol>` package.

    .. versionadded:: 2.10.0
    r   charger   r   r!   c                 Z    t          j        |          }t          || j                   |S )N)r   )r   Molr   r   )rO   r   r   s      r   rP   zRDKitInferrer.__call__  s)    hsmmC4444
r   Nr   )r   r   r   r   r   r-   r   rP   r   r   r   r   r     sC           FCOOO     r   r   r   r   )*r   r/   collectionsr   
contextlibr   dataclassesr   typingr   r   r   r	   r
   numpyr(   rx   ImportErrorrdkitr   rdkit.Chem.AllChemr   rdkit.Chem.rdChemReactionsr   r   r   r   AROMATICr   TRIPLEupdater   GetPeriodicTabler   rdkit.Chem.rdDetermineBondsr   r   r2   r5   r8   r   r   r   r   r   <module>r      sU  0& &P  # # # # # #       ! ! ! ! ! ! 8 8 8 8 8 8 8 8 8 8 8 8 8 8    Xk - -??????OOOOOOOO =]#m$== K NN+:K:K:M:MNNNOOO*T*,,N- - - - - - - - - - - - - - -  Xk                      #6 	   (   
 $C
 C
 C
 C
 C
 C
 C
 C
L $J5 J5 J5 J5 J5 J5 J5 J5Z $         s$   BCCC)C<<D D 