(83)

정규식(Regular Expression)-re모듈 사용법

분량+저녁크리로 인해 2부작으로 나눠버림... 이 글의 re모듈은 파이썬에서 사용하는거지만, 앞 글에 있는 기호와 메타문자는 언어를 불문하고 정규 표현식에서 다 쓰인다. https://koreanraichu.tistory.com/118 정규식(Regular Expression)-기호와 메타문자 문자 찾는 것 자체는 find()도 해주는데, 얘는 딱 정확하게 일치하는 문자열만 찾아준다. 그럼 정규식은? 그건 대충 와일드카드같은 거다. 그러니까 find()는 소라빵 찐빵 팥빵 붕 koreanraichu.tistory.com 다른 언어를 사용한다고 해도 앞 글은 한번정도는 읽어보자. re.search() 자... 전에도 서술했지만, find()는 정규식을 주면 그 정규식이랑 일치하는 걸 찾지 정규식으로 검색하..

정규식(Regular Expression)-기호와 메타문자

문자 찾는 것 자체는 find()도 해주는데, 얘는 딱 정확하게 일치하는 문자열만 찾아준다. 그럼 정규식은? 그건 대충 와일드카드같은 거다. 그러니까 find()는 소라빵 찐빵 팥빵 붕어빵 이런 식으로 딱딱 키워드를 찾는거고 정규식은 *빵으로 소라빵 찐빵 붕어빵 팥빵 다 찾는 거지. 참고로 정규식을 쓰려면 re를 불러야 한다. import re ㄱㄱ 정규식 문자 정규식에서 쓰는 문자들과 이게 뭐 하는건지를 간단히 알아보자. . Wildcard(구글 검색에서 *) for i in range(len(pokemon)): if re.search('김.',pokemon[i]): print(pokemon[i]) 김부추 김후추 김양상추 박알타리김치 고등어김치찜 김배추 참고로 전부 본인 포켓몬 이름임. 왜요 ^ ~로 ..

Cutter 기능 추가: 정규식 도입

Finder는 도입하려면 좀 걸립니다... 얘는 아예 정규식+찾아바꾸기가 필요한거라...... 정규식 도입 import pandas as pd import re from datetime import datetime enzyme_table = pd.read_csv('/home/koreanraichu/restriction.csv') enzyme_table2 = pd.read_csv('/home/koreanraichu/restriction_RE.csv') # 정규식 도입을 위해... 어쩔 수 없이 합쳤음... enzyme_table = pd.concat([enzyme_table,enzyme_table2]) enzyme_table = enzyme_table.sort_values('Enzyme') enzyme_t..

Searcher 기능 추가: 그 뭐더라 그 D로 시작하는 그거

일단... 해당 기능 추가 결과물이고요... 정규식 얘기는 나중에 입 털어드림... import re # 정규식용 모듈 정규식은 얘가 있어야 쓸 수 있다. elif keyword == "name": enzyme_RE = input("효소의 이름이 뭘로 시작하나요? ") enzyme_RE_2 = '^' + enzyme_RE 물론 if문에도 관련 코드를 추가했다. (^ 붙으면 그걸로 시작하는 걸 찾아준다) else: print("Enzyme with start with {0}".format(enzyme_RE)) for i in range(len(enzyme_table)): DB_enzyme = str(enzyme_table['Enzyme'][i]).strip() DB_seq = str(enzyme_table..

cutter, finder, searcher에 앞으로 추가할 기능

FASTA 파일 지원 1) 일단 사용자가 FASTA파일을 읽어오게 되면 따로 시퀀스 정보 입력을 받을 필요가 없어서 그거 관련도니 처리가 필요함. (시퀀스 이름은 Biopython SeqIO로 FASTA파일 ID 가져올 예정) 2) Biopython의 경우 FASTA파일에 꺾쇠가 하나면 read, 여러개면 parse로 가져오는데 parse로 읽을 걸 read로 가져오면 에러뜸. 에러에 대한 처리가 필요하고... parse로 가져오는 파일은 꺾쇠가 여러개인데, 이게 다르게 말하면 ID랑 시퀀스라 여러개라 그거 읽어오면 여러개를 돌리고 저장까지 해야 하는거라 이거는 Jupyter단에서는 힘듭니다... OTL 그래서 단식만 읽을거임... 3) FASTA 관련된 기능이긴 한데, 본인은 애초에 경로가 고정되어 있..

For vs While

기본 파이썬에는 두 가지 반복문이 있는데 한놈은 For고 한놈은 While이다. While은 베이직에서 본 거 같은디... (do while loop) 아무튼... 둘 다 반복문이긴 한데, 둘이 맥락은 좀 다르다. 내가 10페이지의 책을 읽는 것을 for와 while을 이용해 설명하자면 For: 1쪽부터 10쪽까지 읽어야징 While: 읽은 페이지 수가 10이 될 때까지 읽어야징 이런 차이가 있다. ...사실 이렇게 말하면 모르시겠져? 그래서 가져왔음. 둘 다 3^1~1^10까지 출력하는 코드인데(사실 저렇게 안하고 프린트문 줘도 됨) For: 1부터 10까지 3에 제곱해 While: j가 있는데 이게 11보다 작을 동안 3에 제곱하고 하나씩 더해 이런 식으로 돌아간다. For문은 범위를 주고 반복하는 ..

Finder & Cutter 패치

1. 공통: 이제 어디 자르는지도 나옵니다. 살려줘... 2. Cutter: 제한효소 누락되던 거 수정했습니다. 근데 된건지 모르겠음. def count_func (a,b): while a in b: global site_count global res_loc global res_loc_list loc = b.find(a) site_count += 1 b = b[loc+len(a):] res_loc = loc + 1 res_loc_list.append(res_loc) return site_count, res_loc # 이거 통으로 코드에 넣었더니 if 안에 있는데도 시퀀스 없으면 끝내더라... # 위치 출력은 되는 것 같은데, 이거 더해야 하는데... 이렇게 하면 위치가 출력되긴 한데 문제가 하나 있다. ..

Searcher 만들었음

DB를 구축할 때 수동으로 구축했는데, CSV 구분자가 ,다보니 .로 들어간게 좀 있어서 그거 수정했음... (마른세수) 효소 이름 오타난것도 수정했습니다... 이래서 손끝 다치면 안됨... import pandas as pd enzyme_table = pd.read_csv('/home/koreanraichu/restriction.csv') # 이쪽은 Finder나 cutter에도 쓰이는 그 DB가 맞습니다. enzyme_table2 = pd.read_csv('/home/koreanraichu/restriction_RE.csv') # 이쪽은 restriction site나 cut site에 A,T,G,C가 아닌 다른 알파벳이 들어가기 때문에 여기서 처음 불러오는 DB입니다. enzyme_table = p..

Cutter & Finder 패치노트

공통패치 Cut수 세 주는 기능이 추가되었습니다. Cutter Cut수에 따른 효소 리스트 업 기능이 추가되었습니다. 살려줘... (아직 자르는 위치 안했음) 파일 이름 형식이 변경되었습니다. 그래서 이제 시퀀스 이름도 받습니다. Finder Cut수 세 주는 기능에 따른 출력 형식 수정이 있었습니다. Cut수 세 주는 기능 사실상 엄청난 노가다의 결과...ㅠㅠ (생략) if res_find in sequence: site_count = 0 while sequence.find(res_find) != -1: loc = sequence.find(res_find) site_count += 1 sequence = sequence[loc+len(res_find):] print(enzyme, res_find, se..

제한효소 커터 2편 나왔음

사실 전에 만든 코드 이름은 Finder고, 이놈이 커터임. import pandas as pd 이 코드도 판다스가 있어야된다. (DB가 csv) enzyme_table = pd.read_csv('/home/koreanraichu/restriction.csv') enzyme_table = enzyme_table.sort_values('Enzyme') # Finder에도 쓰이는 '그' DB 맞습니다. 현재 수동 구축 중... print(enzyme_table) print(len(enzyme_table)) 아직도 갈 길이 멀지만 일단 D까지 추가했음... 아울러 py파일은 print가 빠집니다. sequence = input("검색할 시퀀스를 입력해주세요: ") 이건 시퀀스 입력받는 코드(아직 이름은 안 받..

제한효소 커터 만들었음

근데 NEB커터 쓰세여 그거 좋음 일단 이 코드는 이 시퀀스를 자르는 제한효소들을 찾는 게 아님. 이 효소가 이 시퀀스를 자르는가? 를 보는 코드임다. 이 점 유념해주세요. 그리고 이거 올리면서 Jupyter가 매트랩이랑 비중 같아졌다 코드 Jupyter notebook으로 코딩한거고 나중에 일부 블록은 정리할 예정. import pandas as pd 구축한 csv파일을 가져오고 취급하려면 얘가 필요하다. csv파일은 혹시 써보실 분 계시면 말씀주세요. 참고로 csv파일이 되게 단촐해서 효소 이름, 인식하는 시퀀스, 자르는 시퀀스, 자르는 형태(sticky or blunt)가 들어가 있음. 나중에 여건이 된다면 똑같은 부분을 인식하고 자르는 다른 효소나 처리온도에 대한 정보도 추가할 예정. (물론 출력..

오케이 따옴표 떼버렸음

text = [] while True: input_text = input("wordcloud로 만들 텍스트를 입력해주세요. ") text.append(input_text) if input_text == "": break text = ' '.join(text) text=okt.nouns(text) text = ' '.join(text) 크게는 저 부분을 수정했고, 전체적으로 wordcloud 만들기 위해 입력받는 부분도 간소화했음. (While True 주고 입력 없으면 break 하도록) 참고로 Wordcloud는 안에 들어가는 글자가 많을 수록 멋지게 나옵니다. 이 점 유념하시길.

10진수->2진수 변환 코드

일반적으로 우리가 쓰는 숫자는 10진수가 맞는데, 컴퓨터는 손가락이 두 개라 이진법을 쓴다. 예, 그겁니다. 일반적으로 10진법을 2진법으로 변환할때는 2로 나누는데, 13을 예시로 들자면 1. 13/2=6...1 2. 6/2=3...0 3. 3/2=1...1 이렇게 구한 다음 3번 결과의 몫 1부터 시작해 3번 결과의 나머지-2번 결과의 나머지-1번 결과의 나머지 순으로 올라가서 1101이 된다. 1의 보수는 여기서 0을 1로, 1을 0으로 바꾼 0010. 2의 보수는 1의 보수에 1을 더하면 된다. (0011) 참고로 이진수로 변환된 숫자는 8, 16진수와 상호변환이 가능한데 1. 110010010을 8진수로 바꾸려면 110 010 010으로 세자리씩 끊어서 10진법으로 바꾼다. (622) 2. 11..

정규식(Regular Expression)-re모듈 사용법

Coding/Python 2022. 8. 22. 00:28

분량+저녁크리로 인해 2부작으로 나눠버림... 

 

이 글의 re모듈은 파이썬에서 사용하는거지만, 앞 글에 있는 기호와 메타문자는 언어를 불문하고 정규 표현식에서 다 쓰인다. 

https://koreanraichu.tistory.com/118

 

정규식(Regular Expression)-기호와 메타문자

문자 찾는 것 자체는 find()도 해주는데, 얘는 딱 정확하게 일치하는 문자열만 찾아준다. 그럼 정규식은? 그건 대충 와일드카드같은 거다. 그러니까 find()는 소라빵 찐빵 팥빵 붕

koreanraichu.tistory.com

다른 언어를 사용한다고 해도 앞 글은 한번정도는 읽어보자. 


re.search()

자... 전에도 서술했지만, find()는 정규식을 주면 그 정규식이랑 일치하는 걸 찾지 정규식으로 검색하질 않아요... 

 

print(re.search('G...',DNA))
<re.Match object; span=(1, 5), match='GAGG'>

단식

 

for i in range(len(df)):
    enzyme = df['Enzyme'][i]
    if re.search('A.....',enzyme):
        print(enzyme)
Acc36I
AccB1I
AccB2I
AccB7I
AceIII
AflIII
Alw21I
Alw26I
Ama87I
AmaCSI
ApaORI
AquIII
Asp10HII
Asp26HI
Asp27HI
Asp35HI
Asp36HI
Asp40HI
Asp50HI
Asp700I
Asp745I
Asp59I
AsuIII
AsuC2I
AsuHPI

복식

일단 자세한건 re.match()에서 서술하겠지만, 일단 re.search()가 정규식 검색할 때 쓰는 게 맞다. 

 

re.match()

print(re.match('G...',DNA))
None

re.search()와 달리 re.match()는 처음부터 정규식 형식이랑 일치하는 걸 찾아준다. 쟤가 그래서 왜 None이냐... 

DNA="AGAGGTTAAAGAACAAAGGCTTACTGTGCGCAGAGGAACGCCCATTTAGCGGCTGGCGTTTTGAATCCTCGGTCCCCCTTGTCTATCCAGATTAATCCAATTCCCTCATTTAGGACCCTACCAAGTCAACATTGGTATATGAATGCGACCTCGAAGAGGCCGCCTAAAAATGACAGTGGTTGGTGCTCTAAACTTCATTTGGTTAACTCGTGTATCAGCGCGATAGGCTGTTAGAGGTTTAATATTGTATGGCAAGGTACTTCCGGTCTTAATGAATGGCCGGGAAAGGTACGCACGCGGTATGGGGGGGTGAAGGGGCGAATAGACAGGCTCCCCTCTCACTCGCTAGGAGGCAATTGTATAAGAATGCATACTGCATCGATACATAAAACGTCTCCATCGCTTGCCCAAGTTGTGAAGTGTCTATCACCCCTAGGCCCGTTTCCCGCATATTAACGCCTGATTGTATCCGCATTTGATGCTACCGTGGTTGAGTCAGCGTCGAGCACGCGGCACTTATTGCATGAGTAGAGTTGACTAAGAGCCGTTAGATGCCTCGCTGTACTAATAGTTGTCGACAGATCGTCAAGATTAGAAAACGGTAGCAGCATTATCGGAGGTTCTCTAACTAGTATGGATAGCCGTGTCTTCACTGTGCTGCGGCTACCCATCGCCTGAAAACCAGTTGGTGTTAAGCGATCCCCTGTCCAGGACGCCACACGTAGTGAAACATACACGTTCGTCGGGTTCACCCGGGTCGGATCTGAGTCGACCAAGGACACACTCGAGCTCCGATCCCTACTGTCGAGAAATTTGTATCCCGCCCCCGCAGCTTGCCAGCTCTTTGAGTATCATGGAGCCCATGGTTGAATGAGTCCAATAACGAACTTCGACATGATAAAGTCCCCCCCTCGCGACTTCCAGAGAAGAAGACTACTGAGTTGAGCGTTCCCAGCACTTCAGCCAAGGAAGTTACCAATTTTTAGTTTCCGAGTGACAC"

원본 시퀀스가 이거였음. G로 시작하는 게 첫 번째 글자가 아니라 두 번째 글자기때문에 첫 빠따부터 에이 뭐야 없어가 되버린다. 

 

print(re.match('.G...',DNA))
print(re.search('.G...',DNA))
<re.Match object; span=(0, 5), match='AGAGG'>
<re.Match object; span=(0, 5), match='AGAGG'>

이거는 둘 다 똑같은 결과가 나온다. (정규식 형식은 어쨌든 일치하므로)

 

re,match()의 메소드들

이거 참고로 단독소환 쌉가능. 

 

records = re.finditer('A.{4}C',DNA)
for r in records:
    print(r.group(),r.start(),r.end(),r.span())

finditer에 대해서는 밑에서 또 설명할 예정이니까 이것부터 보고 갑시다. 저기 r.뭐시기 된 저거요. 저게 re.match의 메소드인데 순서대로 

1) 그룹(문자열)
2) 시작
3) 끝
4) span

