Taking atomic coordinates into account when doing MCS
Published
June 23, 2022
One of the “underdocumented”, and perhaps lesser known, features of the RDKit MCS code is the ability to take atomic coordinates into account when generating the MCS. The idea here is to find the MCS between a set of 3D molecules where the distance between potential matching atoms is taken into account.
You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension: jupyter labextension install jupyterlab_3dmol
Clip out the central ring and change one of the atoms to an N
m2 = Chem.RWMol(m1)keep = [6,7,12,13,24,25]remove =set(range(m2.GetNumAtoms())).difference(keep)m2.BeginBatchEdit()for aidx in remove: m2.RemoveAtom(aidx)m2.CommitBatchEdit()m2.GetAtomWithIdx(0).SetAtomicNum(7)m2
You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension: jupyter labextension install jupyterlab_3dmol
A normal MCS will, of course, match this to the N-containing ring:
# exported from the binding db and converted to SDF in pymolms = [x for x in Chem.ForwardSDMolSupplier('../data/1TDU-results.sdf')]ms2d = [Chem.Mol(x) for x in ms]for m in ms2d: rdDepictor.Compute2DCoords(m)IPythonConsole.drawOptions.addAtomIndices =FalseDraw.MolsToGridImage(ms2d)
You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension: jupyter labextension install jupyterlab_3dmol
matches = [x.GetSubstructMatch(qry) for x in ms2d]conf = Chem.Conformer(qry.GetNumAtoms())for i,mi inenumerate(matches[0]): conf.SetAtomPosition(i,ms2d[0].GetConformer().GetAtomPosition(mi))qry.AddConformer(conf)rdDepictor.SetPreferCoordGen(False) # coordgen doesn't always obey the scaffold, so switch to the RDKit coordinatesfor m in ms2d: rdDepictor.GenerateDepictionMatching2DStructure(m,qry)rdDepictor.SetPreferCoordGen(True)Draw.MolsToGridImage(ms2d,highlightAtomLists=matches)
matches = [x.GetSubstructMatch(qry) for x in ms2d]conf = Chem.Conformer(qry.GetNumAtoms())for i,mi inenumerate(matches[0]): conf.SetAtomPosition(i,ms2d[0].GetConformer().GetAtomPosition(mi))qry.AddConformer(conf)rdDepictor.SetPreferCoordGen(False) # coordgen doesn't always obey the scaffold, so switch to the RDKit coordinatesfor m in ms2d: rdDepictor.GenerateDepictionMatching2DStructure(m,qry)rdDepictor.SetPreferCoordGen(True)Draw.MolsToGridImage(ms2d,highlightAtomLists=matches)
This is an example where the constrained coordinates, which only match part of a ring system, cause problems.
Both of those MCS results are matching significant parts of the molecules, but we saw that the molecules didn’t actually align quite that well.
What about if we take atom coordinates into account?
matches = [x.GetSubstructMatch(qry) for x in ms2d]conf = Chem.Conformer(qry.GetNumAtoms())for i,mi inenumerate(matches[0]): conf.SetAtomPosition(i,ms2d[0].GetConformer().GetAtomPosition(mi))qry.AddConformer(conf)for m in ms2d: rdDepictor.GenerateDepictionMatching2DStructure(m,qry)Draw.MolsToGridImage(ms2d,highlightAtomLists=matches)
The MCS gave us a SMARTS which matches, but unfortunately it does not provide the matching atoms. Finding those via substructure search would be easy if we could assume that the MCS only matches each molecule once, but that’s not always going to be the case.
This is actually one of those examples.
Let’s look at how many times the core can match each of the molecules:
allMatches = []for m in ms: allMatches.append(m.GetSubstructMatches(qry,uniquify=False))allMatches
Now define a function which goes through all the possible substructure matches and finds the one which satisfies the 3D distance constraints on the core:
Let’s redraw the molecules in 3D and highlight the atoms involved in the MCS. It’s nice to see, plus I learned some stuff about how to use py3Dmol while doing it… so that’s a bonus. :-)
You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension: jupyter labextension install jupyterlab_3dmol