nev*_*int 3 perl bioinformatics fasta
我有两个关注Fasta文件:
file1.fasta
>0
GAATAGATGTTTCAAATGTACCAATTTCTTTCGATT
>1
GTTAAGTTATATCAAACTAAATATACATACTATAAA
>2
GGGGCTGTGGATAAAGATAATTCCGGGTTCGAATAC
Run Code Online (Sandbox Code Playgroud)
file2.qual
>0
40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40
40 40 40 40 40 40 40 40 15 40 40
>1
40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 20 40 40 40
40 40 40 40 40 40 40 40 40 40 40
>2
40 40 40 40 7 40 40 5 40 40 40 40 40 40 40 40 37 13 31 20 15 40 10 11 4
40 8 3 29 10 19 18 40 19 15 5
Run Code Online (Sandbox Code Playgroud)
请注意每个fasta标题的"qual"文件中的换行符 - 标有">".两个文件的文件头数('>')相同.数字质量数=序列长度.
我想要做的是附加这两个文件产生:
GAATAGATGTTTCAAATGTACCAATTTCTTTCGATT 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 15 40 40
GTTAAGTTATATCAAACTAAATATACATACTATAAA 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 20 40 40 40 40 40 40 40 40 40 40 40 40 40 40
GGGGCTGTGGATAAAGATAATTCCGGGTTCGAATAC 40 40 40 40 7 40 40 5 40 40 40 40 40 40 40 40 37 13 31 20 15 40 10 11 4 40 8 3 29 10 19 18 40 19 15 5
Run Code Online (Sandbox Code Playgroud)
但不知怎的,我的代码不能正确地做到这一点?特别是'qual'文件中每个条目的第二行都没有打印出来.
use strict;
use Data::Dumper;
use Carp;
use File::Basename;
my $fastafile = $ARGV[0] || "reads/2039F.2.fasta";
my $base = basename( $fastafile, ".fasta" );
my $qualfile = "reads/" . $base . ".qual";
print "$qualfile\n";
open SEQ, '<', $fastafile or die $!; #Seq
open PRB, '<', $qualfile or die $!; #quality
while (my $seq = <SEQ>) {
my $qual = <PRB>;
chomp($seq);
chomp($qual);
if ($seq =~ /^>/ || $qual =~ /^>/) {
next;
}
else {
print "$seq\t$qual\n";
}
}
Run Code Online (Sandbox Code Playgroud)
这样做的正确方法是什么?
问题是你正在并行浏览文件,所以当一行中的行为">"时,下一行可能不是">".
您正在读取数据的方式是成对的,如下所示:
1: >0 2: >0 1: GAATAGATGTTTCAAATGTACCAATTTCTTTCGATT 2: 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 1: >1 2: 40 40 40 40 40 40 40 40 15 40 40 1: GTTAAGTTATATCAAACTAAATATACATACTATAAA 2: >1 1: >2 2: 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 20 40 40 40 1: GGGGCTGTGGATAAAGATAATTCCGGGTTCGAATAC 2: 40 40 40 40 40 40 40 40 40 40 40 1: EOF 2: >2 1: EOF 2: 40 40 40 40 7 40 40 5 40 40 40 40 40 40 40 40 37 13 31 20 15 40 10 11 4 1: EOF 2: 40 8 3 29 10 19 18 40 19 15 5
应用循环规则的同一组数据将执行此操作:
1: GAATAGATGTTTCAAATGTACCAATTTCTTTCGATT 2: 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 1: GGGGCTGTGGATAAAGATAATTCCGGGTTCGAATAC 2: 40 40 40 40 40 40 40 40 40 40 40
因此,您需要将循环逻辑分开或找到使文件匹配的方法.
这是尝试分离寻求,但我还没有测试过.
fileIO: {
while( 1 ){
my $seq;
my $qual = q{};
while( 1 ){
$seq = <SEQ>;
last fileIO if not $seq; # stop at end of file
last if $seq !~ /^>/;
}
while( 1 ){
my $qual_in = <PRB>;
last fileIO if not $qual_in; # stop at end of file
last if $qual_in =~ /^>/ and $qual ne q{};
next if $qual_in =~ /^>/ and $qual eq q{};
$qual .= $qual_in;
}
print "$seq \n $qual \n";
}
}
Run Code Online (Sandbox Code Playgroud)
我将上面的代码重新分解为一个函数,它将根据需要从任意文件句柄中读取一个块,它似乎可以根据需要工作.注意当然我在这里尝试了一些技巧,我一直想用于实用的东西.
use strict;
use warnings;
#
# readUntilNext( $fileHandle, \$scalar_ref );
#
# returns 0 when nothing could be read from the fileHandle.
# otherwise returns 1;
#
sub readUntilNext {
my ($fh) = shift;
my ($output) = shift;
my ($output_buffer) = '';
while (1) {
my $line = <$fh>;
if ( !$line ) { # No more data
# No data to flush to user, return false.
return 0 if $output_buffer eq q{};
last; # data to flush to user, loop exit.
}
if ( $line =~ /^>/ ) {
# Didn't get anything, keep looking.
next if $output_buffer eq q{};
# Got something, flush data to user.
last;
}
chomp($line);
$output_buffer .= $line;
}
# Data to flush to user
# Write to the scalar-reference
$$output .= $output_buffer;
return 1;
}
open my $m, '<', 'a.txt';
open my $n , '<', 'b.txt';
# Creates 2 scalar references every loop, and only loops as long
# as both files have data.
while ( readUntilNext( $m, \my $seq ) && readUntilNext( $n, \my $qual ) ) {
print "$seq\t$qual\n";
}
Run Code Online (Sandbox Code Playgroud)
经过测试的上述代码完全符合您的要求.
注意那个\我的东西
while( readUntilNext( $m, \my $seq ) ) {
}
Run Code Online (Sandbox Code Playgroud)
从根本上说是一样的
my $seq;
while( readUntilNext( $m, \$seq ) ) {
}
Run Code Online (Sandbox Code Playgroud)
除了事实上前者每次创建一个新的标量,保证相同的值不会对一个成功的循环可见;
所以它变得更像:
while( 1 ){
my $seq;
last if not readUntilNext($m, \$seq);
do {
# loop body here
}
}
Run Code Online (Sandbox Code Playgroud)