2023년 2월 25일 토요일

또 하나의 기타, Dame(Saint M250 VGNT로 추정)

아내의 배려로 기타 스탠드(3대 거치용)의 허전하게 남아있던 빈 곳을 채울 '관상용' 일렉트릭 기타를 구입하게 되었다. 지난번 DBZ Cavallo 기타를 산 것이 겨우 한 달 전이었으니 너무 빨리 기회가 돌아온 것인지도 모르겠다.

며칠 동안의 고통스러운(?) 중고 기타 탐색 작업 끝에 결국은 또 뮬 악기장터에서 적당한 것을 구할 수 있었다. 당근마켓이나 네이버 중고나라는 매물이 올라오자마자 금방 사라져서 구입 기회를 잡기가 어렵다. 기록을 위해 판매글 링크를 남겨둔다(2023년 10월 19일 확인해 보니 이 링크는 사라졌다).

마호가니 몸체에 플레임 메이플이 올려진 24 프렛 Dame 기타를 풍성한 악세사리(스탠드 두 개, JamMate RockFrog, 스트랩, 새것이나 다름없는 가방)와 함께 좋은 가격에 인수하였다. 아래쪽 스트랩 핀 근처의 투명 도장 마감이 조금 깨진 것을 제외하면 관리가 잘 되어 있었다. 금속 부분의 광택도 잘 살아 있고, 지판에도 나에게 넘겨지기 직전 새로 바른 오일이 살짝 남은 상태이다. 프렛의 수, 픽업 구성 등으로 미루어 보면 데임의 일렉트릭 기타 모델 중 Saint M250 VGNT(vintage natural)로 추정된다. 제조국은 인도네시아. 데임 본사에 시리얼번호 조회를 문의하니 2006년도 생산이라고 하였다.

스트링 리테이너는 나사못을 조여서 고정해 놓았다.


전기기타용  USB 인터페이스인 RockFrog. 나는 리눅스에서 사용하기에 매우 편리한 이런 스타일의 물건을 좋아한다. 

흥미롭게도 프리앰프(부스터?)를 내장하였다. 중고로 구입할 때부터 개조가 되어 있었다고 한다. 혹시 전전 주인이 이 글을 접하게 되면 반가워할 것 같다. 게인과 볼륨 조절을 위한 노브 두 개는 뒷면에 위치하였으며, 전원 투입용 토글 스위치는 전면에 위치한다. 이를 달기 위해 아름다운 플레임 메이플 탑에 구멍을 뚫는 것도 큰 결심이 필요했으리라!

노브는 새것으로 교체하였다고 한다.


2N7000 MOSFET을 사용한 부스터 회로 기판(사례는 여기를 참조)이 내부에 들어있다.

백플레이트는 없다. 이걸 제거했더니 소리가 좋아졌다는 전설 같은 이야기가 있다(링크).

뒤를 열어 보았더니 작은 인쇄회로기판과 9V 건전지가 들어 있었다. 구글에서 'electric guitar gain boost circuit'로 검색하면 많은 정보가 나온다. 별도의 전원을 사용하는 게인 부스터를 기타 내부에 넣는 이유는 무엇인지 모르겠지만 음악감상용 앰프 자작에 약간의 경험이 있는 내가 이를 가볍게 여기고 싶지는 않다. 새로운 공부 거리를 얻은 것을 즐겁게 여기도록 하겠다.

단, 전면의 톤 노브를 시계방향으로 끝까지 돌리면 소리가 나지 않는 기이한 현상이 벌어진다. 전 주인도 이런 상태에 대해서 판매 글에 분명히 언급하였었다. 일부러 이렇게 만든 것일까, 혹은 배선의 실수인가? 의도적으로 이렇게 동작하도록 만들기도 어려울 것 같다. 

멀티미터를 연결해 놓고 톤 포텐셔미터를 돌려 보았다. 시계방향으로 끝까지 돌리면 0옴이 된다. 흠, 슬라이더를 끝까지 돌리면 그라운드에 닿는다는 뜻인데...

전기 기타의 내부 회로를 공부한 다음 뒷뚜껑을 다시 열어 보았다. Pinterst 등에서 실체 배선도 형태의 회로를 쉽게 찾아볼 수 있다. 톤 조절 노브를 시계방향으로 돌리면, 주파수가 높은 신호를 그라운드로 보내버리는 경로의 저항이 높아져서 고음이 많이 출력되는 매우 심플한 구조이다.톤을 조절하는 포텐셔미터의 3번 핀(pin or lug)은 아무 곳에도 연결하지 않는 것이 정석이다. 일반적인 오디오 앰플리파이어의 passive tone control circuit과 비교해 보라.

