2018년 7월 10일 화요일

Anvi'o의 사소한 문제점 개선하기

지난주부터 Anvi'o(Advanced analysis and visualization platform for 'omics data)에 관심을 갖고서 설치 및 테스트를 진행하고 있다. 설치와 사용이 쉽고 project page에서 풍부한 문서를 제공하고 있어서 초심자도 무난하게 사용할 수 있다. 오늘은 실제 부딛혔던 사소한 문제와 그 해결책에 대한 경험을 정리하고자 한다. 돌이켜보니 그렇게 큰 좌절은 아니었었다.

설치 방법

Homebrew, conda, 직접 설치, 혹은 docker 등 몇 가지 방법 중에서 원하는 것을 택하면 된다. 나는 처음에 conda를 이용하여 아주 쉽게 설치를 했으나 프로젝트 페이지에서 설명한 몇 가지 스크립트가 아예 깔리지 않은 것을 발견하였다. 왜 이런 일이 발생했는가? 그 이유는 다음과 같다.

  • Anvi'o의 실행에는 python 3이 필요하다. 이것을 미처 모르고 python 2.7 기반의 conda environment에 Anvi'o를 설치했던 것이다.
  • 프로젝트 페이지에 설명된 기능은 최신판인 v5.1을 기준으로 한 것이다. 예를 들어 function enrichment analysis와 ANI 분석 같은 것은 예전 버전에는 구현되지 않았다. 아쉽게도 Anvi'o의 bioconda 패키지는 v4.0이다.
다른 workflow가 잘 도는 것을 확인했음에도 불구하고 ANI 계산용 스크립트인 anvi-compute-ani가 아예 존재하지 않았다. 왜 그런지 탐구해 보니 위에서 나열한 두 번째 이유에 의한 것이었다. 그래서 docker image를 사용한다면 번거로운 설치 과정을 거치지 않고도 anvi'o의 모든 기능을 사용할 수 있을 것으로 생각했었다. 그러나...

Anvi'o docker image의 사소한 문제

Docker의 정의를 내린다면 "an open platform for distributed applications for developers and sysadmins"라 할 수 있다. Docker가 어떻게 돌아가는지를 깊게 이해하지 못해도 개발자가 배포한 이미지를 가져와서("docker pull <이미지 이름>") 컨테이너를 생성하는 것("docker run <이미지 이름>")으로 실행한다는 것 정도만 기억하면 족하다. 도커 컨테이너는 이미지가 실행된 상태를 뜻한다. 사실은 문제 해결을 위해서는 이보다 조금은 더 깊은 지식이 필요하다.

