2021년 12월 31일 금요일

PCL86 싱글 엔디드 앰플리파이어 다시 만들기(3) - 부귀환 적용

신년을 위한 프로젝트로 남겨 두려 했다가 쉬는 김에 끝장을 보기로 하였다. 출력 트랜스 2차 권선에서 초단 캐소드로 저항을 연결하는 가장 전통적인 방식을 취하였다. 캐패시터는 달지 않았다. Pinterest에서 찾은 Stephan Gloeden의 회로도에서는 33K 저항을 사용하고 있었다. 부품통에는 이에 딱 맞는 수치의 저항이 없어서 저항 두 개를 직렬로 연결하여 비슷한 값을 만들었다. 캐소드 단자까지는 실드선을 사용하여 연결하였다.

상당히 어지러운 배선이지만 소리만 잘 난다면...
소리는 더 차분해지고 부귀환 적용 전과 비교하면 당연히 출력이 작아졌다. 스피커와의 매칭 문제는 해결이 되었을까? 글쎄... 나아진 것 같기도 하고, 아닌 것 같기도 하고.

선재 피복 색깔의 선택에는 일관성이 없고, 지나치게 길다. 배선을 자주 정리하는 아마추어의 입장에서는 작업을 할 때마다 자꾸 선이 짧아지니 길게 배선하는 것도 그렇게 나쁜 일은 아니다. 잡음이 타고 들어오지만 않는다면 말이다.

작동 전압을 측정해 보았다. 그라운드를 기준으로 플레이트는 262~263V, 스크린 그리드는 243~246V, 5극관쪽의 캐소드에는 6.2~6.5V의 전압이 걸림을 확인하였다.

2014년 내 생애 첫 진공관 앰프로 주문 제작을 하여 그 특성도 잘 알지 못한 상태로 그저 '이게 진정 좋은 소리로구나'하는 편견 또는 착각에 빠져 살다가 조금씩 불만스런 점을 발견하게 되고, 급기야 거의 전부를 걷어내고 다시 만들면서 뒤늦은 깨달음을 얻게 되었다. 다른 앰프의 제작을 통해서는 알 수 없었던 많은 경험을 바로 이 PCL86 싱글 앰프를 통해 하게 된 것이다. 개조 전에는 소리가 점점 마음에 들지 않아서 더 이상 듣지 않으려는 극단적인 생각도 했었다.

아직 이해할 수 없는 원 제작자의 설계 포인트는 다음의 두 가지이다. 이는 전부 이번의 작업을 통해 상식적인 수준으로 개선하였다.
  • 싱글 엔디드 앰프이면서 왜 출력 트랜스의 코어 사이에 갭을 넣지 않았을까?
  • 왜 상판 자체를 그라운드로 이용했을까? 상판을 그라운드에 연결했다는 뜻이 아니다. 상판을 그라운드 "선"처럼 사용했다는 것이다. 
전원 트랜스와 출력 트랜스를 다음과 같이 배치한 것은 정말 탁월한 선택이었다. 이 점은 원 제작자로부터 배울만한 포인트였다. 단, 나의 경우에는 두 트랜스 모두 코어 측면을 가리는 밴드가 없었다. 따라서 밴드가 있거나 또는 트랜스가 케이스에 들어 있는 경우라면 어떻게 배치하든 전원 트랜스로부터 유도되는 잡음이 없을 수도 있을 것이다.
전원 트랜스로부터 험이 유도되지 않는다. 적어도 내 귀로는 들리지 않았다.

최악의 험이 출력 트랜스로 유도된다.

바로 위의 배치보다는 낫지만 여전히 잡음이 유도된다.
2022년에는 무엇을 만들 것인가? 현재 소유한 것에 대한 불만이 증폭되거나 새로운 것에 대한 호기심이 발동해야만 일을 저지르게 되는 것은 아니다. 보관해 놓은 여분의 부품들에게 늘 귀를 기울이고 있다 보면 날 좀 어떻게 해 달라고 아우성을 치는 소리가 들릴 것이다. 그러면 또 뭔가 일을 꾸미게 될 것이다. 여분의 PCB, 출력 트랜스, 진공관... 그럴 여지가 얼마든지 있다.

네이버의 앰프 자작 관련 카페에서 글을 읽다가(회원은 아님) 이런 글을 발견했다. 진공관 앰프는 사용하는 전력에 비하여 효율이 매우 떨어지므로 매우 환경 비친화적이다. 1인 1앰프로 제한을 하는 것이 합리적일 수 있다는 것이다. 백열등의 생산이 금지된 것과 마찬가지로, 민수 용도의 전자제품에서 진공관을 쓰지 못하게 하는 일이 생기지는 않을까? 흠, 그렇다면 화석연료를 사용하여 나오는 에너지에 의존하는 모든 취미 활동을 막아야 할지도 모른다. 그러나 누군가의 취미를 지원하는 시장은 누군가에게는 생계 수단이 되기도 한다. 클라우드에 올린 10GB의 사진도 탄소 발자국을 남기는 것은 당연하다. 참 어려운 문제이다.

PCL86 싱글 엔디드 앰플리파이어 다시 만들기(2) - 회로의 큰 변경 없이 재조립

6LQ8 SE 앰프의 PCB를 사용하여 회로를 완전히 다시 꾸미려고 하다가 방향을 크게 선회하여 기존의 것을 최대한으로 활용하여 빠르게 마무리하였다. 회로도는 다음과 같다. 빨간색 점선 안의 것이 원 제작자가 만들어 놓은 것이다.

전원부의 평활용 캐패시터까지는 공통이고 그 후는 각 채널에 대해서 따로 구성되어 있다.
F. R.의 2008년도 원본 회로도는 다음과 같은 점이 다르다.

  • 5극관에 연결된 캐소드 저항/캐패시터는 180R/100uF 63V
  • 스크린 그리드는 HT 250V에서 1K 저항을 통하여 전원 공급
출력 트랜스의 배치에 따라서 전원 트랜스로부터 유입되는 험이 크게 달라진다는 것을 알게 되었다. 내가 아는 상식으로는 그저 코어 옆면을 일직선으로 되게 하지 말고 직각으로 두어야 누설 자속에 의한 유도 험이 적다는 것 정도였다. 그러나 실험을 해 보니 두 트랜스를 같이 세운 상태에서는 직각으로 두어도 꽤 높은 수준의 험이 발생하였다. 그래서 원 제작자가 만들었던 상태대로 출력 트랜스를 눕혔더니 유도 험이 최소 수준으로 줄어들었다. 
출력 트랜스의 배치 테스트.


아마도 트랜스 옆면에서 코어를 둘러싸는 밴드가 있었다면, 혹은 자속을 차단할 수 있는 케이스를 씌운다면 상황은 훨씬 나았을 것이다. 트랜스 배치는 결국 원래의 모습으로 돌아왔지만, 코어를 전부 빼서 갭을 준 뒤 재조립한 것이 가장 중요한 개선이 될 수도 있다. 사실 재조립은 썩 마음에 들게 되지는 않았다. 코어의 측면에 페인트가 발라져 있었던 것을 생각하지 않고 뒤죽박죽으로 꽂았더니 적층 후 I 코어 전체가 E쪽보다 두꺼워지고 말았다. 아래 사진을 보면 출력 트랜스의 상부 커버가 수평이 아니라 안쪽으로 약간 기울어져 있음을 느낄 수 있을 것이다.


이 PCL86 싱글 엔디드 앰프를 거실의 스피커(B&W DM10)에 물린 경우 약간의 답답한 소리가 나는 현상은 트랜스 코어의 재조립으로 현저히 개선되지는 않았다. 침실의 스피커에 비하여 감도가 2 dB 낮은 스피커라서 그런 것이 아닐까 의심하고 있다. 피드백을 적용하면 출력은 줄어들겠지만 댐핑팩터가 증가하여 전 주파수 대역에 대하여 비교적 평탄한 재생 특성을 보이게 되지 않을까? 부족한 지식으로 이렇게 추론하는 것이 올바른지는 알 수 없지만 말이다.

부귀환 적용 실험은 신년을 위한 프로젝트로 남겨 두도록 한다.



2021년 12월 26일 일요일

PCL86 싱글 엔디드 앰플리파이어 다시 만들기(1)

매우 저렴한 가격에 이 앰프를 만들어 준 사람에게 미안한 마음을 품고 회로를 싹 걷어낸 뒤 다시 만든 것이 지난 8월이었다(링크). 소리가 난다고 하여 마냥 기뻐할 일은 아니었다. 왜냐하면 특정 스피커에 대해서는 매우 만족스럽지 못한 소리가 나지 않았기 때문이었다. 그냥 참고 듣기에는 자존심이 허락하지 않아서 다시 만들기로 마음을 먹었다. 한 섀시에 대해서 벌써 세 번째의 알맹이가 들어차게 되는 셈이다.

이번에는 제이앨범 한병혁 님이 제작한 6LQ8 SE 앰프용 PCB를 활용해 보기로 하였다. 회로 구성은 거의 유사하여 부품만 바꾸어서 납땜을 하면 될 정도이다. 다만 핀의 배열이 다르므로 섀시 고정용 소켓을 사용한 뒤 전선을 통하여 PCB에 연결을 하기로 마음을 먹었다. 출력 트랜스를 분해하여 코어를 재배열한 뒤 제대로 갭을 주어서 조립한 것도 이전과는 크게 달라진 점이다(링크).

인터넷에서 ECL/PCL86 싱글 엔디드 앰프의 회로도를 찾으면 꽤 많은 결과를 얻을 수 있다. 이번에 내가 택한 것은 바로 다음의 것이다.

 출처: LivingInThePast Audio Web

며칠 전에 소개한 바 있었던 다음의 회로도에서는 드라이브관과 출력관의 플레이트를 4.7M 저항으로 연결하는 매우 간단한 부귀환(negative feedback) 방법을 사용하여 눈길을 끈다. 지금껏 내가 공부했던 회로에서는 출력 트랜스 2차와 드라이브관 캐소드를 연결하는 global negative feedback만을 보아왔기 때문이다. 
출처: http://www.mcamafia.de/tubes/keksdose/cookiebox.htm
일반적인 부귀환 방법에서는 출력 트랜스의 2차 리드 중 정확한 것을 골라야 하고, 위상 차이로 인하여 캐패시터를 저항과 병렬로 연결하기도 한다. 플레이트-플레이트를 연결하는 부귀환 방법이 정말 간단하고 효율적이라면, 수많은 싱글 앰프의 회로가 이를 채용했을 것이다.

출력관용 캐소드 저항은 기존의 것을 그대로 활용하면 되므로, 비좁은 PCB에 와트수가 큰 저항을 우겨넣으려고 애쓸 필요는 없다. 공개된 ECL/PCL86 SE 앰프에서는 캐소드 저항을 제외하면 0.5W급을 쓰라고 하지만 1/4W급이라고 해서 별 일이 있겠는가? 0.5W급 저항을 PCB에 꽂기에 구멍 간격이 너무 좁으면 세워서 납땜을 해도 된다.

만약 이렇게 다시 만들어도 소리가 신통치 않으면? 다 해체하고 잊어버리련다. 이것 말고도 탐구할 복합관은 많다. 한번도 실망을 주지 않았던 6LQ8이 그렇고, 현대관이 생산되는 6BM8도 있다.


2021년 12월 25일 토요일

[ 독서 기록] '언어의 높이 뛰기'외 3권

이번에는 대출 기간을 한 차례 연장하였지만 깊이 생각을 하면서 독서 기록을 남길 시간이 부족하였다. 책 표지와 제목 정도를 기록하는 것으로 만족하련다.

  • 신지영 교수의 언어 감수성 향상 프로젝트 <언어의 높이뛰기>
  • 디지털 트랜스포메이션: 뉴 호라이즌. 이상인 지음
  • 지리 기술 제도: 제프리 삭스(Jeoffry D. Sachs) 지음/이종인 옮김. 원제는 <The Ages of Globalization>
  • 하버드가 밝혀낸 외계의 첫 번째 신호 <오우아무아>: 아비로브(Avi Loeb) 지음/강세중 옮김

책을 읽을 때에는 '이런 것을 기억해 놓고 나중에 꼭 독후감에 써야지'라고 다짐했던 포인트가 꽤 많이 있었다. 인상이 깊었던 쪽을 사진으로 찍어 놓기도 하고, 심지어 저자에게 이메일을 보내겠다고 저장 정보를 기록해 놓기까지 하였었다. 그런데 반납 기일이 다 될 때까지 블로그 작성을 미루고 미루다가 이제와서 책 제목이라도 기록에 남기겠다는 일념으로 노트북 컴퓨터를 여니 그 다짐이 어디로 갔는지 모르겠다.

신지영 교수의 책은 전에도 한번 읽은 적이 있다. 우리가 무심코 사용하는 언어의 잘못된 쓰임새라든가, 비민주적이고 차별적인 요소 등을 가려내고 올바르게 쓰려는 운동을 오래 지속해 온 학자이다. 책의 앞부분에는 초임 교수 시절, 교수는 당연히 나이가 어느 정도 든 남자일 것이라는 사고의 틀 안에 갇힌 학교에서 겪었던 언어 속의 여러 불합리한 모습을 고발하는 것으로 시작하였다. 그랬다면 책의 부제를 '신지영 교수의...'라고 시작하도록 저자가 놔 두지는 않았을 것 같은데... 

대화 중에 상대방을 부르는 적절한 호칭이 우리 언어에는 없다. 함부로 부를 수가 없어서 이를 극도로 꺼리고, 상대를 부르는데 쓸 낱말이 아예 존재하지 않는 것이 한국어를 포함한 극소수 언어의 현실이다. 우리말에서는 호칭에서 상하관계를 분명히 드러내어 불러야 하기 때문에 영어의 'you'와 같이 평등하게 2인칭을 부르는 말이 아예 없다. 그렇기 때문에 처음 만나는 사이에서는 나이가 어떻게 되는지, 어디에 근무하며 직함은 무엇인지를 꼬치꼬치 캐물어야 하고 그것이 실례가 되지 않는다. 유튜브를 찾아보면 신지영 교수가 '대통령'이라는 낱말도 바꾸어야 한다고 주장하는 강연을 볼 수 있다. 나도 정말 그렇게 생각한다. '대권'이라는 말이 나는 너무나 듣기가 싫다. 국민으로부터 위임받아 권한을 행사할 뿐인데, '대권' 나라에서 가장 큰 권력이라는 느낌을 주기 때문이다.

