示例#1
0
def create_model(**initial_counts):
    """
    create_model(**initial_counts) -> model
    
    Creates a model for the catalytic reaction example.
    
    If specified, the optional keyword arguments A (defaults to  50) and
    D (defaults to 80) define the initial copy counts of species A and D
    respectively.
    """

    initial_counts.setdefault('A', 50)
    initial_counts.setdefault('D', 80)
    s_1 = lambda *x: non_neg(initial_counts['A'] - x[0])
    s_2 = lambda *x: non_neg(x[0] - x[1])
    s_3 = lambda *x: x[1]
    s_4 = lambda *x: non_neg(initial_counts['D'] - x[2])
    s_5 = lambda *x: x[2]

    return cmepy.model.create(
        name='simple catalytic reaction',
        reactions=('A->B', 'B->C', 'B+D->B+E'),
        propensities=(lambda *x: 1.0 * s_1(*x), lambda *x: 1000.0 * s_2(*x),
                      lambda *x: 100.0 * s_4(*x) * s_2(*x)),
        transitions=((1, 0, 0), (0, 1, 0), (0, 0, 1)),
        species=('A', 'B', 'C', 'D', 'E'),
        species_counts=(s_1, s_2, s_3, s_4, s_5),
        shape=(initial_counts['A'] + 1, ) * 2 + (initial_counts['D'] + 1, ),
        initial_state=(0, ) * 3)
示例#2
0
def create_model(**initial_counts):
    """
    create_model(**initial_counts) -> model
    
    Creates a model for the catalytic reaction example.
    
    If specified, the optional keyword arguments A (defaults to  50) and
    D (defaults to 80) define the initial copy counts of species A and D
    respectively.
    """
    
    initial_counts.setdefault('A', 50)
    initial_counts.setdefault('D', 80)
    s_1 = lambda *x : non_neg(initial_counts['A']-x[0])
    s_2 = lambda *x : non_neg(x[0] - x[1])
    s_3 = lambda *x : x[1]
    s_4 = lambda *x : non_neg(initial_counts['D']-x[2])
    s_5 = lambda *x : x[2]
    
    return cmepy.model.create(
        name = 'simple catalytic reaction',
        reactions = (
            'A->B',
            'B->C',
            'B+D->B+E'
        ),
        propensities = (
            lambda *x : 1.0 * s_1(*x),
            lambda *x : 1000.0 * s_2(*x),
            lambda *x : 100.0 * s_4(*x) * s_2(*x)
        ),
        transitions = (
            (1, 0, 0),
            (0, 1, 0),
            (0, 0, 1)
        ),
        species = (
            'A',
            'B',
            'C',
            'D',
            'E'
        ),
        species_counts = (
            s_1,
            s_2,
            s_3,
            s_4,
            s_5
        ),
        shape = (initial_counts['A'] + 1, )*2 + (initial_counts['D'] + 1,),
        initial_state = (0, )*3
    )
示例#3
0
def main():
    """
    the complete example from the slides
    """
    
    import numpy
    from cmepy import solver, recorder, model
    from cmepy.util import non_neg

    s_0 = 50
    e_0 = 10

    s = lambda *x : x[0]
    e = lambda *x : non_neg(e_0 - x[1])
    c = lambda *x : x[1]
    p = lambda *x : non_neg(s_0 - x[0] - x[1])

    m = model.create(
        species_counts = (s, e, c, p, ),
        propensities = (
            lambda *x : 0.01*s(*x)*e(*x),
            lambda *x : 35.0*c(*x),
            lambda *x : 30.0*c(*x),
        ),
        transitions = (
            (-1, 1),
            (1, -1),
            (0, -1)
        ),
        shape = (s_0 + 1, min(s_0, e_0) + 1),
        initial_state = (s_0, 0)
    )

    enzyme_solver = solver.create(
        model = m,
        sink = False
    )

    time_steps = numpy.linspace(0.0, 10.0, 101)

    r = recorder.create(
        (['S', 'E', 'C', 'P'], m.species_counts)
    )

    for t in time_steps:
        enzyme_solver.step(t)
        r.write(t, enzyme_solver.y)   

    recorder.display_plots(r)
