aakash0017's picture
Upload folder using huggingface_hub
b7731cd
# Copyright 2001 by Tarjei Mikkelsen. All rights reserved.
#
# This file is part of the Biopython distribution and governed by your
# choice of the "Biopython License Agreement" or the "BSD 3-Clause License".
# Please see the LICENSE file that should have been included as part of this
# package.
"""BioPython Pathway module.
Bio.Pathway is a lightweight class library designed to support the following tasks:
- Data interchange and preprocessing between pathway databases and analysis software.
- Quick prototyping of pathway analysis algorithms
The basic object in the Bio.Pathway model is Interaction, which represents an arbitrary
interaction between any number of biochemical species.
Network objects are used to represent the connectivity between species in pathways
and reaction networks.
For applications where it is not necessary to explicitly represent network connectivity,
the specialized classes Reaction and System should be used in place of Interacton and
Network.
The Bio.Pathway classes, especially Interaction, are intentionally
designed to be very flexible. Their intended use are as wrappers around database
specific records, such as BIND objects. The value-added in this module is a
framework for representing collections of reactions in a way that supports
graph theoretic and numeric analysis.
Note: This module should be regarded as a prototype only. API changes are likely.
Comments and feature requests are most welcome.
"""
from functools import reduce
from Bio.Pathway.Rep.MultiGraph import MultiGraph
class Reaction:
"""Abstraction for a biochemical transformation.
This class represents a (potentially reversible) biochemical
transformation of the type::
a S1 + b S2 + ... --> c P1 + d P2 + ...
where:
- a, b, c, d ... are positive numeric stochiometric coefficients,
- S1, S2, ... are substrates
- P1, P2, ... are products
A Reaction should be viewed as the net result of one or more individual
reaction steps, where each step is potentially facilitated by a different
catalyst. Support for 'Reaction algebra' will be added at some point in
the future.
Attributes:
- reactants -- dict of involved species to their stochiometric coefficients:
reactants[S] = stochiometric constant for S
- catalysts -- list/tuple of tuples of catalysts required for this reaction
- reversible -- true iff reaction is reversible
- data -- reference to arbitrary additional data
Invariants:
- for all S in reactants: reactants[S] != 0
- for all C in catalysts: catalysts[C] != 0
"""
def __init__(self, reactants=None, catalysts=(), reversible=0, data=None):
"""Initialize a new Reaction object."""
# enforce invariants on reactants:
if reactants is None:
self.reactants = {}
else:
self.reactants = reactants.copy()
# loop over original, edit the copy
for r, value in reactants.items():
if value == 0:
del self.reactants[r]
self.catalysts = sorted(set(catalysts))
self.data = data
self.reversible = reversible
def __eq__(self, r):
"""Return true iff self is equal to r."""
return (
isinstance(r, Reaction)
and self.reactants == r.reactants
and self.catalysts == r.catalysts
and self.data == r.data
and self.reversible == r.reversible
)
def __hash__(self):
"""Return a hashcode for self."""
t = tuple(self.species())
return hash(t)
def __repr__(self):
"""Return a debugging string representation of self."""
return "Reaction(%r, %r, %r, %r)" % (
self.reactants,
self.catalysts,
self.reversible,
self.data,
)
def __str__(self):
"""Return a string representation of self."""
substrates = ""
products = ""
all_species = sorted(self.reactants)
for species in all_species:
stoch = self.reactants[species]
if stoch < 0:
# species is a substrate:
if substrates != "":
substrates = substrates + " + "
if stoch != -1:
substrates = substrates + str(abs(stoch)) + " "
substrates = substrates + str(species)
elif stoch > 0:
# species is a product:
if products != "":
products = products + " + "
if stoch != 1:
products = products + str(stoch) + " "
products = products + str(species)
else:
raise AttributeError("Invalid 0 coefficient in Reaction.reactants")
if self.reversible:
return substrates + " <=> " + products
else:
return substrates + " --> " + products
def reverse(self):
"""Return a new Reaction that is the reverse of self."""
reactants = {}
for r in self.reactants:
reactants[r] = -self.reactants[r]
return Reaction(reactants, self.catalysts, self.reversible, self.data)
def species(self):
"""Return a list of all Species involved in self."""
return list(self.reactants)
class System:
"""Abstraction for a collection of reactions.
This class is used in the Bio.Pathway framework to represent an arbitrary
collection of reactions without explicitly defined links.
Attributes:
- None
"""
def __init__(self, reactions=()):
"""Initialize a new System object."""
self.__reactions = set(reactions)
def __repr__(self):
"""Return a debugging string representation of self."""
return "System(" + ",".join(map(repr, self.__reactions)) + ")"
def __str__(self):
"""Return a string representation of self."""
return (
"System of "
+ str(len(self.__reactions))
+ " reactions involving "
+ str(len(self.species()))
+ " species"
)
def add_reaction(self, reaction):
"""Add reaction to self."""
self.__reactions.add(reaction)
def remove_reaction(self, reaction):
"""Remove reaction from self."""
self.__reactions.remove(reaction)
def reactions(self):
"""Return a list of the reactions in this system.
Note the order is arbitrary!
"""
# TODO - Define __lt__ so that Reactions can be sorted on Python?
return list(self.__reactions)
def species(self):
"""Return a list of the species in this system."""
return sorted(
set(reduce(lambda s, x: s + x, [x.species() for x in self.reactions()], []))
)
def stochiometry(self):
"""Compute the stoichiometry matrix for self.
Returns (species, reactions, stoch) where:
- species = ordered list of species in this system
- reactions = ordered list of reactions in this system
- stoch = 2D array where stoch[i][j] is coef of the
jth species in the ith reaction, as defined
by species and reactions above
"""
# Note: This an inefficient and ugly temporary implementation.
# To be practical, stochiometric matrices should probably
# be implemented by sparse matrices, which would require
# NumPy dependencies.
#
# PS: We should implement automatic checking for NumPy here.
species = self.species()
reactions = self.reactions()
stoch = [] * len(reactions)
for i in range(len(reactions)):
stoch[i] = 0 * len(species)
for s in reactions[i].species():
stoch[species.index(s)] = reactions[i].reactants[s]
return (species, reactions, stoch)
class Interaction:
"""An arbitrary interaction between any number of species.
This class definition is intended solely as a minimal wrapper interface that should
be implemented and extended by more specific abstractions.
Attributes:
- data -- reference to arbitrary additional data
"""
def __init_(self, data):
self.data = data
def __hash__(self):
"""Return a hashcode for self."""
return hash(self.data)
def __repr__(self):
"""Return a debugging string representation of self."""
return "Interaction(" + repr(self.data) + ")"
def __str__(self):
"""Return a string representation of self."""
return "<" + str(self.data) + ">"
class Network:
"""A set of species that are explicitly linked by interactions.
The network is a directed multigraph with labeled edges. The nodes in the graph
are the biochemical species involved. The edges represent an interaction between
two species, and the edge label is a reference to the associated Interaction
object.
Attributes:
- None
"""
def __init__(self, species=()):
"""Initialize a new Network object."""
self.__graph = MultiGraph(species)
def __repr__(self):
"""Return a debugging string representation of this network."""
return "<Network: __graph: " + repr(self.__graph) + ">"
def __str__(self):
"""Return a string representation of this network."""
return "Network of %i species and %i interactions." % (
len(self.species()),
len(self.interactions()),
)
def add_species(self, species):
"""Add species to this network."""
self.__graph.add_node(species)
def add_interaction(self, source, sink, interaction):
"""Add interaction to this network."""
self.__graph.add_edge(source, sink, interaction)
def source(self, species):
"""Return list of unique sources for species."""
return self.__graph.parents(species)
def source_interactions(self, species):
"""Return list of (source, interaction) pairs for species."""
return self.__graph.parent_edges(species)
def sink(self, species):
"""Return list of unique sinks for species."""
return self.__graph.children(species)
def sink_interactions(self, species):
"""Return list of (sink, interaction) pairs for species."""
return self.__graph.child_edges(species)
def species(self):
"""Return list of the species in this network."""
return self.__graph.nodes()
def interactions(self):
"""Return list of the unique interactions in this network."""
return self.__graph.labels()