1# #START_LICENSE###########################################################
2#
3#
4# This file is part of the Environment for Tree Exploration program
5# (ETE).  http://etetoolkit.org
6#
7# ETE is free software: you can redistribute it and/or modify it
8# under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11#
12# ETE is distributed in the hope that it will be useful, but WITHOUT
13# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15# License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with ETE.  If not, see <http://www.gnu.org/licenses/>.
19#
20#
21#                     ABOUT THE ETE PACKAGE
22#                     =====================
23#
24# ETE is distributed under the GPL copyleft license (2008-2015).
25#
26# If you make use of ETE in published work, please cite:
27#
28# Jaime Huerta-Cepas, Joaquin Dopazo and Toni Gabaldon.
29# ETE: a python Environment for Tree Exploration. Jaime BMC
30# Bioinformatics 2010,:24doi:10.1186/1471-2105-11-24
31#
32# Note that extra references to the specific methods implemented in
33# the toolkit may be available in the documentation.
34#
35# More info at http://etetoolkit.org. Contact: huerta@embl.de
36#
37#
38# #END_LICENSE#############################################################
39"""
40This module implements the interoperability between Phylogeny and
41Clade attributes in the phyloXMl schema and the ETE Tree objects.
42
43The PhyloxmlTree class should be use as a substitute for base Clade
44and Phylogeny classes.
45
46"""
47from __future__ import absolute_import
48
49import sys
50from ._phyloxml import Clade, Phylogeny, Confidence, Tag_pattern_
51from .. import PhyloTree
52
53class PhyloxmlTree(PhyloTree):
54    ''' PhyloTree object supporting phyloXML format. '''
55
56    def __repr__(self):
57        return "PhyloXML ETE tree <%s>" %hex(hash(self))
58
59    def _get_dist(self):
60        v = self.phyloxml_clade.get_branch_length_attr()
61        if v is None:
62            v = self.phyloxml_clade.get_branch_length()
63        if v is None:
64            self._set_dist(self._dist)
65            v = self.phyloxml_clade.get_branch_length_attr()
66        return float(v)
67
68    def _set_dist(self, value):
69        try:
70            self.phyloxml_clade.set_branch_length(float(value))
71            self.phyloxml_clade.set_branch_length_attr(float(value))
72        except ValueError:
73            raise
74
75    def _get_support(self):
76        if len(self.phyloxml_clade.confidence) == 0:
77                _c = Confidence(valueOf_=1.0, type_="branch_support")
78                self.phyloxml_clade.add_confidence(_c)
79        return float(self.phyloxml_clade.confidence[0].valueOf_)
80
81    def _set_support(self, value):
82        self._get_support()
83        self.phyloxml_clade.confidence[0].valueOf_ = float(value)
84
85    def _get_name(self):
86        return self.phyloxml_clade.get_name()
87
88    def _set_name(self, value):
89        try:
90            self.phyloxml_clade.set_name(value)
91        except ValueError:
92            raise
93
94    def _get_children(self):
95        return self.phyloxml_clade.clade
96
97    dist = property(fget=_get_dist, fset=_set_dist)
98    support = property(fget=_get_support, fset=_set_support)
99    children = property(fget=_get_children)
100    name = property(fget=_get_name, fset=_set_name)
101
102    def __init__(self, phyloxml_clade=None, phyloxml_phylogeny=None, **kargs):
103        if not phyloxml_phylogeny:
104            self.phyloxml_phylogeny = Phylogeny()
105        else:
106            self.phyloxml_phylogeny = phyloxml_phylogeny
107        if not phyloxml_clade:
108            self.phyloxml_clade = Clade()
109            self.phyloxml_clade.set_branch_length(0.0)
110            self.phyloxml_clade.set_name("NoName")
111            #self.__support = Confidence(valueOf_=1.0, type_="branch_support")
112            #self.phyloxml_clade.add_confidence(self.__support)
113        else:
114            self.phyloxml_clade = phyloxml_clade
115        super(PhyloxmlTree, self).__init__(**kargs)
116
117    def build(self, node):
118        nodetype = Tag_pattern_.match(node.tag).groups()[-1]
119        if nodetype == 'phylogeny':
120            self.phyloxml_phylogeny.buildAttributes(node, node.attrib, [])
121        elif nodetype == 'clade':
122            if "branch_length" in node.attrib:
123                node.attrib["branch_length_attr"] = node.attrib["branch_length"]
124            self.phyloxml_clade.buildAttributes(node, node.attrib, [])
125        for child in node:
126            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
127            self.buildChildren(child, node, nodeName_, nodetype=nodetype)
128
129    def buildChildren(self, child_, node, nodeName_, fromsubclass=False, nodetype=None):
130        if nodetype == 'phylogeny':
131            baseclass = self.phyloxml_phylogeny
132            if nodeName_ == 'clade':
133                self.build(child_)
134            else:
135                baseclass.buildChildren(child_, node, nodeName_)
136        elif nodetype == 'clade':
137            baseclass = self.phyloxml_clade
138            if nodeName_ == 'clade':
139                new_node = self.add_child()
140                new_node.build(child_)
141            else:
142                baseclass.buildChildren(child_, node, nodeName_)
143
144    def export(self, outfile=sys.stdout, level=0, namespace_='phy:', name_='Phylogeny', namespacedef_=''):
145        if not self.up:
146            self.phyloxml_phylogeny.clade = self.phyloxml_clade
147            self.phyloxml_clade.clade = self.children
148            self.phyloxml_phylogeny.export(outfile=outfile, level=level, name_=name_, namespacedef_=namespacedef_)
149        else:
150            self.phyloxml_clade.clade = self.children
151            self.phyloxml_clade.export(outfile=outfile, level=level, name_=name_, namespacedef_=namespacedef_)
152
153