Как мы нашли белок

Логотип конференции PEGS Boston
С 30 апреля по 4 мая проходила моя любимая ежегодная конференция PEGS Boston. На протяжении 14 лет в дизайне логотипа и всех сопутствующих материалов этой конференции используется изображение одного и того же белка, и вот уже 13 лет подряд организаторы конференции задают вопрос: что это за белок? В этом году команда ДВБ впервые ответила на этот вопрос. И теперь главный вопрос: как?

В первую очередь давайте обратим внимание на изображение. Это cartoon-представление белка, в котором альфа-спирали заменены на цилиндры. В PyMOL подобного поведения можно добиться следующими настройками:

show_as cartoon, all
set cartoon_fancy_helices, 0
set cartoon_cylindrical_helices, 1

Также белок покрашен в режиме спектра, распределенного по длине последовательности. Самая первая аминокислота покрашена в фиолетовый, а последняя в красный. Делается это еще одной простой командой:

spectrum count, rainbow

Теперь мы можем превратить стандартное полноатомное представление
Белок в полноатомном представлении
в симпатичный вид а-ля PEGS
Белок в cartoon-представлении

Наша первая идея состояла в том, что можно нагенерировать изображений из Protein DataBank и сравнить их с нашим изображением, например, 2D-Хэммингом. Впоследствии мы отказались от этой идеи (а зря!), но скрипт генерации у нас появился:

from pymol import cmd
import os

DIR = '/path/to/locate/pdbs'
IMG = '/path/to/store/images'

if not os.path.exists(IMG):
    os.mkdir(IMG)

for ent in os.listdir(DIR):
    filename = os.path.join(IMG, "%s.png" % ent)
    if os.path.exists(filename):
        continue
    cmd.load(os.path.join(DIR, ent))
    cmd.show_as('cartoon', 'all')
    cmd.set('cartoon_fancy_helices', 0)
    cmd.set('cartoon_cylindrical_helices', 1)
    cmd.spectrum('count', 'rainbow')
    cmd.orient()
    cmd.save(filename)
    cmd.reinitialize()

Запуск через консольный режим PyMOL делается тоже просто:

pymol -qc make_images.py

Отказались мы от этой идеи по причине того, что актуальный PDB имеет уж слишком много записей. На момент написания этого поста статистика следующая:

Experimental Method Proteins Nucleic Acids Protein/NA Complex Other Total
X-Ray 117481 1919 6011 10 125421
NMR 10708 1243 249 8 12208
Electron Microscopy 1546 31 542 0 2119
Other 215 4 6 13 238
Multi Method 116 4 2 1 123
Total 130066 3201 6810 32 140109
Правильная же ориентация белка нам неизвестна и, конечно, может сильно отличаться от представленной в логотипе — ведь наверняка дизайнеры конференции повернули его. В связи с этим мы решили начать фильтровать изображение по некоторым простым признакам, которые мы смогли увидеть глядя на картинку глазами.

В этом нам очень помогло, что Саша Надолинский узнал автора изображения и нашел на его сайте картинку высокого разрешения. Из нее мы пришли к выводу, что искать требуется белок с одной цепью, в состав которого входит не менее 30 альфа-спиралей, не менее 17 из которых имею длину 5 и менее аминокислот. Также мы обратили внимание, что в начале цепи идет альфа-спираль, так что мы решили добавить это знание в наши фильтры. Единственное, мы не были уверены, что раскраска цепи каноническая от синего к красному, поскольку помимо классического режима rainbow существует также rainbow_rev, в котором все ровно наоборот. С другой стороны белка также присутствовала спираль, но не с самого начала. В связи с этим мы решили перестраховаться и сказать, что 3 позиция должна покрываться спиралью.
Разумеется, главным критерием отсева была дата: первый PEGS проводился в 2005 году, а значит белок должен был быть кристаллизован ранее. Если посмотреть на график роста размера Protein DataBank, видно, что это действительно мощнейший фильтр из всех.
rcsb_years

Итак, поехали. Предварительно нужно скачать весь Protein DataBank (у нас он был уже скачан ранее). Как это сделать, подробно можно прочитать здесь, там же дан удобный скрипт для скачивания всего добра через rsync. Мы же возьмем из него одну строчку, которая скачает нам только структуры по папочкам:

$> rsync -rlpt -v -z --delete --port=33444 rsync.wwpdb.org::ftp/data/structures/divided/pdb/ /path/to/your/local/dir > /tmp/pdb-download.log 2> /dev/null

Таким образом мы получаем все 130+ тысяч структур из RCSB PDB. Кажется, что это огромные данные, но мы будем работать с ними лишь примитивными инструментами командной строки, чтоб показать обратное. В первую очередь отберем все белки до 2005 года.

$> for filename in $(ls pdbs/*/*); do awk '$1 == "HEADER" {split($(NF-1),a,"-"); if (a[3] < 5 || a[3] > 18) {print FILENAME}}' $filename; done > pdbs_prior_2005.txt

На самом деле тот же код можно значительно ускорить, используя grep или ag для начальной фильтрации:

$> ag '^HEADER' pdbs | awk '{split($0,a,":"); split($(NF-1),b,"-"); if (b[3] < 5 || b[3] > 18) {print a[1]}}' > pdbs_prior_2005.txt

На маленьком множестве в 1000 файлов разница вот такая:

$> time (for filename in $(ls pdbs/*/*); do awk '$1 == "HEADER" {split($(NF-1),a,"-"); if (a[3] < 5 || a[3] > 18) {print FILENAME}}' $filename; done > /dev/null)
3,45s user 1,84s system 98% cpu 56,206 total

$> time (grep -e '^HEADER' pdbs/* | awk '{split($0,a,":"); split($(NF-1),b,"-"); if (b[3] < 5 || b[3] > 18) {print a[1]}}' > /dev/null)
7,34s user 0,19s system 100% cpu 7,530 total

$> time (ag '^HEADER' pdbs | awk '{split($0,a,":"); split($(NF-1),b,"-"); if (b[3] < 5 || b[3] > 18) {print a[1]}}' > /dev/null)
0,70s user 0,30s system 278% cpu 0,358 total

Очевидно, на выборке в 130+ тысяч стоит использовать ag 😉. Так или иначе, теперь у нас есть файл pdbs_prior_2005.txt, содержащий пути до всех файлов, чья дата загрузки в Protein DataBank раньше, чем 2005 год. Как и показано на графике выше, таких структур —

Теперь начнем отбирать по количеству альфа-спиралей. В первую очередь возьмем все белки с 30 и более спиралями. На этот раз сразу сделаем это эффективно:

$> cat pdbs_prior_2005.txt | xargs ag "^HELIX   30" | awk '{split($0,a,":"); print a[1]}' > pdbs_p2005_h30.txt

Следующая задача: найти 17 спиралей длиной не более 5 аминокислот. И вновь awk спасет нас, теперь благодаря возможности выполнения арифметических операций:

$> for filename in $(cat pdbs_p2005_h30.txt);do ag "^HELIX" $filename | awk 'BEGIN{i=0}{ if ($9-$6 < 6) {i++} }END{ if (i > 16) { print "'$filename'" } }'; done > pdbs_ph_h17.txt

Что же у нас получилось к текущему моменту?

$> wc -l pdbs_ph_h17.txt
2537 pdbs_ph_h17.txt

Размер файла уже достаточно разумный, всего 2537 записей, однако это всё еще слишком много, чтоб отсматривать глазами. Добавим правило про третью аминокислоту в альфа-спирали:

$> cat pdbs_ph_h17.txt | xargs ag "^HELIX    1" | awk '($6 < 3) { split($1,a,":"); print a[1] }' > pdbs_phh_aa3.txt
$> wc -l pdbs_phh_aa3.txt
142 pdbs_phh_aa3.txt

Теперь у нас есть всего 142 структуры!
Просмотрев их все глазами, мы смогли идентифицировать нужную — 1G72 (она была 117 в списке). Как оказалось, её изображение на сайте RCSB находится ровно в той же ориентации, что и на логотипе, а значит исходная идея с Хэммингом отлично бы сработала. Но это была замечательная возможность попрактиковаться в работе с инструментами командной строки над "большими" данными.