이렇게 된다. 출력은 

AAGAAC 8 14 (8, 14)

이렇게 된다. 

 

re.findall()

이름을 보면 아시겠지만 그냥 다 찾아주는 애다. 반복문 데려 올 필요도 없다. 

 

print(re.findall('G...',DNA))
['GAGG', 'GAAC', 'GGCT', 'GTGC', 'GCAG', 'GGAA', 'GCCC', 'GCGG', 'GGCG', 'GAAT', 'GGTC', 'GTCT', 'GATT', 'GGAC', 'GTCA', 'GGTA', 'GAAT', 'GCGA', 'GAAG', 'GGCC', 'GCCT', 'GACA', 'GTGG', 'GGTG', 'GGTT', 'GTGT', 'GCGC', 'GATA', 'GGCT', 'GTTA', 'GAGG', 'GTAT', 'GGCA', 'GGTA', 'GGTC', 'GAAT', 'GGCC', 'GGGA', 'GGTA', 'GCAC', 'GCGG', 'GGGG', 'GGGT', 'GAAG', 'GGGC', 'GAAT', 'GACA', 'GGCT', 'GCTA', 'GGAG', 'GCAA', 'GTAT', 'GAAT', 'GCAT', 'GCAT', 'GATA', 'GTCT', 'GCTT', 'GCCC', 'GTTG', 'GAAG', 'GTCT', 'GGCC', 'GTTT', 'GCAT', 'GCCT', 'GATT', 'GTAT', 'GCAT', 'GATG', 'GTGG', 'GAGT', 'GCGT', 'GAGC', 'GCGG', 'GCAT', 'GAGT', 'GAGT', 'GACT', 'GAGC', 'GTTA', 'GATG', 'GCTG', 'GTTG', 'GACA', 'GATC', 'GTCA', 'GATT', 'GAAA', 'GGTA', 'GCAG', 'GGAG', 'GTTC', 'GTAT', 'GGAT', 'GCCG', 'GTCT', 'GTGC', 'GCGG', 'GCCT', 'GAAA', 'GTTG', 'GTGT', 'GCGA', 'GTCC', 'GGAC', 'GCCA', 'GTAG', 'GAAA', 'GTTC', 'GTCG', 'GGTT', 'GGGT', 'GGAT', 'GAGT', 'GACC', 'GGAC', 'GAGC', 'GATC', 'GTCG', 'GAAA', 'GTAT', 'GCCC', 'GCAG', 'GCCA', 'GCTC', 'GAGT', 'GGAG', 'GGTT', 'GAAT', 'GAGT', 'GAAC', 'GACA', 'GATA', 'GTCC', 'GCGA', 'GAGA', 'GAAG', 'GAGT', 'GAGC', 'GTTC', 'GCAC', 'GCCA', 'GGAA', 'GTTA', 'GTTT', 'GAGT', 'GACA']

근데 위치까지 준다고는 안 했다. 

 

re.finditer()

print(re.finditer('A..C',DNA))
<callable_iterator object at 0x7f009c5f8100>

얘는 다른 메소드들처럼 걍 쌩으로 print문에 넣으면 안된다. 저렇게 뜬다. 

 

records = re.finditer('A..C',DNA)
for r in records:
    print(r)
<re.Match object; span=(16, 20), match='AGGC'>
<re.Match object; span=(37, 41), match='ACGC'>
<re.Match object; span=(63, 67), match='AATC'>
<re.Match object; span=(84, 88), match='ATCC'>
<re.Match object; span=(93, 97), match='AATC'>
<re.Match object; span=(99, 103), match='ATTC'>
<re.Match object; span=(114, 118), match='ACCC'>
<re.Match object; span=(123, 127), match='AGTC'>
<re.Match object; span=(142, 146), match='ATGC'>
<re.Match object; span=(156, 160), match='AGGC'>
<re.Match object; span=(189, 193), match='AAAC'>
<re.Match object; span=(205, 209), match='ACTC'>
<re.Match object; span=(224, 228), match='AGGC'>
<re.Match object; span=(290, 294), match='ACGC'>
<re.Match object; span=(294, 298), match='ACGC'>
<re.Match object; span=(323, 327), match='AGAC'>
<re.Match object; span=(327, 331), match='AGGC'>
<re.Match object; span=(340, 344), match='ACTC'>
<re.Match object; span=(350, 354), match='AGGC'>
<re.Match object; span=(366, 370), match='ATGC'>
<re.Match object; span=(370, 374), match='ATAC'>
<re.Match object; span=(381, 385), match='ATAC'>
<re.Match object; span=(388, 392), match='AAAC'>
<re.Match object; span=(428, 432), match='ACCC'>
<re.Match object; span=(434, 438), match='AGGC'>
<re.Match object; span=(455, 459), match='ACGC'>
<re.Match object; span=(467, 471), match='ATCC'>
<re.Match object; span=(478, 482), match='ATGC'>
<re.Match object; span=(493, 497), match='AGTC'>
<re.Match object; span=(507, 511), match='ACGC'>
<re.Match object; span=(542, 546), match='AGCC'>
<re.Match object; span=(551, 555), match='ATGC'>
<re.Match object; span=(596, 600), match='AAAC'>
<re.Match object; span=(639, 643), match='AGCC'>
<re.Match object; span=(665, 669), match='ACCC'>
<re.Match object; span=(678, 682), match='AAAC'>
<re.Match object; span=(693, 697), match='AAGC'>
<re.Match object; span=(698, 702), match='ATCC'>
<re.Match object; span=(712, 716), match='ACGC'>
<re.Match object; span=(717, 721), match='ACAC'>
<re.Match object; span=(727, 731), match='AAAC'>
<re.Match object; span=(731, 735), match='ATAC'>
<re.Match object; span=(750, 754), match='ACCC'>
<re.Match object; span=(766, 770), match='AGTC'>
<re.Match object; span=(778, 782), match='ACAC'>
<re.Match object; span=(782, 786), match='ACTC'>
<re.Match object; span=(794, 798), match='ATCC'>
<re.Match object; span=(817, 821), match='ATCC'>
<re.Match object; span=(857, 861), match='AGCC'>
<re.Match object; span=(873, 877), match='AGTC'>
<re.Match object; span=(901, 905), match='AGTC'>
<re.Match object; span=(930, 934), match='AGAC'>
<re.Match object; span=(961, 965), match='AGCC'>
<re.Match object; span=(996, 1000), match='ACAC'>

Biopython에서 parse로 불러오는것마냥 for문이 필요하다. 

 

전방탐색

text='http://localhost:8888/notebooks/re.search.ipynb'

이런 텍스트가 있을 때 

p = re.compile(".+:")
print(p.search(text))

보통은 이렇게 찾는다. 근데 이 방식에는 문제가 있어요... 정규식이 복잡해지면 정규식 짜다가 

이러고 밥상 엎는다. 

 

긍정형 전방 탐색

p = re.compile(".+(?=:)")
print(p.search(text))
<re.Match object; span=(0, 16), match='http://localhost'>

?=가 들어가는 것. 저 식의 경우 :가 있으면 응 있네 여이따 하고 찾아는 주지만 출력을 안 한다. (저거는 Jupyter URL로 해서 그렇다)

 