示例#4
0
def create_model_michaelis_menten(s_0=50, e_0=10):
    """
    Creates a model for a simple michaelis-menten enzymatic reaction system:
    
    E+S <-> C -> E + D
    
    The reaction propensities are
    
    E+S -> C : 0.01
    C -> E+S : 35.0
    C -> E+D : 30.0
    
    while the initial counts are s_0 copies of S, e_0 copies of E, 
    and zero copies of both C and D.
    """

    # first, define functions mapping states to species copy counts
    species_c = (
        lambda *x: x[0],
        lambda *x: non_neg(e_0 - x[1]),
        lambda *x: x[1],
        lambda *x: non_neg(s_0 - x[0] - x[1]),
    )
    # second, define reaction propensities via species counts
    props = (
        lambda *x: 0.01 * species_c[0](*x) * species_c[1](*x),
        lambda *x: 35.0 * species_c[2](*x),
        lambda *x: 30.0 * species_c[2](*x),
    )

    # construct the model
    return model.create(name='simple Michaelis-Menten system',
                        species=(
                            'S',
                            'E',
                            'C',
                            'D',
                        ),
                        species_counts=species_c,
                        reactions=(
                            'E+S->C',
                            'C->E+S',
                            'C->E+D',
                        ),
                        propensities=props,
                        transitions=((-1, 1), (1, -1), (0, -1)),
                        shape=(s_0 + 1, max(s_0, e_0) + 1),
                        initial_state=(s_0, 0))
示例#5
0
def create_model_michaelis_menten(s_0 = 50, e_0 = 10):
    """
    Creates a model for a simple michaelis-menten enzymatic reaction system:
    
    E+S <-> C -> E + D
    
    The reaction propensities are
    
    E+S -> C : 0.01
    C -> E+S : 35.0
    C -> E+D : 30.0
    
    while the initial counts are s_0 copies of S, e_0 copies of E, 
    and zero copies of both C and D.
    """
    
    # first, define functions mapping states to species copy counts
    species_c = (
        lambda *x : x[0],
        lambda *x : non_neg(e_0 - x[1]),
        lambda *x : x[1],
        lambda *x : non_neg(s_0 - x[0] - x[1]),
    )
    # second, define reaction propensities via species counts
    props = (
        lambda *x : 0.01*species_c[0](*x)*species_c[1](*x),
        lambda *x : 35.0*species_c[2](*x),
        lambda *x : 30.0*species_c[2](*x),
    )
    
    # construct the model
    return model.create(
        name = 'simple Michaelis-Menten system',
        species = ('S', 'E', 'C', 'D', ),
        species_counts = species_c,
        reactions = ('E+S->C', 'C->E+S', 'C->E+D', ),
        propensities = props,
        transitions = ((-1, 1), (1, -1), (0, -1)),
        shape = (s_0 + 1, max(s_0, e_0) + 1),
        initial_state = (s_0, 0)
    )
示例#6
0
def gen_states(**initial_counts):
    """
    gen_states(**initial_counts) -> first state, ..., last state
    
    Creates a generator over states in a *truncated* reaction count state
    space, for the catalytic reaction example.
    
    If specified, the optional keyword arguments A (defaults to  50) and
    D (defaults to 80) define the initial copy counts of species A and D
    respectively.
    
    Each state yielded by this generator has the form state = (r_1, r_2, r_3),
    where non-negative integers r_1, r_2 and r_3 denote the count of the
    reactions 1, 2 and 3, respectively.
    
    Only states satisfying the following inequality are considered:
    
        (r_1, r_2, r_3) such that r_1 -3 <= r_2 <= r_1
    
    The upper bound on r_2 follows from the model, as reaction 2 may occur at
    most once for each occurance of reaction 1. The lower bound on r_2 is an
    *artificial restriction that truncates the state space*. This introduces
    error, but because the rate constant of reaction 2 is 1000 times larger
    than the rate constant of reaction 1, the count of reaction 2 shall be
    close to the count of reaction 1 with high probability, and the
    resulting truncation error shall be small. This results in a truncated
    state space with roughly 4 * (A+1) * (D+1) states, compared to the
    0.5 * (A+1)**2 * (D+1) states required for the full state space.
    """
    
    initial_counts.setdefault('A', 50)
    initial_counts.setdefault('D', 80)
    for r_1 in xrange(initial_counts['A'] + 1):
        r_2_min = non_neg(r_1 - 3)
        r_2_max = r_1
        for r_2 in xrange(r_2_min, r_2_max + 1):
            for r_3 in xrange(initial_counts['D'] + 1):
                yield (r_1, r_2, r_3)
    return