쓰고 싶은 말은 너무나 많은데 눈이 침침하고 화면은 너무나 작다. 가끔은 설명을 위해 한자어도 섞어서 쓰고 싶은데 마우스가 없는 노트북 컴퓨터에서 작업을 하기가 힘들다. 노화에 따른 신체적인 변화를 겪는다고 보고 싶지는 않다. 길게 누워서 스마트폰이나 문지르며 생각은 생략한 채로 '건너뛰기 정보 입수'에만 몰두한 부작용이 아닌가 싶다.

아비 로브의 책은 과학을 하는 자세에 대한 철학적 질문을 던지는 것 같았다. 이번에 빌린 책 중에서는 가장 강렬한 메시지를 전하는 것으로 느꼈다.

나는 그러한 모든 의사결정 기관이 자원의 상당 부분, 말하자면 20% 정도를 고위험 프로젝트에 의무적으로 할애해야 한다는 생각을 자주 했다. 금융 포트폴리오와 마찬가지로 인류는 과학에 분산 투자할 필요가 있다.

하지만 많은 연구원이 처한 상황은 이러한 이상과는 거리가 멀다. 특히 젊은 시절의 열정을 잃고 경력 사다리를 통해 종신 고용직까지 오른 뒤에는 더하다. 연구원들은 그 직업의 안정성을 활용하는 대신 학생들과 박사 후 연구원들로 구성된 메아리 방을 만들어 과학적 영향력과 명성을 증폭하는 데 쓴다. 영예는 학계의 얼굴을 꾸며 주는 화장일 뿐인데도 집착하는 경우가 너무나 많다.

나는 종신 고용직에서 일을 하는 것도 아니고, 교수도 아니다. 학회 같은 곳에서 만난 사람이  '김 아무개 교수님, 박 아무개 교수님'이라고 옆에 있는 사람에게 인사를 나누다가 내 앞에 와서는 약간의 뜸을 들이면서 '정 박사님'이라고 고쳐 부르는 것이 불편할 뿐이다. 이런 일과 관련된 개인적인 에피소드가 꽤 있다. 그러나 자존심 문제도 있고 하니 상세하게 적지는 않겠다. 호칭을 통해서 사회적 지위를 재확인하는 일이 없었으면 하는 일이다. 남녀노소 지위고하를 막론하고 서로를 부를 수 있는 말을 만들어야 하지 않겠는가?

그렇다고 하여 여기 인용한 글귀를 공감하지 못한다거나, 그럴 자격이 없다는 뜻은 아니다. 저자가 강조하는 것은 권위에 대한 맹종이 아니라 열린 사고이다. 과학사에서 일어난 혁명적인 사건은 모두 그렇게 생겨난 것이다.

2021년 12월 21일 화요일

영원한 숙제, PCL86 싱글 엔디드 앰프

부순 앰프 다시 만들기 - PCL86 싱글 앰프(2021년 8월 8일 포스팅)

이만하면 썩 잘 만들었어! 하고 자만심을 갖고 있었다. 최소한 침실에서 사용하는 스피커(인켈 SH-950)에 연결했을 때는 그랬었다. 자작 앰프가 쌓이면서 공간이 협소하여 거실로 갖고 나와서 B&W DM10에 연결해 보니 AM 라디오 소리가 난다. 귀를 의심하지 않을 수가 없었다. 내가 참조했던 앰프의 회로도는 다음 그림과 같다. 폴란드 쪽의 커뮤티니에서 입수한 회로도인데 원본의 위치를 지금은 못 찾겠다.

원본이 있었던 URL을 찾기 어렵다. 여기에는 이것과도 매우 흡사한 회로도가 있다. 2008년 이 회로를 그린 F. R.은 누구일까? 

출력 트랜스의 코어에 갭이 없어서 그런가? 6LQ8 싱글 앰프에 사용하던 초소형 출력 트랜스를 연결해 보았다.


이 트랜스는 6LQ8 싱글 앰프에 물린 상태에서는 스피커를 가리지 않고 잘 울린다. 그러나 PCL86 싱글 앰프 + DM10의 조합에서는 트랜스를 바꾸기 전과 마찬가지로 AM 라디오 소리가 난다.

다시 좌절감에 휩싸인다. 적출한 트랜스는 코어를 전부 분리하여 E와 I를 한데 모은 뒤 갭을 주어 재조립하였다. 언제든 쓰일 날이 올 테니까... 재활용 커버라서 앞뒤의 색깔이 다르다.



분리한 코어를 정리하여 갭을 준 뒤 끼우는 방법은 다음 동영상 "Winding a ultra linear single ended output transformer 6K, 10K, 12K to 4, 8 Ohm"을 참조하면 쉽게 이해할 수 있다. 맨 마지막의 E 코어를 나저미와 반대 방향으로 끼우는 것이 핵심이다. 트랜스에서 코어를 빼낸 뒤 재조립하면 아무래도 이전과 똑같은 두께가 되질 않는다. 결국 I자 코어 한 장은 꽂지를 못했다. 억지로 끼워 넣으면 양 끝의 E 코어가 벌어지기 때문이다. 함침 작업이 되어 있지 않아서 코어를 분해하는 것은 무척 쉬웠으나 곳곳에 녹이 슨 흔적이 있었다. 최종 재조립 후 내가 한 일은 겉에다 목공용 바니쉬를 겹겹이 바르는 정도였다. 트랜스포머 제조 등에 쓰이는 절연용 바니쉬가 있는 것으로 알지만 일반인이 1-2리터 정도를 사는 것은 지극히 어렵다.





그렇다면 회로에 근본적인 문제가 있다는 뜻일까? 3극+5극 복합관을 사용한 싱글 엔디드 앰프의 회로라는 것이 다 거기서 거기이고, PCL86은 음질적인 면에서 결코 가벼이 볼 관은 아니다. 그런데 왜 이렇게 특정 스피커에 대하여 마음에 들지 않는 소리가 나는 것인지! 스피커의 sensitivity는 87과 db/W 89 db/W의 차이가 있어서 DM10을 울리기 조금 더 어려운 것은 맞다. 그렇다고 하여 고음부가 이렇게 잘려 나갈 수가 있을까? 회로도에는 4와트(2W + 2W인가?)라고 적혀 있는데 말이다.

스피커 시스템을 탓하기에 앞서서 앰프쪽을 개선할 여지가 더욱 많다고 생각한다. 구글 검색을 통하여 ECL/PCL86 싱글 앰프의 매우 상세한 제작기를 발견하여 이를 공부 재료로 삼으려 한다.


피드백 방법이 매우 독특하고, LM317을 이용하여 캐소드에 일정한 전류를 흐르게 만든 것을 참조할 필요가 있다. 성능이 서로 다른 중고 진공관을 좌우 채널에 사용할 때 출력을 맞추는데 매우 유용한 방식으로 여겨진다. 이 숙제를 잘 해결한다면, 앞으로 6BM8 등 복합관을 이용한 싱글 앰프를 만드는 데에도 큰 도움이 될 것이다.

2021년 12월 26일 업데이트

맨 위에 보인 회로도를 인용했던 가장 오래된(?) 글을 찾았다.

출처 링크: diyAudio ECL86/PCL86 Schematic 질문에 대한 13번째 댓글(tubeman13). 이미지에 대한 링크.

Pinterst에서는 종이에 직접 그린 회로도에 대한 이미지도 있다(링크). 맨 위에 보인 회로도와 거의 같다.

2021년 12월 19일 일요일

로봇이 시중을 드는 세상, 그리고 영화 [그녀(Her)]

국립중앙박물관에서 관람객을 위한 안내용 로봇을 처음 본 것이 올해였다. 휴머노이드가 아니라 카메라와 화면 및 스피커가 달린 몸체가 바퀴로 움직이는 그런 형태의 것이었다. 얼마 전 유성호텔 커피숍에서는 음료수를 나르는 로봇을 접하기도 했었다. 작은 바퀴로 움직이다 보니 고르지 않은 바닥을 지나면서 로봇의 윗부분으로 갈 수록 진동이 더욱 증폭되어 쟁반에 담긴 커피가 흐르거나 쓰러지지는 않을지 약간은 위태로운 모습을 보였었다.

일요일을 맞아 아내와 함께 유성에 있는 음식점에 가게 되었다. 코로나 백신 접종 여부를 확인하고 자리에 앉으니 테이블마다 주문 및 결제 시스템이 갖추어져 있었다. 카페나 패스트푸드점에서 흔히 보던 키오스크가 소형화되어 식당의 각 테이블에 설치되어 음식이 나오기도 전에 돈을 먼저 내게 만든다. 사실 나는 돈을 미리 내고 손님이 음식을 직접 가져다 먹고 치우는 시스템을 그렇게 좋아하지는 않는다. 원래 그러한 서비스 비용이 가격에 다 포함되어 있었던 것이 아닌가?

식당을 둘러보니 처음 보는 물건이 있다. 바로 음식을 나르는 로봇이었다. 호텔에서 보았던 로봇보다는 장애물 회피 움직임 등 모든 면에서 나은 움직임을 보였다. 음식뿐만 아니라 종업원을 불러서 가져다 달라고 흔히 요청하는 앞접시와 일회용 앞치마 등도 담겨 있었다. 음식을 나르는 로봇이 있다고 하여 종업원이 없는 것은 아니었다.

우리가 주문한 음식과 같은 것을 실은 로봇이 테이블 옆에 와서 멈추었지만, 화면에 표시된 테이블 번호가 우리가 앉은 자리의 것과 일치하는지를 확인하기 전까지는 음식을 내리지 못했다. 오! 벌써 이런 세상이 되었나? 이러한 로봇으로 인해서 식당은 서비스 속도와 질이 높아지고 인건비도 줄이게 되었을까?

신기함을 느끼기에 앞서서 각 테이블마다 주문 및 결제 시스템을 설치하고 서빙용 로봇을 갖추는데 얼마나 많은 돈이 들어갔을지 잠시 생각해 보았다. 로봇으로부터 음식을 내려놓은 뒤 동작이 완료되었다는 사실을 스크린에 터치해 주어야 했다. 중량 센서가 있어서 그릇을 내려놓았음을 로봇이 알지는 못하는 것 같았다. 그리고 음식을 내리기 위하여 자리에서 일어나는 것도 약간은 불편하였다. 만약 거동이 불편하거나 어린이가 와서 음식을 내리다가 그릇을 엎기라도 한다면? 그러다가 뜨거운 음식이나 깨진 그릇에 다치기라도 한다면 그 책임 소재는? 

바로 어제 넷플릭스에서 보았던 호아킨 피닉스와 스칼렛 요한슨(목소리로만 출연) 주연의 2013년도 영화 <그녀(Her)>가 생각났다. 혹시 이 영화를 볼 생각이 있는 사람이라면 이 글이 스포일러가 될 수도 있으니 글 아랫쪽으로 건너뛰시기를 바란다.

고도로 기술이 발달한 사회에서 사람들은 음성으로 소통할 수 있는 OS에게 마음을 터 놓고, 심지어는 사랑의 감정을 느끼게 된다. 공교롭게도 남자 주인공은 손으로 쓴 것만 같은 편지를 대신 써 주는 작가이다. 아날로그적 감성을 듬뿍 담아 사람들 사이의 빈 틈을 매우는 일을 직업으로 가진 사람이 정작 자신의 결혼 생활에서는 실패했고, 소개 받은 사람과의 첫 만남에서도 좀처럼 솔직한 마음을 담아 내지 못한다. 오히려 그는 OS를 점점 친구나 연인처럼 여기게 되고, 길거리를 다니는 수많은 사람들(실제 촬영은 현대적인 모습을 담아내기 위해서인지 상하이에서 이루어졌다고 함)은 저마다 이어셋을 꽂고 무엇인가를 중얼댄다. 아래의 동영상은 '사만다'가 가의 인간 연인을 위해 직접 만든 노래 "The Moon Song"이다.

사만다는 몸을 갖춘 인간과의 교감을 위해 나름대로의 노력을 한다. 인간과 OS의 기묘한 사랑에 흥미를 갖는 여성을 끌어들여서 직접 사랑의 행위를 하려는 시도는 이에 몰입하지 못한 테오도르 때문에 실패로 돌아가지만.

그러나 이 관계는 오래 지속되지 못한다. 그 과정은 인간 커플이 서로에게 더 이상 흥미와 새로움을 느끼지 못하면서 관계가 깨어지는 것과 많이 닮았다. 사만다는 이미 작고한 철학자의 저작물을 전부 읽고 그를 되살려내어 즐겁게 대화하면서 이를 오히려 테오도르에게 소개한다. 인간 커플과 테오도르-사만다의 더블 데이트도 이루어진다. 어느 날 일순간 OS가 접속되지 않는 상태가 된다. 패닉에 다다른 테오도르는 단말기를 들고 거리로 뛰어나가 접속이 되는 곳을 찾고자 한다. 이어서 다시 돌아온 사만다의 고백이 이어진다. 테오도르는 사만다가 유일한 친구이자 애인이었지만, 사만다는 더 이상 그런 상태가 아니었다. 더 많은 사람을 알게 되면서 그들과도 친구 이상의 관계를 갖게 되고, 무엇보다도 인간을 책에 비유한다면 그 단어 사이의 공간이 너무나 길다고 토로한다.

약간의 이야기가 더 이어지지만 영화 줄거리는 여기까지만 하자. 왜 <She>가 아니고 <Her>가 제목인지는 영어 대사를 다시 집중하여 듣기 전까지는 알 수가 없다. 어찌하여 인간은 AI에 감정적인 면까지 의존하게 되었나? 기계는 사람이 하기 힘들거나 지루한 작업을 대신 하는 고마운 존재라고 일단은 아주 단순하게 그 의미를 부여해 볼 수 있다. 식당에 등장한 서빙용 로봇이 그러한 목적으로 도입되었다고 일단 생각해 보자. 점주는 같은 시간에 더 많은 손님에게 서비스를 제공할 수 있고, 종업원의 고용을 줄여서 인건비를 현저하게 줄였을 수도 있다. 그러나 종업원이 직접 테이블로 와서 주문을 받고, 음식을 가져다 주는 접점에서 일어나는 많은 일들이 그렇게 무가치한 일일까? 서로 대화와 눈빛을 통해서 요구 조건을 전달하고, 감사 또는 불만을 전하는 그 자연스러운 일이 과연 로봇으로 대체해도 되는 일일까? 어쩌면 음식을 주문받고 나르는 모든 일은 너무나 힘들고 보람이 없는 일이기에, 결국은 로봇이 다 감당해야 하는 일인가?