부정형 전방 탐색

여러분들은 불신의 아이콘에 대해 아시는가? 

얘 맞다. 

그러니까 이런 거. 

 

블로그에서 뭔가를 검색했는 데 저게 보이면 일단 거르고 보잖음. 근데 쟤랑 그거랑 뭔 상관이냐고? 자, 생각해봅시다... 일반적으로 맛집을 찾을 때 저런 바이럴들이 많이 나오니까 우리는 저것들을 피하기 위한 키워드를 정해서 맛집을 찾잖음? (오빠랑 맛집 뭐 이런걸로다가) 부정형 전방 탐색은 맛집 검색을 하면서 아예 저 불신의 아이콘을 빼버리고 찾는 거라고 보면 됨. 

 

file_list=['buchu.jpg','moon.jpg','text.txt','py.py','BOJ.ipynb','jemok.png','pyo.csv']

그러니까 이런 파일들이 있을 때 jpg파일을 빼려면 txt, py, ipynb, png, csv파일을 묶어야 하는데 정규식에 어느 세월에 저걸 다 쓰고 앉았음? 

for i in file_list:
    if re.match('.*[.](?!jpg$).*$',i):
        print(i)
text.txt
py.py
BOJ.ipynb
jemok.png
pyo.csv

이럴 때 부정형 전방탐색으로 jpg를 빼버리면 된다. 정확히는 jpg가 포함되지 않은 것만 보여준다. 

 

sub(), subn()

p=re.compile('W')
p.sub('[A|T]','CCWGG')

이런 식으로 쓰면 W가 A or T로 바뀌어서 나온다. 

 

p=re.compile('N')
p.sub('.','GATNNNATCNNNNNNNN',count=3)

이런 식으로 바꿀 횟수를 지정하는 것도 가능하다. (count=n)

 

('GAT...ATC........', 11)

subn()도 쓰는 방법은 비슷한데, 얘는 반환 형태가 튜플이고 몇 글자 바꿨는지가 나온다. 

 

re.compile()

정규식 일일이 쓰기 귀찮을 때 쓰면 좋다. 

 

p = re.compile('G....C')
print(p.search(DNA))

compile에 옵션을 지정하고, 그 다음 match나 search, 파인드올 돌리면 된다. 

p = re.compile('t.....t',re.I)
print(p.findall(DNA))

옵션은 이런 식으로 붙고, 총 네 개가 있다. 

 

re.compile()의 옵션

1)Dotall(S):와일드카드를 ㄹㅇ 와일드카드로 쓸 수 있다. 저 옵션이 없으면 개행문자는 와일드카드로 대체가 안되는데, 저 옵션을 붙여벼리면 아 그런건 모르겠고 와일드카드! 가 된다. 

2) Ignorecase(I): 대소문자를 무시하고 그냥 일치하는 문자열을 찾아준다. 그러니까 저 옵션을 주면 A랑 a랑 같아진다. (원래 파이썬은 대소문자 칼같이 구별한다) 

3) Multiline(M): 여러 줄로 된 문자열을 줄단위로 인식한다. 그러니까 이게 무슨 말이냐... 

나 보기가 역겨워
가실 때에는
말없이 고이 보내 드리오리다
 
영변에 약산
진달래꽃
아름 따다 가실 길에 뿌리오리다
  
가시는 걸음걸음
놓인 그 꽃을
사뿐히 즈려밟고 가시옵소서
 
나 보기가 역겨워
가실 때에는
죽어도 아니 눈물 흘리오리다

이 시는 김소월의 진달래꽃이다. 마야 아니다 우리가 볼 때는 4연이고 각 연마다 3행인데, Multiline이 없는 정규식 처리에서는 저걸 그냥 한 줄로 본다. 행이고 연이고 그런건 모르겠고 걍 한줄이여! 이렇게 되버리는데 Multiline 옵션이 들어가면 12줄짜리 텍스트(연과 연 사이 개행문자 포함 15줄)로 본다. 

 

4) Verbose(X): 정규식에 주석을 넣을 수 있다. 코드와 마찬가지로 정규식도 복잡해지면 

이렇게 된다. (아니면 머리에 블루스크린이 뜨거나) Verbose 옵션을 주면 그걸 방지하고자 주서을 넣을 수 있게 된다. 

Lv. 35 라이츄

Lv. 35 라이츄

광고 매크로 없는 청정한 블로그를 위해 노력중입니다. 근데 나만 노력하는 것 같음… ㅡㅡ

정규식(Regular Expression)-기호와 메타문자

Coding/Python 2022. 8. 22. 00:17

문자 찾는 것 자체는 find()도 해주는데, 얘는 딱 정확하게 일치하는 문자열만 찾아준다. 그럼 정규식은? 그건 대충 와일드카드같은 거다. 그러니까 find()는 소라빵 찐빵 팥빵 붕어빵 이런 식으로 딱딱 키워드를 찾는거고 정규식은 *빵으로 소라빵 찐빵 붕어빵 팥빵 다 찾는 거지. 

참고로 정규식을 쓰려면 re를 불러야 한다. 

import re

ㄱㄱ


정규식 문자

정규식에서 쓰는 문자들과 이게 뭐 하는건지를 간단히 알아보자. 

 

.

Wildcard(구글 검색에서 *)

 

for i in range(len(pokemon)):
    if re.search('김.',pokemon[i]):
        print(pokemon[i])
김부추
김후추
김양상추
박알타리김치
고등어김치찜
김배추

참고로 전부 본인 포켓몬 이름임. 왜요 

 

^

~로 시작하는 단어

 

for i in range(len(pokemon)):
    if re.search('^김',pokemon[i]):
        print(pokemon[i])
김부추
김후추
김양상추
김배추

꺾쇠가 들어가면 ~로 시작하는 단어를 찾아달라는 얘기. 꺾쇠를 단어 앞에 쓴다. 

 

$

for i in range(len(pokemon)):
    if re.search('!$',pokemon[i]):
        print(pokemon[i])
앗!잘못던짐!
고객님!

~로 끝나는 단어를 찾아달라는 얘기. 달러를 뒤에 쓴다. 이거 ^랑 헷갈리면 안된다. 

 

|

for i in range(len(df)):
    enzyme = df['Enzyme'][i]
    sequence = df['sequence'][i]
    if re.search('W|S',sequence):
        print(enzyme,sequence)

OR. 햄버거|피자는 햄버거 or 피자라는 얘기. 참고로 대문자 I나 소문자 L이 아니고 쉬프트+백슬래시(\)이다. 

 

[ ]

for i in range(len(df)):
    enzyme = df['Enzyme'][i]
    sequence = df['sequence'][i]
    if re.search('[NSW]',sequence):
        print(enzyme,sequence)

일단 하는 역할 자체는 OR이랑 비슷하다. 대괄호 안에 있는것들 중 하나를 포함하고 있는 것. Cutter에 있는 제한효소 인식 시퀀스도 전부 대괄호로 치환한 것. 

 

[^]

for i in range(len(df)):
    enzyme = df['Enzyme'][i]
    sequence = df['sequence'][i]
    if re.search('^Ba[^c]',enzyme):
        print(enzyme,sequence)
BaeI ACNNNNGTAYC
Bal228I GGNCC
BamNII GGWCC
BanI GGYRCC
BanII GRGCYC
BasI CCANNNNNTGG
BavAII GGNCC
BavBII GGNCC

쓰는 법은 일반적인 ^ 쓰는것처럼 앞에 붙이면 된다. 단, 대괄호 안에 있는 꺾쇠는 [] 안에 있는것들 중 쟤는 빼라는 얘기. 

 

[-]

어디부터 어디까지라고 지정하는 것.

[a-z] : 영어 문자의 모든 범위를 지정한다.
[가-힣] : 한글 문자의 모든 범위를 지정한다.
[0-9] : 숫자의 모든 범위를 지정한다.

 

( )

for i in range(len(df)):
    enzyme = df['Enzyme'][i]
    sequence = df['sequence'][i]
    if re.search('(Eco)',enzyme):
        print(enzyme,sequence)
Eco24I GRGCYC
Eco31I GGTCTC
Eco47I GGWCC
Eco57I CTGAAG
Eco64I GGYRCC
Eco81I CCTNAGG
Eco88I CYCGRG
Eco91I GGTNACC
Eco130I CCWWGG
Eco1831I CCSGG
EcoA4I GGTCTC
EcoHI CCSGG
EcoHK31I YGGCCR
Eco75KI GRGCYC
Eco57MI CTCRAG
EcoNI CCTNNNNNAGG
EcoO44I GGTCTC
EcoO65I GGTNACC
EcoO109I RGGNCCY
EcoO128I GGTNACC
EcoP15I CACGAG
EcoR124II GAANNNNNNNRTCG
EcoRII CCWGG
EcoT14I CCWWGG
EcoT38I GRGCYC
Eco13kI CCNGG
Eco21kI CCNGG
Eco27kI CYCGRG
Eco137kI CCNGG

괄호 안에 있는 걸 그룹으로 묶어서 찾는다. [붕어빵]은 붕 아님 어 아님 빵 들어간건 다 찾아주는데 (붕어빵)은 붕어빵만 찾는다. 

 

메타 문자

백슬래시 뒤에 뭔가 오는 것. 

 

\d, \D

숫자 포함, 숫자 제외

 

for i in range(len(pokemon)):
    if re.search('\d',pokemon[i]):
        print(pokemon[i])
대포동1호
김2번척추씨

대포동1호 뭐예요 제 파이어로요

 

for i in range(len(df)):
    enzyme = df['Enzyme'][i]
    sequence = df['sequence'][i]
    if re.search('^A..\D',enzyme):
        print(enzyme,sequence)
AarI CACCTGC
AccI GTMKAC
AccB1I GGYRCC
AccB2I RGCGCY
AccB7I CCANNNNNTGG
AceI GCWGC
AceIII CAGCTC
AclWI GGATC
AcoI YGGCCR
AcpII CCANNNNNTGG
AcrII GGTNACC
AcsI RAATTY
AcuI CTGAAG
AcyI GRCGYC
AdeI CACNNNGTG
AeuI CCWGG
AfiI CCNNNNNNNGG
AflI GGWCC
AflIII ACRYGT
AglI CCWGG
AgsI TTSAA
AhaI CCSGG
AhaII GRCGYC
AhdI GACNNNNNGTC
AjnI CCWGG
AjuI GAANNNNNNNTTGG
AlfI GCANNNNNNTGC
AloI GAACNNNNNNTCC
AlwI GGATC
AlwNI CAGNNNCTG
AlwXI GCAGC
AmaCSI GCTCCA
AocI CCTNAGG
AocII GDGCHC
AorI CCWGG
AosII GRCGYC
ApaBI GCANNNNNTGC
ApaORI CCWGG
ApeKI GCWGC
ApoI RAATTY
ApyI CCWGG
ApyPI ATCGAC
AquI CTCGRG
AquII GCCGNAC
AquIII GAGGAG
AquIV GRGGAAG
ArsI GACNNNNNNTTYG
AseII CCSGG
AspI GACNNNGTC
AspAI GGTNACC
AspEI GACNNNNNGTC
AspHI GWGCWC
AspNI GGNNCC
AstWI GRCGYC
AsuI GGNCC
AsuIII GRCGYC
AsuC2I CCSGG
AsuHPI GGTGA
AtsI GACNNNGTC
AvaI CYCGRG
AvaII GGWCC
AvcI GGNCC

