Friday, October 29, 2010

miRNA-seq

miRNA seq에 대한 분석을 리뷰 하기위해.. 다음과 같은 논문을 정리한다.


1.discovering microRNAs from deep sequencing data using miRDeep (Nature computational biology 2008)
2.Current tools for the identification of miRNA genes and their targets (Nucleic Acids Research 2009)
3.miRTRAP, a computational method for the systematic identification of miRNAs from high throughput sequencing data (2010 Genome Biology)
4.DSAP: deep-sequencing small RNA analysis pipeline (2010 Nucleic Acids Research)


위의 1번 논문은 거의 NGS 데어터를 이용한 miRNA 분석의 초창기 논문으로 볼수 있으며
2번 논문의 경우 거의 computational prediction에 가까운 논문이고 3번은 전혀 들여가 보지 않았으며 4번의 경우 web-server로 최근에 나온 논문.


다른건 모르겠는데.. isomiRs를 찾기위한(?) alignment 및 multiple alignment에 대한 공부가 필요한 것 같다(한때 BSA 책 공부 할때 바짝 up 됐었는데...).




PPT

bit 연산자

-사례 1
context.Dr7 |= 1 << (available * 2)
"파이썬 해킹 프로그래밍"이라는 책을 보고 있는데 하드포인트브레이크를 설정할때 위와 같은 구절이 나온다. 도대체 |= 는 뭔가? 평소에 잘 보지 않은 연산자로 보아 비트 연산자 일거고.. 사실 위의 구절이 하려는 의도(디버그 레지스터인 Dr7는 0~3까지 디버그 레지스터인 Dr0~3까지의스위치 역할을 하기에 0~3번째 위치의 bit 를 on 해주기 위한 것)를 이미 알기에 대략 추측을 햇지만.. << 는 비트를 왼쪽으로 미는것일거고 |=는 다양한 시도 끝에.. 아 bitwise or인 | 를 실행 시키고 그 결과를 대입 연산자 = 를 통해 다시 context.Dr7에 넣는구나라는 것을 깨달았다.


available 이 1이라고 가정하고 bin(context.Dr7) =  0b1010이라고 하면 1<< (1*2) 이므로 bin(1<<(available*2)) = 0b100 이 될 것이기에 0b1010과 0b100을 bitwise or로 하면 0b1110이 될것이고 그 값이 Dr7에 들어 가게 된다.


결과적으로 변수의 특정 위치(그러니까 그 변수의 특정 포지션의 bit)에 특정값을 밀어 넣는다고 생각하면 된다.


 -사례 2
전에 포스팅한 reference free short read validation의 논문의 quarc인가 하는 프로그램을 들여다 보면 K-mer 를 int 형 배열에 넣는데, K-mer에 K를 2라고 가정하면 종류가 최대 4**2=16가지의 K-mer 가 생성되기때문에 
_base2int = int[16]
d_base = {'A':0, 'G':1, 'C':2, 'T':3} 으로 해서 "AC" 라는 K-mer가 있으면 value= 0 으로 초기화 한뒤 value += d_base['A'] ; value = value << 2; value += d_base['C'] 식으로 각 K-mer의 index value를 만드뒤 이 값을 이용해서 _base2int의 값에 접근.

Thursday, October 28, 2010

circos

용주형의 특명으로 살펴보게된 circos. 사실 알아두면 나중에 필요할 일이 생길거 같다는 느낌에 보게되었다.
circos는 comparative genomics 데이터를 visualization하기 좋은 툴이다. 물론 개발자는 여러다른 예를 들지만..

처음에 메뉴얼 찾는데 웹페이지를 막 뒤지고 다운 받을 수 있는 모든 pdf를 다운 받고 훓어본 결과...
http://mkweb.bcgsc.ca/circos/tutorials/course/ 로 가서 개발자가 여러 컨퍼런스에서 강연했던 자료인 handout이랑 slide에 대한 ppt를 다운 받고 handout은 글이 많으므로 slide만 보면 대충 내용이 파악된다.
xml 처럼(이런게 xml 형식인가?.. 여튼) 그리고자 하는 결과의 component들을 인풋 파일로 정의해주고 이를 태그로 나타내주면 그려주는 형식이다.

개발자의 홈피를 가면 재밌는게 많은거 같은데.. 이 사람.. 색다르다. CSH 에서 나오는 저널중에 하나의 표지도 이사람이 만들었다는데(DNA sequence를 GC content로 색깔을 나타내고 sequence fragment repeat frequency로 curve를 만들어서 그렸는데 보면 무슨 virus를 형광 다이로 염색한 듯한 모습이다).. visualization에 매력을 느끼게 한다.

Saturday, October 23, 2010

python 개발 환경 구축

요즘 보는 있는 python 책들 어디서나 IDE(intergrated development enviroment)로 eclipse와 PyDev를 추천한다. 해서 미루다 미루다 미루다 오늘 한번 새로운 IDE로 이를 써볼려고 install 중이다.


1.eclipse + PyDev install
의외로 간단하다. eclipse 홈피 가서 eclipse 다운받고(난 classic 버젼으로 다운 받음) 그뒤 eclipse 압축 풀고 그담에 실행 시키고 help 메뉴로 가서 install new software을 선택한 뒤에 work with란에 http://pydev.org/updates 라고 넣어준다음에 pydev를 클릭해서 인스톨한다.
그뒤 다시 eclipse를 재실행 시킨후 window 메뉴에서 preferences 메뉴를 선택한뒤 PyDev 트리 마이템을 펼쳐 Interpreter에 python을 선택한다. 그리고 나타나는 대화상자 상단에 python interpreter 섹션에 new 버튼을 클린한뒤에 browser에서 python실행 파일을 선택하고 open 버튼을 누르고 나면 선택한 인터프린터를 위한 라이브러리 리스트를 보여주는 대화상자가 나타나는데 ok 버튼을 누르면 설정이 끝나게 된다.
http://pydev.org/manual_101_install.html

2.동적 라이브러리란?
ctypes 이라는 python의 모듈이 있는데 C언어와 호완이 가능하게 하는 모듈로 동적 라이브러리는 가져다가 쓸수 있게 한다. 그런데 동적 라이브러리란 무엇인가. C 언어 include 설명때 본적이 있는것 같은데.. 그래서 링크를 걸어본다.
http://blog.naver.com/ddrkcodz?Redirect=Log&logNo=10069875361

