Докинг низкомолекулярных лигандов в структуру белка



В этом задании мы будем проводить докинг лигандов в структуру белка, которая была сможелирована на прошлом практикуме. Докинг будем проводить при помощи Autodock Vina и oddt.

In [1]:
import copy
import numpy as np

# Отображение структур
import ipywidgets
import IPython.display
from IPython.display import display,display_svg,SVG,Image

# Open Drug Discovery Toolkit
import oddt
import oddt.docking
import oddt.interactions

# Органика
from rdkit.Chem import Draw
from rdkit.Chem import AllChem
from rdkit.Chem import MolFromSmiles
from rdkit.Chem.Draw import IPythonConsole

# Модуль для манипулирования pdb 
import pmx
In [2]:
# из созданных на прошлом практикуме структур возьмем ту, 
# у которой было наивысшее значение скор-функции - пятую.
pdb=pmx.Model('HYACE5.pdb')

Разделим белок и лиганд на разные структуры:

In [3]:
# посмотрим остатки и локализуем лиганд:
for r in pdb.residues[135:]:
    print r
<Molecule: id = 136 name = ILE chain_id =    natoms = 8>
<Molecule: id = 137 name = SER chain_id =    natoms = 6>
<Molecule: id = 138 name = ASP chain_id =    natoms = 8>
<Molecule: id = 139 name = CYS chain_id =    natoms = 7>
<Molecule: id = 140 name = NAG chain_id =    natoms = 14>
<Molecule: id = 141 name = NAG chain_id =    natoms = 14>
<Molecule: id = 142 name = NDG chain_id =    natoms = 15>
In [4]:
# создадим новые объекты:
# только белок и только лиганд
newpdb = pdb.copy()
for r in newpdb.residues[-3:]:
    newpdb.remove_residue(r)
lig = pdb.copy()
for r in lig.residues[:-3]:
    lig.remove_residue(r)

Теперь найдем геометрический центр лиганда:

In [5]:
coords = np.zeros((len(lig.atoms),3))
for c,a in enumerate(lig.atoms):
    coords[c,:] = a.x
geom_center = np.mean(coords, axis = 0)
geom_center
Out[5]:
array([ 40.22472093,  41.43055814,  29.19934884])
In [6]:
newpdb.writePDB('prot.pdb')
lig.writePDB('lig.pdb')

Подготовка белка для докинга

In [7]:
prot = oddt.toolkit.readfile('pdb','prot.pdb').next()

print prot.OBMol.AddPolarHydrogens()
print prot.OBMol.AutomaticPartialCharge()
print 'is it the first mol in 1lmp is protein?',prot.protein,':) and MW of this mol is:', prot.molwt
True
True
is it the first mol in 1lmp is protein? False :) and MW of this mol is: 15871.05588

Забавно, что белок не был распознан.

Лиганды для докинга
Создадим несколько лигандов на основе NAG и придумаем какие-нибудь еще для разнообразия:

In [8]:
smiles = ['OC1C(C(C(OC1O)CO)O)O', '[NH3+]C1C(C(C(OC1O)CO)O)O', 
          'C1C(C(C(OC1O)CO)O)O', 'C1=CC=C(C=C1)C1C(C(C(OC1O)CO)O)O',
          'c1(O)cc(c2cc(F)cc(I)c2)cc(O)c1', 
          'C1=C(C=C(C(=C1[N+](=O)[O-])[O-])[N+](=O)[O-])[N+](=O)[O-]', 
          'C1=CC(=CC=C1O)OC2=CSC=C2', 'COP(=O)(O)OC1=CC=C(C=C1)C=O']

Отличные вещества! Теперь посмотрим на них и подготовим их структуры к докингу:

In [10]:
mols = []
images =[]
for s in smiles:
    m = oddt.toolkit.readstring('smi', s)
    if not m.OBMol.Has3D(): 
        m.make3D(forcefield='mmff94', steps=150)
        m.removeh()
        m.OBMol.AddPolarHydrogens()

    mols.append(m)
    ### with print m.OBMol.Has3D() was found that:
    ### deep copy needed to keep 3D, write svg make mols flat
    images.append((SVG(copy.deepcopy(m).write('svg'))))
