Skip to content

Open-source toolkit that simplifies and speeds up work with bioinformatics data. high-perf-bio allows you easily upload VCF, BED or arbitrary tables to DB and execute popular bioinformatic queries without MongoDB Query Language knowledge.

License

Notifications You must be signed in to change notification settings

PlatonB/high-perf-bio

Repository files navigation

Синопсис.

Биоинформатика — это не только BWA/GATK/Samtools/VEP/продолжите-список-сами, но и беспросветная табличная рутина. Поэтому любой биоинформатик хранит жирную папку со скриптами, а также богатую историю команд, задействующих coreutils. Форумы завалены bash/awk-однострочниками для решения мелких и не очень задач парсинга. Мало того, что парсеров целый зоопарк, так они ещё и медленные все. Есть, правда, tabix и bedtools, которые частично закрывают проблему производительности благодаря самописным B-tree-алгоритмам. Но они обеспечивают быстрый рандомный доступ только по геномным координатам. А если, предположим, надо найти набор rsIDs и отсечь результаты по p-value?

HIGH-PERF-BIO ПОЗВОЛЯЕТ СОЗДАВАТЬ ПОЛНОЦЕННЫЕ БАЗЫ ДАННЫХ НА ОСНОВЕ ТАБЛИЦ И ЗА ДОЛИ СЕКУНДЫ ВЫПОЛНЯТЬ НАИБОЛЕЕ ПОПУЛЯРНЫЕ В БИОИНФОРМАТИКЕ ДЕЙСТВИЯ ☚

Для VCF создаются многоуровневые документы, что открывает возможность глубоко парсить INFO и генотипные поля.

Проиндексировать можно какие угодно поля и группы полей. Индекс редко используется и занимает много места? Можно его удалить, и, если что, потом создать заново отдельным менеджером — reindex.

Флагманские компоненты проекта — три аннотатора (annotate, dock, ljoin), уникальность которых заключается в свободе выбора характеризуемого столбца и отсутствии привязки к определённому кэшу данных. Грубо говоря, можно аннотировать что угодно по чему угодно.

Что касается фильтрации, то в инструментарии имеется удивительная по своей универсальности программа — query. Можете написать любые MongoDB-запросы на целую научную работу вперёд и хлопнуть их разом. Сочинять запросы - одно удовольствие, т.к. синтаксис MongoDB страшно прост и отлично задокументирован.

По состоянию на начало 2022 года я ещё не видел высокоуровневые программы-группировщики данных. Видимо, считается, что суровый дата-сайнтист всякий раз группирует руками в pandas или какой-нибудь СУБД. Но если вдруг хочется одной командой — такое умеют, скорее всего, лишь count и split.

Вдобавок, компоненты тулкита способны делать такие характерные для стандартных линуксовых утилит штуки, как конкатенация данных, отбор полей и сортировка значений. Но на огромных скоростях и без заковыристого синтаксиса.

Компоненты.

Ядро.

Наиболее универсальные и фичастые программы для взаимодействия с БД.

Программа Основная функциональность
annotate получает характеристики табличного столбца по всем коллекциям БД; поддерживается пересечение координат
concatenate объединяет коллекции; есть опциональная фича удаления дублей документов
count считает количество и частоту элементов каждого набора взаимосвязанных значений разных полей
create создаёт новую или дописывает старую БД по VCF, BED или нестандартным таблицам; производит индексацию коллекций
dock получает характеристики табличного столбца по всем коллекциям и самим таблицам; поддерживается пересечение координат
ljoin фильтрует одни коллекции по наличию/отсутствию значений в других; возможна работа с координатами
info выводит имена или основные свойства имеющихся БД
query выполняет наборы произвольных запросов по всем коллекциям
reindex удаляет и строит индексы коллекций
split дробит коллекции по значениям какого-либо поля

Плагины.

Узкоспециализированные парсеры БД с минимумом настроек.

Программа Основная функциональность
revitalize_id_column восполняет столбец ID VCF-файлов идентификаторами вариантов из БД

Скрипты.

Полезные инструменты для работы с таблицами (не базами).

Программа Основная функциональность
count_lines выдаёт различные метрики, касающиеся количества табличных строк
gen_test_files создаёт из одной таблицы N меньших таблиц

Архитектура.

