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