In [4]:
from rdkit import Chem
from rdkit.Chem import AllChem
from rdkit import RDConfig
from rdkit.Chem.Draw import IPythonConsole 
from rdkit.Chem import Draw
import numpy as np
from IPython.display import display,Image
RDKit WARNING: [17:12:53] Enabling RDKit 2019.09.3 jupyter extensions

Итак, ибупрофен:

In [5]:
ibu=Chem.MolFromSmiles('CC(C)CC1=CC=C(C=C1)C(C)C(=O)O')
AllChem.Compute2DCoords(ibu)
display(ibu)

Посчитаем параметры для правила Лепински и напишем функцию, определяющую, отвечает ли молекула этим правилам.

In [30]:
import rdkit.Chem.Lipinski as Lipinksy
print (Lipinksy.NumHDonors(ibu))
print (Lipinksy.NumHAcceptors(ibu))
print (Lipinksy.rdMolDescriptors.CalcExactMolWt(ibu))
print (Lipinksy.rdMolDescriptors.CalcCrippenDescriptors(ibu)[0])
1
1
206.130679816
3.073200000000001
In [31]:
def lipinsky(smiles):
    return (Lipinksy.NumHDonors(smiles),
            Lipinksy.NumHAcceptors(smiles),
            Lipinksy.rdMolDescriptors.CalcExactMolWt(smiles),
            Lipinksy.rdMolDescriptors.CalcCrippenDescriptors(smiles)[0])


def is_lipinsky(smiles, parameters=(5, 10, 500, 5)):
    return all(i < j for i, j in zip(lipinsky(smiles), parameters))
In [32]:
is_lipinsky(ibu)
Out[32]:
True

Займемся скачиванием азидов

In [1]:
import pubchempy as pcp
In [2]:
compounds = []
per_page = 1000
for smiles in ["N=[N+]=[N-]", "N=N=N", "NN#N"]:
    for i in range(2):
        try:
            a = pcp.get_properties(properties="CanonicalSMILES", identifier=smiles, namespace="smiles", searchtype="substructure", RingsNotEmbedded=True, listkey_count=per_page, listkey_start=i*per_page)
        except:
            print ('oh')
        print ("Retrieved page {} of {} search".format(i+1, smiles))
        compounds.extend(a)
Retrieved page 1 of N=[N+]=[N-] search
Retrieved page 2 of N=[N+]=[N-] search
Retrieved page 1 of N=N=N search
Retrieved page 2 of N=N=N search
Retrieved page 1 of NN#N search
Retrieved page 2 of NN#N search

Думаю, этого хватит.

In [17]:
smiles_list = [k['CanonicalSMILES'] for k in compounds] # просто поглядеть
smiles_list[:10]
Out[17]:
['CC(=O)OCC1C(C(C(C(O1)OC2C(C(OC3C2OC(OC3)C4=CC=CC=C4)OC5=CC=C(C=C5)OC)N=[N+]=[N-])OC(=O)C)OC(=O)C)OC(=O)C',
 'CC(=O)OCC1C(C(C(C(O1)OC2C(C(OC3C2OC(OC3)C4=CC=CC=C4)OC5=CC=C(C=C5)OC)N=[N+]=[N-])OC(=O)C)OC(=O)C)OC(=O)C',
 'CC(=O)OCC(=O)NC1C(CC(OC1C(C(CN=[N+]=[N-])OC(=O)C)OC(=O)C)(C(=O)OC)SC2=CC=CC=C2)OC(=O)C',
 'CC(=O)NC1C(CC(OC1C(C(CN=[N+]=[N-])OC(=O)C)OC(=O)C)(C(=O)OC)SC2=CC=CC=C2)OC(=O)C',
 'CC(C)(C)OC(=O)N1C2CCCC2CC1CN=[N+]=[N-]',
 'CC(C)(C)OC(=O)N1C2CCCCC2CC1CN=[N+]=[N-]',
 'CC(C)(C)OC(=O)N1CC(C(C1)S(=O)(=O)C)N=[N+]=[N-]',
 'COC(=O)C(CC1=C(C=C(C=C1)N=[N+]=[N-])F)N',
 'COC(=O)C(CC1=C(C=C(C=C1)N=[N+]=[N-])F)N.Cl',
 'C(C#N)C(CN=[N+]=[N-])O']

