Package Bio :: Package Pathway
[hide private]
[frames] | no frames]

Source Code for Package Bio.Pathway

  1  # Copyright 2001 by Tarjei Mikkelsen.  All rights reserved. 
  2  # This code is part of the Biopython distribution and governed by its 
  3  # license.  Please see the LICENSE file that should have been included 
  4  # as part of this package. 
  5   
  6  """BioPython Pathway module. 
  7   
  8  Bio.Pathway is a lightweight class library designed to support the following tasks: 
  9   
 10   - Data interchange and preprocessing between pathway databases and analysis software. 
 11   - Quick prototyping of pathway analysis algorithms 
 12   
 13  The basic object in the Bio.Pathway model is Interaction, which represents an arbitrary 
 14  interaction between any number of biochemical species. 
 15   
 16  Network objects are used to represent the connectivity between species in pathways 
 17  and reaction networks. 
 18   
 19  For applications where it is not necessary to explicitly represent network connectivity, 
 20  the specialized classes Reaction and System should be used in place of Interacton and 
 21  Network. 
 22   
 23  The Bio.Pathway classes, especially Interaction, are intentionally 
 24  designed to be very flexible. Their intended use are as wrappers around database 
 25  specific records, such as BIND objects. The value-added in this module is a 
 26  framework for representing collections of reactions in a way that supports 
 27  graph theoretic and numeric analysis. 
 28   
 29  Note: This module should be regarded as a prototype only. API changes are likely. 
 30        Comments and feature requests are most welcome. 
 31  """ 
 32   
 33  from functools import reduce 
 34   
 35  from Bio.Pathway.Rep.MultiGraph import * 
 36   
 37   
