根据配合对长度处理FASTQ文件

时间:2015-05-01 08:50:00

标签: perl bioinformatics bioperl fastq sequencing

以下文件是配对端fastq文件的两个配对,我想根据它们的长度分隔每个fastq。

mate1.fq

@SRR127.1
TGGTTATGATGTTTGTGTAGGAATAGAAATTTTGATTAAGATATTAGTGAAATTTGAATGTAGTTTATTTGGAAGTTATGGAGAGTTTATATTGTATTTATGTTTATTGTTGTAGATTTATATTTATGTGTATATATTAGTTTTTTTGTGT
+
ABAAAF4FFFFFGGGGGGFFGGFGHGFGHHHHHGGCFFGHHHHH5FDBED55DGGFEGFHHHGBHDDHHHFF3AB3FFG5CBGBEF5BD5DGFEGHFAGAFEDGHGFHHGHGEFFGFGGHFEGHHFHGBEBGHHHHGHBHHFHHGGFGHH2
@SRR127.2
TATGGTAAGAAAATTGAAAATTATAAAAAATGAAAAATGTTTATTTGATGATTTGAAAAATGATGAAATTATTGAAAAATGTGAAAAATGAGAAATGTATATTGTAGGATTTGGAATATGGTGAGATAAATGAAAATTATAGTAAATG
+
AABAA5@D4@5CFFCA55FFGGHDGFHFFCC45DGFA2FA5DD55AAAA55DDBDEDDBGGFF5BA5DDABF5D5B5FF1ADFB5EDGHFG5@BFBD55D5FFB@@5@GBGEFBGHHGB@DBBFHFBDG3B43FFH@FGFHH?FHHHH

mate2.fq

@SRR127.1
ACCTATAAAAAAACCATATCAATAACTATAAAATCTTTATAAAATCCCACCCAATTAAAAAAAAATAAATTAATACATATAAAACCTTAAACACATAAAACATAATCACATACTATATAAACAATTACTATCACTACTAAACACCTAATA
+
>AA?AF13B@D@1EFCGGGFFG3EBGHHHBB2FGHHGHGFDGHHDFEGFHGGGHG1FFF1GGCGGGBGHHHHHFHHHHFHEGGFHF0BD1FGHHAGEGHFHHHFGGFHHGHHHFHHGGFHBGHFED1FBGFGFHDGHGHFGG1GB0GFHH
@SRR127.2
CTATTTCTCATTTTTTTATAATTTTCAATTCTCTTACCATATTCCACATCCTACACTAAACATTTCTAAATTTTCCACCTTTTTCTATTTTTCTCACCATATTTCATATCCTAAAAAACATATTCCTCATTTACTATAATTTTCAATTATC
+
11>>AFFDFF3@FFF?EFFGFBGHFDFA33D2FF2GGHFE12DD221AF1F1E1BG1GGBFBGGEGHDAABGAGDFABGG1BBDF12A2@2BG@2@DEFFF2B2@2222BB2211FGEE/11@22B2>1B22F2>GBGBD22BGD2>2B22

我编写了以下代码来执行此操作,但我只对第二个文件(mate2.fq)收到一个奇怪的错误,而它们都有151 bp的读取。

#!/usr/bin/perl

use strict;
use warnings;

my @fh;

my $file_name = $ARGV[0];
my $infile    = $ARGV[1];

#convert every 4-line fastq to 1-line
open(FH, "cat '$infile' | awk '{printf \"%s%s\",\$0,(NR%4?FS:RS)}' | ");

while (<FH>) {
  chomp;

  my @line = split(/\s+/, $_);
  my $len  = length($line[1]);

  if ($len >= 100) {

    #print $len,"\n",$_,"\n";
    push @fh, $len;

    if (not defined $fh[$len]) {
      open $fh[$len], '>', "$file_name\_$len";
    }
    print { $fh[$len] } (join("\n", @line), "\n");
  }

}

错误

  

Can't use string ("151") as a symbol ref while "strict refs" in use at

如何处理这些文件?

2 个答案:

答案 0 :(得分:6)

正如您所读到的,您的问题是由于虚假的push@fh数组的末尾添加了一个整数值。我认为你的目标是扩展数组足够长以添加新的文件句柄。您可以通过分配到$#fh来执行此操作,因此您可以编写$#fh = $len if $#fh < $len;但是这是不必要的,因为Perl会在您简单地分配到数组末尾的元素时自动为您扩展数组

我对您的计划有一些评论,希望您找到有用的

  • 发出awk命令是不必要和浪费的。 Perl完全有能力完成awk所能做的一切

  • 如果您发现自己正在撰写split /\s+/, $_,那么您几乎肯定只是split:默认行为是split ' ', $_。如果您使用/\s+/作为模式,并且恰好在您要拆分的字符串上有前导空格,那么split将返回一个空字符串作为字段列表中的第一项。如果您改为使用' '(文字单个空格,而不是模式/ /),那么这不会发生。实际上,split ' '相当于/\S+/g

  • 在字符串中插入变量值时,如果存在可能属于标识符的后续字符,则通常更适合将标识符放在大括号内。所以"${file_name}_$len"代替"$file_name\_$len"

这就是我编写代码的方式。它将输入记录累积到$line,直到添加了四个记录,然后像以前一样处理该行。

#!/usr/bin/perl

use strict;
use warnings;

my ($file_name, $infile) = @ARGV;

open my $in_fh, '<', $infile or die $!;
my $line;

my @fh;
while ( <$in_fh> ) {
  chomp;
  $line .= $_;

  if ( $. % 4 == 0 or eof ) {

    my @line = split ' ', $line;
    my $len  = length $line[1];
    next if $len < 100;

    open $fh[$len], '>', "${file_name}_$len" unless $fh[$len];
    print { $fh[$len] } "$_\n" for @line;

    $line = undef;
  }
}

答案 1 :(得分:5)

这个错误具体意味着你正在做一些需要引用的东西,但它没有得到一个。

该行:

print {$fh[$len]} (join("\n",@line),"\n");

显式打印到文件句柄 - 看起来像名为@fh的文件句柄列表。

这一行:

push @fh, $len;

将数值插入该列表。 (据推测$line[1]长度为151个字符)。所以你真的想:

 print {151} (join("\n",@line),"\n");

希望这很明显 - 只是不会起作用。您看起来像是在尝试打开文件句柄,并将其插入到数组中:

open $fh[$len], '>', "$file_name\_$len";

我可以建议您使用散列更好吗?否则你有一个充满空元素的数组,其中一个已填充。

你可以改为:

#further up:
my %fh; 


#and then
open ( $fh{$len}, ">", "$file_name\_$len" ) or warn $!; 

不要忘记在最后关闭文件句柄:

foreach my $key ( keys %fh ) {
   close ( $fh{$key} );
}

我也建议而不是:

open( FH, "cat '$infile' | awk '{printf \"%s%s\",\$0,(NR%4?FS:RS)}' | " );

你可能最好在perl中处理它,因为你所做的只是使用外部二进制文件解析文件。 (并使用词汇文件句柄:`open($ input,“ - |,”cat'$ infile'| awk'{printf \“%s%s \”,\ $ 0,(NR%4?FS:RS)}' “)或警告$!;)