2015년 8월 25일 화요일

아이패드와 Behringer UCA200 활용

USB 오디오 인터페이스 중에서 외부 전원 공급을 하지 않은 상태로 아이패드에 직접 연결(카메라 연결킷 사용)하여 사용 가능한 것은 별로 없다. 대부분 전원장치가 딸린 USB 허브를 통해서 연결해야만 한다. Behringer UCA200는 전원을 따로 공급하지 않고도 아이패드에 연결하여 사용 가능한 몇 안되는 오디오 인터페이스 중 하나이다. 모니터용 헤드폰을 꽂을 자리도, 자체 음량 조절 기능도 없다. 오직 USB 단자와 RCA로 되어있는 오디오 인/아웃 단자만 있을 뿐.

나는 최고 음질의 디지털 음악 재생에는 큰 관심이 없어서 DAC에는 신경을 거의 쓰지 않았다. 전적으로 아날로그 방식으로 소스를 앰프에 연결하여 스피커를 구동하는 시스템을 갖추고 연구(?)하는 데에만 몰두하였을 뿐이다. 주로 가요를 들을 때에는 아이패드의 이어폰 단자에 3.5mm 스테레오-RCA Y-케이블을 연결하여 앰프로 음악을 재생한다. 그런데 간혹 아이패드에 꽂힌 커넥터에 옆으로 힘을 주거나 약간 저급한 케이블을 사용하면 험과 비슷한 잡음이 발생한다.

베링거 오디오 인터페이스는 그동안 천덕꾸러기 신세였다. 사무실에 갖고 나가서 컴퓨터에 연결하여 몇번 음악감상을 하다가 오디오트랙 사운드카드(MAYA 5.1 MK-II ZEN)를 구입하게 되면서 서랍속에 처박힌 상태였다. 이를 다시 집에 가져와서 아이패드에 연결하여 사용하기로 하였다. 잡음 없이 깨끗한 소리가 난다.

저가품 일색의 음악감상 환경이지만 나름대로 기기를 골라서 듣는 재미가 있다.


[하루에 한 R] heatmap.2 그림을 조정해 보자

오늘은 하루에 '한 R'이 아니고 '두 R'이 되었다. gplots 패키지를 이용하여 그린 heatmap.2 플롯이 맘에 들지 않으니 손을 좀 대 보자. 어떤 문제가 있는가?
이것은 다음의 스크립트로 그려진 것이다.
> heatmap.2(as.matrix(data.final), col=greenred(10), trace="none")
우선 너무 작아서 있으나 없으나 소용이 없는 probe ID를 나타나지 않게 하자.
> heatmap.2(as.matrix(data.final), col=greenred(10), trace="none", labRow=NA)
Row의 label을 없애버린 것이다. 다음으로는 cexCol 파라미터를 줄여서 컬럼 라벨이 잘리지 않게 만들어 보자.
> heatmap.2(as.matrix(data.final), col=greenred(10), trace="none", labRow=NA, cexCol=0.7)
이상으로도 그렇게 나쁘지는 않다. 그러나 글자 크기를 줄임으로 인하여 가독성이 나빠졌다. 글씨 크기를 그대로 유지하려면 마진을 키우면 된다. 대신 정사각형으로 예쁘던 heatmap이 직사각형이 될 것이다. heatmap.2() 함수 안에서 사용하는 margins는 column/row의 라벨을 나타내는 공간에 관한 것이다. R의 plot area와 주변부의 여유 공간을 뜻하는 margin과는 다르다(참고 R graphics 생기초 링크)
> heatmap.2(as.matrix(data.final), col=greenred(10), trace="none", labRow=NA, margins=c(7,5))
컬럼 라벨(샘플명)의 크기는 그대로 유지되면서 마진이 늘어나는 바람에 글씨가 잘리지 않고 전부 보인다. heatmap이 직사각형으로 찌그러진 것이 보기 싫으면 margins=c(7.7)로 해 보라. heatmap 오른편의 마진이 늘어나면서 heatmap의 가로 사이즈가 줄고 이에 따라서 자연스럽게 정사각형으로 되돌아온다. 이것은 그림을 따로 첨부하지는 않겠다.

마지막으로 Color Key and Histogram이라는 글이 바로 아래의 color key와 살짝 겹치는 문제를 해결해 보자. keysize(기본 수치는 1.5)를 약간 줄여도 제목 텍스트와의 간격은 벌어지지 않는다. 결국 문제는 무엇인가 하면 Color Key and Histogram이라는 텍스트가 두 줄이 된 것이다. 이를 바로잡자고 해서 Key의 폭을 늘이면 heatmap의 폭이 줄어들 것이다. 만약 histogram을 표시할 필요가 없다면 heatmap.2(x,...density.info="none")이라고 하면 된다. 그러면 Color Key라고만 표시가 되어 한결 간결해진다.