소문자 d는 숫자 포함이고 대문자 D는 제외이다. 근데 이 케이스의 경우 ^A..\D보다는 .에 반복 주고 \D로 쓰는 쪽이 더 나을듯... 알파벳 두 글자 이후로 숫자가 오는 제한효소는 리스트업이 안됐는데, AsuC2I처럼 알파벳 세글자 다음에 숫자가 있는 제한효소는 나왔다. 

 

\s, \S

for i in range(len(list_n)):
    if re.search('a\s',list_n[i]):
        print(list_n[i])
a bc
a b c

이게 \s(공백 포함)

 

for i in range(len(list_n)):
    if re.search('a\S',list_n[i]):
        print(list_n[i])
abc
ab c
abab

얘는 \S(공백 제외)이다. 

 

\b, \B

이건 설명하기가 좀 애매한디... 

 

text='he said checkmate for my class mate, before she move her knight.'

이 구문이 있을 때 

 

p = re.compile(r'\bmate')
p.search(text)

이걸 치면 class mate의 mate가 나온다. 

p = re.compile(r'\Bmate')
p.search(text)

이렇게 주면 checkmate의 mate가 나온다. 얘는 단어와 단어 사이의 공백을 따지기 때문. 

 

\w, \W

각각 숫자와 알파벳, 숫자와 알파벳 제외. 

 

for i in range(len(df)):
    enzyme = df['Enzyme'][i]
    sequence = df['sequence'][i]
    if re.search('^X..\w',enzyme):
        print(enzyme,sequence)
XagI CCTNNNNNAGG
XapI RAATTY
XceI RCATGY
XcmI CCANNNNNNNNNTGG
XhoII RGATCY
XmiI GTMKAC
XmnI GAANNNNTTC

이게 \w고 

 

for i in range(len(df)):
    enzyme = df['Enzyme'][i]
    sequence = df['sequence'][i]
    if re.search('^X..\W',enzyme):
        print(enzyme,sequence)

이게 \W. 제한효소 이름은 숫자와 알파벳만으로 되어 있으므로 저렇게 주고 찾으면 검색결과가 없는 게 정상이다. 

 

\A, \Z

문자열의 시작과 끝. ^과 $에 대응하지만 Multiline 옵션을 주더라도 얘는 문자열의 시작과 끝만 출력한다. 

 

*, *?

반복을 나타내는 문자. 0회 이상 반복이면 다 찾는다. 

 

for i in range(len(pokemon)):
    if re.search('김*추',pokemon[i]):
        print(pokemon[i])
김부추
김후추
김양상추
김배추
김2번척추씨

김과 추 사이에 뭐 들어가면 다 나온다. 

 

+, +?

얘는 한 번 이상 반복되면 다 나온다. 

 

for i in range(len(df)):
    enzyme = df['Enzyme'][i]
    sequence = df['sequence'][i]
    if re.search('^Ca+',enzyme):
        print(enzyme,sequence)
Cac8I GCNNGC
CaiI CAGNNNCTG
CauI GGWCC
CauII CCSGG

C로 시작하면서 a가 한 번 이상 들어가는 제한효소를 출력한다. 

 

?

for i in range(len(df)):
    enzyme = df['Enzyme'][i]
    sequence = df['sequence'][i]
    if re.search('^Ca?',enzyme):
        print(enzyme,sequence)
Cac8I GCNNGC
CaiI CAGNNNCTG
CauI GGWCC
CauII CCSGG
CbrI CCWGG
CcuI GGNCC
CelII GCTNAGC
CfrI YGGCCR
Cfr10I RCCGGY
Cfr13I GGNCC
CfrBI CCWWGG
CjeI CCANNNNNNGT
CjePI CCANNNNNNNTC
CpoI CGGWCCG
CspI CGGWCCG
CspCI CAANNNNNGTGG
Csp68KI GGWCC
CstMI AAGGAG
CthII CCWGG
CviBI GANTC
CviJI RGCY
CviTI RGCY
CvnI CCTNAGG

0회 or 1회 이상 반복. ...이럴거면 그냥 C로 시작하는 거 뽑고 말지... 

 

{ }

중괄호를 주면 반복 횟수를 지정할 수 있다. 

 

for i in range(len(pokemon)):
    if re.search('김.{1}추',pokemon[i]):
        print(pokemon[i])

아무거나 1회 반복

 

for i in range(len(pokemon)):
    if re.search('김.{1,3}추',pokemon[i]):
        print(pokemon[i])

아무거나 1~3회 반복

 

for i in range(len(df)):
    enzyme = df['Enzyme'][i]
    sequence = df['sequence'][i]
    if re.search('[GATC]{3}N{3}[GATC]',sequence):
        print(enzyme,sequence)
AdeI CACNNNGTG
AlwNI CAGNNNCTG
AspI GACNNNGTC
AtsI GACNNNGTC
BstZ316I CACNNNGTG
CaiI CAGNNNCTG
DraIII CACNNNGTG
PflFI GACNNNGTC
PsyI GACNNNGTC
TelI GACNNNGTC
Tth111I GACNNNGTC

GATC 중 아무거나 3개 반복되고 N이 3개 온 다음 GATC가 오는 패턴

Lv. 35 라이츄

Lv. 35 라이츄

광고 매크로 없는 청정한 블로그를 위해 노력중입니다. 근데 나만 노력하는 것 같음… ㅡㅡ

Cutter 기능 추가: 정규식 도입

Coding/Python 2022. 8. 22. 00:03

Finder는 도입하려면 좀 걸립니다... 얘는 아예 정규식+찾아바꾸기가 필요한거라...... 


정규식 도입

import pandas as pd
import re
from datetime import datetime
enzyme_table = pd.read_csv('/home/koreanraichu/restriction.csv')
enzyme_table2 = pd.read_csv('/home/koreanraichu/restriction_RE.csv')
# 정규식 도입을 위해... 어쩔 수 없이 합쳤음... 
enzyme_table = pd.concat([enzyme_table,enzyme_table2])
enzyme_table = enzyme_table.sort_values('Enzyme')
enzyme_table.reset_index(inplace=True)
# 합쳤다... 
print(enzyme_table)

뭐가 좀 많은데, RE 들어가는 csv파일이 정규식 처리가 필요한 효소들. 인식 시퀀스에 N, S, B같은 게 있는 효소들이다. 정규식 없이 find를 쓰면 못 찾기때문에 뺐다. 

 

class RE_treatment:
    def RE_wildcard(self,before_seq):
        self.before_seq = before_seq
        before_seq = before_seq.replace("N",".")
        return before_seq
    # Wildcard: 시퀀스 데이터에 N이 있을 경우 Wildcard로 바꾼다. 
    def RE_or(self,before_seq):
        self.before_seq = before_seq
        if "B" in before_seq:
            before_seq = before_seq.replace("B","[CGT]")
        elif "D" in before_seq:
            before_seq = before_seq.replace("D","[AGT]")
        elif "H" in before_seq:
            before_seq = before_seq.replace("H","[ACT]")
        elif "K" in before_seq:
            before_seq = before_seq.replace("K","[GT]")
        elif "M" in before_seq:
            before_seq = before_seq.replace("M","[AC]")
        elif "R" in before_seq:
            before_seq = before_seq.replace("R","[AG]")
        elif "S" in before_seq:
            before_seq = before_seq.replace("S","[CG]")
        elif "V" in before_seq:
            before_seq = before_seq.replace("V","[ACG]")
        elif "W" in before_seq:
            before_seq = before_seq.replace("W","[AT]")
        elif "Y" in before_seq:
            before_seq = before_seq.replace("Y","[CT]")
        return before_seq
    # Or: 시퀀스 데이터에 N 말고 ATGC 말고 다른 알파벳이 있을 경우, 해당하는 정규식 문법으로 바꾼다.

클래스. 대충 쿠키틀 해당 클래스는 N, D, B와 같은 알파벳들을 정규식 처리 하는 코드를 담고 있다. 

 

def convert (a):
    RE = RE_treatment()
    while True:
        if "N" in res_find:
            res_find_after = RE.RE_wildcard(res_find)
        elif "B" in res_find or "D" in res_find or "H" in res_find or "K" in res_find or "M" in res_find or "R" in res_find or "S" in res_find or "V" in res_find or "W" in res_find or "Y" in res_find: 
            res_find_after = RE.RE_or(res_find)
        else: 
            break
        return res_find_after

무식하게 조건문 때려박은 if문... 저 While True가 없으면 GCDGHC처럼 알파벳이 여러글자일 때에 대한 처리가 안된다. (N은 아예 일괄적으로 wildcard화 함)

 

if "N" in res_find or "B" in res_find or "D" in res_find or "H" in res_find or "K" in res_find or "M" in res_find or "R" in res_find or "S" in res_find:
    res_find_after = str(convert(res_find))
else: 
    res_find_after = res_find
# 정규식 처리(문자가 두 개 이상일때에 대한 처리가 필요함)
Findall = re.findall(res_find_after,sequence)
if Findall: 
    count += 1
    site_count = len(Findall)
    if site_count == 1:
    once_cut_list.append(enzyme)
elif site_count == 2: 
    two_cut_list.append(enzyme)
else: 
    multi_cut_list.append(enzyme)
res_loc_list = ', '.join(res_loc_list)
f.write("{0}: {1} {2},{3} times cut. Where(bp): {4} \n".format(enzyme,res_find,feature,site_count,res_loc_list))

(그래서 대충 문제의 코드)

 

어디 자르는지 세 주는 기능

얘는 쉽다. 

 

def cut_func (a,b):
    global res_loc_list
    locs = re.finditer(a,b)
    for i in locs:
        loc = i.start()
        res_loc_list.append(str(loc))
    return res_loc_list
# 여기가 위치 관련 함수입니다.

finditer()로 다 찾은 다음, 해당 레코드에서 start(시작 지점)을 리스트화하면 된다.

결과 

이제 Finder에 도입한 다음 FASTA까지 하면 어지간한건 다 된다. 

Lv. 35 라이츄

Lv. 35 라이츄

광고 매크로 없는 청정한 블로그를 위해 노력중입니다. 근데 나만 노력하는 것 같음… ㅡㅡ

Searcher 기능 추가: 그 뭐더라 그 D로 시작하는 그거

Coding/Python 2022. 8. 21. 23:05

일단... 

해당 기능 추가 결과물이고요... 정규식 얘기는 나중에 입 털어드림... 


import re # 정규식용 모듈

정규식은 얘가 있어야 쓸 수 있다. 

 

elif keyword == "name":
    enzyme_RE = input("효소의 이름이 뭘로 시작하나요? ")
    enzyme_RE_2 = '^' + enzyme_RE

물론 if문에도 관련 코드를 추가했다. (^ 붙으면 그걸로 시작하는 걸 찾아준다)

 

else: 
    print("Enzyme with start with {0}".format(enzyme_RE))
    for i in range(len(enzyme_table)):
        DB_enzyme = str(enzyme_table['Enzyme'][i]).strip()
        DB_seq = str(enzyme_table['sequence'][i]).strip().upper()
        DB_site = str(enzyme_table['restriction_site'][i]).strip().upper()
        if re.search(enzyme_RE_2,DB_enzyme):
            print("{0} | {1} | {2}".format(DB_enzyme,DB_seq,DB_site))
# 간단 검색(머릿글자)

물론 처리하는 코드도 추가했지... 

'Coding > Python' 카테고리의 다른 글