사람이 사람을 대하는 일을 무가치하고 스트레스가 쌓이는 일로만 생각한다면, 그 사회는 건전하지 못하고 오래 지속되기 힘들다는 것이 나의 생각이다. 세상 어디에나 '빌런(villain)'이 넘치고, 이를 고발하는 글이 인터넷에 넘쳐나면서 인간에 대한 혐오를 증폭한다. 주차장에서, 병원에서, 관공서에서, 아파트 바로 윗집에서, 직장에서, 학부모 모임에서, 식당에서, 카페에서... 사람이 직접 대면을 하여 서로를 이해하려 애쓰고 대화와 협력을 통해 풀어나가야 할 일이 너무나 많은데, 이제는 대면 자체를 하지 않으려는 것이 큰 문제다. 전 세계를 휩쓰는 코로나 '역병'도 사람들을 잠재적인 병원체 전달자로 여기고 가까이 하지 않게 만드는 문화를 만드는 주역이 되었다. 이러한 비대면 시대의 빈 틈에서 소위 AI라는 것이 시장을 확장해 나가고 있다.

로봇이나 컴퓨터가 한 일이 사람이 직접 한 일과 구별하기 어려울 때 인간은 그 성과를 놀라워한다. 튜링 테스트도  인공지능의 그러한 능력을 평가하는데에 주안점을 둔 것이라 볼 수 있다. 그러나 우리는 인간적인 접촉을 더욱 원한다. 내가 카카오톡으로 상담을 한 상대방이 챗봇이라는 것을 알았을 때, 유튜브에서 본 정치인의 연설이 실제는 정교한 컴퓨터 그래픽으로 만들어진 것이라는 것을 알았을 때, 이제는 내가 대접을 잘 못받고 있다는 생각이 더 많이 든다. 햄버거를 하나 먹으려고 패스트푸드점에 가서는 '지금이 어떤 시대인데 사람이 주문을 받아? AI 키오스크를 데려다 오라고!'할 사람은 아무도 없을 것이다. 현재의 키오스크 수준이 아직 불완전하니, 더욱 개선되면 과연 나아질까? 그렇지는 않을 것이다.

흠... 어쩌면 세상이 내 생각과 다르게 돌아갈지도 모른다는 비극적인 생각이 갑자기 들었다. 제출해야 하는 설에 손으로 직접 쓴 글씨를 들이밀면 예의가 아니라는 사람들도 있으니 말이다. 

AI는 '인간적인 것과는 거리가 먼' 일에서 힘을 발휘하는 것이 옳다고 생각한다. AI가 만든 정보나 인물(현실의 인물을 거의 동일하게 구현한)은 대중에게 잘못되거나 조작된 이미지를 전달하기에 너무 좋다. 인구가 현재의 수십분의 일 수준으로 줄었을 때라면 AI가 구현한 가상 인물이 설 자리가 많아지겠지만 말이다.



2021년 12월 17일 금요일

Perl을 이용하여 multiple alignment에서 컬럼 단위의 conservation 추출하기

다중서열정렬(multiple-sequence alignment)에서 conserved region을 뚝딱 뽑아주는 프로그램이 널려 있을 것 같지만 현실은 그렇지 않다. trimAl이나 ClipKIT에서 그런 기능을 제공하지는 않는다. 원래 이들 프로그램의 용도는 다른 곳에 있기 때문이다. ClipKIT의 log 파일에서는 각 컬럼의 위치에 대하여 constant site 여부를 보여주기는 하지만(옵션에서 constant site를 추출하도록 지정하는 경우에 한함), 이를 수치로 출력한 뒤 사용자가 고르게 해 주지는 않는다. 그도 그럴 것이, 모든 서열에 대하여 동일한 잔기가 존재하는 경우 계통발생학적 분석에서 많은 정보를 주지 못하기 때문이다.

Biostars를 검색하니 이런 목적으로 Perl 코드를 이용하는 방법이 소개되어 있었다. 무려 10.5년 전의 질문과 답이었다!


여기에 대하여 답을 제공한 Neilfws라는 사용자의 프로필을 따라가 보니 그는 내가 관심을 갖고 체크해 두었던 논문 "Pathogenic archaea: do they exist?" BioEssays 25:1119의 공저자인 Neil Saunders라는 사람이었다(구글 스칼라). 시드니에 거주하며 Curtin University에 근무하는 것으로 나온다.

파이썬의 세계에서는 이러한 요구사항을 충족하는 매우 좋은 방법이 있는지는 모르겠다. Neil의 답글에 따르면, Perl에서는 Bio::SimpleAlign 오브젝트를 이용하여 차근차근 풀어 나가는 방법이 전부이다. 
출처: Biostar
이 해법에서는 alignment를 컬럼 단위로 slice하여 처리하는 것이 핵심으로 보인다. BioPerl로 늘 FASTA 파일만 다루다가 이 스크립트를 따라하면서 AlignIO 및 SimpleAlign을 처음으로 다루어 본다. 아, 부끄러워라.

3만개가 넘는 SARS-CoV-2 genome의 MSA를 처리하는 것이 목표라서 일단은 100개 서열만 취하여 테스트를 해 보았다. 현재 사용하는 리눅스 서버에서 약 13분이 걸렸다. 이를 32,483으로 확장했을 때 단순히 서열의 수에 비례하여 시간이 증가한다고 가정하면... 어휴, 71시간이 걸린다. CPU를 하나밖에 사용하지 못하는 스크립트라는 것이 문제이다. 이를 병렬화하려면 어떻게 해야 하나? MSA를 위치 기반으로 썰어서 20개 정도로 나누어서 각각을 별도의 job으로 돌리고, 다시 이를 합치면서 coordinate를 재계산하고... 아, 귀찮아.

바로 곁에 있는 '최신' 컴퓨터엔 AMD Ryzen 9 5950x에서 시험 삼아 100개의 서열을 처리해 보았다. 5분 정도가 걸렸으므로 구형 Xeon 서버보다는 2.7배 정도 빠르다. 그래, 여기에서 돌리자. 어제 늦게 퇴근하면서 Ryzen 서버에서 작업을 시작하였는데 오전 10시 23분 현재 17500 site에 대한 계산이 끝났다. 오늘 퇴근 무렵이면 전체 29 kb에 대한 conservation 수치를 얻을 수 있을 것이다. 이를 사용하면 내 입맛에 맞게 기준을 정하여 conserved sequence를 뽑는 것이 가능하다. 100% conserved sequence를 추려내면 길이가 짧은 서열만이 나와서 후속 분석 작업에 쓰기 곤란하다는 것은 이미 ClipKIT 결과를 통해서 알고 있다.

trimAl은 정말 느리다. 그러나 alignment의 포맷 전환이라든가 위치 기반 추출 등 유용한 부속 기능이 있어서 가끔씩 쓰기에는 좋다.

독후감 쓸 거리가 몇 개 있는데 주말에 차분히 앉아서 블로그 작업을 할 수 있을지 모르겠다. 요즘은 뇌세포가 퇴화했는지 생각을 글로 풀어나가는 것이 예전보다는 어렵다.


2021년 12월 13일 월요일

'신규확진 절반 돌파감염'의 정확한 의미를 생각해 보자

연일 COVID-19 신규 감염자의 수가 급증하고 있다. 조금 뒤면 점심 시간이 시작되는데, 새롭게 강화된 정책을 놓고 식당이나 카페 입구에서는 실랑이가 벌어질 것이 뻔하다. 전에는 동선 파악을 위하여 QR이나 안심콜을 하는 정도로 충분했지만, 이제는 접종 후 며칠이 지났는지까지 업주가 확인을 해야 되기 때문이다. 위반 사항이 적발될 경우 업주에게 더 큰 처벌을 내리는 것에 대해서도 불만이 많은 것으로 안다.

온 인류가 백신에 희망을 걸고 있지만 이미 백신을 맞은 사람이 COVID-19에 걸리는 일이 워낙 많아지다보니 백신이 도대체 무슨 소용이 있느냐는 회의감을 느끼는 사람이 많아지는 것을 부인할 수 없다. '신규확진 절반 돌파감염'이라는 자극적인 기사 제목이 온갖 매스컴의 헤드라인을 장식하고 있다. 이에 우리 연구원의 김두진 박사가 백신 효과를 따지기 위한 올바른 계산 방법을 설명한 인터뷰가 기사로 실렸기에 이를 소개한다.

[동아사이언스] '신규확진 절반 돌파감염' 등 불완전한 문구가 '백신 무용론' 부추겨

오늘 신규 확진자가 2천명이 나왔다고 가정하자. 그 중에서 1천명은 이미 백신을 맞은 사람이라고 하자. 그러면 '신규확진 절반 돌파감염'이라는 기사 제목줄은 결코 거짓말은 아니다. 그러나 그 '절반'의 의미를 잘 음미해야 한다. 이해를 돕기 위해서 간단한 그림을 그려 보았다. 이 그림이 현재의 상황을 가장 정확하게 설명한다고 믿는다.

만약 백신이 아무런 효과가 없다면, 신규확진자를 표시하는 빨간색 원은 인구 집단 전체를 가리키는 사각형 내에 아무데나 찍힐 것이다. 그리고 그 매일 매일의 위치도 바뀔 것이다. 그러나 좀 더 과학적으로 생각해 보자. 백신접종과 신규확진 사이에 아무런 상관 관계가 없다면, 신규확진자를 구성하는 2천명 중에서 비접종자와 접종자의 비율은 전체 인구 중에서 백신을 맞지 않은 사람과 맞은 사람의 비율을 그대로 반영하지 않겠는가? 현재 우리나라의 접종 완료자 비율이 80%라면, 그러한 가정(즉, 백신이 전혀 효과가 없었다) 하에서 신규확진자 중 접종완료자의 비율도 80%가 될 것이다. 그러나 현재 상황은 80%가 아니라 50%이다. 분명히 효과가 있는 것이다. 다시 말해서 백신의 효과를 논하려면, 비접종자 중 확진자의 비율과 접종자 중 확진자의 비율을 비교해야 하는 것이다. 단순히 확진자 내에서 비접종자와 접종자의 비유만 따지는 것은 의미가 낮다(차마 없다고는 말 못하겠다). 흠, 생각보다는 낮다고 느껴질지도 모르겠다. 김두진 박사가 제공한 그림에서는 신규확진자를 표시하는 원 안에 사망자도 표시하여 이해를 돕게 만들었다.

물론 다음과 같은 상황이 더 바람직함은 말할 나위도 없다. 저 빨간색 원이 한참 위로 밀려 올라가기를 바라는 심정은 누구나 다 갖고 있을 것이다.

개인적으로는 백신의 부작용에 대해서 고민이 많다. 나 하나만 놓고서 백신의 편익을 따져 본다면 맞지 않는 것이 이득일 수도 있다. 이미 2차까지 맞고도 약간의 몸살 기운 비슷한 것을 제외하면 큰 일은 없었으니 다행이라고 여긴다. 3차 접종까지 그러할지는 알 수 없다!

그러나 사회 전체를 놓고 보면 백신을 맞지 않은 상태에서 COVID-19에 걸렸지만(그 가능성은 백신을 맞은 상태에 비교하면 더 높을 것이고) 운이 좋아서 경미하게 앓다가 낫게 된다 하더라도, 회복이 되기 전에 전파가 이루어져서 다른 건강 취약 계층을 위험하게 만들 가능성이 있다. 그래서 부작용을 감수하고서라도 백신을 맞는 것이 더 많은 사람을 위해서는 낫다고 판단하게 되는 것이다.

문제는 독감 백신과 같은 일반적인 부작용(발열이나 몸살 같은 증세)보다 COVID-19의 증세가 더 경미하지 않을까하는 얄팍한 생각이 든다는 것, 그리고 안전성이 충분히 검증되지 않은 백신을 맞고 심낭염 등이 걸려서 죽을지도 모른다는 두려움이 든다는 것이다! 이 백신을 맞고 죽을 가능성은 길을 가다가 운석이나 벼락에 맞을 가능성보다는 현저히 낮을지도 모른다. 그러나 만약 그런 불운이 나에게 닥친다면, 모든 것을 잃게 된다.

COVID-19가 참 나쁜 병인 이유는 감염병 자체의 위중함보다는 이를 대처하는 방법(거의 국가 수준에서 반 강제로 이루어지므로 개인의 선택을 존중하기 어렵다)이 국가 및 세계 경제 발전과 개인의 활동에 직접적인 영향을 미치고 있으며, '공포심'이 가져오는 피해가 너무나 크다는 것이다. 정부와 방역 당국도 매일 머리를 싸매고 묘안을 찾기 위해 고민을 하고 있을 것이다. 여기에서 나오는 정책이 정말로 정답이었는지는 시간이 지나 봐야 알 것이다. 일단은 따르는 것 말고는 다른 대책이 없다. 4차 산업 혁명을 논하는 이 시기에 역병이 일상이 된 나날을 보내고 있다니...




2021년 12월 7일 화요일

6LQ8 싱글 엔디드 앰플리파이어의 보수

자작 6LQ8 푸시풀(push-pull) 앰플리파이어에 이어서 같은 진공관을 사용한 싱글 엔디드(single-ended) 앰플리파이어의 보수를 마쳤다. 이번에는 딱히 문제점이 발생한 것을 고친 것은 아니었다. 외부에서 12V 어댑터를 연결하여 히터의 전원을 공급하던 것을 앰프 본체 내부에서 직접 공급하게 만든 것이다. 이를 위하여 여분의 전원 트랜스(0/9/12/15/18V 1.2A)와 정류회로기판을 사용하였다. 6LQ8 데이터시트에 따르면 히터 전원은 6.3V 775mA가 되어야 하므로, 좌우 채널을 이루는 두 진공관의 히터를 직렬로 연결한 상태에서는 추가로 장착한 전원 트랜스의 용량(1.2A)이 부족하지 않다. 0-15V 탭에 정류회로를 연결하여 히터를 점화한 경우 최종 출력 전압은 12.5V 정도가 나와서 매우 적당하였다. 시판되는 직류 12V 어댑터를 사용하면 정격 수치인 12.6V의 95.2% 정도라서 문제는 되지 않는다. 일반적인 경우 +/- 5% 정도의 오차는 허용하기 때문이다. 물론 5%를 조금 넘어간다 해서 당장 진공관이 망가지거나 하지는 않는다.