좀 더 심화된 코스를 원하는가? 키, 덴드로그램, 힛맵의 레이아웃을 아예 바꾸는 방법도 있다. 이를 알아보려면 이 링크를 상세히 읽어보고 layout() 함수와 lmat 매트릭스 및 lwid, lhei 벡터를 이해해야 한다. 예전에는 종이에 그림을 그려가면서 열심히 공부했었는데 다 잊어버렸다! 오늘은 여기까지만 하자.

기타 heatmap으로 그려지는 플롯의 상세한 설정이 나와있는 설명은 다음 사이트를 참조하기 바란다.


[하루에 한 R] Expression data로 heatmap 그리기

오래전의 microarray 실험 데이터를 가지고 뒤늦은 논문을 쓰고 있다. 대단한 발견이라고 할만한 것은 없고, 너무 오래되어서 더 이상 시의성이 없는 데이터로 추락(?)하기 전에 일단락하여 발표하기 위함이다. 사실 과학에서는 과거의 연구성과가 상당한 시간이 흐른 뒤에 발굴되어 재평가되면서 과학계의 역사를 새로 쓰는 일이 다반사이다. 따라서 변신에 변신을 꾀하면서 지나치게 유행을 좇아 연구 분야 변신을 하는 것은 그렇게 바람직하지는 않다고 본다. '시대적 요청'이라는 것이 있기는 하지만 말이다.

heatmap 또는 heat map이란 데이터를 2차원 형태로 늘어놓고 각각의 값을 색으로 표현한 데이터 시각화 기법의 하나이다. 데이터의 배열을 행 또는 열에 따라 적절히 조절(clustering)함으로써 눈에 확 뜨이는 두드러지는 패턴을 찾아낼 수 있다.

21C 미생물프론티어 사업단 시절을 풍미했던 바로 그 대장균 microarray를 이용한 데이터를 이용해 보고자 한다. 한 개의 slide에 같은 프로브 셋이 두 개의 블록으로 나뉘어 찍혀 있으므로, 칩 하나로부터 두 개의 샘플 데이터가 얻어진다. 엄밀히 따지면 이렇게 나온 데이터는 technical replicate에 해당한다. 그러나 편의상 마치 biological replicate인 것처럼 다루었다. 이를 보고 '말도 안돼!'라고 외치실 분이 있을지도 모른다^^ 이번 포스팅에서는 R을 이용하여 QC, normalization, DEG 추출 등과 같은 expression analysis를 하는 방법을 다루고자 함이 아니다. 단지 hierarchical clustering을 동반한 heatmap을 그리는 작업을 설명하기 위해 고전적인 microarray data를 이용하는 것일 뿐이다.


처음에는 CLC Genomics Workbench의 Transcriptomics Analysis(과거에는 "Expression Analysis")로 heatmap을 그려 보았는데 도무지 마음에 드는 그림이 나오지 않았었다. CLC에서는 GEO 데이터를 어떻게 임포트하는가? GSE####_series_matrix.txt.gz 형식의 series matrix 파일을 다운로드하였다면 압축을 풀고 Import -> Standard Import 메뉴에서 파일 유형을 Expression array/data: GEO SOFT format series file (.txt/.text)로 설정하여 해당 파일을 읽어들이면 된다.

그러면 R을 사용해서 좀 더 예쁜 heatmap을 그려보자. R에 기본으로 내장된 heatmap() 함수는 그다지 예쁘지 않은데다가 사용자 입맛대로 조정을 할 여지가 별로 많지 않다. 따라서 gplots 패키지가 제공하는 heatmap.2() 함수가 인기를 끄는 모양이다. HeatPlus 라는 패키지도 있으니 참고하면 되겠다. 몇 가지 유용한 링크부터 먼저 소개하고 진행하겠다.

입력물로는 GEO에서 다운로드한 series matrix 파일을 이용하겠다. !로 시작하는 코멘트 라인은 전부 제거하여 헤더와 데이터 부분만을 남겼다. 이 파일은 이미 normalization과 log2 transformation이 된 상태이다. 파일명은 data.txt로 수정하여 접근하기 쉬운 폴더(C:\R_work)에 복사해 두었다. 첫번째 시도는 우선 되는대로 막 그리는 것.
> install.packages("gplots")
> library("gplots")
> setwd("C:R_work")
> data = read.table("data.txt", header=TRUE, sep="\t", row.names="ID_REF")
> jpeg("plot1.jpg")
> heatmap.2(as.matrix(data), col=greenred(10), trace="none")
> dev.off()