3.gcc 설명 및 옵션
http://blog.naver.com/alan100?Redirect=Log&logNo=60045179899

3.동적 라이브러리 만들기
opcode (*.o)에서 프로그램에서 바로 동적 라이브러리 생성: http://adnoctum.tistory.com/231
정적 라이브러리 생성 후 이를 가지고 동적 라이브러리 생성 : http://blog.naver.com/mklife?Redirect=Log&logNo=150024128340

4.동적 라이브러리의 장점
http://blog.naver.com/no1rogue?Redirect=Log&logNo=30094944212

In conclusion
정리를 해보면.. 결국 ctypes 모듈로 C 언어로 된 라이브러리(동적 라이브러리) 를 사용하려면 
C 언어로 된 프로그램을 동적 라이브러리로 생성. 
오른쪽과 같은 libhello.c 프로그램이 있을때 
gcc -fPIC -c libhello.c   #컴파일을 하되 링크까지는 수행하지 않고 오브젝트 파일 까지만 생성한다.
gcc -shared -fPIC -o libhello.so libhello.o  #shared 옵션을 이용해서 공유(동적) 라이브러리 생성
오른쪽 그림과 같이 동적 라이브러리를 사용한 python 프로그램 생성


끝...


동적 라이브러리를 이용하는 C 언어 프로그램을 만들시에는 사용하는 동적 라이브러리가 /usr/lib64에 있어야 한다. (주의 : *.so 파일을 옮긴 뒤에 ldconfig를 해야 한다)

Thursday, October 21, 2010

knock out, knock in, knock down - genetically manupulated mice and the nobel prize

http://www.nejm.org/doi/pdf/10.1056/NEJMp0707712

The New England Journal of Medicine 에 2007년도에 나온 논문
2007년도 노벨상 생리의학 부문에 대한 설명이다.

Eukaryotic Cytosine Methyltransferases

Yong-Gun Lee and I decided to write introduction and method of paper which we are planning. I don't want to fit introduction shortly after finishing research for publishing the paper. that's not the right order of work. Though this process, we try to make up for lack of story line.

This paper is quite long, but it's really good to understand a general concept of methyltransferase. Actually it's true that I deferred a study on DNMT families. Through this time, I will organize these things.


This paper was published in Annu. Rev. Biochem. 2005.

Introduction
     Cytosine Methylation in Host Defense and Genome Stability
     Cytosine Methylation and Gene Regulation
     Conservation Between Bacterial and Eukaryotic Cytosine Methyltransferase
The cytosine methyltransferase families of eukaryotes
1.Dnmt1 : 처음으로 purified & cloned 된 DNA methyltransferase. Cedar가 hemimethylaed DNA가 unmethyl보다 빨리 methylation된다는 것을 발견. Dnmt1은 hemimethylated DNA 의 methylation에 preference 하나 de novo methylation 기능도 있는것처럼 이야기를 한다(어떤 factor에 의해 inhibit 되어 있을지도 모르지만 여튼 methylation pattern이 유지 된다는 의미에서 de novo methylation 이 block을 당해야 해서). 처음 murine erythroleukemia cells의 Dnmt1의 cDNA를 찾았고, 이것은 1620개의 AA(1100 N-termi + GKGK.. + 500 C-termi)로 되어 있고 그중 C-terminal 쪽의 ~500AA가 bacterial restriction methyltransferase M.Ddel과 유사함을 알아냄.
N-termi를 보면 진화 과정에서 functional 한 domain이 늘어나는것을 볼 수있다.N-termi에 핵안으로 Dnmt1을 import 시키는 시퀀스(NLS domain)와 replication foci와 결합하는 시퀀스가 있다. 원래는 G0기에는 Dnmt1은 degradation되나 두번째 start codon에서 부터 생긴 짧은 Dnmt1은 그렇지 않으며 이 짧은 것만 가지고 있는 mouse는 생존가능.
mouse의 oocyte에는 Dnmt1의 짧은 폼만 있으며 이를 Dnmt1o 라고 한다(이와 같이 truncation되어있는것은 oocyte에서의 Dnmt1의 많은축적과 연관되어 보임).
Dnmt1의 functional domain 중 BAH(bromo-adjacent homology) domain은 protein-protein interaction module로 chromatin regulation에 속하는 protein에서도 발견된다. cysteine-rich region은 zinc ions과 결합하는데 기능은 안알려져 있지만 모든 mammalian의 methyltransferase와 MBD(methyl-binding domain) protein와 CpG binding protein에서 발견. GK(glycine, lysine) rich region은 N-termi와 C-termi를 연결해주는데 histone H4의 N-termi 와 유사하고 posttranslational modification의 역할을 하는게 아닐까 추측된다.
biological role of Dnmt1 :
loss of function allleles of Dnmt1의 결과 1. genome이 demethlation되어있고 2. homozygous embryos에서는 대부분의 imprinted gene의 biallelic expression이 나타나고 3.Xist 유전자의 demethylation결과 activation되서 모든 X chromosome 이 inactivation되고 4.exogenous marker gene의 mutation rate 올라가며 5.ES cells이 undifferentiated 상태에서는 정상적으로 크다가 differentiative 상태로 유도되면 apoptosis로 인해 죽게 되고 6.마지막으로 LTR transposons의 발현이 많아진다.
Heterozygosity for mutations in Dnmt1 결과 : 이것이 실제 측정가능한 demethylation에  영향을 미치는 지는 정확히 밝혀지지 않았지만 1.Dnmt1을 wild type의 10%정도 발현하게 했더니 생존 가능하나 성장의 제한이 생기며 lymphoma에 걸리 확률이 크게 높아지며 2. Dnmt1의 overexpression의 경우 imprinted loci에 unmethylated allele이 de novo methylation되는 현상이 나타났다(이는 Dnmt1이 methylation maintenance 역할을 한다는 것에 반하는 것).
DNMT1은 human colon cancer에서 200배 가까이 많이 발현된다는 것이 보도되어 있다(어떤 랩에서는 human colon cancer에서 다른 양상을 보이기도 한다). 일반적으로 tumor에서 m5C가 적어지는 것을 발견하는데 이는 Dnmt1의 발현이 많아지는 것과 모순되는 결과다.또한 아직까지 Dnmt1 유전자의 amplication이나 mutation으로 인한 cancer의 보고가 없기때문에 이것이 꼭 oncogene이라는 증거는 없다.
2. MET1 of A.thaliana : 처음 plant의 DNA methyltransferase는 A.thaliana에서 발견되었으며 이는 Dnmt1과 유사하였고 이름을 MET1이라 하였다. 시퀀스는 Dnmt1와 거의 유사(GK rich region이 살짝다르지만 C-termi 는 50% identity, N-termi 는 24%), BAH domain이 존재, cysteine-rich region은 없다. invitro 상에서는 MET1의 methylation 기능이 보고되지 않았지만 in vivo 상에서 homozygous mutation이 demethylation되고 phenotypic abnormalities가 나타난다. MET1의 mutant는 CpG 에 국한되어 demethylation이 나타나고 오히려 CpNpG의 methylation은 증가함을 보인다. 또한 MET1이 de novo methylation에 관여한다는 논문이 있다. homozygous mutation에 의한 demethylation은 식물에서는 후손의 heterozygous mutant나 wild-type segregants에 유전된다. 이는 각 세대마다 methylation pattern이 reset되는 mammalian과 차이를 나타낸다. 이는 genome을 알더라도 그 genome의 history를 알지 못하면 phenotype을 알 수 없다는 이야기가 될수 있다.
3. The Dnmt3 Family : 야기mammalian genome은 Dnmt3 family에 속하는 Dnmt3A와 Dnmt3B를 encoding한다. 또한 세번째 homologue인 Dnmt3L도 있는데 이는 methyltransferase activity는 없고 germ line에서의 regulatory factor로의 역할을 한다. 식물(A.thaliana)에서는 Dnmt3 family인 DRM(domains rearranged methyltransferase) family 는 methyltransferase의 motif가 circular permutation 되어 있다. 또한 Apis mellifera(꿀벌)에서도 Dnmt3가 발견됨.
-DNMT3A AND DNMT3B IN MAMMALS : Dnmt3A와 Dnmt4B의 시퀀스는 거의 유사하고 PWWP domain, cysteine-rich zyinc-binding region, MBDs를 포함하고 있다. hemimethylated 와 unmethylated 를 같은 rate로 methylation 하며 거의 CpG를 methylation시킨다. 그러나Dnmt3A는 CpA도 methylation 시킨다고 알려져 있다. adult cell에서 tissue마다 양이 다르게 발현되나 기본적으로 Dnmt1보다 발현양이 적다.


