[Bioinformatics] - 생물학적 서열의 기본적 처리

이전에 계속 언급했듯이 생물학적 시스템과 유전 정보는 DNA에 암호화돼 있습니다.

생명정보학 알고리즘과 도구들은 실용적인 목적으로 DNA를 1차원적 뉴클레오티드 서열로 표기합니다.

DNA 또는 RNA 분자는 네 개의 뉴클레오티드로 구성돼 있으므로 컴퓨터로 표현할 때 네 개의 독립적인 문자로 표현합니다.

 

DNA의 경우 A,C,G,T 로 표현합니다. 이는 각각 아데닌, 시토닌, 구아닌, 티민이며 RNA의 경우 T 대신 U인 우라실로 표현합니다.

DNA의 기본 알파벳에는 네 개의 뉴클레오티드만 포함돼 있지만, IUPAC은 확장된 심볼들을 정리해 뉴클레오티드의 모호성을 허용하는 확장된 심볼들을 정의했습니다. 확장된 심볼들을 통해 중합 효소 연쇄 반응(PCR) 프라이머의 디자인과 같이 불확실한 뉴클레오티드가 있는 경우에 유용하게 표현할 수 있게 됐습니다.

 

생물학적으로 중요한 또 다른 서열은 단백질 서열이며 아미노산 서열로 구성돼 있습니다.

유전 코드로 20개의 아미노산이 암호화될 수 있으므로 표 1을 참조하면 서열은 20개의 각각 다른 알파벳 문자로 이뤄졌음을 확인할 수 있습니다. 종결코돈을 표현하는 문자도 있어야 합니다. 종결코돈 문자를 DNA 번역을 자동으로 수행하는 도구에서 사용합니다. 종결코돈으로 가장 많이 사용하는 문자는 언더스코어 또는 별표입니다.

 

표1. 뉴클레오티드를 표현하는 IUPAC 심볼

 

심볼 이름 뉴클레오티드

A 아데닌 A
C 시토닌 C
G 구아닌 G
T 티민 T
U 우라실 U
K 케토 G, T
M 아미노 A, C
R 퓨린 A, G
S 강함 C, G
W 약함 A, T
Y 피리미딘 C, T
B A 아님 C, G, T
D C 아님 A, G, T
H G 아님 A, C, G
V T 아님 A, C, G
N 모든 염기 A, C, G, T

 

표2. 아미노산을 표현하는 IUPAC 심볼

A 알라닌
C 시스테인
D 아스파르트산
E 글루탐산
F 페닐알라닌
G 글라이신
H 히스티딘
I 아이소류신
L 라이신
M 메티오닌
N 아스파라간
P 프롤린
Q 글루타민
R 아르기닌
S 세린
T 트레오닌
V 발린
T 트립토판
Y 타이로신

 

함수1. DNA의 서열이 유효한지 확인하기. 서열이 유효하다면 True, 유효하지 않다면 False를 반환

 

def validate_dna (dna_seq):
    seqm = dna_seq.upper()
    valid = seqm.count("A") + seqm.count("C") + seqm.count("G") + seqm.count("T")
    if valid == len(seqm): return True
    else: return False 

validate_dna("atgcgatcgattcggagcg")

True

 

함수2. 서열에서 각 심볼의 빈도를 계산. 결과로 딕셔너리를 반환.

 

def frequency (seq):
    dic = {}
    for s in seq.upper():
        if s in dic: dic[s] += 1
        else: dic[s] = 1
    return dic

frequency("atgcgatcgattcggagcg")

{'A': 4, 'T': 4, 'G': 7, 'C': 4}

 

입력받은 아미노산 서열의 빈도를 계산. 결과 값으로 가장 많이 출현한 아미노산의 심볼과 출현한 값을 출력합니다.

 

seq_aa = input("Protein sequence : ")
freq_aa = frequency(seq_aa)
list_f = sorted(freq_aa.items(), key=lambda x: x[1], reverse=True)

for (k,v) in list_f:
    print("Aminocaid:", k, ":", v)
    
Aminocaid: A : 2
Aminocaid: T : 1
Aminocaid: G : 1

 

