Kodomo

Пользователь

Как использовать Python при написании скриптов для PyMOL

Для тех, кто знает Python:

PyMol имеет встроенный интерпретатор Python, и любая команда, которую не понял интерпретатор командной строки PyMOL, отправляется прямиком в интерпретатор Python. Однако интерактивно (непосредственно набирая команды в командной строке PyMOL) таким образом можно писать только однострочные команды. Если вы хотите написать цикл, придется писать его в отдельный скрипт и запускать этот скрипт (ну или писать его в одну строку, по крайней мере, я другого способа не знаю). Для этого внутри цикла в том месте, где вы собираетесь писать на питоне, нужно вставить строку python, а там, где питон закончился и начался обычный PyMOL'ный синтаксис, вставить строку python end. Пример из подсказок к заданию:

   1 frag ala
   2 python 
   3 for x in range(1,25):
   4         cmd.edit(atom)
   5         editor.attach_amino_acid("pk1","ala")
   6 python end

Естественно, что в цикле мы хотим писать какие-то команды самого PyMOL'а, либо использовать доступную ему информацию. Это можно сделать с помощью модуля cmd, который реализует интерфейс к стандартным командам PyMOL. Как им пользоваться для конкретной команды, бывает, написано в описании команды на pymolwiki, а бывает, что и нигде не написано, но, в принципе, понятно :-)

Ну и можно сказать pydoc pymol, если он правильно установлен под линуксом, или в самом pymol'е сказать import pymol, потом help(pymol), если pydoc не работает (например, так можно хоть что-то узнать про модуль editor).

См. также примеры в конце.

Для тех, кто не знает Python

Если вы не знаете python, но хотите использовать все возможности PyMOL'а, то есть смысл выучить python, это очень просто. Если вы хотите просто выполнить побольше заданий, в том числе и тех, которые учат писать циклы на питоне, то, возможно, этот текст немного поможет.

Возьмем пример из подсказки к заданию и попробуем разобраться, как написать что-то подобное:

   1 mset
   2 frag ala
   3 python 
   4 for x in range(1,25):
   5         cmd.edit(atom)
   6         editor.attach_amino_acid("pk1","ala")
   7         cmd.edit(bond) e.g. atom1,atom2
   8         cmd.torsion phi
   9         cmd.edit(bond) e.g. atom1,atom2
  10         cmd.torsion psi
  11 python end
  1. Ограничиваем часть скрипта, написанную на питоне, строками python и python end. В принципе, можно этого не делать, но тогда не всю функциональность python'а можно будет использовать (в частности, индентацию).
  2. Индентация. Как вы заметили, часть кода написана с отступом. В большинстве других языков отступы делать не обязательно, и их делают только для красоты. В python отступы – это элемент синтаксиса. Если вы пишете вложенный блок кода (тело цикла или оператора условия), то этот вложенный блок должен писаться с отступом по сравнению с окружающим его кодом. Например, если вы пишете цикл:

   1 for x in range(1, 25):
   2         smth
   3         smth else
   4 smth more

то в цикле будет выполняться только то, что написано с отступом (smth и smth else). Напротив, команда smth more будет выполняться только после завершения цикла. В качетсве отступа можно использовать табуляцию или несколько пробелов. Рекомендуется использовать 4 пробела. Если вы неправильно использовали индентацию (отступы), то python скажет что-то вроде IndentationError: expected an indented block или IndentationError: unexpected indent.

  1. cmd. Чтобы вызывать команды PyMOL из питонской части скрипта, придется воспользоваться словечком cmd. На самом деле это модуль, реализующий интерфейс к командам PyMOL из интерпретатора python. Для нас сейчас важно только то, что с помощью него можно вызывать команды PyMOL следующим образом:

cmd.<имя команды>(<агрументы>)

Например, команда edit выбирает атом для редактирования. Обычно она пишется как-то так:

   1 edit resi 25 and name ca

из питона мы будем вызывать ее так:

   1 cmd.edit(“resi 25 and name ca”)

Описание того, как вызывать команду через cmd, можно частенько найти на pymolwiki в описании самой команды. Например для edit там написано:

   1 cmd.edit( string selection  [ ,string selection ] )

а для команды torsion

   1 cmd.torsion( float angle )

Что за string и float?

  1. Типы данных и переменные. Посмотрим на выражения for x in range(1,25), editor.attach_amino_acid("pk1","ala") и cmd.edit(atom), а также на предыдущий пункт. В частности, нас интересуют аргументы вызываемых функций edit, torsion, range, attach_amino_acid и edit (аргументы функций – то, что написано в скобках после имени функции и передается ей для обработки). Что-то написано в кавычках, что-то без, где-то только цифры, где-то цифры и буквы. Очевидно, что все это просто переменные, относящиеся к разным типам данных, либо по-разному заданные. Из типов данных нас интересуют только строки, целочисленные переменные и числа с плавающей точкой.