Что происходит с обрабатываемыми данными с точки зрения программиста: high-perf-bio_architecture

Преимущества.

  • Высокая скорость работы:
    • параллельная обработка нескольких файлов или коллекций;
    • в основе — известная своей отменной производительностью СУБД MongoDB.
  • Простота запуска:
    • самому тулкиту не требуется установка, можно запускать и с флешки;
    • обязательные аргументы - только пути к папкам и имя БД.
  • Наглядность:
    • есть инструмент вывода примерной структуры интересующей БД.
    • для просмотра баз также существует бесплатный MongoDB Compass.
  • Автоматизация:
    • одна команда — обработка всех коллекций базы.
    • полностью автоматическое чтение и создание VCF/BED.
  • Гибкость:
    • индексируемые, а значит быстро парсимые, вложенные поля.
  • Конвейерность:
    • результаты можно перенаправлять в другую БД, минуя создание конечных файлов (но есть баг).
  • Техподдержка:
    • -h: вывод тщательно продуманной справки по синтаксису команд.
    • Тьюториал прямо в этом ридми.
    • Всегда бесплатная консультация.

Недостатки.

  • Высокая производительность возможна лишь при вытаскивании небольших частей коллекций. Преимущество в скорости теряется, если запросить, к примеру, половину dbSNP.
  • Проблемы с производительностью при запросах по нескольким полям, несмотря на задействование индексов.
  • Индексы целиком размещаются в RAM. Готовьтесь к тому, что придётся запихивать в оперативку весящий 15.6 ГБ индекс поля ID dbSNP.
  • Наличие виртуальных ядер процессора не обеспечивает прироста скорости при распараллеливании. hpb_create_benchmark
  • Инструмент ljoin не использует индексы при пересечении/вычитании по геномным координатам. Создатели MongoDB знают о лежащей в основе проблеме, и, надеюсь, когда-нибудь исправят.
  • При скидывании результатов в другую БД сбивается последовательность полей. Голосуйте за исправление этого бага тут (может потребоваться VPN).

Перед началом работы.

Чудо-команда установки.

wget https://github.com/PlatonB/high-perf-bio/archive/refs/heads/master.zip && unzip -o master.zip && rm master.zip && cd high-perf-bio-master && bash __install_3rd_party.sh

Тулкит скачан и распакован, зависимости разрешены. В принципе, теперь можно приступать к эксплуатации. Но при желании ознакомиться с нюансами установки читайте идущие следом разделы.

Установка сторонних компонентов.

Программа Предназначение
MongoDB собственно, размещает данные в базы, индексирует поля и выполняет запросы
PyMongo позволяет сабжевому Python-тулкиту бесшовно работать с MongoDB-базами
Streamlit основа для веб-интерфейса этого инструментария

Установка MongoDB сложновата из-за невероятно абсурдного решения признать новую лицензию MongoDB несвободной, повлекшего не менее идиотское удаление продукта из штатных репозиториев линуксовых дистрибутивов. Но в декабре-2022 в составе тулкита появился скрипт, ставящий MongoDB и другие необходимые high-perf-bio сторонние решения одной командой. Выполните 5 элементарных действий:

  1. Скачайте архив с инструментарием.
  2. Распакуйте его в любую папку.
  3. В терминале перейдите в папку high-perf-bio-master:
cd /path/to/high-perf-bio-master
  1. Разрешите зависимости:
bash __install_3rd_party.sh
  1. Перезагрузитесь, иначе не заработает GUI тулкита.

Удаление сторонних компонентов.

Это делается так же просто, как и установка:

  1. cd /path/to/high-perf-bio-master
  2. bash __uninstall_3rd_party.sh

Примечания.

  • Если хотите установить MongoDB вручную, то на официальном сайте СУБД есть подробные инструкции.
  • Скрипт-инсталлятор, найдя папку miniconda3 в домашнем каталоге, установит Streamlit с помощью Conda. В противном случае будет задействован Pip.
  • Скрипт-инсталлятор ставит PyMongo исключительно через Pip, ибо Conda-версия этого драйвера неработоспособна.
  • Скрипт-деинсталлятор не удаляет Pip-зависимости Streamlit.
  • Скрипт-деинсталлятор беспощадно сносит /etc/mongod.conf и другие конфиги. Если вы их правили, забэкапьте.
  • Windows. Теоретически, после установки MongoDB и whl-пакетов PyMongo + Streamlit программа должна работать. Но у меня сейчас этой ОС нет, и я пока не проверял. Надеюсь, кто-нибудь поделится опытом в Issues.

