annotate corebio/seq_io/_nexus/Nodes.py @ 9:f3462128e87c

Minor alterations to the galaxy interface with some better examples and error messages added.
author davidmurphy
date Mon, 30 Jan 2012 08:17:57 -0500
parents c55bdc2fb9fa
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
1 # Copyright 2005 by Frank Kauff & Cymon J. Cox. All rights reserved.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
2 # This code is part of the Biopython distribution and governed by its
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
3 # license. Please see the LICENSE file that should have been included
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
4 # as part of this package.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
5 #
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
6 # Nodes.py
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
7 #
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
8 # Provides functionality of a linked list.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
9 # Each node has one (or none) predecessor, and an arbitrary number of successors.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
10 # Nodes can store arbitrary data in a NodeData class.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
11 #
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
12 # Subclassed by Nexus.Trees to store phylogenetic trees.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
13 #
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
14 # Bug reports to Frank Kauff (fkauff@duke.edu)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
15 #
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
16
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
17 class ChainException(Exception):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
18 pass
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
19
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
20 class NodeException(Exception):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
21 pass
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
22
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
23 class Chain:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
24 """Stores a list of nodes that are linked together."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
25
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
26 def __init__(self):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
27 """Initiates a node chain: (self)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
28 self.chain={}
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
29 self.id=-1
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
30
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
31 def _get_id(self):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
32 """Gets a new id for a node in the chain."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
33 self.id+=1
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
34 return self.id
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
35
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
36 def all_ids(self):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
37 """Return a list of all node ids."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
38 return self.chain.keys()
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
39
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
40 def add(self,node,prev=None):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
41 """Attaches node to another: (self, node, prev)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
42 if prev is not None and prev not in self.chain:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
43 raise ChainException('Unknow predecessor: '+str(prev))
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
44 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
45 id=self._get_id()
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
46 node.set_id(id)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
47 node.set_prev(prev)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
48 if prev is not None:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
49 self.chain[prev].add_succ(id)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
50 self.chain[id]=node
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
51 return id
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
52
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
53 def collapse(self,id):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
54 """Deletes node from chain and relinks successors to predecessor: collapse(self, id)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
55 if id not in self.chain:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
56 raise ChainException('Unknown ID: '+str(id))
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
57 prev_id=self.chain[id].get_prev()
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
58 self.chain[prev_id].remove_succ(id)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
59 succ_ids=self.chain[id].get_succ()
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
60 for i in succ_ids:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
61 self.chain[i].set_prev(prev_id)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
62 self.chain[prev_id].add_succ(succ_ids)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
63 node=self.chain[id]
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
64 self.kill(id)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
65 return node
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
66
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
67 def kill(self,id):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
68 """Kills a node from chain without caring to what it is connected: kill(self,id)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
69 if id not in self.chain:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
70 raise ChainException('Unknown ID: '+str(id))
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
71 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
72 del self.chain[id]
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
73
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
74 def unlink(self,id):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
75 """Disconnects node from his predecessor: unlink(self,id)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
76 if id not in self.chain:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
77 raise ChainException('Unknown ID: '+str(id))
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
78 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
79 prev_id=self.chain[id].prev
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
80 if prev_id is not None:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
81 self.chain[prev_id].succ.pop(self.chain[prev_id].succ.index(id))
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
82 self.chain[id].prev=None
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
83 return prev_id
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
84
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
85 def link(self, parent,child):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
86 """Connects son to parent: link(self,son,parent)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
87 if child not in self.chain:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
88 raise ChainException('Unknown ID: '+str(child))
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
89 elif parent not in self.chain:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
90 raise ChainException('Unknown ID: '+str(parent))
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
91 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
92 self.unlink(child)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
93 self.chain[parent].succ.append(child)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
94 self.chain[child].set_prev(parent)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
95
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
96 def is_parent_of(self,parent,grandchild):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
97 """Check if grandchild is a subnode of parent: is_parent_of(self,parent,grandchild)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
98 if grandchild==parent or grandchild in self.chain[parent].get_succ():
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
99 return True
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
100 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
101 for sn in self.chain[parent].get_succ():
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
102 if self.is_parent_of(sn,grandchild):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
103 return True
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
104 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
105 return False
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
106
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
107 def trace(self,start,finish):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
108 """Returns a list of all node_ids between two nodes (excluding start, including end): trace(start,end)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
109 if start not in self.chain or finish not in self.chain:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
110 raise NodeException('Unknown node.')
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
111 if not self.is_parent_of(start,finish) or start==finish:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
112 return []
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
113 for sn in self.chain[start].get_succ():
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
114 if self.is_parent_of(sn,finish):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
115 return [sn]+self.trace(sn,finish)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
116
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
117 class Node:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
118 """A single node."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
119
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
120 def __init__(self,data=None):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
121 """Represents a node with one predecessor and multiple successors: (self, data=None)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
122 self.id=None
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
123 self.data=data
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
124 self.prev=None
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
125 self.succ=[]
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
126
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
127 def set_id(self,id):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
128 """Sets the id of a node, if not set yet: (self,id)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
129 if self.id is not None:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
130 raise NodeException, 'Node id cannot be changed.'
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
131 self.id=id
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
132
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
133 def get_id(self):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
134 """Returns the node's id: (self)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
135 return self.id
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
136
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
137 def get_succ(self):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
138 """Returns a list of the node's successors: (self)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
139 return self.succ
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
140
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
141 def get_prev(self):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
142 """Returns the id of the node's predecessor: (self)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
143 return self.prev
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
144
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
145 def add_succ(self,id):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
146 """Adds a node id to the node's successors: (self,id)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
147 if isinstance(id,type([])):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
148 self.succ.extend(id)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
149 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
150 self.succ.append(id)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
151
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
152 def remove_succ(self,id):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
153 """Removes a node id from the node's successors: (self,id)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
154 self.succ.remove(id)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
155
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
156 def set_succ(self,new_succ):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
157 """Sets the node's successors: (self,new_succ)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
158 if not isinstance(new_succ,type([])):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
159 raise NodeException, 'Node successor must be of list type.'
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
160 self.succ=new_succ
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
161
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
162 def set_prev(self,id):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
163 """Sets the node's predecessor: (self,id)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
164 self.prev=id
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
165
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
166 def get_data(self):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
167 """Returns a node's data: (self)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
168 return self.data
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
169
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
170 def set_data(self,data):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
171 """Sets a node's data: (self,data)."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
172 self.data=data