38 -class Reaction(object):
39 """Abstraction for a biochemical transformation. 40 41 This class represents a (potentially reversible) biochemical 42 transformation of the type: 43 44 a S1 + b S2 + ... --> c P1 + d P2 + ... 45 46 where 47 - a, b, c, d ... are positive numeric stochiometric coefficients, 48 - S1, S2, ... are substrates 49 - P1, P2, ... are products 50 51 A Reaction should be viewed as the net result of one or more individual 52 reaction steps, where each step is potentially facilitated by a different 53 catalyst. Support for 'Reaction algebra' will be added at some point in 54 the future. 55 56 Attributes: 57 58 reactants -- map of involved species to their stochiometric coefficients: 59 reactants[S] = stochiometric constant for S 60 catalysts -- list of tuples of catalysts required for this reaction 61 reversible -- true iff reaction is reversible 62 data -- reference to arbitrary additional data 63 64 Invariants: 65 66 for all S in reactants: reactants[S] != 0 67 for all C in catalysts: catalysts[C] != 0 68 69 """ 70
71 - def __init__(self, reactants = {}, catalysts = [], 72 reversible = 0, data = None):
73 """Initializes a new Reaction object.""" 74 # enforce invariants on reactants: 75 self.reactants = reactants.copy() 76 # loop over original, edit the copy 77 for r, value in reactants.items(): 78 if value == 0: 79 del self.reactants[r] 80 self.catalysts = sorted(set(catalysts)) 81 self.data = data 82 self.reversible = reversible
83
84 - def __eq__(self, r):
85 """Returns true iff self is equal to r.""" 86 return isinstance(r, Reaction) and \ 87 self.reactants == r.reactants and \ 88 self.catalysts == r.catalysts and \ 89 self.data == r.data and \ 90 self.reversible == r.reversible
91
92 - def __ne__(self, r):
93 """Returns true iff self is not equal to r.""" 94 return not self.__eq__(r)
95
96 - def __hash__(self):
97 """Returns a hashcode for self.""" 98 t = tuple(self.species()) 99 return hash(t)
100
101 - def __repr__(self):
102 """Returns a debugging string representation of self.""" 103 return "Reaction(" + \ 104 ",".join(map(repr, [self.reactants, 105 self.catalysts, 106 self.data, 107 self.reversible])) + ")"
108
109 - def __str__(self):
110 """Returns a string representation of self.""" 111 substrates = "" 112 products = "" 113 all_species = sorted(self.reactants) 114 for species in all_species: 115 stoch = self.reactants[species] 116 if stoch < 0: 117 # species is a substrate: 118 if substrates != "": 119 substrates = substrates + " + " 120 if stoch != -1: 121 substrates = substrates + str(abs(stoch)) + " " 122 substrates = substrates + str(species) 123 elif stoch > 0: 124 # species is a product: 125 if products != "": 126 products = products + " + " 127 if stoch != 1: 128 products = products + str(stoch) + " " 129 products = products + str(species) 130 else: 131 raise AttributeError("Invalid 0 coefficient in Reaction.reactants") 132 if self.reversible: 133 return substrates + " <=> " + products 134 else: 135 return substrates + " --> " + products
136
137 - def reverse(self):
138 """Returns a new Reaction that is the reverse of self.""" 139 reactants = {} 140 for r in self.reactants: 141 reactants[r] = - self.reactants[r] 142 return Reaction(reactants, self.catalysts, 143 self.reversible, self.data)
144
145 - def species(self):
146 """Returns a list of all Species involved in self.""" 147 return list(self.reactants.keys())
148 149
150 -class System(object):
151 """Abstraction for a collection of reactions. 152 153 This class is used in the Bio.Pathway framework to represent an arbitrary 154 collection of reactions without explicitly defined links. 155 156 Attributes: 157 158 None 159 """ 160
161 - def __init__(self, reactions = []):
162 """Initializes a new System object.""" 163 self.__reactions = set(reactions)
164
165 - def __repr__(self):
166 """Returns a debugging string representation of self.""" 167 return "System(" + ",".join(map(repr, self.__reactions)) + ")"
168
169 - def __str__(self):
170 """Returns a string representation of self.""" 171 return "System of " + str(len(self.__reactions)) + \ 172 " reactions involving " + str(len(self.species())) + \ 173 " species"
174
175 - def add_reaction(self, reaction):
176 """Adds reaction to self.""" 177 self.__reactions.add(reaction)
178
179 - def remove_reaction(self, reaction):
180 """Removes reaction from self.""" 181 self.__reactions.remove(reaction)
182
183 - def reactions(self):
184 """Returns a list of the reactions in this system. 185 186 Note the order is arbitrary! 187 """ 188 #TODO - Define __lt__ so that Reactions can be sorted on Python? 189 return list(self.__reactions)
190
191 - def species(self):
192 """Returns a list of the species in this system.""" 193 return sorted(set(reduce(lambda s, x: s + x, 194 [x.species() for x in self.reactions()], [])))
195
196 - def stochiometry(self):
197 """Computes the stoichiometry matrix for self. 198 199 Returns (species, reactions, stoch) where 200 201 species = ordered list of species in this system 202 reactions = ordered list of reactions in this system 203 stoch = 2D array where stoch[i][j] is coef of the 204 jth species in the ith reaction, as defined 205 by species and reactions above 206 """ 207 # Note: This an inefficient and ugly temporary implementation. 208 # To be practical, stochiometric matrices should probably 209 # be implemented by sparse matrices, which would require 210 # NumPy dependencies. 211 # 212 # PS: We should implement automatic checking for NumPy here. 213 species = self.species() 214 reactions = self.reactions() 215 stoch = [] * len(reactions) 216 for i in range(len(reactions)): 217 stoch[i] = 0 * len(species) 218 for s in reactions[i].species(): 219 stoch[species.index(s)] = reactions[i].reactants[s] 220 return (species, reactions, stoch)
221 222
223 -class Interaction(object):
224 """An arbitrary interaction between any number of species. 225 226 This class definition is intended solely as a minimal wrapper interface that should 227 be implemented and extended by more specific abstractions. 228 229 Attributes: 230 231 data -- reference to arbitrary additional data 232 """ 233
234 - def __init_(self, data):
235 self.data = data
236
237 - def __hash__(self):
238 """Returns a hashcode for self.""" 239 return hash(self.data)
240
241 - def __repr__(self):
242 """Returns a debugging string representation of self.""" 243 return "Interaction(" + repr(self.data) + ")"
244
245 - def __str__(self):
246 """Returns a string representation of self.""" 247 return "<" + str(self.data) + ">"
248 249
250 -class Network(object):
251 """A set of species that are explicitly linked by interactions. 252 253 The network is a directed multigraph with labeled edges. The nodes in the graph 254 are the biochemical species involved. The edges represent an interaction between 255 two species, and the edge label is a reference to the associated Interaction 256 object. 257 258 Attributes: 259 260 None 261 """ 262
263 - def __init__(self, species = []):
264 """Initializes a new Network object.""" 265 self.__graph = MultiGraph(species)
266
267 - def __repr__(self):
268 """Returns a debugging string representation of this network.""" 269 return "<Network: __graph: " + repr(self.__graph) + ">"
270
271 - def __str__(self):
272 """Returns a string representation of this network.""" 273 return "Network of " + str(len(self.species())) + " species and " + \ 274 str(len(self.interactions())) + " interactions."
275
276 - def add_species(self, species):
277 """Adds species to this network.""" 278 self.__graph.add_node(species)
279
280 - def add_interaction(self, source, sink, interaction):
281 """Adds interaction to this network.""" 282 self.__graph.add_edge(source, sink, interaction)
283
284 - def source(self, species):
285 """Returns list of unique sources for species.""" 286 return self.__graph.parents(species)
287
288 - def source_interactions(self, species):
289 """Returns list of (source, interaction) pairs for species.""" 290 return self.__graph.parent_edges(species)
291
292 - def sink(self, species):
293 """Returns list of unique sinks for species.""" 294 return self.__graph.children(species)
295
296 - def sink_interactions(self, species):
297 """Returns list of (sink, interaction) pairs for species.""" 298 return self.__graph.child_edges(species)
299
300 - def species(self):
301 """Returns list of the species in this network.""" 302 return self.__graph.nodes()
303
304 - def interactions(self):
305 """Returns list of the unique interactions in this network.""" 306 return self.__graph.labels()
307