Произвольное расположение MongoDB-данных.

(опционально)

К примеру, у вас есть до неприличия маленький SSD и вполне просторный HDD (далее - V1). И так случилось, что MongoDB заталкивает базы и логи в первое из перечисленных мест. Как сделать, чтобы эти данные хостились на V1?

  1. Создайте папку для БД и лог-файл.
mkdir /mnt/V1/mongodb
touch /mnt/V1/mongod.log

P.S. Можно было и через файл-менеджер;).

  1. Предельно аккуратно укажите пути к свежеупомянутым папке и файлу в главном конфиге MongoDB:
sudo nano /etc/mongod.conf
<...>
storage:
  dbPath: /mnt/V1/mongodb
<...>
systemLog:
  <...>
  path: /mnt/V1/mongod.log
<...>

Сохраните изменения (CTRL+S) и выйдите из редактора (CTRL+X).

  1. Предоставьте необходимые права доступа нашим переселенцам:
sudo chown mongodb -R /mnt/V1/mongodb
sudo chown mongodb -R /mnt/V1/mongod.log

MongoDB Compass.

(опционально)

Рекомендую устанавливать с Flathub. Compass - родной GUI к MongoDB. В нашем случае он позволяет использовать high-perf-bio не вслепую: делает возможным просмотр создаваемых компонентами тулкита коллекций и индексов. Compass также даёт простор для ручного/продвинутого администрирования БД: составлять запросы, оценивать их производительность, экспериментировать с агрегациями и т.д.. MongoDB_Compass_high-perf-bio

GUI.

В июне 2022 года графический интерфейс на основе Streamlit достиг функционального паритета с консольным. Но, живя в мире биоинформатики, лучше привыкать к командной строке.

Запуск GUI.

Gnome.

Правой кнопкой по __run_gui_streamlit.sh --> Свойства --> Права --> галочку на Разрешить выполнение файла как программы. Это надо сделать лишь однократно. В контекстном меню __run_gui_streamlit.sh появится пункт Запустить как программу. Каждый раз после нажатия на Запустить как программу будет открываться вкладка браузера с GUI к high-perf-bio, а также, с чисто технической целью, окно Терминала. Как закончите работать с тулкитом, просто закройте и то, и другое.

KDE.

Правой кнопкой по __run_gui_streamlit.sh --> Свойства --> Права --> галочку на Является выполняемым --> OK. Правой кнопкой по __run_gui_streamlit.sh --> Открыть с помощью... --> Другое приложение... --> Система --> выделите Konsole --> OK. Вылезет консоль - закройте её. Левой кнопкой по __run_gui_streamlit.sh --> галочку на Больше не задавать этот вопрос --> Запустить. Вышеперечисленное надо сделать лишь один раз. После этих манипуляций GUI будет напрямую запускаться левым кликом по __run_gui_streamlit.sh.

Командная строка.

streamlit run _gui_streamlit.py

Тьюториал.

Основы и игрушечные примеры.

Управление через командный и графический интерфейсы схоже, и здесь для краткости я буду приводить только команды.

Чтобы не прописывать каждый раз путь к тому или иному компоненту, перейдём в основную папку инструментария.

cd $HOME/Биоинформатика/high-perf-bio-master

Примечание: корректируйте приведённые в примерах пути в зависимости от реального расположения ваших папок или файлов.

Для удобства можете вывести имена всех программ проекта high-perf-bio.

ls -R

Каждый инструмент содержит подробную справку. Пока с ней не ознакомились, реальные задачи не запускайте.

python3 create.py -h
python3 annotate.py -h

и т.д..

У меня нет цели продемонстрировать в тьюториале все аргументы программ. Наоборот, хочу показать, как обойтись минимумом таковых.

В папке high-perf-bio-master уже есть небольшие примеры данных. Но в качестве материала для базы лучше скачать что-то серьёзное, например, VCF-таблицу всех SNP. Переименуйте её, добавив расширение vcf перед gz.