$ docker run --rm -p 8080:8080 -v /home/merenbey/my_data:/my_data -it meren/anvio:latest
:: anvi`o ::  / >>>

위와 같이 실행하여 anvi'o의 최신판 v5.1의 이미지를 실행하였다. 기본적인 pangenome 분석은 해 놓았고, 이어서 anvi-compute-ani을 실행하여 ANI 분석을 시도하였는데 다음과 같은 에러가 발생하는 것이었다.
Config Error: PyANI returned with non-zero exit code, there may be some errors. please check the log file for details.
 실제 ANI의 계산은 PyANI(average_nucleotide_identity.py)에 의해 이루어진다. 왜 이런 에러가 발생하는 것일까? PyANI의 로그 파일을 열어보았다. vim 등의 기본 에디터가 없어서 좀 불편한다.


pandas가 없다고? pip를 이용하여 설치된 python library를 확인하려는데 pip도 없다. 이걸 어떻게 해야 하나? 컨테이너 안에서 apt-get, pip... 이런 것을 깔아야 되나? 컨테이너에서 빠져나오면 이런 설정 사항은 다 없어지는데? 약간의 삽질을 하다가 이런 문제가 생긴 원인을 발견하였다. Anvi'o에 딸린 모든 python 스크립트는  python 3을 기반으로 한다. 따라서 pip3는 존재한다. /usr/local/bin/anvi-compute-ani를 열어보면 첫 줄(흔히 shebang line이라 부름)에는 다음과 같이 씌여있다.
#!/usr/bin/python3
그러나 Anvi'o 컨테이너의 default python interpreter는? 커맨드라인에서 python -V을 치면 Python 2.7.12가 출력된다. 그렇다면 /usr/local/bin/average_nucleotide_identity.py의 shebang line은?
#!/usr/bin/env python
그렇다. PyANI 스크립트는 시스템 기본 버전인 python 2.7의 위치에서 pandas를 찾으려고 애를 쓰는 것이다!  pip3 freeze를 해 보면 python 3.x의 pandas가 잘 존재함을 확인할 수 있다. PyANI가 python3을 사용해서 돌게만 만들면 모든 문제가 해결될 것으로 생각하여 average_nucleotide_identity.py 스크립트를 편집하려 했는데, 문제는 docker container에는 편집기로 쓸만한 것이 없다는 것이다. vim을 설치하려니 apt-get update부터 시작해야 한다. 만약 호스트 터미널로 되돌아가면 컨테이너 내에 설치했던 프로그램은 전부 사라질 것이다. 이를 유지하는 방법은 나중에 생각해 보기로 하자.

다소 번거롭지만 vim을 설치하여 /usr/local/bin/average_nucleotide_identity.py의 첫 줄을 #!/usr/bin/env python로 수정한 다음 anvi-compute-ani를 실행해 보았다. 이번에는 아무런 에러가 없이 잘 진행이 되었고 ani-display-pan으로 그 결과를 확인하였다. 웹브라우저를 연 뒤 Layer 탭으로 가서 ANI 관련 사항을 체크한 뒤 그림을 다시 그려야 ANI heatmap이 보인다. Layer는 anvi'o의 시각화에서 매우 중요한 개념이므로 관련 문서를 찾아서 철저히 읽어봐야 되겠다. 데이터 파일이 있는 디렉토리에 shebang line을 수정한 average_nucleotide_identity.py 스크립트를 준비해 둔 다음 컨테이너 내에서 이를 /usr/local/bin/ 위치에 복사하는 것도 일종의 꼼수가 되겠다.

average_nucleotide_identity.py을 고치기가 귀찮다면 /usr/bin/python3를 /usr/bin/python이란 이름으로 바꾸어도 된다. 어차피 python 2.7은 필요가 없고, 컨테이너를 나가면 아무런 흔적을 남기지 않기 때문이다.

Docker 내부에 프로그램 설치하고 재활용하기

다음 웹페이지에서 힌트를 얻었다. 두번째의 PDF 파일은 무작정 따라하면서 기본 개념을 익히는데 도움이 될 것으로 생각한다. 그런데 여기에서 지시한대로 따라하면 docker import가 잘 되지 않는다. 세번째 자료도 매우 잘 작성되어서 도움이 많이 될 것이다.

[pyrasis.com] Docker 기본 사용법 추천!

docker run으로 Anvi'o 컨테이너를 생성하여라. 그 안에서 apt-get update, apt-get install vim을 하여 필요한 프로그램을 설치하고 /usr/local/bin/average_nucleotide_identity.py도 편집을 하여라. 그 다음 별도의 터미널 창에서 docker ps를 하여 현재 돌고 있는 Anvi'o 컨테이너의 ID를 확인한다. 이제 docker commit 명령을 실행할 단계이다.
# docker commit e47956140b67 my_docker_image
Image의 이름으로 쓸 수 있는 문자에는 한계가 있다. 오직 [a-z0-9-_.]만 허용이 된다. 이렇게 하여 나만의 docker image를 만든 것이다. 이를 실행하려면 docker run [options] my_docker_image를 하면 된다. 그 안에서는 vim도 실행이 되고, average_nucleotide_identity.py도 변경된 shebang line을 유지하고 있다.

아직도 docker run --rm의 의미를 이해하지 못하고 있다!

--rm 옵션은 컨테이너가 종료되었을 때 이를 자동으로 제거한다. 이 옵션이 없으면 현재 실행 중이 컨테이너의 변경 상태(패키지 설치, 파일 생성 및 변경 등)가 다음번에 docker run을 실행할 때에도 유지될 것 같은데 실제로는 그렇지 않다. 내가 아직도 docker에 대한 기본 이해가 부족한 것이다.

댓글 없음: