RNA Splicing 이란 RNA가 전사되는 과정에서 실제로 번역되는데 필요한 서열만 골라쓰는 것을 말합니다. 그 과정은 핵 안에서 RNA polymerase(RNAP)가 전사를 시작하는데, 먼저 DNA 나선을 반으로 가르는 작업을 합니다. 그런 다음 한가닥의 template DNA로 RNAP는 precursor mRNA(pre-mRNA)라는 분자를 만들어 template DNA 가닥을 내려오면서 상보적 base를 생성하게 되며, 물론 mRNA는 A를 만나면 T 대신 Uracil인 U로 생성이 됩니다.
이 과정에서 생성된 RNA는 template DNA이외의 나머지 한가닥과 동일해지며, 이 가닥을 coding strand 라고 합니다.
일단 RNAP에 의해서 몇개의 RNA 염기가 만들어지면 곧 분리되었던 DNA는 다시 결합하여 2중 나선으로 돌아갑니다.
이 과정에서 전사되는 전체 DNA 일부 서열은 RNA로 단백질로 번역되지 않는데, pre-mRNA가 맨처음 intron과 exon으로 쪼개집니다. 그 때, intron 부분의 서열은 버려지고 exon 부분의 서열은 다시 순서대로 합쳐져서 최종 mRNA가 만들어지게 됩니다. 이렇게 쪼개고 붙이는 과정을 splicing이라고 부르며 이것은 spliceosome 이라고 불리는 DNA와 단백질 집합에 의해 촉진됩니다.
이번 문제는 좀 간단했습니다. 첫번째로 주어지는 DNA 서열이고 나머지 서열이 intron 서열들일때, DNA 서열에서 intron 영역을 제외하고 exon 영역만 splicing 하여 protein 서열로 변경하기만 하면 되었습니다.
하지만 이 문제를 RNA 서열이 아니라 DNA 서열에서의 splicing 이기 때문에 DNA 서열을 단백질 서열로 변경하는 DNA 코돈 테이블이 필요합니다.
codon_table = {
"TTT": "F", "CTT": "L", "ATT": "I", "GTT": "V",
"TTC": "F", "CTC": "L", "ATC": "I", "GTC": "V",
"TTA": "L", "CTA": "L", "ATA": "I", "GTA": "V",
"TTG": "L", "CTG": "L", "ATG": "M", "GTG": "V",
"TCT": "S", "CCT": "P", "ACT": "T", "GCT": "A",
"TCC": "S", "CCC": "P", "ACC": "T", "GCC": "A",
"TCA": "S", "CCA": "P", "ACA": "T", "GCA": "A",
"TCG": "S", "CCG": "P", "ACG": "T", "GCG": "A",
"TAT": "Y", "CAT": "H", "AAT": "N", "GAT": "D",
"TAC": "Y", "CAC": "H", "AAC": "N", "GAC": "D",
"TAA": "Stop", "CAA": "Q", "AAA": "K", "GAA": "E",
"TAG": "Stop", "CAG": "Q", "AAG": "K", "GAG": "E",
"TGT": "C", "CGT": "R", "AGT": "S", "GGT": "G",
"TGC": "C", "CGC": "R", "AGC": "S", "GGC": "G",
"TGA": "Stop", "CGA": "R", "AGA": "R", "GGA": "G",
"TGG": "W", "CGG": "R", "AGG": "R", "GGG": "G"
}
그 다음에는 다음 절차대로 데이터를 가공하여 처리하면 됩니다.
def seperate_introns(m:dict) -> dict:
result = {"dna_seq": "", "introns": []}
for idx, (k, seq) in enumerate(m.items()):
if idx == 0: # 첫번째 서열은 전체 DNA 시퀀스
result["dna_seq"] = seq
else: # 나머지 서열은 intron 배열에
result["introns"].append(seq)
return result
def make_exons(data:dict):
ori_seq = data["dna_seq"]
exon_seq = ori_seq
for intron in data["introns"]:
exon_seq = exon_seq.replace(intron, "") # intron 삭제
return exon_seq
def make_protein_seq(exons_seq):
p_seq = ""
start_idx = exons_seq.find("ATG")
for idx in range(start_idx, len(exons_seq), 3):
codon = exons_seq[idx: idx+3]
if codon_table[codon] == "Stop": # Stop 코돈에서 번역을 중단합니다.
return p_seq
p_seq += codon_table[codon]
return p_seq
위의 1,2,3 과정을 거치면 정답이 출력되게 됩니다.
run = tz.compose(
make_protein_seq,
make_exons,
seperate_introns,
make_map,
input_processor)
run(test_fasta)
import toolz as tz
import re
codon_table = {
"TTT": "F", "CTT": "L", "ATT": "I", "GTT": "V",
"TTC": "F", "CTC": "L", "ATC": "I", "GTC": "V",
"TTA": "L", "CTA": "L", "ATA": "I", "GTA": "V",
"TTG": "L", "CTG": "L", "ATG": "M", "GTG": "V",
"TCT": "S", "CCT": "P", "ACT": "T", "GCT": "A",
"TCC": "S", "CCC": "P", "ACC": "T", "GCC": "A",
"TCA": "S", "CCA": "P", "ACA": "T", "GCA": "A",
"TCG": "S", "CCG": "P", "ACG": "T", "GCG": "A",
"TAT": "Y", "CAT": "H", "AAT": "N", "GAT": "D",
"TAC": "Y", "CAC": "H", "AAC": "N", "GAC": "D",
"TAA": "Stop", "CAA": "Q", "AAA": "K", "GAA": "E",
"TAG": "Stop", "CAG": "Q", "AAG": "K", "GAG": "E",
"TGT": "C", "CGT": "R", "AGT": "S", "GGT": "G",
"TGC": "C", "CGC": "R", "AGC": "S", "GGC": "G",
"TGA": "Stop", "CGA": "R", "AGA": "R", "GGA": "G",
"TGG": "W", "CGG": "R", "AGG": "R", "GGG": "G"
}
test_fasta = """
>Rosalind_10
ATGGTCTACATAGCTGACAAACAGCACGTAGCAATCGGTCGAATCTCGAGAGGCATATGGTCACATGATCGGTCGAGCGTGTTTCAAAGTTTGCGCCTAG
>Rosalind_12
ATCGGTCGAA
>Rosalind_15
ATCGGTCGAGCGTGT
"""
input_processor = lambda i: i.strip().split("\n")
def make_map(input_data:list) -> dict:
d = {}
key = ""
for line in input_data:
if line.startswith(">"):
key = line.replace(">", "")
d[key] = ""
else:
d[key] += line
return d
def seperate_introns(m:dict) -> dict:
result = {"dna_seq": "", "introns": []}
for idx, (k, seq) in enumerate(m.items()):
if idx == 0:
result["dna_seq"] = seq
else:
result["introns"].append(seq)
return result
def make_exons(data:dict):
ori_seq = data["dna_seq"]
exon_seq = ori_seq
for intron in data["introns"]:
exon_seq = exon_seq.replace(intron, "")
return exon_seq
def make_protein_seq(exons_seq):
p_seq = ""
start_idx = exons_seq.find("ATG")
for idx in range(start_idx, len(exons_seq), 3):
codon = exons_seq[idx: idx+3]
if codon_table[codon] == "Stop":
return p_seq
p_seq += codon_table[codon]
return p_seq
run = tz.compose(
make_protein_seq,
make_exons,
seperate_introns,
make_map,
input_processor)
run(test_fasta)