Сохранила азиды в json и научилась извлекать оттуда на всякий случай (ох как помогло)

In [ ]:
import json
with open('./term8/compounds.json', 'w') as f:
    json.dump(compounds, f)
In [16]:
with open('compounds.json', 'r', encoding='utf-8') as f:
    compounds = json.load(f)
    print(compounds[0]) # поглядели
{'CID': 155859234, 'CanonicalSMILES': 'CC(=O)OCC1C(C(C(C(O1)OC2C(C(OC3C2OC(OC3)C4=CC=CC=C4)OC5=CC=C(C=C5)OC)N=[N+]=[N-])OC(=O)C)OC(=O)C)OC(=O)C'}

Прикинем template для эмуляции продукта Click Chemistry.

In [22]:
template = 'N1N=NC(=C1)C(C)(C(=O)O)C1=CC=C(C=C1)CC(C)C'
template_mol = Chem.MolFromSmiles('N1N=NC(=C1)C(C)(C(=O)O)C1=CC=C(C=C1)CC(C)C')
AllChem.Compute2DCoords(template_mol)
display(template_mol)

Пстроим новые smiles, затем молекулы; и отфильтруем

In [28]:
new_smiles = []

for smi in smiles_list:
    for a in ["N=[N+]=[N-]", "N=N=N", "NN#N"]:
        if a in smi:
            newsmi=smi.replace(a, template)
            new_smiles.append(newsmi)
        else:
            continue
In [29]:
len(new_smiles)
Out[29]:
4005
In [45]:
good_mol = []

for smi in new_smiles:
    try:
        newmol=Chem.MolFromSmiles(smi)
        if is_lipinsky(newmol) == True:
            good_mol.append(newmol)
            #display(newmol)
    except:
        pass
len(good_mol)
RDKit ERROR: [22:13:41] Explicit valence for atom # 8 Cl, 3, is greater than permitted
RDKit ERROR: [22:13:44] Explicit valence for atom # 8 Cl, 3, is greater than permitted
Out[45]:
460

Итого получилось 4005 smiles потенциальных азидных аналогов ибупрофена, из которых 460 удовлетворяют правилу Липински.

Изобразим первые 12 получившихся адекватных молекул.

In [50]:
from IPython.display import SVG

for mol in good_mol:
    AllChem.Compute2DCoords(mol)
display(Draw.MolsToGridImage(good_mol[:12],useSVG=True, molsPerRow=3, subImgSize=(300, 300)))
O O N N N O OH F NH2 N N N N O OH OH N N N N O OH O O O O N N N O HO NH N N N O OH HCl S O O N N N O OH O N N N O OH OH O O O N N N O OH N O O N N N O OH O O N N N N O OH H2N S N N N O OH O O N S N N N O HO

Теперь изобразим Similiraty Map ибупрофена с пятым веществом из нашего массива.

In [46]:
from rdkit.Chem.Draw import SimilarityMaps

fp = SimilarityMaps.GetMorganFingerprint(good_mol[4], fpType='bv')

fig, maxweight = SimilarityMaps.GetSimilarityMapForFingerprint(ibu, good_mol[4], SimilarityMaps.GetMorganFingerprint)

Построим 3D структуру.

In [47]:
m3d=Chem.AddHs(good_mol[4])
Chem.AllChem.EmbedMolecule(m3d)
AllChem.MMFFOptimizeMolecule(m3d,maxIters=500,nonBondedThresh=200 )
m3d
Out[47]:

И даже покрутим! (но не в html)

In [48]:
import nglview as nv
In [49]:
nv.show_rdkit(m3d)

До чего техника дошла...