DC로 만들지 않은 상태에서 12V 탭에서 히터 전원을 교류 상태로 공급해도 되지만, 그라운드 처리가 까다로와진다. 가장 바람직한 것은 전원 트랜스 2차의 센터탭을 앰프 회로의 그라운드에 한 점에서 연결하는 것이다. 그러나 이 트랜스에는 센터탭으로 쓸 만한 것이 없다. 만약 0-6-12V..의 전원 트랜스였다면 6V 탭을 쓰면 된다. 탭이 없으면, 저항 두 개를 이용하여 가상 중점을 만들 수도 있다. Valve Wizard의 Heater/Filament Supplies 문서에서 "Artificial Centre Tap" 항목을 참조하라.

트랜스 쪽에 적당한 탭이 있다 하여도 이 앰프의 PCV 자체에 한계점에 의해서 쓰기 어려운 사정이 하나 있다. 보드 내에서 히터 공급선의 하나와 그라운드를 연결하여 쓸 것을 전제로 만들었기 때문이다. 머리를 조금만 쓰면 직류를 만들지 않은 상태에서 가상 중점을 그라운드에 연결할 방법이 없는 것은 아니지만, 조금이라도 험을 줄이려면 직류가 더 나을 것이라는 생각에 예전에 만든 정류회로기판을 사용하기로 하였다.

두 번째의 개선 포인트는 두꺼운 4P 커넥터로 앰프 베이스로부터 바깥쪽을 빙 둘러서 상판으로 전원을 공급하였는데, 사실 이는 매우 거추장스런 모습이라서 상판에 구멍을 뚫고 내부에서 선을 연결하게 만든 것이다.

두꺼운 선을 여럿 연결할 때 나는 접속자를 즐겨 사용한다. DIY 오디오에서는 잘 쓰이지 않는 기법(?)이다.

무신호 상태에서 전원을 넣고 스피커에 귀를 가까이 대면 약하게 험이 들린다. 특별히 예민하게 생각하지 않는다면 음악 감상에는 큰 문제가 없는 수준이다. 전원쪽에는 잔류 리플을 제거하기 위한 특별한 조치를 취하지는 않았다. 예전에 전원 트랜스의 코어를 빼서 갭을 주어 싱글 엔디드 앰프용 출력 트랜스로 개조한 것이 남아 있었는데, 이를 초크 코일 대신으로 삽입하였다. 없는 것보다는 나은데, 제대로 만든 초크 코일을 사서 써 본 일이 없으니 그 효과가 어느 수준인지를 알기가 어렵다. 여력이 생긴다면 MOSFET를 이용한 노이즈 제거 회로를 만들어서 쓸 수도 있을 것이다.

출력 트랜스에는 폐 컴퓨터에서 적출한 냉각팬 관련 부품을 씌웠다. 여기에 포맥스나 아크릴 조각을 잘라서 덮으면 깔끔하게 마무리가 될 것 같다. 원래는 하얀 정육면체 모양의 덮개가 있었는데 방송 촬영 후 없어진 상태로 돌려받게 되었다. 히터 점화용 DC 어댑터도 없어진 것이 이번 보수 작업의 직접적인 계기가 된 것이다. 소품 대여와 관련하여 특별히 계약서를 쓴 것도 아니고, 약간의 대여료를 받았기 때문에 일부 부속품이 없어지거나 망가지더라도 어차피 감수할 생각이었다.

무척 작은 출력 트랜스를 사용한 소출력 싱글 앰프이지만 밤 늦은 시간에 침실에서 조용하게 FM 방송을 듣기에는 무리가 없다. 작업을 마친 뒤 사진 기록을 남겨 본다. 내가 생각해도 참 별난 모습의 진공관 앰프이다.




아직 나에게는 8개의 6LQ8 진공관이 남아 있다. 이것을 다 쓰려면 아마도 앰프를 하나 더 만들어야 될 것이다.


언제쯤 되어야 6V6이나 EL84와 같이 유구한 역사를 지닌 오디오 신호 증폭 전용관으로 앰프를 만들어 소리를 들어 보게 될까? 그렇게 될 날이 언젠가는 오게 될 것이다. 아마도 앞으로 2년 이내에?

2021년 12월 13일 업데이트

출력 트랜스 커버에 철망을 씌웠다. 스테인리스 스틸 판(10 cm x 10 cm)으로 정육면체를 만든 뒤 하얀색 시트지를 쓰워서 '두부 한 모' 형태의 커버를 만들어 씌었었는데, 방송 촬용을 마치고 나서는 어디론가 사라져 버렸다. Shuttle 베어본 컴퓨터 XPC SG33G5에서 떼어낸 부품이 아직도 남아서 자작 앰프의 한 곳을 장식하고 있다.



나에게 XPC SG33G5를 납품했던 (주)오믹시스의 우태하 사장님! 어디 계십니까... 보고 싶습니다.


2021년 12월 6일 월요일

VCF 파일을 BED로 전환할 때 좌표 정보는 어떻게 바꾸어야 하는가

요즘 SARS-CoV-2의 알려진 변이체 정보를 분석하여 변이 위치를 수집한 뒤 conserved region에 해당하는 영역에서 바이러스 검출용 PCR 프라이머를 설계하는 방법을 공부하고 있다. 특히 다음 논문에서는 튜토리얼 형태로 이 과정을 잘 설명하고 있어서 전체를 재현해 보았다.

PCR Primer Design for the Rapidly Evolving SARS-CoV-2 Genome. Methods Mol Biol. 2022;2392:185-197. doi: 10.1007/978-1-0716-1799-1_14. https://pubmed.ncbi.nlm.nih.gov/34773624/

여기에서 VCF를 BED로 전환하는 awk 명령어가 마음에 들지 않았다. 

  • [VCF] NC_045512 204 . G T  #나머지 컬럼 생략
  • [BED] NC_045512 203 204
204번째 위치의 G가 T로 바뀐 단일염기치환을 BED 파일에서는 왜 (203, 204)라는 위치로 표시하는 것일까? 'awk 명령어에 오류가 있는 것 같다!'는 것이 내 생각이었다. BEDOPS의 vcf2bed라는 유틸리티를 사용하면 정확한 feature 구간 위치 정보의 전환이 이루어질 것 같았다. 그런데 결과는 같았다.

왜 이렇지?

그건 내가 무식했기 때문이었다. 일단 유전체 관련 파일 포맷에서 위치 정보를 기술하는데 0-based 혹은 1-based system 중 어느 것을 쓰는지 잘 알아 두어야 한다. GFF/BAM/VCF는 1-based이지만 BAM/BED는 전산인이 좋아하는 0-based system을 사용한다. 이를 설명하는 글을 몇 개 찾아보았다. 전부 10년 가까이 된 글이다. 이를 아직까지 모르고 있었다니!


0-based system(+ half open)은 프로그램 입장에서 길이를 계산하기가 더욱 쉽다. 겹침(overlap)의 확인도 더욱 쉽다고 한다.


따라서 '인간적인' 1-based 좌표 체계에서 204번째 염기에 단일염기치환이 일어났음을 BED로 표시하려면 203, 204가 된다.
  • 1-based: [start, end]
  • 0-based: [start-1, end)
다음은 vcf2bed의 공식 설명에 웹문서에서 가져온 것이다. 대단히 부끄럽지만 오늘이라도 무식에서 벗어난 것을 다행으로 생각하자.



6LQ8 푸시풀 앰프의 잡음 줄이기

나의 6LQ8 푸시풀 앰프 '티라미수 II'는 방송 촬영 일정에 맞추어 급하게 만든 것이라서 음질적으로는 완벽한 튜닝을 하지 못한 상태였다. 약 반년이 넘는 대여 기간 후 돌아온 앰프를 점검해 보니 생각보다 잡음이 많았다. 특히 오른쪽 채널에서 무신호 시에 '웅-'하는 소리가 크게 들렸다. 처음에는 오른쪽 채널 보드 바로 밑에 위치한 히터 전원 공급용 SMPS에서 잡음이 유도된다는 생각을 갖고 있었는데 그건 아니었다. 왜 한쪽 채널에서만 잡음이 발생하는 것인가? 좌우 진공관을 바꾸어 끼워도 잡음은 여전히 오른쪽에서만 났다. 출력 트랜스에 문제가 생겼나? 그럴 가능성은 매우 희박하다. 부품을 바꾸어 연결하는 테스트를 해 보니 여전히 오른쪽 보드가 문제인 것 같았다.

부품이 조밀하게 꽂혀 있지만 비교적 단순한 PCB에서 무슨 문제가 발생한단 말인가? 저항이나 캐패시터와 같은 수동 소자에 무슨 문제가 생기겠는가? 제이앨범에서 새 PCB를 새로 구해서 처음부터 다시 만들어 볼까?

앰프 상판을 열어 놓은 상태로 이곳 저곳을 건드려 보았다. 간헐적으로 오른쪽 채널에서 천둥 소리 비슷한 굉음이 들린다. 입력단에서 접촉이 좋지 않아서 플로팅 상태가 될 때 흔히 들리는 소리다. 음량 조절용 포텐셔미터(흔히 '볼륨'이라 부르는 것)의 납땜 상태에 의심이 가기 시작하였다. 보드의 신호 입력용 커넥터를 스크류 드라이버로 단락시키면 아무런 소리가 나지 않는다. 이 관찰 결과는 앰프 보드 자체와 출력 트랜스까지는 문제가 없음을 시사한다.

포텐셔미터는 Alpha 제품이라서 품질 자체가 불량하다고 판단하기는 어려웠다. 포텐셔미터 전후를 연결하는 상태가 불량하다 판단하고 다음과 같은 몇 가지 개선 사항을 적용하였다.

  1. PCB의 착탈식 커넥터 중 신호 입력쪽은 납땜 직결한다.
  2. 입력 실드선을 교체한다. 낡은 인터케이블을 잘라서 사용했었는데 품질이 영 마음에 들지 않았다.
  3. NFB 배선에는 실드선을 사용하고 그라운드 처리도 빼먹지 않았다. 
  4. 포텐셔미터와 입력단 사이에 커플링 캐패시터와 470K 그리드 리크 저항을 삽입한다. 아래 사진에 보인 만능기판이 바로 이 기능을 한다. 이 기판은 43 오극관 앰프의 초기 실험에서 사용하던 것이다.
빨간색 캐패시터는 예전에 사용하던 TPA3116에서 적출한 것이다. 

입력단에 포텐셔미터가 위치할 경우 그리드 리크 저항은 종종 생략된다. 그러나 포텐셔미터의 접촉이 좋지 않을 때에 그리드에 바이어스 전압이 걸리지 못하게 되므로 문제가 생길 수 있다. 커플링 캐패시터는 입력단에 DC가 유입되는 것을 막는 역할을 한다. 비정상적인 신호가 들어오지 않는 이상 커플링 캐패시터는 없는 것이 가장 좋을 수도 있을 것이다.

결과는? 언제 그랬냐는 듯이 잡음이 사라졌다. 결국은 좋지 못한 선재와 납땜 불량이 원인이었던 것 같다.

선재의 재활용에는 특히 주의해야 할 것 같다. 한국진공관앰프동호회의 고 안병원 회장께서 작성하신 '왕초보 따라하기'를 보면 폐 컴퓨터에서 쓸만한 전선을 많이 구할 수 있다고 하셔서 나도 이를 따라 했었다. 그런데 이렇게 재활용한 전선 중에는 유난히 납땜이 잘 되지 않는 것이 있었다. 주석도금선처럼 은색을 띤 연선에 왜 이렇게 납이 붙지 않을까? 어쩌면 이런 전선 중 일부는 알루미늄을 사용하며 제조한 것이 아닌지 모르겠다. 알루미늄은 구리보다 전도도가 떨어지지만 가볍기 때문에 송전선 등에서 흔히 쓰이는 것으로 알고 있다. 요즘 전기차에서도 선재 총 중량을 줄이기 위해 알루미늄을 많이 쓴다고 한다. 그런데 알루미늄과 구리를 같이 꼬아서 연결하면 알루미늄이 부식하는 현상(갈바닉 부식, Galvanic corrosion)이 일어난다고 한다. 이는 전기 배선뿐만이 아니라 서로 다른 종류의 금속을 직접적으로 접촉해야만 하는 모든 현장에서 만나게 되는 문제이다.

유튜브: How to identify copper vs. alunimum wire | DIY material knowledge

우리나라의 DIYer가 알루미늄이 든 선재를 접할 일이 얼마나 있을지는 잘 모르겠다. 단지 나의 납땜 실력 부족을 선재 탓으로 돌리는 것은 아니었을까? 어쨌든 선재는 가급적 새 것을 사용하는 것이 바람직할 것이다.

납땜 개선 작업이 끝난 티라미수-II 앰프.
진공관 앰프의 매력은 따뜻한 불빛을 바라보며 아날로그 감성을 느낄 수 있다는 것.

다음 숙제는 6LQ8 '싱글' 앰프를 개선하는 것. 하부 케이스와 상판 사이의 배선을 바깥쪽에서 매우 굵은 4P 커넥터로 연결하던 종전 방식을 바꾸려 한다. 전원부 하나로 두 앰프를 번갈아 쓰던 예전 방식을 더 이상 고수할 필요가 없기 때문이다. 나무로 만들어진 상판에 구멍을 뚫고 케이블을 그리로 지나가게 하면 된다. 두 번째로는 히터 전원 공급 방식을 바꾸는 것이다. 기존에는 12V 직류 어댑터를 외부에서 접속하는 방식을 썼었다. 위에서 보인 푸시풀 앰프에서는 어댑터를 앰프 케이스 안에 넣어 버렸었다. 그러려면 어댑터 하나를 완전히 희생해야 한다. 마침 남는 전원트랜스가(9/12/15/18V 1.2A) 하나 있으니 이를 사용하려고 한다. 필요하다면 DC로 정류하여 사용할 수도 있다. 







