Запускаем Pymol как RPC сервер:
from multiprocessing import Process
def launch_pymol():
!pymol -R &> /dev/null
Process(target=launch_pymol).start()
Импортируем прокси для работы с PyMOL
import xmlrpc.client as xmlrpclib
cmd = xmlrpclib.ServerProxy('http://localhost:9123')
Загружаем структуру 1LMP
from IPython.display import Image
cmd.do(f'''
reini
fetch 1lmp
hide nonbonded
bg_color white
select ligand, resn nag+ndg
show sticks, ligand
zoom 1lmp, -7
png pic/1.png, width=1080, height=720, ray=1
''')
Image('pic/1.png',retina= True)
С помощью Wizard->Demo->Sculpting изменяем структуру, результат представлен ниже.
Image('pic/2.png', width = 540)
Для начала выбираем остаток, мутация которого может привести к потере связывания с лигандом. На странице PDB указано, что остаток Asp101A образует с NAG водородную связь:
Image('pic/3.png', width = 300)
Визуализируем ее в PyMOL:
cmd.do('''
reini
fetch 1lmp
remove resn HOH
bg_color white
select ligand, resn nag+ndg
dist hbond1, ligand, resi 101, 3.5, mode=2
show sticks, resi 101
orient resi 101+130
zoom resi 101+130, 2
view1 = get_view()
png pic/4.png, width=1080, height=720, ray=1
delete hbond1
''')
Image('pic/4.png',retina= True)
А теперь проведем мутацию остатка Asp101 на Ala. Водородная связь при такой мутации исчезнет.
cmd.do('''
wizard mutagenesis
refresh_wizard
python
cmd.get_wizard().do_select("resi 101")
cmd.get_wizard().set_mode("ALA")
cmd.get_wizard().apply()
cmd.set_wizard()
python end
dist hbond1, ligand, resi 101 , 3.5, mode=2
set_view(view1)
png pic/5.png, width=1080, height=720, ray=1
''')
Image('pic/5.png',retina=True)
Разместим исходную структуру и структуру с мутацией рядом друг с другом, выделим аминокислоту с мутацией другим цветом:
cmd.do('''
set_view(view0)
fetch 1lmp, original
remove resn HOH
translate [40, 0, 0], original
orient all
select ligand1, original and resn nag+ndg
select ligand2, 1lmp and resn nag+ndg
as cartoon, not ligand*
color slate, original
color grey50, ligand*
show sticks, resi 101
color yellow, resi 101 and 1lmp
set stick_radius, 0.5, resi 101 and 1lmp
color tv_red, resi 101 and original
png pic/6.png, width=1080, height=720, ray=1
''')
Image('pic/6.png',retina=True)
Совместим эти две структуры и сделаем на основе этого анимационный ролик:
import time
cmd.do('''
mset 1 x150
set movie_auto_interpolate, off
frame 30
align original, 1lmp
mview store, object=original
mview store, object=1lmp
frame 150
mview store, object=original
mview store, object=1lmp
frame 1
translate [20, 0, 0], object=original
translate [-20, 0, 0], object=1lmp
mview store, object=original
mview store, object=1lmp
mview reinterpolate, object=original
mview reinterpolate, object=1lmp
''')
time.sleep(0.1)
cmd.frame(1)
cmd.zoom()
cmd.mview('store')
cmd.frame(30)
cmd.zoom()
cmd.mview('store')
cmd.frame(60)
cmd.zoom('all', -5)
cmd.mview('store')
cmd.frame(90)
cmd.zoom('resi 101', 1)
cmd.mview('store')
cmd.frame(120)
cmd.turn('y', -30)
cmd.mview('store')
cmd.frame(150)
cmd.turn('y', 60)
cmd.mview('store')
cmd.mview('reinterpolate')
Сохраняем каждый 3-й кадр:
cmd.do('''
python
cmd.mstop()
for x in range(0, 150, 3):
cmd.mpng('mv/', x + 1, x + 1, mode=1, width=720, height=480)
python end
''')
Создаем файл .gif
import imageio
import os
filenames = sorted(os.listdir('mv'))[1:]
with imageio.get_writer('movie.gif', mode='I', fps=10) as writer:
for filename in filenames:
filepath = os.path.join('mv', filename)
image = imageio.imread(filepath)
writer.append_data(image)
Отображение того, что получилось:
from IPython.display import Image, display
display(Image(filename='movie.gif', format='png'))
cmd.do('''
reini
fetch 1lmp
hide nonbonded
bg_color white
load tamra.sdf
remove tamra and id 54
show sticks, resi 47
remove resi 47 and name OG1
fuse tamra and donor, resi 47 and name CB, mode=1
torsion -100
remove tamra
orient resi 47
turn y, -150
unpick
png pic/7.png, width=1080, height=720, ray=1
''')
time.sleep(0.1)
Image('pic/7.png',retina=True)
Построение полианилиновой спирали длиной 100 аминокислот.
cmd.do('''
reini
bg_color white
fragment ALA
''')
# Построим цепь из 100 а.о. аланина
for i in range(2, 101):
cmd.do(f'''
edit resi {i} and name C
editor.attach_amino_acid('pk1', 'ALA')
''')
# Исправим торсионные углы
phi = -57
psi = -47
for i in range(2, 101):
cmd.do(f'''
set_dihedral resi {i} and name N, resi {i} and name CA, resi {i} and name C, resi {i+1} and name N, {phi}
set_dihedral resi {i} and name C, resi {i+1} and name N, resi {i+1} and name CA, resi {i+1} and name C, {psi}
''')
cmd.do('''
show cartoon
orient
zoom ala, 5
unpick
png pic/8.png, width=1080, height=720, ray=1
''')
time.sleep(0.1)
Image('pic/8.png')
Возьмем заготовки для нуклеиновых кислот из структуры 1BNA. Определим матрицу превращения (trans) при совмещении одной пары нуклеотидов с последующей.
cmd.do('''
reini
fetch 1bna
remove resn HOH
create pair, resi 6+19
create nextpair, resi 7+18
pair_fit resi 6 and backbone,resi 7 and backbone, resi 19 and backbone, resi 18 and backbone
''')
trans = cmd.get_object_matrix('pair')
#Сделаем заготовку из двух пар
cmd.do('''
reini
fetch 1bna
create nextpair, resi 6+19
copy pair1, nextpair
delete 1bna
alter pair1, resi=0
''')
#Применим матрицу превращения 99 раз
for x in range(99):
cmd.transform_object('nextpair', trans)
cmd.alter('nextpair', f'resi={x+1}')
cmd.fuse('nextpair', 'pair1', 3)
cmd.delete('nextpair')
cmd.show('sticks')
cmd.unpick()
cmd.do('''
save 'dna.pdb'
reini
load dna.pdb
bg_color white
zoom dna, -10
orient
png pic/9.png, width=1080, height=720, ray=1
''')
Image('pic/9.png')