display_svg(*images)
***** - Open Babel Depiction H H H H H O O O O O O *****
***** - Open Babel Depiction O H H H H H H H O O + N O O *****
***** - Open Babel Depiction O O O O O H H H H *****
***** - Open Babel Depiction O H H H H O O O O *****
***** - Open Babel Depiction H H O I F O *****
***** - Open Babel Depiction N O OH OH N O HO N O OH *****
***** - Open Babel Depiction O O S H *****
***** - Open Babel Depiction H 3 C O P O O O O H *****

Докинг

In [11]:
# create docking object
# центром докинга дадим геометрический центр лиганда,
# найденный нами ранее - приблизительное положение сайта связывания
dock_obj= oddt.docking.AutodockVina.autodock_vina(
    protein=prot,size=(20,20,20),center=geom_center,
    executable='/usr/bin/vina',autocleanup=True, num_modes=20)

print dock_obj.tmp_dir
print " ".join(dock_obj.params)
/tmp/autodock_vina_IcHje6
--center_x 40.2247209302 --center_y 41.4305581395 --center_z 29.1993488372 --size_x 20 --size_y 20 --size_z 20 --cpu 1 --exhaustiveness 8 --num_modes 20 --energy_range 3
In [12]:
# do it
res = dock_obj.dock(mols,prot)

Результаты докинга

In [14]:
import pandas as pd
In [13]:
# отсортируем результаты по аффинности (параметр vina_affinity):
res_sorted = sorted(res, key = lambda x : float(x.data['vina_affinity']))
In [32]:
hbtot = []
hbstr = []
phob = []
for i,r in enumerate(res_sorted):
    int1, int2, strict = oddt.interactions.hbonds(prot,r)
    hbtot.append(len(int1))
    hbstr.append(strict.sum())
    ph1, ph2 = oddt.interactions.hydrophobic_contacts(prot,r)
    phob.append(len(ph1))
dat = pd.DataFrame({'Formula':[r.formula for r in res_sorted],
                   'Affinity':[r.data['vina_affinity'] for r in res_sorted], 
                   'RMSD':[r.data['vina_rmsd_ub'] for r in res_sorted], 
                   'HB_tot':hbtot,'HB_strict':hbstr, 'Hydphobic':phob})