GC 함량의 계산은 DNA 서열에서 ‘G’와 ‘C’ 뉴클레오티드의 비율을 계산하는 것입니다.

 

def gc_content (dna_seq): 
    gc_count = 0
    for s in dna_seq:
        if s in "GCgc": gc_count += 1
    return gc_count / len(dna_seq)

gc_content("AAATGGCGCGCGC")

0.6923076923076923

 

유전자 또는 엑손을 찾는 경우처럼 GC 함량을 계산해야 할 때가 있습니다. 아래의 스크립트의 함수는 중첩되지 않는 k 길이만큼의 부분 서열에 대한 GC 함량을 계산합니다.

 

def gc_content_subseq (dna_seq, k=100):
    """ 겹치지 않는 k 길이의 부분 서열에 대한 GC 함량을 리스트로 반환한다. """
    res = []
    for i in range(0, len(dna_seq)-k+1, k):
        subseq = dna_seq[i:i+k]
        gc = gc_content(subseq)
        res.append(gc)
    return res

 

전사와 역상보

DNA에서 RNA로의 전사는 DNA에 포함된 유전 정보로부터 단백질을 합성하는 전체 과정에서 기본적인 단계입니다.

전사를 구현하는 함수를 이해하기 위해 DNA 분자가 서로 반대 방향으로 읽히는 두 개의 상보적 가닥으로 구성돼 있음을 기억해봅시다.

 

전사가 일어나면 두 가닥이 나뉘고 새로운 RNA 서열이 해당 DNA 가닥에 상보적으로 생성됩니다. 따라서 해당 DNA 가닥은 주형 가닥(template strand)에 상보적인 가닥인 비주형 가닥(coding strand)과 유사합니다.

 

단지 뉴클레오티드의 ‘T’가 ‘U’로 바뀌기만 했죠? 이러한 맥락에서 DNA 가닥을 입력하면 간단히 ‘T’를 ‘U’로 대체해 RNA 서열을 얻을 수 있습니다.

다음 파이썬 코드에서는 입력한 DNA 서열이 유효한지 검사하고 유효하지 않다면 예외를 발생시켜 프로그램을 종료합니다.

replace() 를 사용해서 모든 ‘T’ 문자를 ‘U’로 바꿔서 새로운 문자열을 반환하고 있습니다.

 

def transcription (dna_seq):
    assert validate_dna(dna_seq),  "Invalid DNA sequence"
    return dna_seq.upper().replace("T","U")    

transcription("atgcgatcgattcggagcg")

 

이전의 함수들은 하나의 DNA 서열만 주어지므로 주어진 서열의 상보적 서열도 고려해야 합니다.

실제로 생물정보학 데이터베이스에서는 한 가닥의 DNA 서열만 제공되므로 상보적 가닥을 처리해야 하죠.

 

다음 함수는 입력된 DNA 서열에 역상보적인 서열을 결과로 만듭니다. 상보적 서열은 ‘A’가 ‘T’로, ‘C’가 ‘G’로 바뀌는 것을 의미합니다. 또한 역서열을 만들기 위해 for문을 돌 때 결과로 만드는 문자열의 가장 앞에 새로운 문자를 추가하는 방식으로 구현합니다.

 

번역

세포에서 단백질은 전령 RNA(messenger RNA, mRNA)로부터 번역이라 불리는 과정을 거쳐 아미노산의 체인을 만들며 합성됩니다. DNA에서 mRNA로의 전사 과정은 어려운 과정이 아니었습니다.

이번에는 DNA에서부터 단백질로 바로 번역하는 과정을 생각해봅시다. 번역을 하는 컴퓨터의 동작 방식은 다음과 같습니다.

  1. 번역할 DNA 서열은 겹치지 않게 세 개씩 문자를 읽어 코돈이라 불리는 하위 서열을 만듭니다.
  2. 각 코돈에 대해 아미노산은 변환 표에 따라 번역됩니다.
  3. 변환된 단백질 서열은 순서를 맞춰서 결과가 생성됩니다.