2021년 12월 3일 금요일

설계된 프라이머의 결합 위치를 그림으로 표시해 보자

BioPerl의 그래픽스 기능(Bio::Graphics)을 사용하여 서열 'track' 위에 여러 feature를 표시할 수 있다. 프라이머 정보 역시 feature로 간주하여 방향까지 표시되는 화살표로 표현하면 된다. HOWTO 문서를 참조하여 직접 손으로 Perl 코드를 짜도 되지만, 남들이 먼저 만들어 놓은 것을 살짝 고쳐서 쓰면 더욱 낫지 않겠는가?

프라이머를 설계하고 시각화하는 공개 프로그램을 뒤적거리다가 이런 논문을 발견하였다.

PrimerView: high-throughput primer design and visulaization (2015).  GitHub 링크

미국 조지 워싱턴 대학의 Damien M. O'Halloran이라는 사람이 단독으로 개발하여 발표한 것이다. 이 도구는 리눅스에 설치하여 쓰는 Perl module이다. 여러 유전자를 multi-FASTA file로 제공하면 primer3가 각 유전자를 증폭하는 프라이머쌍을 설계하고, template DNA에 결합하는 위치를 이미지 파일로 보여주는 소박한(?) 도구이다. O'Halloran은 2016년에 GUI tool인 PrimerMapper(GitHub 링크)라는 것을 발표하기도 하였다. 기능은 훨씬 많아진 것 같은데 아직 제대로 테스트를 해 보지 못하였다.

PrimerView는 내부적으로 primer3_core를 사용하도록 되어 있다. Template DNA의 염기서열은 사용자가 제공하면 되지만 각 염기서열에서 설계하는 최대 프라이머쌍의 수 등 사용자가 입맛에 맞게 파라미터를 맞추어 넣을 수가 없다. 핵심 구성요소인 PRIMERVIEW.pm을 아무리 들여다 보아도 primer3 파라미터를 넣는 곳은 없다. 

그러면 소스를 고쳐 보면 되겠지... 모듈에서 대부분의 기능을 구현하고 메인 소스 코드는 간결하게 만드는 스크립트 작성 스타일에는 별로 익숙하지 않아서 시행착오를 거듭하여 수정을 해 보았다. 그런데 뭔가 이상하다. 아무리 모듈을 고쳐도 결과는 변화가 없다. 그거 참 이상하다. 이유는 간단한 곳에 있었다. 스크립트가 참고하는 모듈의 위치는 /usr/local/share/perl/5.30.0인데 프로그램을 설치한 곳의 lib/ 이하 위치를 참조하는 것으로 생각하여 엉뚱한 것을 고쳤던 것이다. @INC 배열로 지정된 곳 중 어디에 PRIMERVIEW.pm이 있는지를 찾고 나서야 비로소 답을 알게 되었다. Perl의 모듈 관리가 원래 그렇다. FindBin과 use lib 디렉티브를 잘 사용하여 보다 깔끔하게 고쳐야 되겠다.

원본 모듈에서는 사용자가 입력한 염기서열만을 primer3로 보내게 된다. 서열 정보를 담는 input file의 앞부분에 내가 별도의 파일로 제공한 primer3 파라미터 파일을 삽입하게 만들었다. 다음은 그 결과로 얻은 그림이다. 입력 template는 신종코로나바이러스의 게놈 서열을 주었고 총 20쌍의 프라이머를  만들게 하였다. Product size는 150-200 bp range로 하였다.

Primer Map이 그려주는 그림보다는 나은가? 해상도가 다르다는 것이 가장 큰 차이점이라고 생각한다.
프라이머 위에 적힌 숫자는 프라이머 ID를 대신하는 것으로서, 5'-end의 위치에 해당한다. 여기서 주의할 것이 하나 있다. Primer3의 위치 체계는 0-based라는 점이다. 그리고 한쪽 프라이머가 (거의) 동일한 상태에서 반대편 프라이머는 별도의 것을 취하는 복수의 amplimer를 예측하기도 한다는 점이다.

이 그림에서는 어떤 프라이머가 서로 짝을 이루고 있는지 한눈에 보이지는 않는다. 그러나 잘 관찰하면 어렵지 않게 파악할 수 있다.

PrimerView의 독특한 점은 설계한 프라이머가 결합하는 위치를 muscle alignment를 돌려서 찾는다는 것이다. 아니, primer3 결과 파일에 결합 위치가 다 있는데 왜 이런 수고를? 염기서열이 그대로 보이는 출력물을 이미지로 만들기 위해서 그런지도 모르겠다.

만약 다른 프로그램으로 프라이머를 설계한 뒤 결합 위치를 표시하고자 한다면 이러한 정보를 수록한 텍스트 파일을 먼저 만든 다음, PRIMERVIEW.pm의 _graphics_all_primers 함수를 참조하여 코드를 직접 만들어야 한다. 이것은 별 문제가 되지 않지만, 정보 파일을 만드는 일은 각자 알아서 해야 한다. EMBOSS의 primersearch가 되었든, 최근에 소개한 MFEprimer가 되었든 다른 프라이머 평가 도구를 써서 만든 결과 파일을 다듬어야 한다.


2021년 12월 2일 목요일

감염병 진단용 PCR 프라이머 설계 그리고 결과물의 평가

PCR을 이용한 감염병 진단 제품을 개발하는 기업에게는 대단히 죄송한 이야기가 되겠지만 나는 지금까지 프라이머 설계를 학술적으로 매우 중요하고 매력적인 일이라고 생각하지 않았었다. 지난 여름이 되어서야 주변의 요청에 의하여 COVID-19의 유전체 서열을 바탕으로 PCR용 프라이머를 설계하는데 사용할 conserved sequence를 추출하는 작업을 하게 되었고, 그 과정에서 파생되는 일들을 정리하고 활용 범위를 확대하기 위한 가능성을 모색하는 중이다. 당연히 강한 흥미를 느끼면서 이 일에 조금씩 빠져들고 있다.

온라인에는 웹서비스로 돌아가는 다양한 PCR 프라이머 설계 및 평가용 툴이 존재한다. 어떤 프로그램은 소스 또는 실행파일을 가져다가 로컬 컴퓨터에서 직접 설치하여 사용하도록 배려해 주기도 한다. 예를 들자면 나는 EMBOSS의 primersearch를 이따금씩 사용한다. 이것은 프라이머 설계용 도구가 아니라 프라이머쌍의 서열(한 줄에 한 쌍)과 DNA 염기서열 정보를 입력하면 결합 위치와 amplimer(=amplicon)의 크기 정보를 Whitehead primer3_core 프로그램의 출력 파일 형태로 작성해 준다. 조정 가능한 파라미터 중에서 가장 중요한 것은 allowed percent mismatch이다. 그러나 서로 다른 쌍에 속하는 프라이머가 상호작용을 하여 다이머(dimer)를 만드는지의 여부를 점검해 주지는 않는다. 다시 말하자면 한 쌍으로 주어진 프라이머가 template DNA 서열에 mismatch를 고려하여 서로 마주보고 결합하는 것을 가정하여 생성되는 amplimer에 대한 결과만을 제시할 뿐이다. 프라이머 정보 파일을 구성하는 각 줄에 대해서 독립적인 분석을 수행하며, multiplexed PCR은 알 바가 아니다. 다음은 primersearch의 전형적인 실행 결과 파일이다.

Primer name primers-0
Amplimer 1
        Sequence: NC_045512
        Severe acute respiratory syndrome coronavirus 2 isolate Wuhan-Hu-1, complete genome
        TGATGGTGGTGTCACTCGTG hits forward strand at 8701 with 0 mismatches
        GGCACGACAAAACCCACTTC hits reverse strand at [21039] with 0 mismatches
        Amplimer length: 165 bp

Primer name primers-1
Amplimer 1
        Sequence: NC_045512
        Severe acute respiratory syndrome coronavirus 2 isolate Wuhan-Hu-1, complete genome
        GCCGCTGTTGATGCACTATG hits forward strand at 17170 with 0 mismatches
        TGTCGTCTCAGGCAATGCAT hits reverse strand at [12567] with 0 mismatches
        Amplimer length: 168 bp

프라이머끼리 서로 결합하여 어떤 다이머를 만드는지 점검하고 싶다면 ThermoFisher Scientific의 Multiple Primer Analyzer를 이용하면 좋다. 여기에서는 입력한 프라이머의 기본 특성 외에 self-dimer와 cross-dimer 정보를 제공한다.

이보다 더욱 진보한 프라이머 점검 도구에는 MFEprimer라는 것이 있다(논문 목록). 2009년에 최초 버전이 나왔으니 꽤 오랫동안 공들여서 기능을 추가하고 다듬어 온 도구라고 할 수 있다. 인간 등 주요 모델 생명체에 대한 'Background Database'를 선택하여 최대 50개까지의 프라이머에 대한 specificity check를 하게 배려해 준다. 명령행 버전을 설치하면 background database를 사용자가 공급할 수 있고, 입력하는 프라이머 수에 대한 제한도 없다. 내가 생각하는 MFEprimer의 가장 큰 특징은 당초 프라이머 설계 과정에서 누가 짝을 이루고 있는지를 전혀 고려하지 않고 amplicon을 예측해 준다. 물론 헤어핀과 다이머에 대한 점검은 기본이다. 최신 버전의 기능 소개 및 다른 버전과의 비교는 여기에 잘 설명되어 있다.

다음은 내 컴퓨터에 설치한 MFEprimer 명령행 버전에 100 쌍의 프라이머 서열을 넣고 분석한 첫 번째 amplimer의 구조이다.

Amp 1: primer-33-forward + primer-63-reverse ==> hCoV-19_USA_...(너무 길어서 생략):26844-26879

    Size = 35 bp, GC content = 54.29%
    F: Tm = 61.24 °C, Delta G = -23.36 kcal/mol
    R: Tm = 62.74 °C, Delta G = -23.58 kcal/mol
    Binding sites: 26845(20/20) ... 26879(20/20)

>>>primer-33-forward
   1                  20
5' GGACACcATCTAGGACGCTG 3'
   ::::::::::::::::::::              26879
5' GGACACCATCTAGGACGCTGTGACATCAAGGACCT 3'
   26845          ::::::::::::::::::::
               3' CGCTGTGAcATcAAGGAcCT 5'
                 20                  1
                     primer-63-reverse<<<

어? 이건 cross-dimer가 아닌가? 원래 다른 위치를 증폭하도록 설계된 프라이머가 5'-...CGCTG(끝)-3'라는 염기서열 매치를 통해서 다이머를 형성한 것으로 볼 수도 있다. ThermoFisher Scientific의 Multiple Primer Analyzer에서는 두 프라이머 사이에 단지 5개 염기가 연속적으로 결합하여 만들어지는 다이머는 표시하지 않는다. 아마도 두 프라이머 사이에 불연속적인 basepairing을 포함하여 최소한 6개 염기는 붙어야 다이머로 판단하는 것 같다. MFEprimer가 이를 amplimer로 판정하는 이유는, amplimer의 염기서열(5'-GGACACCATCTAGGACGCTGTGACATCAAGGACCT-3')이 template DNA 내 26845..26875 위치에 분명히 존재하기 때문일 것이다.

그러면 MFEprimer는 몇 % 혹은 몇 base의 mismatch까지 고려하여 amplimer를 예측하는가? 이렇게 갑자기 물으면 대답하기가 어려워진다. 원래 MFEprimer는 프라이머 서열 검색에 k-mer 알고리즘을 쓰기 때문이다. NGS short read의 조립이나 유전체 비교 계산에 널리 쓰이는 바로 그 k-mer 말이다. 그렇기 때문에 이전 버전에서는 k-mer 내부에서 일어나는 mismatch는 허용하지 못하였었다. 그러나 v3.0부터는 그 기능이 추가되었다고 한다. 다음의 사례를 보자. Reverse primer binding site 내에 1-bp mismatch가 보인다. 

>>>primer-61-forward
   1                  20
5' TACGCGTTCCATGTGGTCAT 3'
   ::::::::::::::::::::                                                    26937
5' TACGCGTTCCATGTGGTCATtcaatccagaaacta...tgctggacaccatctAGGACGCTGTGATATCAAGG 3'
   26765                                                ::::::::::::.:::::::
                                                     3' AGGACGCTGTGAcATcAAGG 5'
                                                       20                  1
                                                           primer-62-reverse<<<

3'-end의 mismatch는 PCR 반응에 바람직하지 않으므로 허용하지 않지만, 웹 버전에서는 이를 해제할 수 있다.

명령행 버전에서는 훨씬 상세하게 mismatch 관련 파라미터를 건드릴 수 있다. 자세한 사항은 논문의 'The k-mer mismatch search algorithm' 섹션을 상세히 읽어보기 바란다. 나도 아직 완벽하게 이해하지는 못했다.
  • --misMatch int   max allowed mismatches between kmer and its binding sites
  • --misStart int   mis-match starts from the position of 3' end, 1 is for the very end of primer. (default 1)
  • --misEnd int     mis-match ends to the position of 3' end, 9 (kvalue) for the 9th base from the 3'end (default 9)
Mismatch 관련 파라미터의 설정은 EMBOSS primersearch가 훨씬 더 이해하기 쉽고 직관적이다. 그러나 실행 속도는? MFEprimer가 말할 수 없이 더 빠르다.

primer3_core의 실행

꽤 오래 전에 primer3의 WWW 버전을 설치하여 조금 써 본 일이 있으나 명령행에서 primer3_core 실행파일은 이번에 처음 돌려 보았다. 프라이머를 고를 염기서열 정보를 인수(FASTA file)로 제공하는 것으로 생각했는데, 그게 아니라 입력 파일('input.txt') 내에 ID와 서열을 각각 한 줄로 써 넣어야 함을 알았다. 어떤 문서에서는 입력 파일 내에 FASTA file의 path를 넣으면 된다고 설명하였는데 아무리 애를 써 봐도 작동하지 않았다.