Поскольку формат этого файла — VCF, программа создания БД сама отбросит метастроки, сконвертирует хромосомы из HGVS в обычный вид, преобразует ячейки определённых столбцов в BSON-структуры и проиндексирует поля с хромосомами, позициями и rsIDs. Файл — один, значит, распараллелить заливку не удастся. Таким образом, команда может получиться весьма минималистичной. Достаточно подать путь к папке со свежескачанным VCF.

python3 create.py -S $HOME/Биоинформатика/dbSNP

При работе с high_perf_bio высока вероятность возникновения двух проблем: вы забыли, как называется БД и из чего она состоит. В таких ситуациях перед запуском любого парсера требуется получить представление о парсимой БД. Для начала найдите её имя в списке всех имён.

python3 info.py

Затем выведите первостепенные характеристики конкретной базы.

python3 info.py -d dbSNP

Теперь мы многое знаем о БД и можем, к примеру, осуществить по ней запрос. Для разминки отберём снипы интервала chr14:105746998-105803861, упомянутого в статье "Локусы влияющие на экспрессию антигенов HLA в участке 14-й хромосомы, ассоциированном с развитием рассеянного склероза, и функции расположенных в них генов" (П.А. Быкадоров и др.). Создадим текстовый файл get_ms_locus.txt, впишем туда запрос и выполним его программой query. Помните, что операторы и строковые значения надо заключать в кавычки (неважно, одинарные или двойные), а целочисленные значения оставлять без ничего. Содержимое get_ms_locus.txt:

{'#CHROM': 14, 'POS': {'$gte': 105746998, '$lte': 105803861}}

Команда, которая прочитает запрос из файла и выполнит его:

python3 query.py -S $HOME/Биоинформатика/toy_queries/get_ms_locus.txt -D dbSNP -T $HOME/Биоинформатика/ms_locus

Кстати, инструмент query гораздо мощнее, чем могло показаться по примеру выше. Можно задавать не один, а сколько угодно запросов, а также тематически распределять их по разным файлам.

Ещё, чтобы лучше привыкнуть к high_perf_bio, найдём характеристики вариантов из папки high-perf-bio-master/test_data/TSV. С расположением rsID-столбца повезло — он первый. С единственной коллекцией базы dbSNP тоже всё ок — поскольку это ex-VCF, то там есть поле ID. Значит, обойдёмся минимумом аргументов: пути к папке с игрушечной таблицей и конечной папке, имя базы и игнор табличной шапки.

python3 annotate.py -S $HOME/Биоинформатика/high-perf-bio-master/test_data/TSV -D dbSNP -T $HOME/Биоинформатика/TSV_ann -m 1

Пример чуть посерьёзнее.

А вот задача явно ближе к реальной биоинформатике. Вы когда нибудь задумывались, есть ли на свете варианты, являющиеся eQTL сразу во всех тканях? Сейчас посмотрим. Скачаем таблицы пар вариант-ген. Нам понадобятся только *.signif_variant_gene_pairs.txt.gz-файлы. Таблицы так себе приспособлены к анализу: координаты, аллели и номер сборки запихнуты в один столбец, а rsIDs вовсе отсутствуют. Сконвертировать это непарсибельное хозяйство в VCF предлагаю скриптом, а обогатить VCFs сниповыми идентификаторами — high-perf-bio-плагином revitalize_id_column. Дарить rsIDs VCF-файлам готова ранее созданная нами MongoDB-версия dbSNP. Насыщение поля ID идентификаторами может оказаться неполным. Чтобы не оставалось строк с точками, добавим аргумент -r.

cd plugins
python3 revitalize_id_column.py -S $HOME/Биоинформатика/GTEx_Analysis_v8_eQTL_VCF -D dbSNP -T $HOME/Биоинформатика/GTEx_Analysis_v8_eQTL_VCF_rsIDs -r

Зальём удобоваримую версию GTEx-таблиц в базу. Коллекций — несколько десятков, поэтому лично я предпочёл бы распараллелить размещение и индексацию на 8 процессов.

python3 create.py -S $HOME/Биоинформатика/GTEx_Analysis_v8_eQTL_VCF_rsIDs -d GTEx -p 8

