Хемоинформатика

В этом практикуме мы будем искать аналоги ибупрофена.

In [1]:
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
In [2]:
ibu=Chem.MolFromSmiles('CC(C)CC1=CC=C(C=C1)C(C)C(=O)O')
AllChem.Compute2DCoords(ibu)
display(ibu)

Так выглядит ибупрофен. Посчитаем параметры для правила Липински:

In [3]:
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.0732

Ибупрофен удовлетворяет правилу пяти Липински. Сделаем функцию для проверки этого правила для будущих аналогов ибупрофена:

In [4]:
def checkLip(molecule): 
    return bool((Lipinksy.NumHDonors(molecule) <= 5) and (Lipinksy.NumHAcceptors(molecule) <= 10) \
    and (Lipinksy.rdMolDescriptors.CalcExactMolWt(molecule) < 500) \
    and(Lipinksy.rdMolDescriptors.CalcCrippenDescriptors(molecule)[0]) <= 5)
In [5]:
checkLip(ibu)
Out[5]:
True

Мы будем искать аналоги, имитируя реакцию Click-химии. В ней изначально участвуют 2 вещества: одно с терминальной алкильной группой, другое - с терминальным азидом. А продуктом является вещество с двойной связью и азидом в цикле. Мы не можем провести реакцию in silico, но можем сымитировать ее, подставив азид в цикл ибупрофена, а потом заменим эту азидную часть на азид + довесок веществ, найденных в PubChem, и таким образом сделаем что-то похожее на ибупрофен.

Сначала модифицируем ибупрофен. Выберем место для модицикации:

In [6]:
ibu2=Chem.MolFromSmiles('C(C#C)C(C)CC1=CC=C(C=C1)C(C)C(=O)O')
AllChem.Compute2DCoords(ibu2)
display(ibu2)
In [6]:
ibu3=Chem.MolFromSmiles('CC(C)CC1=CC=C(C=C1)C(C(C#C))C(=O)O')
AllChem.Compute2DCoords(ibu3)
display(ibu3)
In [17]:
ibu4=Chem.MolFromSmiles('CC(C#C)(C)CC1=CC=C(C=C1)C(C)C(=O)O')
AllChem.Compute2DCoords(ibu4)
display(ibu4)
In [7]:
ibu5=Chem.MolFromSmiles('CC(C)C(C#C)C1=CC=C(C=C1)C(C)C(=O)O')
AllChem.Compute2DCoords(ibu5)
display(ibu5)

Мне нравится последний вариант, будем модифицировать его.

In [7]:
ibu_mod = Chem.MolFromSmiles('N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2')
AllChem.Compute2DCoords(ibu_mod)
display(ibu_mod)
checkLip(ibu_mod)
Out[7]:
True

Дальше был проведен поиск по PubChem структур веществ, у которых есть терминальная азидная группировка. Нашлось 143075 соединений, они были сохранены в файл 3893474530663651931.txt.

In [27]:
! wget ftp://ftp-private.ncbi.nlm.nih.gov/pubchem/.fetch/88/3893474530663651931.txt
--2018-05-19 00:36:57--  ftp://ftp-private.ncbi.nlm.nih.gov/pubchem/.fetch/88/3893474530663651931.txt
           => `3893474530663651931.txt'
Resolving ftp-private.ncbi.nlm.nih.gov... 130.14.29.30
Connecting to ftp-private.ncbi.nlm.nih.gov|130.14.29.30|:21... connected.
Logging in as anonymous ... Logged in!
==> SYST ... done.    ==> PWD ... done.
==> TYPE I ... done.  ==> CWD (1) /pubchem/.fetch/88 ... done.
==> SIZE 3893474530663651931.txt ... 11961031
==> PASV ... done.    ==> RETR 3893474530663651931.txt ... done.
Length: 11961031 (11M) (unauthoritative)

100%[======================================>] 11,961,031  2.66M/s   in 4.3s    

2018-05-19 00:37:04 (2.66 MB/s) - `3893474530663651931.txt' saved [11961031]

In [8]:
strings = np.genfromtxt('3893474530663651931.txt', dtype=np.str)
smiles = []
for line in strings:
    if (len(line[1]) < 30) and (len(line[1]) > 10) and not ( '.' in line[1]):
        smiles.append(line[1])

print len(smiles)
12194

Теперь сымитируем клик-реакцию:

In [9]:
good_analogs = []
ibu_mod = 'N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2'
# Новую молекулу лучше создавать в try из-за битых  Smiles:
for smi in smiles:
    try:
        if not "N=[N+]=[N-]" in smi:
            continue
        newsmi = smi.replace("N=[N+]=[N-]", ibu_mod)
        if checkLip(Chem.MolFromSmiles(newsmi)):
            good_analogs.append(newsmi)
    except Exception:
        pass   