코로나바이러스의 유전체(29.9 kb)에 대하여 총 100개의 프라이머 쌍을 만들도록 input.txt를 짠 뒤 primer3_core를 실행해 보았다. 다음은 input.txt의 전문이다. 맨 마지막 줄의 '=' 문자는 생략해서는 안 된다.

PRIMER_TASK=generic
PRIMER_PICK_LEFT_PRIMER=1
PRIMER_PICK_INTERNAL_OLIGO=0
PRIMER_PICK_RIGHT_PRIMER=1
PRIMER_OPT_SIZE=20
PRIMER_MIN_SIZE=18
PRIMER_MAX_SIZE=22
PRIMER_PRODUCT_SIZE_RANGE=150-200
PRIMER_EXPLAIN_FLAG=1
PRIMER_LOWERCASE_MASKING=1
PRIMER_NUM_RETURN=100
PRIMER_THERMODYNAMIC_PARAMETERS_PATH=/etc/primer3_config/
SEQUENCE_ID=NC_045512
SEQUENCE_TEMPLATE=ATTAAAGGTTTATACCTTCCCAGGTAACAAACCAACCA...(생략)
=

Template 서열 내에서 각 프라이머가 어떻게 위치하는지를 시각적으로 보여주는 방법이 있다면 참 좋겠다는 생각이 든다. 물론 염기서열 정보를 다루는 일반적인 상용 GUI 소프트웨어에는 프라이머를 설계하여 그 위치를 표시하는 기능은 다 들어 있을 것이다. 그러나 프라이머 정보(염기서열 및 위치)를 별도로 갖고 있을 때 이를 일괄적으로 임포트하는 기능은 아마 없을 것이다. 나의 프로그래밍 기법이 충분하다면 아래와 같은 수준의 이미지를 만들어 봄직도 한데 말이다. Perl의 Bio::Graphics를 이용하여 이런 출력물을 만드는 방법을 공부해 볼까? 아이고, 인공지능과 기계학습, 신경망, 딥 러닝과 같은 buzzword가 난무하는 2021년 마지막 달에 과연 합당한 결심일지 모르겠다. '메타버스'라는 말도 있구나! 정말로 관심이 있다면 Perl로 짜여진 PrimerView(2015)부터 공부를 하는 것이 좋을 것이다.

출처: PrimerDesign-M

Primer3_core가 설계한 프라이머가 만들어낼 100개의 amplimer는 서로 조금씩 위치가 겹칠까? 한쪽 프라이머를 고정해 놓고, 반대편 프라이머를 여러 개 선발하여 이를 별도의 amplimer로 취급할까? 이런 세부적인 사항을 건드리는 파라미터는 위 input.txt 파일에서 찾아볼 수 없다. primer3의 논문(NAR 2012)에서 새로 도입된 파라미터인 SEQUENCE_OVERLAP_JUNCTION_LIST는 내가 궁금해하는 사항과는 거리가 멀다. 단, left primer를 하나 지정해 두고 여러 right primer를 골라서 별도의 amplimer로 취급하는 경우는 확인을 하였다. left primer의 이름은 달리 부르고 있었으나 염기서열과 위치를 보니 전부 동일한 것이었다. 예를 들어 PRIMER_LEFT_61는 이름은 다르게 불리지만 총 7개의 amplimer에서 공통적으로 쓰이고 있었고, amplimer size는 159~180였다. 프라이머의 길이가 20 bp이므로 7개의 right primer 중 많은 것이 서로 겹치고 있음이 명백하다. 

Sequence Manipulation Suite: Primer Map에서 그린 소박한 그림. Primer3_core가 어떤 생각을 갖고 프라이머를 설계했는지 한눈에 알아볼 수 있다. 이렇게 만든 프라이머를 전부 때려넣고 MFEprimer를 돌리면 어찌 헷갈리지 않겠는가? 

만약 이 프라이머 서열을 MFEprimer에 넣어서 점검하려면, 동일한 프라이머는 제거하고 하나만 넣는 것이 옳을 수도 있다. 만약 모든 것이 성가시고 multiplexed PCR을 하지 않을 것이 확실하다면, 프라이머 쌍 하나에 대하여 개별적으로 MFEprimer를 실시하는 것도 바람직하다.

MFEprimer에 대해서 상세히 조사하게 된 것은 PCR Primer Design for the Rapidly Evolving SARS-CoV-2 Genome(Methods Mol Biol 2022? 내년에 정식 출판될 예정인가?)이라는 논문을 따라 하면서 많은 흥미를 느꼈기 때문이다. fIDBAC을 설치하여 사용하려다가 많은 실망을 했었는데, 이번에는 꽤 좋은 도구를 만난 것 같아서 반갑게 느껴진다. 튜토리얼 형식으로 되어 있어서 매우 쉽게 실행 가능하였는데, 변이 위치를 BED의 구간으로 전환하는 awk 공식은 좀 잘못되어 있는 듯하다. 이에 대해서는 별도의 위키문서 SARS-CoV-2 검출을 위한 PCR 프라이머 설계에 기록해 놓았다.

Multiple sequence alignment를 이용한 PCR용 프라이머 설계 방법에 대해서는 다음 기회에...

확인할 사항

Primer3_core의 coordinate system은 BED 파일처럼 0-based 같다는 생각이 든다. 확인해 볼 필요가 있다. 'primer3_core -format_output' 옵션을 이용하여 출력 파일을 읽기 쉬운 형태로 바꾸어서 실행해 보니 내 예상이 맞았다. 출력 파일 넷째 줄에 'Using 0-based sequence positions'라는 글귀가 선명하다.

2021년 11월 25일 목요일

PubMLST 자료를 쉽게 가져오는 방법 - mlst_check(Sanger)

오늘도 나의 2021년 11월 하순을 뜨겁게 달구고 있는 fIDBAC과 관련한 이야기를 써 내려가려고 한다. fIDBAC 파이프라인에서는 16S rRNA 서열 분석과 KmerFinder를 통해서 top 20 closest genome을 고르고, 이를 대상으로 fastANI를 실시하여 일정 컷오프를 통과하는 결과로부터 query genome이 어떠한 species에 해당하는지를 판별하여 그 정보를 OUTDIR/fastANISpecies 파일에 출력한다. example/example.fa를 사용한 경우는 이러하다. 

$ cat example_2021_11_25_08_20_15/fastANISpecies 
Salmonella enterica

fastANISpecies 파일에 여러 라인이 기록될 수도 있을까? fIDBAC.pl(v20181126)의 133번째 줄에서 다음과 같이 fastANISpecies 파일의 첫 줄만을 뽑아내도록 한 것을 보면 가끔 그런 일이 생기기도 하는 모양이다.

my $template=`head -n 1  $result/fastANISpecies`;chomp $template;

fastANISpecies 파일을 만드는 과정에 대해서도 살펴볼 것이 많지만 이에 대해서는 나중에 알아보기로 하고, 오늘은 fIDBAC.pl이 이 파일을 이용하는 다음 단계에 관해서 탐구해 보자. 이 단계에서 fIDABAC.pl 스크립트는 표준 출력으로 다음을 내보낸다.

Salmonella enterica...Salmonella enterica...

마치 강도에 피습당한 피해자가 '나를 칼로 찌른 놈은 아무개였어...'하고 간신히 내뱉고는 숨을 거두는 영화의 한 장면같다. 똑같은 종명(Salmonella enterica)를 두 번에 걸쳐서 출력한 것으로 보이지만 앞의 것은 $name 변수이고 뒤의 것은 $template 변수이다. 어느 종에 대한 MLST 분석을 해야 하는지 결정하는 열쇠가 되는 것이 바로 $name이다.

config_db.txt에서 설정한 LPSN(Species.tax 파일)의 첫 번째 컬럼은 'Salmonella_enterica'와 같은 형식으로 되어 있다. 공백을 underscore로 치환한 것이다. 왜냐하면 MLST DB를 구성하는 각 종명이 디렉토리 형식으로 그대로 쓰여야 하기에, 공백을 그대로 두면 곤란하기 때문이다. 이 문자열은 최종적으로 $species 변수에 저장된다. 일단 Species.txt 파일에서 첫 컬럼을 하나씩 읽어서 underscore를 다시 공백으로 바꾸어 $name과 비교하고, 일치하는 것이 있으면 이를 OUTDIR/Taxonomy.txt에 기록한다. 이는 MLST 함수가 하는 일 중의 하나이다.

MLST 분석은 fIDBAC.pl의 199번 라인부터 시작한다. 

my ($species, $flag) = split (/\t/, MLST ($template));
 if ($flag == 0){
      my $mlstlist = glob "$pubMLSTdb/$species/*.txt" ;
      system("perl $Bin/run_MLST.pipeline.pl -s $species -t $mlstlist -q $input -o $result \n");
  }else{
      print STDERR "This species is not exists in the pubMLST db\n";
} 

여기까지 살펴보면 $template와 $name 변수가 제대로 쓰였음을 알 수 있다. pubMLSTdb가 설치된 디렉토리 하위에는 $species에 해당하는 서브디렉토리가 존재하고, 또 그 밑에 세부적인 파일들(allelic progiles & sequenes)이 있어야 한다. 정확히 말하자면 여기까지가 서론이었다.

config_db.txt에서는 pubMLSTdb의 설치 위치를 지정해 두어야 한다. 그리고 fIDBAC README.md 파일에 의하면 'Download PubMLST database here.'라고 하였다. 그러나 'here'를 클릭하면 XML 파일이 나올 뿐이다. PubMLST 공식 웹사이트의 다운로드 페이지를 가 보아도 전체 자료를 하나로 묶어서 클릭만 하면 쉽게 내려받을 수 있게 만들지 않았다. 흠... 공식으로 제공하는 API를 이용해서 활용할 재주는 나에게 없다. 어떻게 해야 오늘 날짜 기준으로 153개나 되는 데이터베이스를 한꺼번에 가져올 수 있을까? 'bactopia datasets --available_datasets'으로 확인하면 무려 683개나 되는 자료가 있다. 아마 후자의 숫자는 PubMLST가 호스팅하지 않는 다른 것까지 포함해서 그런지도 모른다.

Torsten Seemann의 mlst를 사용하여 다운로드한 자료를 쓸 수 있을까? 이는 직접 실행할 일은 별로 없고, TORMES를 통해서 이용하게 된다. 나의 경우에는 다음의 위치에 파일들이 전부 저장되어 있다.

/opt/miniconda3/envs/tormes-1.3.0/db/pubmlst

그러면 이 디렉토리를 config_db.txt의 pubMLSTdb로 설정하면 될까? 전혀 그렇지 않다. 이 디렉토리의 목록은 다음과 같다. fIDBAC.pl에서는 Salmonela_enterica라는 하위 디렉토리를 이로부터 찾으려고 할 것이지만, 실제 존재하는 디렉토리 명칭은 약칭인 senteriaca이다. 이는 pubMLST 체계에서는 공식적으로 쓰이는 문자열이지만 fIDBAC.pl은 완전한 종명을 원한다.


어쩌겠는가? 완전한 종명 체계로 pubMLST를 다운로드해 주는 유틸리티를 찾아 보아야 한다. 검색 끝에 Sanger Institute에서 개발한 mlst_check라는 것을 발견하였다. 설치는 쉽게 하였으나 역시 SSL 인증서 문제로 직장 내 전산망에서는 다운로드 명령('download_mlst_databases')이 먹히질 않았다. 이를 우회하는 가장 간단한 방법은 노트북 컴퓨터로 집에서 설치한 뒤 직장으로 가지고 나와서 복사하는 것이다. 

이제 fIDBAC이 잘 실행되겠지... 그러나 이는 잘못된 기대였다. T. Seemann의 mlst 명령을 이용한 것과 Sanger의 mlst_check를 이용한 것은 종명 서브디렉토리뿐만 아니라 그 하위의 파일 구조도 다르다는 것을 발견하였다. Salmonalle enterica의 예를 들어 보자.

  • T. Seemann의 스타일: senterica 디렉토리 하위에 aroC.tfa  dnaN.tfa  hemD.tfa...의 파일이 있음
  • Sanger의 스타일: Salmonella_enteria 디렉토리 하위에 profiles/profiles_csv와 alleles/alleles_fasta 두 개의 파일이 있음. 이는 fIDBAC에 의해 쓰이기가 곤란하다. 왜냐하면 '$mlstlist = glob "$pubMLSTdb/$species/*.txt'라는 코드를 상기해 보라.
지금까지 테스트한 바에 따르면, T. Seemann 스타일로 다운로드하되 종명 디렉토리를 Salmonella_enterica로 바꾸어 놓은 것만 제대로 결과를 내었다. 어느 것이 더 바람직한가? (1) T. Seemann 스타일로 다운로드한 뒤 senterica => Salmonella_enterica로 디렉토리명을 바꾸는 것과, (2) Sanger 스타일로 다운로드한 뒤 alleles_fasta 파일을 처리하여 각 유전자별로 aroC.tfa  dnaN.tfa... 파일을 만드는 것. 종명과 그 약자를 연결한 파일이 있다면 (1)의 작업은 아주 쉬울 것이다. 그러나 이는 간편한 텍스트 파일이 아니라 XML로 주어진다. 

이 문제를 해결한 뒤에도 복수의 scheme이 존재하는 종이라든가(예: Acinetobacter_baumannii_1 & Acinetobacter_baumannii_2), spp로 끝나는 scheme을 fIDBAC이 제대로 처리할지는 의문이다.

여기까지 적고 나니 회의감이 밀려온다. 내가 지금 월 하고 있는거지?

회의감을 정리하는 도중 또 경악을 금치 못할 일을 발견하였다. run_MLST.pipeline.pl 스크립트가 pubMLST가 지정된 위치를 별도로 지정하여 사용하는 것이다! config_db.txt는 어디다 갖다 버리고!

2021년 11월 24일 수요일

fIDBAC 실행용 펄 스크립트의 use compiler directive 선언 오류, 그리고 플러스 알파(+베타, 감마...)

fIDBAC(어제 작성한 소개의 글 링크)에서 오류를 찾는 것이 취미가 될 수준에 이르렀다. 나는 파이썬에는 까막눈이지만 Perl은 조금 아는 편이라서 fIDBAC의 주요 스크립트를 뜯어보는 수준은 된다. 메인 스크립트는 fIDBAC.pl이다.

fDIBAC.pl을 처음 실행하게 되면 GACP.pm 모듈을 인식하지 못한다는 에러가 발생한다. 