def create_model(dna_count=2, rna_max=15, m_max=15, d_max=15):

    # define mappings from state space to species copy counts
    dna = lambda *x: x[0]
    dna_d = lambda *x: x[1]
    dna_2d = lambda *x: dna_count - x[0] - x[1]
    rna = lambda *x: x[2]
    m = lambda *x: x[3]
    d = lambda *x: x[4]

    # define reaction propensity constants
    k = (
        4.3e-2,
        7.0e-4,
        7.8e-2,
        3.9e-3,
        1.2e7,
        4.791e-1,
        1.2e5,
        8.765e-12,
        1.0e8,
        0.5,
    )

    return cmepy.model.create(
        name='Goutsias transcription regulation',
        species=(
            'DNA',
            'DNA-D',
            'DNA-2D',
            'RNA',
            'M',
            'D',
        ),
        species_counts=(
            dna,
            dna_d,
            dna_2d,
            rna,
            m,
            d,
        ),
        reactions=(
            'RNA -> RNA + M',
            'M -> *',
            'DNA-D -> RNA + DNA-D',
            'RNA -> *',
            'DNA + D -> DNA-D',
            'DNA-D -> DNA + D',
            'DNA-D + D -> DNA-2D',
            'DNA-2D -> DNA-D + D',
            'M + M -> D',
            'D -> M + M',
        ),
        propensities=(
            lambda *x: k[0] * rna(*x),
            lambda *x: k[1] * m(*x),
            lambda *x: k[2] * dna_d(*x),
            lambda *x: k[3] * rna(*x),
            lambda *x: k[4] * dna(*x) * d(*x),
            lambda *x: k[5] * dna_d(*x),
            lambda *x: k[6] * dna_d(*x) * d(*x),
            lambda *x: k[7] * dna_2d(*x),
            lambda *x: k[8] * 0.5 * m(*x) * non_neg(m(*x) - 1),
            lambda *x: k[9] * d(*x),
        ),
        transitions=(
            (0, 0, 0, 1, 0),
            (0, 0, 0, -1, 0),
            (0, 0, 1, 0, 0),
            (0, 0, 1, 0, 0),
            (-1, 1, 0, 0, -1),
            (1, -1, 0, 0, 1),
            (0, -1, 0, 0, -1),
            (0, 1, 0, 0, 1),
            (0, 0, 0, -2, 1),
            (0, 0, 0, 2, -1),
        ),
        shape=(dna_count + 1, ) * 2 + (rna_max + 1, m_max + 1, d_max + 1),
        initial_state=(dna_count, 0, 0, 2, 6))
示例#8
0
"""
some mono-molecular models
"""

from cmepy.util import non_neg
from cmepy import model

