def build_fixed_basic_tree1(self): """ Returns a bifurcating basic tree looking like: http://en.wikipedia.org/wiki/Tree_traversal ( ( A, ( C, E )D )B, ( ( H )I )G )F Preorder traversal sequence: F, B, A, D, C, E, G, I, H Inorder traversal sequence: A, B, C, D, E, F, G, H, I Postorder traversal sequence: A, C, E, D, B, H, I, G, F Level-order traversal sequence: F, B, G, A, D, I, C, E, H """ tree = trees.Tree(oid='tree1') tree.seed_node.oid = 'F' node_B = tree.seed_node.new_child('B') node_B.new_child('A') node_D = node_B.new_child('D') node_D.new_child('C') node_D.new_child('E') node_G = tree.seed_node.new_child('G') node_I = node_G.new_child('I') node_I.new_child('H') return tree
def build_fixed_basic_tree2(self): """ Returns a larger bifurcating basic tree: ( ( ( ( T1, ( ( T2, T3 )i5, T4 )i4 )i3, ( T5, T6, T13 )i6 )i2, ( ( T7, ( T8, T9 )i9 )i8, T10 )i7 )i1, T14, ( T11, T12 )i10 )i0; """ tree = trees.Tree(oid='tree2') tree.seed_node.oid = 'i0' node_i1 = tree.seed_node.new_child('i1') node_i2 = node_i1.new_child('i2') node_i3 = node_i2.new_child('i3') node_i3.new_child('T1') node_i4 = node_i3.new_child('i4') node_i5 = node_i4.new_child('i5') node_i5.new_child('T2') node_i5.new_child('T3') node_i4.new_child('T4') node_i6 = node_i2.new_child('i6') node_i6.new_child('T5') node_i6.new_child('T6') node_i7 = node_i1.new_child('i7') node_i8 = node_i7.new_child('i8') node_i8.new_child('T7') node_i9 = node_i8.new_child('i9') node_i9.new_child('T8') node_i9.new_child('T9') node_i7.new_child('T10') tree.seed_node.new_child('T14') node_i10 = tree.seed_node.new_child('i10') node_i10.new_child('T11') node_i10.new_child('T12') node_i6.new_child('T13') return tree
def uniform_pure_birth(taxa_block, birth_rate=1.0, ultrametricize=True, tree_factory=None, rng=None): "Generates a uniform-rate pure-birth process tree. " if rng is None: rng = GLOBAL_RNG # use the global rng by default if tree_factory is not None: tree = tree_factory() tree.taxa_block = taxa_block else: tree = trees.Tree(taxa=taxa_block) leaf_nodes = tree.leaf_nodes() count = 0 while len(leaf_nodes) < len(taxa_block): parent_node = rng.choice(leaf_nodes) edge_length = rng.expovariate(len(leaf_nodes) / birth_rate) child1 = trees.Node() child2 = trees.Node() child1.node_id = 'n' + str(count + 1) child2.node_id = 'n' + str(count + 2) child1.edge.length = edge_length child2.edge.length = edge_length parent_node.add_child(child1) parent_node.add_child(child2) count = count + 2 leaf_nodes = tree.leaf_nodes() leaf_nodes = tree.leaf_nodes() for idx, leaf in enumerate(leaf_nodes): leaf.taxon = taxa_block[idx] if ultrametricize: max_distance_from_root = max( [node.distance_from_root() for node in leaf_nodes]) for node in leaf_nodes: node.edge.length = node.edge.length + (max_distance_from_root - node.distance_from_root()) return tree
def star_tree(taxa_block): "Builds and returns a star tree from the given taxa block." star_tree = trees.Tree(taxa=taxa_block) for taxon in taxa_block: star_tree.seed_node.new_child(node_taxon=taxon) return star_tree
def constrained_kingman(pop_tree, gene_trees_block=None, node_factory=None, tree_factory=None, rng=None, num_genes_attr='num_genes', pop_size_attr='pop_size'): """ Given a population tree, `pop_tree` this will return a *pair of trees*: a gene tree simulated on this population tree based on Kingman's n-coalescent, and population tree with the additional attribute 'gene_nodes' on each node, which is a list of uncoalesced nodes from the gene tree associated with the given node from the population tree. `pop_tree` should be a DendroPy Tree object or an object of a class derived from this with the following attribute `num_genes` -- the number of gene samples from each population in the present. Each edge on the tree should also have the attribute `pop_size` -- the effective size of the population at this time. If `gene_trees_block` is given, then the gene tree is added to the tree block, and the tree block's taxa block will be used to manage the gene tree's `taxa`. """ # get our random number generator if rng is None: rng = GLOBAL_RNG # use the global rng by default if gene_trees_block is not None: gtaxa = gene_trees_block.taxa_block else: gtaxa = taxa.TaxaBlock() # we create a set of gene nodes for each leaf node on the population # tree, and associate those gene nodes to the leaf by assignment # of 'taxon'. for leaf_count, leaf in enumerate(pop_tree.leaf_iter()): gene_nodes = [] for gene_count in range(getattr(leaf, num_genes_attr)): if node_factory is not None: gene_node = node_factory() else: gene_node = trees.Node() gene_node.taxon = gtaxa.get_taxon(label=leaf.taxon.label + '_' + str(gene_count + 1)) gene_nodes.append(gene_node) leaf.gene_nodes = gene_nodes # We iterate through the edges of the population tree in post-order, # i.e., visiting child edges before we visit parent edges. For # each edge visited, we take the genes found in the child nodes, # and run the coalescent simulation on them bounded by the length # of the edge. Any genes that have not yet coalesced at the end of # this period are added to the genes of the tail (parent) node of # the edge. # start with a new (deep) copy of the population tree so as to not # to change the original tree poptree_copy = copy.deepcopy(pop_tree) # start with a new tree if tree_factory is not None: gene_tree = tree_factory.new_tree() else: gene_tree = trees.Tree() for edge in poptree_copy.postorder_edge_iter(): edge.head_node.gene_nodes = edge.head_node.gene_nodes # if mrca root, run unconstrained coalescent if edge.head_node.parent_node is None: if len(edge.head_node.gene_nodes) > 1: final = coalescent.coalesce(nodes=edge.head_node.gene_nodes, pop_size=pop_size, period=None, rng=rng) else: final = edge.head_node.gene_nodes gene_tree.seed_node = final[0] else: if hasattr(edge, pop_size_attr): pop_size = getattr(edge, pop_size_attr) else: # this means all our time will be in population units pop_size = 1 uncoal = coalescent.coalesce(nodes=edge.head_node.gene_nodes, pop_size=pop_size, period=edge.length, rng=rng) if not hasattr(edge.tail_node, 'gene_nodes'): edge.tail_node.gene_nodes = [] edge.tail_node.gene_nodes.extend(uncoal) if gene_trees_block is not None: gene_trees_block.append(gene_tree) return gene_tree, poptree_copy