Напомню, мы хотели найти варианты, дающие о себе знать во всех тканях. Применим алгоритм пересечения. Что такое левые/правые коллекции и охват, подробно рассказано в справке ljoin — здесь я на этом останавливаться не буду. Указываем в явном виде одну левую коллекцию. Любую. Правыми коллекциями для решения задачи надо сделать все остальные, но перечислять их не нужно — в программе такой сценарий предусмотрен по умолчанию. То, что нам нужно пересекать, а не вычитать, опять же, явно прописывать не обязательно. С наличием идентификаторов у нас проблем нет, поэтому можно работать по ним, хотя координатные вычисления программой тоже поддерживаются. Подавать аргумент с именем пересекаемого поля не будем, т.к. по дефолту идёт ID. eQTL нам общие для всех тканей надо найти? Значит, задаём охват максимальный. Он равен количеству всех коллекций минус 1 (вычли одну левую). Программа, кстати, позволяет исследователю не тратить время на определение этого значения, а указать 0.

python3 ljoin.py -D GTEx -T $HOME/Биоинформатика/GTEx_common -l Adipose_Subcutaneous.v8.signif_variant_gene_pairs_rsIDs.vcf -c 0

Вездесущие eQTL обнаружились, и их 224045 штук. А сколько будет вариантов, влияющих на экспрессию генов только в крови и больше нигде? Это решается вычитанием.

python3 ljoin.py -D GTEx -T $HOME/Биоинформатика/GTEx_onlyWB -l Whole_Blood.v8.signif_variant_gene_pairs_rsIDs.vcf -a subtract -c 0

Таких уникальных вариантов — 86051 из 2399784 кровяных.

Найти что ли клинически значимые варианты среди эксклюзивно кровяных? Воспользуемся таблицей ассоциаций вариант-патология проекта DisGeNET. Эта таблица — небиоинформатического формата, поэтому при создании на её основе базы и дальнейшей работе с этой базой применимы не все удобные умолчания.

python3 create.py -S $HOME/Биоинформатика/DisGeNET -s semicolon -i snpId,chromosome,position

Можно, кстати, из этой БД создать новую, которая разбита на похромосомные коллекции, урезанные до 5 самых необходимых полей.

python3 split.py -D DisGeNET -T DisGeNET_chrs -f chromosome -k snpId,chromosome,position,diseaseName,score -i snpId,chromosome,position

Ой, кажется, забыли проиндексировать поле со скорами ассоциаций. С кем не бывает? Воспользуемся штатным редактором индексов, чтобы потом программы, отсекающие малоподтверждённые пары, не тратили силы на тупой перебор скоров.

python3 reindex.py -D DisGeNET_chrs -a score

Теперь, наконец, аннотируем уникальные Whole Blood eQTLs по DisGeNET. Результаты кидаем в свежую БД.

python3 annotate.py -S $HOME/Биоинформатика/GTEx_onlyWB -D DisGeNET_chrs -T GTEx_onlyWB_Clin -f snpId -i snpId,chromosome,position,score

Хоть какое-то упоминание в DisGeNET имеют 1914 кровяных вариантов. Отбирём наиболее клинически значимые. Как в DisGeNET присваиваются скоры? Если ассоциация упоминается в отобранных нейросетевым парсером BeFree статьях, ей прибавляют скор 0.01 * количество_статей, но не более 0.1. Если ассоциация взята из одного курируемого источника (UniProt, ClinVar, GWAS Catalog, GWASdb) - то за ней сразу бронируется аж 0.7. Два курируемых источника - 0.8, три и более - 0.9. Хочется, конечно, выставить 0.9, но тогда ничего не останется. Сделаем 0.81, чтобы связь подтверждалась, как минимум, двумя солидными базами и одной статьёй.

{'score': {'$gte': Decimal128('0.81')}}
python3 query.py -S $HOME/Биоинформатика/queries/parse_GTEx.txt -D GTEx_onlyWB_Clin -T GTEx_onlyWB_strongClin

Результаты разбросаны по хромосомам, а названия болезней иногда дублируются. Как тогда собрать список болезней? Очень просто: сконкатенировать коллекции, применив подходящие опции. Поскольку мы используем отбор полей, -u уникализирует не целиковые документы, а усечённые с помощью -k.

python3 concatenate.py -D GTEx_onlyWB_strongClin -T GTEx_onlyWB_081Dis -k diseaseName -u