In [33]:
dat[:]
Out[33]:
Affinity Formula HB_strict HB_tot Hydphobic RMSD
0 -6.6 C12H8FIO2 1 2 12 0.000
1 -6.6 C12H8FIO2 2 2 12 2.054
2 -6.6 C12H8FIO2 4 4 3 6.216
3 -6.6 C12H8FIO2 4 4 3 5.887
4 -6.5 C12H8FIO2 1 1 12 5.952
5 -6.4 C12H8FIO2 3 3 5 2.678
6 -6.4 C12H8FIO2 3 3 5 3.042
7 -6.4 C12H8FIO2 2 2 19 5.419
8 -6.4 C12H8FIO2 0 1 12 5.966
9 -6.1 C12H16O5 10 11 2 0.000
10 -6.0 C12H16O5 9 9 6 2.338
11 -5.9 C12H16O5 6 8 3 5.401
12 -5.9 C6H3N3O7 1 1 1 0.000
13 -5.8 C12H16O5 8 10 9 5.440
14 -5.8 C6H3N3O7 1 1 1 4.969
15 -5.8 C6H3N3O7 0 0 0 5.549
16 -5.8 C6H3N3O7 1 1 1 5.109
17 -5.7 C12H16O5 7 9 6 4.767
18 -5.7 C12H16O5 2 3 17 7.297
19 -5.7 C12H16O5 7 10 8 4.996
20 -5.7 C6H3N3O7 0 0 1 4.613
21 -5.7 C6H3N3O7 0 0 2 4.167
22 -5.7 C6H3N3O7 0 0 1 5.512
23 -5.6 C12H16O5 0 0 18 5.840
24 -5.6 C12H16O5 8 9 1 4.976
25 -5.6 C6H3N3O7 1 1 2 4.823
26 -5.6 C8H9O5P 4 7 4 0.000
27 -5.5 C6H3N3O7 0 0 1 2.439
28 -5.5 C10H8O2S 2 2 8 0.000
29 -5.5 C8H9O5P 3 4 2 6.567
... ... ... ... ... ... ...
42 -4.8 C10H8O2S 1 1 11 8.077
43 -4.8 C10H8O2S 4 5 2 6.871
44 -4.8 C8H9O5P 3 3 3 5.247
45 -4.7 C6H12O6 7 10 0 3.700
46 -4.7 C6H12O6 7 9 0 3.757
47 -4.7 C6H14NO5 8 10 0 3.275
48 -4.7 C6H14NO5 5 7 0 4.548
49 -4.7 C10H8O2S 3 3 4 2.194
50 -4.7 C8H9O5P 3 3 4 7.206
51 -4.6 C6H12O6 3 4 0 4.237
52 -4.6 C6H12O6 9 10 0 2.866
53 -4.6 C6H12O6 7 8 0 3.550
54 -4.6 C6H14NO5 5 5 0 3.726
55 -4.6 C6H14NO5 5 5 0 4.099
56 -4.6 C6H14NO5 7 9 0 3.295
57 -4.6 C6H14NO5 5 6 0 4.184
58 -4.6 C6H12O5 9 10 0 0.000
59 -4.6 C10H8O2S 1 1 4 5.452
60 -4.5 C6H12O6 8 8 0 3.930
61 -4.5 C6H12O6 8 9 0 3.738
62 -4.5 C6H12O5 8 8 1 3.697
63 -4.5 C6H12O5 8 8 0 3.221
64 -4.4 C6H12O6 7 7 0 2.251
65 -4.4 C6H14NO5 5 6 0 3.532
66 -4.4 C6H12O5 8 9 0 3.619
67 -4.4 C6H12O5 7 8 0 1.935
68 -4.3 C6H12O5 4 5 0 3.912
69 -4.3 C6H12O5 9 9 0 2.633
70 -4.2 C6H12O5 7 9 0 2.317
71 -4.2 C6H12O5 6 8 0 2.909

72 rows × 6 columns

Анализ докинга
Забавно, что первые позиции заняла не модификация NAG, а придуманное мною галогенпроизводное. Рассмотрим поближе его структуры 0 (лучшая по RMSD), 3 (4 водородные связи, и все - строгие) а также лучшее из производных NAG - номер 9.

In [34]:
for i in (0, 4, 9):
    res_sorted[i].write(filename='%s.pdb' % str(i), format='pdb')

Интересно, откуда у галогенпроизводного взялось аж 4 водородных связи учитывая что ОН групп у негов всего две. У производного NAG их тоже многовато.

In [47]:
def print_hbonds(res, i):
    int1, int2, strict = oddt.interactions.hbonds(prot, res[i])
    for x,y in zip(int1, int2):
        print "%s:%s-->%s:%s" % (x[8] or 'PROT', x[5], y[9] or "LIG", y[5])
In [48]:
print_hbonds(res_sorted, 3)
PROT:O.2-->LIG:O.3
PROT:O.3-->LIG:O.3
PROT:N.ar-->LIG:F
PROT:O.3-->LIG:O.3
In [49]:
print_hbonds(res_sorted, 9)
PROT:O.2-->LIG:O.3
PROT:O.3-->LIG:O.3
PROT:O.3-->LIG:O.3
PROT:O.3-->LIG:O.3
PROT:O.2-->LIG:O.3
PROT:O.2-->LIG:O.3
PROT:O.3-->LIG:O.3
PROT:N.am-->LIG:O.3
PROT:O.3-->LIG:O.3
PROT:N.am-->LIG:O.3
PROT:O.3-->LIG:O.3

Видно, что многие связи дублируют друг друга; Также довольно забавно наблюдать, как в водородные связи попала связь между ароматическим азотом и фтором.

Рис.1. Находка 0 в белке.
Рис.2. Находка 3 в белке. Из 4 найденных программой водородных связей под критерии сбственно водородной связи попадает только одна.
Рис.3. Находка 9 в белке. Видим, что ОН группы лиганда могут образовать сразу по несколько водродных связей. Также интересна конформация, напоминающая не просто "кресло", а самый настоящий стул.