Комплемент и обратный комплемент

Из одной нити ДНК легко получить парную. Но «правильная» парная нить — это обратный комплемент, а не просто комплемент.

Обратный комплемент — последовательность, которую читают на второй нити ДНК в направлении 5'→3': берём комплемент каждой буквы и переворачиваем результат.

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

Комплемент против обратного комплемента

Комплемент — просто заменить каждую букву на парную (A↔T, G↔C). Но из-за антипараллельности нитей вторую нить читают в обратном направлении. Поэтому биологически осмысленна именно обратная комплементарная строка.

Нить 1 (5'->3'):  A T G C
комплемент:       T A C G   <- та же ориентация
Нить 2 (5'->3'):  C G T A   <- обратный комплемент (читаем справа налево)
pairs = {"A": "T", "T": "A", "G": "C", "C": "G"}

def complement(seq):
    return "".join(pairs[b] for b in seq)

def reverse_complement(seq):
    return "".join(pairs[b] for b in reversed(seq))

dna = "ATGCGGT"
print("Исходная:           ", dna)
print("Комплемент:         ", complement(dna))
print("Обратный комплемент:", reverse_complement(dna))

Вывод:

Исходная:            ATGCGGT
Комплемент:          TACGCCA
Обратный комплемент: ACCGCAT

Элегантный приём через str.translate

Перебор по буквам читаем, но есть идиоматичный быстрый способ — таблица трансляции символов.

table = str.maketrans("ATGC", "TACG")

def reverse_complement(seq):
    return seq.translate(table)[::-1]

print(reverse_complement("AAAACCCGGT"))

Вывод:

ACCGGGTTTT

str.translate заменяет все буквы за один проход на уровне C — быстрее цикла на больших геномах, а срез [::-1] переворачивает строку.

Зачем это на практике

  • Гены на минус-нити. Если ген расположен на второй нити, чтобы прочитать его «как написано», берут обратный комплемент участка плюс-нити.
  • Палиндромы. Многие рестрикционные сайты равны своему обратному комплементу (GAATTC) — отсюда симметрия разрезания.
  • Картирование ридов. Рид может прийти с любой нити; при выравнивании пробуют и его, и его обратный комплемент.

Особенно ярко обратный комплемент проявляется при подборе праймеров для ПЦР — реакции размножения нужного участка ДНК. Праймер — короткий кусочек ДНК (обычно 18–25 букв), который «садится» на нить-матрицу по комплементарности и задаёт точку старта копирования. Пара праймеров ограничивает участок с двух сторон, и один из них всегда задаётся как обратный комплемент конца целевого участка, потому что должен садиться на противоположную нить, идущую в обратном направлении. Ошибка в обратном комплементе здесь означает, что праймер просто не сработает, — поэтому биологи дотошно его проверяют, а инструменты дизайна праймеров считают его автоматически.

Как работает под капотом: палиндром ДНК

«Палиндром» в ДНК — не как «А роза упала», а равенство обратному комплементу. Причина биологическая: многие белки, работающие с ДНК (рестриктазы, факторы транскрипции), сами симметричны — состоят из двух одинаковых половинок. Такому белку удобно садиться на симметричный участок ДНК, где каждая половинка узнаёт свою нить. Поэтому палиндромность сайта — не курьёз, а отражение симметрии молекулы-партнёра. Проверим знаменитый сайт EcoRI.

table = str.maketrans("ATGC", "TACG")
def reverse_complement(seq):
    return seq.translate(table)[::-1]

for site in ["GAATTC", "GGATCC", "ATGCAT", "ATGGCA"]:
    rc = reverse_complement(site)
    print(f"{site}: обр.компл. {rc} -> палиндром: {site == rc}")

Вывод:

GAATTC: обр.компл. GAATTC -> палиндром: True
GGATCC: обр.компл. GGATCC -> палиндром: True
ATGCAT: обр.компл. ATGCAT -> палиндром: True
ATGGCA: обр.компл. TGCCAT -> палиндром: False

Частые ошибки

  • Дать комплемент вместо обратного. Самый частый баг: забыть перевернуть строку.
  • Неверная таблица пар. Перепутать A↔G вместо A↔T ломает всё молча.
  • Не учесть N. str.translate оставит N как есть, но цикл со словарём упадёт по KeyError.

Стоит сравнить два способа реализации, которые мы показали, не только по скорости, но и по поведению на «грязных» данных. Вариант со словарём pairs[b] явный и читаемый, но строгий: любая буква вне ATGC роняет программу. Вариант через str.maketrans работает на уровне C (быстрее в разы на длинных строках) и мягок к незнакомым символам — оставляет их нетронутыми. У мягкости есть обратная сторона: если в данных оказалась опечатка, она тихо пройдёт дальше. Универсального «правильного» выбора нет — он зависит от того, хотите вы упасть громко при первой же проблеме или продолжить, сохранив подозрительные символы. Осознанный выбор между «строгим» и «снисходительным» поведением — типичное инженерное решение, которое в биоинформатике приходится принимать постоянно из-за неидеальности реальных данных.

Итог

  • Комплемент меняет буквы на парные; обратный комплемент ещё и переворачивает строку.
  • Биологически осмыслена обратная комплементарная нить (антипараллельность 5'→3').
  • str.maketrans + срез [::-1] — быстрый идиоматичный способ.
  • Обратный комплемент нужен для генов на минус-нити, палиндромных сайтов и картирования ридов.
Проверьте себя
1. Чем обратный комплемент отличается от просто комплемента?
AНичем
BОбратный комплемент дополнительно переворачивает строку
CКомплемент длиннее
DОбратный комплемент не меняет буквы
2. Какой обратный комплемент у последовательности ATGC?
ATACG
BGCAT
CCGTA
DATGC
3. Что значит, что последовательность ДНК «палиндром»?
AОна читается одинаково слева направо буквенно
BОна равна своему обратному комплементу
CВ ней поровну A и T
DОна симметрична по длине