-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathNode Class - Exercise 6a.py
222 lines (187 loc) · 8.23 KB
/
Node Class - Exercise 6a.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
"""
Exercise 6 - Creating and Using Node and Tree Classes
@author: jembrown
Below is the beginning of a Node class definition and a simple example of how
to link nodes to form a tree. Use this as a springboard to start thinking about:
- What other attributes of a Node might we like to store?
- How do we define a Tree class? What attributes should it have?
- Can you write a function to print out a parenthetical tree string
(e.g., ((spA,spB),spC)) if the only argument passed to the function is a
root node? This will require recursion.
"""
# ---> Defining Node and Tree classes <---
class Node:
def __init__(self,name="",parent=None,children=None):
self.name = name
self.parent = None
if children is None:
self.children = []
else:
self.children = children
# ---> Creating and linking nodes <---
# Creating nodes to build this simple three-taxon tree: ((spA,spB),spC)
# spA spB spC
# \ / /
# \ / /
# \/ /
# \ /
# \ /
# \/
# |
# Define the root node to start. It currently has no parents or children.
root = Node("root")
# Define a node for species C. It is a direct descendant of the root.
spC = Node("SpeciesC",parent=root)
root.children.append(spC) # Adds spC as a child of the root
# Define a node for the ancestor of species A and B, descending from the root.
ancAB = Node("ancAB",parent=root)
root.children.append(ancAB)
spA = Node("SpeciesA",parent=ancAB) # Creates spA with ancAB as its parent.
spB = Node("SpeciesB",parent=ancAB) # Creates spB with ancAB as its parent.
ancAB.children.append(spA)
ancAB.children.append(spB)
print("ancAB's children: ")
for child in ancAB.children:
print child.name
print("")
print("root's children: ")
for child in root.children:
print child.name
# Play around with nodes and see if you can build more complicated trees!
###Playing with the Golden-green Woodpecker tree - (P. leucolaemus(P. flavigula(P. aurulentus,P. chrysochloros)))
root = Node("root")
leucolaemus = Node ("leucolaemus",parent=root)
root.children.append(leucolaemus)
ancflav_aur_chry=Node("ancflav_aur_chry",parent=root)
root.children.append(ancflav_aur_chry)
flavigula=Node("flavigula",parent=ancflav_aur_chry)
ancflav_aur_chry.children.append(flavigula)
ancaur_chry=Node("ancaur_chry",parent=ancflav_aur_chry)
ancflav_aur_chry.children.append(ancaur_chry)
aurulentus=Node("aurulentus",parent=ancaur_chry)
ancaur_chry.children.append(aurulentus)
chrysochloros=Node("chrysochloros",parent=ancaur_chry)
ancaur_chry.children.append(chrysochloros)
print("ancaur_chry children: ")
for child in ancaur_chry.children:
print child.name
print("root's children: ")
for child in root.children:
print child.name
print("ancflav_aur_chry children: ")
for child in ancflav_aur_chry.children:
print child.name
# Eventually, we will want to create a Tree class, where a parenthetical tree
# string is passed as an argument to the constructor and it automatically creates
# all the nodes and links them together. Start thinking about how to do that.
# Let's go ahead and define a Tree object that houses all these nodes and
# organizes methods associated with them.
import ctmc
# We'll need this later, I promise. It's always better to put import statements
# outside of class definitions. In fact, it's best to put them all at the top
# of a file. This imports the ctmc class that we previously defined.
class Tree:
"""
Defines a class of phylogenetic tree, consisting of linked Node objects.
"""
def __init__(self):
"""
The constructor really needs to be more flexible, but for now we're
going to define the whole tree structure by hand. This just uses
the same statements we used above. By next Thurs (3/19), see if you can
write a constructor that takes a parenthetical tree as its argument and
builds the corresponding tree in memory.
"""
self.root = Node("root")
self.spC = Node("SpeciesC",parent=self.root)
self.root.children.append(self.spC)
self.ancAB = Node("ancAB",parent=self.root)
self.root.children.append(self.ancAB)
self.spA = Node("SpeciesA",parent=self.ancAB)
self.spB = Node("SpeciesB",parent=self.ancAB)
self.ancAB.children.append(self.spA)
self.ancAB.children.append(self.spB)
# Now, let's add branch lengths to our Node objects (remember, these fields
# can be added arbitrarily in Python). In the future, we should probably include
# branch lengths in the Node constructor.
self.spA.brl = 0.1
self.spB.brl = 0.1
self.spC.brl = 0.2
self.ancAB.brl = 0.1
self.root.brl = 0
# We're also going to add lists to each node that will hold simulated
# sequences.
self.spA.seq = []
self.spB.seq = []
self.spC.seq = []
self.ancAB.seq = []
self.root.seq = []
self.setModels(self.root)
# Write a recursive function that takes the root node as its only argument and
# prints out all the names of the terminal nodes in the tree. Due next Tues (3/17).
def printNames(self,node):
"""
A method of a Tree object that will print out the names of its
terminal nodes.
"""
if len(node.children) > 0:
for child in node.children:
self.printNames(child)
else:
print node.name
# Write a recursive function to calculate the total tree length (the sum of
# all the branch lengths). Again, the root node of a tree should be the only
# argument the first time this function is called. Due next Tues (3/17).
def treeLength(self,node):
"""
A method to calculate and return total tree length.
"""
sumbrl=0
if node.children is not None:
for child in node.children:
sumbrl += self.treeLength(child)###this sums the value of branch length and assigns the new value to the sum
return node.brl + sumbrl
# Write a recursive function that takes the root node as one of its arguments
# and prints out a parenthetical (Newick) tree string. Due next Tues (3/17).
def newick(self,node):
"""
A method of a Tree object that will print out the Tree as a
parenthetical string (Newick format).
"""
listoflists=[]
if len(node.children) > 0:
for child in node.children:
d=self.newick(child)
listoflists.append(d)
else:
listoflists.append(node.name)
return listoflists###instead of a string this returns a list of lists, I know this could be a problem in the future, but for now the relationships of the nodes are mantained
# Now, let's write a recursive function to simulate sequence evolution along a
# tree. This amounts to simply simulating evolution along each branch
# from the root towards the tips. We'll need to use our ctmc class for setting the
# conditions of our simulation, which is why we imported it above our tree
# class definition. In this case, we've stored the definition of our ctmc
# class in a separate file (ctmc.py) to keep our tree code compact.
# Now, let's add a ctmc object to each internal node in our tree (except the
# root). Again, it would be best to add the ctmcs as part of the Node
# constructor, if we know that we'll be simulating data.
# Try to get this simulator and associated functions working by next Thurs. (3/19)
def setModels(self,node):
"""
This method of a Tree object defines a ctmc object associated with all
nodes that have a branch length (i.e., all but the root).
"""
def simulate(self,node):
"""
This method simulates evolution along the branches of a tree, taking
the root node as its initial argument.
"""
def printSeqs(self,node):
"""
This method prints out the names of the tips and their associated
sequences as an alignment (matrix).
"""
d=Tree()
d.printNames(node=d.root)
d.treeLength(node=d.root)
d.newick(node=d.root)##This gives a list of lists and not a string...=P