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

제미나이의 도움을 받아... 일부 블록을 업데이트했음. 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