2021년 5월 31일 월요일

다시 반도체 앰프에 대한 흥미를 갖다

어제 B&W DM10 스피커를 들여온 사건(글 링크)와는 관계없이 며칠 전부터 반도체 앰프에 관한 정보를 뒤적이고 있었다. 왜 그렇게 되었는지는 잘 기억이 나지 않는다. 그것도 일반 가정용 하이파이 앰프가 아니라 스튜디오 모니터 앰프에 관해서 말이다.

고통스런(?) 검색이 무엇에서 시작된 것일까? 길어야 열흘 전부터였는데, 직접적인 계기가 무엇이었는지 잘 생각이 나지 않는다.

아마도 소출력 진공관 싱글 앰프에 너무 많은 것을 기대하지 말자는 생각이 들면서 그리 되었던 것 같다. 진공관 앰프에 대한 막연한 호기심으로 만들기 쉬운 소출력 싱글 앰프부터 접근하게 되고, 출력이 작으니 이를 잘 울리기 위해 고능률의 스피커를 장만해야 할지도 모른다는 압박감에 시달리고...

맨 위의 사진에서 보인 TDA7265 앰프는 스펙상으로는 15와트 미만의 출력에서 0.1% 미만의 의율을 나타내는 준수한 증폭용 칩이다. 직접 만든 케이스가 외관상 영 허름하여 즐겨 쓰지는 않았지만, 내가 보유한 스피커를 울리기에 부족함이 없다. 여기에 버퍼 프리앰프부를 다는 것이 음질의 현격한 개선을 가져다줄 것으로 생각하지는 않지만, 알루미늄 케이스에 얼기설기 만들어 놓고 쓰지 않는 것보다는 나을 것으로 생각한다. 

TDA7265 앰프의 케이스를 열어 보았다. 전원 트랜스와 주기판의 위치를 조금만 옮기면 프리앰프 기판이 들어갈 자리는 충분히 나온다. 실은 플라스틱 케이스라서 접지가 붙은 파워 케이블을 꼭 써야 할 이유도 없다.

TDA7265 앰프에 프리앰프 보드를 합쳐 버리기로 결정을 내렸다. 만들고 다시 부수어서 다른 곳에 넣고... 자작이란 원래 그런 것이다!

이 앰프만으로도 충분히 집이 떠나갈듯한 음량으로 소리를 낼 수 있다. 보유 중인 진공관 앰프로는 아무래도 부족한 것은 사실이다. 그렇지만 채널당 50와트 정도를 내는 레퍼런스급(고급을 의미하는 것은 아님)의 앰프는 하나 있어야 되겠다는 생각이 머리를 떠나지 않는다. 과거 가정용 오디오의 표준적인 제원이 그러하지 않았던가?

인터M의 공식 제품 라인업에서는 사라졌으나 아직 신품을 구할 수 있는 R150PLUS라는 앰프가 관심 대상이다. 스테레오 모드로 8옴 스피커를 연결하여 작동시키면 50W+50W의 출력이 나온다. 모델명에서 R은 'Reference'를 의미한다. 조금만 검색을 하면 중고품을 얼마든지 찾을 수 있다. 실제로 가정용 앰프 대신 이런 것을 쓰는 사람들이 꽤 있는 것으로 안다. 단독주택이라서 앰프의 음량을 올리는 것에 제한이 없다면 매우 적당한 물건이다.

요즘 블루투스나 MP3 재생, 라디오 수신 등 다양한 기능을 갖춘 중국제 저가 앰프가 무척 많이 유통되고 있다. Class D 증폭 소자를 채용하여 무게도 얼마 나가지 않는다. 그런데 이런 것은 별로 고르고 싶지가 않다. 이런 것을 쓰느니 위의 사진에서 보인 앰프 보드 - 게인클론 부류의 것이라면 더 나을 것임 - 중 좋은 부품을 쓴 것을 골라서 직접 만드는 것이 나을 것이다. 그러나 출력을 수십 와트 수준으로 끌어올리고 싶다면 견고하고 단락 등 만약의 사태에 대비한 준비가 잘 되어 있는 스튜디오 모니터용 앰프 또는 공연용 앰프를 적당히 구해서 쓰는 것도 나쁘지 않을 것이다. 물망에 올랐던 다른 앰프는 Berhinger의 A500이나 Europower KM750 등이 있었다.

이런 앰프를 쓰려면 밸런스 입력을 위하여 콘솔 믹서(아, 왜 팔았지...)를 쓰거나 그런 용도로 만들어진 케이블을 써야 한다. 공연장처럼 케이블을 길게 뽑지 않는 가정에서 무슨 이런 물건이 필요할까 생각할 수도 있으나 '소리 만들기'의 기본을 공부하기에 좋은 장비인 것은 사실이다.

RefSeq Masher, 편리한 것은 좋은데...

RefSeq Masher는 Mash MinHash 기법을 이용, 내가 갖고 있는 시퀀싱 데이터가 54,925개의 RefSeq Genome 중 어느 것에 해당하는지를 찾아주는 유틸리티이다. Mash를 직접 쓰는 것에 비하면 훨씬 편리하다. 문제점은 Mash sketch DB가 좀 오래되었다는 점이다. 오늘 날짜로 RefSeq에서 박테리아의 assembly summary file을 받아 보니 216,709 줄이나 된다. 첫 두 줄은 코멘트이므로 제거한다 해도 RefSeq Masher가 제공하는 기본 DB의 거의 4배가 된다. 게다가 bacteria 이외의 것은 아직 확인해 보지도 않았다. 최신 유전체 자료를 이용하여 custom Mash sketch DB를 만든다 해도 문제가 해결되지는 않는다. RefSeq Masher는 distance를 계산한 결과를 다시 'ncbi_refseq_taxonomy_summary.csv'라는 파일과 연결하여 taxonomy를 뽑아내는 것으로 끝을 맺기 때문이다. Custom DB를 만들어 봐야 taxonomy 파일까지 준비하지 않으면 소용이 없다. RefSeq Masher의 개발자들도 아직 여기까지는 신경을 쓰고 있지 않은데 내가 아쉬워하는 것이 무슨 의미가 있을까 싶다.

검색을 거듭해 보니 Mash의 공식 매뉴얼 문서(PDF)에서는 RefSeq release 88로 만든 sketch DB를 제공하고 있음을 확인하였다. 그러나 언제적 release인가! RefSeq의 가장 최근 배포판은 5월 27일, 그러니까 4일 전에 배포된 Release 206이다.

54,925개의 genome이 포함된 RefSeq은 언제적 release일까? 이것이 RefSeq 88보다 예전 것임은 명백하다. 왜냐하면 파일 사이즈가 94M와 1002M로 크게 차이가 나기 때문이다.

2년 정도 주기로 누군가에 의해 RefSeq Mash sketch DB가 만들어져서 세상에 공개된다면 참 좋을 것이다. KRAKEN2처럼 말이다. 안타깝게도 custom DB를 만드는 방법은 매뉴얼에서 확인하기 어렵다. Minikraken2의 2019년 4월 업데이트는 메모리에 올라가는 용량(8G)에 대해서만 강조하고 있을 뿐, 몇 건의 genome sequence로부터 만들어진 것에 대해서는 자세히 적어 놓지를 않았다. 

Mash의 예전 문서에서 Building a custom RefSeq database라는 섹션을 찾기는 했지만 이대로 따라서 할만 한 일인지 확신이 서지 않는다... Mash 1.0 documentation에는 존재하다가 지금은 사라진 이유가 있을 것이다. 

B&W DM10 스피커를 들여놓다

처남이 중고로 구입하여 사용하던 B&W DM10 스피커를 둘 곳이 마땅치 않아 그냥 주겠다고 하여 서울에 다녀오는 김에 잠시 들러서 차에 싣고 왔다. 그냥 받아 오기는 미안하여 카카오톡으로 아이스크림 기프티콘을 하나 보내 주었다.

음악과 오디오를 좋아하면서도 정작 유명한 오디오 기기 브랜드는 잘 알지 못한다. B&W라... Bowers & Wilkins(위키백과, 현 웹사이트)의 약자로서 영국 브랜드이다. 영국 스피커 회사라면 탄노이, 하베스, 로더 정도만 겨우 아는 수준이었다. 구글을 뒤져보니 앵무조개 모양의 스피커 시스템이 바로 B&W의 작품이었다. 아! 이 모습은 너무나 유명하지 않던가.

Nautilus: The ultimate loudspeaker(출처)
DM10은 1981-83 사이에 제조해서 판매한 B&W의 염가형 스피커 시스템이라고 한다. 당시 판매 가격은 180 달러 정도였다고 한다. HiFi Classic이라는 웹사이트에 꽤 상세한 리뷰 기사가 실렸다(링크). 구글을 뒤지면 발매 당시의 브로셔도 쉽게 구할 수 있다(링크).
What we heard was generally consistent with what we had measured... The bass was surprisingly strong and clean, despite the low-frequency power limitations evident in our distortion measurements...  At any listening level that most people would reasonably use at home, it was completely clean... It is unquestionably one of the better speaker-system values in today's market. (HiFi Classic 마지막 줄)
전면 그릴은 달려 있지 않고, 인클로저도 군데군데 까진 상태였다. 특이하게도 트위터의 보이스 코일에서 나오는 선이 인클로저 내부가 아니라 외부에서 납땜을 해야 하는 구조였다. 전면 그릴이 없으니 잘못 건드리면 끊어지기 쉽다. 처남도 이를 직접 수리를 했었다는데, 어제 집에 들고 와 보니 나도 뭘 잘못 건드렸는지 한쪽 선이 끊어져 있는 것 아닌가. 딱 코털(?) 정도의 길이로 돌출한 가냘픈 선을 다루면서 만약 이것이 코털 뽑히듯 끊어지면 되살릴 방법이 없다고 생각했다. 아주 조심스럽게 납땜 작업으로 트위터를 되살렸다.
원으로 표시한 곳 내부가 직접 납땜하여 수선한 곳이다. 피복에 해당하는 것은 잘못하여 떨어져 나갔다. 이 가냘픈 선이 엣지 부근에서 끊어지면 정말로 낭패다!

TDA7265 앰프로 소리를 들어보고 있다.