정규식(Regular Expression)-기호와 메타문자  (0) 2022.08.22
Cutter 기능 추가: 정규식 도입  (0) 2022.08.22
cutter, finder, searcher에 앞으로 추가할 기능  (0) 2022.08.21
For vs While  (0) 2022.08.21
Finder & Cutter 패치  (0) 2022.08.21
Lv. 35 라이츄

Lv. 35 라이츄

광고 매크로 없는 청정한 블로그를 위해 노력중입니다. 근데 나만 노력하는 것 같음… ㅡㅡ

cutter, finder, searcher에 앞으로 추가할 기능

Coding/Python 2022. 8. 21. 23:04

FASTA 파일 지원

1) 일단 사용자가 FASTA파일을 읽어오게 되면 따로 시퀀스 정보 입력을 받을 필요가 없어서 그거 관련도니 처리가 필요함. (시퀀스 이름은 Biopython SeqIO로 FASTA파일 ID 가져올 예정)

2) Biopython의 경우 FASTA파일에 꺾쇠가 하나면 read, 여러개면 parse로 가져오는데 parse로 읽을 걸 read로 가져오면 에러뜸. 에러에 대한 처리가 필요하고... parse로 가져오는 파일은 꺾쇠가 여러개인데, 이게 다르게 말하면 ID랑 시퀀스라 여러개라 그거 읽어오면 여러개를 돌리고 저장까지 해야 하는거라 이거는 Jupyter단에서는 힘듭니다... OTL 그래서 단식만 읽을거임... 

3) FASTA 관련된 기능이긴 한데, 본인은 애초에 경로가 고정되어 있으니까 상관 없는데... 그리고 파일이 저장되는 위치가 Jupyter 코드가 있는 경로기도 하고(홈), 리눅스는 경로가 간단간단해요 생각보다... usr 이런거 아니면. 그래서 경로가 고정되어 있지만, 사용자들 입장에서 이러면 상당히 불편하기때문에... FASTA 파일 열 때 뿐 아니라 파일 저장할 때 저장 경로를 선택할 수 있는 창을 띄울 예정입니다... 아니 누가 자기 파일 경로를 다 외워... 

 

Searcher 기능 관련

1) Wildcard 기능(시퀀스 혹은 효소 이름)

2) restriction site에 N이나 W같은 알파벳이 있을 때 처리법... 이건 finder보다 cutter단에서 처리하는 게 쉽습니다. finder는 찾아서 텍스트를 대체해야 하니... 이거는 둘 다 정규식 찾아서 직접 해 보고 적응해야 합니다. N은 차라리 wildcard니까 적용하기 쉽지... W M 이런거는 or이라;;;; 

사실 언제 추가될지는 모르겠지만 일단 우선적으로 해보겠음. 

'Coding > Python' 카테고리의 다른 글

Cutter 기능 추가: 정규식 도입  (0) 2022.08.22
Searcher 기능 추가: 그 뭐더라 그 D로 시작하는 그거  (0) 2022.08.21
For vs While  (0) 2022.08.21
Finder & Cutter 패치  (0) 2022.08.21
Searcher 만들었음  (0) 2022.08.21
Lv. 35 라이츄

Lv. 35 라이츄

광고 매크로 없는 청정한 블로그를 위해 노력중입니다. 근데 나만 노력하는 것 같음… ㅡㅡ

For vs While

Coding/Python 2022. 8. 21. 23:03

기본

파이썬에는 두 가지 반복문이 있는데 한놈은 For고 한놈은 While이다. While은 베이직에서 본 거 같은디... (do while loop) 아무튼... 둘 다 반복문이긴 한데, 둘이 맥락은 좀 다르다. 내가 10페이지의 책을 읽는 것을 for와 while을 이용해 설명하자면 

For: 1쪽부터 10쪽까지 읽어야징
While: 읽은 페이지 수가 10이 될 때까지 읽어야징

이런 차이가 있다. ...사실 이렇게 말하면 모르시겠져? 그래서 가져왔음. 

둘 다 3^1~1^10까지 출력하는 코드인데(사실 저렇게 안하고 프린트문 줘도 됨)

For: 1부터 10까지 3에 제곱해
While: j가 있는데 이게 11보다 작을 동안 3에 제곱하고 하나씩 더해 

이런 식으로 돌아간다. For문은 범위를 주고 반복하는 반복문이고 While은 어떤 조건을 주고 반복하는 조건부 반복문. 그래서 For는 범위가 끝나면 반복문이 끝나고 While은 조건을 만족하면 반복문이 끝난다. 

참고로 베이직의 Do while loop와 비슷한건 While쪽이다. 

 

For ~ in range

본인은 보통 for i in range: 로 쓴다. 국민 알파벳 뭐 이런건가 바이오파이썬 할 때도 많이 봤던 그거 맞다. 고 때는 for record in records: 형태로 썼다.

for i in range(5):
    print(i)

이런 식으로 쓴다. 이건 0부터 4까지 출력하는 코드로, range는 별 지시가 없으면 0부터 시작해서 ~미만까지 잡는다. 

a=list(range(1,11))
for i in a: 
    print(i*i)

이미 리스트가 존재할때는 이런 식으로 쓰기도 한다. 

a="힘세고 강한 아침!"
for i in a: 
    print(i)

내가 그 얘기를 안해줄 뻔 했는데... 이거 문자열에도 먹힌다. 

 

While True

그냥 무한루프. 

 

i=1
while True: 
    i += 1
    if i > 10:
        break
print(i)

이게 While True를 적용한 간단한 코드인데, 밑에 있는 break는 뭐냐... While True는 무한루프라 사용자가 멈추지 않는 이상 계속 돌아간다. 그러면 ctrl+c를 누르거나 프로세스를 죽이지 않는 이상 계에에에에에에에에속 돌아간다 이 얘기. 저기 있는 if문과 break는 i에 1을 계에에에에속 더하다가 i가 10보다 크면 루프문을 빠져나와라 이 얘기다. 즉, while True는 break 없으면 계에에에에에에에에속 돌아간다. 

Lv. 35 라이츄

Lv. 35 라이츄

광고 매크로 없는 청정한 블로그를 위해 노력중입니다. 근데 나만 노력하는 것 같음… ㅡㅡ

Finder & Cutter 패치

Coding/Python 2022. 8. 21. 23:00

1. 공통: 이제 어디 자르는지도 나옵니다. 살려줘... 
2. Cutter: 제한효소 누락되던 거 수정했습니다. 근데 된건지 모르겠음. 


def count_func (a,b):
    while a in b:
        global site_count
        global res_loc 
        global res_loc_list
        loc = b.find(a)
        site_count += 1
        b = b[loc+len(a):]
        res_loc = loc + 1
        res_loc_list.append(res_loc)
    return site_count, res_loc
# 이거 통으로 코드에 넣었더니 if 안에 있는데도 시퀀스 없으면 끝내더라... 
# 위치 출력은 되는 것 같은데, 이거 더해야 하는데...

이렇게 하면 위치가 출력되긴 한데 문제가 하나 있다. 저 로직이 해당 시퀀스에서 제한효소 인식 site가 있으면 그 부분 다음 글자부터 slicing을 한다. 그래서 

AfaI [167, 150, 167, 53, 70] [830, 677, 507, 451, 378]
# restriction site 위치와 b(시퀀스에서 restriction site가 끝나는 부분부터 슬라이싱한 결과)의 길이

이렇게 나온다... (왼쪽이 find 결과) 오른쪽은 슬라이싱하고 남은 자리. 

 

def cut_func (a,b):
    while a in b:
        global res_loc
        global res_loc_list
        global length_seq
        global length_list
        loc = b.find(a)
        b = b[loc+len(a):]
        res_loc = loc + 1
        res_loc_list.append(res_loc)
        length_seq = len(b)
        length_list.append(length_seq)
    return res_loc_list,length_list
# 여기가 위치 관련 함수입니다.
# len(a): 인식 시퀀스 길이, len(b): 슬라이싱 하고 남은 시퀀스 길이

일단 복잡하니까 함수 밖으로 빼고 

AanI [80] [15]
# 결과(AanI의 시퀀스는 TTATAA로 6bp)
# 슬라이싱하고 남은 텍스트의 길이가 15bp이다.

저게 왜 저렇게 나오냐면 

1. AanI이 인식하는 시퀀스(TTATAA)는 6bp이다. (len(AanI)=6)
2. AanI이 인식하는 시퀀스 다음 위치부터 슬라이싱하면 15bp가 남는다. (왼쪽은 find에 +1한 값이다)

 

length_list.append(seq_length - (length_seq + len(a))) # slicing 후의 길이 목록

그래서 전체 길이-(슬라이싱+인식 시퀀스)+1하면 위치가 같게 나온다. (위 코드의 값에 1을 더하면 된다) 저렇게 하면 AanI의 경우 100-(15+6)+1이 되므로 80. 

 

def cut_func (a,b):
    while a in b:
        global res_loc # find로 나오는 값
        global res_loc_list
        seq_length = len(sequence)
        loc = b.find(a)
        b = b[loc+len(a):]
        res_loc = len(sequence) - (len(b) + len(a)) + 1
        res_loc_list.append(str(res_loc)) # find로 나오는 위치 목록(slicing에 따른 보정 필요)
    return res_loc_list,length_list
# 여기가 위치 관련 함수입니다.
res_loc_list = ', '.join(res_loc_list)
            f.write("{0}: {1} {2},{3} times cut. Where(bp): {4} \n".format(enzyme,res_find,feature,site_count,res_loc_list))

정리하고 출력 코드 바꾸면 된다. 

 

테스트 시퀀스(cutter, 100bp)
테스트 시퀀스(cutter, 1.5kb)
테스트 시퀀스(finder, 100bp)
테스트 시퀀스(finder, 1kb)

 

'Coding > Python' 카테고리의 다른 글

cutter, finder, searcher에 앞으로 추가할 기능  (0) 2022.08.21
For vs While  (0) 2022.08.21
Searcher 만들었음  (0) 2022.08.21
Cutter & Finder 패치노트  (0) 2022.08.21
Cutter와 Finder에 패치가 있었습니다.  (0) 2022.08.21
Lv. 35 라이츄

Lv. 35 라이츄

광고 매크로 없는 청정한 블로그를 위해 노력중입니다. 근데 나만 노력하는 것 같음… ㅡㅡ

Searcher 만들었음

Coding/Python 2022. 8. 21. 22:57

DB를 구축할 때 수동으로 구축했는데, CSV 구분자가 ,다보니 .로 들어간게 좀 있어서 그거 수정했음... (마른세수) 
효소 이름 오타난것도 수정했습니다... 

이래서 손끝 다치면 안됨... 


import pandas as pd
enzyme_table = pd.read_csv('/home/koreanraichu/restriction.csv')
# 이쪽은 Finder나 cutter에도 쓰이는 그 DB가 맞습니다. 
enzyme_table2 = pd.read_csv('/home/koreanraichu/restriction_RE.csv')
# 이쪽은 restriction site나 cut site에 A,T,G,C가 아닌 다른 알파벳이 들어가기 때문에 여기서 처음 불러오는 DB입니다. 
enzyme_table = pd.concat([enzyme_table,enzyme_table2])
enzyme_table = enzyme_table.sort_values('Enzyme')
enzyme_table.reset_index(inplace=True)
# 니네는 꼭 합치고 나면 인덱스도 바꿔줘야되더라...

사실 DB가 두갠데(둘다 GitHub에 올라가 있음), 하나는 Finder랑 Cutter에도 적용중이고 다른 하나는 적용하려면 별도의 처리가 필요해서(그게 RE 들어간 거) 여기에 처음 도입했음. 아직까지 통합DB가 없어서 불러온 다음 합치고 인덱싱 다시 하는 절차가 필요합니다. 

 

