전사/번역을 Biopython 없이 해보자
이걸 왜 하냐... Biopython 깔면 장땡 아니냐... 변환해주는 툴 있지 않냐... 하시는데 변환해주는 툴은 인터넷이 안되면 못 쓰고, Biopython은 VScode에서 안된다. 일단 리눅스에서는 spyder랑 pycharm에서만 정상적으로 인식했다.
전사
DNA를 인트론 자르고 mRNA로 만드는 과정이다. 그리고 RNA가 DNA와 다른 점은 티민 대신 우라실(U)이 들어간다는 점. 그래서 ATGC->AUGC로 바꾸기만 하면 된다.
def transcription(text) :
pass
우리는 찍어낸다 함수. 원래는 파일을 따로 하려고 했는데 아니 이게… 씁… 전사가 너무 간단함.
def transcription(text) :
text = text.replace('T','U')
return text
sequence = input('DNA 시퀀스를 입력해주세요: ')
sequence = sequence.upper()
print(transcription(sequence))
위에도 썼지만 전사는 T(티민)를 U(우라실)로 바꾸기만 하면 된다. 진짜로 그게 다다. 문제는 번역이지…
번역
번역이 왜 문제임? 을 설명하려면 이 표가 필요하다.

이건 코돈 테이블이라는 거다. 당신이 이 글을 읽는 시간에도 리보솜에서 mRNA를 해독하고 아미노산 호출해서 단백질 만들 때 이 테이블대로 만들어서 지지고 볶고 PTM까지 조지는 과정을 거치는데... 으악 이게 뭐예요? 왼쪽에 있는 세 글자가 mRNA의 염기 세 개다. 그러니까 구아닌 시토신 시토신은 알라닌이라는 아미노산을 지정한다 이 얘기. 이건 생물종별로 코돈이 다르긴 한데 보통은 사람 코돈으로 하니까 그것까진 걱정 안 하셔도 됨.
여기서 뭐가 문제인지 깨달은 분도 계실 것이다. 그렇다. 여기서 문제는 전사와 달리 번역을 할 때는 알파벳 세 개를 찝어다가 저 표에서 맞는 아미노산을 골라야 한다는 거다. 한 아미노산에 대해서 여러가지 코돈이 대응하는 경우는 있지만, 번역하는 데 있어서 그건 문제가 안된다. 우리는 염기를 3개씩 묶어서 할 거지 아미노산으로 염기 찾는 걸 하는 게 아니거든…
그 외에도 고려할 게 몇 개 있는데, 그건 차차 설명하도록 하자. 기능 구현하는데도 피똥 쌀 예정이다.
def translation(text) :
pass
우리는 또 찍어낸다 함수를.
codon_table = {
# U
"UUU":"F", "UUC":"F", "UUA":"L", "UUG":"L",
"UCU":"S", "UCC":"S", "UCA":"S", "UCG":"S",
"UAU":"Y", "UAC":"Y", "UAA":"*", "UAG":"*",
"UGU":"C", "UGC":"C", "UGA":"*", "UGG":"W",
# C
"CUU":"L", "CUC":"L", "CUA":"L", "CUG":"L",
"CCU":"P", "CCC":"P", "CCA":"P", "CCG":"P",
"CAU":"H", "CAC":"H", "CAA":"Q", "CAG":"Q",
"CGU":"R", "CGC":"R", "CGA":"R", "CGG":"R",
# A
"AUU":"I", "AUC":"I", "AUA":"I", "AUG":"M",
"ACU":"T", "ACC":"T", "ACA":"T", "ACG":"T",
"AAU":"N", "AAC":"N", "AAA":"K", "AAG":"K",
"AGU":"S", "AGC":"S", "AGA":"R", "AGG":"R",
# G
"GUU":"V", "GUC":"V", "GUA":"V", "GUG":"V",
"GCU":"A", "GCC":"A", "GCA":"A", "GCG":"A",
"GAU":"D", "GAC":"D", "GAA":"E", "GAG":"E",
"GGU":"G", "GGC":"G", "GGA":"G", "GGG":"G"
}
gpt한테 물어봤더니 코돈 테이블을 딕셔너리로 만든 다음 거기서 뒤져서 대체하게 하란다. 일회성으로 돌릴거면 함수 안에 넣어도 되는데 저거 한번 돌리고 땡 아니면 걍 전역 하라고 함… 전역변수 하라는 얘기는 함수 밖으로 빼라는 얘기다. 왜 그렇게 하냐고? 전역변수면 한 번만 부르면 되는데, 함수 안에 때려박으면 함수 돌릴때마다 쟤를 불러야 한다 이거지.
def translation(text) :
text = text.upper()
protein = []
for i in range(0, len(text) - 2, 3):
codon = text[i:i+3]
amino_acid = codon_table.get(codon, '???')
protein.append(amino_acid)
return "".join(protein)
그러니까 착한 코더분들은 툴 찾아서 쓰십쇼… 일단 저 ???가 굳이 필요한지는 모르겠는게, 연구자들이 저런거 돌리는 시퀀스는 이미 DB에 있는거다. 그러니까 없는 코돈이 없다. for문 안에 0, len(text) - 2, 3으로 되어있는 이유는 0부터 시퀀스 길이-2까지 3개만인데…보통 시퀀스 3배수로 하지 않나? 라고 할 수 있지만 PCR 산물은 3배수 아닐수도 있다.