공간이 부족하여 임시로 이렇게 배치하였다.
최초로 앰프를 연결하여 소리를 듣는데 영 이상하다. 한쪽 채널의 극성이 반대로 연결되었을 때에 나는 전형적인 소리이다. 분명히 색깔을 맞추어 연결했는데 왜 이런담? 혹시 인클로저 내부에서 +/-선을 반대로 연결하였나? 시험삼아 한쪽 채널의 극성을 반대로 연결하니 편안한 소리가 난다. 명료하고도 두툼한 소리가 듣기 좋다. 극성 확인을 위해 건전지를 가져다가 스피커에 연결해 보았다. 왼쪽은 적-(+), 흑-(-) 연결에서 우퍼가 앞으로 쑥 튀어나온다. 그런데 오른쪽 채널은 반대로 쑥 들어가는 것이 아닌가. 흠... 아마도 처남 이전의 소유주가 수리를 하면서 단자에 극성을 반대로 납땜한 것이 틀림이 없다. 어떻게 이런 실수를 했을까? 만약 공임을 받고 수리를 하는 기사의 실수였다면 정말 한심한 일이 아닐 수 없다.

경량 구조이지만 우퍼는 8인치이다. 트위터는 1인치 돔 타입. 카탈로그에 의하면 주파수 재생 특성은 75 to 20,000 Hz ±3 dB, 민감도는 87 dB이다. 

나의 오디오 취미에서 스피커쪽은 상대적으로 관심이 덜 가는 분야였다. 스피커는 소리의 최종적인 출구로서 투자 대비 만족도가 가장 높은 곳인데 말이다. 아마 초기에 스피커 DIY를 조금 해 보다가 흥미가 지속되지 못해서 그만 둔 것에도 원인이 있을 것이다. 당시 내 블로그에는 이런 덧글이 있었다. 제대로 즐기기 위해 할 수 있는 시도가 있음에도 불구하고 주변부만 맴돌고 있는 것 같아 안타깝다고... 나는 그때 스피커 유닛을 처음으로 구입하여 두꺼운 종이로 만든 통에 넣고는 마음에 들어하지 않고 있었다. 그 덧글을 남긴 분의 시각에서는 한심해 보였을지도 모르는 일이다.

취미란 것이 원래 그런 것 아닌가. 효율과는 관계없이 많은 비용을 들이면서 먼 길을 돌아오기도 하고, 무지의 장막 한 겹만 걷으면 곧 새로운 세계가 펼쳐지는데 그 앞에서 발걸음을 멈추기도 하고..

내가 어설프게 만든 소출력 진공관 앰프를 잘 울리기 위해 스피커를 맞추고 싶은 생각은 별로 없다. 진공관 앰프는 그저 만드는 과정을 즐기는 재미와 전원을 넣었을 때 빨갛게 달아오르는 불빛을 바라보는 재미를 위한 것이다. 우연한 기회에 처남으로부터 얻은 스피커(이를 빈티지 스피커라 하기에는 아직 젊은 것 같은데)가 취미의 범위를 조금 더 확장해 준 것 같아서 즐겁다.


2021년 5월 28일 금요일

antiSMASH v5가 이렇게 설치하기 어려운 소프트웨어였던가?

antiSMASH는 유전체 서열로부터 이차대사물의 생합성 유전자군(BGC, biosynthetic gene cluster)를 예측하는 도구이다. 현재 버전은 5.x까지 나온 상태이다. 버전 3과 4에서는 지금 KAIST에 재직 중인 김현욱 교수가 개발에 참여하였던 것으로 안다.

파이썬 2.7 시절의 버전인 antiSMASH 4.x는 무난히 설치하여 잘 쓰고 있었다. 최신 버전을 설치하려니 생각보다 매우 어렵다. 설치 시 나오는 메시지를 구글에 때려넣고 검색을 거듭하여 해결 방법을 찾아 보았다. antiSMASH GitHub 웹사이트의 issue #234번에서 힌트를 얻어서 다소 복잡한 설치 명령어를 입력하여 겨우 설치에 성공하였다. GitHub의 파이썬 소스를 가져다가 저렇게 한 줄의 명령어로 설치하는 방법은 이번에 처음 써 보는 것이다.

$ conda create -n antismash5 "python>3" pip numpy "biopython=1.76" \
    helperlibs jinja2 pysvg-py3 bcbio-gff pyscss matplotlib scipy "scikit-learn>=0.19" \
    "diamond==0.9.*" "fasttree==2.1.*" "glimmerhmm==3.0.*" hmmer2 \
    "hmmer==3.1b2" "meme<=4.11.2" "muscle==3.8.*" "blast=2.2.*" prodigal
$ conda activate antismash5
$ python -m pip install git+https://github.com/antismash/antismash.git@5-1-2 OK!
$ download-antismash-databases # 일부만 성공, SSL 인증서 관련 에러 발생!

문제는 이것으로 전부가 아니라는 것. 위에서 보인 명령어 중 가장 마지막 것('download-antismash-database')를 실행할 때 SSL 인증서와 관련한 urllib의 에러가 난다. 짜증스러울 정도로 자주 만나던 에러다.

urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1131)

REQUESTS_CA_BUNDLE 환경변수를 수정하는 것으로도 해결이 되지 않는다. 드디어 파이썬 소스 코드를 고쳐서 시도할 순간이 되었다. 이에 대한 해결 방법은 구글링을 하면 어렵지 않게 찾을 수 있다. 내가 참조한 글은 urllib request.py urlopen SSL 인증서 에러 문제 해결 SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED]이다. 파이썬 문법을 잘 모르는 상태에서 소스 코드를 고치려니 참 부자연스럽다. download-antismash-database에서 호출하는 download_databases.py 스크립트를 vi로 열어서 앞부분에 import ssl을 적당히 삽입하고, 다음의 빨간색 줄에 해당하는 코드를 삽입한 것이 전부였다. urlopen() 안에 한 줄로 넣어 버리는 방법도 어디선가 읽은 적이 있었다.


이렇게 한 다음 문제의 스크립트를 재실행하면 에러가 났었던 clusterblast_20190415 데이터베이스의 다운로드 및 설치가 무사히 끝난다. antiSMASH용 데이터베이스의 위치는 다음과 같으므로, SSL 인증서 문제가 발생하지 않는 다른 전산망의 컴퓨터에서 받은 파일을 가져다가 덮어씌워도 될 것이다.

antismash5/lib/python3.8/site-packages/antismash/databases

새롭게 설치한 antiSMASH를 이용하여 Acineobacter baumannii의 complete genome sequence를 분석해 보았다. 분석 소요 시간은 얼마 되지 않는다. 결과 화면은 다음과 같다.


PYTHONHTTPSVERIFY라는 환경 변수를 0으로 설정하면 된다는 글도 있었다. 위에서 소개한 방법을 이용하여 다른 서버에 antiSMASH 프로그램을 설치한 뒤 'export PYTHONHTTPSVERIFY=0'을 실행하고 나서 download-antismash-database를 실행해 보았다. 그랬더니... 되긴 뭐가 돼! 결론적으로는 download_databases.py 스크립트를 수정하여 데이터베이스 설치를 완료하였다.