enzyme = input("찾고자 하는 효소를 입력해주세요: ")
# 아직 시퀀스로 검색하는 기능은 없습니다.

아직 효소 이름으로만 된다. (시퀀스로 검색하게 되면 밑에 로직도 수정해야 함)

 

def SeqtoString (a):
    a = enzyme_table.sequence[(enzyme_table['Enzyme'] == enzyme)]
    a = a.to_string(index = False)
    a = str(a)
    return a
def SitetoString (a):
    a = enzyme_table.restriction_site[(enzyme_table['Enzyme'] == enzyme)]
    a = a.to_string(index = False)
    a = str(a)
    return a

문자열화 해 주는 함수가 있고... 

 

for i in range(len(enzyme_table)):
    find_seq = SeqtoString(enzyme)
    Site_seq = SitetoString(enzyme_table['restriction_site'][i])
    DB_enzyme = enzyme_table['Enzyme'][i]
    DB_seq = enzyme_table['sequence'][i]
    DB_site = enzyme_table['restriction_site'][i]
    if find_seq == str(DB_seq):
        print(DB_enzyme,DB_seq,DB_site)
    else: 
        pass

일단 이렇게만 하고 HaeIII으로 검색해 본 결과. 잘 되는데, 입력한 효소는 빼는 게 맞지 않나... (시퀀스로 검색하게 되면 이 부분도 바뀐다)

 

print("{0} | {1} | {2} | Input enzyme".format(enzyme,find_seq,Site_seq))
for i in range(len(enzyme_table)):
    find_seq = SeqtoString(enzyme)
    Site_seq = SitetoString(enzyme)
    DB_enzyme = enzyme_table['Enzyme'][i]
    DB_seq = enzyme_table['sequence'][i]
    DB_site = enzyme_table['restriction_site'][i]
    if find_seq == str(DB_seq) and DB_enzyme != enzyme:
        if Site_seq == DB_site:
            print("{0} | {1} | {2} | Isoschizomer".format(DB_enzyme,DB_seq,DB_site))
            # 인식하는 시퀀스와 자르는 방식이 같은 제한효소
        else: 
            print("{0} | {1} | {2} | Neoschizomer".format(DB_enzyme,DB_seq,DB_site))
            # 인식하는 시퀀스는 같으나 자르는 방식이 다른 제한효소
    elif find_seq == str(DB_seq) and DB_enzyme == enzyme:
        pass
    else: 
        pass

Isoschizomer와 Neoschizomer를 구별해준다. (입력한 효소는 물론 뺐다) 시퀀스로 검색하는 기능을 넣게 되면, 이 부분도 로직이 바뀌게 된다. (시퀀스로 검색할 경우 해당 시퀀스를 인식하는 제한효소를 다 뽑아와야 함) 

 

Iso = ', '.join(Iso)
Neo = ', '.join(Neo)
print("Isoschizomer: {0} \nNeoschizomer: {1}".format(Iso,Neo))
# 실제로 Isoschizomer인데도 Neoscizomer로 표기하는 문제가 있습니다. (BamHI-Nsp29132OO)

물론 본인쟝은 친절하게 텍스트로도 출력해드림. (얘는 따로 데이터 저장할 생각은 없음)


참고

Isoschizomer: 인식하는 시퀀스와 자르는 형태가 같은 제한효소
Neoschizomer: 인식하는 시퀀스는 같은데 자르는 형태가 다른 제한효소(예: GGCC를 인식하지만 한놈은 GG/CC로 자르고 한놈은 /GGCC로 자르는 것)


keyword = input("효소 이름으로 찾으실거면 enzyme을, restriction site sequence로 찾으실거면 sequence를 입력해주세요. ")
if keyword == "enzyme":
    enzyme = input("찾고자 하는 효소를 입력해주세요: ")
elif keyword == "sequence":
    seq = input("찾고자 하는 restriction site sequence를 입력해주세요: ")
else: 
    print("다시 입력해주세요. ")
# 효소 이름으로 찾느냐, 시퀀스로 찾느냐에 따라 검색 결과가 다릅니다.

현재 효소 이름과 인식하는 시퀀스로 찾는 기능을 지원함. (둘 중 하나로만 찾을 수 있습니다)

 

if keyword == "enzyme":
    find_seq = SeqtoString(enzyme)
    Site_seq = SitetoString(enzyme)
    Iso = []
    Neo = []
    print("{0} | {1} | {2} | Input enzyme".format(enzyme,find_seq,Site_seq))
    for i in range(len(enzyme_table)):
        DB_enzyme = str(enzyme_table['Enzyme'][i]).strip()
        DB_seq = str(enzyme_table['sequence'][i]).strip().upper()
        DB_site = str(enzyme_table['restriction_site'][i]).strip().upper()
        if find_seq == str(DB_seq) and DB_enzyme != enzyme:
            if Site_seq == DB_site:
                Iso.append(DB_enzyme)
                print("{0} | {1} | {2} | Isoschizomer".format(DB_enzyme,DB_seq,DB_site))
                # 인식하는 시퀀스와 자르는 방식이 같은 제한효소
            elif Site_seq != DB_site: 
                Neo.append(DB_enzyme)
                print("{0} | {1} | {2} | Neoschizomer".format(DB_enzyme,DB_seq,DB_site))
                # 인식하는 시퀀스는 같으나 자르는 방식이 다른 제한효소
        elif find_seq == str(DB_seq) and DB_enzyme == enzyme:
            pass
        else: 
            pass
# 여기까지는 효소 이름으로 검색할 때의 코드

이 쪽은 효소 이름으로 찾을 때 로직이고 

 

else: 
    find_seq = seq
    print("Searched by: {0}".format(seq))
    for i in range(len(enzyme_table)):
        DB_enzyme = str(enzyme_table['Enzyme'][i]).strip()
        DB_seq = str(enzyme_table['sequence'][i]).strip().upper()
        DB_site = str(enzyme_table['restriction_site'][i]).strip().upper()
        if find_seq == DB_seq:
            print("{0} | {1} | {2}".format(DB_enzyme,DB_seq,DB_site))
        else:
            pass
# 여기까지는 인식 시퀀스로 검색할 때의 코드

이 쪽은 시퀀스로 찾는 로직입니다. 

별개로 sticky만, blunt만 찾는 것도 있으면 좋을 것 같긴 함. 

'Coding > Python' 카테고리의 다른 글

For vs While  (0) 2022.08.21
Finder & Cutter 패치  (0) 2022.08.21
Cutter & Finder 패치노트  (0) 2022.08.21
Cutter와 Finder에 패치가 있었습니다.  (0) 2022.08.21
제한효소 커터 2편 나왔음  (0) 2022.08.21
Lv. 35 라이츄

Lv. 35 라이츄

광고 매크로 없는 청정한 블로그를 위해 노력중입니다. 근데 나만 노력하는 것 같음… ㅡㅡ

Cutter & Finder 패치노트

Coding/Python 2022. 8. 21. 22:54

공통패치

Cut수 세 주는 기능이 추가되었습니다. 

Cutter

Cut수에 따른 효소 리스트 업 기능이 추가되었습니다. 살려줘... (아직 자르는 위치 안했음)
파일 이름 형식이 변경되었습니다. 그래서 이제 시퀀스 이름도 받습니다. 

 

Finder

Cut수 세 주는 기능에 따른 출력 형식 수정이 있었습니다. 


Cut수 세 주는 기능

사실상 엄청난 노가다의 결과...ㅠㅠ 

 

(생략)
        if res_find in sequence:
            site_count = 0
            while sequence.find(res_find) != -1:
                loc = sequence.find(res_find)
                site_count += 1
                sequence = sequence[loc+len(res_find):]
                print(enzyme, res_find, sequence.find(res_find))
            f.write("{0}: {1} {2},{3} times cut.\n".format(enzyme,res_find,feature,site_count))
(생략)

이 코드가 단식으로는 되는데 전체 코드에 쌩으로 도입했더니, restriction site가 없는 효소가 나오면 거기서 멈춰버린다. (여기까지가 전날 저녁에 try했던 부분)

def count_site (a,b):
    site_count = 0
    while a in b:
        loc - b.find(a)
        site_count += 1
        b = b[loc+len(a):]
        return site_count

그래서 해당 로직을 아예 함수로 빼버렸다. 

(마른세수)

 

def count_site (a,b):
    site_count = 0
    while a in b:
        loc = b.find(a)
        site_count += 1
        b = b[loc+len(a):]
        return site_count

근데 생각해보니 네번째 줄에 -가 왜 들어감? (원래 =)

실례지만 0컷이면 안 나와야 정상 아니냐. 

 

def count_func (a,b):
    site_count = 0
    while a in b:
        loc = b.find(a)
        site_count += 1
        b = b[loc+len(a):]
    return site_count
# 이거 통으로 코드에 넣었더니 if 안에 있는데도 시퀀스 없으면 끝내더라... 
print(count_site("GGCC",sequence))

답답해서 직접 해봤더니 이건 잘 되더라. 

 

def count_func (a,b):
    while a in b:
        global site_count
        loc = b.find(a)
        site_count += 1
        b = b[loc+len(a):]
    return site_count
# 이거 통으로 코드에 넣었더니 if 안에 있는데도 시퀀스 없으면 끝내더라...

함수 내에서는 그냥 전역변수 선언하고 

(생략)
        if res_find in sequence:
            site_count = 0
            count_func(res_find,sequence)
            count += 1
            f.write("{0}: {1} {2},{3} times cut.\n".format(enzyme,res_find,feature,site_count))
        else: 
            count += 0
(생략)
# 여러분 드디어 저장기능이 추가되었습니다!!!

site_count 변수를 함수 밖으로 빼버렸다. (site_count는 if문 안쪽에 있다)

 

(흐-뭇)

 

Cut수별로 나눠주는 기능

(생략)
        if res_find in sequence:
            site_count = 0
            count_func(res_find,sequence)
            count += 1
            count_nocut += 0
            cut_list.append(enzyme)
            f.write("{0}: {1} {2},{3} times cut.\n".format(enzyme,res_find,feature,site_count))
        else: 
            count += 0
            count_nocut += 1
            nocut_list.append(enzyme)
    cut_list = ', '.join(cut_list)
    nocut_list = ', '.join(nocut_list)
    f.write("Total: {0} enzymes cut input sequence, {1} enzymes never cut this sequence. \n".format(count,count_nocut))
    f.write("Enzyme cuts: {0} \nEmzyme no cuts: {1}".format(cut_list,nocut_list))
    f.close()
# 진짜 세주는거 겨우 추가했습니다...ㅠㅠ

사실 길어서 생략했는데 코드 위쪽에 0컷이랑 컷 두 개의 리스트가 있다. 

count = 0
count_nocut = 0
cut_list = []
nocut_list = []

이놈들. (count는 원래 있던 변수고 그 밑에 있는 게 새로 추가한 변수)

 

그래서 이렇게 나오는데... 이게 사람이요... 살다보면 1컷 궁금하다... 

 

count = 0
count_nocut = 0
once_cut_list = []
multi_cut_list = []
nocut_list = []
(생략)
        if res_find in sequence:
            site_count = 0
            count_func(res_find,sequence)
            count += 1
            count_nocut += 0
            if site_count == 1:
                once_cut_list.append(enzyme)
            else: 
                multi_cut_list.append(enzyme)
            f.write("{0}: {1} {2},{3} times cut.\n".format(enzyme,res_find,feature,site_count))
        else: 
            count += 0
            count_nocut += 1
            nocut_list.append(enzyme)
    once_cut_list = ', '.join(once_cut_list)
    multi_cut_list = ', '.join(multi_cut_list)
    nocut_list = ', '.join(nocut_list)