그림 출처: Amplified Parts 


 포텐셔미터를 앞에서(손잡이쪽) 보았을 때 핀 번호는 왼쪽부터 1-2(슬라이더)-3의 순이 된다. 따라서 3번 핀은 손잡이를 시계방향으로 끝까지 돌렸을 때 슬라이더가 닿는 곳이 된다. 그런데 석연치 않은 점을 발견하였다. 아무런 전선도 연결되지 않은 3번 핀이 기타 내부 벽에 발라 놓은 카본 실드에 닿아 있는 것 아닌가. 여기는 당연히 회로의 그라운드와 연결되어 있을 것이다.

무릎을 탁 쳤다. 아! 문제는 여기에 있었구나. 포텐셔미터를 살짝 돌려서 3번 핀을 카본 실드에서 떨어지게 한 뒤 최대한 닿지 않게 러그를 구부린 다음 바로 곁의 카본 실드면에 절연 테이프를 발랐다. 역시 내 예상이 맞았다. 톤 노브를 시계 방향으로 돌리면 고음이 증가하면서 카랑카랑한 소리가 났다. 노브를 끝까지 돌렸을 때 소리가 전혀 나지 않는 현상이 이제는 일어나지 않았다.

절연 테이프를 붙이기 직전의 상태. 톤 조절용 포텐셔미터의 본체를 반시계방향으로 살짝 돌림과 동시에 3번 핀을 구부려서 더이상 벽면의 카본 실드에 닿지 않게 하였다.


나의 피크 꽂이.

내가 '데임'이라는 기타 브랜드와 이렇게 인연을 맺게 될 줄이야... 자잘한 문제를 해결하였으니 이제 남은 것은 연습뿐이다. 

Bernth의 동영상 5 picking tips to save years of guitar practice! 중에서.

오스트리아의 기타 연주자, 작곡가이자 유튜버인 Bernth교육 사이트에 가입하여 진지하게 연습을 시작할 것을 고민해 보자. 국내에도 많은 온라인 레슨이 있지만, Bernth가 제공하는 유튜브 동영상이 꽤 재미있기 때문이다.


2023년 2월 21일 화요일

Performaxe라는 기묘한 물건

Flying V형의 기타를 앉아서 치려면 편안한 자세가 잘 나오지 않는다. 다리 사이에 몸체의 뾰족한 부분을 끼우듯이 위치를 잡은 뒤 치는 것이 일반적으로 권고하는 자세인데, 이렇게 하면 상체와 기타 사이에 공간이 떠서 안정적으로 유지하기가 힘들다. 특히 얇은 기타의 몸체가 왼쪽 허벅지를 

네이버의 직장인 일렉기타 카페를 들락거리다가 Performaxe라는 기묘한 물건을 발견하였다. 일반명은 electric guitar leg rest로서, mule에 사용기가 올라와 있다. Flying V에는 다음 사진과 같이 장착하면 된다.

사진 출처: Guitar Scientist


매우 쓸만한 아이디어 상품이지만 가격이 너무 비싸고, 현재는 재고가 없다. 이 디자인을 응용(도용?)하여 자체적으로 만들 수는 없을까? 어설프지만 CAD로 도면을 그릴 수는 있으니, 아크릴, 목재, 볼트 및 나비너트를 이용하면 가능할 것도 같은데...

[하루에 한 R] ComplexHeatmap에서 특정 row label을 볼드로 표시하기

미생물 균주의 ANI와 dDDH를 절반씩 혼합한 매트릭스를 만든 뒤 균주 이름을 표시한 row label 중 type strain에 해당하는 것을 bold로 표현하기 위한 방법을 찾아 보았다. 다음의 글은 pheatmap 패키지를 사용한 것으로서 함수 구조가 비슷한 ComplexHeatmap 환경에서도 적용할 수 있었다.

[Stack Overflow] How to label some rowname of heatmap in bold and other in italic