-DNMT3L :

-DNMT3 FAMILY MEMBERS IN INVERTEBRATES :
-THE DRM FAMILY : RNA-GUIDED METHYLTRASFERASES IN PLANTS :


4.DIM-2 and RID in N.crassa
5.Chromomethylases
6.Dnmt2
Methylated DNA binding proteins
regulatory inputs that control sequence-specific DNA methylation
     interatcion of Repeated seqeunces
     regulation of cytosine methylation by histone H3 Methylation
     swi2/snf2 helicase homologues and cytosine methylation
     RNA directed DNA methylation
conclusion

Wednesday, October 20, 2010

Reference-Free validation of Short Read Data

plos one에 얼마전에 나온 논문
NGS 데이터 파이프 라인을 구축하는데 가장 처음의 step으로 들어가게 될 프로그램이라 생각해서 리뷰를 해봤는데...
genome bias 에 대한 이야긴 줄 알았는데 그건 아니다. 하긴 read 만 가지고 전체 genome이 아닌 bias된 게놈만이 시퀀싱 된 줄 알수는 없다만..

이 논문은 리드 자체에 bias가 있는지를 체크 해볼 수 있는 프로그램이라고 보면 될거 같다.
read 별 각 position 별로 AGTC가 잘 분포 되어 있는지 또 k-mer로 정했을때 그 k-mer또한 분포가 position별로 동일한지를 체크 할수 있다 (체크 할수 있다기 보다는 그림으로 그릴수 있다 (우리같이 수주를 하는 사람들한테는 가능한 그림이 많이 들어가는게 좋아보이기 때문에).

java로 된 프로그램인데 사실 내용은 너무나 단순하다. 그런데 그 단순한 프로그램에다가 왜 두번째 analysis는 넣지 않은건지.. java 전혀 모르는 나에게 고생하면서 k-mer 일 때의 frequency가 나오게 만들게 하다니.. 아 그리고 quality 파일 만들어주는 변수가 int형으로 선언되는 바람에 read가 무자게 많으면 overflow나서 음수값이 출력된다는거..(스크립트 언어에 익숙한 나로는 이거 찾느라 피곤하게 됐다.)


알게된 내용:
1. mac에서 개발할 프로그램을 archive로 packing하면 __MACOSX가 딸려 생성된다는 것(첨에 프로그램 풀고 나서 이 폴더가 뭔가 했다.http://floatingsun.net/2007/02/07/whats-with-__macosx-in-zip-files/ : 이것에 대해 한소리 하는 블로거).
2. solexa 의 read가 첫 10 base의 퀄리티는 좋을지 몰라도 상당히 시퀀스가 안정적이지 못하다(뒷부분의 퀄리티가 안좋아 져서 항상 그것만 고려해서 trimming을 햇는데 앞부분의 시퀀스도 썩 훌륭한 경향을 보이지 않다니... 얼마나 짤라내야 하는거야...).


PPT

Tuesday, October 19, 2010

linux distribution. choice of linux

http://www.linux.com/learn/docs/ldp/282996-choosing-the-best-linux-distributions-for-you

어떤 linux를 쓸까 고민하는데 위 링크가 이에 대한 나름의 조언이랄까.. 정리랄까..

use-case 별로 가장 괜찮은 linux를 추천한다.

hanil 서버의용도 best enterprise server라고 해야 하나.. 어떤 카타고리인지도 모르겠지만..
확실한건 fedora 가 많이 언급이 안된다. desktop으로는 ubuntu를 laptop으론 openSUSE를 추천하는데..

괜히 fedora 깔았나.. 난 푸른 계열의 기본 바탕화면이 좋은데..

gnuplot

http://hgh73.blog.me/90093480100

Sunday, October 17, 2010

linux server

--apache server--

일단 hanil 서버를 관찰 결과를 보자면 fedora 13을 깔았는데 기본적으로 모든 서버가 다 작동 되는걸로 보인다.

apache server의 위치는 /etc/httpd/ 그 안에 conf 폴더가 설정 폴더.
-httpd.conf 파일을 내용: 대부분 주석에 내용으로 파악이 가능. 
httpd.conf 를 수정뒤 syntax error가 없는 지 확인하기 위해서 httpd -t 명령어를 이용하면 된다.


"keepAlive"에 대한 설명 : http://cafe.rootcenter.com/130079030932
"MPM"(multi_processing modules) : perfork, worker, perchild 방식이 있고, 현제 시스템의 방식은 httpd -l 명령어로 확인가능
1. perfork : 응답 프로세스를 미리 띄어 놓고, 클라이언트의 요청이 있을 때 자식 프로세스가 반응할 수 있도록 하는 설정
2. worker : 프로세스 기반의 서버인 prefork와 스레드로 클라이언트 요청에 응답하는 혼합된 스레드 서버.
3. perchild : 고정 프로세스 개수를 설정한 후 각 프로세스는 특정 스레드를 개수만큼 작동시킴.
"Listen" : 웹서버의 서비스 포트로 80 이 기본이며 다른 포트 번호를 사용할 경우  ServerName 지시자에 명시해야 한다.


"ServerAdmin" : 시스템 관리자 Email 주소
"Directory tag:아파치 서버가 접근하는 각 디렉토리에 아떠한 서비스와 기능들을 허용하고 또는 삭제 할 것인가 설정하는 부분
1.options: "indexes" : 웹사이트에 접속했을 때 index.html이 없을 경우 웹서버 스스로 그 디렉토리의 파일들을 보여 줄것이라는 의미, ExecCGI: CGI 스크립트 실행 허용,
SSI 란? http://blog.naver.com/v_kazel_v?Redirect=Log&logNo=110028893616
2.AllowOverride : 웹문서 디렉토리에서 접근 제한 설정 파일인 .htaccess 파일을 작동시킬 것인지 여부를 결정(접근 제한을 위해선 AllowOverride를 All로 설정하고 .htaccess 만들어 놓는다),
3.order : http://blog.naver.com/hkh119?Redirect=Log&logNo=120021176586
"UserDir" : 루트 이외의 다른 계정으로 홈페이지를 운영하고자 할때 사용자의 웹문서 기본 기렉토리를 UserDir 지시자로 지정 해준다. 먼저 default 로 되어 있는 UserDir disabled를 제거 하고 일반적으로 UserDir public_html 이라고 지정하고 나서 를 지정한다.
"DirectoryIndex" : 클라이언트가 웹서버에 대한 요청이 있을 때 클라이언트에 전달하는 html문서의 순서를 지정해 주는 지시자
"AccessFilleName" : 각 디렉토리에서 접근 제어 정보를 가지고 있는 파일명을 지정하는 지시자.


--보안--
기본적으로 파일이 생성되면 umask에 값을 뺀 값으로 퍼미션이 잡힌다. umask 명령어로 기본 umask 값을 볼수 있다(일반적으로 umak는 0022).
SUID,SGID 프로그램은 보안상 위험하다.
<참고>파일 권한 {'x'1:,'w':2,'r':4}, user,group,other 순, 4자 permission 구조 sticky bit(1000) : 모든 사용자가 쓰고 삭제 할수 있는 디렉토리를 의미, 파일구조 맨마지막에 t가 붙는다, SetGID(2000) : , SetUID(4000)
http://kin.naver.com/qna/detail.nhn?d1id=1&dirId=110&docId=64531886&qb=Y2htb2QgU2V0dWlk&enc=utf8&section=kin&rank=2&search_sort=0&spq=0&pid=g7VyQB331xwssZijnSKssv--138254&sid=TLsxtXIPu0wAAC2@F3g
find / -type f \( -perm -04000 -o -perm -02000 \) : SUID/SGID 프로그램 존재 확인 명령어
find / -perm -2 -print : 누구나 쓰기 가능한 world-writable 파일을 모두 찾는 명령어
find / -nouser - nogroup -print : 유저 권한이 없는 파일 검색
find / -name .rhosts -print : 원격 호스트 파일 (.rhost) 파일 검색. 이는 제거 하는것이 좋다.

charttr : 파일 속성을 변경해주는 유틸리티로 루트 자신도 파일을 변경하지 못하도록하는 것.
lastlog : /etc/passwd에 등록되어 있는 사용자의 최근 로그인 상황을 볼수 있다(자주 사용하지 않을 사용자가 로긴 되어있을 경우 크래킹을 의심).

Nmap : 포트 스캔 도구
yum list  : 설치된 패키지와 업데이트 가능한 패키지 보기
yum list installed <패키지 명> : 특정 패키지 설치 확인
yum list available 'somthing*' : yum 가능한 패키지 보기(somthing이란 이름이 들어간 패키지)
yum check-update : 업데이트 가능한 패키지 보기
yum install <패키지 명> : 패키지 설치
yum info <패키지 명> : 패키지 정보 알아보기

yum install nmap 으로 nmap 설치 이후 hanil 서버의 열린 포트를 알아본다
nmap -sS  
그뒤 특정 포트에 대한 설정을 iptable이용하여 하면 STATE 필드가 filtered로 변한다.

Snort : 네트워크를 통한 침입에 대한 탐지 및 경고를 시스템 관리자에게 알려주는 네트워크 침입 탐지 시스템으로 libpcap 라이브러리를 이용하여 네트워크상의 패킷과 설정 파일에서 정의된 룰에 의해서 침입 및 공격을 알려주는 도구.
yum install snort
/etc/snort/snort.conf 파일에 설정 내용이 들어 있다(var HOME_NET 로 설정).
외부에서 포트 스캔을 하거나 접근 시도가 있으면 /var/log/snort 에 기록이 남는다.

lastlog : 텔넷 접속으로 로그인한 사용자를 추적할때 사용하는 명령어로 /var/log/lastlog의 내용 출력
last : /var/log/wtmp 파일에 저장된 정보를 읽어 들여 로그인한 사용자의 정보를 출력 (last graphy21 : 특정 사용자 로그인 정보)
xferlog : FTP로 파일 전송 기록을 저장하는 파일 (more xferlog)
커널과 시스템에 관련된 로그 메시지들은 syslogd와 klogd 두개의 데몬에 의해서 /var/log/messages에 기록된다.

--SElinux (Security Enhanced Linux)--
a
--TCP/IP 네트워크 (iptable 설정)--


Thursday, October 14, 2010

linux command

--send message in linux:
* 메세지 브로드캐스트
  wall 메세지
  ctrl+D

*개인에게 메세지 보내기
  write userid pts/number
  ctrl+d

--display cpu information:
cat proc/cpuinfo

--mail in linux (when sendmail server is running) : 
-check mail : mail
-writing mail :
mail graphy21@gmail.com
subject: something
something
.

2*(ctrl+c) mean cancel.
-writing mail by file : mail -s 'subject' graphy21@gmail.com < some_file.ext

--check running demon in kernel:
ps acx
-check zombi process & kill that:
ps axj # 'z' in STAT field in output mean zombi
kill -l # list of signal which can be send to process
kill [-signal number || signal] PID # example : kill -9 973

Tuesday, October 12, 2010

리눅스 운영체제의 이해와 개발

병렬 프로그래밍을 보다가 thread를 이용해서 posix에서 알아서 cpu를 조정하는 것을 알았다(우스워 보일지 모르지만 나름 굉장한 흥분된 발견이였다. python 예제에서 나왔을 때 아무 생각 없이 따라 했는데 연대 핸드아웃 프린트 물 보다보니 확실히 이해하는 순간... 여튼). 그러면 순간 드는 생각이 아니 그럼 os는 어떻게 알아서 thread를 관리하지? 라는 생각. 그래서 os가 어떻게 돌아가는지 알아야 겠다는 생각에 선택한 책.
상품평에 의하면 완전 쉬운 해설과 친절한 최고의 책과 같이 되어있지만... 나와 같은 허접덩이한테는 그저 외계어에 가깝다.
그런데 재밌는건 이해가 거의 안되지만(하다못해 처음 kernel을 다운 받아서 컴파일 하는 과정 조차 이해되지 않음) 왠지 모르게 재밌게 읽고 있다는 것이다. 신기..
내 목표는 이해와 개발이 아니라 끝까지 정독과 개념 잡기 정도 이다. 끝을 꼭 보자. 끝을 보도 책에 대한 나의 평가를 다시 붙이도록 한다.

Sunday, October 10, 2010

evolution of methylome

영건씨랑 이야기 하다 좀더 정리가 된거 같아서 관련 내용을 기록한다.

목표 : methylation의 evolution의 경향

기존의 논문은 dna sequence로 phylogeny tree를 만들고 그걸 기준으로 methylation pattern을 정리 한다. 정해진 트리에 맞춰서 transposon (repeat sequence) 과 genebody (혹은 exon과 intron 부위를 나눠서) methylation pattern(여러종을 보기때문에 CpG 뿐만 아니라 CHH등)을 보고 DNMT의 homologue 의 존재 여부와 연관을 지어 phylogeny의 어느 branch는 어떤 시퀀스(CG나 CHH)가 많이 methylation되어 있고 어느 부분은 그렇지 않다라는 식으로 정리한다.
우리는 아예 phylogeny를 methylation이 들어간 정보로 새로히 그려보고자 한다. 그리고 그 tree를 그리기 위한 genomic region을 크게 gene body 와 transposon으로 나누고 두 영역으로 그린 tree가 같은가를 본다.
FFP를 선택한 이유에 대해서는 기존의 multiple alignment를 통한 phylogeny tree를 그리는 것은 homology가 있는 시퀀스를 선택해서 그려야 하는데(특정 부위에 의한 biased가 있는게 아닐까 생각한다) 이러한 제약이 없다.

Wednesday, October 6, 2010

python 3부 : 모듈

이부분은 chapter의 순서와 상관없이 나가겠다. 보고 싶은것 부터..

chapter18 : 보다 견고한 코드 만들기
이부분에서는 unittest 모듈을 사용하는 방법을 알려준다.
일반적으로 unittest의 TestCase의 클래스를 상속 받는 클래스를 생성한다음에 TestSuite 에 넣고 실행. 자세한것은 책 참조

아 보다가 알아낸것 None은 "is" 연산자를 이용해야 한다는데 아래 링크 참조
http://jaredgrubb.blogspot.com/2009/04/python-is-none-vs-none.html

chapter19 : distutils를 이용한 배포
ㅁㅁ

etc
- timeit 모듈 : 실행 시간 재는 모듈
http://man.lupaworld.com/content/develop/diveintopython-html-5.4/diveintopython-5.4/performance_tuning/timeit.html

python appendix

디버깅
파이썬에서 C언어 디버깅을 위한 유틸인 gdb 처럼 비슷한 pdb를 제공한다.
pdbtest 라는 모듈이 있을때 이것을 디버깅 하기 위한 모듈이 pdb.
import pdb, pdbtest 한뒤 pdb.runcall(pdbtest.func) 과 같이 하면 pdbtest 모듈의 func 함수를 테스트 해볼 수 있다. 디버깅 모드로의 실행은 run, runcall. runeval 이 있다.
b (break) : 브레이크 포인트설정및 확인
w (where) : 현재 스택 프레임 확인 등....
디버깅 모드(Pdb)에서 help를 치면 각종 명령어를 볼수 있으며 특정 명령어에 대한 설명을 보려면 help <명령어> 하면 된다.

Sunday, October 3, 2010

python 1부 : 문법 2

1부의 내용이 너무 길어지는 바람에 포스팅을 나누기로한다. 
책을 4장까지 밖에 보지 않았지만 지금까지 느낀점을 이야기 하자면 이 책의 포지션이 좀 애매하다는 것이다. 컴퓨터 언어를 전혀 모르는 이를 위해 쓴거 같지도 않고 그렇다고 심화해서 좀더 깊이 설명한것도 아니고 어중간하게 설명한다는 점이다. 글을 보다 보면 C를 알고 있다는 전제 하에 설명한거 같은데 그렇다고 뚜렷하게 각각의 요소를 C의 구성요소로 어떻게 만들었는지 설명하는 것도 아니고.. 애매하다. 


C로 만들었다고 하는데 객체 개념이 어떻게 들어갔는지, C++도 C로 만들은 것인지 그렇다면 궁극적으로 C는 무엇으로 만들었는지(어셈블리어라고 생각하고 있지만)등의 궁금증이 생긴다. 이것 또한 저자한테 질문을 해봐야 겠다. 어제 토요일 늦게 질문을 올렸는데 월요일에 답변이 오지 않으면 왠지 실망할거 같은 느낌이다.


chapter5 : 클래스
클래스의 선언은 함수의 선언과 유사하게 def 대신 class 키워드를 사용하면 된다. 클래스가 선언과 동시에 클래스 객체가 생성된다(클래스 이름의 이름 공간이 생긴다). 클래스를 사용하기 위해선 인스턴스 객체를 생성해야 한다. class MyClass:Name='shkm';def Print(self):print(self.Name) 이라는 클래스가 있으면 p1 = Myclass()와 같이 인스턴스 객체를 만들게 되고 이는 클래스의 객체와 모든 멤버변수와 멤버함수를 공유하게 된다. 다만 인스턴스 객체의 멤버변수가 변하게 되면 (p1.Name='eykang') 변경된 내용을 인스턴스 객체 이름 공간에 저장하게 된다.
클래스의 멤버변수,함수들은 default로 public으로 정의 된다. 위의 Myclass 에서 보면 self가 나오는데 이는 C++의 this와 같은 역할(자기 자신을 가르키는 포인터)을 한다. 이 self는 예약어는 아니지만(곧 다른 이름으로 표현 가능) 관행상 self라고 하며 '정적메소드'와 '클래스메소드'를 제외한 메소드의 첫번째 매개변수는 self로 취급된다.
그럼 self로 메소드를 나타내야 하는 이유? 인스턴트 객체도 클래스 객체의 메소드를 가리키고 있기 때문에 메소드를 사용하기 위해서는 자기 자긴을 가르키는 포인터를 넘겨줘야 한다. 그러나 그 메소드를 실행할때는 p1.Print() 처럼 정작 self에 대한 매개 변수를 넘겨주지 않는데 이는 자동적으로 self가 들어가게 된다. 이와 같은 호출을 바운드 메서드 호출이라 한다.
파이썬에서는 실행시간에 각 클래스와 인스턴스 이름 공간에 멤버 변수를 추가하거나 삭제할 수있다. 이는 서로 이름 공간이 분리 되어 있기 때문이라고 이해하면 된다. 클래스 객체에 새로운 멤버 변수를 추가하면 이는 인스턴스 객체에서 참조할수 있는데 이는 객체에서의 멤버 변수 탐색이 인스턴스>클래스>전역 순이기 때문에 자기 자신에 없는 멤버변수라도 클래스 객체에 생기면 참조할수 있는 것이다. 반면에 인스턴스 객체에 새로운 멤버변수를 추가하게 되면 자기 자신의 인스턴스 객체에서만 참조가 가능하다. 인스턴스 객체 내의 내장 속성 __class__를 이용하면 클래스 객체의 멤버변수를 바꿀수도 참조 할수도 있다.
한 클래스가 다른 클래스의 상속인지 확인하거나 한 인스턴스 객체가 어떤 클래스로부터 생성되었는지 확인하기 위해 isinstance(인스턴스 객체, 클래스 객체) 를 이용할 수 있다.
클래스 생성시 객체를 초기화 하기 위해 생성자가 파이썬 역시 있으며 이는 __init__() 멤버함수이다. 소멸자는  __del__() 이다. 생성자는 인스턴스 객체 생성시 호출되면 소멸자는 인스턴스 객체의 참조 카운트가 0이 될때 호출된다.
정적 메서드 : 원래 클래스의 멤버 함수를 사용하기 위해서는 인스턴스 객체를 생성하고 그것을 통해서 가능한데(그렇기 때문에 이러한 멤버 함수는 반드시 인자로 self가 있어야 한다) 인스턴스 객체 없이 클래스를 통해 직접 호출할수 있는 맴버 함수를 static method라고 한다(객체를 통하지 않기때문에 self 매개변수가 필요 없다).
클래스 메서드 : 클래스 메서드는 정적 메서드와 동일하나 단 암묵적으로 클래스를 첫 인자로 받는다.
파이썬에서 클래스는 기본적으로 public의 속성인데 멤버 변수 이름 앞에 __를 붙이면 private가 된다.
클래스의 연산자 오버로딩을 위한 멤버 함수들이 있다(책 참조).
인스턴스 객체의 멤버 변수 정보를 알려면 인스턴스 객체.__dict__을 이용하면 된다.
클래스 객체.__bases__ 는 클래스 객체의 직계 base 클래스를 알 수 있다.
파이썬에서는 base 클래스의 생성자를 이용하려면 derived 클래스의 생성자 내에 명시적으로 base 클래스를 언바운드 메서드 호출(self 인자를 넘겨주면서 호출하는 것)을 해야 한다.
C++에서는 method overriding 하기 위해서는 base 클래스의 함수와 derived 클래스의 함수가 이름, 매개변수, 리턴값이 같아야 하나 python에서는 함수 이름만 같아도 된다.
책에는 안나온 내용이지만 클래스 내에 함수 overloading은 python에서 안되는 것 같다. 그러나 *argv 나 **argv 나 기본적으로 python 자체가 각 자료형에 맞게 polymorphism이 이뤄진다는 걸생각하면 C++의 함수 overloading의 문법이 아니라도 의미적으로 가능하다.
클래스 객체.__mro__ 라고하면 상속 구조 속에 이름을 찾는 순서가 튜플로 나타내어진다.
다중 상속일 때 derived 클래스에서 base 클래스의 생성자를 호출할경우 중복 호출이 일어 날수 있는데 이러한 일을 방지 하기 위해 super() 내장함수를 이용한다(super().__init__(self)).

chapter6 : 모듈
모듈 이란? 여러코드를 한데 묶어 다른 곳에서 재사용 할수 있는 코드 모음(보통 비슷한 기능을 하는 함수나 큰 기능을 수행하는데 필요한 일련의 함수와 데이터가 포함)
dir(모듈) 하면 모듈 내의 함수, 데이터의 종류를 볼수 있다.
모듈의 정보 : http://docs.python.org/release/3.0.1/library/index.html
python의 모듈 경로 찾기 :  1.현재 디렉토리 2.PYTHONPATH 3.표준라이브러리디렉토리 , 위의 경로들은 sys.path에서볼수 있으며 추가도 가능하다.
import 문은 어디서나 가능, 심지어 함수 안에서 조차.
from <모듈> import * 하면 __로 시작하는 모듈안의 어트리뷰트 (함수와 데이터)를 제외한 모든 어트리뷰트를 이름 공간에 임포트 합니다.
모듈 reload를 위해 import imp; imp.reload(<모듈>).
모듈도 객체이다. 곧 모듈이 import가 되면 메모리에 로딩되면서 레퍼런스를 전달해 준다.
모듈의 __name__ 속성은 자신이 모듈로 쓰이면 모듈 이름이, 자신이 main 프로그램으로 직접 호출이 되면 __main__을 리턴한다.
관련있는 여러개의 모듈을 묶은 것을 패키지라고 한다. 패키지 디렉토리 안에는 여러 모듈 디렉토리와 함께 __init__.py 파일이 있는데 이는 패키지가 import 될때 실행되는 파일이다. __init__.py 파일 안에 __all__ 속성은 form import * 을 실행할때 포함할 하위 패키지의 목록이다. 상위 패키지를 import  했다고 해서 하위 패키지가 import 되는 것이 아니다. 하위 패키지의 모듈을 사용하기 위해서는 반드시 하위 패키지를 import 해야 한다.

chapter7 : 예외처리
프로그램의 제어 흐름을 조정하기 위해 사용하는 이벤트를 exception(예외)라고 한다.
이건 책 참조. 각종 내장 예외에 대한 것들.
try:
except:
finally:
raise 구문
assert 구문

chapter8 : 입출력
2.x 버젼에선 print는 함수가 아니였으나 3 버젼에서는 함수다.
locals(),vars(),globals() 함수는 지역변수들을 사전 형태로 반환한다.
open으로 파일 객체를 만들면 read(),readline(),readlines() 뿐만 아니라 seek()과 tell()함수도 제공된다.
seek() : 사용자가 원하는 위치로 파일 포인터를 이동
tell() :현재 파일에서 어디까지 읽고 썻는지 위치를 반환
with 구문을 이용하면 close()을 안해도 된다.
with open('test.txt') as f: print(f.readlines());print(f.cloased) 를 False 가 나오는데 위 구문을 마치고 f.closed로 확인해 보면 파일 객체인 f가 닫혀 있는걸 확인 할수 있다.
colors = ['red','green','black']이라는 변수가 있을때 이 내용을 그대로 파일에 넣고 나중에 읽었을때 그대로 리스트로 받을 수 있는데 이는 pickle이라는 모듈을 이용하면 된다.
import pickle; f= open('colors.txt','wb'); pickle.dump(colors,f); f.close(); del colors; f = open('colors.txt',rb); colors=pickle.load(f); f.close() 이렇게 하면 리스트 내용이 바이너리로 colors.txt 파일에 들어갔다가 고대로 pickle.load()로 읽어 들이면 바로 리스트로 입력이 된다(pickle을 이용할땐 반드시 바이너리 형식을 이용해야 한다). 이러한 pickle의 대상은 파이썬의 대부분의 객체가 가능하다(기본 자료형, 사용자 정의 클래스). 다만 pickle.dump로 사용자 정의 클래스를 파일에 바이너리로 저장했다가 다시 load로 읽어 들일때 그 클래스가 프로그램 내에 사전에 정의 되어 있어야 한다. 그렇지 않으면 AttributeError 발생

chapter9 : C/C++와 연동

Saturday, October 2, 2010

python 1부 : 문법

난 파이썬 유져다. 그러나 아직 단 한번도 제대로 python 기초 책 조차 들여다 본적이 없다. 2년전 쯤에 이화여대에서 agile 수업이 있을때 강사에게 python의 실력을 좀더 늘리려면 어떻게 해야 하겠냐는 질문에 그 강사는 우선 한번 python 기초 책을 첨부터 끝까지 훑어보라 이야기 했다. 2년이 지난 지금에서야 그 일을 시작하려 한다. 너무 먼 길을 돌아온 기분이다. C를 보고 C++을 보고 이제야 내 주종목을 보려한다. 감회가 새롭다. 기대도 높다. 흥분된다.


목표하는 것은 2주 안에 책을 정독하고 다른 블로그에서 찾은 berkeley 에 한 bioinfomatician이 만들어 놓은 methylC 코드를 분석해서 내가 필요로 하는  BS-seq 분석 파이프라인을 갖추는 것이다. 항상 그렇듯 새로이 어떤 공부를 시작하면 즐거운 긴장감이 감돈다. 특히 이번 공부는 그 흥분감이 강렬하다. 매우 기분좋다. 마치 소개팅 나가듯. go go !


선택한 text는 오른쪽 그림의 책이다. 원래는 프리렉의 것을 하려고 했으나 이 책 저자의 블로그를 보고 느낀 그의 이미지에 이 책을 선택했다.


내가 몰랐던 내용만 요약한다.


chapter1
이 책은 python 3 버젼에 근거 하고 있다. 우선 2.x 버젼과의 차이를 알아본다.
print 가 함수 형태로 변했다. print 'good'은 3 버젼에서는 통용되지 않고 print('good') 이어야 한다. 또한 함수화 되었기 때문에 추가적 매개변수의 전달이 가능하다. print('welcome to','python',sep='~',end='!')이라고 하면 welcome to~python! 으로 출력이 된다.
long 형이 없어지고 int형으로 통일 되었다.
int나누기 int는 float 형이 된다.
2.x 에서는 일반 스트링이 인코딩이 있는 문자열이었고 유니코드가 따로 있었는데  3 버젼에서는 유니코드를 따로 지정하지 않고 일반 스트링이 기존의 유니코드와 동일하며, 인코딩이 있는 문자열은 bytes로 표현된다.
2.x 버젼으로 짜여진 코드를 3 버젼으로 바꾸기 위해서 python 에 들어 있는 2to3를 이용할 수 있다.

chapter2 : 자료형 및 연산자
// : 정수 나누기, 2//3 하면 0이 된다.예전의 /와 같은 역할.
인덱싱을 이용한 문자열 변경은 허용되지 않는다. a='python';a[0]='a'하면 에러.
ord() : 문자의 유니코드를 출력, chr(): 유니코드의 문자를 출력
리스트에 값을 추가 할때 append 하면 맨 마지막에 insert를 이용하면 원하는 위치에 값을 넣을수있다.
3 버젼에는 set이라는 자료형이 추가 되었다. 이는 거의 리스트와 유사하며 단 순서가 없다. 그리고 정의는 {}를 이용한다. set형은 index를 제공하지 않는다. 메서드는 리스트와 거의 유사하며, 추가적으로 교집합과 합집합을 구할수 있다. a = {1,2,3} ; b = {3,4,5}와 같이 a,b 두개의 set이 정의되어 잇을때 a.union(b)하면 합집합을 a.intersection(b)하면 교집합을 구하는 메서드를 제공한다. -는 차집합을 |는 합집합을 & 는 교집합을 뜻하는 연산자도 제공한다.
튜플은 읽기 전용으로 그만큼 빠르다. 튜플을 이용하면 변수가 하나 더 필요한 swap 예제가 간단히 해결된다. a,b=1,2; (a,b) = (b,a)
2.x 버젼에서는 사전 자료형의 items(),keys(),values()의 리턴 값이 리스트 였는데 3버젼에서는 dict 객체로 변경되었다. 그래서 list화 하고 싶으면 list() 생성자를 이용해야 한다. 사전의 삭제는 del 문을 이용해서 하나씩 삭제할수도 있고, clear()메소드를 이용해서 전부 삭제할수도 있다.
0 과 '' 과 None은 False를 뜻하고 나머지는 True를 뜻한다.
객체의 고유한 아이디를 출력하기 위해 id() 함수를 이용할수 있다.
리스트를 제외한 객체를 복사 할때는 copy모듈을 사용하여 shallow copy가 되며(리스트의 경우 = 연산자를 이용하면 같은 객체를 가르키게 된다.) deepcopy를 위해선 deepcopy()함수를 사용해야 한다. copy() , deepcopy()는 copy 모듈에 있다. 부가적인 설명을 하자면 a=1; b=a 일때 b는 a의 shallowcopy를 한다. 이는 int형이라 문제가 없지만 예를 들어 a = [1,2,[3,4]] ; b = copy.copy(a)로 shallow copy를 할경우 a 변수 안에 동적 할당한 [3,4]가 새로이 생성되어서 copy된 것이 아니기 때문에 b 역시 [3,4] 는 같은 객체를 가르키고 있다. 그래서 a[1].append(5)를 하게 되면 a, b 둘다 [1,2,[3,4,5]]가 된다.

chapter3 : 함수
def는 함수 객체를 만들겠다는 키워드이다. 함수 선언부에 return이 없으면 None이 return된다.함수 이름은 함수 객체를 참조하는 레퍼런스이다. 원래 함수는 return 값이 하나이지만 여러개의 return이 가능한 것처럼 보이는 것은 여러개의 값을 튜플 객체로 만들어 리턴하는 것이기 때문이다. 함수의 매개 변수 전달은 C의 call by reference와 유사하나 다만 수치형 데이터와 같이 매개 변수가 변경 불가능한 경우는 call by value와 같이 행동한다.(요부분은 확인 필요, 저자의 질문답변시 추가할 예정)
질문에 대한 저자의 답변 : http://groups.google.com/group/python3/browse_thread/thread/173957a484c24206/1c768deb2057dafe#1c768deb2057dafe
함수의 매개변수의 갯수가 가변적일때 *를 이용할수 있다. def func(*args):라고 하면 func에 넘겨주는 매개 변수가 정해지지 않은 것이고 이는 튜플 형태로 처리된다. 사전 형태로 가변 인수를 넘기고 싶을때는 함수를 선언할때 매개 변수 앞에 **를 붙이면 된다.
람다 함수는 함수이름(레퍼런스) 없이 함수 객체만 생성하는 것으로 그 형태는 lambda 인수 : <구문> 으로 lambda x,y : x*y 식으로 사용할수 있다.
리눅스의 man페이지 처럼 모듈이나 함수의 내용을 알고 싶을때 help()함수를 이용할수있다. 이때 출력되는 내용은 객체 안에 있는 __doc__속성이다. 이는 모든 객체의 부모인 object에 포함된 기본속성이다. 예를 들어 func이라는 함수가 있을때 __doc__의 내용을 func.__doc__ = "..." 으로 직접 적을 수도 있고 func 를 정의 할때 그안에 "나 """를 이용해서설명을 적으면 자동으로 __doc__ 안에 저장된다.
interator (이터레이터) : 순회가능한 객체(list, string등)이 for와 같은 문에서 작동할때(예 : a = 'abc'; for i in a:print(i)) 이터레이터 객체를 불러서 이터레이터 안에 __next__() 메소드를 실행하여 객체 안의 값을 하나씩 리턴할수 있게 된다. 예제가 수행되는 과정은 it = iter(a); it.__next__();의 반복으로 이뤄지는 것이다.
generator(제너레이터) :
http://groups.google.com/group/python3/browse_thread/thread/16096054ad5a4631/eb4725f8f41984cb#eb4725f8f41984cb

chapter4 : 제어
조건문에서 70 <= score < 80 과 같은 것이 허락된다.
and 와 &, or와 |은 동일한 연산을 하나 and와 or의 경우 단축 평가를 된다.
보통 리스트 항목과 인덱스 값을 동시에 얻을때 인덱스 값을 먼저 얻고 그 것을 이용해서 리스트의 아이템을 얻어내는데 enumerate 함수를 이용하면 간단히 해결할수 있다. enumerate('시퀀스 타입객체'[,'시작값'=0]) 의 형태로 호출하며 호출 결과 튜플 형태인 (인덱스,시퀀스 객체의 아이템) 이 리턴된다.
기존 리스트 객체를 이용하여 조합, 필터링등의 추가적인 연산을 통해 새로운 리스트 객체를 생성할때 list comprehensions(리스트 내장)을 이용하면 좋다. 형태는 [<표현식> for <아이템> in <시퀀스 타입 객체> (if <조건식>)] 이며 예는 L1 = [1,2,3,4,5]; [i**2 for i in L1 if i**2] 이다. [x*y for x in L1 for y in L2] 도 가능하다.
리스트 안의 값을 if문으로 필터링 하는 방법과 동일하게 filter() 함수를 이용할수 있다. 그 형태는 filter(| None, <이터레이션이 가능한 자료형>) 으로 def bigThan20(i): return i>20; L = [10,30,50] ; IterL = filter(bigThan20,L) 하면 IterL에는 10 만 있는 이터레이터 가 들어 있다. 즉 반환값으로 이터레이터를 반환한다.
zip()함수는 이터레이터를 지원하는 클래스 여러개를 묶어서 zip형의 객체를 반환하며 반대로 묶여 있는 zip형 클래스 앞에 *을 붙여서 zip()을 호출하면 객체를 분리시킨다.
map()함수를 이용하면 이터레이터가능한 객체의 값들을 함수에 적용시켜 값을 리턴한다.
L = [1,2,3]이 있을때 이를 출력하는 방법은 for i in L: print(i)가 있고 print('\n'.join(i for i in L)) 이 있는데 후자의 것이 print함수를 한번만 호출하기 때문에 성능이 탁월하다.