## Задание 0
В этой работе PyMOL был использован как модуль из Jupyter Notebook.
Структура 1cll была загружена программно командой `fetch`.
Для backbone-атомов было включено представление `lines`, после чего выполнено приближение к остаткам 4 и 5.
Для наглядности остатки 4 и 5 были дополнительно выделены стиками и цветом.
Итоговое изображение было сохранено в PNG и выведено в ноутбуке.
import __main__
__main__.pymol_argv = ['pymol', '-x']
import pymol
pymol.finish_launching()
from pymol import cmd
from IPython.display import Image, display
# Сбрасываем прошлое состояние
cmd.reinitialize()
# Загружаем структуру
cmd.do('''
fetch 1cll, async=0
as lines, n. C+O+N+CA
zoom i. 4+5
''')
# Немного улучшаем вид
cmd.do('''
bg_color white
color gray70, all
show sticks, i. 4+5
color hotpink, i. 4+5
orient i. 4+5
zoom i. 4+5, 8
''')
# Сохраняем итоговую картинку
out_png = r"C:\Users\Tata\Documents\jupyter_pol\seminar1_task1_1cll.png"
cmd.png(out_png, width=1400, height=1000, dpi=200, ray=1)
print(out_png)
display(Image(filename=out_png))
## Задание 1
## Sculpting в PyMOL на примере 1LMP
В этом задании была изучена возможность интерактивного изменения структуры белка с помощью режима Sculpting в PyMOL. В качестве примера использовалась структура 1LMP. Сначала структура была загружена в Jupyter через модуль PyMOL, после чего белковая цепь была показана в виде cartoon, а связанный лиганд — в виде sticks.
Далее был выделен участок белка, расположенный рядом с лигандом, и для него был опробован режим Sculpting. С помощью интерактивного редактирования был изменён локальный участок структуры: боковая цепь/небольшой фрагмент около сайта связывания был слегка смещён. Это позволило оценить, как PyMOL поддерживает локальную геометрию при ручном изменении конформации.
Таким образом, Sculpting можно использовать для наглядного локального редактирования структуры и демонстрации того, как меняется форма участка белка при небольших конформационных изменениях.
# Загружаем структуру
cmd.reinitialize()
cmd.fetch('1lmp', async_=0)
# Убираем воду и мусор
cmd.remove('solvent')
# Делаем понятное отображение
cmd.hide('everything', 'all')
cmd.show('cartoon', 'chain A')
cmd.color('palegreen', 'chain A')
# Лиганд показываем стиками
cmd.show('sticks', 'chain B')
cmd.color('orange', 'chain B')
# Общий вид
cmd.orient()
cmd.zoom('all', 3)
before1_png = r"C:\Users\Tata\Documents\jupyter_pol\1lmp_before_sculpt.png"
cmd.png(before_png, width=1400, height=1000, dpi=200, ray=1)
display(Image(filename=before_png))
# Остатки белка рядом с лигандом
cmd.select('site', 'byres (chain A within 5 of chain B)')
# Показываем их стиками
cmd.show('sticks', 'site')
cmd.color('yellow', 'site')
# Приближаем активную область
cmd.zoom('site or chain B', 3)
before2_png = r"C:\Users\Tata\Documents\jupyter_pol\1lmp_before_sculpt.png"
cmd.png(before_png, width=1400, height=1000, dpi=200, ray=1)
display(Image(filename=before_png))
before3_png = r"C:\Users\Tata\Documents\jupyter_pol\1lmp_before_sculpt.png"
cmd.png(before_png, width=1400, height=1000, dpi=200, ray=1)
display(Image(filename=before_png))
after_png = r"C:\Users\Tata\Documents\jupyter_pol\1lmp_after_sculpt.png"
cmd.png(after_png, width=1400, height=1000, dpi=200, ray=1)
display(Image(filename=after_png))
session_file = r"C:\Users\Tata\Documents\jupyter_pol\1lmp_sculpt_session.pse"
cmd.save(session_file)
print(session_file)
## Задание 2
import __main__
__main__.pymol_argv = ['pymol', '-x']
import pymol
pymol.finish_launching()
from pymol import cmd
from IPython.display import Image, display
cmd.reinitialize()
cmd.fetch('1lmp', async_=0)
cmd.remove('solvent')
cmd.hide('everything', 'all')
cmd.show('cartoon', 'chain A')
cmd.color('palegreen', 'chain A')
cmd.show('sticks', 'chain B')
cmd.color('orange', 'chain B')
cmd.orient()
cmd.zoom('all', 3)
## предварительная зона оценки контактов
cmd.select('contact_zone', 'byres (chain A within 4 of chain B)')
cmd.show('sticks', 'contact_zone')
cmd.color('yellow', 'contact_zone')
cmd.set('label_size', 10)
cmd.set('label_color', 'black')
cmd.label('contact_zone and name CA', '"%s%s" % (resn, resi)')
cmd.zoom('contact_zone or chain B', 5)
before_mut_png = r"C:\Users\Tata\Documents\jupyter_pol\1lmp_contact_before_mut.png"
cmd.png(before_mut_png, width=1400, height=1000, dpi=200, ray=1)
display(Image(filename=before_mut_png))
after_mut_2_png = r"C:\Users\Tata\Documents\jupyter_pol\1lmp_contact_before_mut.png"
cmd.png(after_mut_2_png, width=1400, height=1000, dpi=200, ray=1)
display(Image(filename=after_mut_2_png))
## Задание 3
import __main__
__main__.pymol_argv = ['pymol', '-x']
import pymol
pymol.finish_launching()
from pymol import cmd
## Делаем копию белка, чтобы 1 мутировать, а вотрой оставить исходным
cmd.reinitialize()
# Загружаем исходную структуру
cmd.fetch('1lmp', 'WT', async_=0)
# Делаем полную копию, вместе с лигандом
cmd.create('MUT', 'WT')
# Убираем воду
cmd.remove('solvent')
# Белки
cmd.hide('everything', 'all')
cmd.show('cartoon', 'WT and chain A')
cmd.show('cartoon', 'MUT and chain A')
cmd.color('palegreen', 'WT and chain A')
cmd.color('lightblue', 'MUT and chain A')
# Лиганд показываем у ОБОИХ объектов
cmd.show('sticks', 'WT and chain B')
cmd.show('sticks', 'MUT and chain B')
cmd.color('orange', 'WT and chain B')
cmd.color('tv_red', 'MUT and chain B')
# Чтобы сначала объекты не лежали друг на друге, уводим MUT вправо
cmd.translate([35, 0, 0], object='MUT', camera=0)
cmd.zoom('WT or MUT', 4)
# Выбираем остатки белка рядом с лигандом
cmd.select('wt_site', 'byres (WT and chain A within 4 of WT and chain B)')
cmd.select('mut_site', 'byres (MUT and chain A within 4 of MUT and chain B)')
# Показываем это окружение стиками
cmd.show('sticks', 'wt_site')
cmd.show('sticks', 'mut_site')
cmd.color('yellow', 'wt_site')
cmd.color('cyan', 'mut_site')
cmd.zoom('wt_site or mut_site or WT and chain B or MUT and chain B', 5)
# Подписываем номера остатков у MUT, чтобы было удобно выбирать мутацию
cmd.set('label_size', 10)
cmd.set('label_color', 'black')
cmd.label('mut_site and name CA', '"%s%s" % (resn, resi)')
cmd.zoom('mut_site or MUT and chain B', 6)
cmd.hide('labels', 'all')
## Вручную мутируем TRP63 через Wizard -> Mutation на ALA
## Накладываем мутированную форму белка на исходную и выделяем мутированный остаток для лучшей визуализации
# Совмещаем только белковые цепи
cmd.super('MUT and chain A and name CA', 'WT and chain A and name CA')
# Место мутации показываем стиками
cmd.show('sticks', 'WT and chain A and resi 63')
cmd.show('sticks', 'MUT and chain A and resi 63')
cmd.color('firebrick', 'WT and chain A and resi 63')
cmd.color('blue', 'MUT and chain A and resi 63')
# Если окружение лиганда уже было выделено, можно оставить его стиками
cmd.zoom('WT or MUT', 4)
cmd.bg_color('white')
cmd.set('cartoon_transparency', 0.25, 'MUT and chain A')
cmd.set('stick_radius', 0.18)
# Лиганд у MUT лучше сделать полупрозрачным, чтобы при совмещении не мешал
cmd.set('stick_transparency', 0.5, 'MUT and chain B')
cmd.matrix_reset('WT', mode=1)
cmd.matrix_reset('MUT', mode=1)
cmd.super('MUT and chain A and name CA', 'WT and chain A and name CA')
cmd.zoom('WT or MUT', 4)
## Создание видео с местом мутации
cmd.mstop()
cmd.mview('clear')
cmd.mset('1 x1')
cmd.frame(1)
cmd.matrix_reset('MUT', mode=1)
cmd.matrix_reset('WT', mode=1)
cmd.mview('clear')
cmd.mset('1 x1')
cmd.frame(1)
cmd.matrix_reset('MUT', mode=1)
# 2) новый медленный ролик
cmd.mset('1 x420')
cmd.frame(1)
# старт: только MUT, WT скрыт
cmd.enable('MUT')
cmd.disable('WT')
# медленные переключения WT поверх MUT
cmd.mdo(120, 'enable WT')
cmd.mdo(200, 'disable WT')
cmd.mdo(280, 'enable WT')
cmd.mdo(360, 'disable WT')
cmd.mdo(420, 'enable WT')
# запуск
cmd.frame(1)
cmd.mplay()
## Сохраняем в PyMol кадры, совмещаим их для аолучения фильма, загружаем его и выводим в Jupyter
import os
frames_dir = r"C:\Users\Tata\Documents\jupyter_pol\movie_frames"
os.makedirs(frames_dir, exist_ok=True)
print(os.path.exists(frames_dir))
print(frames_dir)
cmd.png(r"C:\Users\Tata\Documents\jupyter_pol\movie_frames\test.png")
1
cmd.set('cache_frames', 0)
cmd.mpng("C:/Users/Tata/Documents/jupyter_pol/movie_frames/frame")
from glob import glob
import imageio.v2 as imageio
import os
frames = sorted(glob(r"C:\Users\Tata\Documents\jupyter_pol\movie_frames\frame*.png"))
out_mp4 = r"C:\Users\Tata\Documents\jupyter_pol\mutation_movie.mp4"
print("Кадров найдено:", len(frames))
print("Первый кадр:", frames[0] if frames else "нет кадров")
with imageio.get_writer(
out_mp4,
fps=25, # меньше fps = медленнее видео
codec="libx264",
pixelformat="yuv420p"
) as writer:
for f in frames:
writer.append_data(imageio.imread(f))
print("Видео сохранено:", out_mp4)
print("Размер файла:", os.path.getsize(out_mp4))
from IPython.display import Video
Video("mutation_movie.mp4", embed=True, width=800)
## Задание 4
Для присоединения TAMRA я использовала карбоксильную группу красителя и гидроксильную группу Tyr62 белка. Поскольку по условию нужна именно сложноэфирная связь, пришивку выполняли не через аминогруппу, а через кислород тирозина. Сначала у TAMRA был выбран карбоксильный углерод и удалён кислород из группы –OH, который должен уходить при образовании эфира. Затем командой fuse карбоксильный углерод TAMRA был соединён с кислородом Tyr62, а командой torsion метка была довернута в более удобное положение, чтобы уменьшить перекрывание с белком.
cmd.reinitialize()
# Белок
cmd.fetch("1lmp", "WT", type="pdb", async_=0)
cmd.create("prot_tamra", "WT")
cmd.remove("hydro")
# TAMRA из локального файла
cmd.load(r"C:\Users\Tata\Documents\jupyter_pol\tamra.sdf", "TAMRA")
cmd.remove("TAMRA and hydro")
# Показываем TAMRA и подписываем номера атомов
cmd.show("sticks", "TAMRA")
cmd.label("TAMRA and not hydro", "str(ID)")
# Место пришивки: OH Tyr62
cmd.select("site_oh", "prot_tamra and chain A and resi 62 and resn TYR and name OH")
cmd.show("sticks", "site_oh")
cmd.zoom("site_oh or TAMRA", 8)
# остатки белка в копии, которые находятся рядом с лигандом
cmd.select("prot_site", "byres (prot_tamra and chain A within 4 of prot_tamra and chain B)")
# показать это окружение стиками
cmd.show("sticks", "prot_site")
# при желании покрасить
cmd.color("yellow", "prot_site")
# лиганд тоже показать стиками
cmd.show("sticks", "prot_tamra and chain B")
cmd.color("orange", "prot_tamra and chain B")
# выбираем атомы
cmd.select("tamra_c", "TAMRA and id 29")
cmd.select("tamra_oh", "TAMRA and id 2")
cmd.select("site_oh", "prot_tamra and chain A and resi 62 and resn TYR and name OH")
# удаляем OH у TAMRA
cmd.remove("id 2")
# ВАЖНО: меняем порядок selection
cmd.fuse("site_oh", "tamra_c")
cmd.unpick()
tamra_png = r"C:\Users\Tata\Documents\jupyter_pol\tamra.png"
cmd.png(tamra_png, width=1400, height=1000, dpi=200, ray=1)
display(Image(filename=tamra_png))
Задание 5¶
В этом задании я построила поли-аланиновую α-спираль длиной 100 аминокислот в PyMOL. Сначала был создан первый остаток alanine, а затем цепь достраивалась по одному остатку через edit и editor.attach_amino_acid: команда edit каждый раз выбирала C-конец растущей цепи, а attach_amino_acid(..., ss=1) присоединяла следующий alanine в α-спиральной геометрии. Команду bond я отдельно оставила в скрипте как явный пример работы с пептидной связью: на практике после attach_amino_acid она уже обычно создана автоматически. Команду torsion я использовала для аккуратного поворота терминальной метильной группы у последнего alanine — так я показала, как можно вращать фрагмент вокруг выбранной связи, не разрушая общую форму спирали. В итоге получилась длинная регулярная поли-аланиновая α-спираль из 100 аминокислот.
from pymol import cmd, editor
# параметры
aa = "ala"
n = 100
obj = "polyA_100"
cmd.reinitialize()
# первая аминокислота
cmd.fragment(aa, obj)
cmd.alter(obj, "chain='A'")
cmd.sort(obj)
# C-концевой атом C
cterm_C = f"({obj} and name C and not (neighbor name N))"
# достраиваем цепь до 100 остатков
for _ in range(n - 1):
cmd.edit(cterm_C)
editor.attach_amino_acid("pk1", aa, ss=1)
cmd.sort(obj)
try:
cmd.bond(f"{obj} and resi 1 and name C", f"{obj} and resi 2 and name N")
except:
pass
# довернем метильную группу у последнего alanine
cmd.edit(f"{obj} and resi {n} and name CA", f"{obj} and resi {n} and name CB")
cmd.torsion(60)
cmd.unpick()
# оформление
cmd.hide("everything", obj)
#cmd.show("cartoon", obj)
#cmd.color("wheat", obj)
cmd.orient(obj)
cmd.zoom(obj)
# считаем всю цепь спиралью
cmd.alter(obj, "ss='H'")
cmd.rebuild()
# показываем только cartoon
cmd.hide("everything", obj)
cmd.show("cartoon", obj)
# делаем спираль красивее и толще
cmd.set("cartoon_fancy_helices", 1)
cmd.set("cartoon_smooth_loops", 1)
cmd.set("cartoon_tube_radius", 0.6)
cmd.set("cartoon_oval_length", 1.2)
cmd.set("cartoon_oval_width", 0.5)
# оформление
cmd.bg_color("white")
cmd.color("deepsalmon", obj)
cmd.orient(obj)
cmd.zoom(obj)
ala_png = r"C:\Users\Tata\Documents\jupyter_pol\ala.png"
cmd.png(ala_png, width=1400, height=1000, dpi=200, ray=1)
display(Image(filename=ala_png))
Задание 6¶
В этом задании я строила длинную B-форму ДНК не вручную по одному нуклеотиду, а через матрицу преобразования. Сначала я взяла из структуры 1BNA две соседние пары оснований и командой pair_fit совместила первую пару со второй по нескольким атомам сахаро-фосфатного остова. После этого с помощью get_object_matrix получила матрицу перехода от одной пары к следующей. Дальше первая пара была размножена 100 раз: каждую новую копию я создавала командой create и сдвигала на один шаг вдоль спирали командой transform_selection с той самой матрицей. В результате получилась длинная правозакрученная B-ДНК из 100 пар оснований.
from pymol import cmd
cmd.reinitialize()
cmd.fetch("1bna", "templ", type="pdb", async_=0)
cmd.remove("solvent")
# Берем НЕ концевую, а внутреннюю пару
cmd.create("pair0", "templ and ((chain A and resi 2) or (chain B and resi 23))")
cmd.create("pair", "pair0")
cmd.create("nextpair", "templ and ((chain A and resi 3) or (chain B and resi 22))")
# Совмещаем pair с nextpair по атомам сахаро-фосфатного остова
cmd.pair_fit(
"pair and chain A and resi 2 and name P", "nextpair and chain A and resi 3 and name P",
"pair and chain A and resi 2 and name C1'", "nextpair and chain A and resi 3 and name C1'",
"pair and chain A and resi 2 and name C4'", "nextpair and chain A and resi 3 and name C4'",
"pair and chain B and resi 23 and name P", "nextpair and chain B and resi 22 and name P",
"pair and chain B and resi 23 and name C1'", "nextpair and chain B and resi 22 and name C1'",
"pair and chain B and resi 23 and name C4'", "nextpair and chain B and resi 22 and name C4'"
)
# Получаем матрицу перехода
trans = cmd.get_object_matrix("pair")
# Размножаем первую пару 100 раз
cmd.create("bp001", "pair0")
prev = "bp001"
for i in range(2, 101):
name = f"bp{i:03d}"
cmd.create(name, prev)
cmd.transform_selection(name, trans)
prev = name
# Собираем все пары в один объект
cmd.create("dna100", "bp*")
# Оформление
cmd.hide("everything", "templ or pair0 or pair or nextpair or bp*")
cmd.show("cartoon", "dna100")
cmd.color("marine", "dna100 and chain A")
cmd.color("lightpink", "dna100 and chain B")
cmd.bg_color("white")
cmd.orient("dna100")
cmd.zoom("dna100", 2)
Для итоговой визуализации B-ДНК я использовала представление sticks, так как объект был собран из отдельных повторяющихся пар оснований и cartoon-режим отображался некорректно. Чтобы двойная спираль была лучше видна, радиус sticks был увеличен, поэтому модель стала более толстой и наглядной.
cmd.hide("everything", "all")
cmd.show("sticks", "dna100")
cmd.set("stick_radius", 0.29)
cmd.color("marine", "dna100 and chain A")
cmd.color("lightpink", "dna100 and chain B")
cmd.bg_color("white")
cmd.orient("dna100")
cmd.zoom("dna100", 2)
dna_b_png = r"C:\Users\Tata\Documents\jupyter_pol\dna_b.png"
cmd.png(dna_b_png, width=1400, height=1000, dpi=200, ray=1)
display(Image(filename=dna_b_png))