len(good_analogs)
RDKit ERROR: [21:13:57] SMILES Parse Error: extra open parentheses for input: 'CC(C)(CC(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:13:57] SMILES Parse Error: extra open parentheses for input: 'C(/C=C(/CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)\C'
RDKit ERROR: [21:13:57] SMILES Parse Error: extra open parentheses for input: 'C1=CC2=C(C=C1N(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:13:57] SMILES Parse Error: extra open parentheses for input: 'CC(CCC(=O)NCCCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:13:57] SMILES Parse Error: extra open parentheses for input: 'CC(CCC(=O)NCCCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:13:57] SMILES Parse Error: extra open parentheses for input: 'C/C=C/CC(CCCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:13:57] SMILES Parse Error: extra open parentheses for input: 'C=CCC(CCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:13:59] SMILES Parse Error: extra open parentheses for input: 'C1CCC(C(C1)N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:00] SMILES Parse Error: extra open parentheses for input: 'C1=CC(=C(C=C1N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:01] SMILES Parse Error: extra open parentheses for input: 'C1=C(OC(=C1)N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C=C(C'
RDKit ERROR: [21:14:01] SMILES Parse Error: extra open parentheses for input: 'C(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C(C'
RDKit ERROR: [21:14:01] SMILES Parse Error: extra open parentheses for input: 'C1=C(C(=C(N1)N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:02] Explicit valence for atom # 4 Cl, 3, is greater than permitted
RDKit ERROR: [21:14:04] SMILES Parse Error: extra open parentheses for input: 'CC1=C(C=CC(=C1CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:04] SMILES Parse Error: extra open parentheses for input: 'CC(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(COC(=O)CCCC'
RDKit ERROR: [21:14:04] SMILES Parse Error: extra open parentheses for input: 'C1=CC(=C(C=C1N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:05] SMILES Parse Error: extra open parentheses for input: 'CC1C=C(C=CC1OCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C(C'
RDKit ERROR: [21:14:05] SMILES Parse Error: extra open parentheses for input: 'C1=CC(=C(C=C1N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:05] SMILES Parse Error: extra open parentheses for input: 'CC1=NC(=C(C(=C1)N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:06] SMILES Parse Error: extra open parentheses for input: 'C1=CC(=CC=C1C(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:06] SMILES Parse Error: extra open parentheses for input: 'C1=CC(=CC=C1C(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:07] SMILES Parse Error: extra open parentheses for input: 'CCOC(=O)C(CCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:07] SMILES Parse Error: extra open parentheses for input: 'CCOC(=O)C(CCCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(CC'
RDKit ERROR: [21:14:07] SMILES Parse Error: extra open parentheses for input: 'C1=C(C=C(C=C1N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:07] SMILES Parse Error: extra open parentheses for input: 'CC(CCC(=O)OCCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:07] SMILES Parse Error: extra open parentheses for input: 'CC1=C(C(C(C(C1N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:07] SMILES Parse Error: extra open parentheses for input: 'C1=CC(C(C(C1N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:07] SMILES Parse Error: extra open parentheses for input: '[B](N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)[P+](CS'
RDKit ERROR: [21:14:08] SMILES Parse Error: extra open parentheses for input: 'C1CC([C@@H](CC1CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:08] SMILES Parse Error: extra open parentheses for input: 'CC(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:08] SMILES Parse Error: extra open parentheses for input: 'C1=C(N(C(=N1)CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:08] SMILES Parse Error: extra open parentheses for input: 'CC(CCC(=O)OCCCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:08] SMILES Parse Error: extra open parentheses for input: 'CCC(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(/C(=C/C'
RDKit ERROR: [21:14:08] SMILES Parse Error: extra open parentheses for input: 'CC(CCCCCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:08] SMILES Parse Error: extra open parentheses for input: 'CC(CCCCCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:08] SMILES Parse Error: extra open parentheses for input: 'CC1=C(C=CC(=C1N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:09] SMILES Parse Error: extra open parentheses for input: 'C1CC(CCC1N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(CC'
RDKit ERROR: [21:14:09] SMILES Parse Error: extra open parentheses for input: 'CC(CCC(=O)OCCCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:10] SMILES Parse Error: extra open parentheses for input: 'C1=CC(=C(C=C1N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:10] SMILES Parse Error: extra open parentheses for input: 'CC1=NC(=C(C(=C1)N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:11] SMILES Parse Error: extra open parentheses for input: 'CC=CC(CCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:11] SMILES Parse Error: extra open parentheses for input: 'CCC=CC(CCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:11] SMILES Parse Error: extra open parentheses for input: 'CCC=CC(CCCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:11] SMILES Parse Error: extra open parentheses for input: 'C(CNC(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:11] SMILES Parse Error: extra open parentheses for input: 'C1=CC(=CC=C1NC(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:11] SMILES Parse Error: extra open parentheses for input: 'C1=CC(=CC=C1NC(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:11] SMILES Parse Error: extra open parentheses for input: 'C(CNC(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:11] SMILES Parse Error: extra open parentheses for input: 'C1=CC(=CC=C1NC(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:13] SMILES Parse Error: extra open parentheses for input: 'C(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)CN(CC'
RDKit ERROR: [21:14:16] Explicit valence for atom # 1 Cl, 2, is greater than permitted
RDKit ERROR: [21:14:16] SMILES Parse Error: extra open parentheses for input: 'CC1=CC(=C(C(=C1)N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:17] SMILES Parse Error: extra open parentheses for input: 'C1=CC(=C(C=C1CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:17] SMILES Parse Error: extra open parentheses for input: 'CC(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)CN1CCC(CC1)(C'
RDKit ERROR: [21:14:17] SMILES Parse Error: extra open parentheses for input: 'C1=C(N=C(C(=N1)N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:19] SMILES Parse Error: extra open parentheses for input: 'C1=CC(=C(C=C1CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:20] SMILES Parse Error: extra open parentheses for input: 'CC(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:20] SMILES Parse Error: extra open parentheses for input: 'CC/C=C/CCC(CCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:20] SMILES Parse Error: extra open parentheses for input: 'CC(=CCC(CCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:20] SMILES Parse Error: extra open parentheses for input: 'C/C=C/CC(CCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:20] SMILES Parse Error: extra open parentheses for input: 'CCC(CCCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:20] SMILES Parse Error: extra open parentheses for input: 'CCC(CCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:21] SMILES Parse Error: extra open parentheses for input: 'C[Si](C)(C)OC(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:21] SMILES Parse Error: extra open parentheses for input: 'CC/C=C\CCC(CCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:21] SMILES Parse Error: extra open parentheses for input: 'CC(=CCC(CCCN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:21] SMILES Parse Error: extra open parentheses for input: 'C(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)[C@@H](C'
RDKit ERROR: [21:14:22] SMILES Parse Error: extra open parentheses for input: 'COC[C@@](CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)(C'
RDKit ERROR: [21:14:22] SMILES Parse Error: extra open parentheses for input: 'C(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)CO/C(=C/[N+]'
RDKit ERROR: [21:14:22] SMILES Parse Error: extra open parentheses for input: 'C(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)CO/C(=C/[N+]'
RDKit ERROR: [21:14:22] SMILES Parse Error: extra open parentheses for input: 'C1=C(C=NC(=C1N1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)C'
RDKit ERROR: [21:14:22] SMILES Parse Error: extra open parentheses for input: 'C(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)COC(=C[N+]'
RDKit ERROR: [21:14:22] SMILES Parse Error: extra open parentheses for input: 'C(CN1N=NC=C1C(C(C)C)c2ccc(C(C)C(=O)O)cc2)COC(=C[N+]'
Out[9]:
8259

Ура, нашлось целых 8259 соединений-аналогов ибупрофена, удовлетворяющих правилу пяти Липински. Посмотрим несколько из них:

In [10]:
from random import sample
In [12]:
type(good_analogs[1])
Out[12]:
str
In [11]:
sample_mols = [Chem.MolFromSmiles(item) for item in sample(good_analogs, 20)]
len(sample_mols)
Out[11]:
20
In [16]:
for mol in sample_mols:
    AllChem.Compute2DCoords(mol)
    display(mol)

Я очень пыталась заставить работать Draw.MolsToGridImage, но он постоянно ругался на несостыковку типов, хотя там по идее все было правильно. Поэтому мне пришлось использовать для отображения аналогов ибупрофена не эту прекрасную функцию, а обычный display.

Дальше построим Similarity map для 5-го соединения из изображенных выше.

In [14]:
from rdkit.Chem.Draw import SimilarityMaps
from IPython.display import Image
In [16]:
ibu = Chem.MolFromSmiles('CC(C)CC1=CC=C(C=C1)C(C)C(=O)O')
In [21]:
from rdkit.Chem.Draw import SimilarityMaps

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

fig, maxweight = SimilarityMaps.GetSimilarityMapForFingerprint(ibu, \
                sample_mols[4], SimilarityMaps.GetMorganFingerprint)
In [22]:
fig
Out[22]:
In [23]:
maxweight
Out[23]:
0.21671967287596544

Понятия не имею, откуда берется эта серая линия через все изображение, но как я ни пыталась что-то сделать, она не исчезла. Ну и ладно, similarity map от нее несильно страдает.

In [24]:
m3d=Chem.AddHs(sample_mols[4])
Chem.AllChem.EmbedMolecule(m3d)
AllChem.MMFFOptimizeMolecule(m3d,maxIters=500,nonBondedThresh=200 )
Out[24]:
0
In [25]:
m3d
Out[25]:

Теперь посмотрим это в 3D:

In [26]:
import nglview as nv
import ipywidgets
In [27]:
nv.show_rdkit(m3d)

Вот такая вот молекула получилась (Рис. 1). (В html она не видна, но на скриншоте видно, что она честно была запущена прям в ноутбуке.)

Рис. 1. Аналог ибупрофена.