코돈에서 아미노산으로 변환하는 핵심적인 데이터 구조는 변환 표이며, 이는 파이썬의 딕셔너리 자료 구조로 이뤄집니다. 사전의 key는 64개의 코돈이고 해당 value는 아미노산입니다.

다음 함수는 내부에 변환 사전을 미리 정의하고 이를 참조하여 변환 과정을 진행합니다. 만약 유효하지 않은 코돈이 함수에 전달된다면 None이 반환됩니다. 또한 종결 코돈이 ‘_’ 심볼을 반환하는 것을 확인해봅시다.

 

def translate_codon (cod):
    tc = {"GCT":"A", "GCC":"A", "GCA":"A", "GCG":"A", 
      "TGT":"C", "TGC":"C",
      "GAT":"D", "GAC":"D",
      "GAA":"E", "GAG":"E",
      "TTT":"F", "TTC":"F",
      "GGT":"G", "GGC":"G", "GGA":"G", "GGG":"G",
      "CAT":"H", "CAC":"H",
      "ATA":"I", "ATT":"I", "ATC":"I",
      "AAA":"K", "AAG":"K",
      "TTA":"L", "TTG":"L", "CTT":"L", "CTC":"L", "CTA":"L", "CTG":"L",
      "ATG":"M", "AAT":"N", "AAC":"N",
      "CCT":"P", "CCC":"P", "CCA":"P", "CCG":"P",
      "CAA":"Q", "CAG":"Q",
      "CGT":"R", "CGC":"R", "CGA":"R", "CGG":"R", "AGA":"R", "AGG":"R",
      "TCT":"S", "TCC":"S", "TCA":"S", "TCG":"S", "AGT":"S", "AGC":"S",
      "ACT":"T", "ACC":"T", "ACA":"T", "ACG":"T",
      "GTT":"V", "GTC":"V", "GTA":"V", "GTG":"V",
      "TGG":"W",
      "TAT":"Y", "TAC":"Y",
      "TAA":"_", "TAG":"_", "TGA":"_"}
    if cod in tc: return tc[cod]
    else: return None

 

여기에서 고려해야 할 사항은 표준 유전 코드가 매번 통용되지 않는다는 점입니다. 진핵세포의 미토콘드리아와 같은 몇몇 유기체는 단백질 합성에 다른 코돈 테이블을 가지고 있습니다.

 

해당 함수를 사용해 전체 DNA 서열을 번역하는 함수를 작성할 수 있습니다. 이 함수는 DNA 서열과 처음 번역하는 위치를 입력받아 해당하는 아미노산 서열을 결과로 반환합니다. DNA 서열에서 코돈으로 분할하는 것은 range 함수에 적절하게 인덱스를 사용해 진행합니다.

 

def translate_seq (dna_seq, ini_pos = 0):
    """ Translates a DNA sequence into an aminoacid sequence. """
    assert validate_dna(dna_seq), "Invalid DNA sequence"
    seqm = dna_seq.upper()
    seq_aa = ""
    for pos in range(ini_pos,len(seqm)-2,3):
        cod = seqm[pos:pos+3]
        seq_aa += translate_codon(cod)
    return seq_aa


def codon_usage(dna_seq, aa):
    """Provides the frequency of each codon encoding a given aminoacid, in a DNA sequence ."""
    assert validate_dna(dna_seq), "Invalid DNA sequence"
    seqm = dna_seq.upper()
    dic = {}
    total = 0
    for i in range(0, len(seqm)-2, 3):
        cod = seqm[i:i+3]
        if translate_codon(cod) == aa:
            if cod in dic: 
                dic[cod] += 1
            else: dic[cod] = 1
            total += 1
    if total >0:
        for k in dic:
            dic[k] /= total
    return dic

 

유전 코드는 중복되므로 반복되는 값이 있습니다. 예를 들어 하나의 아미노산은 여러 개의 다른 코돈으로 암호화 됩니다. 이를 일반적으로 코돈 사용(Codon Usage)이라고 부릅니다. 코돈 사용의 통계를 다른 종의 유전자에 적용해보면 재미있는 결과를 얻을 수 있습니다.

반응형