Подсчет последовательностей в файле, начинающихся и заканчивающихся пользовательским соответствием
У меня есть файл с последовательностями ДНК в формате 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 (ложь) для ваших матчей.