Результат. Варианты, влияющие на экспрессию генов исключительно в крови, обуславливают развитие, вероятнее всего, перечисленных 10 патологий: "Psoriasis", "Inflammatory Bowel Diseases", "Vitiligo", "Crohn Disease", "Diabetes Mellitus, Non-Insulin-Dependent", "Age related macular degeneration", "ovarian neoplasm", "Behcet Syndrome", "IGA Glomerulonephritis", "Hirschsprung Disease".

Расскажите о применении high_perf_bio в своих исследованиях!

Механизм пересечения и вычитания.

Этот раздел — попытка максимально доступно объяснить, как работает программа ljoin.

Терминология.

Термин Аналог в реляционных БД Аналог в Python Пример Пояснение
Поле Столбец Ключ словаря 'f1' Может присутствовать в одних документах и при этом отсутствовать в других
Документ Строка Словарь {'f1': 1, 'f2': 'one', 'f3': 'c1.txt'} Объект из пар поле-значение. В качестве значений могут быть вложенные объекты
Коллекция Таблица Список словарей Набор, как правило, объединённых по смыслу документов

Тестовые данные.

В качестве примера будет БД из трёх игрушечных коллекций, которые легко пересекать и вычитать в уме. _id-поле здесь и далее опускается.

Коллекция c1.

{'f1': 1, 'f2': 'one', 'f3': 'c1.txt'}
{'f1': 2, 'f2': 'two', 'f3': 'c1.txt'}
{'f1': 3, 'f2': 'three', 'f3': 'c1.txt'}
{'f1': 4, 'f2': 'four', 'f3': 'c1.txt'}
{'f1': 5, 'f2': 'five', 'f3': 'c1.txt'}

Коллекция c2.

{'f1': 3, 'f2': 'three', 'f3': 'c2.txt'}
{'f1': 4, 'f2': 'four', 'f3': 'c2.txt'}
{'f1': 5, 'f2': 'five', 'f3': 'c2.txt'}
{'f1': 6, 'f2': 'six', 'f3': 'c2.txt'}
{'f1': 7, 'f2': 'seven', 'f3': 'c2.txt'}

Коллекция c3.

{'f1': 5, 'f2': 'five', 'f3': 'c3.txt'}
{'f1': 6, 'f2': 'six', 'f3': 'c3.txt'}
{'f1': 7, 'f2': 'seven', 'f3': 'c3.txt'}
{'f1': 8, 'f2': 'eight', 'f3': 'c3.txt'}
{'f1': 9, 'f2': 'nine', 'f3': 'c3.txt'}

Параметры отбора документов левой коллекции.

По справке к ljoin вы уже знаете, что каждая из коллекций, условно обозначенных как "левые", фильтруется по всем "правым". Левой пусть будет c1, а в качестве правых — c2 и c3. Непосредственно обрабатываемое поле — допустим, f1. Общее представление об условях отбора документов c1:

Действие Охват Документ из c1 сохраняется, если
пересечение 1 совпадение в c2 или c3
пересечение 2 совпадение в c2 и c3
вычитание 1 несовпадение в c2 или c3
вычитание 2 несовпадение в c2 и c3

Решение.

Стадии.

  1. Левостороннее внешнее объединение. Независимо от того, хотим мы пересекать или вычитать, выполнение $lookup-инструкции лишь объединит коллекции. Каждый документ, получающийся в результате объединения, содержит: 1. все поля документа левой коллекции; 2. поля с соответствиями из правых коллекций (далее — результирующие). Если для элемента выбранного поля данного левого документа не нашлось совпадений в одной из правых коллекций, то в результирующем поле появится пустой список (Python-представление Null-значения из мира баз данных). Если же совпадение имеется, то в качестве значения результирующего поля возвратится список с содержимым соответствующего правого документа. Если выявилось совпадение с несколькими документами какой-то одной правой коллекции, то они в полном составе поступят в результирующее поле.

Схема объединённого документа.

{левый документ, псевдоним правой коллекции 1: [правый документ 1.1, правый документ 1.2, ...],
                 псевдоним правой коллекции 2: [правый документ 2.1, правый документ 2.2, ...],
                 ...}

Объединённые документы тестовых коллекций (c1 vs c2, c3).