된 거 맞다. DNA를 입력해서 RNA로 전사하고 그걸로 번역까지 해야 한다.
아직 안 끝났다!
중요한건 우리는 이제 막 번역 로직을 구현했을 뿐이고, 실제로 생물학 연구자들이 활용하는 두 가지에 대해서는 구현이 안 됐다. 그 두 가지가 뭐냐...
첫번째, 모든 번역의 시작점은 AUG(메티오닌)이다. 그러니까 DNA 시퀀스에서는 몇 번째에 존재하던 상관없이 AUG가 시작점이다. GAATTGCTAUG 뭐 이런 시퀀스가 있으면 GAATTGCT[AUG] <<여기 대괄호 친 AUG가 시작점이다.
두번째, 종결코돈이 나오면 더 이상 번역 안 하고 끝낸다. 위에 돌린 거 보면 번역 결과가 GSSRVPRVLSK*NELPYIEEGSCEG*WDCASSLTSVEIPDRPNACPRSIQDITSIHLL*RRGWNVFFFHDAPRGWGSIFGTTVGRGIFNDGLSFIAMMAFVGATFLFHYLHNKVTDSWAMESEEVSGYYPLLKSLNCPLVF*DCIFDIFGVDKCVVLHHVD
로 나오는데, 원래 번역대로라면 GSSRVPRVLSK에서 끝났어야 맞다.
def translation(text) :
text = text.upper()
protein = []
for i in range(0, len(text) - 2, 3):
codon = text[i:i+3]
amino_acid = codon_table.get(codon, '???')
protein.append(amino_acid)
if amino_acid == "*":
break
return "".join(protein)
두번째 부분에 대해서는 if문 하나 추가하면 땡이다. 내가 위에 전역변수 선언한 표에 보면 종결코돈이 *로 되어있다. 그러니까 테이블 돌다가 * 나오면 끝내셈 하면 된다. 종결코돈은 툴 바이 툴인데 마침표로 표시하는데도 있음.
def translation(text) :
text = text.upper()
start = text.find("AUG")
if start == -1:
return "No start point(AUG)"
protein = []
for i in range(start, len(text) - 2, 3):
codon = text[i:i+3]
amino_acid = codon_table.get(codon, '???')
protein.append(amino_acid)
if amino_acid == "*":
break
return "".join(protein)
find함수로 AUG를 찾은 다음 거기서부터 번역을 시작하면 장땡이다. 이게 또 피쌸돌렸거나 하면 없을 수도 있기때문에 if문 하나 때려박아줌... 그런데! 여기서 또 중요한 게 하나 있다. 저 기능이 보통 옵션으로 제공된다. 그러니까 AUG를 안 찾고 번역하는 함수도 필요하긴 하다는 것.

그래서 AUG로 시작하는 거, 아닌거 둘 다 했다. (함수 따로 빼버림)
결론: 착한 연구자 여러분들은 이런거 구현할 시간에 그냥 툴 쓰십시오
'Coding > Python' 카테고리의 다른 글
| 정말 오랜만에 Project restriction enzyme 업데이트 (0) | 2025.11.28 |
|---|---|
| 판다스 없이 표 만들기 (0) | 2025.09.27 |
| Matplotlib으로 정규분포를 그려보자 (0) | 2024.07.16 |
| Matplotlib으로 그래프를 그려보자 (2) (0) | 2024.06.05 |
| Matplotlib으로 그래프를 그려보자 (0) | 2024.06.03 |