jpeg으로 출력한 그림을 보자. 어떤 문제점이 존재하는가? microarray data의 heatmap은 각 샘플이 얼마나 유사한지를 보여주기도 하므로 일종의 QC 개념으로 쓸 수도 있다. 동일 조건에서 나온 각 6개의 샘플들이 한데 묶이므로 일단 큰 문제는 없다. 단 하나의 슬라이드에서 나온 두 블록이 항상 가장 가까이 묶이지는 않았음을 기억은 해 두자. 샘플의 이름이 마진에 비해 너무 길어서 잘렸고, 4721개나 되는 probe의 수는 하나의 heatmap으로 표현하기에는 너무 많다. probe ID와 dendrogram이 제대로 보이질 않으니 말이다. 그리고 대부분의 데이터가 0 근처에 있어서 너무 밋밋한 그림이 되었다.

Plot의 마진을 설정하는 방법은 완전히 다른 주제라서 여기에서는 다루지 않겠다. 이제 그림을 좀 더 돋보이게 하는 방법을 알아보겠다. 

모든 컬럼에서 특정 조건(값의 범위)을 충족시키는 row만 남기기(미완?)

Two-color microarray experiment에서 얻어진 데이터이므로 log2(Fold_change)가 0 근처에 있는 것은 그림을 복잡하게만 만들뿐 heatmap에 남겨둘 필요가 없다. 특정 column의 값을 기준으로 하여 전체 row를 삭제하는 방법은 인터넷 검색에서 흔히 찾을 수 있다. 예를 들어 첫번째 컬럼의 값이 -0.5보다 크고 0.5보다 작은 것을 데이터에서 제외해 보자. 이를 "dropping"이라 한다.
> data.2 = data[-which(data[,1] > -0.5 & data[,1] < 0.5), ]
그렇다면 18개의 모든 컬럼에 대해서 -0.5 < 데이터값 < 0.5를 만족시키는 row를 일괄적으로 삭제하려면 어떻게 하면 좋을까? 어느 한 컬럼이라도 -0.5 .. 0.5의 범주에 들면 그 row를 삭제한다는 것이 아니고(이렇게 되면 너무 많은 row가 제거될 것이다), 모든 컬럼이 다 그럴 때에만 제거하지는 것이다. 데이터가 카운트 값이면 row 단위로 합하여 그것을 기준으로 하면 되겠지만 이번의 사례에서는 '범위'가 판단의 기준이라서 쉽지가 않다.

아주 단순하게는(그리고 미련하게는) which() 함수 내부의 조건에 해당하는 부분을 모든 컬럼으로 확장하면 된다. (data[,1] > -0.5 & data[,1] < 0.5) & (data[,2] > -0.5 & data[,2] < 0.5) & (data[,3] > -0.5 & data[,3] < 0.5) ... (data[,18] > -0.5 & data[,18] < 0.5) 오타가 안나도록 주의깊게 타이프를 치면 된다. 그런데 이 방법은 너무 우습지 않은가? 만약 dropping을 마친 row가 아직도 너무 많아서 cutoff 값을 바꾸고 싶다면? 구글링을 열심히 해 보았지만 이 경우 딱 맞는 솔루션은 보이질 않는다. R에서 별로 바람직하게 여겨지지 않는 for 문을 사용하여 어찌어찌 만들어 보았는데 최종적으로 선별된 프로브의 수가 너무 많아서 역시 구별이 가능한 수준의 그림이 만들어지질 않는다.

row를 값의 범위에 의해 선별하여 버리는 방법을 알아내는 것이 문제가 아니라, 남은 row 자체가 너무 많다는 것이 문제다. 결국은 논문 작업을 위해서 뽑아둔 DEG 목록을 활용하기로 하였다. 몇 그룹의 조건으로부터 총 813개의 DEG를 확보하여 all_DEG.txt 파일에 저장하였다. 한 줄에 하나씩의 probe ID가 들어있고 중복을 없애는 작업이 필요하다. scan() 함수를 사용하여 매트릭스 형태가 아닌 데이터 파일을 입력하는 것은 조금 복잡하다. 이 링크를 참조하여 추후에 조금 더 공부하도록 하자.
> deg = scan(file="all_DEGs.txt", what=list(probe=character()))
> deg.nr = unique(deg$probe)
여기까지 왔으면 heatmap 작성 대상 유전자(probe ID)의 목록이 deg.nr이라는 벡터에 들어있는 상태이다.