{'f1': 1, 'f2': 'one', 'f3': 'c1.txt', 'c2': [], 'c3': []}
{'f1': 2, 'f2': 'two', 'f3': 'c1.txt', 'c2': [], 'c3': []}
{'f1': 3, 'f2': 'three', 'f3': 'c1.txt', 'c2': [{'f1': 3, 'f2': 'three', 'f3': 'c2.txt'}], 'c3': []}
{'f1': 4, 'f2': 'four', 'f3': 'c1.txt', 'c2': [{'f1': 4, 'f2': 'four', 'f3': 'c2.txt'}], 'c3': []}
{'f1': 5, 'f2': 'five', 'f3': 'c1.txt', 'c2': [{'f1': 5, 'f2': 'five', 'f3': 'c2.txt'}], 'c3': [{'f1': 5, 'f2': 'five', 'f3': 'c3.txt'}]}

То же самое в схематичном виде (l — документ левой коллекции, r№a — alias (псевдоним) правой; 0 — в правой нет совпадений, 1 — есть одно).

l, r1a: 0, r2a: 0
l, r1a: 0, r2a: 0
l, r1a: 1, r2a: 0
l, r1a: 1, r2a: 0
l, r1a: 1, r2a: 1
  1. Фильтрация. Изучая предыдущий пункт, вы уже, наверное, догадались, что пересекать или вычитать — значит, фильтровать результаты объединения по количеству непустых или пустых результирующих списков соответственно.

Пересечение. Охват 1.

Чтобы значение левого поля f1 попало в результаты, такое же значение должно найтись хотя бы в одном правом f1.

Объединённые документы, отвечающие условию.

{'f1': 3, 'f2': 'three', 'f3': 'c1.txt', 'c2': [{'f1': 3, 'f2': 'three', 'f3': 'c2.txt'}], 'c3': []}
{'f1': 4, 'f2': 'four', 'f3': 'c1.txt', 'c2': [{'f1': 4, 'f2': 'four', 'f3': 'c2.txt'}], 'c3': []}
{'f1': 5, 'f2': 'five', 'f3': 'c1.txt', 'c2': [{'f1': 5, 'f2': 'five', 'f3': 'c2.txt'}], 'c3': [{'f1': 5, 'f2': 'five', 'f3': 'c3.txt'}]}

Схема соответствующих условию объединённых документов.

l, r1a: 1, r2a: 0
l, r1a: 1, r2a: 0
l, r1a: 1, r2a: 1

Окончательный результат в табличном виде.

f1 f2 f3
3 three c1.txt
4 four c1.txt
5 five c1.txt

Пересечение. Охват 2.

Чтобы значение левого поля f1 попало в результаты, такое же значение должно найтись в двух правых f1.

Объединённый документ, отвечающий условию.

{'f1': 5, 'f2': 'five', 'f3': 'c1.txt', 'c2': [{'f1': 5, 'f2': 'five', 'f3': 'c2.txt'}], 'c3': [{'f1': 5, 'f2': 'five', 'f3': 'c3.txt'}]}

Схема соответствующего условию объединённого документа.

l, r1a: 1, r2a: 1

Окончательный результат в табличном виде.

f1 f2 f3
5 five c1.txt

Вычитание. Охват 1.

Чтобы значение левого поля f1 попало в результаты, такого же значения не должно быть хотя бы в одном правом f1.

Объединённые документы, отвечающие условию.

{'f1': 1, 'f2': 'one', 'f3': 'c1.txt', 'c2': [], 'c3': []}
{'f1': 2, 'f2': 'two', 'f3': 'c1.txt', 'c2': [], 'c3': []}
{'f1': 3, 'f2': 'three', 'f3': 'c1.txt', 'c2': [{'f1': 3, 'f2': 'three', 'f3': 'c2.txt'}], 'c3': []}
{'f1': 4, 'f2': 'four', 'f3': 'c1.txt', 'c2': [{'f1': 4, 'f2': 'four', 'f3': 'c2.txt'}], 'c3': []}

Схема соответствующих условию объединённых документов.

l, r1a: 0, r2a: 0
l, r1a: 0, r2a: 0
l, r1a: 1, r2a: 0
l, r1a: 1, r2a: 0

Окончательный результат в табличном виде.

