成功标题匹配后,将FASTA序列打印到输出文件的同一行

时间:2014-10-21 15:08:31

标签: perl

在上一个问题之后,我有一些代码几乎可以做我打算做的事情,但并不完全。

我试图将FILE1(3750/126477等)中的每个位置与FILE2(517-1878,2156-3289等)中的每个范围进行比较。如果它落在一个范围内,我想打印位置,范围,方向,然后将FASTA序列从下一行打印到输出文件中的同一行。目前,如果多个位置位于相同的范围内,那么当我希望每个匹配包含相关的基因序列时,它会将所有位置分组到一个块中,然后才将序列包含在最后一行中。

我的FILE1示例数据:

7065_8#10   3750    -   t
7065_8#10   126477  -   c
7065_8#10   1200    +   T
7065_8#10   3800    -   t

我的FILE2示例数据:

>SAEMRSA15_00010 dnaA_chromosomal_replication_initiator_protein_DnaA 517  1878 forward
ATGTCGGAAAAAGAAATTTGGGAAAAAGTGCTTGAAATTGCTCAAGAAAAATTATCAGCTGTAAGTTACTCAACTTTCCTAAA
>SAEMRSA15_00020 dnaN_DNA_polymerase_III,_beta_chain 2156  3289 forward
ATGATGGAATTCACTATTAAAAGAGATTATTTTATTACACAATTAAATGACACATTAAAAGCTATTTCACCAAGAACAACA
>SAEMRSA15_00030 conserved_hypothetical_protein 3670  3915 forward
GTGATTATTTTGGTTCAAGAAGTTGTAGTAGAAGGAGACATTAATTTAGGTCAATTTCTAAAAACAGAAGGGATTATTGAATCTGGTGGTCAAG

我的代码:

#!/usr/bin/perl 

use strict;
use warnings;
use autodie;

my $outputfile = "/Users/edwardtickle/Documents/CC22CDS.txt"; 

open FILE1, "/Users/edwardtickle/Documents/CC22indels.tab";

open FILE2, "/Users/edwardtickle/Documents/CC22_CDS_rmmge.aln";

open (OUTPUTFILE, ">$outputfile");
my @file1list=();

while (<FILE1>) {
if (/^\S+\s+(\d+)/) {
push @file1list, $1;
}
}

my $nextline = 0;
close FILE1;

while ( my $line = <FILE2> ) {
if ($nextline) {
    print OUTPUTFILE "$line\n";
    $nextline = '';
}
elsif ($line =~ /^>(\S+)\s+\S+\s+(\d+)\s+(\d+)\s+(\S+)/) {
    my $cds1 = $1;
    my $cds2 = $2;
    my $cds3 = $3;
    my $cds4 = $4;

    for my $cc22 (@file1list) {
        if ( $cc22 > $cds2 && $cc22 < $cds3 ) {
            $nextline++;
            print OUTPUTFILE "$cc22 $cds2 $cds3 $cds4\n";
        }
    }
    }
  }

close FILE2;

我的结果:

1200 517 1878 forward
ATGTCGGAAAAAGAAATTTGGGAAAAAGTGCTTGAAATTGCTCAAGAAAAATTATCAGCTGTAAGTTACTCAACTTTCCTAAA

3750 3670 3915 forward
3800 3670 3915 forward
 GTGATTATTTTGGTTCAAGAAGTTGTAGTAGAAGGAGACATTAATTTAGGTCAATTTCTAAAAACAGAAGGGATTATTGAATCTGGTGGTCAAG

我想要的结果:

1200 517 1878 forward
ATGTCGGAAAAAGAAATTTGGGAAAAAGTGCTTGAAATTGCTCAAGAAAAATTATCAGCTGTAAGTTACT

3750 3670 3915 forward    GTGATTATTTTGGTTCAAGAAGTTGTAGTAGAAGGAGACATTAATTTAGGTCAATTTCTAAAAACAGAAGGGATTATTGA
3800 3670 3915 forward
GTGATTATTTTGGTTCAAGAAGTTGTAGTAGAAGGAGACATTAATTTAGGTCAATTTCTAAAAACAGAAGGGATTATTGAATCTGGTGGTCAAG

我认为这是因为代码的第一部分在第二个if规则之前永远不会匹配,但我不知道如何在保持功能的同时更改顺序。

或者,有没有一种方法可以在标题匹配后打印下一行,如果它包含字母ATCG(它显然总是会)。这会让我感觉更有效,但我又不知道从哪里开始。

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

要获得所需的结果而不过多更改现有代码,您可以在处理标题行时获取序列行:

while ( my $line = <FILE2> ) {
    if ($line =~ /^>(\S+)\s+\S+\s+(\d+)\s+(\d+)\s+(\S+)/) {
        my $cds1 = $1;
        my $cds2 = $2;
        my $cds3 = $3;
        my $cds4 = $4;
        # fetch the next line from the file -- i.e. the sequence
        $nextline = <FILE2>;

        for my $cc22 (@file1list) {
            if ( $cc22 > $cds2 && $cc22 < $cds3 ) {
                print "$cc22 $cds2 $cds3 $cds4 $nextline";
            }
        }
    }
}

答案 1 :(得分:0)

您可以使用内部循环打印相同范围内的所有匹配项。

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

open my $IND, '<', 'file1' or die $!;
my @pos;
while (<$IND>) {
    push @pos, (split)[1];
}

@pos = sort { $a <=> $b } @pos;

open my $FST, '<', 'file2' or die $!;
while (<$FST>) {
    next unless /^>/;
    my ($from, $to, $direction) = (split)[2 .. 4];
    shift @pos while $pos[0] < $from;
    next if $pos[0] > $to;

    my $nextline = <$FST>;
    while ($pos[0] <= $to) {
        print "$pos[0] $from $to $direction\n";
        print $nextline;
        shift @pos;
    }
}