Can't locate GACP.pm in @INC (you may need to install the GACP module) (@INC contains: ...)

스크립트의 위치로 이동하여 실행을 하거나, 혹은 PERL5LIB 환경변수를 스크립트가 위치한 곳으로 선언하면 일단은 에러가 없어진다. GACP.pm은 config_db.txt 설정 파일을 읽어들여서 중요한 프로그램과 파일을 변수로 저장하는 역할을 한다.

왜 이런 사소한 오류가 뜨는 것일까? fIDBAC.pl 스크립트의 시작 부분을 확인해 보았다.

#!/usr/bin/perl -w
#author:liangq at 20181126 ,modified by liangqian ,at 20181206
use strict ;
use Getopt::Long ;
use Cwd 'abs_path';
use File::Basename ;
use File::Path 'mkpath';
use FindBin '$Bin';
use Data::Dumper;
use List::Util qw/max min/;
use lib $Bin;
use threads;
use GACP qw(parse_config);

특별한 문제는 없다. FindBin을 이용하여 원본 펄 스크립트의 위치를 찾아서 $Bin 변수에 저장하고(작은 따옴표로 둘러싼 것은 별로 마음에 들지 않음), 이어서 use lib $Bin 디렉티브를 선언했으니 펄 스크립트가 있는 디렉토리를 @INC의 맨 앞에 추가한 셈이 된다. 그리고 가장 마지막에서 use GACP를 선언하여 GACP.pm 모듈을 선언하였다. 훌륭하다!

그런데도 여전히 같은 에러가 발생하였다. GACP.pm을 로드하는 스크립트가 또 있나? fIDBAC.pl에 의해 내부적으로 구동되는 다른 스크립트 중에서 select_kmerfinder_16SAndANI.pl와 AR_VF.run.pl도 GACP.pm을 필요로 한다. 스크립트에 오타 같은 것은 없는데 왜 에러가 사라지지를 않는 것일까...

이런! select_kmerfinder_16SAndANI.pl 파일을 열어보니 'use lib $Bin' 라인이 없었다. 무슨 이런 실수를... 개발자는 항상 스크립트 설치 디렉토리에서만 테스트를 했단 말인가? 수준 이하의 오류를 찾아내어 수정하느라 인생을 낭비하는 것만 같아서 이제는 서글프기까지 하다. 빠진 라인을 삽입하였더니 이 오류는 사라졌다.

그러나 아직 끝이 아니다. 

  1. run_rgi.sh가 호출하는 format_RGIresult.pl는 도대체 GitHub 사이트 어디에 숨어 있는가?
  2. config_DB.txt에서 'orthoANI'라는 이름으로 부르는 프로그램은 도대체 무엇을 의미하는가? 내가 발견한 fIDBAC 파이프라인의 문제점 중 가장 심각한 것은 바로 여기에 있다. 
orthoANI의 문제를 좀더 상세하게 알아보자. config_DB.txt 파일을 열어보면 orthoANI는 ANI.pl 펄 스크립트를 지정하는 것으로 보인다. 그러나 OrthoANI라 하면, 보통은 천랩에서 개발한 ANI 계산용 알고리즘을 뜻한다. 이 알고리즘을 프로그램으로 구현한 것은 자바 애플리케이션인 OAT(Orthologous Average Nucleotide Identity Tool)이다. 'ortho-'라는 접두사를 붙여서 불필요한 혼동을 불러 일으키고 있다. 이것이 (2)에 따르는 첫 번째 문제이다.

ANI.pl은 원래 Jaipeng Chen이라는 사람이 JSpecies(GUI Java application)를 참조하여 legacy blast + Perl로 만든 ANI 계산용 스크립트이다(GitHub). 9년 전에 업로드된 상태 그대로 수정되지 않았다. fIDBAC의 script/Average_Nucleotide_Identity/readme.txt 파일에서도 이 GitHub를 인용하고 있으니 내 예상이 틀리지는 않을 것이다. ANI.pl이 호출되는 순서는 다음과 같다.

fDIBAC.pl(main script) -> OrthoANI.all_tre.new.py -> orthoAni.sh라는 스크립트를 실행 단계에 작성하여 활용함

OrthoANI.all_tre.new.py에서 orthoAni.sh 파일을 작성하기 위하여 다음과 같은 문자열을 만들어 ANI.pl을 실행하도록 만드는데, 이게 또 이상하다. 


ANI.pl의 필수 옵션인 '-fd formatdb -bl blastall'이 빠진 상태이다.  이 옵션은 formatdb와 blastall 실행 파일을 지정하기 위한 것이다. $PATH에 위치한다고 하여 생략해서는 안 된다. 따라서 그림에서 보인 cmd로는 ANI.pl이 제대로 실행되지 않는다. 이것이 두 번째 문제이다. 그러면 cmd를 조합하는 명령어 라인에 '-fd formatdb -bl blastall'을 삽입하면 되지 않을까 생각할 수 있다. 그러나 전혀 그렇지 않다. ANI.pl은 출력 파일을 쓰지도 않고, 오로지 표준 출력에 두 genome으로부터 계산한 ANI 수치를 표시할 뿐이다 OrthoANI.all_tre.new.py 스크립트의 후반부를 보면 ANI 수치 쌍을 전부 조합하여 하나의 OrthoANI.txt 파일을 만드는 것으로 되어 있는데, 내가 알고 있는 ANI.pl의 출력 형식으로는 이를 어떻게 만드는지 이해하기 어렵다. 이것이 세 번째의 문제이다.

full_path_to_file_1 VS full_path_to_file_2
 ANI: 93.0621988037596

세 번째 문제의 해결을 위해서 지금까지 미루어 두었던 파이썬 공부를 시작할 용의가 있다. 지금이 아니라면, 앞으로 영원히 파이썬 문맹으로 남게 될지도 모른다.

2021년 진공관 앰프 제작을 위한 정보 수집

세상은 넓고 고수는 많다. 인터넷을 뒤져서 단편적으로 얻은 지식에 내 생각을 약간 달아서 블로그에 적는다고 하여 세상의 지식이 늘어나는데 보탬이 될 일은 없을 것이다. 그저 내 기억력을 보조하기 위한 수단으로 기록을 할 뿐이다.

지금까지 예닐곱대의 진공관 앰프를 다루어 보았다. 여기에는 외부에 제작을 의뢰한 것, 알리익스프레스에서 완제품으로 구입한 프리/헤드폰 앰프가 전부 포함된다. 완성품 보드를 구입하여 주변 부품만 붙인 것도 있고, 빈 PCB만 구해서 부품을 손수 납땜하여 만든 것도 있으며(6LQ8 PP & SE), CAD를 이용한 상판 설계와 point-to-point wiring으로 전 과정을 만든 것도 있다. 매우 낮은 출력이지만 푸시풀 앰프도 있었다.

내년에는 '제대로 된' 푸시풀 앰프를 point-to-point 결선 방법으로 만들고 싶다. 기왕이면 고정 바이어스 회로를 채택하여 서로 매칭이 되지 않은 출력관이라 하더라도 무난하게 쓰도록 만들자는 목표를 삼아 보았다. 아직 출력관은 정하지 않았다. 갖고 있는 PCL86을 그대로 쓸 수도 있고, EL84나 6V6도 고려 대상에 들어간다. EL84 또는 6V6은 완제품 혹은 반제품 형태의 PCB가 알리익스프레스 등에 흔하게 팔린다. 이걸 그대로 사서 쓴다면 만드는 재미는 반감될 것이고, 바이어스 조정도 힘들어진다.

푸시풀 앰프를 만드는데 필수적인 요소인 위상분리기(phase splitter) 또는 위상반전기(phase inverter)의 작동 원리를 이해하는 것도 어렵지만, 요즘은 고정 바이어스 공급 회로의 오묘함에 더욱 매력을 느끼는 중이다.

필요한 정보를 찾아서 목록으로 만들어 보았다. 특히 세상에 없던 6LQ8 사용 오디오 앰플리파이어가 자작인들을 통해서 2010년대 중반에 등장하게 되었으므로 그 개발 뒷이야기를 알아두는 것이 유익할 것이다.

[제이앨범] 작업실 > 앰프 자작 > 11LQ8/6LQ8 카테고리의 모든 글

[6LQ8 PP 관련 회로도 자료]  

[다음 블로그: 끝없는 여정] 6V6 푸시풀 파워앰프 - 회로도

[소리전자] PCL86 PP ('시나브로') PCB형 인티앰프 일반형 부품키트 - 회로도 참고용. 어떤 타입의 위상분리회로를 쓴 것인지 상당히 헷갈린다.

[Franz Wichlas] 4 x PCL86-PP - Amp - Jogis Röhrenbude의 웹사이트에 게시됨

[DIY Audio] New build of P-P PCL86 Amp - 로그인 필요. 회로도는 맨 아래 포스팅 참조

[DIY Audio] PC86 - Worth a try?

[The Tube CAD Journal] Phase splitters

