写一个Perl脚本,它接受一个fasta并反转所有序列(没有BioPerl)?

时间:2016-08-04 19:32:17

标签: perl bioinformatics fasta

我不知道这是否只是Stawberry Perl的一个怪癖,但我似乎无法让它运行。我只需要取一个fasta并反转其中的每个序列。

- 问题 -

我有一个multifasta文件:

>seq1
ABCDEFG
>seq2
HIJKLMN

,预期输出为:

>REVseq1
GFEDCBA
>REVseq2
NMLKJIH

脚本在这里:

$NUM_COL = 80; ## set the column width of output file
$infile = shift; ## grab input sequence file name from command line
$outfile = "test1.txt"; ## name output file, prepend with “REV”
open (my $IN, $infile);
open (my $OUT, '>', $outfile);
$/ = undef; ## allow entire input sequence file to be read into memory
my $text = <$IN>; ## read input sequence file into memory
print $text; ## output sequence file into new decoy sequence file
my @proteins = split (/>/, $text); ## put all input sequences into an array


for my $protein (@proteins) { ## evaluate each input sequence individually
    $protein =~ s/(^.*)\n//m; ## match and remove the first descriptive line of
    ## the FATA-formatted protein
    my $name = $1; ## remember the name of the input sequence
    print $OUT ">REV$name\n"; ## prepend with #REV#; a # will help make the
    ## protein stand out in a list
    $protein =~ s/\n//gm; ## remove newline characters from sequence
    $protein = reverse($protein); ## reverse the sequence

    while (length ($protein) > $NUM_C0L) { ## loop to print sequence with set number of cols

    $protein =~ s/(.{$NUM_C0L})//;
    my $line = $1;
    print $OUT "$line\n";
    }
    print $OUT "$protein\n"; ## print last portion of reversed protein
}

close ($IN);
close ($OUT);
print "done\n";

2 个答案:

答案 0 :(得分:2)

这将按照您的要求进行

它从FASTA文件中构建哈希%fasta,保持数组@keys以保持序列顺序,然后打印出哈希的每个元素

序列的每一行在添加到散列之前使用reverse反转,并使用unshift以相反的顺序添加序列的行

程序期望输入文件作为命令行上的参数,并将结果打印到STDOUT,可以在命令行上重定向

use strict;
use warnings 'all';

my (%fasta, @keys);

{
    my $key;

    while ( <> ) {

        chomp;

        if ( s/^>\K/REV/ ) {
            $key = $_;
            push @keys, $key;
        }
        elsif ( $key ) {
            unshift @{ $fasta{$key} }, scalar reverse;
        }
    }
}

for my $key ( @keys ) {
    print $key, "\n";
    print "$_\n" for @{ $fasta{$key} };
}

输出

>REVseq1
GFEDCBA
>REVseq2
NMLKJIH


更新

如果您希望重新包装序列以便最后使用短行,那么您只需要重写转储哈希的代码

此替代方法使用原始文件中最长行的长度作为限制,并将反转序列重新包装为相同的长度。它的作者是指定一个显式长度而不是计算它很简单

您需要在程序顶部添加use List::Util 'max'

my $len = max map length, map @$_, values %fasta;

for my $key ( @keys ) {
    print $key, "\n";
    my $seq = join '', @{ $fasta{$key} };
    print "$_\n" for $seq =~ /.{1,$len}/g;
}

鉴于原始数据,输出与上述解决方案的输出相同。我用它作为输入

>seq1
ABCDEFGHI
JKLMNOPQRST
UVWXYZ
>seq2
HIJKLMN
OPQRSTU
VWXY

有了这个结果。所有行都被包装为11个字符 - 原始数据中最长JKLMNOPQRST行的长度

>REVseq1
ZYXWVUTSRQP
ONMLKJIHGFE
DCBA
>REVseq2
YXWVUTSRQPO
NMLKJIH

答案 1 :(得分:1)

我不知道这是否仅适用于使用玩具数据集或实际研究FASTA的类,其数量级为千兆字节。如果是后者,那么将整个数据集保存在内存中是有意义的,因为你的程序和Borodin都会这样做,但是一次只读一个序列,打印出来并将其忘记。以下代码执行此操作并处理may have asterisks as sequence-end markers的FASTA文件,只要它们以>开头,而不是;

#!/usr/bin/perl
use strict;
use warnings;

my $COL_WIDTH = 80;

my $sequence = '';
my $seq_label;

sub print_reverse {
    my $seq_label = shift;
    my $sequence = reverse shift;
    return unless $sequence;
    print "$seq_label\n";
    for(my $i=0; $i<length($sequence); $i += $COL_WIDTH) {
        print substr($sequence, $i, $COL_WIDTH), "\n";
    }
}

while(my $line = <>) {
    chomp $line;
    if($line =~ s/^>/>REV/) {
        print_reverse($seq_label, $sequence);
        $seq_label = $line;
        $sequence = '';
        next;
    }
    $line = substr($line, 0, -1) if substr($line, -1) eq '*';
    $sequence .= $line;
}
print_reverse($seq_label, $sequence);