Guest User

Untitled

a guest
Dec 13th, 2017
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.73 KB | None | 0 0
  1. #!/usr/bin/env python
  2. from ete3 import Tree
  3. import random
  4.  
  5.  
  6. def delete_single_child_internal(t):
  7. """Utility function that removes internal nodes
  8. with a single child from tree"""
  9.  
  10. for node in t.traverse("postorder"):
  11. if(not node.is_leaf() and len(node.get_children()) < 2):
  12. node.delete()
  13.  
  14. if len(t.get_children()) == 1:
  15. t = t.children[0]
  16. t.up = None
  17.  
  18.  
  19. def birth_only_tree(birth, nsize=10, max_time=None):
  20. """Generates a uniform-rate birth-only tree.
  21. Arguments:
  22. - ``birth`` : birth rate
  23. - ``nsize`` : desired number of leaves
  24. - ``max_time`` : maximum allowed time for evolution
  25. """
  26.  
  27. done = False
  28. total_time = 0
  29.  
  30. # create initial root node and set length to 0
  31. tree = Tree()
  32. tree.dist = 0.0
  33. # check if a stopping condition is provided
  34. if not (nsize or max_time):
  35. raise ValueError('A stopping criterion is required')
  36.  
  37. while True:
  38.  
  39. # get the current list of extant species
  40. leaf_nodes = tree.get_leaves()
  41.  
  42. # get required waiting time before next speciation
  43. wtime = random.expovariate(len(leaf_nodes) / birth)
  44.  
  45. # check if stopping criterion is reached then
  46. # stop loop if yes
  47. if len(leaf_nodes) >= nsize or (max_time and total_time + wtime >= max_time):
  48. done = True
  49.  
  50. # update the length of all current leaves
  51. # while not exceeding the maximum evolution time
  52. max_limited_time = min(
  53. wtime, (max_time or total_time + wtime) - total_time)
  54. for leaf in leaf_nodes:
  55. leaf.dist += max_limited_time
  56.  
  57. if done:
  58. break
  59.  
  60. # update total time of evolution
  61. total_time += max_limited_time
  62.  
  63. # add a new node to a randomly chosen leaf.
  64. node = random.choice(leaf_nodes)
  65. c1 = Tree()
  66. c2 = Tree()
  67. node.add_child(c1)
  68. node.add_child(c2)
  69. c1.dist = 0.0
  70. c2.dist = 0.0
  71.  
  72. # Label leaves here and also update
  73. # the last branch lengths
  74.  
  75. leaf_nodes = tree.get_leaves()
  76. leaf_compteur = 1
  77. for (ind, node) in enumerate(leaf_nodes):
  78. node.name = 'T%d' % leaf_compteur
  79. leaf_compteur += 1
  80.  
  81. return tree
  82.  
  83.  
  84. def birth_death_tree(birth, death, nsize=10, max_time=None, remlosses=True, r=True):
  85. """Generates a birth-death tree.
  86. Arguments:
  87. - ``birth`` : birth rate
  88. - ``death`` : death rate
  89. - ``nsize`` : desired number of leaves
  90. - ``max_time`` : maximum time of evolution
  91. - ``remlosses`` : whether lost leaves (extinct taxa) should be pruned from tree
  92. - ``r`` : repeat until success
  93. """
  94. # initialize tree with root node
  95. tree = Tree()
  96. tree.add_features(extinct=False)
  97. tree.dist = 0.0
  98. done = False
  99.  
  100. # get current list of leaves
  101. leaf_nodes = tree.get_leaves()
  102. curr_num_leaves = len(leaf_nodes)
  103.  
  104. total_time = 0
  105. died = set([])
  106.  
  107. # total event rate to compute waiting time
  108. event_rate = float(birth + death)
  109.  
  110. while True:
  111. # waiting time based on event_rate
  112. wtime = random.expovariate(event_rate)
  113. total_time += wtime
  114. for leaf in leaf_nodes:
  115. # extinct leaves cannot update their branches length
  116. if not leaf.extinct:
  117. leaf.dist += wtime
  118.  
  119. if curr_num_leaves >= nsize:
  120. done = True
  121.  
  122. if done:
  123. break
  124.  
  125. # if event occurs within time constraints
  126. if max_time is None or total_time <= max_time:
  127.  
  128. # select node at random, then find chance it died or give birth
  129. # (speciation)
  130. node = random.choice(leaf_nodes)
  131. eprob = random.random()
  132. leaf_nodes.remove(node)
  133. curr_num_leaves -= 1
  134.  
  135. # birth event (speciation)
  136. if eprob < birth / event_rate:
  137. child1 = Tree()
  138. child1.dist = 0
  139. child1.add_features(extinct=False)
  140. child2 = Tree()
  141. child2.dist = 0
  142. child2.add_features(extinct=False)
  143. node.add_child(child1)
  144. node.add_child(child2)
  145. leaf_nodes.append(child1)
  146. leaf_nodes.append(child2)
  147. # update add two new leave
  148. # (remember that parent was removed)
  149. curr_num_leaves += 2
  150.  
  151. else:
  152. # death of the chosen node
  153. if curr_num_leaves > 0:
  154. node.extinct = True
  155. died.add(node)
  156. else:
  157. if not r:
  158. raise ValueError(
  159. "All lineage went extinct, please retry")
  160. # Restart the simulation because the tree has gone
  161. # extinct
  162. tree = Tree()
  163. leaf_nodes = tree.get_leaves()
  164. tree.add_features(extinct=False)
  165. tree.dist = 0.0
  166. curr_num_leaves = 1
  167. died = set([])
  168. total_time = 0
  169.  
  170. # this should always hold true
  171. assert curr_num_leaves == len(leaf_nodes)
  172.  
  173. if remlosses:
  174. # prune lost leaves from tree
  175. leaves = set(tree.get_leaves()) - died
  176. tree.prune(leaves)
  177. # remove all non binary nodes
  178. delete_single_child_internal(tree)
  179.  
  180. leaf_nodes = tree.get_leaves()
  181. leaf_compteur = 1
  182. for ind, node in enumerate(leaf_nodes):
  183. # label only extant leaves
  184. if not node.extinct:
  185. # node.dist += wtime
  186. node.name = "T%d" % leaf_compteur
  187. leaf_compteur += 1
  188. return tree
  189.  
  190.  
  191. if __name__ == '__main__':
  192. yuletree = birth_only_tree(1.0, nsize=10)
  193. bdtree = birth_death_tree(1.0, 0.5, nsize=10)
Add Comment
Please, Sign In to add comment