def detect_metals(mol, *args, **kwargs): """Detects metals. Generates a SMILES out of the entered mol for validation, performs metal disconnection, turns the changed mol into another SMILES and validates it with the first SMILES created. Parameters ---------- mol: rdkit.Chem.Mol The molecule which has to be searched for metal substructures. Returns ------- boolean: bool Returns if the stucture contains a metal (True), or not (False). """ smiles_before = _validation_smiles(mol) mol_without_metal = rdMolStandardize.MetalDisconnector().Disconnect(mol) smiles_after = _validation_smiles(mol_without_metal) if smiles_before == smiles_after: return False else: return True
def graph_corpus(input, output, suffix='sdf'): metals = {'Na', 'Zn', 'Li', 'K', 'Ca', 'Mg', 'Ag', 'Cs', 'Ra', 'Rb', 'Al', 'Sr', 'Ba', 'Bi'} voc = utils.VocGraph('data/voc_atom.txt') inf = gzip.open(input) if suffix == 'sdf': mols = Chem.ForwardSDMolSupplier(inf) total = 2e6 else: mols = pd.read_table(input).drop_duplicates(subset=['Smiles']).dropna(subset=['Smiles']) total = len(mols) mols = mols.iterrows() vals = {} exps = {} codes, ids = [], [] chooser = rdMolStandardize.LargestFragmentChooser() disconnector = rdMolStandardize.MetalDisconnector() normalizer = rdMolStandardize.Normalizer() for i, mol in enumerate(tqdm(mols, total=total)): if mol is None: continue if suffix != 'sdf': idx = mol[1]['Molecule ChEMBL ID'] mol = Chem.MolFromSmiles(mol[1].Smiles) else: idx = mol.GetPropsAsDict() idx = idx['chembl_id'] try: mol = disconnector.Disconnect(mol) mol = normalizer.normalize(mol) mol = chooser.choose(mol) mol = disconnector.Disconnect(mol) mol = normalizer.normalize(mol) except: print(idx) symb = [a.GetSymbol() for a in mol.GetAtoms()] # Nr. of the atoms bonds = mol.GetBonds() if len(bonds) < 4 or len(bonds) >= 63: continue if {'C'}.isdisjoint(symb): continue if not metals.isdisjoint(symb): continue smile = Chem.MolToSmiles(mol) try: s0 = smile.replace('[O]', 'O').replace('[C]', 'C') \ .replace('[N]', 'N').replace('[B]', 'B') \ .replace('[2H]', '[H]').replace('[3H]', '[H]') s0 = Chem.CanonSmiles(s0, 0) code = voc.encode([smile]) s1 = voc.decode(code)[0] assert s0 == s1 codes.append(code[0].reshape(-1).tolist()) ids.append(idx) except Exception as ex: print(ex) print('Parse Error:', idx) df = pd.DataFrame(codes, index=ids, columns=['C%d' % i for i in range(64*4)]) df.to_csv(output, sep='\t', index=True) print(vals) print(exps)
def corpus(input, output, suffix='sdf'): if suffix =='sdf': inf = gzip.open(input) mols = Chem.ForwardSDMolSupplier(inf) # mols = [mol for mol in suppl] else: df = pd.read_table(input).Smiles.dropna() mols = [Chem.MolFromSmiles(s) for s in df] voc = Voc('data/voc_smiles.txt') charger = rdMolStandardize.Uncharger() chooser = rdMolStandardize.LargestFragmentChooser() disconnector = rdMolStandardize.MetalDisconnector() normalizer = rdMolStandardize.Normalizer() words = set() canons = [] tokens = [] smiles = set() for mol in tqdm(mols): try: mol = disconnector.Disconnect(mol) mol = normalizer.normalize(mol) mol = chooser.choose(mol) mol = charger.uncharge(mol) mol = disconnector.Disconnect(mol) mol = normalizer.normalize(mol) smileR = Chem.MolToSmiles(mol, 0) smiles.add(Chem.CanonSmiles(smileR)) except: print('Parsing Error:') #, Chem.MolToSmiles(mol)) for smile in tqdm(smiles): token = voc.split(smile) + ['EOS'] if {'C', 'c'}.isdisjoint(token): print('Warning:', smile) continue if not {'[Na]', '[Zn]'}.isdisjoint(token): print('Redudent', smile) continue if 10 < len(token) <= 100: words.update(token) canons.append(smile) tokens.append(' '.join(token)) log = open(output + '_voc.txt', 'w') log.write('\n'.join(sorted(words))) log.close() log = pd.DataFrame() log['Smiles'] = canons log['Token'] = tokens log.drop_duplicates(subset='Smiles') log.to_csv(output + '_corpus.txt', sep='\t', index=False)
def test5Metal(self): mol = Chem.MolFromSmiles("C1(CCCCC1)[Zn]Br") md = rdMolStandardize.MetalDisconnector() nm = md.Disconnect(mol) # Metal.MetalDisconnector.Disconnect(mol) self.assertEqual(Chem.MolToSmiles(nm), "[Br-].[CH-]1CCCCC1.[Zn+2]") # test user defined metal_nof md.SetMetalNof( Chem.MolFromSmarts( "[Li,K,Rb,Cs,Fr,Be,Mg,Ca,Sr,Ba,Ra,Sc,Ti,V,Cr,Mn,Fe,Co,Ni,Cu,Zn,Al,Ga,Y,Zr,Nb,Mo,Tc,Ru,Rh,Pd,Ag,Cd,In,Sn,Hf,Ta,W,Re,Os,Ir,Pt,Au,Hg,Tl,Pb,Bi]~[N,O,F]" )) mol2 = Chem.MolFromSmiles("CCC(=O)O[Na]") nm2 = md.Disconnect(mol2) self.assertEqual(Chem.MolToSmiles(nm2), "CCC(=O)O[Na]")
def standardize_mol( mol: Chem.rdchem.Mol, disconnect_metals: bool = False, normalize: bool = True, reionize: bool = True, uncharge: bool = False, stereo: bool = True, ): r""" This function returns a standardized version the given molecule, with or without disconnect the metals. The process is apply in the order of the argument. Arguments: mol: The molecule to standardize. disconnect_metals: Whether to disconnect the metallic atoms from non-metals normalize: Whether to apply normalization (correct functional groups and recombine charges). reionize: Whether to apply molecule reionization uncharge: Whether to remove all charge from molecule stereo: Whether to attempt to assign stereochemistry Returns: mol: The standardized molecule. """ mol = copy_mol(mol) if disconnect_metals: md = rdMolStandardize.MetalDisconnector() mol = md.Disconnect(mol) if normalize: mol = rdMolStandardize.Normalize(mol) if reionize: reionizer = rdMolStandardize.Reionizer() mol = reionizer.reionize(mol) if uncharge: uncharger = rdMolStandardize.Uncharger() mol = uncharger.uncharge(mol) if stereo: Chem.AssignStereochemistry(mol, force=False, cleanIt=True) return mol
def standardize_mol(mol): """ Standardize molecule. Parameters ---------- mol : rdkit.Chem.rdchem.Mol Molecule. Returns ------- rdkit.Chem.rdchem.Mol or None Standardized molecule or None if standardization failed. """ try: # sanitize molecule Chem.SanitizeMol(mol) # remove non-explicit hydrogens mol = Chem.RemoveHs(mol) # disconnect metals from molecule mol = rdMolStandardize.MetalDisconnector().Disconnect(mol) # normalize moleucle mol = rdMolStandardize.Normalize(mol) # reionize molecule mol = rdMolStandardize.Reionize(mol) # uncharge molecule (this helps to standardize protonation states) u = rdMolStandardize.Uncharger() mol = u.uncharge(mol) # assign stereochemistry Chem.AssignStereochemistry(mol, force=True, cleanIt=True) return mol except Exception as e: print(f"ERROR in standardization: {e}") return None
def my_standardizer(mol: Chem.Mol) -> Chem.Mol: """ MolVS implementation of standardization Args: mol (Chem.Mol): non-standardized rdkit mol object Returns: Chem.Mol: stndardized rdkit mol object """ mol = copy.deepcopy(mol) Chem.SanitizeMol(mol) mol = Chem.RemoveHs(mol) disconnector = rdMolStandardize.MetalDisconnector() mol = disconnector.Disconnect(mol) normalizer = rdMolStandardize.Normalizer() mol = normalizer.normalize(mol) reionizer = rdMolStandardize.Reionizer() mol = reionizer.reionize(mol) Chem.AssignStereochemistry(mol, force=True, cleanIt=True) # TODO: Check this removes symmetric stereocenters return mol
r = SaltRemover() molecule_column = input_table['Molecule'] # Input from KNIME table stand_mol_list = [] errs = [] mixture = "No" for index, input_cell in molecule_column.iteritems( ): # iterate through molecule list mol = input_cell if mol is None: stand_mol_list.append( ("Got empty molecule", index, mol, "No", None, None)) continue try: mol = rdMolStandardize.MetalDisconnector().Disconnect( mol) # Disconnect metals except ValueError as e: if len(Chem.GetMolFrags(mol, asMols=True, sanitizeFrags=False)) > 1: mixture = "Yes" stand_mol_list.append( ("Failed at disconnect", index, None, mixture, None, str(e))) continue mol = r.StripMol(mol) # Check if we have multiple fragments present if len(Chem.GetMolFrags(mol, asMols=True, sanitizeFrags=False)) > 1: mixture = "Yes" else: mixture = "No"