Строки (string) всегда пишутся в кавычках, например “resi 25 and name ca” - это строка. Таким обазом понятно, что когда в документации написано cmd.edit( string selection ), то это значит, что функция cmd.edit принимает в качестве аргумента строку (в данном случае, задающую выделение атомов).

Целочисленные переменные пишутся без кавычек и обозначаются словом int. Например, cmd.mset( string specification [, int frame] ) значит, что функция cmd.mset принимает два параметра, строку и целочисленную переменную. Параметры разделяются запятой:

   1 cmd.mset( “aaa”, 100 )

Числа с плавающей точкой называются float, пишутся без кавычек, но с точкой, например 3.14. Таким образом, команда cmd.torsion принимает в качестве агрумента число с плавающей точкой.

Естественно, все вышеперечисленное можно сохранить в переменную и использовать через имя переменной без всяких кавычек:

   1 atom = “resi 25 and name ca
   2 cmd.edit(atom)
  1. Циклы и списки. Циклы в питоне имеют следующий синтаксис:

   1 for <variable_name> in <iterable>:
   2         function(variable_name)
   3 

где variable_name, понятно, имя переменной, например x или i или что угодно еще, а iterable – любой объект, из которого можно брать значения и подставлять в переменную variable_name. Мы с этой целью будем использовать функцию range() и списки.

range() - позволяет писать циклы типа:

   1 for i in range(25):
   2         print i
   3 

где i последовательно принимает значения от 0 до 24 включительно (не включая 25!)

   1 for i in range(1, 26):
   2         print i
   3 

где i принимает значения от 1 до 25 включительно (не включая 26!)

   1 for i in range(1, 26, 2):
   2         print i
   3 

где i принимает значения от 1 до 25 через 2, то есть 1, 3, 5, 7,...

списки – встроенный тип данных в питоне, который позволяет хранить упорядоченное множество любых других объектов, которые записываются в квадратных скобках через запятую, например:

['n', 'ca', 'c', 'o'] – это список.

Или так:

numbers = [1.3, 1.4, 1.5]

списки можно подставлять в циклы, в таком случае переменная цикла будет последовательно принимать значения элементов списка, например:

   1 for x in ['n', 'ca', 'c', 'o']:
   2         cmd.edit(“name ” + x + “ and resi 25”)
   3         do smth
   4 

Этот цикл будет последовательно выбирать для редактирования атомы остова остатка 25. Обратите внимание, что строки можно конкатенировать с помощью плюса.

  1. Немного примеров, демонстрирующих еще кое-какие возможности, которые может быть полезно запомнить.

Например, мы хотим знать, какие номера и b-факторы имеют атомы всех остатков аспартата нашего белка (не знаю зачем, правда :-)). пишем такой скрипт (я постарался сделать его максимально сложным, чтобы показать побольше):

   1 load our_protein.pdb
   2 numbers = [] # инициализируем пустой список для номеров остатков аспартата
   3 # заполняем этот список с помощью команды iterate
   4 # кстати, полезная в целом команда :-)
   5 iterate (resn asp and name ca), numbers.append(resi)
   6 # переходим в режим python
   7 python
   8 # пишем цикл по остаткам аспартата
   9 for number in numbers:
  10         printAsp number ” + number
  11         # теперь получаем список атомов аспартата и печатаем имя атома и b-фактор
  12         residue = cmd.get_model( "resi " + number )
  13         for atom in residue.atom:
  14                 print atom.name, atom.b
  15 python end
  16 # собственно, все

Что здесь требует объяснения

numbers.append(resi) – с помощью метода append можно добавить элемент к списку

про iterate все написано в pymolwiki.

residue = cmd.get_model(), for atom in residue.atom – функция get_model возвращает объект — внутреннее представление модели белка в PyMOL. Мы присваиваем ему имя residue, потому что он содержит только атомы одного выбранного остатка ("resi " + number) . После того через точку можно дотянуться до списка атомов выбранного остатка, который хранится в полученном объекте (который теперь называется residue): residue.atom. По этому списку можно ходить циклом. (см также pymolwiki про get_model)

Еще маленький пример на цикл с range. Транслировать ca-атомы остатков с 45 по 86 через 1 на 2 ангстрема по оси x (вот уж точно никогда не понадобится).

   1 load our_protein.pdb
   2 python
   3 for number in range(45, 86, 2):
   4         cmd.translate([1, 0, 0], “resi ” + str(number) + “ and name ca”)
   5 python end

Что тут требует объяснения:

str(number) – чтобы конкатенировать строку и число, нужно число превратить в строку. Это делается функцией str. Соответствнно также можно строку превратить в целое число или число с плавающей точкой (не всякую строку, разумеется) – int(some_string) или float(some_string).