我有一个代码,试图确定给定DNA序列的起始和结束密码子的位置。 我们将起始密码子定义为 ATG 序列,将末端密码子定义为 TGA,TAA,TAG 序列。
我遇到的问题是下面的代码仅适用于前两个序列(DM208659和AF038953),但不适用于其余的序列。
我的方法下面有什么问题?
此代码可以从here复制粘贴。
#!/usr/bin/perl -w
while (<DATA>) {
chomp;
print "$_\n";
my ($id,$rna_sq) = split(/\s+/,$_);
local $_ = $rna_sq;
while (/atg/g) {
my $start = pos() - 2;
if (/tga|taa|tag/g) {
my $stop = pos();
my $gene = substr( $_, $start - 1, $stop - $start + 1 ),$/;
my $genelen = length($gene);
my $ct = "$id $start $stop $gene $genelen";
print "\t$ct\n";
}
}
}
__DATA__
DM208659 gtgggcctcaaatgtggagcactattctgatgtccaagtggaaagtgctgcgacatttgagcgtcac
AF038953 gatcccagacctcggcttgcagtagtgttagactgaagataaagtaagtgctgtttgggctaacaggatctcctcttgcagtctgcagcccaggacgctgattccagcagcgccttaccgcgcagcccgaagattcactatggtgaaaatcgccttcaatacccctaccgccgtgcaaaaggaggaggcgcggcaagacgtggaggccctcctgagccgcacggtcagaactcagatactgaccggcaaggagctccgagttgccacccaggaaaaagagggctcctctgggagatgtatgcttactctcttaggcctttcattcatcttggcaggacttattgttggtggagcctgcatttacaagtacttcatgcccaagagcaccatttaccgtggagagatgtgcttttttgattctgaggatcctgcaaattcccttcgtggaggagagcctaacttcctgcctgtgactgaggaggctgacattcgtgaggatgacaacattgcaatcattgatgtgcctgtccccagtttctctgatagtgaccctgcagcaattattcatgactttgaaaagggaatgactgcttacctggacttgttgctggggaactgctatctgatgcccctcaatacttctattgttatgcctccaaaaaatctggtagagctctttggcaaactggcgagtggcagatatctgcctcaaacttatgtggttcgagaagacctagttgctgtggaggaaattcgtgatgttagtaaccttggcatctttatttaccaactttgcaataacagaaagtccttccgccttcgtcgcagagacctcttgctgggtttcaacaaacgtgccattgataaatgctggaagattagacacttccccaacgaatttattgttgagaccaagatctgtcaagagtaagaggcaacagatagagtgtccttggtaataagaagtcagagatttacaatatgactttaacattaaggtttatgggatactcaagatatttactcatgcatttactctattgcttatgccgtaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
BC021011 ggggagtccggggcggcgcctggaggcggagccgcccgctgggctaaatggggcagaggccgggaggggtgggggttccccgcgccgcagccatggagcagcttcgcgccgccgcccgtctgcagattgttctg
DM208660 gggatactcaaaatgggggcgctttcctttttgtctgtactgggaagtgcttcgattttggggtgtccc
AF038954 ggacccaagggggccttcgaggtgccttaggccgcttgccttgctctcagaatcgctgccgccatggctagtcagtctcaggggattcagcagctgctgcaggccgagaagcgggcagccgagaaggtgtccgaggcccgcaaaagaaagaaccggaggctgaagcaggccaaagaagaagctcaggctgaaattgaacagtaccgcctgcagagggagaaagaattcaaggccaaggaagctgcggcattgggatcccgtggcagttgcagcactgaagtggagaaggagacccaggagaagatgaccatcctccagacatacttccggcagaacagggatgaagtcttggacaacctcttggcttttgtctgtgacattcggccagaaatccatgaaaactaccgcataaatggatagaagagagaagcacctgtgctgtggagtggcattttagatgccctcacgaatatggaagcttagcacagctctagttacattcttaggagatggccattaaattatttccatatattataagagaggtccttccactttttggagagtagccaatctagctttttggtaacagacttagaaattagcaaagatgtccagctttttaccacagattcctgagggattttagatgggtaaatagagtcagactttgaccaggttttgggcaaagcacatgtatatcagtgtggacttttcctttcttagatctagtttaaaaaaaaaaaccccttaccattctttgaagaaaggaggggattaaataattttttcccctaacactttcttgaaggtcaggggctttatctatgaaaagttagtaaatagttctttgtaacctgtgtgaagcagcagccagccttaaagtagtccattcttgctaatggttagaacagtgaatactagtggaattgtttgggctgcttttagtttctcttaatcaaaattactagatgatagaattcaagaacttgttacatgtattacttggtgtatcgataatcatttaaaagtaaagactctgtcatgcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
答案 0 :(得分:4)
我删除了$_
的使用(当你local
使用它时我特别颤抖 - 你这样做是正确的,但为什么要强迫自己担心如果其他一些功能会破坏{{1} ,而不是使用已经可用的$_
?
此外,我将$rna_sq
和$start
更正为字符串中基于0的索引(这使得数学的其余部分更加直接),并提前计算$stop
所以它可以直接在$genelen
操作中使用。 (或者,您可以将substr
本地化为1以使用基于1的数组索引,请参阅perldoc perlvar。)
$[
答案 1 :(得分:1)
当if (/tga|taa|tag/g)
无法找到最终密码子时,它永远不会脱离你的内循环。它反复匹配/atg/g
,永远不会进一步推进。你可以强行将它从内循环中弹出:
if (/tga|taa|tag/g) {
...
}
else {
last;
}
答案 2 :(得分:1)
这完全取决于您是否要生成可能重叠的序列。例如,序列AF038954包含atgaccatcctccagacatacttccggcagaacagggatga
,其末尾与atgaagtcttggacaacctcttggcttttgtctgtga
重叠。你想报告他们吗?
如果您不想报告重叠的序列,这是一个非常简单的问题,您只需使用一个正则表达式即可解决:
while (<DATA>) {
chomp;
print "processing $_\n";
my ($id, $rna_sq) = split;
while ($rna_sq =~ /(atg.*?(?:tga|taa|tag))/g) {
printf "\t%8s %4i %4i %s %i\n",
$id,
pos($rna_sq) - length($1) + 1,
pos($rna_sq),
$1,
length($1);
}
}
正则表达式(atg.*?(?:tga|taa|tag))
匹配您所需的开始,然后尽可能少地匹配接下来的内容(?
以阻止.*
“贪婪”)然后您需要的结束。使用while
循环对其进行迭代,在此匹配后重新启动,这符合不查找重叠的要求。
如果你做想要报告重叠序列,你需要一个两阶段的过程:找到开始,找到结束,然后找到另一个开始,从你离开的地方开始寻找最后一次开始。但是你仍然可以使用第二个正则表达式做一个更简单的工作:
while (<DATA>) {
chomp;
print "processing $_\n";
my ($id, $rna_sq) = split;
while ($rna_sq =~ /atg/g) {
if ($' =~ /(.*?(?:tga|taa|tag))/) {
my $match = "atg$1";
printf "\t%8s %4i %4i %s %i\n",
$id,
pos($rna_sq) - 2,
pos($rna_sq) - 3 + length($match),
$match,
length($match);
}
}
}
这里我们使用(通常是非推荐的)$'
特殊变量,它包含匹配后的内容。我们查看此序列以查找序列的结尾并输出详细信息。因为我们与$rna_seq
的主要全局匹配不包括序列(如上所述),所以我们重新开始搜索上一次搜索停止的开始,即在我们找到的开始之后。这样我们做包含重叠序列。