이 함수를 변형하여 원하는 바를 달성하기는 했지만 %>%(chain operator), walk(), bquote(), as.expression() 등 내가 거의 쓰지 않는 구문을 사용하고 있어서 완벽하게 이해하기 어려웠다. 특히 그림을 그릴 매트릭스(실제로는 데이터프레임)의 row 및 column 이름은 단순한 genome assembly accession(GCF_#########.#)이고, heatmap 그림에서는 이를 풀어서 균주의 구체적인 이름(예: Paenibacillus polymyxa E681)으로 나타내야 하기 때문에 기본 예제에 대해 손을 댈 곳이 많았다.

ComplexHeatmap의 개발자는 gridtext라는 것을 사용하여 heatmap에 표현되는 텍스트의 여러 속성을 제어하는 방법을 설명하였다(링크). Heatmap() 함수의 인자에  row_names_gp = gpar(fontface = vector)를 지정하면 된다. vector는 c("plain", "bold", "italic", "bold.italic"...)의 형태로 주어진다. 10.3.2 Row/column names 서브섹션에 실제 활용 사례가 나온다.

내가 사용한 코드를 약간 단순하게 정리하면 대략 다음과 같다. 데이터프레임의 column/row label과 실제로 heatmap에서 표시하고 싶은 균주 이름을 accession-label.csv라는 별도의 텍스트 파일로 마련한 다음 R에서 읽어들여 key라는 named vector를 만들었다. ff_vector는 각 row label의 표시 방식(plain, bold...)를 담고 있다. 클러스터링은 dend라는 외부 자료를 기준으로 실행한다는 것도 중요하다. dend는 phylo가 아니라 dendrogram class여야 함에 유의하자. 나에게는 Heatmap() 함수를 실행하기 전의 코드 조각이 더 유용한 것 같다. 트리를 나눈 뒤 각 클레이드의 가지를 다른 색깔로 표시하고 heatmap도 이에 따라 분리해 놓는 방법에 대해서는 아래 코드에 기재하지 않았다. Legend의 커스터마이제이션도 마찬가지로 표시하지는 않았다.

# 균주 정보를 담은 named vector "key" 생성하기
data = read.table("accession-label.csv", sep=",", stringsAsFactors=F)
key = data[,2] # "GCF_000146875.3 Paenibacillus polymyxa E681"
names(key) = data[,1] # "GCF_000146875.3"

type_strain_acc = c("GCF_000000000.1", "GCF_111111111.1", "GCF_222222222.1")

n = length(rownames(total))
ff_vector = rep("plain", n)

for (i in 1:n) {
   if (rownames(total)[i] %in% type_strain_acc) {
      ff_vector[i] = "bold"
   }
}

ht = Heatmap(as.matrix(total), row_labels = key[rownames(total)],
        cluster_rows = dend, cluster_columns = dend, col = col_rnorm,
        row_title = "ANI", column_title = "dDDH", 
        row_names_gp = gpar(fontsize = 8, fontface = ff_vector), 
        column_names_gp = gpar(fontsize = 8),
        )
draw(ht)

부득이하게 column/row label을 "블러" 처리하였다.


약 일주일에 걸쳐서 무궁무진하고 다채로운 ComplexHeatmap 세계의 아주 좁은 구석을 돌아다녀 보았다. 덩달아서 한참 동안이나 손을 놓고 있었던 R 기능의 세부적인 사항을 공부하는 아주 좋은 계기가 되었음은 두말할 나위도 없다. 이렇게 멋진 패키지를 개발한 "bioinformagician" Zuguang Gu에게 무한한 감사의 뜻을 전한다.

2023년 2월 20일 월요일

우분투 환경의 R에서 일부 패키지가 설치되지 않을 때(dependencies 'xml2', 'curl' are not availble)

Xubuntu에서 R을 실행한 다음 몇 가지 패키지를 설치하려는데 dependency가 충족되지 않았다면서 실패하였다. 사정을 자세하게 살펴보면 다음과 같다.

  1. 컴퓨터에는 Windows가 깔려 있다. 보안이 좀 유별난 곳이라서 R 4.2.1에서 설치되지 않는 패키지가 있어서 VirtualBox로 Xubuntu를 설치한 뒤 그 안에서 R을 돌리면 Windows에서 문제가 되는 패키지가 잘 깔렸다.
  2. VirtualBox 내의 Xubuntu에서 대부분의 작업을 하다가 tidyverse 및 gridtext 패키지를 설치하려니 xml2, curl dependency가 충족되지 않았다면서 실패하였다.

에러 메시지는 이러하다.

ERROR: dependencies ‘xml2’, ‘curl’ are not available for package ‘XYZ’

흠, 집에서 노트북 컴퓨터(Windows)로 일을 해야 되나... 그냥 포기하기에는 아까워서 검색을 해 보니 R에서 결핍을 호소하는 dependency는 OS 차원의 문제라는 것을 알았다. 커맨드 프롬프트로 나가서 몇 개 패키지를 설치한 뒤 다시 R로 돌아오면 된다는 것이다. 참고한 글은 다음과 같다.

[Stack Overflow] R ERROR: dependencies 'xml2', 'httr' are not available for package (Linux Mint 20.1)

여기에서는 다음의 명령어를 실행하라고 제안하였다.

sudo apt install build-essential libcurl4-gnutls-dev libxml2-dev libssl-dev

결과는? 깔끔하게 tidyverse 및 gridtext 패키지 설치에 성공하였다. 문제의 원인은 아주 간단한 곳에 있었다. 집에서 사용하는 우분투 데스크탑 서버는 개발용 환경이 충분히 깔려 있는 상태이고, 사무실 PC는 Windows 내의 VirtualBox에 설치한 Xubuntu라서 최소한의 것만이 설치된 상태이다. 당연히 이러한 부작용이 일어날 수 있는 상황이었다. 혹시 내가 예전에 써 둔 글에서 이미 문제 해결방법을 기록해 둔 것은 아닌지 모르겠다.

문제를 해결하였으므로 ComplexHeatmap에서 특정 row label의 표현 방법(예: 볼드체로 표시)을 바꾸는 연습을 할 수 있게 되었다. 함수를 이용하는 트릭과 gridtext를 사용하는 방법을 연구해 본 뒤 나중에 별도의 글로 작성할 예정이다.

2023년 2월 15일 수요일

[하루에 한 R] ComplexHeatmap 맛보기

내 위키 사이트에 별도로 작성해 두었던 ANI 매트릭스 자료 분석법 문서를 수정하여 ComplexHeatmap의 Heatmap() 함수를 다루는 방법을 추가하였다. 앞으로 특별한 일이 없다면 gplots의 heatmap.2() 함수를 쓸 일은 없을 것 같다.

R을 이용하여 ANI matrix 자료 다루기

아직까지는 Heatmap() 함수 기능의 아주 일부분을 체험해 본 것에 불과하다.




Heatmap의 색은 데이터 수치에 따라 파랑-하양-빨강으로 분포하게 되는데, 이를 하양-빨강의 단색 계열의 명암으로 나타낼 방법은 없을까? ComplexHeatmap Complete Reference의 7번 Legends 섹션을 계속 들여다 보았지만,  새로 추가하는 legend는 자유롭게 수정이 가능하지만 heatmap에서 자체적으로 생성되는 legend의 색을 바꾸는 방법이 보이지를 않았다. 

이걸 사용자 입맛대로 바꾸지 못한다는 것은 말이 되지 않는다. 어디에 있을까... 아, 섹션 4의 A list of heatmaps를 둘러보니 하나의 플롯에 그려진 heatmap 두 개의 색상 체계가 다른 것을 발견하였다.

그림 출처 링크


가운데 heatmap을 그린 명령어를 확인해 보았다.

col_rnorm = colorRamp2(c(-3, 0, 3), c("green", "white", "red"))
col_runif = colorRamp2(c(0, 3), c("white", "orange"))
col_letters = c("a" = "pink", "b" = "purple", "c" = "blue")
ht1 = Heatmap(mat1, name = "rnorm", col = col_rnorm,
    row_title = "Heatmap 1", column_title = "Heatmap 1")
ht2 = Heatmap(mat2, name = "runif", col = col_runif,
    row_title = "Heatmap 2", column_title = "Heatmap 2")
ht3 = Heatmap(le, name = "letters", col = col_letters)
ht_list = ht1 + ht2 + ht3

두번째 줄이 유력한 용의자이다. colorRamp2() 함수는 circlize 패키지에서 제공하는데, 이는 ComplexHeatmap의 개발자인 "Bioinformagician" Zuguang Gu의 작품이기도 하다. 추앙하고 싶은 생명정보학자 리스트에 그의 이름을 올리겠다.

자, 그러면 흉내내기를 시작한다.

col_runif = colorRamp2(c(0.85, 1), c("white", "orange"))
Heatmap(as.matrix(ani), name = "ANI", row_labels = key.2[rownames(ani)], 
   row_names_gp = gpar(fontsize = 5), column_names_gp = gpar(fontsize = 5), 
   col = col_runif)
화면 캡쳐하다가 column dendrogram이 잘렸다.


다음 과제물 해결을 위한 힌트는 여기에서 얻도록 한다. 오늘은 힘들어서 더 이상은 못 하겠다.

Changing the default background color


2023년 2월 16일 업데이트

두 heatmap의 절반씩을 합쳐서 하나로 만들면 소원이 없겠네...



투명 이미지를 활용? 고민해 보자. 노동집약적인 방법을 동원한 결과는 다음과 같다.



포토샵을 잘 다루는 아들녀석에게 마무리를 위한 하청(?)을 주려다가 R 내에서 어떻게든 해 보기로 했다. 색상을 잘 선택하면 성격이 다른 두 자료를 하나의 매트릭스로 합쳐서 heatmap을 그려도 구별이 잘 되게 할 수 있을 것만 같다.