def _label(tree, ancestors): """ Relabel internal nodes of a tree and map them to the corresponding name of ancestral sequences. :param tree: str, a NEWICK format string or file for a tree (must start with "(" and end with ';'). :param ancestors: dict, a dict object stores sequences. :return: tuple, a relabeled tree object and a dict object for sequences. """ if isinstance(tree, str): if os.path.isfile(tree): pass elif tree.startswith('(') and tree.endswith(';'): tree = StringIO(tree) else: error('Invalid tree encounter, tree relabel aborted.') sys.exit(1) tree = Phylo.read(tree, 'newick') number, maps = tree.count_terminals(), {} for clade in tree.find_clades(): if not clade.is_terminal(): clade.confidence = None number += 1 old, new = clade.name, 'NODE{}'.format(number) maps[old] = new clade.name = new ancestors = {maps.get(k, k): v for k, v in ancestors.items()} return tree, ancestors
def __init__(self, tree, leave=False): """ A class handles phylogenetic trees. :param tree: str, a newick tree file or tree string (must start with '(' and end with ';'). :param leave: bool, whether exit the process or not once an error occurred. """ if isinstance(tree, str): if tree.startswith('(') and tree.endswith(';'): tree = StringIO(tree) elif os.path.isfile(tree): pass else: error( 'Invalid tree: {}, tree should be either a NEWICK format ' 'tree string or tree file.'.format(tree)) tree = None else: error('Invalid tree, tree should be a string.') tree = None if tree is None and leave: sys.exit(1) else: tree = Phylo.read(tree, 'newick') if tree else None if tree: leaves = len([c for c in tree.find_clades() if c.is_terminal()]) nodes = len([c for c in tree.find_clades() if not c.is_terminal()]) length = sum([ c.branch_length if c.branch_length else 0.0 for c in tree.find_clades() ]) else: leaves, nodes, length = 0, 0, 0.0 self.tree = tree self.leaves = leaves self.nodes = nodes self.length = length