A2B2C = model.create(
    name = 'simplest nontrivial mono-molecular reaction',
    propensities = (
        lambda *x: non_neg(31.0-x[0]),
        lambda *x: non_neg(x[0]-x[1]),
    ),
    transitions = (
        (1, 0),
        (0, 1),
    ),
    reactions = (
        'A->B',
        'B->C',
    ),
    species_counts = (
        lambda *x: non_neg(31-x[0]),
        lambda *x: non_neg(x[0]-x[1]),
        lambda *x: x[1],
    ),
    species = (
        'A',
        'B',
        'C',
    ),
示例#9
0
def create_model(max_papi = 100,
                 papi_count = 5,
                 dna_count = 1,
                 lrp_count = 100):
    """
    creates pap-pili epigenetic switch model.
    """
    
    # define mappings from state space to species counts
    dna = lambda *x : x[0]
    dna_lrp = lambda *x : x[1]
    lrp_dna = lambda *x : x[2]
    lrp_dna_lrp = lambda *x : non_neg(dna_count - x[0] - x[1] - x[2])
    lrp = lambda *x :non_neg(
        lrp_count - 2*lrp_dna_lrp(*x) - dna_lrp(*x) - lrp_dna(*x)
    )
    papi = lambda *x : x[3]
    
    def f(r):
        return r / (1.0 + r)
    
    # define reaction propensities
    props = (
        lambda *x : 1.0 * dna(*x) * lrp(*x),
        lambda *x : (2.5 - 2.25*f(papi(*x))) * lrp_dna(*x),
        lambda *x : 1.0 * dna(*x) * lrp(*x),
        lambda *x : (1.2 - 0.20 * f(papi(*x))) * dna_lrp(*x),
        lambda *x : 0.01 * lrp_dna(*x) * lrp(*x),
        lambda *x : (1.2 - 0.20 * f(papi(*x))) * lrp_dna_lrp(*x),
        lambda *x : 0.01 * dna_lrp(*x) * lrp(*x),
        lambda *x : (2.5 - 2.25 * f(papi(*x))) * lrp_dna_lrp(*x),
        lambda *x : 10.0 * lrp_dna(*x),
        lambda *x : 1.0 * papi(*x),
    )
    # define corresponding reaction state space offsets
    transitions = (
        (-1, 0, 1, 0), # LRP + DNA -> LRP-DNA
        (1, 0, -1, 0), # LRP-DNA -> LRP + DNA
        (-1, 1, 0, 0), # DNA + LRP -> DNA-LRP
        (1, -1, 0, 0), # DNA-LRP -> DNA + LRP
        (0, 0, -1, 0), # LRP-DNA + LRP -> LRP-DNA-LRP
        (0, 0, 1, 0), # LRP-DNA-LRP -> LRP-DNA + LRP
        (0, -1, 0, 0), # LRP + DNA-LRP -> LRP-DNA-LRP
        (0, 1, 0, 0), # LRP-DNA-LRP -> LRP + DNA-LRP
        (0, 0, 0, 1), # * -> PapI
        (0, 0, 0, -1), # PapI -> *
    )
    
    species_names = (
        'DNA',
        'DNA-LRP',
        'LRP-DNA',
        'LRP-DNA-LRP',
        'LRP',
        'PapI',
    )
    species_counts = (
        dna,
        dna_lrp,
        lrp_dna,
        lrp_dna_lrp,
        lrp,
        papi,
    )
    
    return cmepy.model.create(
        name = 'pap-pili epigenetic switch',
        species = species_names,
        species_counts = species_counts,
        propensities = props,
        transitions = transitions,
        shape = (dna_count+1, )*3 + (max_papi+1, ),
        initial_state = (dna_count, 0, 0, papi_count)
    )
示例#10
0
def create_model(dna_count=2, rna_max=15, m_max=15, d_max=15):
    
    # define mappings from state space to species copy counts
    dna =  lambda *x : x[0]
    dna_d = lambda *x : x[1]
    dna_2d = lambda *x : dna_count - x[0] - x[1]
    rna = lambda *x : x[2]
    m = lambda *x : x[3]
    d = lambda *x : x[4]
    
    # define reaction propensity constants
    k = (
        4.3e-2,
        7.0e-4,
        7.8e-2,
        3.9e-3,
        1.2e7,
        4.791e-1,
        1.2e5,
        8.765e-12,
        1.0e8,
        0.5,
    )
    
    return cmepy.model.create(
        name = 'Goutsias transcription regulation',
        species = (
            'DNA',
            'DNA-D',
            'DNA-2D',
            'RNA',
            'M',
            'D',
        ),
        species_counts = (
            dna,
            dna_d,
            dna_2d,
            rna,
            m,
            d,
        ),
        reactions = (
            'RNA -> RNA + M',
            'M -> *',
            'DNA-D -> RNA + DNA-D',
            'RNA -> *',
            'DNA + D -> DNA-D',
            'DNA-D -> DNA + D',
            'DNA-D + D -> DNA-2D',
            'DNA-2D -> DNA-D + D',
            'M + M -> D',
            'D -> M + M',
        ),
        propensities = (
            lambda *x : k[0] * rna(*x),
            lambda *x : k[1] * m(*x),
            lambda *x : k[2] * dna_d(*x),
            lambda *x : k[3] * rna(*x), 
            lambda *x : k[4] * dna(*x) * d(*x), 
            lambda *x : k[5] * dna_d(*x), 
            lambda *x : k[6] * dna_d(*x) * d(*x), 
            lambda *x : k[7] * dna_2d(*x), 
            lambda *x : k[8] * 0.5 * m(*x) * non_neg(m(*x) - 1), 
            lambda *x : k[9] * d(*x),
        ),
        transitions = (
            (0, 0, 0, 1, 0),
            (0, 0, 0, -1, 0),
            (0, 0, 1, 0, 0),
            (0, 0, 1, 0, 0),
            (-1, 1, 0, 0, -1),
            (1, -1, 0, 0, 1),
            (0, -1, 0, 0, -1),
            (0, 1, 0, 0, 1),
            (0, 0, 0, -2, 1),
            (0, 0, 0, 2, -1),
        ),
        shape = (dna_count+1, )*2 + (rna_max+1, m_max+1, d_max+1),
        initial_state = (dna_count, 0, 0, 2, 6)
    )
示例#11
0
from cmepy import model
from cmepy.util import non_neg

s_0 = 50
e_0 = 10

# species count function definitions
s = lambda *x : x[0]
e = lambda *x : non_neg(e_0 - x[1])
c = lambda *x : x[1]
p = lambda *x : non_neg(s_0 - x[0] - x[1])

# model definition, in terms of species count functions
m = model.create(
    name = 'enzyme kinetics',
    species = ('S', 'E', 'C', 'P', ),
    species_counts = (s, e, c, p, ),
    reactions = ('E+S->C', 'C->E+S', 'C->E+P', ),
    propensities = (
        lambda *x : 0.01*s(*x)*e(*x),
        lambda *x : 35.0*c(*x),
        lambda *x : 30.0*c(*x),
    ),
    transitions = (
        (-1, 1),
        (1, -1),
        (0, -1)
    ),
    shape = (s_0 + 1, min(s_0, e_0) + 1),
    initial_state = (s_0, 0)
)
示例#12
0
from cmepy import model
from cmepy.util import non_neg

s_0 = 50
e_0 = 10

# species count function definitions
s = lambda *x: x[0]
e = lambda *x: non_neg(e_0 - x[1])
c = lambda *x: x[1]
p = lambda *x: non_neg(s_0 - x[0] - x[1])

# model definition, in terms of species count functions
m = model.create(name='enzyme kinetics',
                 species=(
                     'S',
                     'E',
                     'C',
                     'P',
                 ),
                 species_counts=(
                     s,
                     e,
                     c,
                     p,
                 ),
                 reactions=(
                     'E+S->C',
                     'C->E+S',
                     'C->E+P',
                 ),
示例#13
0
文件: gou07.py 项目: fcostin/cmepy
def create_model_quad_autocat(max_p=30,
                              max_q=30,
                              fixed_s=True,
                              s_0=10,
                              d_0=2,
                              vol=1.0):
    """
    Creates a species-count based model for the system of reactions:
    
        S->P
        D+P->D+P+P
        P+P->P+Q
        P+Q->Q+Q
        P->*
        Q->*
    
    The copy counts of the species S and D are assumed to be constant,
    with s_0 (default 10) copies of S and d_0 (default 2) copies of D.
    
    If fixed_s is set to False, copy count of species S will no longer be
    constant, and will be decreased by the reaction S->P.
    """
    
    model_name = 'Quadratic Autocatalator (%s S)'
    
    p = lambda *x : x[0]
    q = lambda *x : x[1]
    d = lambda *x : d_0
    
    if fixed_s:
        s = lambda *x : s_0
        model_name %= 'fixed'
        
        transitions = (
            (1, 0),
            (1, 0),
            (-1, 1),
            (-1, 1),
            (-1, 0),
            (0, -1),
        )
        
        shape = (max_p+1, max_q+1)
        initial_state = (0, )*2
    else:
        model_name %= 'variable'
        s = lambda *x : x[2]
        transitions = (
            (1, 0, -1),
            (1, 0, 0),
            (-1, 1, 0),
            (-1, 1, 0),
            (-1, 0, 0),
            (0, -1, 0),
        )
        
        shape = (max_p+1, max_q+1, s_0+1)
        initial_state = (0, 0, 3, )
    
    m = model.create(
        name = model_name,
        reactions = (
            'S->P',
            'D+P->D+2P',
            'P+P->P+Q',
            'P+Q->2Q',
            'P->*',
            'Q->*',
        ),
        propensities = (
            lambda *x : 0.002 * (vol ** -1) * s(*x),
            lambda *x : 0.001 * (vol ** -2) * d(*x) * p(*x),
            lambda *x : 0.005 * (vol ** -2) * p(*x) * non_neg(p(*x) - 1) / 2.0,
            lambda *x : 0.004 * (vol ** -2) * p(*x) * q(*x),
            lambda *x : 0.002 * (vol ** -1) * p(*x),
            lambda *x : 0.050 * (vol ** -1) * q(*x),
        ),
        transitions = transitions,
        species = ('P', 'Q', 'S', 'D',
        ),
        species_counts = ( p, q, s, d, ),
        shape = shape,
        initial_state = initial_state
    )
    return m
示例#14
0
def create_model_quad_autocat(max_p=30,
                              max_q=30,
                              fixed_s=True,
                              s_0=10,
                              d_0=2,
                              vol=1.0):
    """
    Creates a species-count based model for the system of reactions:
    
        S->P
        D+P->D+P+P
        P+P->P+Q
        P+Q->Q+Q
        P->*
        Q->*
    
    The copy counts of the species S and D are assumed to be constant,
    with s_0 (default 10) copies of S and d_0 (default 2) copies of D.
    
    If fixed_s is set to False, copy count of species S will no longer be
    constant, and will be decreased by the reaction S->P.
    """

    model_name = 'Quadratic Autocatalator (%s S)'

    p = lambda *x: x[0]
    q = lambda *x: x[1]
    d = lambda *x: d_0

    if fixed_s:
        s = lambda *x: s_0
        model_name %= 'fixed'

        transitions = (
            (1, 0),
            (1, 0),
            (-1, 1),
            (-1, 1),
            (-1, 0),
            (0, -1),
        )

        shape = (max_p + 1, max_q + 1)
        initial_state = (0, ) * 2
    else:
        model_name %= 'variable'
        s = lambda *x: x[2]
        transitions = (
            (1, 0, -1),
            (1, 0, 0),
            (-1, 1, 0),
            (-1, 1, 0),
            (-1, 0, 0),
            (0, -1, 0),
        )

        shape = (max_p + 1, max_q + 1, s_0 + 1)
        initial_state = (
            0,
            0,
            3,
        )

    m = model.create(name=model_name,
                     reactions=(
                         'S->P',
                         'D+P->D+2P',
                         'P+P->P+Q',
                         'P+Q->2Q',
                         'P->*',
                         'Q->*',
                     ),
                     propensities=(
                         lambda *x: 0.002 * (vol**-1) * s(*x),
                         lambda *x: 0.001 * (vol**-2) * d(*x) * p(*x),
                         lambda *x: 0.005 *
                         (vol**-2) * p(*x) * non_neg(p(*x) - 1) / 2.0,
                         lambda *x: 0.004 * (vol**-2) * p(*x) * q(*x),
                         lambda *x: 0.002 * (vol**-1) * p(*x),
                         lambda *x: 0.050 * (vol**-1) * q(*x),
                     ),
                     transitions=transitions,
                     species=(
                         'P',
                         'Q',
                         'S',
                         'D',
                     ),
                     species_counts=(
                         p,
                         q,
                         s,
                         d,
                     ),
                     shape=shape,
                     initial_state=initial_state)
    return m
示例#15
0
def main():
    
    import numpy
    from cmepy import solver, recorder, model
    from cmepy.util import non_neg

    s_0 = 50
    e_0 = 10

    s = lambda *x : x[0]
    e = lambda *x : non_neg(e_0 - x[1])
    c = lambda *x : x[1]
    p = lambda *x : non_neg(s_0 - x[0] - x[1])

    m = model.create(
        species_counts = (s, e, c, p, ),
        propensities = (
            lambda *x : 0.01*s(*x)*e(*x),
            lambda *x : 35.0*c(*x),
            lambda *x : 30.0*c(*x),
        ),
        transitions = (
            (-1, 1),
            (1, -1),
            (0, -1)
        ),
        shape = (s_0 + 1, min(s_0, e_0) + 1),
        initial_state = (s_0, 0)
    )

    enzyme_solver = solver.create(
        model = m,
        sink = False
    )

    time_steps = numpy.linspace(0.0, 30.0, 101)
    
    species = ['S', 'E', 'C', 'P']
    
    r = recorder.create(
        (species, m.species_counts)
    )

    for t in time_steps:
        enzyme_solver.step(t)
        r.write(t, enzyme_solver.y)

    import pylab
    
    species_colours = {
        'S' : 'r',
        'E' : 'k',
        'C' : 'g',
        'P' : 'b',
    }
    
    pylab.figure()
    for var in species:
        colour = species_colours[var]
        measurement = r[var]
        mu = numpy.reshape(numpy.array(measurement.expected_value), (-1, ))
        sigma = numpy.array(measurement.standard_deviation)
        
        mu_style = '-'+colour
        mu_pm_sigma_style = '--'+colour
        pylab.plot(measurement.times, mu, mu_style, label = var)
        pylab.plot(measurement.times, mu + sigma, mu_pm_sigma_style)
        pylab.plot(measurement.times, mu - sigma, mu_pm_sigma_style)
    
    title_lines = (
        'Enzymatic Reaction Species Counts:',
        'expected values $\pm$ 1 standard deviation',
    )
    pylab.title('\n'.join(title_lines))
    pylab.xlabel('time')
    pylab.ylabel('species count')
    pylab.legend()
    pylab.show()