Source code for schrodinger.rdkit.coarsegrain

"""
Conversions between Coarse-grained Schrodinger structure objects (mmct) and
RDKit mol objects.

Please see schrodinger.rdkit_adapter for structural/philosophic differences
between these two formats
"""

from rdkit import Chem

from schrodinger.infra import mm
from schrodinger.application.matsci import msutils
from schrodinger.thirdparty import rdkit_adapter

SDGR_INDEX = rdkit_adapter.adapter.SCHRODINGER_INDEX


# Each CG particle name is mapped to an element name. These atoms are used to
# generate RDKIT mol for CG system.
[docs]def get_cgparticle_to_element_mapper(cg_particle_names): """ Create a mapper between coarse-grain particle name and an element. :type cg_particle_names: list :param cg_particle_names: list of CG particle names :rtype: dict :return: dict with CG particle name as key and element name as value """ periodic_table = Chem.rdchem.GetPeriodicTable() proxy_element = [ periodic_table.GetElementSymbol(atomic_num) for atomic_num in range(1, 118) if periodic_table.GetDefaultValence(atomic_num) == -1 ] # remove CG bead names from the proxy element due to possible conflict # between two names. for aname in cg_particle_names: try: proxy_element.remove(aname) except ValueError: continue if len(cg_particle_names) > len(proxy_element): raise RuntimeError( f"Cannot have more than {len(proxy_element)} unique particle names") # Create a mapper between schrodinger CG particle name and new element # name for rdkit mol mapper = { particle_name: proxy_element_name for particle_name, proxy_element_name in zip( cg_particle_names, proxy_element) } return mapper
[docs]def get_map_sdgr_to_rdk(mol): """ Get a dict mapping schrodinger atoms index to rdkit atom index :type mol: `rdkit.Mol` :param mol: rdkit molecule for which mapping is desired :rtype: dict :return: dict with key as schrodinger atom index and rdkit atoms index as value """ return {a.GetIntProp(SDGR_INDEX): a.GetIdx() for a in mol.GetAtoms()}
def _coarsegrain_st_to_rdkit(st): """ Create RDKIT mol object from a coarse-grained structure :type st: `schrodinger.structure.Structure` :param st: structure :raise: rdkit_adapter.adapter.InconsistentStructureError :rtype: `rdkit.Mol`, dict :return: rdkit molecule and internal mapping dict between schrodinger particle name and rdkit proxy element name """ # an atomistic structure, raise error if not msutils.is_coarse_grain(st, by_atom=True): raise rdkit_adapter.adapter.InconsistentStructureError( "_coarsegrain_st_to_rdk_mol only supports coarse-grained " "structures. Please see rdkit_adapter.to_rdkit function") st = st.copy() msutils.remove_atom_property(st, prop=mm.MMCT_ATOM_PROPERTY_COARSE_GRAIN) particle_name = sorted(set(atom.name for atom in st.atom)) proxy_element_mapper = get_cgparticle_to_element_mapper(particle_name) for atom in st.atom: atom.element = proxy_element_mapper[atom.name] mol = rdkit_adapter.to_rdkit(st, sanitize=False) # reset name of rd_mol for atom in mol.GetAtoms(): st_idx = atom.GetIntProp(SDGR_INDEX) st_atom = st.atom[st_idx] atom.name = st_atom.name atom.SetProp('smilesSymbol', st_atom.name) atom.SetNoImplicit(True) mol.UpdatePropertyCache(strict=False) return mol, proxy_element_mapper
[docs]def get_coarsegrain_smiles(st, atom_ids=None): """ Get smiles for coarse-grained structure :type st: `schrodinger.structure.Structure` :param st: structure :type atom_ids: list :param atom_ids: list of substructure atom id :return: str :rtype: smiles for coarse grain substructure """ mol, _ = _coarsegrain_st_to_rdkit(st) if not atom_ids: return Chem.MolToSmiles(mol) sdgr_to_rdk_idx = get_map_sdgr_to_rdk(mol) rdk_atom_ids = [sdgr_to_rdk_idx[idx] for idx in atom_ids] return Chem.MolFragmentToSmiles(mol, rdk_atom_ids)