$Bio::TreeIO::phyloxml::VERSION
=
'1.7.8'
;
sub
_initialize
{
my
(
$self
,
%args
) =
@_
;
$args
{-treetype} ||=
'Bio::Tree::Tree'
;
$args
{-nodetype} ||=
'Bio::Tree::AnnotatableNode'
;
$self
->SUPER::_initialize(
%args
);
if
(
$self
->mode eq
'r'
) {
if
(
$self
->_fh) {
$self
->{
'_reader'
} = XML::LibXML::Reader->new(
IO
=>
$self
->_fh,
no_blanks
=> 1
);
}
if
(!
$self
->{
'_reader'
}) {
$self
->throw(
"XML::LibXML::Reader not initialized"
);
}
}
elsif
(
$self
->mode eq
'w'
) {
$self
->_print(
'<?xml version="1.0" encoding="UTF-8"?>'
,
"\n"
);
}
$self
->treetype(
$args
{-treetype});
$self
->nodetype(
$args
{-nodetype});
$self
->{
'_lastitem'
} = {};
$self
->_init_func();
}
sub
_init_func
{
my
(
$self
) =
@_
;
my
%start_elements
= (
'phylogeny'
=> \
&element_phylogeny
,
'clade'
=> \
&element_clade
,
'sequence_relation'
=> \
&element_relation
,
'clade_relation'
=> \
&element_relation
,
);
$self
->{
'_start_elements'
} = \
%start_elements
;
my
%end_elements
= (
'phylogeny'
=> \
&end_element_phylogeny
,
'clade'
=> \
&end_element_clade
,
'sequence_relation'
=> \
&end_element_relation
,
'clade_relation'
=> \
&end_element_relation
,
);
$self
->{
'_end_elements'
} = \
%end_elements
;
}
sub
DESTROY {
my
$self
=
shift
;
if
(
$self
->mode eq
'w'
) {
$self
->_print(
'</phyloxml>'
);
$self
->flush
if
$self
->_flush_on_write &&
defined
$self
->_fh;
}
$self
->SUPER::DESTROY;
}
sub
next_tree
{
my
(
$self
) =
@_
;
my
$reader
=
$self
->{
'_reader'
};
my
$tree
;
while
(
$reader
->
read
)
{
if
(
$reader
->nodeType == XML_READER_TYPE_END_ELEMENT)
{
if
(
$reader
->name eq
'phylogeny'
)
{
$tree
=
$self
->end_element_phylogeny();
last
;
}
}
$self
->processXMLNode;
}
return
$tree
;
}
sub
add_attribute
{
my
(
$self
,
@args
) =
@_
;
my
(
$obj
,
$attr
) =
$self
->_rearrange([
qw(OBJ ATTR)
],
@args
);
if
(
$attr
) {
$attr
=
'<dummy '
.
$attr
.
'/>'
;
}
my
$oldreader
=
$self
->{
'_reader'
};
$self
->{
'_reader'
} = XML::LibXML::Reader->new(
string
=>
$attr
,
no_blanks
=> 1
);
my
$reader
=
$self
->{
'_reader'
};
$self
->{
'_currentannotation'
} = [];
$self
->{
'_currenttext'
} =
''
;
$self
->{
'_lastitem'
}->{
'dummy'
}++;
push
@{
$self
->{
'_lastitem'
}->{
'current'
}}, {
'dummy'
=>{}};
push
@{
$self
->{
'_currentitems'
}},
$obj
;
while
(
$reader
->
read
)
{
$self
->processAttribute(
$self
->current_attr);
}
if
(
exists
$self
->current_attr->{
'id_source'
}) {
my
$idsrc
=
$self
->current_attr->{
'id_source'
};
$self
->{
'_id_link'
}->{
$idsrc
} =
$obj
;
}
my
$idref
=
''
;
if
(
exists
$self
->current_attr->{
'id_ref'
}) {
$idref
=
$self
->current_attr->{
'id_ref'
};
}
my
$srcbyidref
=
''
;
$srcbyidref
=
$self
->{
'_id_link'
}->{
$idref
};
if
(
$idref
xor
$srcbyidref
) {
$self
->throw(
"id_ref and id_src incompatible: $idref, $srcbyidref"
);
}
my
$newac
=
$obj
->annotation;
if
(
scalar
keys
%{
$self
->current_attr} ) {
my
$newattr
= Bio::Annotation::Collection->new();
foreach
my
$tag
(
keys
%{
$self
->current_attr}) {
my
$sv
= Bio::Annotation::SimpleValue->new(
-value
=>
$self
->current_attr->{
$tag
}
);
$newattr
->add_Annotation(
$tag
,
$sv
);
}
$newac
->add_Annotation(
'_attr'
,
$newattr
);
}
pop
@{
$self
->{
'_currentitems'
}};
$self
->{
'_lastitem'
}->{
$reader
->name }--
if
$reader
->name;
pop
@{
$self
->{
'_lastitem'
}->{
'current'
}};
$self
->{
'_reader'
} =
$oldreader
;
return
$obj
;
}
sub
add_phyloXML_annotation
{
my
(
$self
,
@args
) =
@_
;
my
(
$obj
,
$xml_string
) =
$self
->_rearrange([
qw(OBJ XML)
],
@args
);
$xml_string
=
'<phyloxml>'
.
$xml_string
.
'</phyloxml>'
;
$self
->debug(
$xml_string
);
my
$oldreader
=
$self
->{
'_reader'
};
$self
->{
'_reader'
} = XML::LibXML::Reader->new(
string
=>
$xml_string
,
no_blanks
=> 1
);
my
$reader
=
$self
->{
'_reader'
};
$self
->{
'_lastitem'
}->{
'clade'
}++;
push
@{
$self
->{
'_lastitem'
}->{
'current'
}}, {
'clade'
=>{}};
push
@{
$self
->{
'_currentitems'
}},
$obj
;
$reader
->
read
;
while
(
$reader
->
read
)
{
$self
->processXMLNode;
}
pop
@{
$self
->{
'_currentitems'
}};
$self
->{
'_lastitem'
}->{
$reader
->name }--
if
$reader
->name;
pop
@{
$self
->{
'_lastitem'
}->{
'current'
}};
$self
->{
'_reader'
} =
$oldreader
;
return
$obj
;
}
sub
write_tree
{
my
(
$self
,
@trees
) =
@_
;
foreach
my
$tree
(
@trees
) {
my
$root
=
$tree
->get_root_node;
$self
->_print(
"<phylogeny"
);
my
@tags
=
$tree
->get_all_tags();
my
$attr_str
=
''
;
foreach
my
$tag
(
@tags
) {
my
@values
=
$tree
->get_tag_values(
$tag
);
foreach
(
@values
) {
$attr_str
.=
" "
.
$tag
.
"=\""
.
$_
.
"\""
;
}
}
my
(
$b_rooted
) =
$tree
->get_tag_values(
'rooted'
);
if
(
$b_rooted
) {
$attr_str
.=
" rooted=\"true\""
;
}
else
{
if
(
$tree
->is_binary(
$tree
->get_root_node)) {
$attr_str
.=
" rooted=\"true\""
;
}
else
{
$attr_str
.=
" rooted=\"false\""
;
}
}
$self
->_print(
$attr_str
);
$self
->_print(
">"
);
if
(
$root
->isa(
'Bio::Tree::AnnotatableNode'
)) {
$self
->_print(
$self
->_write_tree_Helper_annotatableNode(
$root
));
}
else
{
$self
->_print(
$self
->_write_tree_Helper_generic(
$root
));
}
while
(
my
$str
=
pop
(@{
$self
->{
'_tree_attr'
}->{
'clade_relation'
}})) {
$self
->_print(
$str
);
}
while
(
my
$str
=
pop
(@{
$self
->{
'_tree_attr'
}->{
'sequence_relation'
}})) {
$self
->_print(
$str
);
}
$self
->_print(
"</phylogeny>"
);
}
$self
->flush
if
$self
->_flush_on_write &&
defined
$self
->_fh;
return
;
}
sub
_write_tree_Helper_annotatableNode
{
my
(
$self
,
$node
,
$str
) =
@_
;
my
$ac
=
$node
->annotation;
my
@relations
=
$ac
->get_Annotations(
'clade_relation'
);
foreach
(
@relations
) {
my
$clade_rel
=
$self
->_relation_to_string(
$node
,
$_
,
''
);
push
(@{
$self
->{
'_tree_attr'
}->{
'clade_relation'
}},
$clade_rel
);
}
$str
.=
'<clade'
;
my
(
$attr
) =
$ac
->get_Annotations(
'_attr'
);
if
(
$attr
) {
my
(
$id_source
) =
$attr
->get_Annotations(
'id_source'
);
if
(
$id_source
) {
$str
.=
" id_source=\""
.
$id_source
->value.
"\""
;
}
}
$str
.=
">"
;
foreach
my
$child
(
$node
->each_Descendent() ) {
$str
=
$self
->_write_tree_Helper_annotatableNode(
$child
,
$str
);
}
$str
= print_annotation(
$node
,
$str
,
$ac
);
if
(
$node
->has_sequence) {
foreach
my
$seq
(@{
$node
->sequence}) {
my
@relations
=
$seq
->annotation->get_Annotations(
'sequence_relation'
);
foreach
(
@relations
) {
my
$sequence_rel
=
$self
->_relation_to_string(
$seq
,
$_
,
''
);
push
(@{
$self
->{
'_tree_attr'
}->{
'sequence_relation'
}},
$sequence_rel
);
}
$str
= print_seq_annotation(
$node
,
$str
,
$seq
);
}
}
$str
.=
"</clade>"
;
return
$str
;
}
sub
_write_tree_Helper_generic
{
my
(
$self
,
$node
,
$str
) =
@_
;
$str
.=
'<clade>'
;
foreach
my
$child
(
$node
->each_Descendent() ) {
$str
=
$self
->_write_tree_Helper_generic(
$child
,
$str
);
}
my
@tags
=
$node
->get_all_tags();
foreach
my
$tag
(
@tags
) {
my
@values
=
$node
->get_tag_values(
$tag
);
foreach
my
$val
(
@values
) {
$str
.=
"<property datatype=\"xsd:string\" ref=\"tag:$tag\" applies_to=\"clade\">"
;
$str
.=
$val
;
$str
.=
"</property>"
;
}
}
if
(
$node
->id) {
$str
.=
"<name>"
;
$str
.=
$node
->id;
$str
.=
"</name>"
;
}
if
(
$node
->branch_length) {
$str
.=
"<branch_length>"
;
$str
.=
$node
->branch_length;
$str
.=
"</branch_length>"
;
}
if
(
$node
->bootstrap) {
$str
.=
"<confidence type = \"bootstrap\">"
;
$str
.=
$node
->bootstrap;
$str
.=
"</confidence>"
;
}
$str
.=
"</clade>"
;
return
$str
;
}
sub
_relation_to_string {
my
(
$self
,
$obj
,
$rel
,
$str
) =
@_
;
my
@attr
=
$obj
->annotation->get_Annotations(
'_attr'
);
if
(
@attr
) {
my
@id_source
=
$attr
[0]->get_Annotations(
'id_source'
);
}
my
(
$id_ref_0
) =
$obj
->annotation->get_nested_Annotations(
'-keys'
=> [
'id_source'
],
'-recursive'
=> 1);
my
(
$id_ref_1
) =
$rel
->to->annotation->get_nested_Annotations(
'-keys'
=> [
'id_source'
],
'-recursive'
=> 1);
my
$confidence
=
$rel
->confidence();
my
$confidence_type
=
$rel
->confidence_type();
$str
.=
"<"
;
$str
.=
$rel
->tagname;
$str
.=
" id_ref_0=\""
.
$id_ref_0
->value.
"\""
;
$str
.=
" id_ref_1=\""
.
$id_ref_1
->value.
"\""
;
$str
.=
" type=\""
.
$rel
->type.
"\""
;
if
(
$confidence
) {
$str
.=
" ><confidence"
;
if
(
$confidence_type
) {
$str
.=
" type=\""
.
$confidence_type
.
"\""
;
}
$str
.=
">"
;
$str
.=
$confidence
;
$str
.=
"</confidence>"
;
$str
.=
"</"
;
$str
.=
$rel
->tagname;
$str
.=
">"
;
}
else
{
$str
.=
"/>"
;
}
return
$str
;
}
sub
read_annotation
{
my
(
$self
,
@args
) =
@_
;
my
(
$obj
,
$path
,
$attr
) =
$self
->_rearrange([
qw(OBJ PATH ATTR)
],
@args
);
my
$ac
=
$obj
->annotation;
if
(
$attr
) {
my
@elements
=
split
(
'/'
,
$path
);
my
$final
=
pop
@elements
;
push
(
@elements
,
'_attr'
);
push
(
@elements
,
$final
);
$path
=
join
(
'/'
,
@elements
);
return
$self
->_read_annotation_attr_Helper( [
$ac
],
$path
);
}
else
{
return
$self
->_read_annotation_text_Helper( [
$ac
],
$path
);
}
}
sub
_read_annotation_text_Helper
{
my
(
$self
,
$acs
,
$path
) =
@_
;
my
@elements
=
split
(
'/'
,
$path
);
my
$key
=
shift
@elements
;
my
@nextacs
= ();
foreach
my
$ac
(
@$acs
) {
foreach
my
$ann
(
$ac
->get_Annotations(
$key
)) {
if
(
$ann
->isa(
'Bio::AnnotationCollectionI'
)) {
push
(
@nextacs
,
$ann
)}
}
}
if
(
@elements
== 0) {
my
@values
= ();
my
@texts
=
map
{
$_
->get_Annotations(
'_text'
)}
@nextacs
;
foreach
(
@texts
) {
$_
&&
push
(
@values
,
$_
->value);
}
return
@values
;
}
else
{
$path
=
join
(
'/'
,
@elements
);
return
$self
->_read_annotation_text_Helper( \
@nextacs
,
$path
);
}
}
sub
_read_annotation_attr_Helper
{
my
(
$self
,
$acs
,
$path
) =
@_
;
my
@elements
=
split
(
'/'
,
$path
);
my
$key
=
shift
@elements
;
my
@nextacs
= ();
foreach
my
$ac
(
@$acs
) {
foreach
my
$ann
(
$ac
->get_Annotations(
$key
)) {
if
(
$ann
->isa(
'Bio::AnnotationCollectionI'
)) {
push
(
@nextacs
,
$ann
)}
}
}
if
(
@elements
== 1) {
my
$attrname
=
$elements
[0];
my
@sv
=
map
{
$_
->get_Annotations(
$attrname
)}
@nextacs
;
return
map
{
$_
->value}
@sv
;
}
else
{
$path
=
join
(
'/'
,
@elements
);
return
$self
->_read_annotation_attr_Helper( \
@nextacs
,
$path
);
}
}
sub
processXMLNode
{
my
(
$self
) =
@_
;
my
$reader
=
$self
->{
'_reader'
};
my
$nodetype
=
$reader
->nodeType;
if
(
$nodetype
== XML_READER_TYPE_ELEMENT)
{
$self
->{
'_lastitem'
}->{
$reader
->name}++;
push
@{
$self
->{
'_lastitem'
}->{
'current'
}}, {
$reader
->
name
=>{}};
if
(
exists
$self
->{
'_start_elements'
}->{
$reader
->name}) {
my
$method
=
$self
->{
'_start_elements'
}->{
$reader
->name};
$self
->
$method
();
}
else
{
$self
->element_default();
}
if
(
$reader
->isEmptyElement) {
$nodetype
= XML_READER_TYPE_END_ELEMENT;
}
}
if
(
$nodetype
== XML_READER_TYPE_TEXT)
{
$self
->{
'_currenttext'
} =
$reader
->value;
}
if
(
$nodetype
== XML_READER_TYPE_END_ELEMENT)
{
if
(
exists
$self
->{
'_end_elements'
}->{
$reader
->name}) {
my
$method
=
$self
->{
'_end_elements'
}->{
$reader
->name};
$self
->
$method
();
}
else
{
$self
->end_element_default();
}
$self
->{
'_lastitem'
}->{
$reader
->name }--;
pop
@{
$self
->{
'_lastitem'
}->{
'current'
}};
$self
->{
'_currenttext'
} =
''
;
}
}
sub
processAttribute
{
my
(
$self
,
$data
) =
@_
;
my
$reader
=
$self
->{
'_reader'
};
if
(
$reader
-> moveToFirstAttribute) {
do
{
$data
->{
$reader
->name()} =
$reader
->value;
}
while
(
$reader
-> moveToNextAttribute);
$reader
-> moveToElement;
}
}
sub
element_phylogeny
{
my
(
$self
) =
@_
;
$self
->{
'_currentitems'
} = [];
$self
->{
'_currentnodes'
} = [];
$self
->{
'_currentannotation'
} = [];
$self
->{
'_currenttext'
} =
''
;
$self
->{
'_levelcnt'
} = [];
$self
->{
'_id_link'
} = {};
$self
->{
'_tree_attr'
} =
$self
->current_attr;
$self
->processAttribute(
$self
->current_attr);
return
;
}
sub
end_element_phylogeny
{
my
(
$self
) =
@_
;
my
$root
;
if
( @{
$self
->{
'_currentnodes'
}} > 1)
{
$root
=
$self
->nodetype->new(
-id
=>
''
,
tostring
=> \
&node_to_string
,
);
while
( @{
$self
->{
'_currentnodes'
}} ) {
my
(
$node
) = (
shift
@{
$self
->{
'_currentnodes'
}});
$root
->add_Descendent(
$node
);
}
}
elsif
( @{
$self
->{
'_currentnodes'
}} == 1)
{
$root
=
shift
@{
$self
->{
'_currentnodes'
}};
}
my
$tree
=
$self
->treetype->new(
-root
=>
$root
,
-id
=>
$self
->current_attr->{
'name'
},
%{
$self
->current_attr}
);
foreach
my
$tag
(
keys
%{
$self
->current_attr} ) {
$tree
->add_tag_value(
$tag
,
$self
->current_attr->{
$tag
} );
}
return
$tree
;
}
sub
element_clade
{
my
(
$self
) =
@_
;
my
$reader
=
$self
->{
'_reader'
};
my
%clade_attr
= ();
$self
->processAttribute(\
%clade_attr
);
my
$tnode
=
$self
->nodetype->new(
-id
=>
''
,
tostring
=> \
&node_to_string
,
%clade_attr
,
);
my
$ac
=
$tnode
->annotation;
my
$newattr
= Bio::Annotation::Collection->new();
foreach
my
$tag
(
keys
%clade_attr
) {
my
$sv
= Bio::Annotation::SimpleValue->new(
-value
=>
$clade_attr
{
$tag
}
);
$newattr
->add_Annotation(
$tag
,
$sv
);
}
$ac
->add_Annotation(
'_attr'
,
$newattr
);
if
(
exists
$clade_attr
{
'id_source'
}) {
$self
->{
'_id_link'
}->{
$clade_attr
{
'id_source'
}} =
$tnode
;
}
push
@{
$self
->{
'_currentitems'
}},
$tnode
;
}
sub
end_element_clade
{
my
(
$self
) =
@_
;
my
$reader
=
$self
->{
'_reader'
};
my
$curcount
=
scalar
@{
$self
->{
'_currentnodes'
}};
my
$level
=
$reader
->depth() - 2;
my
$childcnt
=
$self
->{
'_levelcnt'
}->[
$level
+1] || 0;
my
$tnode
=
pop
@{
$self
->{
'_currentitems'
}};
if
(
$childcnt
> 0) {
if
(
$childcnt
>
$curcount
)
{
$self
->throw(
"something wrong with event construction treelevel "
.
"$level is recorded as having $childcnt nodes "
.
"but current nodes at this level is $curcount\n"
);
}
my
@childnodes
=
splice
( @{
$self
->{
'_currentnodes'
}}, -
$childcnt
);
for
(
@childnodes
) {
$tnode
->add_Descendent(
$_
);
}
$self
->{
'_levelcnt'
}->[
$level
+1] = 0;
}
push
@{
$self
->{
'_currentnodes'
}},
$tnode
;
$self
->{
'_levelcnt'
}->[
$level
]++;
}
sub
element_relation
{
my
(
$self
) =
@_
;
$self
->processAttribute(
$self
->current_attr);
my
$relationtype
=
$self
->current_attr->{
'type'
};
my
$id_ref_0
=
$self
->current_attr->{
'id_ref_0'
};
my
$id_ref_1
=
$self
->current_attr->{
'id_ref_1'
};
my
@srcbyidref
= ();
$srcbyidref
[0] =
$self
->{
'_id_link'
}->{
$id_ref_0
};
$srcbyidref
[1] =
$self
->{
'_id_link'
}->{
$id_ref_1
};
if
( (
$id_ref_0
xor
$srcbyidref
[0])||(
$id_ref_1
xor
$srcbyidref
[1]) ) {
$self
->throw(
"id_ref and id_src incompatible: $id_ref_0, $id_ref_1, "
,
$srcbyidref
[0],
$srcbyidref
[1]);
}
my
$ac0
=
$srcbyidref
[0]->annotation;
my
$newann
= Bio::Annotation::Relation->new(
'-type'
=>
$relationtype
,
'-to'
=>
$srcbyidref
[1],
'-tagname'
=>
$self
->current_element
);
$ac0
->add_Annotation(
$self
->current_element,
$newann
);
my
$ac1
=
$srcbyidref
[1]->annotation;
$newann
= Bio::Annotation::Relation->new(
'-type'
=>
$relationtype
,
'-to'
=>
$srcbyidref
[0],
'-tagname'
=>
$self
->current_element
);
$ac1
->add_Annotation(
$self
->current_element,
$newann
);
push
(@{
$self
->{
'_currentannotation'
}},
$newann
);
}
sub
end_element_relation
{
my
(
$self
) =
@_
;
my
$ac
=
pop
(@{
$self
->{
'_currentannotation'
}});
}
sub
element_default
{
my
(
$self
) =
@_
;
my
$reader
=
$self
->{
'_reader'
};
my
$current
=
$self
->current_element();
my
$prev
=
$self
->prev_element();
$self
->processAttribute(
$self
->current_attr);
my
$idref
=
''
;
if
(
exists
$self
->current_attr->{
'id_ref'
}) {
$idref
=
$self
->current_attr->{
'id_ref'
};
}
my
$srcbyidref
=
''
;
$srcbyidref
=
$self
->{
'_id_link'
}->{
$idref
};
if
(
$idref
xor
$srcbyidref
) {
$self
->throw(
"id_ref and id_src incompatible: $idref, $srcbyidref"
);
}
if
( (
$srcbyidref
&&
$srcbyidref
->isa(
$self
->nodetype)) || ((!
$srcbyidref
) &&
$prev
eq
'clade'
) ) {
my
$tnode
;
if
(
$srcbyidref
) {
$tnode
=
$srcbyidref
;
}
else
{
$tnode
=
$self
->{
'_currentitems'
}->[-1];
}
my
$ac
=
$tnode
->annotation();
my
$newann
= Bio::Annotation::Collection->new();
$ac
->add_Annotation(
$current
,
$newann
);
push
(@{
$self
->{
'_currentannotation'
}},
$newann
);
}
elsif
(
$prev
eq
'clade_relation'
||
$prev
eq
'sequence_relation'
) {
}
else
{
my
$ac
=
$self
->{
'_currentannotation'
}->[-1];
if
(
$ac
) {
my
$newann
= Bio::Annotation::Collection->new();
$ac
->add_Annotation(
$current
,
$newann
);
push
(@{
$self
->{
'_currentannotation'
}},
$newann
);
}
}
}
sub
end_element_default
{
my
(
$self
) =
@_
;
my
$reader
=
$self
->{
'_reader'
};
my
$current
=
$self
->current_element();
my
$prev
=
$self
->prev_element();
my
$idsrc
=
$self
->current_attr->{
'id_source'
};
my
$idref
=
''
;
if
(
exists
$self
->current_attr->{
'id_ref'
}) {
$idref
=
$self
->current_attr->{
'id_ref'
};
delete
$self
->current_attr->{
'id_ref'
};
}
my
$srcbyidref
=
''
;
$srcbyidref
=
$self
->{
'_id_link'
}->{
$idref
};
if
(
$idref
xor
$srcbyidref
) {
$self
->throw(
"id_ref and id_src incompatible: $idref, $srcbyidref"
);
}
if
((!
$srcbyidref
) &&
$prev
eq
'phylogeny'
) {
$self
->prev_attr->{
$current
} =
$self
->{
'_currenttext'
};
}
elsif
(
$prev
eq
'clade_relation'
||
$prev
eq
'sequence_relation'
) {
my
$ann_relation
=
$self
->{
'_currentannotation'
}->[-1];
if
(
$current
eq
'confidence'
) {
if
(
exists
$self
->current_attr->{
'type'
}) {
$ann_relation
->confidence_type(
$self
->current_attr->{
'type'
});
}
$ann_relation
->confidence(
$self
->{
'_currenttext'
});
}
else
{
$self
->throw(
$current
,
" is not allowed within <*_relation>"
);
}
}
elsif
((
$srcbyidref
&&
$srcbyidref
->isa(
$self
->nodetype)) || ((!
$srcbyidref
) &&
$prev
eq
'clade'
))
{
my
$ac
=
pop
(@{
$self
->{
'_currentannotation'
}});
$self
->annotateNode(
$current
,
$ac
);
my
$tnode
;
if
(
$srcbyidref
) {
$tnode
=
$srcbyidref
;
}
else
{
$tnode
=
$self
->{
'_currentitems'
}->[-1];
}
if
(
$current
eq
'name'
) {
$tnode
->id(
$self
->{
'_currenttext'
});
}
elsif
(
$current
eq
'branch_length'
) {
$tnode
->branch_length(
$self
->{
'_currenttext'
});
}
elsif
(
$current
eq
'confidence'
) {
if
((
exists
$self
->current_attr->{
'type'
}) && (
$self
->current_attr->{
'type'
} eq
'bootstrap'
)) {
$tnode
->bootstrap(
$self
->{
'_currenttext'
});
}
}
elsif
(
$current
eq
'sequence'
) {
my
$str
=
''
;
if
(
my
(
$molseq
) =
$ac
->get_Annotations(
'mol_seq'
)) {
my
(
$strac
) =
$molseq
->get_Annotations(
'_text'
);
$str
=
$strac
->value();
}
my
$newseq
= Bio::Seq->new(
-seq
=>
$str
,
-annotation
=>
$ac
,
-nowarnonempty
=>1);
$tnode
->sequence(
$newseq
);
$ac
->remove_Annotations(
'mol_seq'
);
$tnode
->annotation->remove_Annotations(
$current
);
if
(
$idsrc
) {
$self
->{
'_id_link'
}->{
$idsrc
} =
$newseq
;
}
}
elsif
(
$idsrc
&&
$current
eq
'taxonomy'
) {
$self
->{
'_id_link'
}->{
$idsrc
} =
$ac
;
}
}
else
{
my
$ac
=
pop
(@{
$self
->{
'_currentannotation'
}});
if
(
$ac
) {
$self
->annotateNode(
$current
,
$ac
);
}
}
}
sub
annotateNode
{
my
(
$self
,
$element
,
$newac
) =
@_
;
if
(
scalar
keys
%{
$self
->current_attr} ) {
my
$newattr
= Bio::Annotation::Collection->new();
foreach
my
$tag
(
keys
%{
$self
->current_attr}) {
my
$sv
= Bio::Annotation::SimpleValue->new(
-value
=>
$self
->current_attr->{
$tag
}
);
$newattr
->add_Annotation(
$tag
,
$sv
);
}
$newac
->add_Annotation(
'_attr'
,
$newattr
);
}
if
(
$self
->{
'_currenttext'
} ) {
my
$newvalue
= Bio::Annotation::SimpleValue->new(
-value
=>
$self
->{
'_currenttext'
} );
$newac
->add_Annotation(
'_text'
,
$newvalue
);
}
}
sub
current_attr {
my
(
$self
) =
@_
;
return
0
if
!
defined
$self
->{
'_lastitem'
} ||
!
defined
$self
->{
'_lastitem'
}->{
'current'
}->[-1];
my
@keys
=
keys
%{
$self
->{
'_lastitem'
}->{
'current'
}->[-1]};
(
@keys
== 1) ||
die
"there should be only one key for each hash"
;
return
$self
->{
'_lastitem'
}->{
'current'
}->[-1]->{
$keys
[0]};
}
sub
prev_attr {
my
(
$self
) =
@_
;
return
0
if
!
defined
$self
->{
'_lastitem'
} ||
!
defined
$self
->{
'_lastitem'
}->{
'current'
}->[-2];
my
@keys
=
keys
%{
$self
->{
'_lastitem'
}->{
'current'
}->[-2]};
(
@keys
== 1) ||
die
"there should be only one key for each hash"
;
return
$self
->{
'_lastitem'
}->{
'current'
}->[-2]->{
$keys
[0]};
}
sub
current_element {
my
(
$self
) =
@_
;
return
0
if
!
defined
$self
->{
'_lastitem'
} ||
!
defined
$self
->{
'_lastitem'
}->{
'current'
}->[-1];
my
@keys
=
keys
%{
$self
->{
'_lastitem'
}->{
'current'
}->[-1]};
(
@keys
== 1) ||
die
"there should be only one key for each hash"
;
return
$keys
[0];
}
sub
prev_element {
my
(
$self
) =
@_
;
return
0
if
!
defined
$self
->{
'_lastitem'
} ||
!
defined
$self
->{
'_lastitem'
}->{
'current'
}->[-2];
my
@keys
=
keys
%{
$self
->{
'_lastitem'
}->{
'current'
}->[-2]};
(
@keys
== 1) ||
die
"there should be only one key for each hash"
;
return
$keys
[0];
}
sub
treetype{
my
(
$self
,
$value
) =
@_
;
if
(
defined
$value
) {
$self
->{
'treetype'
} =
$value
;
}
return
$self
->{
'treetype'
};
}
sub
nodetype{
my
(
$self
,
$value
) =
@_
;
if
(
defined
$value
) {
$self
->{
'nodetype'
} =
$value
;
}
return
$self
->{
'nodetype'
};
}
sub
node_to_string
{
my
(
$self
) =
@_
;
my
$str
=
''
;
my
$ac
=
$self
->annotation;
$str
.=
'<clade'
;
my
@attr
=
$ac
->get_Annotations(
'_attr'
);
if
(
@attr
) {
my
@id_source
=
$attr
[0]->get_Annotations(
'id_source'
);
if
(
@id_source
) {
$str
.=
" id_source=\""
.
$id_source
[0]->value.
"\""
;
}
}
$str
.=
'>'
;
$str
= print_annotation(
$self
,
$str
,
$ac
);
if
(
$self
->has_sequence) {
foreach
my
$seq
(@{
$self
->sequence}) {
$str
= print_seq_annotation(
$self
,
$str
,
$seq
);
}
}
$str
.=
'</clade>'
;
return
$str
;
}
sub
print_annotation
{
my
(
$self
,
$str
,
$ac
) =
@_
;
my
@all_anns
=
$ac
->get_Annotations();
foreach
my
$ann
(
@all_anns
) {
my
$key
=
$ann
->tagname;
if
(
$key
eq
'_attr'
) {
next
; }
if
(
$ann
->isa(
'Bio::Annotation::SimpleValue'
))
{
if
(
$key
eq
'_text'
) {
$str
.=
$ann
->value;
}
else
{
$str
.=
"<$key>"
;
$str
.=
$ann
->value;
$str
.=
"</$key>"
;
}
}
elsif
(
$ann
->isa(
'Bio::Annotation::Collection'
))
{
my
@attrs
=
$ann
->get_Annotations(
'_attr'
);
if
(
@attrs
) {
$str
.=
"<$key"
;
$str
= print_attr(
$self
,
$str
,
$attrs
[0]);
$str
.=
">"
;
}
else
{
$str
.=
"<$key>"
;
}
$str
= print_annotation(
$self
,
$str
,
$ann
);
$str
.=
"</$key>"
;
}
}
return
$str
;
}
sub
print_attr
{
my
(
$self
,
$str
,
$ac
) =
@_
;
my
@all_attrs
=
$ac
->get_Annotations();
foreach
my
$attr
(
@all_attrs
) {
if
(!
$attr
->isa(
'Bio::Annotation::SimpleValue'
)) {
$self
->throw(
"attribute should be a SimpleValue"
);
}
$str
.=
' '
;
$str
.=
$attr
->tagname;
$str
.=
'='
;
$str
.=
'"'
.
$attr
->value.
'"'
;
}
return
$str
;
}
sub
print_seq_annotation
{
my
(
$self
,
$str
,
$seq
) =
@_
;
$str
.=
"<sequence"
;
my
(
$attr
) =
$seq
->annotation->get_Annotations(
'_attr'
);
if
(
$attr
) {
my
(
$id_source
) =
$attr
->get_Annotations(
'id_source'
);
if
(
$id_source
) {
$str
.=
" id_source=\""
.
$id_source
->value.
"\""
;
}
}
$str
.=
">"
;
my
@all_anns
=
$seq
->annotation->get_Annotations();
foreach
my
$ann
(
@all_anns
) {
my
$key
=
$ann
->tagname;
if
(
$key
eq
'_attr'
) {
next
; }
if
(
$ann
->isa(
'Bio::Annotation::SimpleValue'
))
{
if
(
$key
eq
'_text'
) {
$str
.=
$ann
->value;
}
else
{
$str
.=
"<$key>"
;
$str
.=
$ann
->value;
$str
.=
"</$key>"
;
}
}
elsif
(
$ann
->isa(
'Bio::Annotation::Collection'
))
{
my
@attrs
=
$ann
->get_Annotations(
'_attr'
);
if
(
@attrs
) {
$str
.=
"<$key"
;
$str
= print_attr(
$self
,
$str
,
$attrs
[0]);
$str
.=
">"
;
}
else
{
$str
.=
"<$key>"
;
}
$str
= print_annotation(
$self
,
$str
,
$ann
);
$str
.=
"</$key>"
;
}
}
if
(
$seq
->seq()) {
$str
.=
"<mol_seq>"
;
$str
.=
$seq
->seq();
$str
.=
"</mol_seq>"
;
}
$str
.=
"</sequence>"
;
return
$str
;
}
1;