제미나이의 도움을 받아... 일부 블록을 업데이트했음. py파일에 업데이트가 반영될지는 모르겠지만.
공통 업데이트
여러분 Jupyter에서 마크다운 쓸 수 있는거 아셨어요? 주피터에서 코드, 마크다운, raw text(VScode에서는 안됨) 다 가능합니다.

그래서 이런식으로 설명이 필요한 블록 위에 마크다운으로 설명 달아놨음.

searcher는 검색 결과 읽는법까지 달아놨음...
Cutter, Finder
searcher에는 해당 업데이트가 적용되지 않았음.
OS 선택지에 맥 추가
본인쟝 아이폰 아이패드까지 쓰고 있지만 유일하게 안써본게 맥북임. (아이맥은 고딩떄 써봤음) 그래서 전에 코딩하면서도 리눅스 아니면 다른 OS로 선택지가 나뉘었었는데, 그 다른 OS에 사실상 맥이 포함이었습니다. 근데 저대로 하면 맥에는 C드라이브가 없어서 안 열리지 않냐고? 나도 맥북 있었으면 선택지 옛저녁에 추가했지.
OS = platform.platform()
if 'Linux' in OS:
default_dir = '/'
elif 'Darwin' in OS or 'macOS' in OS:
default_dir = '/Users'
else:
default_dir = 'C:\\'
# Mac은 뭐라고 뜨는지 몰라서 선택지에 없었는데 제미나이가 알려줬음둥...
그래서 저거 코드 수정 다 끝내는 김에 제미나이한테 물어봤다. 맥은 뭐라고 나오는지.
클래스 코드 간소화
지피티도 없을 시절 클래스 코드 어땠습니까...
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
악 내눈! 뭔 if가 이렇게 많아! 염기들 분기 처리가 이따구라 여러분들 코드 읽다가 아 안돼! 가 절로 나왔습니다...
# 코드 개편이 있었습니다. 원래는 줄줄이 나열했었는데 제미나이의 도움으로...
class RE_treatment():
# A, T, G, C 외의 다른 알파벳들을 전부 와일드카드로 변환
CODE_TO_REGEX= {
"N":".", "B": "[CGT]", "D": "[AGT]", "H": "[ACT]", "K": "[GT]",
"M": "[AC]", "R": "[AG]", "S": "[CG]", "V": "[ACG]",
"W": "[AT]", "Y": "[CT]"
}
def RE_treatment_all(self, before_seq):
# 이제 제한효소 시퀀스에 A, T, G, C 외에 다른 게 있으면 저기서 찾아서 변환하면 됩니다.
# 그리고 그 일을 얘가 할거예요.
def replacer(match):
return self.CODE_TO_REGEX[match.group(0)]
pattern = "[" + "".join(self.CODE_TO_REGEX.keys()) + "]" # 위에 있는 딕셔너리에서 갖다가
return re.sub(pattern, replacer, before_seq) # 변환합니다.
# 여기까지가 클래스입니다
예전에 전사번역 구현할때도 딕셔너리로 해결봤었는데 이번에도 마찬가지로 A, T, G, C가 아닌 알파벳과 거기에 해당하는 정규식 패턴을 키-값으로 묶어서 딕셔너리화했다. 그래서 이제 A, T, G, C가 아닌 다른 알파벳이 들어있는 시퀀스가 들어오면 이 클래스에서 그 알파벳에 해당하는 규식정씨 패턴으로 바꿔준다.
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+1))
return res_loc_list
# 여기가 위치 관련 함수입니다.
def convert (a):
RE = RE_treatment()
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)
return res_find_after
# 함수가 대체 몇 개야...!!!
# 저 or 진짜 무식하게 다 때려박았음... 줄일 방법 제보 받아요...
이건 담주에 빼겠음. 위는 몰라도 밑의 기능을 클래스에서 같이 합니다. 위에껀 블록 합치든가 같이 빼든가 해도 됨.
파일 저장 코드 일부 수정
# 파일명 관현 구역
output_filename = 'Result_{0}-{1}-{2}_{3}'.format(year,month,day,sequence_name)
full_filepath = os.path.join(save_path, output_filename)
# 이쪽은 크게 건드릴 일 없습니다.
경로를 설정했음에도 자꾸 저 코드가 있는 파일이 걸려서 코드 바꿨음.
print("파일이 {0}에 저장되었습니다. ".format(full_filepath))
파일이 저장됐을때의 출력문도 수정함.
예외처리 적용
try:
for i in range(len(enzyme_table)):
treatment = RE_treatment()
enzyme = enzyme_table['Enzyme'][i]
feature = enzyme_table['cut_feature'][i]
res_find_before = str(enzyme_table['sequence'][i])
# 변환 로직 (이전에 개선된 treatment.RE_treatment_all 사용)
res_find_after = treatment.RE_treatment_all(res_find_before)
Findall = re.findall(res_find_after, sequence)
site_count = len(Findall)
res_loc_list = []
if Findall:
# 얘도 저장 이슈때문에 추가한건데 프로그레스 보이고 좋네요 ㅋㅋ
print(f"DEBUG: Processing cutting enzyme {enzyme}")
# cut_func 호출
cut_func(res_find_after,sequence)
# ... (나머지 리스트 추가 및 파일 쓰기 로직) ...
res_loc_list = ', '.join(res_loc_list)
f.write("Enzyme: {0} | Sequence: {1} | Cut feature: {2} | {3} times cut \nWhere(bp): {4} \n".format(enzyme,res_find_before,feature,site_count,res_loc_list))
else:
# ... (no_cut_list 추가 로직) ...
no_cut_list.append(enzyme)
print(f"DEBUG: Enzyme {enzyme} not found.")
# 예외처리하다가 오류가 나면 FATAL ERROR가 보이게 될 거예요.
except Exception as e:
print(f"\nFATAL ERROR during enzyme loop: {e}")
# 오류가 발생했음을 파일에도 기록
f.write(f"\n--- ERROR OCCURRED DURING ANALYSIS LOOP ---\nError: {e}\n--- Partial results saved ---\n")
파일 쓰는 부분에 예외처리가 추가되어서 돌리다가 뻑나거나 하면 어느 시점에서 에러가 났는지 알려준다. 저것도 로직때문에 쓴거같은데...
'Coding > Python' 카테고리의 다른 글
| 파스칼의 삼각형 (0) | 2025.12.06 |
|---|---|
| 스택과 큐를 구현해보자 (0) | 2025.12.03 |
| 판다스 없이 표 만들기 (0) | 2025.09.27 |
| 전사/번역을 Biopython 없이 해보자 (0) | 2025.09.10 |
| Matplotlib으로 정규분포를 그려보자 (0) | 2024.07.16 |