我在 BioPerl 中加载了一个系统发育树。我想在打印出树时使用自定义排序函数(下面的“$depth_sort”)对节点进行垂直排序。然而,下面使用的记录方法以读取树的相同顺序写出树,而没有实际排序:
use strict;
use Bio::TreeIO;
my $input = new Bio::TreeIO(-file=>"input.tree", -format=>'newick');
my $tree = $input->next_tree;
my $depth_sort = sub { $a->depth <=> $b->depth };
#this is the way it is supposed to work:
my $out = new Bio::TreeIO(
-file => ">sorted.tree",
-format => 'newick',
-order_by => $depth_sort
);
$out->write_tree($tree);
相反,我可以手动遍历树以查看发生了什么。如果我在本地进行自己的排序,它会按预期工作:
my $rnode = $tree->get_root_node;
&printNode($rnode);
sub printNode {
my $thisNode = shift;
#print the node identity and depth, just to keep track:
print "this is " . $thisNode->internal_id .
" with depth " . $thisNode->depth . "\n";
if (! $thisNode->is_Leaf) {
my @children = sort $depth_sort $thisNode->each_Descendent();
for my $otherNode (@children) { &printNode($otherNode); }
}
}
但是,如果我将自定义排序传递给 each_Descendent(上面的 write 调用应该采用的方式):
my @children = $thisNode->each_Descendent($depth_sort);
然后它随着消息而死:
无法在 treeFlipper.pl 第 7 行第 1 行的未定义值上调用方法“深度”。
我在这里找到了另一个我认为让我走上正轨的线程,但我还没有解决它:Perl 排序;干净地处理跨命名空间的 $a、$b 包全局变量
在第一个答案中切换到原型方法:
my $depth_sort = sub ($$) {
my ($a1,$b1) = @_;
return ($a1->depth <=> $b1->depth) };
给我:
无法在 treeFlipper.pl 第 9 行第 1 行的 unblessed 引用上调用方法“深度”。
但是,如果我检查 ref 类型,那似乎是正确的:
print ref($a1) . "\n";
给
Bio::Tree::Node
当我尝试强制祝福参考时(这可能是一件可怕的事情):
bless $a1, 'Bio::Tree::Node';
bless $b1, 'Bio::Tree::Node';
我得到:
不是 /usr/local/share/perl/5.14.2/Bio/Tree/Node.pm 第 433 行第 1 行的 HASH 引用。
该线程中的其他方法(使用调用者)给了我同样的旧“未定义值”错误。
这是 BioPerl 的问题,还是(我怀疑)我仍然遗漏了什么?谢谢!
编辑:在 Ubuntu 12.04 LTS 上使用 Perl 5.14.2