(생략)

그래서 0컷 1컷 멀티컷 나눠드렸습니다. 

가 이거. 근데... 에픽하이에도 투컷이 있고... (fly랑 one 좋아함) NEB cutter도 투컷까지는 보여줘요... 

 

count = 0
count_nocut = 0
once_cut_list = []
two_cut_list = []
multi_cut_list = []
nocut_list = []
(생략)
        if res_find in sequence:
            site_count = 0
            count_func(res_find,sequence)
            count += 1
            count_nocut += 0
            if site_count == 1:
                once_cut_list.append(enzyme)
            elif site_count == 2: 
                two_cut_list.append(enzyme)
            else: 
                multi_cut_list.append(enzyme)
            f.write("{0}: {1} {2},{3} times cut.\n".format(enzyme,res_find,feature,site_count))
        else: 
            count += 0
            count_nocut += 1
            nocut_list.append(enzyme)
(생략)

나눠드렸습니다^^ (출력은 1컷 2컷 멀티컷 빵컷 순) 빵컷하니까 빵 자르는 것 같잖아요 

 

def count_func (a,b):
    while a in b:
        global site_count
        loc = b.find(a)
        site_count += 1
        b = b[loc+len(a):]
    return site_count
# Cutter test하다가 여기에도 추가했음...

Finder에도 이 함수는 똑같이 들어간다. 

with open ('Result_{0}-{1}-{2}_{3}-{4}.txt'.format(year,month,day,enzyme,sequence_name),'w',encoding='utf-8') as f: 
    if sequence.find(res_find) != -1:
        site_count = 0
        cut_count = count_func(res_find,sequence)
        sequence = sequence.replace(res_find,res_site)
        print(enzyme,",",cut_feature)
        print(sequence,cut_count)
        f.write("{0} | {1} | {2} | {3} times cut\n".format(enzyme,res_site,cut_feature,cut_count))
        f.write('Sequence name: {0} \n {1}'.format(sequence_name,sequence))
        f.close()
        # DB에 효소가 있고 일치하는 시퀀스가 있을 때
(하략)

대신 Finder는 DB에 효소가 있고, 효소가 해당 시퀀스를 자를 때만 cut수를 세 준다. 

 

그래서 이렇게 나온다. (HaeIII이 해당 시퀀스를 자른다)

'Coding > Python' 카테고리의 다른 글

Finder & Cutter 패치  (0) 2022.08.21
Searcher 만들었음  (0) 2022.08.21
Cutter와 Finder에 패치가 있었습니다.  (0) 2022.08.21
제한효소 커터 2편 나왔음  (0) 2022.08.21
제한효소 커터 코드 패치했음  (0) 2022.08.21
Lv. 35 라이츄

Lv. 35 라이츄

광고 매크로 없는 청정한 블로그를 위해 노력중입니다. 근데 나만 노력하는 것 같음… ㅡㅡ

Cutter와 Finder에 패치가 있었습니다.

Coding/Python 2022. 8. 21. 22:48

Finder

with open ('Result_{0}-{1}-{2}_{3}-{4}.txt'.format(year,month,day,enzyme,search_sequence_name),'w',encoding='utf-8') as f:
    if search_sequence.find(res_find) != -1:
        search_sequence = search_sequence.replace(res_find,res_site)
        print(enzyme,",",cut_feature)
        print(search_sequence)
        f.write("{0} | {1} | {2} \n".format(enzyme,res_site,cut_feature))
        f.write('Sequence name: {0} \n'.format(search_sequence_name))
        f.write(search_sequence)
        f.close()
        # DB에 효소가 있고 일치하는 시퀀스가 있을 때
    elif enzyme_table['Enzyme'].isin([enzyme]).any() == True and search_sequence.find(res_find) == -1:
        print("No restriction site in this sequence. ")
        f.write("{0} | {1} | {2} \n".format(enzyme,res_site,cut_feature))
        f.write('Sequence name: {0} \n'.format(search_sequence_name))
        f.write("This restricion enzyme never cut this sequence. ")
        f.close()
        # DB에 효소가 있으나 일치하는 시퀀스가 없을 때
    else:
        print("No data in database. ")
        f.write("{0} \n".format(enzyme))
        f.write("This restriction enzyme not entried in database. ")
        f.close()
        # DB에 효소가 없을 때

저장 형식은 동일하고, 저장용 코드가 간소화 되었습니다. 저게 format이 들을 줄은 몰랐지... 

 

Cutter

filter = input("sticky로 자르는 제한효소만 보고 싶으면 sticky, blunt로 자르는 제한효소만 보고 싶으면 blunt를 입력해주세요. ")

Filter 기능이 추가되었습니다. 거창한 건 아니고, sticky end나 blunt end만 보고 싶을 때 쓰시면 됩니다. 

 

if filter == 'sticky':
    enzyme_table = enzyme_table[enzyme_table['cut_feature']== 'sticky']
    enzyme_table.reset_index(inplace=True)
elif filter == 'blunt':
    enzyme_table = enzyme_table[enzyme_table['cut_feature']== 'blunt']
    enzyme_table.reset_index(inplace=True)
else: 
    pass

참고로 filter 입력 여부에 따라 DB에서 해당 조건으로만 테이블을 재구성합니다. (아무것도 안 입력하면 패스)

 

count = 0
with open('Result.txt','w',encoding='utf-8') as f:
    f.write("Restriction enzyme which cuts this sequence: ")
    for i in range(len(enzyme_table)):
        enzyme = enzyme_table['Enzyme'][i]
        res_find = enzyme_table['sequence'][i]
        res_find = str(res_find)
        if res_find in sequence:
            print(enzyme, res_find, sequence.find(res_find))
            f.write("{0}: {1} \n".format(enzyme,res_find))
            count += 1
        else: 
            count += 0
    print(count)
    f.write("Total: {0} enzymes cut input sequence".format(count))
# 아직 저장기능은 없습니다. 지금 출력도 좀 중구난방이라 정리 좀 해야될듯. 
# find로 나오는 위치의 경우 0부터 시작하기떄문에 하나 더해줬습니다. 아울러 해당 메소드가 '가장 처음에 나오는 글자'만 찾아주는거지 전체 검색이 아니기때문에 여러군데를 자르는지 여부는 모릅니다.

아 출력 파일도 만들어준다구! 형식은 (날짜)-filter입니다. (아무것도 선택하지 않을 경우 filter=None)

참고로 여기에 쓰이는 DB와 쓰이지는 않는 DB 둘 다 구축 끝냈습니다. (쓰이지 않는 DB: 인식 혹은 자르는 시퀀스에 N, R, Y같은 게 들어가서 따로 처리해야 함) 

'Coding > Python' 카테고리의 다른 글

Searcher 만들었음  (0) 2022.08.21
Cutter & Finder 패치노트  (0) 2022.08.21
제한효소 커터 2편 나왔음  (0) 2022.08.21
제한효소 커터 코드 패치했음  (0) 2022.08.21
제한효소 커터 만들었음  (0) 2022.08.21
Lv. 35 라이츄

Lv. 35 라이츄

광고 매크로 없는 청정한 블로그를 위해 노력중입니다. 근데 나만 노력하는 것 같음… ㅡㅡ

제한효소 커터 2편 나왔음

Coding/Python 2022. 8. 21. 22:45

사실 전에 만든 코드 이름은 Finder고, 이놈이 커터임. 


import pandas as pd

이 코드도 판다스가 있어야된다. (DB가 csv)

enzyme_table = pd.read_csv('/home/koreanraichu/restriction.csv')
enzyme_table = enzyme_table.sort_values('Enzyme')
# Finder에도 쓰이는 '그' DB 맞습니다. 현재 수동 구축 중... 
print(enzyme_table)
print(len(enzyme_table))

아직도 갈 길이 멀지만 일단 D까지 추가했음... 아울러 py파일은 print가 빠집니다. 

 

sequence = input("검색할 시퀀스를 입력해주세요: ")

이건 시퀀스 입력받는 코드(아직 이름은 안 받음)

 

for i in range(len(enzyme_table)):
    res_find = enzyme_table['sequence'][i]
    res_find = str(res_find)
    if res_find in sequence:
        print(enzyme_table['Enzyme'][i],res_find,sequence.find(res_find))
    else: 
        print(enzyme_table['Enzyme'][i],"Not found")

문자열화가 for문 안에서 이루어지고, 자르는 효소와 자르지 않는 효소의 출력 방식만 다르다. 현재 저장도 지원 안 해줌. 

'Coding > Python' 카테고리의 다른 글

Cutter & Finder 패치노트  (0) 2022.08.21
Cutter와 Finder에 패치가 있었습니다.  (0) 2022.08.21
제한효소 커터 코드 패치했음  (0) 2022.08.21
제한효소 커터 만들었음  (0) 2022.08.21
오케이 따옴표 떼버렸음  (0) 2022.08.21
Lv. 35 라이츄

Lv. 35 라이츄

광고 매크로 없는 청정한 블로그를 위해 노력중입니다. 근데 나만 노력하는 것 같음… ㅡㅡ

제한효소 커터 코드 패치했음

Coding/Python 2022. 8. 21. 22:44

패치노트

1. 출력 파일명 형식 변경 저기도 format이 먹힐 줄은 몰랐음 
2. 출력 파일의 형식 변경(시퀀스 이름 추가)
3. 깃헙에 해당 코드 py파일도 추가됨

 

패치 결과

원래 날짜만 추가했었는데 생각해보니 날짜가 같으면 헷갈릴 것 같아서 효소랑 시퀀스 이름도 추가함

시퀀스 이름은 출력 파일에도 저장됩니다. (그래서 이제 세줄임) 

'Coding > Python' 카테고리의 다른 글

Cutter와 Finder에 패치가 있었습니다.  (0) 2022.08.21
제한효소 커터 2편 나왔음  (0) 2022.08.21
제한효소 커터 만들었음  (0) 2022.08.21
오케이 따옴표 떼버렸음  (0) 2022.08.21
10진수->2진수 변환 코드  (0) 2022.08.21
Lv. 35 라이츄

Lv. 35 라이츄

광고 매크로 없는 청정한 블로그를 위해 노력중입니다. 근데 나만 노력하는 것 같음… ㅡㅡ

제한효소 커터 만들었음

Coding/Python 2022. 8. 21. 21:49

근데 NEB커터 쓰세여 그거 좋음 


일단 이 코드는 이 시퀀스를 자르는 제한효소들을 찾는 게 아님. 이 효소가 이 시퀀스를 자르는가? 를 보는 코드임다. 이 점 유념해주세요. 그리고 이거 올리면서 Jupyter가 매트랩이랑 비중 같아졌다 

 

코드

Jupyter notebook으로 코딩한거고 나중에 일부 블록은 정리할 예정. 

import pandas as pd

구축한 csv파일을 가져오고 취급하려면 얘가 필요하다. csv파일은 혹시 써보실 분 계시면 말씀주세요. 

참고로 csv파일이 되게 단촐해서 효소 이름, 인식하는 시퀀스, 자르는 시퀀스, 자르는 형태(sticky or blunt)가 들어가 있음. 나중에 여건이 된다면 똑같은 부분을 인식하고 자르는 다른 효소나 처리온도에 대한 정보도 추가할 예정. (물론 출력 파일에도 같이 나오게 해야 하는 게 함정)

 