f1 f2 f3
1 one c1.txt
2 two c1.txt
3 three c1.txt
4 four c1.txt

Вычитание. Охват 2.

Чтобы значение левого поля f1 попало в результаты, такого же значения не должно быть в двух правых f1.

Объединённые документы, отвечающие условию.

{'f1': 1, 'f2': 'one', 'f3': 'c1.txt', 'c2': [], 'c3': []}
{'f1': 2, 'f2': 'two', 'f3': 'c1.txt', 'c2': [], 'c3': []}

Схема соответствующих условию объединённых документов.

l, r1a: 0, r2a: 0
l, r1a: 0, r2a: 0

Окончательный результат в табличном виде.

f1 f2 f3
1 one c1.txt
2 two c1.txt

Повторы.

В конечный файл направятся все дубли элемента, находящиеся в пределах поля левой коллекции, но от повторов правых элементов копийность результатов не зависит.

Задавайте вопросы!

Понятно, что реальные данные гораздо сложнее, чем раз-два-три-четыре-пять. Кидайте свои задачи на пересечение или вычитание в Issues — подскажу, как решить.

Полезные советы.

Метастроки.

У части тулзов high_perf_bio есть опция --meta-lines-quan/-m. Она даёт программе знать, сколько строк в начале файла не нужно никак трогать. Эти строки содержат т.н. метаинформацию, которая посвящает исследователя в различные особенности файла. Программам же они, как правило, только мешают. VCF — формат довольно строгий, и там метастроки чётко обозначены символами ##, что даёт возможность скипать их автоматически. Для остальных форматов требуется ручное указание количества игнорируемых строк. Как это количество узнать? Если файл маленький, просто откройте его в обычном блокноте. В хороших блокнотах, как, например, elementary OS Code, есть нумерация строк, что облегчает задачу. Если же файл большой, то так сделать не получится — в лучшем случае вылезет ошибка, в худшем — осложните себе работу зависанием. Вас раздражает командная строка? Можете считывать первые строки сжатого файла скриптом-предпросмотрщиком из моего репозитория bioinformatic-python-scripts. Уже привыкли к эмулятору терминала? Тогда юзайте командную утилиту zless.

zless -N $HOME/Биоинформатика/dbSNP_common/00-common_all.vcf.gz

Скроллить можно колесом мыши или двумя пальцами вверх-вниз по тачпаду. Закрыть предпросмотр: q.

Спецсимволы.

В ту или иную команду могут закрасться зарезервированные символы. Командная оболочка, на них наткнувшись, не сможет обработать вашу команду как единое целое. Я, к примеру, при тестировании high_perf_bio получил ошибку из-за решётки в начале имени хромосомного поля.

python3 create.py -S $HOME/Биоинформатика/dbSNP_common -i #CHROM,POS,ID
create.py: error: argument -i/--ind-col-names: expected one argument

Из-за наличия решётки интерпретатор подумал, что CHROM,POS,ID — комментарий, а не перечисление индексируемых полей. Получилось, что аргумент -i, строго требующий значения, остался без такового. Надо было просто взять набор имён полей в одинарные кавычки (заэкранировать).

python3 create.py -S $HOME/Биоинформатика/dbSNP_common -i '#CHROM,POS,ID'

А знаете, почему программы high_perf_bio заставляют перечислять что-либо через запятую без привычного нам по естественным языкам пробела? Не подумайте, что из вредности:). Пробел считается границей между аргументами. Т.е., при использовании запятых с пробелом каждый следующий элемент воспринимался бы шеллом в качестве нового аргумента.

python3 create.py -S $HOME/Биоинформатика/high-perf-bio-master/test_data/TSV -i SYMBOL, AF
create.py: error: unrecognized arguments: AF

Требование перечислять без пробела я ввёл, чтобы избавить вас от необходимости экранирования. Правильное оформление последней команды не подразумевает обязательного наличия надоедливых кавычек.

python3 create.py -S $HOME/Биоинформатика/high-perf-bio-master/test_data/TSV -i SYMBOL,AF

About

Open-source toolkit that simplifies and speeds up work with bioinformatics data. high-perf-bio allows you easily upload VCF, BED or arbitrary tables to DB and execute popular bioinformatic queries without MongoDB Query Language knowledge.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published