Подсчет последовательностей в файле, начинающихся и заканчивающихся пользовательским соответствием

У меня есть файл с последовательностями ДНК в формате fastta под названием "test.fas":

>test1
GCCATTACAGAACATCAGTCACAGTACGTACTGTGTTCTGCCGTGCTGTCTA
>test2
CGGATGAAGCGCCAATCGTACGTACAATAAGTTGCCTAAAGTGTTTCA
>test3
ATGCATGCATGC

У меня также есть файл последовательности праймеров с разделителями табуляции под названием "primers.txt":

GCCATTACAGAACATCAGTCACA TAGACAGCACGGCAGAACAC
CGGATGAAGCGCCAATC   TGAAACACTTTAGGCAACTTATT

Каждая строка в этом файле primers.txt представляет собой пару праймеров, которая может соответствовать началу и концу последовательности в файле fasta. Второй праймер в каждой строке также должен быть дополнен в обратном порядке, прежде чем он будет соответствовать чему-либо в файле fasta. Глядя на первую пару праймеров в первой строке в primers.txt, после обратного дополнения второго праймера, он должен соответствовать последовательности test1 в файле test.fas.

То, что я хочу сделать, это передать эти два файла в программу perl и получить выходной файл подсчета того, сколько раз была найдена последовательность с парой праймеров из файла primers.txt. В этом случае мой outfile будет перечислять:

1
1

В действительности у меня есть 650000 последовательностей в файле и 170 наборов праймеров для поиска и перечисления из файла. Поэтому я хочу, чтобы длина файла составляла 170 строк, и в каждой строке указывалось, сколько раз было найдено совпадение в файле fasta для этой конкретной пары праймеров. По сути, для каждой строки в файле primer.txt подсчитайте, сколько раз последовательность появляется в файле fasta, который начинается и заканчивается этой парой праймеров. Это то, что я придумал до сих пор:

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

print "Name of the FASTA file: ";
chomp( my $multifasta = <STDIN> );

print "Name file with primers: ";
chomp( my $pulls = <STDIN> );

print "Name of the output file: ";
chomp( my $out = <STDIN> );

open(MULTIFASTA,$multifasta) || die ;
  my $seq = do { local $/; <MULTIFASTA>};
  close MULTIFASTA;

open(PULLS,$pulls) || die;
  while (my $line = <PULLS>){
  chomp $line;
  my @primers = split (/\t/,$line);
  my $revcomp = reverse $primers[1];
  $revcomp =~ tr/ATGCatgc/TACGtacg/;  #reverse complement the reverse primer
  my $matches = () = $seq =~ /^\Q$primers[0].*\Q$primers[1]$/; #How to structure the regex? 
  open(OUTFILE,">>$out");
  print OUTFILE "$matches\n";   
}

Мой файл заканчивается этим:

0
0

Я явно что-то напортачил. Я быстро попадаю в ловушку, пытаясь попробовать разные вещи, которые нахожу в Google, не имея четкого представления о том, что это делает с кодом, и в этот момент я заблудился. Это является следствием того, что в скором времени действительно нужен ответ и очень мало известно о программировании. После прочтения я понял, что должен читать весь файл для поиска совпадений с локальным, и мне нужно использовать \Q для поиска переменной в регулярном выражении в perl. В любом случае, любая помощь или указатели будут очень цениться. Спасибо -

2 ответа

Решение

Создайте регулярное выражение из всех праймеров. Также храните праймеры в хэше, значениями будут номера строк. Затем переберите файл fasta и попытайтесь найти соответствие регулярному выражению. Если он совпадает, используйте хеш для получения номера строки праймера и используйте другой хеш для записи количества совпадений на номер строки. В конце просто сообщите цифры:

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

my ($fasta_file, $primers_file) = @ARGV;

my %primer;
open my $primers_fh, '<', $primers_file or die $!;
while (<$primers_fh>) {
    chomp;
    my ($first, $second) = split /\t/;
    $second = reverse $second;
    $second =~ tr/actgACTG/tgacTGAC/;
    undef $primer{$first}{$.};
    undef $primer{$second}{$.};
}

my $primers_count = $.;
my $regex =  join '|', keys %primer;

my %seen;
open my $fasta_fh, '<', $fasta_file or die $!;
while (<$fasta_fh>) {
    if (/^($regex)/) {
        ++$seen{$_} for keys %{ $primer{$1} };
    }
}

for my $line_number (sort { $a <=> $b } 1 .. $primers_count) {
    print $seen{$line_number} // 0, "\n";
}

Я думаю, что вы неправильно поняли, что \Q (а также \E) делает. Это для специальных символов регулярных выражений с обратной косой чертой. Это не для "поиска переменной в регулярном выражении". Perl уже распознает переменные в регулярных выражениях. Вам не нужно \Q Вот.

my $matches = () = $seq =~ /^\Q$primers[0].*\Q$primers[1]$/;

Базовое соответствие регулярному выражению, подобное этому, возвращает 1 или 0 для истинного и ложного. Он не возвращает вам массив совпадений, как вы этого хотите. Вам нужно g глобальный модификатор для этого.

Вам, вероятно, также нужно .* быть не жадным, используя .*? вместо.

Вы также используете ^ а также $ неправильно здесь. Это заставляет ваши праймеры совпадать только в начале и в конце (многострочной) строки, а не для строк внутри нее. Вот почему вы получаете 0 (ложь) для ваших матчей.

Другие вопросы по тегам