ABySS向けのデータとしてはIllumina qseq formatでもfastq formatでも構わない。 しかしながら、アラインメントのフェーズで各リードのread1とread2がセットで存在しないと非常に大量のメモリーを必要とする。このため、read1とread2がセットになるようにread1とread2のファイルをあらかじめマージすることが望ましい。
Illuminaからの出力はread1, read2が分かれたqseq.txt format とそれをfastq formatにしたものが多く使われる。
qseq.txt formatはs_[レーン番号]_[リード番号(1 or 2)]_[4桁数字]_qseq.txt というようなファイル多数になっている。
1行で1 readのデータである read1とread2のデータは同様に並んでいるものとすると、 read1のファイルから1行、read2のファイルから1行読んで 出力する事を繰り返せば、同じ断片のread1とread2が隣に来るファイルができる。例えば以下のようなプログラムmerge12.rbを作成し、
#!/usr/local/bin/ruby require 'fileutils' from_dir = ['read1', 'read2'] to_dir = 'read12' cur_dir=Dir.pwd FileUtils.mkpath(to_dir) Dir.chdir(from_dir[0]) files=Dir.glob("*").sort Dir.chdir(cur_dir) #p files files.each do |filename| pairfilename = filename.sub(/(s_\d+)_1_/,'\1_2_') newfilename = filename.sub(/(s_\d+)_1_/,'\1_') # p filename # p pairfilename open("#{from_dir[0]}/#{filename}") do |if1| open("#{from_dir[1]}/#{pairfilename}") do |if2| open("#{to_dir}/#{newfilename}", "w") do |of| if1.each_line do |line| of.puts line of.puts if2.gets end end end end end
以下のように実行する事でmergeしたファイルが得られる。
$ echo ruby merge12.rb | qsub -cwd
ここで、もちろんruby merge12.rbで実行する事もできるが、 "echo"と "|qsub -cwd"ではさむことにより、SGEのjobとして適当なノードで実行させる事を指示している。これにより、現在ログインしているコンピュータのIO負荷が増大するのを避ける。もちろん、nfsサーバーにはしっかり負荷がかかります。
これで、read12というディレクトリにバラバラのファイルが書かれます。このさき、pass filerのreadを選択して単一ファイルにまとめるには
cat read12/* | grep 1$ > ../LIBqf.qseq
などとすれば良いでしょう。
fastq formatは基本的に4行で1 readのデータを表すフォーマットであるから、 上と同様に交互に4行ずつよんで書き出せば良いかのようにも思われるが、コメント等に対する頑健性があまりにも欠けるやり方なので、区切りを認識して処理するようにする。
このため、biorubyのライブラリーを用いることとする。すると、システムにインストールされているrubyでは自分でいれたライブラリーを使えないこと、ruby-1.8よりruby-1.9の方が速いことを踏まえ、rubyからインストールする。
$ wget http://koke.asrc.kanazawa-u.ac.jp/lpm/repository/ruby.lpm $ lpm install ruby.lpm $ wget http://koke.asrc.kanazawa-u.ac.jp/lpm/repository/bioruby.lpm $ lpm install bioruby.lpm
若干美しくないが、以下のようなプログラムを保存。(例えば~/rubysrc/fastqmerge.rbとして)
#!/bin/env ruby require 'bio' ff1 = Bio::FlatFile.open(nil, ARGV[0]) ff2 = Bio::FlatFile.open(nil, ARGV[1]) ff1.each_entry do |fe1| fe2 = ff2.next_entry puts "@#{fe1.definition}\n#{fe1.sequence_string}\n+#{fe1.definition}\n#{fe1.quality_string}\n" puts "@#{fe2.definition}\n#{fe2.sequence_string}\n+#{fe2.definition}\n#{fe2.quality_string}\n" end
実行は
$ ruby ~/rubysrc/fastqmerge.rb /path/to/sequence/files/s_8_1_2_sequence.txt /path/to/sequence/files/s_8_2_2_sequence.txt > s_8_2.sequence.txt
などとする。
このようにして、ライブラリーごとにread1, read2をマージします。 8GBほどのファイルを二つ結合するのに45分 (約3 MB/s)
入力ファイルがgzip等で圧縮されている場合には、openの所を工夫し、
#!/bin/env ruby require 'bio' fh1 = IO.popen("gzip -dc " + ARGV[0]) fh2 = IO.popen("gzip -dc " + ARGV[1]) ff1 = Bio::FlatFile.new(nil, fh1) ff2 = Bio::FlatFile.new(nil, fh2) ff1.each_entry do |fe1| fe2 = ff2.next_entry puts "@#{fe1.definition}\n#{fe1.sequence_string}\n+#{fe1.definition}\n#{fe1.quality_string}\n" puts "@#{fe2.definition}\n#{fe2.sequence_string}\n+#{fe2.definition}\n#{fe2.quality_string}\n" end
のようにした上で
ruby ~/rubysrc/fastqgzmerge.rb /path/to/files/s_8_?_4_sequence.txt.gz > s_8_4.sequence.txt
のように発行する事ができる。所要時間は非圧縮とほとんど変わらない。展開はgzipが並行にやってくれるし、rubyの処理部分がgzipよりずっと遅いということ。
計算ノードで実行させるには
$ echo 'ruby ~/rubysrc/fastqgzmerge.rb /path/to/files/s_8_?_5_sequence.txt.gz > s_8_5.sequence.txt' | qsub -cwd
などのようにすればよい。リダイレクト">"させるので、echo のあとのコマンド全体を引用符で囲う。