Arrays perl从2个数组中提取公共元素(fastq文件中的公共序列)
我有两个文件(成对的)从同一个有机体(文件R1.fastq和文件R2.fastq)读取fastq格式的数据。我想使用bwa和samtools(生物信息学)确定深度覆盖率,为此我需要两个文件具有相同的读取次数,相同的名称(文件1:@XX00341:4450:6341 1:N:0:aacgtaa+TTGCAATT和文件2:@XX00341:4450:6341 2:N:0:aacgtaa+TTGCAATT),在两个文件中的顺序相同,问题是,两个文件都有空读取(每个文件对应的读取,可能在一个文件中为空,但在另一个文件中为空!!!!),如果我尝试使用bwa运行它,它会由于空序列而失败 因此,我试图制作一个perl脚本来提取两个文件中具有相同名称和顺序的非空读取 这是fastq文件的格式(每次读取有4行:名称(@XX00341:19:000H27K25:1:11101:4450:6341 1:N…)、顺序(gaggtgggttgtcacccc…)、Q_头(+)和质量(fffffffffffffffff…) 文件_r1.fastq(以=..1:N:0:aacgtaa+TTGCAATT为特征) 文件_r2.fastq(以=..2:N:0:aacgtaa+TTGCAATT为特征) 在这种情况下,文件_1.fastq(@XX00341:10259:6342 1:N…)中的一次读取为空,第二行和第四行为空(序列和质量),但文件_2.fastq(@XX00341:10259:6342 2:N…)中不为空;在本例中,两个序列(每个文件中的4行)必须省略 这是我试图完成的代码:Arrays perl从2个数组中提取公共元素(fastq文件中的公共序列),arrays,perl,bioinformatics,sequences,fastq,Arrays,Perl,Bioinformatics,Sequences,Fastq,我有两个文件(成对的)从同一个有机体(文件R1.fastq和文件R2.fastq)读取fastq格式的数据。我想使用bwa和samtools(生物信息学)确定深度覆盖率,为此我需要两个文件具有相同的读取次数,相同的名称(文件1:@XX00341:4450:6341 1:N:0:aacgtaa+TTGCAATT和文件2:@XX00341:4450:6341 2:N:0:aacgtaa+TTGCAATT),在两个文件中的顺序相同,问题是,两个文件都有空读取(每个文件对应的读取,可能在一个文件中为空,
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
my ($fastQ_R1, $fastQ_R2);
GetOptions (
'R1|r1=s' =>\$fastQ_R1,
'R2|r2=s' =>\$fastQ_R2,
);
sub extract_list {
my ($file_in) = @_;
open FILE, '<', $file_in or die "cant open the $file_in\n";
my (@elements, @list, @seq);
while(
defined(my $head = <FILE>) && # 1 line
defined(my $seq = <FILE>) && # 2 line
defined(my $qhead = <FILE>) && # 3 line
defined(my $quality = <FILE>) # 4 line
){
if ($seq=~ m/^$/g){
next;
}
else { push @seq, $head; }
}
close FILE;
foreach (@seq){
chomp;
@elements = split '\s', $_;
push @list, $elements[0]; # split to eliminate 1:N... (file_1) and 2:N... (file_2)
}
return @list;
}
my @list_R1 = extract_list ($fastQ_R1);
my @list_R2 = extract_list ($fastQ_R2);
@清单2=
@XX00341:4450:6341
@XX00341:14420:6341
@XX00341:6685:6342
@XX00341:4051:6343
@XX00341:12307:6344
@XX00341:24250:6345
@XX00341:4450:6341
@XX00341:14420:6341
@XX00341:10259:6342
@XX00341:6685:6342
@XX00341:4051:6343
@XX00341:12307:6344
@XX00341:24250:6345
@公共元素=
@XX00341:4450:6341
@XX00341:14420:6341
@XX00341:6685:6342
@XX00341:4051:6343
@XX00341:12307:6344
@XX00341:24250:6345
因此,新数组(@common_elemnts)将用于搜索和提取每个文件的公共读取(4行),并将提供两个输出文件:files_R1_common.fastq(从文件_R1.fastq获得)和files_R2_common.fastq(从文件_R2.fastq获得)
如有任何建议,将不胜感激!!!!
非常感谢您最好使用哈希映射检查列表中是否存在项。
构造公共哈希映射:
my %list1_map = map { $_, 1 } @list_R1;
my %common_map = map { $list1_map{$_} ? ($_, 1) : () )} @list_R2;
然后处理您的列表:
for my $item(@list_R1) {
if (defined ($common_map{$item})) {
# ... process ...
}
在下面的解决方案中,我将FASTQ解析移到了一个单独的类中,该类将从文件中读取4行,并返回一个代表一条记录的id、hdr、seq和qual的hashref。我将编写这个类作为一个练习。这样做使下面的逻辑易于理解。可读性很重要 此代码只需从文件1中保存空序列的ID(即$hdr=~/^@(\S+/)中的$1)。然后读取文件2并输出完整记录,还保存空记录的ID。最后,再次读取文件1并通过删除%筛选哈希所指示的记录来输出完整记录 此解决方案效率低下,因为它会读取文件1两次。原始问题中未提及的是,FASTQ文件通常包含数百万条记录,因此将文件1中所有未筛选的记录保存在%筛选哈希中需要大量RAM,但如果您有大量RAM,您可以根据需要进行更改,但就个人而言,我不会担心about读取文件两次
# SAVE IDS OF EMPTY RECORDS FROM FILE1 IN HASH
my %filter;
my $fq = new Fastq($file1);
while (my $rec = nextSeq($fq))
{
$rec->{seq} or $filter{$rec->{id}} = undef; # not using value
}
# ADD IDS OF EMPTY RECORDS FROM FILE2 TO HASH AND OUTPUT FILTERED_FILE2
open(my $out, '>', "$file2.filtered") or die($!);
$fq = new Fastq($file2);
while (my $rec = nextSeq($fq) )
{
if ( $rec->{seq} )
{
# READ2 FOR THIS PAIR IS NOT EMPTY
if ( ! exists($filter{$rec->{id}}) )
{
# READ1 FOR THIS PAIR IS ALSO NOT EMPTY
print $out join("\n", $rec->{hdr}, $rec->{seq}, '+', $rec->{qual}), "\n";
}
} else
{
# READ2 IS EMPTY, ADD TO FILTERED HASH
$filtered{$rec->{id}} = undef;
}
}
close($out);
# OUTPUT FILTERED_FILE1
open($out, '>', "$file1.filtered") or die($!);
$fq = new Fastq($file1);
while (my $rec = nextSeq($fq) )
{
if ( $rec->{seq} and ! exists($filter{$rec->{id}}) )
{
print $out join("\n", $rec->{hdr}, $rec->{seq}, '+', $rec->{qual}), "\n";
}
}
close($out);
for my $item(@list_R1) {
if (defined ($common_map{$item})) {
# ... process ...
}
# SAVE IDS OF EMPTY RECORDS FROM FILE1 IN HASH
my %filter;
my $fq = new Fastq($file1);
while (my $rec = nextSeq($fq))
{
$rec->{seq} or $filter{$rec->{id}} = undef; # not using value
}
# ADD IDS OF EMPTY RECORDS FROM FILE2 TO HASH AND OUTPUT FILTERED_FILE2
open(my $out, '>', "$file2.filtered") or die($!);
$fq = new Fastq($file2);
while (my $rec = nextSeq($fq) )
{
if ( $rec->{seq} )
{
# READ2 FOR THIS PAIR IS NOT EMPTY
if ( ! exists($filter{$rec->{id}}) )
{
# READ1 FOR THIS PAIR IS ALSO NOT EMPTY
print $out join("\n", $rec->{hdr}, $rec->{seq}, '+', $rec->{qual}), "\n";
}
} else
{
# READ2 IS EMPTY, ADD TO FILTERED HASH
$filtered{$rec->{id}} = undef;
}
}
close($out);
# OUTPUT FILTERED_FILE1
open($out, '>', "$file1.filtered") or die($!);
$fq = new Fastq($file1);
while (my $rec = nextSeq($fq) )
{
if ( $rec->{seq} and ! exists($filter{$rec->{id}}) )
{
print $out join("\n", $rec->{hdr}, $rec->{seq}, '+', $rec->{qual}), "\n";
}
}
close($out);