Запустим PyMol для работы в режиме сервера.
import time
from xmlrpclib import ServerProxy
from IPython.display import Image
cmd = ServerProxy(uri="http://localhost:9123/RPC2")
defaultImage = '/tmp/pymolimg.png'
def prepareImage(width=300, height=300, sleep=2, filename=defaultImage):
## To save the rendered image
cmd.ray(width, height)
cmd.png('/tmp/pymolimg.png')
time.sleep(sleep)
# Define some shortcuts
def focus(x):
cmd.center(x)
cmd.zoom(x)
Загрузим структуру лизоцима радужной форели в комплексе с сахарами (PDB ID 1LMP).
cmd.fetch('1lmp')
cmd.hide('nonbonded')
cmd.bg_color('white')
cmd.select('ligand', '1lmp and resn nag+ndg')
cmd.disable('ligand')
cmd.show('sticks', 'ligand')
prepareImage()
Image(defaultImage)
Выберем остаток, например, аспартат 52.
mutant_resi = 'resi 52'
focus(mutant_resi)
cmd.select(mutant_resi)
prepareImage()
Image(defaultImage)
Проведём мутацию, заменив этот остаток, например, на аланин.
# Mutate Asp to Ala
cmd.wizard("mutagenesis")
cmd.do("refresh_wizard")
cmd.do('cmd.get_wizard().do_select("%s")' % mutant_resi)
cmd.do('cmd.get_wizard().set_mode("ALA")')
cmd.do("refresh_wizard")
cmd.do("cmd.get_wizard().apply()")
cmd.do("cmd.set_wizard()")
# Sometimes the temp mutant is not removed
try:
cmd.remove("/_tmp_mut")
except:
pass
prepareImage()
Image(defaultImage)
Загрузим немутированный белок как новый объект. Покрасим каждую структуру в свой цвет, выделив при этом отдельными цветами остаток с номером 63 и сахар. Перед началом анимации сместим немутированный белок влево.
cmd.fetch('1lmp', 'original')
cmd.hide('everything')
cmd.select('ligand1', '1lmp and resn nag+ndg')
cmd.select('ligand2', 'original and resn nag+ndg')
cmd.disable('ligand*')
cmd.set('cartoon_side_chain_helper', 'on')
cmd.show('cartoon', '(1lmp | original) & !ligand*')
cmd.colour('black', '1lmp')
cmd.colour('density', 'original')
cmd.show('sticks', 'ligand*')
cmd.colour('smudge', 'ligand*')
cmd.show('sticks', mutant_resi)
cmd.colour('red', '1lmp & '+mutant_resi)
cmd.colour('yellow', 'original & '+mutant_resi)
cmd.translate('[-50, 0, 0]', 'original')
focus('1lmp + original')
prepareImage(500, 500)
Image(defaultImage)
В начале анимации совместим белки. Затем увеличим место мутации.
#cmd.colour('black', 'original and not %s' % mutant_resi)
near_mutant = 'byres( %s extend 3)' % mutant_resi
cmd.hide('everything', near_mutant)
cmd.show('lines', near_mutant)
cmd.show('sticks', '%s & !original' % mutant_resi)
cmd.mset('1 x360')
cmd.frame('1')
cmd.clip('near', '100'); cmd.clip('far', '-100')
cmd.mview('store')
cmd.do('mview store, object=original')
# Align the proteins
cmd.frame('60')
cmd.do('translate [50, 0, 0], object=original')
cmd.do('mview store, object=original')
# This step might help to deal with auto-interpolation
cmd.frame('360')
cmd.do('mview store, object=original')
# Close-up of the proteins aligned
cmd.frame('120')
focus('original')
cmd.mview('store')
# Close-up of the mutated residues
cmd.frame('180')
cmd.do('mview store, object=original')
focus(mutant_resi)
cmd.do('util.mrock(180, 360, 360)')
cmd.mview('store')
cmd.frame('360')
focus(mutant_resi)
cmd.clip('near', '100'); cmd.clip('far', '-100')
cmd.mview('store')
cmd.do('mview interpolate, object=original')
cmd.mview('reinterpolate')
# cmd.mplay() # may be used to play the movie
## Saving the frames
cmd.set('ray_trace_frames', '1')
cmd.set('ray_trace_mode', '1')
cmd.set('antialias', '1')
cmd.mpng('1LMP_mutation')
Чтобы из получившихся трёхсот шестидесяти изображений сделать фильм, воспользуемся программой ffmpeg.
ffmpeg -i 1LMP_mutation0%03d.png -c:v libx264 -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" movie_1lmp.mp4
from IPython.display import HTML
from base64 import b64encode
video = open('movie_1lmp.mp4', 'rb').read()
video_encoded = b64encode(video)
video_tag = '<video controls alt="PyMol Movie" src="data:video/mp4;base64,{0}" type="video/mp4">'.format(video_encoded)
HTML(data=video_tag)
Присоединим к белку флуорусцентную метку TAMRA. Для этого сначала загрузим её структуру в формате .SDF.
import urllib2
tamra_url = "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/2762604/record/SDF/?response_type=save&record_type=3d"
connection = urllib2.urlopen(tamra_url)
sdf = connection.read()
with open('tamra.sdf', 'w') as w:
w.write(sdf)
Теперь загрузим файл в PyMol.
cmd.load('tamra.sdf')
# Make some visual changes
cmd.zoom('original')
cmd.disable('1lmp')
cmd.colour('deepblue', 'original & '+mutant_resi)
# Clear animation frames
cmd.mclear()
cmd.mdelete('360', '1')
focus('tamra')
cmd.set('ray_trace_mode', '0')
prepareImage()
Image(defaultImage)
Выберем остаток, к которому присоединим метку. Например, треонин 43.
anchor = 'original & resi 43'
anchor_O = anchor + ' & n. OG1'
cmd.show('sticks', anchor)
cmd.set('stick_radius', '0.1', anchor)
cmd.set('cartoon_side_chain_helper', 'on')
focus(anchor)
cmd.color('red', anchor_O)
prepareImage()
Image(defaultImage)
Присоединим метку к треонину 43.
(Так как атомы разные атомы одного химического элемента в структуре TAMRA не имеют различий в их наименовании, то на этом этапе необходимо воспользоваться GUI PyMol для того, чтобы выбрать атом, к которому будет присоединена метка.)
tamra_C = '/tamra///UNK`/C'
# NOTE: tamra_C should be choosed manually in PyMol GUI
cmd.fuse(anchor_O, tamra_C)
# torsion 15 # use several times
## And then remove the original oxygen from the TAMRA
new_anchor = 'tamra & i. 43 + /tamra///UNK`/'
cmd.disable('original')
focus(new_anchor)
prepareImage()
Image(defaultImage)
Для построения α-спирали из какого-либо аминокислотного остатка нужно сначала выяснить значения углов φ и ψ для этого остатка в α-спиралях известных белков. Для этого можно воспользоваться, например, картой Рамачандрана для интересующего остатка. Для аланина примем значения $ \phi = -50 $ и $ \psi = -40 $. Добавления нового остатка будем производить в цикле, изменяя при этом соответствующие углы для создаваемых остатков.
# Start from scratch
cmd.reinitialize()
cmd.bg_colour('white')
aa = 'ALA'
ala_phi = '-50'
ala_psi = '-40'
# Or change the torsion angle by these values
# to get the phi and psi needed
ala_shift_phi = '89'
ala_shift_psi = '-175'
def polyAA(n, aa, phi=None, psi=None, shift_phi=None, shift_psi=None):
cmd.fragment(aa)
cmd.edit("i. %i & n. C" % 2)
cmd.edit("i. 2 & n. CA", "i. 2 & n. C")
# At first, just add all the aminoacids
for i in range(2, n+1):
# Choose the atom to attach a new residue to
cmd.edit("i. %i & n. C" % i)
cmd.do('editor.attach_amino_acid("pk1", "%s")' % aa)
time.sleep(1)
# Then change dihedral angles
# this way...
if shift_phi and shift_psi:
for i in range(2, n+1):
# Edit the Calpha - C bond of the previous aminoacid
cmd.edit("i. %i & n. CA" % i, "i. %i & n. C" % i)
cmd.do('torsion '+shift_psi)
# Edit the N - Calpha bond
cmd.edit("i. %i & n. N" % (i+1), "i. %i & n. CA" % (i+1))
cmd.do('torsion '+shift_phi)
# ... or better this way
elif phi and psi:
for i in range(2, n+1):
cmd.set_dihedral("i. %i & n. N" % i, "i. %i & n. CA" % i,
"i. %i & n. C" % i, "i. %i & n. N" % (i+1),
phi)
cmd.set_dihedral("i. %i & n. C" % i, "i. %i & n. N" % (i+1),
"i. %i & n. CA" % (i+1), "i. %i & n. C" % (i+1),
psi)
cmd.edit()
cmd.show('cartoon', aa)
focus(aa)
# polyAA(20, 'ALA', shift_phi=ala_shift_phi,
# shift_psi=ala_shift_psi) # an ugly way
polyAA(100, 'ALA', phi=ala_phi, psi=ala_psi) # a better way
prepareImage()
Image(defaultImage)
# NOTE: I have no idea why the first added aminoacid has resi 2, not 1.
cmd.set_view('\
-0.668230056763, 0.238289996982, 0.704759895802, \
0.72214281559, 0.43547591567, 0.537468612194, \
-0.178832814097, 0.868088722229, -0.463076025248, \
-1.80295586586, 4.57921123505, -107.036514282, \
57.723361969, 39.3814544678, -38.9204406738, \
-13.3686256409, 227.318893433, -20.0')
cmd.hide('everything')
cmd.show('sticks')
cmd.set('stick_radius', '0.1')
cmd.show('spheres')
cmd.set('sphere_scale', '0.3')
cmd.spectrum('count')
prepareImage(); Image(defaultImage)
## BTW, here's the code to get the current view matrix
# import sys
# for i, u in enumerate((str(i) for i in cmd.get_view())):
# sys.stdout.write(u)
# sys.stdout.write(', ')
# if (i+1)%3 == 0:
# sys.stdout.write('\\\n')
С помощью программы babel
построим третичную структуру кубана на основе его SMILES-нотации: C12C3C4C1C5C2C3C45
.
echo C12C3C4C1C5C2C3C45 > cubane.smi
obgen cubane.smi > cubane.mol
# Start from scratch
cmd.reinitialize()
cmd.bg_colour('white')
cmd.load('cubane.mol')
prepareImage(); Image(defaultImage)
cmd.hide('everything')
cmd.show('sticks')
cmd.set('stick_radius', '0.1')
cmd.show('spheres')
cmd.set('sphere_scale', '0.2')
cmd.spectrum('count')
focus('cubane')
## Some animation may seem nice
# cmd.mset('1 x180')
# cmd.do('util.mrock(1, 180, 360)')
# cmd.mplay()
prepareImage(300, 200); Image(defaultImage)
Для построения структуры молекулы ДНК необходимо определить матрицу превращения при совмещении одной пары нуклеотидов с последующей. Затем будем размножать эту пару и применять к ней матрицу превращения.
# We can define a function to parse PyMol syntax
# so that there will be no need to type those cmd-s again
def PyMolExecute(commands):
one_command = ''
for line in commands.split('\n'):
if line:
one_command += line.strip()
one_command += '; '
cmd.do(one_command)
PyMolExecute("""
fetch 1BNA
bg white
hide everything
show cartoon
set cartoon_ring_mode, 2
create pair, c. A & i. 6 + c. B & i. 19
create nextpair, c. A & i. 7 + c. B & i. 18
create 1, pair
pair_fit nextpair, pair
""")
trans = cmd.get_object_matrix("nextpair")
for x in range(2, 100):
cmd.create(str(x), str(x-1))
cmd.do('cmd.transform_selection(%i, %s, homogenous=0)' % (x, trans))
time.sleep(1)
PyMolExecute("""
delete 1BNA
hide everything
show sticks
""")
focus("all")
prepareImage(); Image(defaultImage)
# Take a close-up view
cmd.show('surface')
cmd.set_view('\
0.279711633921, 0.0657793134451, -0.957828342915, \
-0.955636739731, 0.115004368126, -0.271171957254, \
0.092316634953, 0.991186976433, 0.0950298756361, \
-5.04646450281e-05, 0.000781282782555, -327.234893799, \
21.9157848358, 43.2902755737, 168.800308228, \
-140695.375, 141349.875, -20.0')
prepareImage(); Image(defaultImage)
Источники, которые были полезны при выполнении заданий: