ete2.phylo.phylotree

Package ete2 :: Package phylo :: Module phylotree |
[hide private]
[frames] | no frames]

# Source Code for Module ete2.phylo.phylotree

      1  __VERSION__="ete2-2.0rev95"
      2  # #START_LICENSE###########################################################
      3  #
      4  # Copyright (C) 2009 by Jaime Huerta Cepas. All rights reserved.
      5  # email: jhcepas@gmail.com
      6  #
      7  # This file is part of the Environment for Tree Exploration program (ETE).
      8  # http://ete.cgenomics.org
      9  #
     10  # ETE is free software: you can redistribute it and/or modify it
     11  # under the terms of the GNU General Public License as published by
     12  # the Free Software Foundation, either version 3 of the License, or
     13  # (at your option) any later version.
     14  #
     15  # ETE is distributed in the hope that it will be useful,
     16  # but WITHOUT ANY WARRANTY; without even the implied warranty of
     17  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     18  # GNU General Public License for more details.
     19  #
     20  # You should have received a copy of the GNU General Public License
     21  # along with ETE.  If not, see <http://www.gnu.org/licenses/>.
     22  #
     23  # #END_LICENSE#############################################################
     24
     25  """
     26  This module defines the PhyloNode dataytype to manage phylogenetic
     27  tree. It inheritates the coretype TreeNode and add some speciall
     28  features to the the node instances.
     29  """
     30
     31  import sys
     32  import os
     33  import re
     34
     35  from ete2 import TreeNode, SeqGroup
     36  from reconciliation import get_reconciled_tree
     37  import spoverlap
     38
     39  __all__ = ["PhyloNode", "PhyloTree"]
     40
     41 -def _parse_species(name):
     42      return name[:3]
     43
     44 -class PhyloNode(TreeNode):
     45      """ Re-implementation of the standart TreeNode instance. It adds
     46      attributes and methods to work with phylogentic trees. """
     47
     48 -    def _get_species(self):
     49          if self._speciesFunction:
     50              try:
     51                  return self._speciesFunction(self.name)
     52              except:
     53                  return self._speciesFunction(self)
     54          else:
     55              return self._species
     56
     57 -    def _set_species(self, value):
     58          if self._speciesFunction:
     59              pass
     60          else:
     61              self._species = value
     62
     63      # This tweak overwrites the native 'name' attribute to create a
     64      # property that updates the species code every time name is
     65      # changed
     66      species = property(fget = _get_species, fset = _set_species)
     67
     68 -    def __init__(self, newick=None, alignment=None, alg_format="fasta", \
     69                   sp_naming_function=_parse_species, format=0):
     70          # _update names?
     71          self._name = "NoName"
     72          self._species = "Unknown"
     73          self._speciesFunction = None
     74          # Caution! native __init__ has to be called after setting
     75          # _speciesFunction to None!!
     76          TreeNode.__init__(self, newick=newick, format=format)
     77
     78          # This will be only executed after reading the whole tree,
     79          # because the argument 'alignment' is not passed to the
     80          # PhyloNode constructor during parsing
     81          if alignment:
     82              self.link_to_alignment(alignment, alg_format)
     83          if newick:
     84              self.set_species_naming_function(sp_naming_function)
     85
     86 -    def set_species_naming_function(self, fn):
     87          for n in self.iter_leaves():
     88              n.features.add("species")
     89              if fn:
     90                  n._speciesFunction = fn
     91
     92 -    def link_to_alignment(self, alignment, alg_format="fasta"):
     93          missing_leaves = []
     94          missing_internal = []
     95          if type(alignment) == SeqGroup:
     96              alg = alignment
     97          else:
     98              alg = SeqGroup(alignment, format=alg_format)
     99          # sets the seq of
    100          for n in self.traverse():
    101              try:
    102                  n.add_feature("sequence",alg.get_seq(n.name))
    103              except KeyError:
    104                  if n.is_leaf():
    105                      missing_leaves.append(n.name)
    106                  else:
    107                      missing_internal.append(n.name)
    108          if len(missing_leaves)>0:
    109              print >>sys.stderr, \
    110                  "Warnning: [%d] terminal nodes could not be found in the alignment." %\
    111                  len(missing_leaves)
    112          # Show warning of not associated internal nodes.
    113          # if len(missing_internal)>0:
    114          #     print >>sys.stderr, \
    115          #       "Warnning: [%d] internal nodes could not be found in the alignment." %\
    116          #       len(missing_leaves)
    117
    118
    119 -    def get_species(self):
    120          """ Returns the set of species covered by its partition. """
    121          return set( [ l.species for l in self.iter_leaves() ])
    122
    123 -    def iter_species(self):
    124          """ Returns an iterator over the species grouped by this node. """
    125          spcs = set([])
    126          for l in self.iter_leaves():
    127              if l.species not in spcs:
    128                  spcs.add(l.species)
    129                  yield l.species
    130
    131 -    def is_monophyletic(self, species):
    132          """ Returns True id species names under this node are all
    133          included in a given list or set of species names."""
    134          if type(species) != set:
    135              species = set(species)
    136          return self.get_species().issubset(species)
    137 -    def get_age(self, species2age):
    138          return max([species2age[sp] for sp in self.get_species()])
    139 -    def reconcile(self, species_tree):
    140          """ Returns the reconcilied topology with the provided species
    141          tree, and a list of evolutionary events inferred from such
    142          reconciliation. """
    143          return get_reconciled_tree(self, species_tree, [])
    144
    145 -    def get_my_evol_events(self, sos_thr=0.0):
    146          """ Returns a list of duplication and speciation events in
    147          which the current node has been involved. Scanned nodes are
    148          also labeled internally as dup=True|False. You can access this
    149          labels using the 'node.dup' sintaxis.
    150
    151          Method: the algorithm scans all nodes from the given leafName to
    152          the root. Nodes are assumed to be duplications when a species
    153          overlap is found between its child linages. Method is described
    154          more detail in:
    155
    156          "The Human Phylome." Huerta-Cepas J, Dopazo H, Dopazo J, Gabaldon
    157          T. Genome Biol. 2007;8(6):R109.
    158          """
    159          return spoverlap.get_evol_events_from_leaf(self, sos_thr=sos_thr)
    160
    161 -    def get_descendant_evol_events(self, sos_thr=0.0):
    162          """ Returns a list of **all** duplication and speciation
    163          events detected after this node. Nodes are assumed to be
    164          duplications when a species overlap is found between its child
    165          linages. Method is described more detail in:
    166
    167          "The Human Phylome." Huerta-Cepas J, Dopazo H, Dopazo J, Gabaldon
    168          T. Genome Biol. 2007;8(6):R109.
    169          """
    170          return spoverlap.get_evol_events_from_root(self, sos_thr=sos_thr)
    171
    172 -    def get_farthest_oldest_leaf(self, species2age):
    173          """ Returns the farthest oldest leafnode to the current
    174          one. It requieres an species2age dictionary with the age
    175          estimation for all species."""
    176
    177          root = self.get_tree_root()
    178
    179          # Get all tree leaves
    180          leaves      = root.get_leaves()
    181
    182          outgroup_dist  = 0
    183          outgroup_node  = self
    184          outgroup_age = 0 #species2age[self.species]
    185
    186          for leaf in leaves:
    187              if species2age[leaf.species] > outgroup_age: # OJO! Change crocodile to invert the comparison.
    188                  outgroup_dist = leaf.get_distance(self)
    189                  outgroup_node = leaf
    190                  outgroup_age = species2age[leaf.species]
    191              elif species2age[leaf.species]==outgroup_age:
    192                  dist = leaf.get_distance(self)
    193                  if dist>outgroup_dist:
    194                      outgroup_dist  = leaf.get_distance(self)
    195                      outgroup_node  = leaf
    196                      outgroup_age = species2age[leaf.species]
    197              else:
    198                  pass
    199          return outgroup_node
    200
    201  # cosmetic alias
    202  PhyloTree = PhyloNode
    203