목록에 존재하는 row name에 해당하는 레코드만을 데이터프레임에서 추출하기

추출할 probe의 목록을 deg.nr이라는 벡터에 담았으니, 이를 참조하여 data 데이터프레임의 일부를 꺼내면 된다. 참조할 곳은 특정 컬럼이 아니라 row name에 해당한다.
> data.final = data[which(row.names(data) %in% deg.nr), ]
> heatmap.2(as.matrix(data.final), col=greenred(10), trace="none")
probe가 457개로 줄어들어서 한층 보기가 수월해졌다.


다음의 숙제는 plot의 마진을 설정하는 일이다. 아마도 par() 함수를 쓰게 되지 않을까 싶다.





awk의 매력

awk는 개발자(Alfred V. Aho, Peter J. Weinberger, Brian W. Kernighan)의 머릿글자를 딴 유틸리티로서 그 자체로 완벽한 "pattern-scanning & processing language"이다. 쉼표나 탭으로 구분된 필드를 지닌 텍스트 파일을 줄 단위로 읽어들여서 패턴을 탐색한 뒤 그 여부에 따라 조작된 결과를 내보내는 도구이다.

(바이오)펄이나 (바이오)파이썬을 사용하여 훨씬 고차원적인 일을 할 수 있음이 당연하다. 반면 awk는 매우 간단한 문법으로도 이에 버금가는 일을 하기에 부족함이 없다. 요즘은 Next-Gene Sequencing 데이터를 비롯한 염기서열 데이터를 awk로 조작하는 방법에 대한 문서를 작성하고 있다. 오류를 수정하고 테스트가 끝나면 인터넷을 통해 공개할 계획이다. 약 10쪽 내외의 분량이 될 것이다.

내가 처음으로 Perl을 익히면서 독학용 교재로 삼은 것은 바로 다음의 자료이다.

Perl in 20 pages by Russell Quong

1998년에 만들어진 이 문서의 원본 사이트는 더 이상 존재하지 않는 듯. 그 이후로 제대로 돈을 주고 산 Perl 관련 책은 [펄 쿡북] [Programming the Perl DBI] [Official Guide to Programming with CGI.pm]이 전부이다. 대부분의 자잘한 실무적인 기법들은 인터넷을 뒤져셔 구한것이 전부이다. 항상 부족하지만 그래도 개인적으로는 약 15년간에 걸쳐서 많은 발전을 이루었다고 자부한다.

2015년 8월 24일 월요일

이유 있는 게으름

나는 마감 일정에 쫒기어 일을 하는 것을 무척 싫어하는 성격이라서, 여유를 두고 일정을 짠 뒤에 업무를 처리하는 것이 습관이 되어 있다. 역설적인 현실이지만 가끔은 너무 빨리 일을 처리하여 도리어 손해를 보는 일이 생기기도 한다.

마감일이 멀찌감치 남은 일은 그만큼 많은 시간을 두고 심사숙고하여 알차게 내용을 채우라는 뜻이다. 그렇지만 이런 일은 항상 긴급을 요하는 일에 밀려서 계속 뒤쳐지게 된다.

'시간적 여유가 있으니까 급한 일 먼저 하지 뭐.'

이러다 보면 결국은 마감일이 다 되어서야 이 일을 하게 된다. 길었던 시간적 여유는 이 일에 거의 소용이 되지 못한다. 어쩌면 이렇게 일을 하는 것이 시간을 가장 효율적으로 쓰는 방법인지도 모른다.

늘 내일이나 주간의 할 일을 기억하거나 기록하려 애쓰고, 다이어리를 들고 다니면서 잠자리에 들기 전에도 떠오르는 일거리를 메모하고... 이런 생활 방식이 최선이라 생각했었는데, 요즘은 이런 태도가 나의 정신적 건강을 자꾸 갉아먹고 있다는 생각이 들었다. 시간적 여유가 있음에도 불구하고 빨리 일을 처리하고 다른 일을 하려다 어처구니없는 실수도 가끔 저지르기도 하고, 머리속은 늘 생각으로 꽉 차서 마음의 여유를 갖지 못한다.

스스로를 자꾸 채찍질하고 있다는 느낌을 지울 수가 없는 것이다.

조바심은 피로감을 낳는다. 생각해 보니 그렇게 살아야 할 이유가 별로 없는 것이다. 쉼표를 찍고 간다는 생각으로 여유를 갖자. 내 스스로에게 관대하지 못하면 다른 사람에게도 어느새 짜증을 내는 나 자신을 발견하게 된다.

업무용 서버 랙 구입