enzyme_table = pd.read_csv('/home/koreanraichu/restriction.csv') # 일단 자체적으로 구축했음... 저거 종류 개많습니다 ㅠㅠ 
enzyme_table = enzyme_table.sort_values('Enzyme')
# csv파일의 구성은 크게 효소 이름, 인식하는 시퀀스, 해당 시퀀스를 자르는 형태와 sticky or blunt 여부로 구성되어 있습니다.

위에서 얘기한 csv파일을 불러와서 효소 이름순으로 정렬합니다. 참고로 효소가 인식하는 시퀀스에 N, W, D, S같은 거(ATGC 말고 다른 거) 들어가 있는 효소는 일단 뺐음. 걔들은 따로 처리해야 하는데 그것까지는 아직 무리입니다. 

 

enzyme=input('시퀀스를 찾을 제한효소를 입력해주세요: ')
search_sequence=input('제한효소 site를 찾을 시퀀스를 입력해주세요: ')

이거는 입력받는 코드. 효소 이름은 토씨 하나 안 틀리고 써야 한다. 

 

if enzyme_table['Enzyme'].isin([enzyme]).any() == True:
    res_find = enzyme_table.sequence[(enzyme_table['Enzyme'] == enzyme)]
    res_find = res_find.to_string(index=False)
    res_find = str(res_find)
    print(res_find)
    # 효소 이름이 데이터베이스에 있을 경우 검색할 시퀀스 데이터를 가져온다
    res_site = enzyme_table.restriction_site[(enzyme_table['Enzyme'] == enzyme)]
    res_site = res_site.to_string(index=False)
    res_site = str(res_site)
    print(res_site)
    # 효소 이름이 데이터베이스에 있을 경우 검색하고 대체할 시퀀스 데이터를 가져온다
    cut_feature = enzyme_table.cut_feature[(enzyme_table['Enzyme'] == enzyme)]
    cut_feature = cut_feature.to_string(index=False)
    cut_feature = str(cut_feature)
    print(cut_feature)
    # blunt or sticky(나중에 저장 기능 추가할 때 넣을 예정입니다)
else: 
    print("No data in Database")

판다스 종특인지는 모르겠으나... to_string() 없으니까 인식 못하데... 

순서대로 '인식하는 시퀀스', '자르는 시퀀스', '자르는 형태' 컬럼. 이 코드 자체는 가져온 DB에 효소 이름이 있어야 진행하므로 DB에 효소가 없을 때는 No data가 뜬다. (참고로 수동으로 구축중이라 시간 무지하게 걸림)

 

if enzyme_table['Enzyme'].isin([enzyme]).any() == True:
    print(search_sequence.find(str(res_find)))
else: 
    pass
# 여기는 검색결과가 존재하지 않으면 -1로 나옵니다. (윗 블럭이랑 여기는 넘어가도 되는 부분)

이 코드도 마찬가지로 DB에 효소가 있을 때 시퀀스를 찾고, 결과를 출력한다. (find.()는 문자열이 없으면 -1로 뽑음)

 

with open ('Result.txt','w',encoding='utf-8') as f: 
    if search_sequence.find(res_find) != -1:
        search_sequence = search_sequence.replace(res_find,res_site)
        print(enzyme,",",cut_feature)
        print(search_sequence)
        f.write(enzyme)
        f.write(", ")
        f.write(res_site)
        f.write(", ")
        f.write(cut_feature)
        f.write("\n")
        f.write(search_sequence)
        f.close()
        # DB에 효소가 있고 일치하는 시퀀스가 있을 때
    elif enzyme_table['Enzyme'].isin([enzyme]).any() == True and search_sequence.find(res_find) == -1:  
        print("No restriction site in this sequence. ")
        f.write(enzyme)
        f.write(", ")
        f.write(res_site)
        f.write(", ")
        f.write(cut_feature)
        f.write("\n")
        f.write("This restricion enzyme never cut this sequence. ")
        f.close()
        # DB에 효소가 있으나 일치하는 시퀀스가 없을 때
    else:
        print("No data in database. ")
        f.write(enzyme)
        f.write("\n")
        f.write("This restriction enzyme not entried in database. ")
        f.close()
        # DB에 효소가 없을 때

출력과 저장에 대한 코드. 크게 DB에 효소가 있나/없나로 갈리고 효소가 있을 때 인식 시퀀스가 있나/없나로 갈린다. 

그래서 각각 

DB에 효소가 있고, 해당 제한효소가 시퀀스를 자를 경우. HaeIII의 시퀀스는 [GG/CC]이다.
 

DB에 효소가 있으나 해당 제한효소가 시퀀스를 자르지 않을 경우
DB에 효소가 없을 경우

이런 식으로 출력된다. 


앞으로 추가할 기능

1. csv 파일 수정에 따른 출력 형식(현재 효소 이름, 자르는 시퀀스, sticky ot blunt 여부만 있는데 처리 온도도 및 같은 시퀀스를 인식하는 다른 효소의 정보도 추가할 예정)

2. 출력 파일명도 형식을 줄 수 있으면 날짜 이런거 들어가면 좋을 것 같음. (아니면 사용자가 입력할 수 있게 하거나) 일단 오늘 날짜 가져오는 게 먼저긴 한데 아니면 하이브리드로 입력 받아서 오늘 날짜랑 같이 묶는 뭐 이런거? 

멀티랑 N, W, K 처리는... 아 그건 제 능력 밖이니까 걍 NEB 커터 쓰세여... 그거 좋음... 

'Coding > Python' 카테고리의 다른 글

제한효소 커터 2편 나왔음  (0) 2022.08.21
제한효소 커터 코드 패치했음  (0) 2022.08.21
오케이 따옴표 떼버렸음  (0) 2022.08.21
10진수->2진수 변환 코드  (0) 2022.08.21
번외편-코딩테스트 풀이 (3)  (0) 2022.08.21
Lv. 35 라이츄

Lv. 35 라이츄

광고 매크로 없는 청정한 블로그를 위해 노력중입니다. 근데 나만 노력하는 것 같음… ㅡㅡ

오케이 따옴표 떼버렸음

Coding/Python 2022. 8. 21. 21:44

윤동주-별 헤는 밤
데네데데네! (데덴네)
뭐요


text = []
while True: 
    input_text = input("wordcloud로 만들 텍스트를 입력해주세요. ")
    text.append(input_text) 
    if input_text == "":
        break
text = ' '.join(text)
text=okt.nouns(text)
text = ' '.join(text)

크게는 저 부분을 수정했고, 전체적으로 wordcloud 만들기 위해 입력받는 부분도 간소화했음. (While True 주고 입력 없으면 break 하도록) 

참고로 Wordcloud는 안에 들어가는 글자가 많을 수록 멋지게 나옵니다. 이 점 유념하시길. 

'Coding > Python' 카테고리의 다른 글

제한효소 커터 코드 패치했음  (0) 2022.08.21
제한효소 커터 만들었음  (0) 2022.08.21
10진수->2진수 변환 코드  (0) 2022.08.21
번외편-코딩테스트 풀이 (3)  (0) 2022.08.21
번외편-코딩테스트 풀이 (2)  (0) 2022.08.21
Lv. 35 라이츄

Lv. 35 라이츄

광고 매크로 없는 청정한 블로그를 위해 노력중입니다. 근데 나만 노력하는 것 같음… ㅡㅡ

10진수->2진수 변환 코드

Coding/Python 2022. 8. 21. 02:24

일반적으로 우리가 쓰는 숫자는 10진수가 맞는데, 컴퓨터는 손가락이 두 개라 이진법을 쓴다. 예, 그겁니다. 일반적으로 10진법을 2진법으로 변환할때는 2로 나누는데, 13을 예시로 들자면 

1. 13/2=6...1
2. 6/2=3...0
3. 3/2=1...1

이렇게 구한 다음 3번 결과의 몫 1부터 시작해 3번 결과의 나머지-2번 결과의 나머지-1번 결과의 나머지 순으로 올라가서 1101이 된다. 1의 보수는 여기서 0을 1로, 1을 0으로 바꾼 0010. 2의 보수는 1의 보수에 1을 더하면 된다. (0011)

참고로 이진수로 변환된 숫자는 8, 16진수와 상호변환이 가능한데 

1. 110010010을 8진수로 바꾸려면 110 010 010으로 세자리씩 끊어서 10진법으로 바꾼다. (622)
2. 110010010을 16진수로 바꾸려면 1 1001 0010으로 네자리씩 끊어서 10진법으로 바꾼다. (192)
3. FF(16)를 8진수로 바꾸려면 2진수로 바꾼 다음 세자리씩 끊어서 10진법으로 바꾼다. (11 111 111->377)
4. 77(8)를 16진수로 바꾸려면 2진수로 바꾼 다음 네자리씩 끊어서 10진법으로 바꾼다. (11 1111->3F)


a = int(input())
bin_list = []
while a >= 1:
    bin_list.append(a%2)
    a = int(a/2)
bin = bin_list[::-1]
bin = ''.join(map(str,bin))
print(bin)
# 입력한 숫자를 이진수로 바꿔준다. (물론 수동 방식이다)

수동변환

 

for i in range(len(bin_list)):
    if bin_list[i] == 1:
        bin_list[i] = 0
    else:
        bin_list[i] = 1
bin = bin_list[::-1]
bin = ''.join(map(str,bin))
print(bin)
# 1의 보수(2의 보수는 이 방식으로 할 경우 처리가 되게 애매해지는 문제가 있다)

1의 보수

 

b=int(comp_1,2)
b=b+1
print(b)
# 그래서 2의 보수는 일단 10진수로 바꾼 다음, 1을 더하고 다시 바꿀 예정. 
comp2_list=[]
while b >= 1:
    comp2_list.append(b%2)
    b = int(b/2)
comp_2 = comp2_list[::-1]
comp_2 = ''.join(map(str,comp_2))
print(comp_2)
# 아, 0 빠진건 알아서 붙이세요.

2의 보수

 

a = int(input())
hex_list = []
while a >= 1:
    if a % 16 == 10: # 16진수에서 10~15까지는 각각 A~F로 표기한다. 즉, 여기에 대한 처리를 따로 진행해야 한다. 
        hex_list.append("A")
    elif a % 16 == 11:
        hex_list.append("B")
    elif a % 16 == 12:
        hex_list.append("C")
    elif a % 16 == 13:
        hex_list.append("D")
    elif a % 16 == 14: 
        hex_list.append("E")
    elif a % 16 == 15:
        hex_list.append("F")
    else: 
        hex_list.append(a % 16)
    a = int(a / 16)
hex = hex_list[::-1]
hex=''.join(map(str,hex))
print(hex)

자매품(16진수)

16진수의 경우 10~15까지를 A~F로 표기하기때문에 그걸 변환해줘야 한다. 

'Coding > Python' 카테고리의 다른 글

제한효소 커터 만들었음  (0) 2022.08.21
오케이 따옴표 떼버렸음  (0) 2022.08.21
번외편-코딩테스트 풀이 (3)  (0) 2022.08.21
번외편-코딩테스트 풀이 (2)  (0) 2022.08.21
Biopython-dbSNP와 Clinvar  (0) 2022.08.21
Lv. 35 라이츄

Lv. 35 라이츄

광고 매크로 없는 청정한 블로그를 위해 노력중입니다. 근데 나만 노력하는 것 같음… ㅡㅡ

방명록