Формат FASTA: как хранят геномы
FASTA — простейший и самый распространённый текстовый формат для последовательностей. Разобрать его — обязательный навык.
FASTA — текстовый формат, где каждая запись состоит из строки-заголовка, начинающейся с символа «больше» (>), и следующих за ней строк с самой последовательностью.
Любой геном, который вы скачаете из GenBank или Ensembl, скорее всего, придёт в FASTA. Формат настолько прост, что писать парсер вручную — нормальная практика и отличное упражнение. Сделаем это и разберём подводные камни.
Как устроен FASTA
Запись = заголовок + тело. Заголовок начинается с > и содержит идентификатор и описание. Тело — последовательность, возможно разбитая на строки фиксированной ширины (часто 60 или 70 символов).
>seq1 пример гена
ATGCGTACGTTAGC
ATCGGCTAGCTAGC
>seq2 другой фрагмент
GGGCCCAAATTTОбратите внимание: одна последовательность может занимать несколько строк — это перенос для читаемости, а не разделитель записей. Записи разделяются только новой строкой-заголовком с >.
Парсер FASTA на чистом Python
Алгоритм: идём по строкам; строка с > начинает новую запись, остальные строки добавляются к текущей последовательности.
fasta = """>seq1 пример гена
ATGCGTACGTTAGC
ATCGGCTAGCTAGC
>seq2 другой фрагмент
GGGCCCAAATTT"""
def parse_fasta(text):
records = {}
name = None
for line in text.splitlines():
line = line.strip()
if not line:
continue
if line.startswith(">"):
name = line[1:].split()[0] # id до первого пробела
records[name] = ""
else:
records[name] += line
return records
for name, seq in parse_fasta(fasta).items():
print(f"{name}: длина {len(seq)} -> {seq}")Вывод:
seq1: длина 28 -> ATGCGTACGTTAGCATCGGCTAGCTAGC seq2: длина 12 -> GGGCCCAAATTT
Двенадцать строк кода — и у нас есть рабочий парсер, склеивающий многострочные последовательности и берущий чистый id из заголовка.
Зачем нужна статистика по FASTA
Получив записи, обычно сразу считают сводку: число последовательностей, общую длину, GC-состав. Это первый sanity-check: совпадает ли размер с ожидаемым, не пустой ли файл.
records = {
"seq1": "ATGCGTACGTTAGCATCGGCTAGCTAGC",
"seq2": "GGGCCCAAATTT",
}
total = sum(len(s) for s in records.values())
gc = sum(s.count("G") + s.count("C") for s in records.values())
print("Записей:", len(records))
print("Суммарная длина:", total)
print(f"Общий GC-состав: {gc / total * 100:.1f}%")Вывод:
Записей: 2 Суммарная длина: 40 Общий GC-состав: 52.5%
Как работает под капотом: почему не split по >
Соблазнительно сделать text.split(">"), но это хрупко: символ > теоретически может встретиться в описании, а пустые куски придётся отбрасывать. Построчный конечный автомат (заголовок/тело) надёжнее и работает потоково — можно читать гигантский файл, не загружая целиком в память.
Формат FASTA родился ещё в 1985 году как часть программы FASTA для поиска сходства последовательностей — отсюда и название. Его пережили десятки более «умных» форматов именно из-за простоты: это просто текст, который читается глазами, грепается, режется стандартными утилитами Unix. У формата есть негласные соглашения, о которых полезно знать. Идентификатор в заголовке часто кодирует источник: например, строка вида sp|P69905|HBA_HUMAN в базе UniProt означает запись из Swiss-Prot с номером P69905. Описание после id человекочитаемое и в анализе обычно игнорируется. Расширения файлов варьируются (.fasta, .fa, .fna для нуклеотидов, .faa для белков), но внутри это всё тот же формат.
Отдельно стоит сжатие. Геномные FASTA-файлы огромны, поэтому почти всегда хранятся сжатыми (обычно gzip, расширение .fasta.gz). На практике их читают «на лету» через модуль gzip стандартной библиотеки, не распаковывая на диск, — это экономит и место, и время. Наш построчный парсер работает с такими файлами без изменений: достаточно открыть файл через gzip.open(path, "rt") вместо обычного open, а дальше логика та же. Это ещё один довод в пользу потокового, а не загружающего-всё-в-память подхода.
Частые ошибки
- Считать каждую строку тела отдельной последовательностью. Многострочное тело надо склеивать до следующего >.
- Брать весь заголовок как id. Обычно id — это часть до первого пробела, остальное — описание.
- Загружать огромный файл целиком. Для геномов читайте построчно (потоково).
Итог
- FASTA — текстовый формат: строка-заголовок с > плюс одна или несколько строк последовательности.
- Парсер строится как построчный автомат: > начинает запись, прочие строки добавляются к телу.
- Id берут до первого пробела; тело склеивают из всех строк до следующего заголовка.
- После парсинга считают сводку (число записей, длину, GC) как первичную проверку.