def remove_hs_from_mol(m): """ removes most Hs Hs that are preserved by the RDKit's Chem.RemoveHs() will not be removed. Additional exceptions: - Hs with a wedged/dashed bond to them - Hs bonded to atoms with tetrahedral stereochemistry set - Hs bonded to atoms that have three (or more) ring bonds that are not simply protonated - Hs bonded to atoms in a non-default valence state that are not simply protonated For the above, the definition of "simply protonated" is an atom with charge = +1 and a valence that is one higher than the default. """ # we need ring info, so be sure it's there (this won't do anything if the rings # have already been found) Chem.FastFindRings(m) if m.NeedsUpdatePropertyCache(): m.UpdatePropertyCache(strict=False) SENTINEL = 100 for atom in m.GetAtoms(): if atom.GetAtomicNum() == 1 and atom.GetDegree( ) == 1 and not atom.GetIsotope(): nbr = atom.GetNeighbors()[0] bnd = atom.GetBonds()[0] preserve = False if bnd.GetBondDir() in (Chem.BondDir.BEGINWEDGE, Chem.BondDir.BEGINDASH) or \ (bnd.HasProp("_MolFileBondStereo") and bnd.GetUnsignedProp("_MolFileBondStereo") in (1, 6)): preserve = True else: is_protonated = nbr.GetFormalCharge() == 1 and \ nbr.GetExplicitValence() == \ Chem.GetPeriodicTable().GetDefaultValence(nbr.GetAtomicNum())+1 if nbr.GetChiralTag() in (Chem.ChiralType.CHI_TETRAHEDRAL_CCW, Chem.ChiralType.CHI_TETRAHEDRAL_CW): preserve = True elif not is_protonated: if nbr.GetExplicitValence() > Chem.GetPeriodicTable( ).GetDefaultValence(nbr.GetAtomicNum()): preserve = True else: ringBonds = [ b for b in nbr.GetBonds() if m.GetRingInfo().NumBondRings(b.GetIdx()) ] if len(ringBonds) >= 3: preserve = True if preserve: # we're safe picking an arbitrary high value since you can't do this in a mol block: atom.SetIsotope(SENTINEL) res = Chem.RemoveHs(m, sanitize=False) for atom in res.GetAtoms(): if atom.GetAtomicNum() == 1 and atom.GetIsotope() == SENTINEL: atom.SetIsotope(0) return res
def smiles_to_fingerprint_bin(smiles, trust_smiles=False): mol = Chem.MolFromSmiles(smiles, sanitize=(not trust_smiles)) if mol is None: return None if trust_smiles: mol.UpdatePropertyCache() Chem.FastFindRings(mol) fp = rdMolDescriptors.GetMorganFingerprintAsBitVect(mol, 2, BITCOUNT) return DataStructs.BitVectToBinaryText(fp)
def _getRDKitEnv(mol, bondPath, baseRad, aromaticColor, extraColor, nonAromaticColor, **kwargs): if not mol.GetNumConformers(): rdDepictor.Compute2DCoords(mol) # get the atoms for highlighting atomsToUse = set() for b in bondPath: atomsToUse.add(mol.GetBondWithIdx(b).GetBeginAtomIdx()) atomsToUse.add(mol.GetBondWithIdx(b).GetEndAtomIdx()) # set the coordinates of the submol based on the coordinates of the original molecule amap = {} submol = Chem.PathToSubmol(mol, bondPath, atomMap=amap) Chem.FastFindRings(submol) conf = Chem.Conformer(submol.GetNumAtoms()) confOri = mol.GetConformer(0) for i1, i2 in amap.items(): conf.SetAtomPosition(i2, confOri.GetAtomPosition(i1)) submol.AddConformer(conf) envSubmol = [] for i1, i2 in amap.items(): for b in bondPath: beginAtom = amap[mol.GetBondWithIdx(b).GetBeginAtomIdx()] endAtom = amap[mol.GetBondWithIdx(b).GetEndAtomIdx()] envSubmol.append( submol.GetBondBetweenAtoms(beginAtom, endAtom).GetIdx()) # color all atoms of the submol in gray which are not part of the bit # highlight atoms which are in rings atomcolors, bondcolors = {}, {} highlightAtoms, highlightBonds = [], [] highlightRadii = {} for aidx in amap.keys(): if aidx in atomsToUse: color = None if aromaticColor and mol.GetAtomWithIdx(aidx).GetIsAromatic(): color = aromaticColor elif nonAromaticColor and not mol.GetAtomWithIdx( aidx).GetIsAromatic(): color = nonAromaticColor if color is not None: atomcolors[amap[aidx]] = color highlightAtoms.append(amap[aidx]) highlightRadii[amap[aidx]] = baseRad color = extraColor for bid in submol.GetBonds(): bidx = bid.GetIdx() if bidx not in envSubmol: bondcolors[bidx] = color highlightBonds.append(bidx) return FingerprintEnv(submol, highlightAtoms, atomcolors, highlightBonds, bondcolors, highlightRadii)
def smiles_to_fingerprint_bin(smiles, trust_smiles=False): mol = Chem.MolFromSmiles(smiles, sanitize=(not trust_smiles)) if mol is None: raise RuntimeError("Bad structure") if trust_smiles: mol.UpdatePropertyCache() Chem.FastFindRings(mol) fp = rdMolDescriptors.GetMorganFingerprintAsBitVect(mol, 2, BITCOUNT) canon_smiles = Chem.MolToSmiles(mol) canon_smiles = str.encode(canon_smiles) return DataStructs.BitVectToBinaryText(fp), canon_smiles
def normalize_mol(m): """ """ Chem.FastFindRings(m) if m.HasSubstructMatch(_alkoxide_pattern): m = Chem.RWMol(m) for match in m.GetSubstructMatches(_alkoxide_pattern): m.RemoveBond(match[0], match[1]) m.GetAtomWithIdx(match[0]).SetFormalCharge(1) m.GetAtomWithIdx(match[1]).SetFormalCharge(-1) res = _normalizer.normalize(m) return res
def _removeHs(data): mols = _parseMolData(data, loadMol=False, useRDKitChemistry=False) ms = [] for molblock in mols: mol = parse_molblock(molblock, useRDKitChemistry=False) props = molblock.split("M END")[1].strip() props = props if len(props) > 1 else None Chem.FastFindRings(mol) mol.UpdatePropertyCache(strict=False) Chem.AssignAtomChiralTagsFromStructure(mol) Chem.AssignStereochemistry(mol, cleanIt=True, force=True) ms.append((remove_hs_from_mol(mol), props)) return _getSDFString(ms)
def cleanup_drawing_mol(m): m = Chem.Mol(m) if not m.GetNumConformers(): # if we don't have a conformer, just return return m conf = m.GetConformer() if conf.Is3D(): for i in range(m.GetNumAtoms()): if abs(conf.GetAtomPosition(i).z) >= 0.0001: raise ValueError( "cleanup_drawing_mol() only works for 2D molecules") conf.Set3D(False) Chem.FastFindRings(m) _cleanup_triple_bonds(m) _cleanup_allenes(m) return m
def glyInMolID(hetIDs, id2SMILES): ''' Returns boolean if at least one ring in the molecule described by the provided string of heteroatom IDs meets the criteria of: Being non-aromatic, containing 4-9 atoms, with only one oxygen and the remaining atoms are carbons''' COset = set(['C', 'O']) out = False # Flag variable to record if a ring meets the above criteria for a glycan ids = hetIDs.split('-') for i in ids: smi = id2SMILES[i] m = Chem.MolFromSmiles( smi, sanitize=False ) # Create rdkit.Chem molecule objects from ligand SMILES, sanitize False to avoid valency errors Chem.FastFindRings(m) # Do a non-SSSR ring find ri = m.GetRingInfo() nRings = ri.NumRings() # Count rings in molecule if nRings == 0: continue # No rings detected, not likely a glycan else: for ring in ri.BondRings(): bondtypes = set([ str(m.GetBondWithIdx(idx).GetBondType()) for idx in ring ]) # Check the type of bonds the compsing the ring atmidxs = set() # Holds atom indices for atoms in each bond for idx in ring: # For each bond, get the bond index & the atom indices for the bond b = m.GetBondWithIdx(idx) atmidxs.add(b.GetBeginAtomIdx()) atmidxs.add(b.GetEndAtomIdx()) atms = [m.GetAtomWithIdx(ai).GetSymbol() for ai in atmidxs ] # convert set of atom indices to atom symbols if (4 <= len(atms) <= 9 and # Check atom count, bond types, only carbon/oxygen, & only one oxygen 'AROMATIC' not in bondtypes and set(atms) == COset and atms.count('O') == 1): out = True return out
def splitMol(self, mol, bondsToKeep): ''' fragments a molecule on a particular set of BRICS bonds. Partially sanitizes the results ''' bbnds = BRICS.FindBRICSBonds(mol) bndsToTry = [] lbls = [] for aids, lbl in bbnds: if lbl in bondsToKeep: bndsToTry.append(mol.GetBondBetweenAtoms( aids[0], aids[1]).GetIdx()) lbls.append([int(x) for x in lbl]) if not bndsToTry: return [] res = Chem.FragmentOnSomeBonds(mol, bndsToTry, dummyLabels=lbls) # We need at least a partial sanitization for the rest of what we will be doing: for entry in res: entry.UpdatePropertyCache(False) Chem.FastFindRings(entry) return res
def _molfromrequest(): # get errors on stderr: sio = sys.stderr = StringIO() tgt = request.get_json() if tgt is None: tgt = request.values sanitize = _stringtobool(tgt.get('sanitize', True)) removeHs = _stringtobool(tgt.get('removeHs', True)) asSmarts = _stringtobool(tgt.get('asSmarts', False)) asRxn = _stringtobool(tgt.get('asRxn', False)) isMol = True if 'smiles' in tgt: if asRxn: mol = AllChem.ReactionFromSmarts(tgt.get('smiles'), useSmiles=not asSmarts) elif asSmarts: mol = Chem.MolFromSmarts(tgt.get('smiles')) sanitize = False else: mol = Chem.MolFromSmiles(tgt.get('smiles'), sanitize=sanitize) elif 'mol' in tgt: mol = Chem.MolFromMolBlock(tgt.get('mol'), sanitize=sanitize, removeHs=removeHs) else: raise InvalidUsage("Neither 'smiles' nor 'mol' present.", status_code=410) if mol is None: errm = sio.getvalue() # some errors leave blank lines errm = errm.replace('RDKit ERROR: \n', '') raise InvalidUsage( "Molecule could not be processed. Error message was:\n%s" % errm, status_code=411) if not sanitize and not asRxn: mol.UpdatePropertyCache(False) Chem.FastFindRings(mol) Chem.SetConjugation(mol) Chem.SetHybridization(mol) return mol
def DrawFgEnv(mol, subMol, molSize=(150, 150)): """Get the SVG image of funtion group fragment Parameters ---------- mol : rdkit.Chem.rdchem.Mol The molecule which contain the aim fragment subMol : str Fragment in fragment format Returns ------- svg : str The svg string of fragment """ if not mol.GetNumConformers(): rdDepictor.Compute2DCoords(mol) subMolDic[subMol] = Chem.MolFromSmarts(subMol) try: atomToUsed = mol.GetSubstructMatch(subMolDic[subMol]) amap = {} submol = Chem.PathToSubmol(mol, atomToUsed, atomMap=amap) Chem.FastFindRings(submol) conf = Chem.Conformer(submol.GetNumAtoms()) confOri = mol.GetConformer(0) for i1, i2 in amap.items(): conf.SetAtomPosition(i2, confOri.GetAtomPosition(i1)) submol.AddConformer(conf) except: submol = mol drawer = rdMolDraw2D.MolDraw2DSVG(molSize[0], molSize[1]) drawopt = drawer.drawOptions() drawopt.continuousHighlight = False drawer.DrawMolecule(submol) drawer.FinishDrawing() svg = drawer.GetDrawingText().replace('\n', '') return svg
def _getMorganEnv(mol, atomId, radius, baseRad, aromaticColor, ringColor, centerColor, extraColor, **kwargs): if not mol.GetNumConformers(): rdDepictor.Compute2DCoords(mol) bitPath = Chem.FindAtomEnvironmentOfRadiusN(mol, radius, atomId) # get the atoms for highlighting atomsToUse = set((atomId, )) for b in bitPath: atomsToUse.add(mol.GetBondWithIdx(b).GetBeginAtomIdx()) atomsToUse.add(mol.GetBondWithIdx(b).GetEndAtomIdx()) # enlarge the environment by one further bond enlargedEnv = set() for atom in atomsToUse: a = mol.GetAtomWithIdx(atom) for b in a.GetBonds(): bidx = b.GetIdx() if bidx not in bitPath: enlargedEnv.add(bidx) enlargedEnv = list(enlargedEnv) enlargedEnv += bitPath # set the coordinates of the submol based on the coordinates of the original molecule amap = {} submol = Chem.PathToSubmol(mol, enlargedEnv, atomMap=amap) Chem.FastFindRings(submol) conf = Chem.Conformer(submol.GetNumAtoms()) confOri = mol.GetConformer(0) for i1, i2 in amap.items(): conf.SetAtomPosition(i2, confOri.GetAtomPosition(i1)) submol.AddConformer(conf) envSubmol = [] for i1, i2 in amap.items(): for b in bitPath: beginAtom = amap[mol.GetBondWithIdx(b).GetBeginAtomIdx()] endAtom = amap[mol.GetBondWithIdx(b).GetEndAtomIdx()] envSubmol.append( submol.GetBondBetweenAtoms(beginAtom, endAtom).GetIdx()) # color all atoms of the submol in gray which are not part of the bit # highlight atoms which are in rings atomcolors, bondcolors = {}, {} highlightAtoms, highlightBonds = [], [] highlightRadii = {} for aidx in amap.keys(): if aidx in atomsToUse: color = None if centerColor and aidx == atomId: color = centerColor elif aromaticColor and mol.GetAtomWithIdx(aidx).GetIsAromatic(): color = aromaticColor elif ringColor and mol.GetAtomWithIdx(aidx).IsInRing(): color = ringColor if color is not None: atomcolors[amap[aidx]] = color highlightAtoms.append(amap[aidx]) highlightRadii[amap[aidx]] = baseRad else: #drawopt.atomLabels[amap[aidx]] = '*' submol.GetAtomWithIdx(amap[aidx]).SetAtomicNum(0) submol.GetAtomWithIdx(amap[aidx]).UpdatePropertyCache() color = extraColor for bid in submol.GetBonds(): bidx = bid.GetIdx() if bidx not in envSubmol: bondcolors[bidx] = color highlightBonds.append(bidx) return FingerprintEnv(submol, highlightAtoms, atomcolors, highlightBonds, bondcolors, highlightRadii)
if (len(bis) > 12): bis = bis[0:2] for Beg, End in bis: b = [AMol.GetBondBetweenAtoms(Beg, End).GetIdx()] m = Chem.FragmentOnBonds(AMol, b, addDummies=False) m.UpdatePropertyCache(strict=False) AllChem.Cleanup(m) AllChem.SetAromaticity(m) Chem.SanitizeMol(m, (Chem.SanitizeFlags.SANITIZE_ADJUSTHS | Chem.SanitizeFlags.SANITIZE_SYMMRINGS)) Chem.SanitizeMol( m, sanitizeOps=Chem.SanitizeFlags.SANITIZE_ALL ^ Chem.SanitizeFlags.SANITIZE_KEKULIZE) m.UpdatePropertyCache(strict=False) Chem.FastFindRings(m) AllChem.Cleanup(m) AllChem.SetAromaticity(m) Chem.SetHybridization(m) # m = Chem.RemoveHs(m) AList.append(m) MyMolList.extend(AList) uniqps = {} for p in MyMolList: # smi = Chem.MolToSmiles(Chem.RemoveHs(Chem.AddHs(p))) smi = Chem.MolToSmiles(p) uniqps[smi] = p MyMolList = uniqps.values() print len(MyMolList)
def DrawRDKitEnv(mol, bondPath, molSize=(150, 150), baseRad=0.3, useSVG=True, aromaticColor=(0.9, 0.9, 0.2), extraColor=(0.9, 0.9, 0.9), nonAromaticColor=None, **kwargs): if not mol.GetNumConformers(): rdDepictor.Compute2DCoords(mol) # get the atoms for highlighting atomsToUse = set() for b in bondPath: atomsToUse.add(mol.GetBondWithIdx(b).GetBeginAtomIdx()) atomsToUse.add(mol.GetBondWithIdx(b).GetEndAtomIdx()) # set the coordinates of the submol based on the coordinates of the original molecule amap = {} submol = Chem.PathToSubmol(mol, bondPath, atomMap=amap) Chem.FastFindRings(submol) conf = Chem.Conformer(submol.GetNumAtoms()) confOri = mol.GetConformer(0) for i1, i2 in amap.items(): conf.SetAtomPosition(i2, confOri.GetAtomPosition(i1)) submol.AddConformer(conf) envSubmol = [] for i1, i2 in amap.items(): for b in bondPath: beginAtom = amap[mol.GetBondWithIdx(b).GetBeginAtomIdx()] endAtom = amap[mol.GetBondWithIdx(b).GetEndAtomIdx()] envSubmol.append( submol.GetBondBetweenAtoms(beginAtom, endAtom).GetIdx()) # Drawing if useSVG: drawer = rdMolDraw2D.MolDraw2DSVG(molSize[0], molSize[1]) else: drawer = rdMolDraw2D.MolDraw2DCairo(molSize[0], molSize[1]) drawopt = drawer.drawOptions() drawopt.continuousHighlight = False # color all atoms of the submol in gray which are not part of the bit # highlight atoms which are in rings atomcolors, bondcolors = {}, {} highlightAtoms, highlightBonds = [], [] highlightRadii = {} for aidx in amap.keys(): if aidx in atomsToUse: color = None if aromaticColor and mol.GetAtomWithIdx(aidx).GetIsAromatic(): color = aromaticColor elif nonAromaticColor and not mol.GetAtomWithIdx( aidx).GetIsAromatic(): color = nonAromaticColor if color is not None: atomcolors[amap[aidx]] = color highlightAtoms.append(amap[aidx]) highlightRadii[amap[aidx]] = baseRad color = extraColor for bid in submol.GetBonds(): bidx = bid.GetIdx() if bidx not in envSubmol: bondcolors[bidx] = color highlightBonds.append(bidx) drawer.DrawMolecule(submol, highlightAtoms=highlightAtoms, highlightAtomColors=atomcolors, highlightBonds=highlightBonds, highlightBondColors=bondcolors, highlightAtomRadii=highlightRadii, **kwargs) drawer.FinishDrawing() return drawer.GetDrawingText()