인증샷에 내 발이 찍혔다.

일반적인 사무용 책상의 높이에 해당하는 12U짜리 미니 서버 랙을 구입했는데 깊이가 생각보다 깊다는 것을 미처 생각하지 못했다. 전체적인 모양은 마치 가정용 냉장고를 눕혀놓은 것과 유사하다. 앞의 문짝만 제외하면 캐비넷과 같은 구조라는 기분이 영 들지 않는다. 지난주에 납품과 함께 설치가 일부 완료되었지만 내부 구조를 마음에 들게 직접 바꾸다가 정말 쓰러지는 줄 알았다! 고정용 사각 볼트는 왜 이렇게 끼워지질 않고 또 선반은 왜 이렇게 무거운지.. 땀을 뻘뻘 흘리며 손톱이 부러지도록 고정 작업을 하였다. 무척 힘이 들었지만, 그러면서도 '흠, 적성에 맞는군'하는 생각이 드는 것은 왜일까?

지금은 기가비트 스위치와 1U 서버가 장착이 된 상태이다. 연구소내 다른 서버실에서 가동되는 2U 서버를 내일쯤 가져올 예정이다. 그러면 이산가족처럼 이곳저곳에 흩어져 있던 서버들이 한 자리에 모인다. 모니터 뒤에는 NAS가 얹혀있다. 무척 소박한 전산 시스템이지만 일개 생물학자에게는 원심분리기와 딥프리저, PCR 머신을 돌리는 실험실과 같은 매우 소중한 자산이다. 서버를 숨겨놓은 골방(원래 통신설비가 있는 방)과 내 사무실 말고는 별도의 실험 공간이 없으니 이것이 내 실험실인 셈이다.

이렇게 서버 랙을 살 줄 알았더라면, 올해 신규 구매한 서버(오른쪽의 타워형)도 랙 마운트 타입으로 살 것을... 그러면 전부 말끔하게 서버 랙  하나에 수납이 될텐데. 

언제 일어날지 모를 비상사태에 대비하면서 서버 작동 소음과 냉방기 소리로 귀가 따가운 서버실에서 애쓰는 전산실 종사자들의 노고를 0.1% 정도 이해할 수 있었다.

요즘 생활의 활력을 주는 세 가지 활동

첫번째, 음악.

악기를 연주하는 것, 음악을 만드는 것(작곡 혹은 레코딩), 음악을 감상하는 것. 최근 2년 간의 활동은 주로 음악을 듣기 위한 환경을 만드는데 지나칠 정도로 쏠려있다. 기타와 건반아, 미안해! 집과 사무실에서 좀 더 양질의 음악을 듣기 위해 앰프와 스피커를 마련하는 것에 큰 재미를 느끼는 중이다. 진공관 앰프, class D 앰프, 어설프게 만든 full-range 스피커 시스템 등. 음악을 만드는 일은 제대로 시작도 해보지 못했는데 계속 나의 일정에서 멀어져만 간다.

두번째, 컴퓨터.

동료들에게 컴퓨터를 이용한 미생물 유전체 분석 기법을 전수하면서 자연스럽게 리눅스의 기초와 활용 기술을 다시금 공부하게 된다. awk가 이렇게 멋진 기능이 많은 유틸리티였구나! 더구나 전산실 전문인력이 아니면서 직접 서버를 몇 대 운용하는 과정에서 자잘한 노하우를 많이 익히게 되고, 많은 즐거움과 보람을 느낀다. 지난주에는 조그만 서버 랙을 구입하여 흩어져있던 서버들을 모으고 있다. 조금 전에는 기가비트 네트웍 스위치에 랙 고정용 날개를 달아서 랙 맨 위칸에 고정하고 왔다. 땀을 뻘뻘 흘리면서...

세번째, 집 보수하기(DIY).

스피커 인클로저를 만들면서 남은 페인트가 일의 발단이 되었다. 습기에 노출되어 검게 썩어서 떨어져 나가던 욕실문을 보수하면서 집안의 다른 문과 창(틀)에 자꾸 관심이 간다. 한번에 다 해치우기는 어렵지만 주말을 이용하면 문 2~3개 정도는 작업이 가능할 것 같다. 테인트를 바르고 마르는 동안 다른 문짝을 작업하면 되니까 말이다. 물론 몸은 꽤 고단하겠지만 말이다. 스피커통을 마감하는 과정에서 자연스럽게 목재의 마감에 대한 관심이 늘어나게 되고, 살면서 조금씩 낡아가는 집을 다른 사람의 손을 빌리지 않고 직접 보수하는 일에 도전하는 재미가 쏠쏠하다.