(antismash5) $ export PYTHONHTTPSVERIFY=0
(antismash5) $ download-antismash-databases
/opt/miniconda3/envs/antismash5/lib/python3.8/site-packages/scss/selector.py:26: FutureWarning: Possible nested set at position 329
  SELECTOR_TOKENIZER = re.compile(r'''
Downloading PFAM version 27.0
Downloading Pfam-A.hmm.gz: 100.00% downloaded.
Creating checksum of Pfam-A.hmm.gz
Extraction of Pfam-A.hmm.gz finished successfully.
Downloading PFAM version 31.0
Downloading Pfam-A.hmm.gz: 100.00% downloaded.
Creating checksum of Pfam-A.hmm.gz
Extraction of Pfam-A.hmm.gz finished successfully.
Downloading Resfam database
Downloading Resfams.hmm.gz: 100.00% downloaded.
Creating checksum of Resfams.hmm.gz
Extraction of Resfams.hmm.gz finished successfully.
Ensuring all cutoffs are present
Downloading ClusterBlast database.
Traceback (most recent call last):
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/urllib/request.py", line 1354, in do_open
    h.request(req.get_method(), req.selector, req.data, headers,
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/http/client.py", line 1252, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/http/client.py", line 1298, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/http/client.py", line 1247, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/http/client.py", line 1007, in _send_output
    self.send(msg)
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/http/client.py", line 947, in send
    self.connect()
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/http/client.py", line 1421, in connect
    self.sock = self._context.wrap_socket(self.sock,
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/ssl.py", line 1040, in _create
    self.do_handshake()
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1131)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/site-packages/antismash/download_databases.py", line 82, in download_file
    req = request.urlopen(url)
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/urllib/request.py", line 222, in urlopen
    return opener.open(url, data, timeout)
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/urllib/request.py", line 525, in open
    response = self._open(req, data)
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/urllib/request.py", line 542, in _open
    result = self._call_chain(self.handle_open, protocol, protocol +
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/urllib/request.py", line 502, in _call_chain
    result = func(*args)
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/urllib/request.py", line 1397, in https_open
    return self.do_open(http.client.HTTPSConnection, req,
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/urllib/request.py", line 1357, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1131)>

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/miniconda3/envs/antismash5/bin/download-antismash-databases", line 8, in <module>
    sys.exit(_main())
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/site-packages/antismash/download_databases.py", line 352, in _main
    download(args)
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/site-packages/antismash/download_databases.py", line 330, in download
    download_clusterblast(args.database_dir)
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/site-packages/antismash/download_databases.py", line 307, in download_clusterblast
    download_if_not_present(CLUSTERBLAST_URL, archive_filename, CLUSTERBLAST_ARCHIVE_CHECKSUM)
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/site-packages/antismash/download_databases.py", line 207, in download_if_not_present
    download_file(url, filename)
  File "/opt/miniconda3/envs/antismash5/lib/python3.8/site-packages/antismash/download_databases.py", line 84, in download_file
    raise DownloadError("ERROR: File not found on server.\nPlease check your internet connection.")
antismash.download_databases.DownloadError: ERROR: File not found on server.
Please check your internet connection.

2021년 5월 23일 일요일

전주 한옥마을을 거닐다가 완판본 문화관을 한참 구경하고 잠시 전주천 변에 앉아 쉬고 있었다.


'전기수'란 소설책을 청중들에게 읽어주는 사람을 말한다. 조선 후기에 생긴 직업적인 이야기꾼이다.

멀리서 농악 소리가 들리더니 점점 가까이 다가온다. 참 오랜만에 듣는 장단이다.

그네터 옆에 마련된 약간 넓은 곳에 농악대가 멈추더니 큰 깃발을 든 사람 셋이서 번갈아 화려한 묘기를 펼쳐 보였다. 생전 처음 보는 장관이라서 한참을 구경하였다. 어깨에 끈을 연결하여 지탱한 항아리 모양의 물건을 다리 사이에 놓고 여기에 깃대를 꽂은 상태로 기를 펼쳐서 빙빙 돌린다. 깃대 꼭대기에 달린 줄을 팔로 지탱하면서 쓰러질락말락 수평으로 돌리기도 하고, 한 손이나 이마에 올려 놓고 중심을 잡기도 한다.

풍물패는 치배(악기를 연주하는 사람)와 잡색(각기 배역을 가지고 춤을 추며 흥을 돋구는 사람)으로 구성된다고 한다. 깃발을 들고 퍼포먼스를 펼치는 사람도 잡색의 일종일까? 지금까지 풍물패에 대하여 아는 것이라고는 꽹과리를 치며 전체를 지휘하는 '상쇠'뿐이었다.

전통 예술의 일종이니 퍼포먼스라고 표현하는 것은 옳지 않고, '연희(演戲)'라고 하는 것이 더 나을 것이다. 그러나 연희의 사전적 의미는 '말과 동작으로 여러 사람 앞에서 재주를 부리는 것"(네이버 사전)이므로 노래나 악기 연주는 이 범주에 들어가지 않는 것 같다. 한국예술종합학교 전통예술원에서도 음악과와 연희과는 다르다. 

흠... 풍물은 연희의 하나로 취급된다. 악기 연주와는 분명히 다르게 취급되는 것이 맞고, 그럴 만한 이유가 있을 것이다. 대학 동기인 이진원 교수(한국예술종합학교)에게 백만 년 만에 카톡을 보내어 물어 봐야 되겠다.



2013년에 구입한 낡은 서버에 CentOS 7을 새로 설치하다

2008년부터 2015년까지 총 4대의 서버를 구입하였다. 주력으로 쓰는 것은 2015년에 구입한 것('tube' server)이니 결코 최신 모델이라고 할 수는 없다. 지금까지 쓰는 Synology NAS는 이보다 조금 더 오래 되었다. 이들은 모두 쌩쌩 날아다니는 속도는 아니지만 특별한 문제를 일으키지 않으니 가끔 먼지를 털어내며 사용을 하고 있다. 

네 대의 서버 중 가장 저렴한 제품이었던 Tyan Korea의 완제품 1U 서버(2013년 구입)에 최신 OS를 설치하기로 하였다. 제품 형번은 KXT14 (S7002G35-W213)이다. 웹사이트를 방문하면 형번을 구성하는 숫자 및 알파벳의 의미를 알 수 있다. 가장 중요한 부품이라 할 수 있는 마더보드의 형번은 Tyan S7200G2NR-LE이다. 마지막으로 전원을 넣은 것은 언제였을까? 아마도 2018년? 2019년 4월부터 2년 동안은 내가 다른 곳에서 근무를 하느라 tube와 NAS를 공식 반출하여 들고 가면서 나머지 것들은 전부 전원을 내려 놓은 상태였다.

한동안 우분투를 편식했으니 이번에는 CentOS를 설치해 보기로 했다. ISO 이미지 파일(다운로드 사이트)을 찾아보니 CentOS Stream이라는 것이 보인다. 기존의 CentOS 7은 2024년 6월까지만 지원이 된다고 한다. RHEL(Red Hat Enterprise Linux)로부터 공개 커뮤니티용으로 다시 만들어져 나온 것이 기존의 CentOS라면, CentOS Stream은 페도라에서 (완벽하지 않은?) 테스트를 거친 뒤 곧바로 공개되는 것처럼 보인다. 가능하다면 유료 서비스인 RHEL를 많이 써 달라는 취지인 것으로 보인다. 우분투도 매번 공짜로 쓰는 처지인데, 어떻게 대비를 해야 될지 조금 걱정이 된다.

워낙 오래 된 컴퓨터라서 USB를 이용하여 간편하게 부팅 매체를 바꿀 수 있는 메뉴를 제공하지는 않는다. 일단 바이오스 셋업에 들어가서 몇 가지를 건드려 주어야 한다.

2009년 AMIBIOS!

Advanced → USB configuration으로 진입한다.

USB 드라이브를 꽂은 상태에서만 맨 아래의 USB mass storage device configuration 메뉴가 나타난다.

몇 번 테스트를 해 보니 Auto나 Hard disk 무엇으로 설정하는 다 된다.

Boot → Boot device priority로 진입한다.
아, 중간 과정을 하나 빼먹은 것 같다. Boot setting 메뉴에서 맨 하단의 Hard disk drives로 들어가서 USB 드라이브를 가장 상위로 가게 만들었었나? 그럴 필요가 없었나? 별로 복잡한 세팅 변경도 아닌데 그것 하나 기억을 못하다니.
1st boot device를 USB(ScanDisk)로 설정한다.

여기까지 하고 저장 후 재부팅을 하면 비로소 USB 드라이브를 통한 부팅이 이루어진다.

이 서버는 ePrism SSL VA의 영향을 받지 않는 '안전한(?) 곳에' 당분간 두면서 테스트용으로 사용해 보련다. 오늘까지 SSL 인증서 문제로 씨름을 하면서 완벽한 해결책에 거의 다가갔다고 생각하지만 전혀 방심을 할 수가 없는 상황이다. 두 곳의 환경을 비교하되 직장 전산망 환경에서 도저히 설치가 되지 않는 파일이나 애플리케이션의 경우는 안전한 곳의 서버에서 설치한 뒤 복사하여 이식하는 편법을 동원하는 수밖에는.


Bactopia test - 방황의 끝(2)

Bactopia(공식문서, GitHub, mSystems 2020년 논문)란 세균 유전체의 분석을 위한 파이프라인이다. TORMES 파이프라인과 유사하면서도 다른 점이 많다. 동일 종에 속하는 여러 균주의 시퀀싱 결과물(fastq)이 있다면, tormes는 이를 조립하여 taxonomic assignment를 실시하고, genome annotation을 실시하면, roary에 의한 pan-genome 분석 및 항생제 내성/병원성 유전자를 검색하여 보기 좋은 리포트를 생성한다.

Bactopia는 로컬 컴퓨터에 연구하려는 species의 DB를 먼저 만드는 것에서 시작한다. 예를 들어 Staphylococcus aureus가 연구 대상이라면, NCBI에서 complete genome 서열(max = 1000)을 다운로드하여 protein DB(이것은 prokka에서 쓰인다)와 genome size 분포 등의 기본 수치를 확보해 놓는다. 항생제 내성/병원성 유전자 DB를 미리 만드는 것은 TORMES와 같다. 분석에 사용할 fastq 파일은 사용자가 제공하거나 SRA/ENA에서 다운로드할 수 있다. 유전체 조립을 하여 minhas skectch에 의해 reference 중 가장 가까운 유전체를 찾고, 이를 기준을 SNP analysis를 실시한다. 그 외의 분석 내용은 TORMES와 유사하다. 단, 그대로 보고용 자료로 쓸 수준의 리포트를 만들어 주지는 않는 것 같다. Nextflow를 쓴다는 것은 bactopia만의 특징이다. Nextflow가 뭔지도 모르면서 벌써 NanoCLUST와 Bactopia라는 애플리케이션을 통히 이를 쓰게 되었다.

Bactopia를 설치하고 테스트 런을 실시하는 과정도 순탄하지는 않았다. Conda 환경에서 돌아가게 만들어져 있지만 DB를 만들기 위한 파일 또는 튜토리얼용 SRA 파일을 내려받는 과정에서 또 SSL 인증서와 관한 문제를 수두룩하게 겪었기 때문이다. 

5월 20일에 작성한 글(Conda 환경이 참조하는 SSL 인증서의 위치는 어디에 있는가? - 방황의 끝)은 어쩌면 방황의 '시작'이었는지도 모른다. 집에서 노트북 컴퓨터에 우분투를 설치하고 bactopia를 테스트하면 아무런 문제가 없다. 그러나 연구소로만 오면 안 된다. 5월 20일 글에서 특정 conda 환경이 참조하는 공식 SSL certificate에 SSLPrisim.crt가 포함된 파일의 위치를 살짝 덮어 쓰는 편법으로 해결을 해 보고자 하였으나, 여의치 않았다.

일요일에 사무실에 나와서 다시 이 문제를 해결하고자 씨름하였다. 결국은 시스템에서 공식적으로 설치한(물론 내가 SSLPrism.crt를 추가하였지만) 인증서의 위치를  두 환경변수 REQUESTS_CA_BUNDLE와 CURL_CA_BUNDLE에 동일하게 설정하는 것이 가장 깔끔한 해결책이라는 결론을 내리게 되었다. 내 블로그에 달린 댓글을 통해서 이러한 환경변수를 통한 해결 방법을 처음 알게 되었지만, 이 변수가 어떤 의미가 있고 어떤 프로그램류에서 쓰이는지에 대해서는 별로 깊게 생각을 하지 않았었다. 검색에 의하면 REQUESTS_CA_BUNDLE는 파이썬을, CURL_CA_BUNDLE은 curl 및 관련 프로그램을 위한 것이다. 이 변수를 제대로 선언했다면 파이썬 패키지의 설치 작업에서 '--trusted-host pypi.org --trusted-host files.pythonhosted.org' 옵션을 줄 필요가 없다. 

모든 애플리케이션이 시스템에 공식적으로 설치된 SSL 인증서를 자동적으로 인식하지는 않는다는 점이 지금까지 이렇게 고생을 하게 만든 이유인 것 같다. 어떤 리눅스 배포판을 쓰느냐에 따라서 시스템에 설치된 인증서의 위치는 조금 다르다.

CentOS라면 이렇게 하면 된다.

export REQUESTS_CA_BUNDLE=/etc/pki/tls/cert.pem

export CURL_CA_BUNDLE=/etc/pki/tls/cert.pem

다음은 우분투의 경우이다.

export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt

export CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt

Bactopia는 참조 유전체 서열을 다운로드할 때 ncbi-genome-download를 사용한다. 이 스크립트는 예전에 설치하여 조금 쓰다가 어느 순간부터 작동이 잘 안되어서 손을 대지 않고 있었는데(역시 SSL 인증서 문제였음), 이번에 bactopia 테스트를 위하여 애를 쓰는 과정에 덩달아 문제가 해결되었다! Bactopia와 database 설치가 모두 완료되어 다음과 같이 첫 명령을 실행하였다.

$ bactopia --accession SRX4563634 \
>          --datasets datasets/ \
>          --species "Staphylococcus aureus" \
>          --coverage 100 \
>          --genome_size median \
>          --cpus 2 \
>          --outdir ena-single-sample

Raw data를 다운로드하는 'gather_fastqs' 단계(fastq-dl 사용)에서 에러가 난다. 인증서 문제는 다 해결한 것 같은데 이유가 뭘까? '--use_ena'를 써서 fastq 파일을 SRA 대신 ENA에서 다운로드하면 될지도 모른다는 생각이 들어서 이 옵션을 주어 보았다. 그랬더니 비로소 bactopia 실행이 에러 없이 완료되었다. 후!

총 3대의 컴퓨터에 몇 번씩 재설치를 해 가면서 문제를 재현하고 한 단계씩 나아가면서 이를 해결하고자 노력하여 여기까지 왔다...

2021년 5월 20일 목요일

Conda 환경이 참조하는 SSL 인증서의 위치는 어디에 있는가? - 방황의 끝

SSL 인증서와 관련한 문제로 2년이 넘게 고생을 해 왔고 이제야 어렴풋하게 이해를 했다고 생각했지만, 오늘 무릎을 치면서 '유레카!'를 외치는 발견을 또 하게 되었다. 늘 눈앞을 가로막고 있는 듯했던 무식의 장막을 하나 더 걷어냈다는 기쁨을 나 혼자 간직할 수가 없어서 이렇게 블로그에 기록을 남긴다. 2년이라는 시간 동안 걷어낸 장막 뒤에는 이보다 훨씬 더 두꺼운 콘크리트 벽이 자리를 잡고 있을지도 모르는 일이지만..

한국생명공학연구원의 전산망 내에서 일을 하는 사람이라면 수산 아이앤티라는 회사에서 제공하는 SSLPrism.crt라는 파일을 웹브라우저에 설치해야 한다. 윈도우에서만 일을 한다면 이것으로 대부분의 업무를 다 볼 수 있다. 리눅스도 웹브라우저에서 SSLPrism.crt 파일을 설치하면 된다. 생명(연)에서 컴퓨터를 구입하여 처음으로 인터넷에 접속을 하면 이 과정이 거의 자동으로 이루어지니 보통은 별로 신경을 쓰지 않아도 된다. 생명(연)에서 안내하는 것은 딱 여기까지이다. 아래에 분홍색으로 표시한 텍스트는 수많은 시행착오와 검색으로 알아낸 사실이다.

소만사니 수산 아이앤티니 하는 회사의 장비가 하는 일은 https://로 시작하는 웹사이트와 내부 사용자가 주고받는 정보를 복호화(즉 암호를 푸는)하는 일이다. 사용자를 보호해 주는 것이 아니라, 사용자가 기관의 민감한 정보를 유출하는지를 감시하기 위한 것이다!(내가 이해하는 것이 100% 정확한 것은 아닐 수도 있음). 다시 말하자면 기관 차원의 보안을 위한 솔루션인 것이다. 만약 접속하고자하는 외부 사이트가 자체 서명한 인증서를 쓰는 경우, 이 장비를 거치면서 최상위 인증서가 SSLPrism.crt인 것으로 바뀌어서 내부로 전달된다. 왜 이렇게 되어야 하는지는 내가 알지 못한다. 이때 전산망 내부에 있는 사용자가 SSL 인증서와 관련한 수많은 오류를 만나게 되는 것이다. 특히 nanopore 구동 관련 software를 설치하면서 많은 어려움을 겪을 것이다. 이것은 방화벽에서 포트를 여는 문제로 완벽하게 해결되지 않을 것이다. 단, 윈도우 환경에서 일반적인 업무를 보는 사람은 별다른 문제를 접하지 않는다...

하지만 리눅스에서는 웹브라우저만을 이용하여 https:// 위치에 있는 파일을 가져오는 것이 아니다.  wget, curl,  그리고 파이썬의 urlopen() 등 많은 애플리케이션이 웹브라우저를 경유하지 않고 직접 외부의 자료를 갖고오게 만든다. 웹브라우저에서 설치한 인증서는 이러한 상황에서 다른 애플리케이션에게 도움을 주지 못한다. 따라서 SSLPrims.crt는 CentOS의 경우 update-ca-trust라는 별도의 프로그램을 이용하여 시스템 전체에 걸쳐 작동하도록 설치해야 한다. 방법은 단순하다. SSLPrism.crt 파일을 /etc/pki/ca-trust/source/anchors/ 디렉토리에 복사한 뒤 update-ca-trust 명령을 실행하면 된다. 물론 이 두 단계의 작업을 하려면 관리자 권한이 필요하다. 이렇게 하면 /etc/pki/tls/cert.pem과 /etc/pki/tls/certs/ca-bundle.crt 두 개의 파일 제일 앞에 SSLPrism.crt 인증서가 위치하게 될 것이다.

이렇게만 해 놓으면, wget 명령에서 '--no-check-certificate', 그리고, curl 명령에서 '--cacert' 등의 파라미터를 설정할 필요가 없다.

그런데 conda 환경 내에서는 system-wide한 인증서 위치를 참조하지 않는 것을 뒤늦게 발견하였다. SILVA database를 다운로드하는 다음의 사례를 보자. 위의 것은 conda 환경에 설치된 wget 명령을(다운로드 실패), 아래는 시스템에 존재하는 /usr/bin/curl을 이용한 것이다(다운로드 성공). 

(base) $ curl https://ftp.ncbi.nlm.nih.gov/genomes/all/GCA/014/706/575/GCA_014706575.1_ASM1470657v1/GCA_014706575.1_ASM1470657v1_genomic.fna.gz > test.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (60) SSL certificate problem: self signed certificate in certificate chain
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

(base) $ /usr/bin/curl https://ftp.ncbi.nlm.nih.gov/genomes/all/GCA/014/706/575/GCA_014706575.1_ASM1470657v1/GCA_014706575.1_ASM1470657v1_genomic.fna.gz > test.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 1576k  100 1576k    0     0   578k      0  0:00:02  0:00:02 --:--:--  578k

그렇다면 conda 환경에서 참조하는 SSL 인증서의 위치는 도대체 어디인가? 'Conda +  SSL + 에러'라는 키워드로 구글 검색을 하면 대부분 .condarc 파일에서 'ssl_verify: false'라고 설정을 하라는 답이 얻어진다. 이것은 conda package를 설치 또는 업데이트할 때의 문제이다. Conda 환경 내에서 개별적으로 돌아가는 애플리케이션이 외부 파일을 가져오고자 할 때 겪는 인증서 문제와는 다른 이야기이다.

테스트를 위해 새로 설치한 miniconda 디렉토리의 하위를 뒤져 보았다. ca-certificates라는 conda package가 설치된 곳을 찾아야 한다. 그것은 바로 다음의 위치였다. 그리고 개별적인 conda 환경은 env/환경명/conda-meta/ca-certificates-2020.12.5-ha878542_0.json 파일을 통해서 자기가 어떤 인증서를 참조하고 있는지를 명시하였다.

/opt/miniconda3/pkgs/ca-certificates-2020.12.5-ha878542_0/ssl

여기에는  cacert.pem과 cert.pem(cacert.pem의 심볼릭 링크) 파일이 존재한다. 당연히 이 파일은 SSLPrisim 인증서를 전혀 알지 못한다. 시스템 전체에 적용되는 /etc/pki/tls/cert.pem 파일을 이 위치의 cacert.pem으로 덮어 씌워버렸다. 

결과는 예상한 바와 같다. Conda 환경에 설치한 wget으로 SILVA database가 무사히 다운로드되었다. 오늘 얻은 하나의 깨달음이 또 다른 '무지의 늪'을 재발견하도록 나를 이끌지도 모르는 일이지만...

TORMES-1.2.1 재설치 테스트

오늘 확인한 바를 최종 점검하기 위해 miniconda3에 tormes-1.2.1을 새롭게 설치해 보았다. SSL 인증서와 관련하여 손을 댄 것은 바로 위에서 언급한 ca-certificates 디렉토리 이하를 고쳐서 system-wide하게 설치된 인증서를 쓰도록 만든 것이 전부이다. quast-download-busco를 실행할 때 BUSCO DB의 위치가 영구적으로 바뀌어서 다운로드가 되지 않는다는 에러를 제외하면 R 패키지 설치까지 전부 완벽하게 끝났다. 아래에 보인 에러는 SSL 인증서와는 관계가 없다. 좀 이상한 것은 세 개의 tar.gz 파일을 wget(/usr/bin/wget이 아니라 tormes 환경에서 설치한 것)으로 다운로드하면 문제가 생기지 않는다는 것이다.

Downloading BUSCO database...
Downloading bacteria database (file: bacteria.tar.gz)...

ERROR! Failed downloading bacteria database (url: https://busco.ezlab.org/v2/datasets/bacteria_odb9.tar.gz), QUAST functionality will be limited! Exception caught: HTTP Error 301: Moved Permanently
You can try to download the file manually, place it in /opt/miniconda3/envs/tormes-1.2.1/lib/python3.6/site-packages/quast_libs/busco/bacteria.tar.gz and restart QUAST
WARNING: Failed to download bacteria database from https://busco.ezlab.org/v2/datasets/bacteria_odb9.tar.gz and unpack it into /opt/miniconda3/envs/tormes-1.2.1/lib/python3.6/site-packages/quast_libs/busco
  Downloading BUSCO database...
Downloading eukaryota database (file: eukaryota.tar.gz)...

ERROR! Failed downloading eukaryota database (url: https://busco.ezlab.org/v2/datasets/eukaryota_odb9.tar.gz), QUAST functionality will be limited! Exception caught: HTTP Error 301: Moved Permanently
You can try to download the file manually, place it in /opt/miniconda3/envs/tormes-1.2.1/lib/python3.6/site-packages/quast_libs/busco/eukaryota.tar.gz and restart QUAST
WARNING: Failed to download eukaryota database from https://busco.ezlab.org/v2/datasets/eukaryota_odb9.tar.gz and unpack it into /opt/miniconda3/envs/tormes-1.2.1/lib/python3.6/site-packages/quast_libs/busco
  Downloading BUSCO database...
Downloading fungi database (file: fungi.tar.gz)...

ERROR! Failed downloading fungi database (url: https://busco.ezlab.org/v2/datasets/fungi_odb9.tar.gz), QUAST functionality will be limited! Exception caught: HTTP Error 301: Moved Permanently
You can try to download the file manually, place it in /opt/miniconda3/envs/tormes-1.2.1/lib/python3.6/site-packages/quast_libs/busco/fungi.tar.gz and restart QUAST
WARNING: Failed to download fungi database from https://busco.ezlab.org/v2/datasets/fungi_odb9.tar.gz and unpack it into /opt/miniconda3/envs/tormes-1.2.1/lib/python3.6/site-packages/quast_libs/busco

만일 tormes 환경 설치 과정 중에 'ClobberError: This transaction has incompatible packages due to a shared path.'라는 보기 싫은 에러 메시지가 나온다면, 'conda clean --all'을 실행하라. 이 명령은 index cache, lock file, 쓰지 않는 cache package 및 tarball을 삭제하여 깔끔한 환경을 만들어 준다.

이것만 기억해 두자. conda에서 새로운 환경을 설치했다면, 어느 버전의 ca-certificates를 참조하는지를 확인하여 이것을 고치면 된다. 지금 설치되어 있는 것만 하여도 이렇게 많으니 말이다...


2021년 5월 24일 업데이트

Conda의 ca-certificates가 제공하는 인증서 파일을 바꿔치기하는 것은 임시방편은 될 수 있지만 그렇게 현명한 방법은 아니다. 이렇게 하여 일부 패키지의 설치 또는 파일의 다운로드에는 성공할 수 있을지 모르나, 'conda update conda'를 실시하게 되면 인증서 파일의 크기가 맞는지 꼼꼼하게 확인하기 때문이다.

SafetyError: The package for ca-certificates located at /opt/miniconda3/pkgs/ca-certificates-2020.12.5-ha878542_0
appears to be corrupted. The path 'ssl/cacert.pem'
has an incorrect size.
  reported size: 263774 bytes
  actual size: 217320 bytes

따라서 2021년 5월 23일에 작성한 글 Bactopia test - 방황의 끝(2)에서 설명한 방법을 따르는 것이 현명할 것이다.

2021년 5월 16일 일요일

[QIIME 2] Nanopore로 생산한 full-length 16S rRNA gene sequencing data 다루기 - 중간 처리가 끝난 데이터에서 각 샘플별 서열을 꺼내는 방법

인터넷에서 구할 수 있는 QIIME 1과 2의 학습용 자료는 매우 많다. 이를 이용하여 2년이 넘게 여러 차례에 걸쳐서 연습을 해 보았으나 실제 내 손에 주어진 데이터가 없으면 근본적인 이해도 잘 되지 않고 진도도 잘 나가지 않는다.

QIIME은 버전 1과 2의 사용 방법과 철학에 현격한 차이가 있어서 두 가지 전부에 익숙해지기가 쉽지 않다. 만약 QIIME을 처음으로 배우는 사람이라면 당연히 버전 2를 권할 것이다. 그런데 최근 새로 주어진 미션에서는 오래전에 454로 생산한 16S microbiome raw data를 분석해야 한다. 아마도 이것이 QIIME 1을 써야 할 마지막 이유가 될 것이다.

나노포어로 시퀀싱하여 demultiplexing까지 끝난 24개의 샘플을 들고 약 일주일 넘게 씨름을 하는 중이다. 미생물 profiling 연구를 하는데 nanpore sequencing 기술이 정말 유용할 것인가? 지금까지 표준 방법으로 널리 쓰이는 일루미나 시퀀싱 자료는 미생물 16S rRNA gene의 V3-V4 region이라는 제한된 영역을 다루지만, nanopore는 1 kb가 훨씬 넘는 16S rRNA 서열 거의 전체(심지어 16S-23S-5S 전체!)를 다룰 수 있으니 species 수준의 해상도는 훨씬 높을 것이 자명하다. 2020년 공개된 논문인 A preliminary study on the potential of Nanopore MinION and Illumina MiSeq 16S rRNA gene sequencing to characterize building-dust microbiomes(full text)의 초록은 이러한 문장으로 결론을 내리고 있다.

At the level of family and above, there was no significant difference between the microbial compositions as revealed by the two platforms. However, at the genus, and particularly at the species level, the ONT MinION reported greater taxonomic resolution than Illumina MiSeq.

EPI2ME에 전체 데이터를 업로드하고 벌써 열흘 정도가 지났는데 아직도 분석이 진행 중이라 한다. 무료 서비스의 한계인지도 모르겠다. 다른 분석 도구로는 무엇을 쓰면 좋을까? 2020년 Nucleic Acids Research에 공개된 NanoCLUST(a species-level analysis of 16S rRNA nanopore sequencing data)라는 도구를 쓰니 별로 어려울 것이 없이 각 샘플에 대하여 10~20개의 species 할당 정보를 손에 쥘 수 가 있었다. NanoCLUST에서 사용하는 클러스터링 방법은 매우 독특하다. 서열 identity를 기준으로 하는 것이 아니라 Uniform Manifold Approximation and Projection(UMAP)와 Hierarchical Density-Based Spatial Clustering of Applications with Noise(HDBSCAN)이라는 방법을 사용하여 'unsupervised read clustering'을 실시한다는 것이다. 이 두 가지의 방법은 캐나다의 Leland McInnes라는 사람이 개발한 것이다.

https://twitter.com/leland_mcinnes
일단 NanoCLUST를 사용하여 일찌감치 전체 데이터 처리를 끝내 놓은 다음, 다른 '전통적'인 방법이 없는지 알아보았다. Deni Ribicic이라는 사람이 q2ONT라는 QIIME 2용 bash pipeline을 만들어 놓았기에 이를 응용해 보기로 했다. GitHub 웹페이지에 나온 QIIME 2 설치 설명에 약간의 실수가 보이길래 이를 바로잡고자 한다.

yml 파일은 qiime2-2019-10을 위한 것인데 conda 환경명을 2019.7로 만드는 것으로 잘못 지시하였다. q2ONT.sh 스크립트 내에서는 2019.10 환경을 activate하는 것으로 짜여져 있으니 이를 고치지 않으면 에러가 발생한다.

q2ONT에서는 OTU clustering의 기준값을 85%로 잡으라고 하였다. 97%가 아닌 85%를 쓰는 이유는 물론 nanopore read의 에러 때문에 그러한 것이다. Deni Ribic이 이런 기준을 쓰게 된 것은 다음의 논문을 근거로 한다. 
Curren, Emily, et al. "Rapid profiling of tropical marine cyanobacterial communities." Regional Studies in Marine Science 25 (2019): 100485.
그래서 나도 q2ONT 스크립트에 24개의 demux read를 넣어 보았다. 이미 24개의 파일로 분리가 되어 있어서 스크립트를 약간 고쳐야 했다. 그러나 그 결과는 처참했다. 약 5천개의 chimera까지 제거된 100만개의 read는 85% OTU clustering을 거쳐도 여전히 60만개 수준이었던 것이다!  Silva 99 database(16S only)의 서열 수 전체가 369,953개라는 것을 생각하면 클러스터링이 거의 되지 않은 것이나 다를바가 없다.

같은 나노포어 데이터를  QIIME 1.9.1의 스크립트로 처리하여 de novo uclust clustering을 해 보았다. 이번에도 threshold를 85%로 잡았지만 q2ONT의 결과와 별로 다르지 않았다. 이쯤에서 중간 결론을 내려 보자. 내가 이번에 매만진 나노포어 데이터가 아주 유별난 것이 아니라면, 85% 서열 기준의 clustring-first method는 적합하지 않아 보인다.

그렇다면 서열 데이터베이스에 대한 검색을 통한 read의 분류를 먼저 이용하는 방법이 나을 수도 있다. 국내에서 나노포어 데이터를 이용하여 microbiome을 분석한 선구자라고 할 수 있는 KAIST 조병관 교수 연구실의 논문을 두 개 찾아서 읽어 보았다. 나노포어 데이터를 사전에 클러스터링하는 것이 아니라 LAST aligner를 써서 16S reference database에 대하여 검색을 한 것으로 나온다. Nanopore의 데이터 특성에 맞는 align parameter가 몇 개의 논문에 소개되어 있었지만, LAST Cookbook에 의하면 last-train을 이용하여 high-indel-error long read를 'genome'에 정렬하는 방법을 소개하였다. Reference DB가 genome이 아닌 16S rRNA 서열이라면 이러한 방법을 그대로 적용하는 것이 옳은지는 아직 알 수가 없다.

LAST website: http://last.cbrc.jp/에서 https://gitlab.com/mcfrith/last로 이전함

LAST를 트레이닝과 더불어서 실행하거나, 또는 mat-convert를 쓰는 경우 상당히 시간이 많이 걸렸다. 실제 데이터를 투입하여 분석을 한 다음 각 query의 best hit을 찾고 이것에 연결된 taxonomy를 뽑으려면 KOBIC의 도움을 받는 것이 좋을 것 같다.

편의성 측면에서는 NanoCLUST가 제일이다. 그런데 전통적인 서열 기반이 아닌 k-mer frequency vector를 이용한 클러스터링을 사람들이 얼마나 받아들이려 할까? 기준을 제시하지 않고도 데이터가 '스스로 뭉치게' 만드는 것이 요즘 데이터 과학의 대세이니 생소한 방법이라고 무시할 수는 없다.

NanoCLUST나 LAST를 쓰기 전에 나노포어 데이터의 전처리를 해 두는 것이 옳지 않을까? QIIME(2) 과정의 일부를 활용하는 것이 필요할 수 있다. 즉 quality와 길이 기준으로 read를 잘라내고, chimera까지 제거해 두는 것이다. 여기까지 진행한 QIIME table과 data로부터 각 샘플별로 FASTA file을 뽑아내면 NanoCLUST 또는 LAST를 쓰기에 매우 좋을 것이다. 물론 프로그램에 따라서는 아무런 전처리를 하지 않은 raw data를 그대로 적용하는 것을 원할 수도 있다. 이는 좀 더 테스트를 해 볼 필요가 있지만.

q2ONT를 돌리고 나면 6.1_uchime-ref-out 디렉토리에 다음의 두 결과 파일이 생긴다.

  • table-nonchimeric-wo-borderline.qza
  • rep-seqs-nonchimeric-wo-borderline.qza
이로부터 특정 샘플에 해당하는 서열을 FASTA file로 뽑아내고 싶다. 어떻게 하면 좋을까? QIIME 2 documentation 웹사이트에서는 이를 직접적으로 설명하지 않기에 Q&A를 뒤져서 겨우 방법을 알아냈다.  우선 추출할 샘플의 ID를 수록한 tsv 파일을 만든다. table-nonchimeric-wo-borderline.qza 파일을 'qiime feature-table summarize'로 처리하여 visualization file을 만든 뒤 컬럼 이름('Sample ID')와 추출할 실제 샘플의 명칭이 정확히 어떻게 되어 있는지를 확인하는 것이 바람직하다. 실수로 공백이 하나 포함되어 있다거나 한다면 모든 샘플이 전부 필터링 아웃되어 제거될 수도 있기 때문이다.

$ cat samples-to-keep.tsv 
Sample ID
0200731-0847-barcode01

다음에 입력할 명령어는 이러하다. qiime feature-table filter-samples 명령어를 사용하여 테이블에 대한 필터링을 수행하고, qiime feature-table filter-seqs 명령에 이를 제공하여 데이터 파일에서 조건을 만족하는 서열을 추출하는 것이다. 오류가 없는지(조건을 잘못 기재하였거나 타이핑 실수 등) 중간에 틈틈이 visualization file을 만들어 확인하는 것이 바람직할 것이다.

$ qiime feature-table filter-samples \
  --i-table 6.1_uchime-ref-out/table-nonchimeric-wo-borderline.qza \
  --m-metadata-file samples-to-keep.tsv \
  --o-filtered-table id-filtered-table.qza

$ qiime feature-table summarize \
  --i-table id-filtered-table.qza \
  --o-visualization temp.qzv

$ qiime tools view temp.qzv # 38435 sequences

$ qiime feature-table filter-seqs \
  --i-data 6.1_uchime-ref-out/rep-seqs-nonchimeric-wo-borderline.qza \
  --i-table id-filtered-table.qza \
  --o-filtered-data id-filtered-seqs.qza

$ qiime tools export \
  --input-path id-filtered-seqs.qza \
  --output-path export_test

$ grep -c '>' export_test/dna-sequences.fasta
38435 # OK!

 '0200731-0847-barcode01' 샘플에 존재하는 38,435개의 서열이 들어 있는 파일인 export_test/dna-sequences.fasta를 얻게 되었다. 이 과정을 24개의 샘플 전체에 대하여 반복을 하면 된다. 좀 귀찮은 일이기는 하다.

'qiime feature-table filter-samples' 명령을 실행할 때 메타데이터 파일에 정의된 샘플의 속성을 기반으로 추출하는 것도 가능하다. 다음의 예시를 보자.

$ qiime feature-table filter-samples \
   --i-table 6.1_uchime-ref-out/table-nonchimeric-wo-borderline.qza \
   --m-metadata-file metadata_all_samples.tsv \
   --p-where "[Sample ID]='0200731-0847-barcode01'" \
   --o-filtered-table subject-1-filtered-table.qza

'--p-where' 뒤에 입력할 조건은 SQLite의 where syntax를 참조하여 만들면 된다.

QIIME 2 문서를 뒤적거리면서 한숨이 나왔다. 기본 개념을 잡는 것이 왜 이렇게 어려울까? 내가 공부가 부족한 것인가? 다들 잘 이해하고 있는데 나만 모르고 있었나? 그저 RFTM(Read the fuxxing manual)을 하지 못한 내 탓으로나 여기고 Amanda Birmingham의 QIIME 2 튜토리얼을 인쇄하여 집에 들고 가련다. 사실 이것도 최신 자료는 아니다. 그리고 오늘은 일요일이다...

2021년 5월 12일 수요일

6LQ8 싱글 앰프 전원부 제작 4부 - 진짜 마무리!

네온 램프가 달린 전원 스위치를 달고 접속자를 꽉 조여서 두꺼운 전선을 체결하였다. 접속자는 이렇게 생긴 물건이다(과거에 쓴 글 링크). 내가 사용하는 압착 플라이어(Lobster FK3)와 구입해 놓은 접속자가 썩 잘 맞지 않아서 불편한 점은 있다. 두꺼운 선 몇 개를 한번에 연결하려면 납땜을 하고 압축튜브를 씌우는 것보다 접속자로 마무리를 하는 것이 훨씬 편하다. 오디오 앰프 자작에서는 흔히 보이지는 않는 모습이지만...

이것이 정말 마지막일까? 흰 바구니 바닥면에 고무 다리도 붙였고, 더 이상의 납땜은 이제 할 필요가 없이 마무리를 하였다.
왼쪽의 초록색 네온 램프(주전원 스위치)는 220V가 들어오고 있음을, 오른쪽의 적색 LED는 히터 점화를 위한 DC 12V 어댑터가 연결되었음을 의미한다. 주전원 스위치는 12V 어댑터의 동작에 아무런 영향을 미치지 않는다. 
가분수 형태의 2층 구조가 마치 현대적 건축물을 보는 것 같다. 언젠가 자투리 땅을 사서 나만의 집을 짓게 되면 이런 형태를 만들어도 될 것 같다. 롤라이의 2안 리플렉스 카메라 형태로 카페 건물을 지은 사람도 있지 않은가?(관련 글 링크) 전원부 바구니와 앰프부 나무판은 서로 고정하지 않은 상태이다. 각재를 구입해 둔 것이 있으니 이것을 적당히 이용하면 될 것이다.

볼륨 조절기가 노출된 전면에는 원래 파란색 포맥스 판(두께 2mm)을 잘라서 가렸었다. 내부가 훤히 들여다 보이는 것이 그렇게 아름답지는 않다. 만약 최종적인 마무리를 한다면 포맥스 가 아닌 알루미늄판을 이용하는 것이 좋을 것 같다. 제이앨범 한병혁 님은 칼로 자를 수 있는 1mm 알루미늄을 재단하여 포맥스 판을 순간접착제로 덧대어 보강하는 방식을 즐겨 사용했던 것으로 알고 있다.
앰프 속에서 작동 중인 것을 제외하면 나에게는 총 14개의 6LQ8 진공관이 있다. 앞으로 새로 앰프를 만들지 않고 수명이 다 된 것을 교체하기만 한다면 언제쯤이나 이 진공관을 다 쓰게 될까? 진공관의 수명은 수천 시간이라고는 하지만 실제로 꽤 오래 사용할 수 있다. 교체용으로 여분의 진공관을 사 놓아야 한다는 것은 초심자라면 누구나 갖는 강박증일 수도 있다. 2014년에 주문제작한 PCL86 진공관은 어떠했나? 그때 여분으로 10개를 한꺼번에 eBay에서 구입했다가 6개는 처분하였고, 하나는 초기 불량에 해당했던 관을 교체하는데 쓰였다.

악순환의 사이클은 이러하다.
  1. 새 진공관 앰프를 샀으니 수명이 다 될 때를 대비하여 진공관을 여분으로 산다.
  2. 이것만 갖고 있으면 평생 쓸 수 있다고 자부심을 갖는다.
  3. 재고 관을 보고 있으면 내 힘으로 직접 앰프를 만들어 보야야 한다는 강박에 시달린다.
  4. 강박에 시달리는 것을 견디다 못하여 여분의 관은 소량만 남기고 팔아버린다.
정말 우스운 이야기지만, 새 앰프를 만들고 싶다는 강렬한 욕망은 보통 지금까지 써 보지 않은 진공관에 대해서 일어난다. 교체용으로 갖고 있는 진공관이 주는 자작 욕망과는 그 등급이 다르다. 아마 이러한 욕심은 오디오 자작인이라면 누구나 느꼈을 것이다. 경험해 보지 못한 것, 소유해 본 일이 없는 것에 대한 욕심이 일어나는 것은 사람에게는 본성과 같은 것이니까. 이를 적절히 제어하는 것이 평화롭게 사는 지름길이다. 

2021년 5월 13일 업데이트

나무판 아랫면에 각목을 접착하여 바구니에 딱 맞게 만들었다. 각목의 모습을 보이기 위해 바구니에 살짝 걸친 모습으로 사진을 찍어 보았다. 이제 바구니의 측면에 구멍을 뚫고 나사못을 박으면 나무판(앰프부)과 바구니(전원부)가 완벽하게 고정될 것이다.



2021년 5월 16일 업데이트

문구점에서 0.4T 알루미늄판을 구입하여 치수대로 자른 뒤 2T 포맥스판을 순간접착제로 붙여서 전면 패널을 만들었다. 이보다 더 두꺼운 알루미늄판을 구입하려면 전문 상점으로 가거나 인터넷 구입을 이용해야 될 것이다. 얇은 알루미늄판에 포맥스판을 덧대는 이 방법은 제이앨범의 한병혁 님이 즐겨 쓰는 방식인데, 알루미늄판의 두께가 최소 1 mm는 되어야 할 것 같다. 다음 그림의 출처는 제이앨범 '포맥스 접합(2011년 글)'이다.


흠집이 잘 나는 것은 알루미늄판의 두께와는 상관이 없으리라. 흠집을 막는 방법에 대해서는 연구가 필요하다. 나무판에 위치를 잘못 잡고 뚫었던 구멍은 전동드릴을 쓸 때 나온 나뭇가루에 목공본드를 짓이겨서 메웠다.





2021년 5월 11일 화요일

6LQ8 싱글 앰프 전원부 제작 3부 - 마무리

처음부터 철저히 계획을 세우고 앰프를 만든 것이 아니라서 통일성도 없고 공간 배치 효율도 나쁘다. 좋은 점이 있다면 비교적 가볍다는 것이 전부이다. 나무판에 앰프 회로와 출력 트랜스를 고정한 원래의 구조를 유지하느라 전원부는 별도의 플라스틱 수납용 바구니에 담아서 아래로 보내는 2층 배열을 택하지 않을 수가 없다. 이 바구니는 '다이소 큐브 바구니(정식 품명은 큐브스텝바스켓 3호; 46004)'라는 이름으로 몇년 전에 팔리던 물건이다. 지금은 구할 수 없다. 요즘 다이소에서 파는 수납용 플라스틱 바구니는 재질이 너무 부드러워서 앰프의 케이스로 쓰기에는 적합하지 않다. 

다음 사진과 같은 상태로 몇달 동안 듣다가, 갑자기 마음이 바뀌어서 싹 다른 모습으로 개작을 할지도 모르는 일이다. 어떤 상황이 되든 투명 아크릴판을 가공하여 만든 상판은 그대로 유지하고 싶다.

이 사진에서 보이는 구멍이 뚫린 흰색 플라스틱 바구니는 지금으로부터 꼭 5년 전에 Sanken power amplifier IC를 이용하여 만든 앰프를 만들 때 썼던 것이다. 관련 글은 여기에 있다. 당시에 정류회로기판(28x28 hole 만능기판, 가로세로 80mm)을 고정하느라 뚫은 4개의 구멍을 그대로 사용할 수 있었다. 그때는 페놀 기판을 썼고 지금은 에폭시 양면기판이니 비용 차이는 상당하다.

부품 고정은 완료하였으나 아직 납땜이 끝나질 않아서 악어 클립이 보인다.

뒷면은 약간 너저분하다. 두꺼운 커넥터는 B전원과 히터 점화용 전원(직류 12V)를 앰프 본체로 공급하는 용도로 쓰인다. 히터 점화용 전원 공급을 위한 직류 어댑터(12V 2A)를 전원 '바구니' 안에 넣을까 말까 고민하다가 밖으로 꺼내기로 하였다. 주전원과 직류 어댑터를 통제하는 전원 스위치도 달지 않았다. 음악이 듣고 싶으면 전원 플러그와 어댑터를 각각 연결해야 하는 매우 원시적인 형태의 앰프이다. 여기에 사용한 12V 어댑터는 2014년 (주)케이벨의 소형 앰프(KB20W)와 함께 구입했던 것이다(당시에 쓴 링크; 어댑터 판매글 링크). 국내 안전 인증을 받지 않은 저가 어댑터가 너무 많이 돌아다니는 것이 안타까운 현실이다.

어댑터를 전원부 바구니에 넣은 다음 하나의 전원 스위치로 on/off를 조절하게 만들 수도 있다. 그러려면 어댑터를 연결할 1구 콘센트를 바구니에 넣든가, 또는 어댑터를 분해해야 한다. 하지만 왠지 그렇게 하기는 싫었다.
티라미수-II 앰프를 만들면서 여분으로 준비했던 재료가 남았다. 이것은 또 어떤 앰프의 통으로 쓰이게 될 것인가?

2021년 5월 10일 월요일

Conda가 SSL 비표준 인증서 문제로 말썽을 부릴 때 REQUESTS_CA_BUNDLE 환경변수에 지정해 버리기

일러두기: 쉘변수(shell variable)와 환경변수(environment variable)는 다르다. 어떻게 다른지 정확하게 설명할 수 있는가? Unix Power Tools의 Shell and Environemtn Variable 항목을 인용하는 것으로 일단 책임을 회피하고자 한다.

Environment variables are managed by your shell. The difference between environment variables and regular shell variables is that a shell variable is local to a particular instance of the shell (such as a shell script), while environment variables are "inherited" by any program you start, including another shell. That is, the new process gets its own copy of these variables, which it can read, modify, and pass on in turn to its own children. In fact, every UNIX process (not just the shell) passes its environment variables to its child processes.

나에게 SSL 인증서 문제는 끊이 없는 떡밥이다. 도대체 몇번째 글을 쓰는 것인지 모르겠다. 해결이 된 것도 같다가, 여전히 이해가 가지 않는 상태로 되돌아가다가..

.condarc 파일에서 ssl_verify: false로 하여도 conda 명령이 제대로 작동하지 않는다면 어떻게 해야 될까? 깨끗하게 우분투 최신판을 설치한 서버(설치만 새로 했을 뿐, 서버의 구입 연도는 정말 오래되었음)에서는 별다른 조치를 취하지 않았음에도 conda 명령은 잘 돌아간다. 그런데 왜 CentOS 서버에서만 다음과 같은 에러가 나는 것일까? 약 2년 전에는 문제를 일으키지 않았었다. 현 근무지의 네트워크 보안이 강화된 것과 분명히 관계가 있으리라. 물론 이것은 전부 리눅스 컴퓨터에서 벌어지는 문제이다.

2021년 5월 18일 업데이트: SSL 인증서 문제를 해결하기 위해 땜질 처방을 너무 심해게 해서 불필요한 에러 오히려 만들고 있다. .condarc 파일에서 ssl_verify: false로 설정해도 conda 명령이 제대로 돌지 않는 이유는 .bashrc 파일에서 REQUESTS_CA_BUNDLE와 CURL_CA_BUNDLE 환경변수를 함부로 선언한 때문이었다. 해당 두 줄을 코멘트 아웃 처리하면 conda 명령이 잘 돈다!

$ conda install -c conda-forge -c bioconda quickmerge
Collecting package metadata (repodata.json): failed

CondaHTTPError: HTTP 000 CONNECTION FAILED for url <https://repo.anaconda.com/pkgs/main/linux-64/repodata.json>
Elapsed: -

An HTTP error occurred when trying to retrieve this URL.
HTTP errors are often intermittent, and a simple retry will get you on your way.

If your current network has https://www.anaconda.com blocked, please file
a support request with your network engineering team.

u'https://repo.anaconda.com/pkgs/main/linux-64'

오늘은 conda 공식 문서에서 안내한 Using non-standard certificates를 따르기로 하였다. 연구소에서 쓰도록 배포되는 SSLPrism.crt 파일을 이 체계에 쑤셔넣으면 될 것이라고 생각했었지만 마음먹은대로 되지는 않았다.

크롬 웹브라우저에서 문제가 되는 웹사이트를 접속한 뒤 주소창 왼쪽의 잠긴 자물쇠를 클릭하여 '인증서(유효)'를 택한다. '인증경로' 탭에서 최상위에 있는 CA를 선택한 뒤 '인증서 보기'를 클릭하면 새 창이 뜰 것이다. 여기에서 '자세히' 탭을 선택한 뒤 '파일에 복사'를 클릭한다. 그러면 '인증서 내보내기 마법사'가 실행될 것이다. 내보내기 파일 형식은 특별히 건드리지 말고 원래 선택되어 있는 DER를 그대로 쓰도록 한다.


그 다음 과정은 conda 공식 문서에 나온대로 하면 된다. openssl 명령을 사용하여 DER로 인코딩하여 파일로 저장한 인증서(.cer)를 .pem으로 바꾼 뒤 이를 REQUESTS_CA_BUNDLE 환경 변수에 지정하면 된다. 명령어는 아래에 소개하였다. 실제 사례에서는 윈도우 PC에서 크롬으로 해당 사이트를 접속하여 .cer 파일을 받은 뒤, 리눅스로 전송하여 사용하였다. 리눅스에서는 오직 파이어폭스만을 쓰고 있기 때문이다.
  
$ openssl x509 -inform der -in /path/to/your/certificate.cer -out /path/to/converted/certificate.pem
$ export REQUESTS_CA_BUNDLE=/path/to/converted/certificate.pem

최상위 인증서에 ePrism SSL이 나오는 것은 어떤 웹사이트인가? non-standard certificate와 자체 서명 인증서는 무엇이 다른가? 최상위 인증서 자리에 ePrism SSL이 자리를 잡고 있는 것은 어떠한 웹사이트의 경우에 그런가? 만약 이런 것을 잘 이해하고 있다면 나는 인터넷 보안 전문가로 보수를 받고 일을 해야 할 것이다...

환경변수를 쓰지 않고 인증서의 위치를 .condarc 파일에 지정할 수는 없을까? 여러 사이트의 접속이 전부 문제라면, 인증서 번들을 전부 일정 디렉토리에 복사해 넣은 뒤 .condarc에서 해당 디렉토리를 지정해 버리면 되지 않을까? 

도대체 어디까지를 내가 알고 있고 어디부터를 모르는 것인지를 모르겠다. 이건 진짜 모른다는 뜻이다. 진정한 앎은 아는 것과 모르는 것의 경계를 명확히 아는 상태에 이르렀음을 의미하므로.

2021년 5월 9일 일요일

6LQ8 싱글 앰프 전원부 제작 2부 - 조정 작업

저항을 조정하여 필요한 전압에 가깝도록 조정을 하고, 싱글용 출력 트랜스를 초크 코일 대신으로 쓰는 실험을 마무리하고자 오늘도 다시 인두를 들었다. 최적 조건은 다 잡은 것으로 생각된다.

우선 돌입전류 제한용 저항을 총 30옴이 되도록 만들었다. 5와트 10옴 시멘트 저항을 직렬로 3개 연결하였다. 최종 전압을 낮추려면 이 위치에 저항을 삽입하는 것이 더욱 효율적이다. 합성저항 30옴이 적용된 구간의 전압 강하는 3.4V이므로 전류는 옴의 법칙에 의해 3.4/30 = 0.113, 즉 113mA이다. 40VA 전원트랜스포머가 지나치게 크게 느껴진다. 최근까지 쓰던 전원회로(6LQ8 PP 및 싱글 앰프에 공통으로 쓰던 것)은 220V:220V 전원트랜스를 브리지 정류한 것이었는데, 전압 강하를 위해 트랜스포머 2차 권선 직후에 삽입한 시멘트 저항의 발열이 심하여 방열판을 달아야 할 정도였었다. 이번에는 열이 거의 나지 않는다.

두번째는 OPT의 1차 권선을 이용한 초크 코일 대용 실험을 확정하는 것. 초크 코일의 출력쪽에 100uF 400V 전해 캐패시터를 연결하고 앰프를 켜니 히터에만 불이 들어오고 소리가 나지 않는다. 무슨 일이 벌어진 것일까? 확인을 해보니 초크 코일에 단선이 일어난 것 같다. 무리하게 작동을 하여 권선이 끊어진 것일까? 그 이유는 알 수 없다. 초크 코일이 하나 더 있어서 이것으로 대체하였다.

초크 코일 직전의 전압은 직류 234V, 직후에는 213V가 나왔다. 220옴 저항을 하나 더 달아서 204V가 앰프 회로에 공급되게 하였다. 설계자가 권장한 전압이 207V이니 매우 근접한 수준이다. 최종 전압 강하용 저항 양단의 전압 차이는 9V이므로 9V/220R = 약 41mA의 전류가 흐른다. 과거 기록을 보면 꼭 1년 전에 6LQ8 싱글 앰프를 처음 제작하여 테스트를 하였는데, 전원부와 출력 트랜스가 다르지만 51mA의 전류가 흘러 들어가는 것으로 적어 놓았다(2020년 5월 7일 글 링크).

전원부에 사용한 평활용 전해 캐패시터(250V 47uF)의 내압은 딱 한계점 수준이다. 배전압 정류회로에서는 두 개의 캐패시터가 직렬로 연결된 상태라서 문제가 없지만, 바로 다음의 캐패시터에는 거의 250V에 가까운 전압이 걸리기 때문이다. 초크 코일 다음에 연결한 전해 캐패시터는 내압이 400V라서 안전하다. 캐패시터의 윗면이 부풀어 오르지 않는지 주기적으로 점검할 필요가 있다. 만약 그런 상태가 된다면 부품을 교체하느니 차라리 전원부를 새로 만드는 것이 낫다. 양면형 기판에 납땜된 부품을 떼어내는 것은 매우 어렵기 때문이다. 

초크 코일을 사용하는 일반적인 진공관 앰프용 전원회로에서는 정류단 다음 π-형태의 매우 단순한 필터가 쓰인다. 초크 코일을 쓰지 않는 것을 가정하여 설계된 전원부 PCB라서 필터 단의 수가 많은 것은 어쩔 수가 없다. 그러나 필터 단의 수가 많아야 했던 또 다른 이유는, 되도록 기성품 전원 트랜스를 쓰려다보니 전압 강하의 폭이 넓어서 다단 필터를 쓰지 않을 수가 없다. 

비교적 간단한 자작 활동이었지만 이것저것 공부하고 궁리할 것이 많았던 좋은 기회였다.


6LQ8 싱글 앰프 전원부 제작 - 일단 소리를 내다

양면 에폭시 만능기판에 납땜하기가 이렇게 힘들다니! 용량이 큰 인두를 쓰니 녹은 납이 구멍을 통과하여 반대쪽으로 흘러내린다. 보통의 단면형 기판이라면 구멍을 관통한 리드선이 없는 상태에서 도넛형 패턴 위에 인두를 대고 납을 녹이면 고대 왕릉처럼 완만한 곡면을 이루며 납이 잘 붙는다. 그런데 양면형 기판에서는 관통 구멍(일반적인 기판과는 달리 금속 채널)을 따라 납이 주르륵 흘러버린다. 아마 15W 정도의 저용량 납땜인두를 사용했다면 그러지 않았을지도 모른다. 

7번째 줄 첫번째 열에 솟아오른 납 봉오리를 보라. 기판을 뒤집어 놓고 납땜을 할 때 흘러내린 것이다.

제이앨범에서 범용으로 사용하는 배전압정류회로 기판에서는 초크를 쓰지 않고 다단의 RC 필터를 쓴다. 제이앨범 밴드에서 제공했던 6LQ8 싱글 앰프 키트 제작 가이드27. 전원 PCB 항목에 최신 회로도가 있다. 여기에서 권장한 부품과 내가 이번에 사용한 것은 무엇이 다른지 비교해 보자.

  • 전원 트랜스: 2차 108V 90mA 대신 40VA급 220V:110V 기성품 사용(히터는 12V DC 어댑터로 공급)
  • 돌입전류 제한용 저항은 50옴(5~10W) 대신 10옴 5W 저항 2개를 직렬 연결하여 20옴으로 만들었음
  • 저항: 25옴 1W 대신 50옴(100옴 1/2W 저항 2개를 병렬 연결)
  • Breeder 저항과 여기에 붙어있는 캐패시터는 그렇게 중요한 것이 아니라서 기록하지는 않음

납이 구멍을 관통하여 흘러내려서 애를 먹은 것 말고는 오배선 실수도 없었고, 감전을 당하지도 않았다. Breeder 저항은 평활회로를 다루면서 수도 없이 감전을 당했던 경험이 있어서 이번에는 잊지 않고 적용하였다.

부하를 걸지 않은 상태에서 전압을 재 보았다. 280V 정도가 나온다. 흠, 정류부를 구성하는 내압 250V 전해 캐패시터에는 가혹한 것이 아닐까... 앰프를 연결하고 나도 전압이 원하는 수준으로 떨어지지 않아서 몇 개의 시멘트 저항을 연결했다. 도합 1킬로옴은 되는 듯. 권장되는 B 전압은 그라운드를 기준으로 측정했을 때 207V이다.

소리는 무난하게 잘 나는데 약간의 험이 들린다. 이걸 개선할 수는 없을까? 초크 코일? 원래 제이앨범의 전원 PCB에서는 다단 RC 필터를 사용하여 험을 실용적으로 문제가 없는 수준까지 낮추는 것이 목표였다. 그래도 초크 코일을 연결하면 조금이라도 낫지 않을까? 하지만 일부러 주문을 하고 싶지는 않았다. 혹시 예전에 전원 트랜스를 개조하여 싱글용 출력 트랜스로 만든 것의 1차 권선을 이용하면 초크 코일을 대용할 수 있지 않을까?

정말로 효과가 있었다. 험이 거의 들리지 않는 것이다. 이 트랜스는 220V:0-3-6-9-12V 600mA의 제품이다. 600mA가 2차 정격이라면 1차 권선에는 이보다 권선비만큼 낮은 전류를 흘려야 한다. 그렇다면 초크 코일로 쓰기에는 용량이 너무 적지 않을까? 만약 과전류를 흘리고 있다면 열이 나거나 소리가 나빠질지도 모른다. 그러나 두 시간 정도 음악을 들으며 점검해 보았을 때 특별히 문제가 생기지 않았다. 초크 코일(전원트랜스)를 사이에 둔 전압 강하가 꽤 높은 것으로 보아 직류 저항 성분이 상당히 높은 것 같았다. 거의 470옴 저항 하나를 대체할 수준이었다. 초크 코일을 거친 다음에는 그라운드와의 사이에 전해 캐패시터를 하나 삽입해야 한다는데(전원 임피던스를 낮추기 위해?) 현 상태에서는 청감상 특별한 문제가 느껴지지 않는다. 늘 일정한 전류가 흐르는 A급의 저출력 앰프라서 그럴 것이다. 

전원트랜스의 전류 정격과 초크 코일의 전류 정격이 동등하지는 않을 것이다. 하지만 여기서는 대충 넘어가도록 하자.

5단 RC 필터의 저항은 100옴 저항을 2개씩 병렬로 연결하여 50옴/단으로 조정한 것이다. 따라서 등에 업힌 저항을 하나씩 끊으면 100옴/단으로 저항이 늘어난다. 그렇다면 전원회로기판을 거친 다음에도 전압이 충분히 떨어지지 않아서 시멘트 저항을 덕지덕지 붙일 필요가 없을지도 모른다. 그러나 1/2W의 저항에게는 감당하기 어려운 열이 날 수도 있다. 

저항이 저항을 하나씩 업고 있다. 총 5개의 합성 저항이 쓰였으며 3개는 기판 뒷면에서 직접 연결해 버렸다. 내 실력으로는 기판 윗면에 고정해 놓은 상태에서는 배선을 마무리하기가 너무 어려웠기 때문이다.

그동안의 경험과 제이앨범의 조언을 통해 들은 바에 의하면, 전원을 효과적으로 낮추려면 저항을 전원트랜스 직후에 삽입하는 것이 가장 좋다고 한다. 물론 발열 대책도 마련해야 한다. 이번 시험 제작에서는 합성 저항으로서 20옴을 사용했지만 권장치인 50옴을 사용했다면 전원회로의 말단에 저항을 계속해서 이어 붙이는 일은 없었을지도 모른다. 

자작의 장점은 케이스의 뚜껑을 닫지 않은 상태에서 작동 상태를 계속 관찰하면서 사고(?)가 발생하지 않는지를 관찰할 수 있다는 것이다. 그러고는 늘 만들다 만 것과 다를 바가 없는 상태를 유지하다가 어느날 맘에 들지 않는다 생각하고 완전히 뜯어 고치게 될 수도 있다. 그 흔적은 사진이나 기억, 그리고 블로그에만 남을 뿐이다.

이렇게 하여 2021년 오십 몇 회(?)의 생일 기념 자작을 마친다. 안전을 위해 최소한의 케이스 비슷한 것이라도 만들어 넣으려면 앞으로 일주일 정도는 더 걸릴 것이다.

2021년 5월 8일 토요일

5월 들어 처음 쓰는 글

연구 과제 관련한 서류를 준비하느라 뛰어다녔더니 5월하고도 벌써 8일이나 되도록 블로그에 아직 글을 한 편도 쓰지 못했다는 사실을 깨달았다. 마음의 여유가 없었던 것 같다. 2년이라는 길지 않은 기간 동안 기업체 파견 근무를 나갔다가 돌아와서 이제 한 달이 조금 더 지났다. 해야 할 일을 찾고, 또 나를 필요로 하는 사람들과 만나서 대화를 하는 과정 중에 조금씩 나의 자리로 되돌아 오고 있다는 느낌을 받는다. 기업에서 했던 일은 또 그것대로 새로운 '키워드'가 되어서 내 활동의 외연을 넓혀주고 있음을 기쁘게 생각한다. 나 자신을 소모하고 온 것이 아니라 새로운 보따리를 하나 챙겨서 돌아왔다는 표현이 맞을 것이다.

5월 8일은 나의 생일이기도 하다. 세상 구경을 하도록 낳아 주신 부모님에게 감사를, 그리고 부족한 용돈으로 티라미수 케이크를 사 온 아들 준영이에게도 고마움을!

미세먼지도 극심하고 701명 수준으로 부쩍 증가한 신종코로나바이러스감염증 확진자 수도 염려가 되어서 주말 외출은 자제하기로 하였다. 이럴 때에는 조용히 집에서 납땜이나 하고 있는 것이 좋은데, 납을 녹일 때 나오는 연기가 실내 공기 오염을 유발하는 원인이 되니 자주 환기를 하는 것이 바람직하다. 그런데 창문을 열면 외부의 미세먼지가 심하게 들어올 것이다. 이런..

6LQ8 싱글 앰프의 전원부를 새로 제작하는 것이 이번 주말의 과제이다. 원래는 하나의 전원부를 6LQ8 푸시풀 앰프와 공유하는 형태였으나, 푸시풀 앰프를 다시 만들면서 전원회로를 완전히 포함하는 것으로 바뀌는 바람에 싱글 앰프의 전원을 따로 만들어야 할 상황에 놓였다. 5월 4일 아세아전원에 주문한 전원 트랜스포머가 조금 전에 도착하였다.

참고할 회로도는 제이앨범에서 찾았다(링크). 캐패시터와 저항의 값은 앰프에 따라서 몇 가지 다른 버전으로 존재하는데, 내가 갖고 있는 부품 중에서 적당한 것을 골라서 사용할 생각이다. 오늘 저녁에는 오랜만에 6LQ8 싱글 앰프의 소리를 들을 수 있겠구나!
그림 출처: [제이앨범] 배전압 전원 PCB를 전파정류기로