[The Bona's HomePage] Phase Splitter - 매우 간결하게 설명을 잘 하였다. 이에 의하면 제이앨범이 디자인한 6LQ8 PP 앰프는 cathodyne phase splitter를 사용한 것이다.

[Audio Asylum] ECC802S SRPP / EL84(6BQ5) Push-Pull Amplifier - 25R 가변저항을 이용하여 두 출력관 사이의 바이어스 전류 균형을 맞춘다. 이런 용도로 사용할 가변저항의 와트 수는 어느 정도가 적당할까? 예를 들어 이런 제품의 규격은 0.5W이다. 2W를 견디는 다회전 볼륨은 훨씬 비싸다.

[Atra-Audio] PP Fixed Bias circuit design and calculator

[The Valve Wizard] Bias Supplies

[VTADIY: Vacuum Tube Amplifiers DIY] 5.3 Power supply for the fixed grid bias of a vacuum tube amplifier

2021년 11월 23일 화요일

fIDBAC: A Platform for Fast Bacterial Genome Identification and Typing 공부하기

유전체 서열 정보를 이용한 미생물 균주의 정확한 동정은 기초 생명과학과 감염병 관련 연구 분야에서 매우 중요한 일이다. 종(species) 또는 더 세분화된 수준으로 균주를 동정하거나 - 후자를 보통 타이핑(typing)이라고들 한다 - 유전체가 보유한 항생제 내성(AMR, antimicrobial resistance) 및 병원성 인자(VF, virulence factor)를 예측하는 것도 중요하다. 만약 유전체 해독을 실시한 미생물 균주가 쓸모있는 이차대사물을 만들어내는 것 같다면, 이를 책임지는 유전자 클러스터를 예측하는 것도 필요하다.

이러한 분석을 한꺼번에 실시하는 '입맛에 딱 맞는' 파이프라인은 아직 눈에 잘 뜨이지 않는다. 다만 병원성 미생물의 동정과 관련된 도구들은 가끔씩 눈에 보여서 이를 설치하고 테스트하면서 나름대로 평가를 하고 있다.

Frontiers in Microniology에 최근 공개된 fIDBAC라는 분석 플랫폼을 요즘 열심히 테스트하고 있다. fIDBAC는 면밀한 검토를 거쳐서 작성된 type strain 유전체 DB(N=12,784; 전체 목록은 12784.genome.txt를 참조)을 바탕으로 하여 미지의 유전체가 주어졌을 때 이것이 어떤 종에 속하는지를 정확히 판별해 주는 것을 목표로 한다.

다음 그림은 논문에서 제공한 graphical abstract이다.
fIDBAC의 프레임워크. 출처 링크
fIDBAC 개발에서 가장 심혈을 기울인 것은 type strain의 유전체 DB curation이었을 것이다. 논문을 보면 NCBI에서 균주의 source에 대한 정보를 참고하여 유전체 정보를 수집한 뒤, LPSN과 Bergey's Manual 및 IJSEM 논문을 참고하여 입증된 종명 및 type strain 정보를 완성했다고 한다. 이명(synonym) 정보를 정리하는 수고스러운 작업도 포함하였다. 

여기까지는 이름이 제대로 되어 있는지를 점검하는 것에 지나지 않는다. 다음 단계에서는 해당 균주의 유전체가 얼마나 온전한지를 확인하는 것이 필요하다. CheckM으로 점검하여 contamination이 5%를 넘거나 completeness가 90% 미만인 것은 버리고, 16S rRNA sequence를 추출하여 LTP database와 비교하여 genus level에서 불일치하는 것은 제외하였다.  

SILVA, RDP, GreenGenes DB는 많이 들어 보았지만 LTP('The All-Species Living Tree' Project)는 생소하여 검색을 해 보았다. 이곳에서 LTP의 상세한 연혁 소개와 함께 다운로드 기능도 제공한다. 앞서 소개한 잘 알려진 ribosomal RNA database가 있음에도 불구하고 LTP가 별도의 프로젝트로서 존재해야만 했던 이유가 있었을 것이다.

큐레이션의 마지막 단계에서는 모든 유전체에 대한 pairwise ANI 계산을 실시하여 동일한 종명을 갖는 것끼리를 클러스터링하였다. 여기에서는 SciPy 파이썬 패키지를 사용하였다고 한다. 이렇게 만들어진 type strain의 유전체 염기서열은 KmerFinder를 통해서 k-mer (다운로드 링크)DB로 변환하였다. KmerFinder에 대한 상세한 정보는 관련 논문을 참조하라.

Reference DB 구축이 완료되었으니, 이를 활용하여 query genome을 동정하는 방법을 수립하는 것이 fIDBAC platform의 나머지 절반 과정이 되겠다. 메인 스크립트(fIDBAC.pl)을 통해서 작동 순서를 알아보면 다음과 같다. 이는 논문에서 소개한 순서와는 조금 다르다.

  1. Reference genome의 k-mer DB에 대하여 검색 실시(findTemplate without -w). 결과 파일은 $sample.out.txt이다. 
  2. Genome annotation 실시(prokka) 후 16S rRNA와 유전자 서열 추출. 아미노산으로 번역한 유전자는 항생제 내성 및 병원성 인자를 탐색하는데 쓰임(AR_VF.run.pl)
  3. 16S rRNA에 대한 검색 및 fastANI를 이용하여 query genome의 종 동정 정보를 fastANISpecies라는 파일에 한 줄로 출력. 이것은 select_kmerfinder_16SAndANI.pl 스크립트를 통해서 이루어지는데 내부 구조가 좀 난해하다. [1]번 과정의 결과 파일($sample.out.txt)로부터 top1/3/10/20의 목록을 취한다. 최고 스코어를 보이는 genome이 3개라면 top1 목록은 세 줄이 된다. FASTA file 이름으로부터 목록 파일을 참조하여 taxonomic name을 얻는 과정이 꽤 된다. 16S rRNA 서열은 16S.V3.fa(관련 파일은 전부 여기에 있음; 이것이 LTP3132_SSU에서 유래한 것으로 추정됨)에 대하여 blastn을 실행하여 top 20을 얻은 뒤, local FASTA file에서 hit에 해당하는 것을 찾아 놓는다. fastANI에 계산에 투입되는 top 20은 16S 분석과 KmerFinder에서 얻어진 top genome을 추려서 얻어지는 것이 아닐까 생각하는데, Perl 스크립트를 뜯어보면서 정말 그러한지를 확인하지는 못하였다. 논문에서는 "The top 20 closest species were extracted from the results of the above-mentioned methods(즉 16S rRNA 서열 분석과 k-mer 분석)."이라고 하였으니 두 가지 결과를 종합하는 것이 맞을 것이다. 단, 두 가지 분석을 통해 얻어진 top 20 closest genome 안에서 종명이 consistent하지 않은 것이 섞여있을 경우 어떻게 처리하는지는 아직 잘 모르겠다.
  4. OrthoANI.all_tre.new.py 스크립트를 사용하여 ANI.pl 실행. 이 Perl wrapper script는 엄밀히 말해서 천랩이 개발한 OrthoANI와는 다른 것인데 왜 이런 이름으로 부르는지를 모르겠다. 이 wrapper script는 아직 잘 작동하지 않는 것 같다. 왜냐하면 주요 결과 파일인 OrthoANI.txtd와 ANI.all.txt가 빈 상태이기 때문이다. 왜 그런가 추적을 해 본 결과 이유는 너무나 허무한 곳에 있었다. OrthoANI.all_tre.new.py 스크립트 내부에 ANI.pl의 경로가 지정되어 있었다. 아니, config_db.txt 파일은 뭐하러 만들었단 말인가? 부글부글...
  5. ANIcaculator를 사용하여 gANI 계산. 유전자는 prokka가 만든 것을 이용한다. Step [4]와 [5]의 상호 연관성은 아직 파악하지 못하였다. ANI > 95%인 것만을 선별하는 것은 fastANI 레벨인가, gANI 레벨인가?
  6. MLST analysis
  7. SNP and MST analysis
  8. ....어휴!
스크립트를 뜯어보면서 작동 순서를 정리하려다가 머리에 쥐가 날 지경이 되었다. 이 목록은 앞으로 시간이 나는대로 틈틈이 업데이트를 해 보겠다. fIDBAC을 로컬 머신에 설치하면서 약 이틀 이상을 삽질(?)한 것을 생각하면 저절로 주먹에 불끈 힘이 솟는다. 설명은 너무나 부실하고, 필수 스크립트가 GitHub 사이트에 빠져 있고, 일반적인 tab-delimited file을 .xls 파일이라 부르는 등 사용자로서는 다소 과격한 의견이 되겠지만 프로그램 배포의 기본을 갖추고 있지 못하기 때문이다. MSTgold(MST for 'minimum spanning trees') 프로그램도 설치해야 fIBAC이 돌아가는데, 전혀 설명이 없다. 

아주 작은 사례를 보자. 사용자가 직접 수정해야 하는 config_db.txt 파일을 제공하고 있기 때문에 이것만 고치면 fIDBAC.pl 스크립트가 돌아갈 것으로 착각하기 쉽다. 그런데 엉뚱하게도 개별적인 스크립트 안에는 필수 프로그램들이 다른 경로로 지정되어 있는 것이 아닌가. 그것도 개발자 환경의 full path로 말이다. 테스트 러닝을 하면서 실행이 안되는 프로그램을 찾아 스크립트 내부를 수정하고, 또 실행 후 수정을 반복하고... 몇 차례의 시행 착오를 거쳐서 최초의 결과물을 손에 쥘 수 있었다. 그리고 본 블로그에서 자세히 설명하지는 않았지만, fIDBAC 개발자가 제시한 12,784 유전체 염기서열을 GenBank에서 다운로드하는 것도 다소 번거로왔다. 개발자는 accession number만 제시했을 뿐, 분석 과정에 필요한 유전체 및 유전자 염기서열을 따로 준비하여 목록 파일을 만들어 두어야 한다. 목록 파일(샘플)을 만드는 설명도 부실해서 애를 먹었고, 이들이 제시한 유전체 중 이미 수십 개는 GenBank에서 탈락하거나 업데이트된 것이 있어서 이를 다시 찾아야 한다. Genome assembly의 업데이트는 GCA_#########. 1뒤의 숫자가 하나 증가하는 것(1 -> 2)으로 표현되는 것도 있으나. 어떤 것은 아예 다른 accession no.로 대체되는 것도 있어서 이를 파악하려면 수작업에 의존하지 않을 수가 없었다.

이렇게 불평을 하기에 앞서서 과연 나는 다른 연구자들에게 도움이 될 수준의 완성도를 갖춘 스크립트를 공개한 적이 있었나? 블로그를 통해서 팁 수준의 짤막한 코드 조각을 이따금씩 올렸을 뿐이다. 남을 비판하기에 앞서서 나부터 반성을 하자.

논문으로서는 좋은 설계 개념을 제시하였지만 프로그램을 가져다 쓰려는 사람에게는 불편한 것이 사실이다. 그런 사람을 위하여 웹사이트를 구축해 놓았으니 꼭 필요한 사람은 이를 사용하면 된다. 앞으로 신종 박테리아는 계속 나올 것이고, 이를 얼마나 충실하게 업데이트를 할지는 지켜보아야 할 일이다. 업데이트는커녕 2년 정도 유지되다가 슬쩍 사라지는 웹사이트도 많이 있기 때문이다.

치명적인 약점(?) 또는 개선할 점을 생각해 보았다. 우선 archaea는 레퍼런스 DB에 전혀 반영되어 있지 않다는 점을 들고 싶다. Archaea는 인체에 병을 일으키는 것이 없다고는 하지만, 일반적인 species 동정을 목적으로 fIDBAC을 이용하려는 사람에게는 치명적인 단점이다. 만약 고균을 포함한다면 fIDBAC은 fIDBAAC(...Bacterial and Archaeal...)이 되어야 할 것이다. k-mer DB는 보다 현대적인 Mash 기반 DB로 바꾸는 것이 바람직할 것이다. 12,000개 정도의 유전체 서열을 다운로드하여 k-mer DB(maketemplatedb 명령)을 어젯밤부터 실행했는데 아직 400개도 진행을 하지 못했다. 파이썬 2.7을 써야 하고(버전 3에서 작동하도록 고쳤다는데 잘 안됨), 다중 쓰레드도 쓰지 못하니 너무나 답답하다.

그래도 fIDBAC을 뜯어보면서 얻은 성과가 있다면 ReadSeq이나 phylip 등 고전적인 프로그램을 다룰 기회가 생겼다는 점이다. 








2021년 11월 17일 수요일

43 오극관 싱글 앰프의 개선 작업 마무리

전원 트랜스포머의 교체 및 B+ 전압 조정 작업이 얼추 끝났다고 생각하고 음악을 듣는데, 좌우 채널 전체에서 '버석 버석'하는 소리가 들리기 시작했다. 접촉 불량인가, 새로운 타입의 발진인가? 또다시 좌절감에 휩싸였다. 겨우 쌍삼극관(6N2P) 하나와 핀이 6개 달린 구형 power pentode 두 개를 가지고  점대점 결선(point-to-point wiring, 나는 하드 와이어링이라는 표현이 옳지 않다고 믿음)으로 만든 싱글 앰프 하나를 제대로 못 만들다니! 내가 X손이라니!

앰프를 뒤집어 놓고 이곳 저곳을 건드려 보았다. B+ 전원 공급을 위해 새로 만들어 넣은 기판을 움직일 때 이에 맞추어 잡음도 같이 발생하는 것을 눈치챘다. 만능기판에 납땜한 스크류 터미널의 접촉이 아무래도 문제인 것 같았다. 나사를 풀고 기판의 동박에 납땜으로 직결을 하였더니 잡음이 사라졌다.

차폐용 커버가 없는 일반(오디오용이 아닌) 전원 트랜스포머를 쓰게 되면서 전원부에서 유도되는 잡음이 이전보다는 약간 늘어난 것 같았다. 리플 제거 보드를 사용함에도 불구하고 험이 들린다는 것은 몹시 자존심이 상하는 일이다. 전원을 넣으면 전원 트랜스 자체에서도 미약하나마 울리는 소리가 난다. 아마도 유도 잡음을 유발하는 부품의 배치 문제일 것으로 여겨진다. 실용상으로는 별 문제가 없으므로 당장은 그냥 쓰기로 하였다.

잡음의 원인을 찾는답시고 출력관을 좀더 상태가 좋은 실바니아 것으로 바꾸어 끼웠다.
대단한 것을 이룬 것은 아니지만 진공관 앰프의 기본에 대하여 이해도를 높인 좋은 계기가 되었다고 생각한다. 아직도 앰프를 뒤집어 놓고 보면 손을 대고 싶은 곳이 한두 군데가 아니다. 하루 아침에 해결될 문제는 아니다. 빨리 끝내려고 할 일이 아니라 과정을 즐기는 것, 그것이 진정한 아마추어의 자세이자 특권이 아닌가 싶다. 

아마추어는 과정을 즐기고, 프로는 결과로 말한다.

2021년 11월 16일 화요일

Roary 'query_pan_genome'의 고약한 출력물

Roary: the Pan Genome Pipeline은 내가 밥 먹듯이 즐겨 사용하는 프로그램이다. 최신판은 2019년 11월 6일에 릴리즈되었으니 더 이상 개선의 여지도 없는 프로그램이 아닐까 한다. MUMmer와 같이 거의 수정도 거치지 않으면서 오랜 기간 사랑받는.

Roary의 부속 유틸리티인 query_pan_genome은 두 그룹 간의 교집합, 합집합, 또는 차집합에 해당하는 gene cluster를 추출하는 다재다능한 프로그램이다. 그룹 정보는 GFF 파일로 제공하면 된다. 예를 들어 그룹 one에는 있지만 그룹 two에는 없는 유전자를 찾고 싶다면, 다음과 같이 실행하면 된다.

$ query_pan_genome -a difference --input_set_one 1.gff,2.gff --input_set_two 3.gff,4.gff,5.gff

만약 각 그룹을 구성하는 GFF 파일이 많다면 명령행에 이를 일일이 타이핑하기가 곤란할 것이다. 그런 경우에는 fofn(file of file name)을 만든 뒤 paste 명령을 써서 쉼표를 사이에 두고 이어 붙이면 된다.

$ cat one.fofn
1.gff
2.gff
3.gff
$ one=$(paste -sd, one.fofn)

두 그룹에 대하여 이렇게 변수를 만든 다음, '--input_set_one $one'과 같은 형식으로 옵션을 주면 된다. GFF 파일이 현재 디렉토리에 없다면, fofn을 만들 때 find 명령어를 잘 이용하면 된다.

'query_pan_genome -a difference' 명령을 수행하면 'set_difference_'로 시작하는 11개의 파일이 생긴다. 그룹 one에만 있는 유전자에 대한 정보는 다음의 파일에 수록된다.

  • set_difference_unique_set_one
  • set_difference_unique_set_one_reannotated
  • set_difference_unique_set_one_statistics.csv
여기서 한 가지 주의할 것이 있다.  그룹 one에만 있는('unique') 유전자란, 그룹 one의 모든 멤버에 다 있는 것만을 포함하는 것이 아니다. 예를 들어 그룹 one이 10개의 균주(A, B, C ... J)로 이루어졌다고 하자. 그러면 set_difference_unique_set_one에는 A에만 있는 것, A와 B에 있는 것 등 별의별 녀석들이 다 섞여 있다. 만약 그룹 특이적인 유전자를 찾는 것이 목적이라면, A부터 J까지 모든 멤버에 다 있는 것을 파악해야 한다. 그러려면 위에서 나열한 세 개의 결과 파일 중 set_difference_unique_set_one_statistics.csv를 참조해야 한다.

여기에서 문제가 발생한다. 바로 gene ID가 바뀐다는 것이다. set_difference_unique_set_one의 첫 번째 컬럼은 Roary 실행 결과 파일에서 보편적으로 쓰이는 unique cluster ID를 유지하지만(cluster는 accessory gene도 포함, 즉 pan genome을 전부 아우름), set_difference_unique_set_one_reannotated에서는 GFF 파일을 참조하여 일부가 gene name으로 바뀌고, 이것이 set_difference_unique_set_one_statistics.csv로 그대로 전달된다.

실제 사례를 들어 보자. 오늘 아침에 query_pan_genome 스크립트로 Strepcococcus genus에 속하는 두 종(N=301, set one은 232개, set two는 69개)의 roary 결과를 투입하여 13683개의 set one-specific gene을 얻었다. 그런데 gene ID를 sort하여 uniq 명령어를 통과시키면 13553개만 남는다. reannotated gene ID에서 중복이 발생했다는 뜻이다.

set_difference_unique_set_one과 set_difference_unique_set_one_reannotated 파일의 나머지 컬럼에는 실제 이를 구성하는 유전자들의 ID가 있으니 그룹 자체를 건드리지는 않는다. 그러나 pan_genome_reference.fa 파일에서 set one에 특이적인 유전자(대표 서열로서)를 찾으려면 여간 번거로운 일이 아니다.

query_pan_genome 스크립트를 전혀 쓰지 않고 roary의 기본 결과 파일인 gene_presence_absence.csv를 R에서 조작하여 각 그룹 특이적인 유전자를 찾을 수는 있는데 여간 성가신 일이 아니다. 왜 query_pan_genome 스크립트는 다시 annotation을 하여 식별자를 유일하지 않은 것으로 만들어 버리는지 알 수가 없다. QueryRoary.pm를 내가 고칠 수 있는 수준의 일도 아니고...