A Python package for generating models of enzymes under the quasi-steady-state assumption (QSSA).
Currently tested with only Python 3.4.
Requires sympy.
pip install git+git://github.com/robjstan/python-enzymegraph.git
Gunawardena, J.
A linear framework for time-scale separation in nonlinear biochemical systems.
PLoS ONE (2012)
Gabow, H. N. & Myers, E. W.
Finding all spanning trees of directed and undirected graphs.
SIAM Journal on Computing (1978)
Biochemical example is the Michaelis-Menten function with product inhibition. $$E + S \underset{k_2}{\overset{k_1}{\rightleftharpoons}} ES \overset{k_\text{cat}}{\rightleftharpoons} EP \underset{k_4}{\overset{k_3}{\rightleftharpoons}} E + P$$
In [1]:
from enzymegraph import *
In [2]:
from sympy import *
from numpy import linspace
from scipy.integrate import odeint
import matplotlib.pyplot as plt
%matplotlib inline
In [3]:
e, s, p, es, ep = symbols('e s p es ep', positive = True)
Then we need to describe the edges between these species/complexes, labelled with their rates, including the uptake of substrate and product.
In [4]:
k1, k2, k3, k4, kcat = symbols('k_1 k_2 k_3, k_4 k_cat', positive = True)
edges = {(e, es): k1*s, (es, e): k2,
(e, ep): k3*p, (ep, e): k4,
(es,ep): kcat, }
In [5]:
graph = enzymegraph(edges)
graph
Out[5]:
In [6]:
edges = list(edges.keys())
enzymegraph(edges)
Out[6]:
In [7]:
m = [[ 0,k1*s, k3*p],
[k2, 0, kcat],
[k4, 0, 0]]
v = [e, es, ep]
enzymegraph.from_matrix(m, v).edges
Out[7]:
In [8]:
for var, ode in graph.ode_model().items():
print("d%s/dt = %s" % (var, ode))
The method enzymegraph.ode_function() returns the equivalent mass-action (ODE) model of the system as a python function (suitable for simulation using scipy.odeint(...).
This requires three extra parameters to be given:
In [9]:
param_dict = {k1:1, k2:0.1, k3:2, k4:0.5, kcat:1}
variables = [e, s, p, es, ep]
extra_odes = {s: k2*es - k1*e*s, p: k4*ep - k3*e*p}
ode_func = graph.ode_function(param_dict, variables, extra_odes)
ode_func
Out[9]:
In [10]:
concs = zip(*odeint(ode_func, [1,1,0,0,0], linspace(0,10,100)))
for conc, var in zip(concs, variables):
plt.plot(conc, label=var)
plt.xlabel("time")
plt.ylabel("concentration")
plt.legend()
plt.show()
In [11]:
for span_tree in graph.spanning_trees():
print(span_tree.edges)
The method enzymegraph.graph_as_tikz(...) outputs the graph as TikZ commands, suitable for inclusion in a LaTeX document.
This requires extra parameters to be given:
In [12]:
vertex_pos = {e: "(0,0)",
es: "(240:2)",
ep: "(300:2)",}
edge_styles = {(e, es): "to[out=210,in=90]",
(e, ep): "to[out=330,in=90]",}
print(graph.graph_as_tikz(vertex_pos, edge_styles, relabel=False))
In [13]:
print(graph.spanning_trees_as_tikz(vertex_pos, edge_styles, relabel=False))
In [14]:
for var, basis_elem in graph.basis_element().items():
print("%s = %s" % (var, basis_elem))
In [15]:
et = symbols('e_t', positive = True)
qssa_reps = graph.qssa_replacements(et)
for var, rep in qssa_reps.items():
print("%s = %s" % (var, rep))
These replacements can be used to substitute into the original ODE system.
e.g. $ \frac{dp}{dt} = k_4 ep - k_3 p e $
In [16]:
dpdt = k4*ep - k3*p*e
print("dp/dt = %s" % dpdt.subs(qssa_reps))
In [16]: