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