def __init__(self, gb):
        self.gb = gb

        # -- flow -- #
        self.discr_flow = Flow(gb)

        shape = self.discr_flow.shape()
        self.flux_pressure = np.zeros(shape)

        # -- temperature -- #
        self.discr_temperature = Heat(gb)

        # -- solute and precipitate -- #
        self.discr_solute_advection_diffusion = Transport(gb)
        self.discr_solute_precipitate_reaction = Reaction(gb)

        # -- porosity -- #
        self.discr_porosity = Porosity(gb)

        # -- fracture aperture -- #
        self.discr_fracture_aperture = FractureAperture(
            gb, "fracture_aperture")

        # -- layer porosity and aperture -- #
        self.discr_layer_porosity = Porosity(gb, "layer_porosity")
        self.discr_layer_aperture = LayerAperture(gb, "layer_aperture")

        # the actual time of the simulation
        self.time = 0
Exemple #2
0
    def __construct_reaction(self, rname, ko, reac, arrow, prod, mname):
        """ Code to parse and construct a reaction"""
        # Step 1. split reactants.
        rname = str(rname)
        mname = str(mname)

        r = Reaction(rname)
        left_coef, left_comp = self.__get_coef_and_name(reac)
        right_coef, right_comp = self.__get_coef_and_name(prod)

        r.substrates.extend(left_comp)
        r.products.extend(right_comp)
        print "[Add pathway] The substrates are ", r.substrates
        print "[Add pathway] The products are ", r.products

        for i in xrange(len(left_coef)):
            r.stoichiometry[left_comp[i]] = left_coef[i]

        for i in xrange(len(right_coef)):
            r.stoichiometry[right_comp[i]] = right_coef[i]
        print "[Add pathway] r.stoichiometry is ", r.stoichiometry
        print "Get external arrow is ", arrow
        r.reversible = arrow
        r.arrow = arrow
        if ko == "false":
            r.ko = False
        else:
            r.ko = True
        r.metabolism = mname
        r.active = True
        return r
 def test_not_a_raf(self):
     g = ReactionGraph()
     rs = [Reaction((_('K'),_('I')), 'reduce', (_('IK'),)),
             Reaction((_('KIK'),_('K')), 'reduce', (_('KIKK'),)),
             Reaction((_('KIKK'),), 'reduce', (_('KKKKK'),))
             ]
     for r in rs:
         g.add_reaction(r)
     raf = g.get_raf([_('I'), _('K'), _('S')])
     self.assertEqual(len(raf), 0)
 def test_raf_chain(self):
     g = ReactionGraph()
     rs = [Reaction((_('K'),), 'reduce', (_('S'),)),
             Reaction((_('S'),_('X')), 'reduce', (_('K'),))]
     for r in rs:
         g.add_reaction(r)
     raf = g.get_raf([_('X')])
     self.assertEqual(len(raf), 2)
     for r in rs:
         self.assertTrue(r in raf)
 def __construct_reaction(self, rname, ko, reac, arrow, prod, mname):
     """ Code to parse and construct a reaction"""
     # Step 1. split reactants.
     rname = str(rname)
     mname = str(mname)
      
     r = Reaction(rname)
     left_coef,  left_comp = self.__get_coef_and_name(reac)
     right_coef, right_comp = self.__get_coef_and_name(prod)
     
     r.substrates.extend(left_comp)
     r.products.extend(right_comp)
     print "[Add pathway] The substrates are ", r.substrates
     print "[Add pathway] The products are ", r.products
     
     for i in xrange(len(left_coef)):
         r.stoichiometry[left_comp[i]] = left_coef[i]
     
     for i in xrange(len(right_coef)):
         r.stoichiometry[right_comp[i]] = right_coef[i]
     print "[Add pathway] r.stoichiometry is ", r.stoichiometry
     print "Get external arrow is ", arrow
     r.reversible = arrow
     r.arrow = arrow
     if ko == "false":
         r.ko = False
     else:
         r.ko = True
     r.metabolism = mname
     r.active = True
     return r
Exemple #6
0
async def on_message(message):

    if str(message.author.id) != '759317087192612864':
        reaction = Reaction(message.author.id, message.content)

        if reaction.contains_flags():
            send_message = reaction.get_flag_response()

            if len(send_message) > 0:
                await client.get_channel(message.channel.id).send(send_message)
        else:
            for emoji in reaction.get_reactions():
                await message.add_reaction(emoji)
Exemple #7
0
            def reset(self):
                oh = Molecule(atom_string='oh', S=0.0, D=0.)  # pH proxy
                x = Molecule(atom_string='x', S=1.0, D=0.01)  # amphiphile
                xx = Molecule(atom_string='xx', S=0.0, D=0.99)  # precursor

                self.subsets = {'env': [oh, xx]}

                self.define_molecules([x, xx, oh])
                self.change_conc_for_all_testtubes(xx, 1E0)
                self.add_reaction(Reaction([xx, oh], [x, x], 0.05, 0.0))
                self.add_reaction(Reaction([x], [], 0.1, 0.0))

                self.generate_ode_fn()
                self.graph()
Exemple #8
0
            def reset(self):
                self.subsets = {'env': [h, p, q]}

                self.define_molecules([a, p, h, q, m])
                self.change_conc_for_all_testtubes(a, 0.0 * 1E-4)
                self.change_conc_for_all_testtubes(p, 1.0E-4)
                self.change_conc_for_all_testtubes(m, 1.0E-3)
                #self.add_reaction(Reaction([p],[a,a],10000.0,0.0))
                self.add_reaction(Reaction([p, h], [a, a], 10000.0, 0.0))
                # self.add_reaction(Reaction([x,a],[],100.0*10000.0,0.0))
                # self.add_reaction(Reaction([x,p],[],100.0*10000.0,0.0))
                self.add_reaction(Reaction([q, m], [p, p], 10000.0, 0.0))
                #self.add_reaction(Reaction([a],[],100.0,0.0))

                self.generate_ode_fn()
 def test_raf_chain_out(self):
     g = ReactionGraph()
     raf_rs = [Reaction((_('K'),), 'reduce', (_('S'),)),
             Reaction((_('S'),_('X')), 'reduce', (_('K'),)),
             ]
     out_rs = [
             Reaction((_('I'),), 'reduce', (_('KK'),)),
             ]
     rs = raf_rs + out_rs
     for r in rs:
         g.add_reaction(r)
     raf = g.get_raf([_('X')])
     self.assertEqual(len(raf), len(raf_rs))
     for r in raf_rs:
         self.assertTrue(r in raf)
Exemple #10
0
def MakeReaction(_name, _r, _i, _p):
    # pass the entities through lists data structure
    if type(_r) is not list or type(_i) is not list or type(_p) is not list:
        print(f'Please provide the sets as lists data type structure!')
        return None
    # NO ONE of the sets can be empty
    if (len(_r) == 0 or len(_i) == 0 or len(_p) == 0):
        print(
            f'The reaction_{_name} cannot be created: some of the provided sets is empty'
        )
        return None
    # construct the sets, being sure that each element is viewed as a string (if I would have converted directly
    # in this way: e.g. set([a,1]) the element 1 was been an int instead of a string '1')
    name = str(_name).lower()
    reactants = set()
    inhibitors = set()
    products = set()
    for r in _r:
        reactants.add(str(r).lower())
    for i in _i:
        inhibitors.add(str(i).lower())
    for p in _p:
        products.add(str(p).lower())
    # intersection between reactants and inhibitors must be empty
    if (not reactants.isdisjoint(inhibitors)
        ):  # true if the intersection IS NOT empty
        print(
            f'The reaction_{name} cannot be created: intersection between reactants and inhibitors is not empty'
        )
        return None
    # create the reaction
    return Reaction(name, reactants, inhibitors, products)
Exemple #11
0
    def __init__(self, gb, models_trans, model_react, tol):

        self.gb = gb
        self.tol = tol

        # set up the transport models
        self.models_trans = np.atleast_1d(models_trans)
        self.discr_trans = {
            m: Transport(self.gb, m, self.tol)
            for m in self.models_trans
        }

        # set up the reaction models
        # we assume only one reaction model
        self.model_react = model_react
        self.discr_react = Reaction(self.tol)
 def test_scc(self):
     g = ReactionGraph()
     rs = [
             Reaction((_('SII(SII)'),), 'reduce', (_('I(SII)(SII)'),)),
             Reaction((_('SII(SII)'),), 'reduce', (_('SII(I(SII))'),)),
             Reaction((_('I(SII)(I(SII))'),), 'reduce', (_('SII(SII)'),)),
             Reaction((_('I(SII)(SII)'),), 'reduce', (_('I(SII)(I(SII))'),)),
             Reaction((_('SII(I(SII))'),), 'reduce', (_('I(SII)(I(SII))'),)),
     ]
     for r in rs:
         g.add_reaction(r)
     sccs = list(g.remove_selfloop().get_without_substrates_subgraph().get_all_strongly_connected_components())
     self.assertEqual(len(sccs), 1)
     for x in rs:
         self.assertTrue(x in set(sccs[0]))
     self.assertEqual(g.get_maximal_cycle_length(), 3)
    def get_reaction_object(self, row):
        """
        Takes a row and returns reaction object.
        """
        r_type = row['ReactionType'].lower()
        categories_dict = self.definitions.categories_dict
        reaction = self.get_preliminary_reaction(row)

        if r_type in categories_dict['Covalent Modification']:
            state = get_state(row, reaction, 'Covalent Modification')
            if r_type == 'pt': # if subtype == Trnas
                reaction.right_reactant.add_modification_site(state)
                reaction.left_reactant.add_modification(state)
            elif '-' in r_type or r_type in ['gap']:
                reaction.right_reactant.add_modification(state)
            else:
                reaction.right_reactant.add_modification_site(state)
            reaction.to_change = state

        elif r_type in categories_dict['Association']:
            # ipi is destinctive state: it is A_[a]--[b]
            # where both domains are in the same protein.
            if r_type == 'ipi':
                state = get_state(row, reaction, 'Intraprotein')
                reaction.left_reactant.add_binding_site(state)
                reaction.to_change = state
            else:
                state = get_state(row, reaction, 'Association')
                #if reaction.rtype == 'Association':
                #    print state
                reaction.left_reactant.add_binding_site(state)
                reaction.right_reactant.add_binding_site(state)
                reaction.to_change = state

        elif r_type in categories_dict['Synthesis/Degradation']:
            pass

        elif r_type in categories_dict['Relocalisation']:
            state = get_state(row, reaction, 'Relocalisation')
            reaction.to_change = state
            reaction.right_reactant.localisation = state
        else:
            reaction = Reaction()

        reaction.definition = self.definitions[r_type]
        return reaction
Exemple #14
0
 def tape_reduce(self, t):
     if t.is_reducible(self):
         reduced, reactives, biproducts = t.sreduce(self, self.max_sample_reductions)
         reaction = Reaction((reduced, *biproducts), 'reduce', 
                 (t, *reactives))
         return self.apply_reaction(reaction)
     else:
         return False
Exemple #15
0
def biomass_equation(biomass_type="standard"):
    """Get the biomass_equation equation for a specific type of biomass_equation equation.

    biomass_type can be one of:
        standard:       the standard biomass_equation equation we were using for the JSON models initially
        kbase:          the revised biomass_equation equation that was included in the kbase models
        kbase_simple:   a simplified version of the kbase biomass_equation equation
        gram_negative:  a Gram negative biomass_equation equation

    :param biomass_type: The type of biomass_equation equation to get
    :type biomass_type: str
    :return: The biomass_equation equation as a Reaction object
    :rtype: Reaction
    """

    if biomass_type == "standard":
        reactants, products = standard_eqn()
    elif biomass_type == "kbase":
        reactants, products = kbase()
    elif biomass_type == "kbase_simple":
        reactants, products = kbase_simple()
    elif biomass_type == "gram_negative" or biomass_type == "gramnegative":
        reactants, products = gram_negative()
    else:
        sys.exit("ERROR: Do not understand what " + biomass_type + " is for a biomass_equation equation\n")

    r = Reaction("biomass_equation")
    for c in reactants:
        cpd = Compound(c, "c")
        r.add_left_compounds({cpd})
        r.set_left_compound_abundance(cpd, reactants[c])

    for c in products:
        cpd = Compound(c, "c")
        r.add_right_compounds({cpd})
        r.set_right_compound_abundance(cpd, products[c])

    rcts = list(reactants.keys())
    prds = list(products.keys())
    rcts.sort()
    prds.sort()
    r.equation = " + ".join(["(" + str(reactants[x]) + ") " + x for x in rcts])
    r.equation += " > "
    r.equation += " + ".join(["(" + str(products[x]) + ") " + x for x in prds])

    return r
    def __construct_reaction_from_reactionlst(self, reaction, rid, reversible):
        substrates = []
        products = []
        stoichiometry = {}
        longname_map = {}

        r = Reaction(rid)
        substrates = self.reactiondb.get_stoichiometry(rid, "_substrates_")
        products = self.reactiondb.get_stoichiometry(rid, "_products_")
        # print "Get RID", rid
        # print "sub is", substrates
        if substrates == "None":
            return None
        for sub in substrates:
            stoichiometry[sub] = self.reactiondb.get_stoichiometry(rid, sub)
            longname_map[sub] = self.reactiondb.get_long_name(sub)
            # print sub, self.reactiondb.get_long_name(sub)

        # print
        for prod in products:
            # print '"' + prod + '"', '"'+ self.reactiondb.get_long_name(prod)+'"'
            stoichiometry[prod] = self.reactiondb.get_stoichiometry(rid, prod)
            longname_map[prod] = self.reactiondb.get_long_name(prod)

        # print
        # print "===="
        r.substrates = substrates
        r.products = products
        r.stoichiometry = stoichiometry
        r.reversible = reversible
        r.longname_map = longname_map
        return r
Exemple #17
0
            def reset(self):
                self.subsets = {'env': [x, y, z]}

                self.define_molecules([a, b, c, x, y, z, h])
                self.set_conc_for_all_testtubes(a, 0.0)
                self.set_conc_for_all_testtubes(c, 1.0E-4)
                self.set_conc_for_all_testtubes(b, 0.0)
                self.set_conc_for_all_testtubes(x, 0.0)
                self.set_conc_for_all_testtubes(y, 0.0)
                self.set_conc_for_all_testtubes(z, 0.0)
                self.set_conc_for_all_testtubes(h, 0.0)

                self.add_reaction(Reaction([a, x], [b, b, h], 10000.0 / 2,
                                           0.0))
                self.add_reaction(Reaction([b, y], [c, c, h], 10000.0 / 2,
                                           0.0))
                self.add_reaction(Reaction([c, z], [a, a, h], 10000.0 / 2,
                                           0.0))

                self.add_reaction(Reaction([a], [], 1.0, 0.0))
                self.add_reaction(Reaction([b], [], 1.0, 0.0))
                self.add_reaction(Reaction([c], [], 1.0, 0.0))

                self.add_reaction(Reaction([h], [], 1.0, 0.0))

                self.generate_ode_fn()
    def __init__(self, gb):
        self.gb = gb

        # -- flow -- #
        self.discr_flow = Flow(gb)

        shape = self.discr_flow.shape()
        self.flux_pressure = np.zeros(shape)

        # -- temperature -- #
        self.discr_temperature = Heat(gb)

        shape = self.discr_temperature.shape()
        self.temperature = np.zeros(shape)
        self.temperature_old = np.zeros(shape)

        # -- solute and precipitate -- #
        self.discr_solute_advection_diffusion = Transport(gb)
        self.discr_solute_precipitate_reaction = Reaction(gb)

        shape = self.discr_solute_advection_diffusion.shape()
        self.solute = np.zeros(shape)
        self.precipitate = np.zeros(shape)
        self.solute_old = np.zeros(shape)
        self.precipitate_old = np.zeros(shape)

        # -- porosity -- #
        self.discr_porosity = Porosity(gb)

        shape = self.discr_porosity.shape()
        self.porosity = np.zeros(shape)
        self.porosity_old = np.zeros(shape)
        self.porosity_star = np.zeros(shape)

        # -- aperture -- #
        self.discr_aperture = Aperture(gb)

        shape = self.discr_aperture.shape()
        self.aperture = np.zeros(shape)
        self.aperture_old = np.zeros(shape)
        self.aperture_star = np.zeros(shape)

        # -- composite variables -- #
        self.porosity_aperture_times_solute = np.zeros(shape)
        self.porosity_aperture_times_precipitate = np.zeros(shape)
            def reset(self):
                self.subsets = {'env': [h, p]}

                self.define_molecules([a, p, h])
                self.set_conc_for_all_testtubes(a, 0.9E-4)
                self.set_conc_for_all_testtubes(p, 0.9E-4)
                self.set_conc_for_all_testtubes(h, 0.0)
                self.add_reaction(Reaction([p, h], [a, a], 10000.0, 0.0))

                self.generate_ode_fn()
Exemple #20
0
            def reset(self):
                self.subsets = {'env': [h, p]}

                self.define_molecules([a, p, h])
                self.change_conc_for_all_testtubes(
                    a, 0.0E-4)  ## this was zero hohee
                self.change_conc_for_all_testtubes(p, 1.0E-4)
                #self.change_conc_for_all_testtubes(h,1.0E-4)
                self.add_reaction(Reaction([p, h], [a, a], 10000.0, 0.0))

                self.generate_ode_fn()
            def reset(self):
                self.subsets = {'env': [u]}

                self.define_molecules([u, v])
                self.set_conc_for_all_testtubes(v, 0.0)
                self.set_conc_for_all_testtubes(u, 1.0)
                self.add_reaction(Reaction([u, v, v], [v, v, v], 1.0,
                                           0.0))  # 8.0

                self.add_reaction(Reaction([u], [], U_DEG_K, 0.0))
                self.add_reaction(Reaction([v], [], V_DEG_K, 0.0))

                for o in [0, 24]:
                    r = 2
                    for sec_i in range(-r, r + 1):
                        self.model.inds[0].sections[sec_i +
                                                    o].concentrations[v] = 1.0

                self.generate_ode_fn()
                self.graph()
    def __construct_reaction_from_kgml(self, reaction, rid, reversible):
        substrates = []
        products = []
        stoichiometry = {}

        for sub in reaction.getiterator('substrate'):
            name = remove_comma(sub.get('name'))
            substrates.append(name)
            stoichiometry[ name ] = self.reactiondb.get_stoichiometry(rid, name)

        for prod in reaction.getiterator('product'):
            name = remove_comma(prod.get('name'))
            products.append(name)
            stoichiometry[ name ] = self.reactiondb.get_stoichiometry(rid, name)

        r = Reaction(rid)
        r.substrates = substrates
        r.products = products
        r.stoichiometry = stoichiometry
        r.reversible = reversible
        return r
 def user_reactions(self, id):
     db_reactions = self.conn.get_user_reactions(id)
     reactions = []
     for db_reaction in db_reactions:
         track_id = db_reaction[0]
         track_duration = db_reaction[1]
         reaction_id = db_reaction[2]
         reaction_hrv = db_reaction[3]
         reaction_date = db_reaction[4]
         reaction_gps = db_reaction[5]
         reactions.append(Reaction(track_id, track_duration, reaction_id, reaction_hrv))
     return reactions
    def __construct_reaction_from_reactionlst(self, reaction, rid, reversible):
        substrates = []
        products = []
        stoichiometry = {}
        longname_map  = {}

        r = Reaction(rid)
        substrates = self.reactiondb.get_stoichiometry(rid, "_substrates_")
        products   = self.reactiondb.get_stoichiometry(rid, "_products_")
        if substrates == "None":
            return None
        for sub in substrates:
            stoichiometry[ sub ] = self.reactiondb.get_stoichiometry(rid, sub)
            longname_map[ sub ] = self.reactiondb.get_long_name(sub)

        for prod in products:
            stoichiometry[ prod ] = self.reactiondb.get_stoichiometry(rid, prod)
            longname_map[ prod ] = self.reactiondb.get_long_name( prod )

        r.substrates = substrates
        r.products = products
        r.stoichiometry = stoichiometry
        r.reversible = reversible
        r.longname_map = longname_map
        return r
Exemple #25
0
 def test_add_get_reactant(self):
     reaction = Reaction()
     reaction.add_limiting_reactant(self._limiting)
     reaction.add_reactant(self._reactant2, 2)
     reaction.add_reactant(self._reactant3, 3)
     self.assertEqual(reaction.get_non_limiting_reactants()[0].n(), 0.002)
     self.assertEqual(reaction.get_non_limiting_reactants()[1].n(), 0.003)
 def __construct_reaction_from_reactionlst(self, reaction, rid, reversible):
     substrates = []
     products = []
     stoichiometry = {}
     longname_map  = {}
     
     r = Reaction(rid)
     substrates = self.reactiondb.get_stoichiometry(rid, "_substrates_")
     products   = self.reactiondb.get_stoichiometry(rid, "_products_")
     # print "Get RID", rid
     # print "sub is", substrates
     if substrates == "None":
         return None
     for sub in substrates:
         stoichiometry[ sub ] = self.reactiondb.get_stoichiometry(rid, sub)
         longname_map[ sub ] = self.reactiondb.get_long_name(sub)
         # print sub, self.reactiondb.get_long_name(sub)
         
     # print 
     for prod in products:
         # print '"' + prod + '"', '"'+ self.reactiondb.get_long_name(prod)+'"'
         stoichiometry[ prod ] = self.reactiondb.get_stoichiometry(rid, prod)
         longname_map[ prod ] = self.reactiondb.get_long_name( prod )
         
     # print
     # print "===="
     r.substrates = substrates
     r.products = products
     r.stoichiometry = stoichiometry
     r.reversible = reversible
     r.longname_map = longname_map
     return r
    def __init__(self, f, chapter=None, check=True):
        """
        Read Reaclib data record.

        Based on description in

        https://groups.nscl.msu.edu/jina/reaclib/db/help.php?topic=reaclib_format&intCurrentNum=0
        """
        if chapter is None:
            l = f.readline()
            if len(l) == 0:
                raise EmptyRecord()
            chapter = int(l.strip())
            firstline = False
        else:
            firstline = True
        self.formula = chapter
        n_in, n_out = self.chapter_info[chapter]
        n = n_in + n_out
        l = f.readline()
        if len(l) == 0 and firstline:
            raise EmptyRecord()
        nuc = [l[5 + 5 * i:5 + 5 * (i + 1)] for i in range(n)]
        nuc_in = isotope.ufunc_ion(nuc[:n_in])

        # deal with panov modification to reaclib
        nuc_out = []
        for n in nuc[n_in:]:
            if n.count('#') > 0:
                ni, nt = n.split('#')
                nuc_out.extend([nt] * int(ni))
            else:
                nuc_out.append(n)

        nuc_out = isotope.ufunc_ion(nuc_out)
        self.label = l[43:47]
        self.type = l[47]

        # we added type ' ' not in REACLIB documentation
        assert self.type in ('n', 'r', 'w', 's', ' '), 'ERROR type: ' + l
        reverse = l[48]
        assert reverse in ('v', ' '), 'ERROR reverse: ' + l
        self.reverse = reverse == 'v'
        self.Q = float(l[52:64])
        coeff = []
        for nci in self.n_coeff:
            l = f.readline()
            for i in range(nci):
                coeff.append(l[i * 13:(i + 1) * 13])
        coeff = [float(i) for i in coeff]
        self.reaction = Reaction(nuc_in, nuc_out)
        self.coeff = coeff
Exemple #28
0
 def tape_break(self, t):
     if not t.is_leaf():
         if self.break_position == 'top':
             term_left, term_right = t.top_break()
         elif self.break_position == 'random':
             term_left, term_right = t.random_break()
         else:
             raise RuntimeError(f'Invalid break position {self.break_position}')
         reaction = Reaction((term_left, term_right), 'break', (t,))
         self.apply_reaction(reaction)
         return True
     else:
         return False
            def reset(self):
                self.subsets = {
                    'env' : [u]
                }

                
                self.define_molecules([u,v])
                self.change_conc_for_all_testtubes(v,0.04)
                self.change_conc_for_all_testtubes(u,U_DRIVE) 
                self.add_reaction(Reaction([u,v,v],[v,v,v],LAMBDA,0.0)) # 8.0

                k = 1.0
                self.add_reaction(Reaction([u],[],U_DEG_K,0.0))
                self.add_reaction(Reaction([v],[],V_DEG_K,0.0))

                for o in range(0,48,16) :
                    for sec_i in [-3,-2,-1,0,1,2,3]:
                        self.model.inds[0].sections[sec_i+o].concentrations[v]=0.0
                        self.model.inds[0].sections[sec_i+o].concentrations[u]=U_DRIVE
                # for i in range(24) :
                #     self.model.inds[0].sections[i].concentrations[v]=0.0
                
                self.generate_ode_fn()
                self.graph()
Exemple #30
0
    def init(self):
        self.define_molecule(self.abb, concentration=0.0)
        self.define_molecule(self.abbb, concentration=0.0)
        self.define_molecule(self.ba, concentration=0.0)

        self.add_reaction(
            Reaction([self.abb, self.abb], [self.ba, self.abbb], 10.0, 0.0))

        # ## manually kick start an autocatalyst (for testing purposes)
        # baa = Molecule(atom_string = 'baa', G=0.001)
        # self.define_molecule(baa,concentration=0.0001)
        # self.add_reaction(Reaction([baa,self.aab],[baa,baa],0.1,0.0))

        while (len(self.reactions) < 20):
            self.generate_avalanche()

        self.generate_ode_fn()
Exemple #31
0
    def from_rxn_file(cls, rxn_file):
        reactions = []
        with open(rxn_file, 'r') as f:
            nrxns = sum(1 for line in f)
        pbar = IntProgressBar('Building rxns and Isotopes', nrxns)
        with open(rxn_file, 'r') as f:
            for rxn in f:
                reactions.append(Reaction(rxn.strip(), pbar=pbar))
        for reaction in reactions:
            print str(reaction)
            print reaction.isotopes
            print reaction.reactants
            print reaction.products
        isotopes = []
        for reaction in reactions:
            isotopes.extend(reaction.isotopes)

        isotopes = set(isotopes)
        return cls(isotopes, reactions)
Exemple #32
0
 def get_reaction(self, info):
     id_ = info["id"]
     if id_ in self._reaction_dict:
         return self._reaction_dict[id_]
     from_material = {
         GW.get_material(name): info["rawMaterial"][name]
         for name in info["rawMaterial"]
     }
     to_material = {
         GW.get_material(name): info["product"][name]
         for name in info["product"]
     }
     duration = info["time"]
     device = get_device_type(info["device"])
     reaction = Reaction(id_,
                         from_material,
                         to_material,
                         device=device,
                         duration=duration)
     self._reaction_dict[id_] = reaction
     return reaction
            def reset(self):
                self.subsets = {
                    'env' : [a,b]
                }

                #self.define_molecules([w,x,y,a,b])
                self.define_molecules([w,x,y,b,a])
                self.change_conc_for_all_testtubes(w,1E-1)
                self.change_conc_for_all_testtubes(x,1E-1)
                self.change_conc_for_all_testtubes(a,1E-1)
                self.add_reaction(Reaction([x,a],[x,x],1.,0.0))
                self.add_reaction(Reaction([w,b],[w,w],1.,0.0))
                self.add_reaction(Reaction([x],[y],0.01,0.0))
                self.add_reaction(Reaction([w],[y],0.01,0.0))
                self.add_reaction(Reaction([y],[],0.2,0.0))

                self.add_reaction(Reaction([a,b],[],0.5,0.0))

                
                self.generate_ode_fn()
                self.graph()
    def __construct_reaction_from_kgml(self, reaction, rid, reversible):
        substrates = []
        products = []
        stoichiometry = {}

        for sub in reaction.getiterator('substrate'):
            name = remove_comma(sub.get('name'))
            substrates.append(name)
            stoichiometry[name] = self.reactiondb.get_stoichiometry(rid, name)

        for prod in reaction.getiterator('product'):
            name = remove_comma(prod.get('name'))
            products.append(name)
            stoichiometry[name] = self.reactiondb.get_stoichiometry(rid, name)

        r = Reaction(rid)
        r.substrates = substrates
        r.products = products
        r.stoichiometry = stoichiometry
        r.reversible = reversible
        return r
    def __construct_reaction(self, rname, ko, reac, arrow, prod, mname):
        """ Code to parse and construct a reaction"""
        # Step 1. split reactants.
        rname = str(rname)
        mname = str(mname)

        r = Reaction(rname)
        left_coef,  left_comp = self.__get_coef_and_name(reac)
        right_coef, right_comp = self.__get_coef_and_name(prod)

        r.substrates.extend(left_comp)
        r.products.extend(right_comp)

        for i in xrange(len(left_coef)):
            r.stoichiometry[left_comp[i]] = left_coef[i]

        for i in xrange(len(right_coef)):
            r.stoichiometry[right_comp[i]] = right_coef[i]
        r.reversible = arrow
        r.arrow = arrow
        if ko == True:
            r.ko = True
        elif ko == False:
            r.ko = False
        elif 'false' in ko:
        # elif type(ko) == type("") and ko.lower() == "false":
            r.ko = False
        else:
            r.ko = True
        r.metabolism = mname
        r.active = True
        return r
Exemple #36
0
    def generate_avalanche(self):
        self.model.event_logger.record_avalanche()

        NUM_LOW_PROPENSITY_REACTIONS = 1
        PROB_HIGH_FLUX = 0.25
        C = 100  # can be 100 or 1000 apparently
        logger.debug('FR: generate_avalanche()')
        # 0: for N = 0 to num_low_propensity_reactions.
        new_species = []
        for rxn_i in range(NUM_LOW_PROPENSITY_REACTIONS):
            # 1: Choose two existing species (r1, r2) to react in a low
            # propensity reaction (kf~0, kb~0) to produce two potential
            # products p1 and p2.

            ## 1b. MDE augment: do this until a p1 or p2 is found that does
            ## not already exist.
            count = 0
            while True:
                count += 1
                if count > 1000:
                    logger.debug(
                        'FR: Unable to find products that do not already exist.'
                    )
                r1, r2 = np.random.choice(list(self.molecules.values()), 2)
                logger.debug(f'FR: try to make low-p rxn for {r1} and {r2}')
                low_prop_reaction = self.generate_reaction(r1, r2)
                if low_prop_reaction is not None:
                    p1, p2 = low_prop_reaction['products']
                    if (p1 not in self.molecules.values()) or (
                            p2 not in self.molecules.values()):
                        break

            if low_prop_reaction is None:
                pass
                logger.debug(
                    'FR: Failed to generate low-propensity reaction. %d' %
                    (rxn_i))
                # this shouldn't happen thanks to 1b above
                quit()
            if low_prop_reaction != None:
                logger.debug('FR: A low propensity reaction occurs.')
                logger.debug(
                    f'FR: {r1} + {r2} --> {low_prop_reaction["products"]}')
                logger.debug(
                    f'FR: This creates new species: {low_prop_reaction["new_species"]}'
                )

                new_species.extend(low_prop_reaction['new_species'])
                # 4: if the condition that the reaction is spontaneous can
                # be satisfied, create novel products at low concentration
                # (e.g. 10E-7 M) and increment newSpec ++ //Store the
                # number of novel species produced.
                # print('Low propensity rxn: %s + %s ~~> %s' %(
                #     r1.atom_string, r2.atom_string,
                #     ','.join([m.atom_string for m in low_prop_reaction['products']])))
                for m in low_prop_reaction['products']:
                    #logger.debug('FR: Spontaneous emergence of small quantity of %s' %(m))
                    self.define_molecule(m)
                    self.change_conc_for_all_testtubes(m, concentration=1E-6)
                    # 5: k_f=0 k_b = 0. //Novel products come to
                    # existence at low concentration and are not
                    # produced, nor decay. MDE: I understand this to
                    # be saying "this reaction is so slow / unlikely,
                    # we consider it to be a one-off event" and do not
                    # create a new "reaction" to simulate it ever
                    # happening again. Molecules will only stick
                    # around if they come to exist by other means.
        # END for n = 0 to num_low_propensity_reactions

        # 8: while newSpec != 1 do [MDE: interpreting as keep going while new species exist]
        #    i.e. "for each new species..."
        # 9: for i = 0 to newSpec

        while len(new_species) > 0:
            ri = new_species.pop()
            logger.debug(f'FR: Look for hi-p reactions for {ri}.')
            # 10: for j = 0 to number of species currently existing
            prob = PROB_HIGH_FLUX / (len(ri.atom_string)**2)
            high_flux_reactions_found = 0
            for jindex in range(len(self.molecules.values())):
                # 11: if rand()oprob_high_flux x 1/(species[i].length)^2
                if np.random.rand() >= prob:
                    pass
                    #logger.debug(f'FR: {ri} does not react with ({jindex}/{len(self.molecules.values())-1})')
                else:
                    """ ALG 3 Begins here. """
                    ## a high-flux reaction occurs...  r1 is ri, r2 is
                    ## to be selected by a roulette algorithm Assuming
                    ## there is a typo in alg 3, and that score is
                    ## simply proportional (not the additive (+=) way
                    ## it is written) on line 2 of Alg 3 of 2008.
                    ## plot(x,1./(1+(rj.length - ri.length)**2)
                    scores = [
                        1. / (1. + ((rj.length - ri.length)**2) *
                              (rj.length)**2)
                        for rj in self.molecules.values()
                    ]
                    #print(scores)
                    scores = [s / sum(scores) for s in scores]
                    # x = ['%s: %s' %(score,name.atom_string)
                    #      for score,name in zip(scores,self.molecules.values())]
                    # print('\n'.join(x))
                    rj = np.random.choice(list(self.molecules.values()),
                                          p=scores)
                    logger.debug(
                        f'FR: {ri} *does* react with ({jindex}/{len(self.molecules.values())-1}): {rj}'
                    )
                    high_prop_rxn = self.generate_reaction(ri, rj)
                    if high_prop_rxn is not None:
                        p1, p2 = high_prop_rxn['products']
                        new_species.extend(high_prop_rxn['new_species'])

                        for m in high_prop_rxn['products']:
                            self.define_molecule(m)  #,concentration=0.0)

                        if len(high_prop_rxn['new_species']) == 0:
                            kb = 0.0
                            logger.debug(
                                'One of the new species already exist.')
                            logger.debug(f'{p1} {p2}')
                        else:
                            kb = np.random.rand() * C * 0.01
                        rxn = Reaction([ri, rj], [p1, p2],
                                       kf=np.random.rand() * C,
                                       kb=kb)
                        logger.debug(
                            f'FR: Adding high propensity reaction: \n\t%s' %
                            (str(rxn)))
                        self.add_reaction(rxn)
                        high_flux_reactions_found += 1
                    else:
                        logger.debug(
                            f'FR: a genrated hi-p rxn. was not actually possible'
                        )

            logger.debug(f'FR: new species {ri} interacts with ' + \
                            f'{high_flux_reactions_found}/{len(self.molecules.values())} ' + \
                            f'existing mols.')
        self.cull_irrelevant_reactions()
        self.cull_unconnected_molecules()
        # the chemistry has likely changed; update the ODE function
        self.generate_ode_fn()
 def wrap(*args, **kwargs):
     reaction = Reaction(*[matchstr, args[0], args[1], args[2], args[3]])
     if reaction.match(0):
         return function(reaction)
Exemple #38
0
    if chem.a.size == 1:
        continue

    # For chemical at hand, iterate over available transforms to generate any
    # possible incoming reactions leading to it.
    candidates = {}
    for t in transforms:
        candidates.update({s: [t.popularity, t.id]
                           for s in chem .make_retrostep(t)})
    new_stats['total'] += len(candidates)

    # Then add valid ones which were not yet generated to the main pool.
    new_rxns = {}
    for smi in set(candidates.keys()).difference(reactions):
        try:
            rxn = Reaction(smi, popularity=candidates[smi][0], 
                           tid=candidates[smi][1])
        except ValueError:
            continue
        new_rxns[smi] = rxn
    new_stats['accepted'] += len(new_rxns)
    new_stats['valid'] += len(new_rxns)
    reactions.update(new_rxns)

    # Finally, use the database to find out which of those newly  added
    # reactions are already published.
    cursor = db['reaction'].find(
        {'_id': {'$in': chem_rec['reactions']['produced']}})
    for rxn_rec in cursor:
        old_stats['total'] += 1

        # RX.ID are not unique thus the 'rxid' field in the database is a
Exemple #39
0
    def initialize(self):
        # First we set the static Volume for the Reaction class
        try:
            Reaction.setGlobalRxnVolume(self.parameterDictionary.getVolume())
        except:
            print "Error: the parameterDictionary cannot find a volume element"
            print "Crashing...."
            sys.exit(0)

        ## We classify all the reactions into a few classes for processing.
        isUnprocessable = lambda x: (x == 0)  ## 0 is an unprocessable reaction
        nonProcessableReactions = [
            line for line in self.rawReactionRules
            if isUnprocessable(util.classifyReaction(line))
        ]
        processibleReactions = [
            line for line in self.rawReactionRules
            if not isUnprocessable(util.classifyReaction(line))
        ]

        ## NOTICE
        # There are currently 32 bad reactions, another 10 or so that were deleted at the outset.
        # ~ 8 Deletion reactions:  "Ste7 + Cell -> Cell kdeg_Ste7 DeleteMolecules"
        # ~ 1 Dilution Reaction:   "{MatchOnce}* + Cell -> Cell kdilution	exclude_reactants(1,Cell)"
        # ~ 23 Creation Reactions: "Cell -> Cell + Ste7(Ste5_site,MAPK_site,S359_T363~none) ksynth_Ste7"

        ## This takes each of the reactions in good reactions and expands them out.
        unidirectionalGoodReactions = []
        for line in processibleReactions:
            expandedLines = util.expandReactions(line)
            unidirectionalGoodReactions.extend(expandedLines)

        # THIS SHOULD ALL BE REDONE, because of DIMERIZATION + MODIFICATION RXNS

        # Get the dimerization reactions.
        tmpFunc = lambda x: (x == 1)
        dimerizationReactionsArray = [
            line for line in unidirectionalGoodReactions
            if tmpFunc(util.classifyReaction(line)) == True
        ]

        # Get the decomposition reactions.
        tmpFunc = lambda x: (x == 2)
        decompositionReactionsArray = [
            line for line in unidirectionalGoodReactions
            if tmpFunc(util.classifyReaction(line)) == True
        ]

        # Get the modification reactions.
        tmpFunc = lambda x: (x == 3)
        modificationReactionsArray = [
            line for line in unidirectionalGoodReactions
            if tmpFunc(util.classifyReaction(line)) == True
        ]

        self.dimerizationReactions = {}
        self.decompositionReactions = {}
        self.modificationReactions = {}

        # Parse each reaction and install it in self.reactionRules.
        # Also determine whether it is a dimerization, decomposition, or modification reaction
        # and put it into the appropriate dictionary.
        for line in unidirectionalGoodReactions:
            aRxn = util.parseReaction(line, self.parameterDictionary)
            self.reactionRules.append(aRxn)

            gb = aRxn.getGenericBinding()
            if aRxn.isDimerizationReaction():
                if gb not in self.dimerizationReactions.keys():
                    self.dimerizationReactions[gb] = []
                self.dimerizationReactions[gb].append(aRxn)
            elif aRxn.isDecompositionReaction():
                if gb not in self.decompositionReactions.keys():
                    self.decompositionReactions[gb] = []
                self.decompositionReactions[gb].append(aRxn)
            elif aRxn.isModificationReaction():
                if gb not in self.modificationReactions.keys():
                    self.modificationReactions[gb] = []
                self.modificationReactions[gb].append(aRxn)

        for fullBindingCreated in self.dimerizationReactions:
            leftSite, rightSite = fullBindingCreated
            for rxn in self.dimerizationReactions[fullBindingCreated]:
                reactant1, reactant2 = rxn.reactants
                if reactant1.startswith(leftSite[0]):
                    self.allosteryInterpreter.createNewAllosteryAtSite(
                        leftSite, reactant1)
                    self.allosteryInterpreter.createNewAllosteryAtSite(
                        rightSite, reactant2)
                elif reactant1.startswith(rightSite[0]):
                    self.allosteryInterpreter.createNewAllosteryAtSite(
                        rightSite, reactant1)
                    self.allosteryInterpreter.createNewAllosteryAtSite(
                        leftSite, reactant2)
                else:
                    raise ValueError

        for fullBindingCreated in self.decompositionReactions.keys():
            leftSite, rightSite = fullBindingCreated
            for rxn in self.decompositionReactions[fullBindingCreated]:
                product1, product2 = rxn.products
                if product1.startswith(leftSite[0]):
                    self.allosteryInterpreter.createNewAllosteryAtSite(
                        leftSite, product1)
                    self.allosteryInterpreter.createNewAllosteryAtSite(
                        rightSite, product2)
                elif product1.startswith(rightSite[0]):
                    self.allosteryInterpreter.createNewAllosteryAtSite(
                        rightSite, product1)
                    self.allosteryInterpreter.createNewAllosteryAtSite(
                        leftSite, product2)
                else:
                    raise ValueError

        self.writeAllostericSitesToMoleculeObject()
Exemple #40
0
 def test_get_yield(self):
     reaction = Reaction()
     reaction.add_limiting_reactant(self._limiting)
     reaction.add_product(self._product, 0.3)
     self.assertEqual(reaction.get_yield(), 75)
Exemple #41
0
 def test_add_get_product(self):
     reaction = Reaction()
     reaction.add_product(self._product, 0.4)
     self.assertEqual(reaction.get_product().n(), 0.001)
    def initialize(self):
        # First we set the static Volume for the Reaction class
        try:
            Reaction.setGlobalRxnVolume(self.parameterDictionary.getVolume())
        except:
            print "Error: the parameterDictionary cannot find a volume element"
            print "Crashing...."
            sys.exit(0)

        ## We classify all the reactions into a few classes for processing.
        isUnprocessable = lambda x: (x == 0) ## 0 is an unprocessable reaction
        nonProcessableReactions = [line for line in self.rawReactionRules if isUnprocessable(util.classifyReaction(line))]
        processibleReactions = [line for line in self.rawReactionRules if not isUnprocessable(util.classifyReaction(line))]

        ## NOTICE
        # There are currently 32 bad reactions, another 10 or so that were deleted at the outset.
        # ~ 8 Deletion reactions:  "Ste7 + Cell -> Cell kdeg_Ste7 DeleteMolecules"
        # ~ 1 Dilution Reaction:   "{MatchOnce}* + Cell -> Cell kdilution	exclude_reactants(1,Cell)"
        # ~ 23 Creation Reactions: "Cell -> Cell + Ste7(Ste5_site,MAPK_site,S359_T363~none) ksynth_Ste7"

        ## This takes each of the reactions in good reactions and expands them out.
        unidirectionalGoodReactions = []
        for line in processibleReactions:
            expandedLines = util.expandReactions(line)
            unidirectionalGoodReactions.extend(expandedLines)


        # THIS SHOULD ALL BE REDONE, because of DIMERIZATION + MODIFICATION RXNS

        # Get the dimerization reactions.
        tmpFunc = lambda x: (x == 1)
        dimerizationReactionsArray = [line for line in unidirectionalGoodReactions if tmpFunc(util.classifyReaction(line)) == True]

        # Get the decomposition reactions.
        tmpFunc = lambda x: (x == 2)
        decompositionReactionsArray = [line for line in unidirectionalGoodReactions if tmpFunc(util.classifyReaction(line)) == True]

        # Get the modification reactions.
        tmpFunc = lambda x: (x == 3)
        modificationReactionsArray = [line for line in unidirectionalGoodReactions if tmpFunc(util.classifyReaction(line)) == True]

        self.dimerizationReactions = {}
        self.decompositionReactions = {}
        self.modificationReactions = {}

        # Parse each reaction and install it in self.reactionRules.
        # Also determine whether it is a dimerization, decomposition, or modification reaction
        # and put it into the appropriate dictionary.
        for line in unidirectionalGoodReactions:
            aRxn = util.parseReaction(line, self.parameterDictionary)
            self.reactionRules.append(aRxn)
            
            gb = aRxn.getGenericBinding()
            if aRxn.isDimerizationReaction():
                if gb not in self.dimerizationReactions.keys():
                    self.dimerizationReactions[gb] = []
                self.dimerizationReactions[gb].append(aRxn)
            elif aRxn.isDecompositionReaction():
                if gb not in self.decompositionReactions.keys():
                    self.decompositionReactions[gb] = []
                self.decompositionReactions[gb].append(aRxn)
            elif aRxn.isModificationReaction():
                if gb not in self.modificationReactions.keys():
                    self.modificationReactions[gb] = []
                self.modificationReactions[gb].append(aRxn)

        for fullBindingCreated in self.dimerizationReactions:
            leftSite, rightSite = fullBindingCreated
            for rxn in self.dimerizationReactions[fullBindingCreated]:
                reactant1, reactant2 = rxn.reactants
                if reactant1.startswith(leftSite[0]):
                    self.allosteryInterpreter.createNewAllosteryAtSite(leftSite, reactant1)
                    self.allosteryInterpreter.createNewAllosteryAtSite(rightSite, reactant2)
                elif reactant1.startswith(rightSite[0]):
                    self.allosteryInterpreter.createNewAllosteryAtSite(rightSite, reactant1)                    
                    self.allosteryInterpreter.createNewAllosteryAtSite(leftSite, reactant2)
                else:
                    raise ValueError

        for fullBindingCreated in self.decompositionReactions.keys():
            leftSite, rightSite = fullBindingCreated
            for rxn in self.decompositionReactions[fullBindingCreated]:
                product1, product2 = rxn.products
                if product1.startswith(leftSite[0]):
                    self.allosteryInterpreter.createNewAllosteryAtSite(leftSite, product1)
                    self.allosteryInterpreter.createNewAllosteryAtSite(rightSite, product2)
                elif product1.startswith(rightSite[0]):
                    self.allosteryInterpreter.createNewAllosteryAtSite(rightSite, product1)                    
                    self.allosteryInterpreter.createNewAllosteryAtSite(leftSite, product2)
                else:
                    raise ValueError

        self.writeAllostericSitesToMoleculeObject()
Exemple #43
0
 def test_add_get_limiting_reactant(self):
     reaction = Reaction()
     reaction.add_limiting_reactant(self._limiting)
     self.assertEqual(reaction.get_limiting_reactant().n(), 0.001)
Exemple #44
0
#!/usr/local/bin/python3.7

import const as cs
from configuration import Config
from reaction import Reaction

# Read temperature
print("Calculation of the reaction rate")
T_K = float(input("Type temperature (in K): "))
if T_K < 0.0:
    raise Exception("Negative temperature")

# Initiate thermodynamics objects
in_state = Config("initial state")
ts_state = Config("transition state")
fi_state = Config("final state")
print()

print(in_state)
print(ts_state)
print(fi_state)

diss = Reaction("dissociation", in_state, ts_state, fi_state, T_K)
print(diss)
       


Exemple #45
0
def readKineticsEntry(entry, speciesDict, energyUnits, moleculeUnits):
    """
    Read a kinetics `entry` for a single reaction as loaded from a Chemkin
    file. The associated mapping of labels to species `speciesDict` should also
    be provided. Returns a :class:`Reaction` object with the reaction and its
    associated kinetics.
    """
    
    if energyUnits.lower() in ['kcal/mole', 'kcal/mol']:
        energyFactor = 1.0 
    elif energyUnits.lower() in ['cal/mole', 'cal/mol']:
        energyFactor = 0.001 
    else:
        raise ChemkinError('Unexpected energy units "{0}" in reaction block.'.format(energyUnits))
    if moleculeUnits.lower() in ['moles']:
        moleculeFactor = 1.0 
    else:
        raise ChemkinError('Unexpected molecule units "{0}" in reaction block.'.format(energyUnits))
    
    lines = entry.strip().splitlines()
    
    # The first line contains the reaction equation and a set of modified Arrhenius parameters
    tokens = lines[0].split()
    A = float(tokens[-3])
    n = float(tokens[-2])
    Ea = float(tokens[-1])
    reaction = ''.join(tokens[:-3])
    thirdBody = False
    
    # Split the reaction equation into reactants and products
    reversible = True
    reactants, products = reaction.split('=')
    if '=>' in reaction:
        products = products[1:]
        reversible = False
    if '(+M)' in reactants: reactants = reactants.replace('(+M)','')
    if '(+m)' in reactants: reactants = reactants.replace('(+m)','')
    if '(+M)' in products:  products = products.replace('(+M)','')
    if '(+m)' in products:  products = products.replace('(+m)','')
    
    # Create a new Reaction object for this reaction
    reaction = Reaction(reactants=[], products=[], reversible=reversible)
    
    # Convert the reactants and products to Species objects using the speciesDict
    for reactant in reactants.split('+'):
        reactant = reactant.strip()
        stoichiometry = 1
        if reactant[0].isdigit():
            # This allows for reactions to be of the form 2A=B+C instead of A+A=B+C
            # The implementation below assumes an integer between 0 and 9, inclusive
            stoichiometry = int(reactant[0])
            reactant = reactant[1:]               
        if reactant == 'M' or reactant == 'm':
            thirdBody = True
        elif reactant not in speciesDict:
            raise ChemkinError('Unexpected reactant "{0}" in reaction {1}.'.format(reactant, reaction))
        else:
            for i in range(stoichiometry):
                reaction.reactants.append(speciesDict[reactant])
    for product in products.split('+'):
        product = product.strip()
        stoichiometry = 1
        if product[0].isdigit():
            # This allows for reactions to be of the form A+B=2C instead of A+B=C+C
            # The implementation below assumes an integer between 0 and 9, inclusive
            stoichiometry = int(product[0])
            product = product[1:]
        if product.upper() == 'M' or product == 'm':
            pass
        elif product not in speciesDict:
            raise ChemkinError('Unexpected product "{0}" in reaction {1}.'.format(product, reaction))
        else:
            for i in range(stoichiometry):
                reaction.products.append(speciesDict[product])
    
    # Determine the appropriate units for k(T) and k(T,P) based on the number of reactants
    # This assumes elementary kinetics for all reactions
    if len(reaction.reactants) + (1 if thirdBody else 0) == 3:
        kunits = "cm^6/(mol^2*s)"
        klow_units = "cm^9/(mol^3*s)"
    elif len(reaction.reactants) + (1 if thirdBody else 0) == 2:
        kunits = "cm^3/(mol*s)" 
        klow_units = "cm^6/(mol^2*s)"
    elif len(reaction.reactants) + (1 if thirdBody else 0) == 1:
        kunits = "s^-1" 
        klow_units = "cm^3/(mol*s)"
    else:
        raise ChemkinError('Invalid number of reactant species for reaction {0}.'.format(reaction))
    
    # The rest of the first line contains the high-P limit Arrhenius parameters (if available)
    #tokens = lines[0][52:].split()
    tokens = lines[0].split()[1:]
    arrheniusHigh = Arrhenius(
        A = (A,kunits),
        n = n,
        Ea = (Ea * energyFactor,"kcal/mol"),
        T0 = (1,"K"),
    )
    
    if len(lines) == 1:
        # If there's only one line then we know to use the high-P limit kinetics as-is
        reaction.kinetics = arrheniusHigh
    else:
        # There's more kinetics information to be read
        arrheniusLow = None
        troe = None
        lindemann = None
        chebyshev = None
        pdepArrhenius = None
        efficiencies = {}
        chebyshevCoeffs = []
        
    
        # Note that the subsequent lines could be in any order
        for line in lines[1:]:
            
            tokens = line.split('/')
            if 'DUP' in line or 'dup' in line:            
                # Duplicate reaction
                reaction.duplicate = True
            
            elif 'LOW' in line or 'low' in line:
                # Low-pressure-limit Arrhenius parameters
                tokens = tokens[1].split()
                arrheniusLow = Arrhenius(
                    A = (float(tokens[0].strip()),klow_units),
                    n = float(tokens[1].strip()),
                    Ea = (float(tokens[2].strip()) * energyFactor,"kcal/mol"),
                    T0 = (1,"K"),
                )
            
            elif 'TROE' in line or 'troe' in line:
                # Troe falloff parameters
                tokens = tokens[1].split()
                alpha = float(tokens[0].strip())
                T3 = float(tokens[1].strip())
                T1 = float(tokens[2].strip())
                try:
                    T2 = float(tokens[3].strip())
                except (IndexError, ValueError):
                    T2 = None
                
                troe = Troe(
                    alpha = (alpha,''),
                    T3 = (T3,"K"),
                    T1 = (T1,"K"),
                    T2 = (T2,"K") if T2 is not None else None,
                )
            
            elif 'CHEB' in line or 'cheb' in line:
                # Chebyshev parameters
                if chebyshev is None:
                    chebyshev = Chebyshev()
                    chebyshev.kunits = kunits
                tokens = [t.strip() for t in tokens]
                if 'TCHEB' in line:
                    index = tokens.index('TCHEB')
                    tokens2 = tokens[index+1].split()
                    chebyshev.Tmin = Quantity(float(tokens2[0].strip()),"K")
                    chebyshev.Tmax = Quantity(float(tokens2[1].strip()),"K")
                if 'PCHEB' in line:
                    index = tokens.index('PCHEB')
                    tokens2 = tokens[index+1].split()
                    chebyshev.Pmin = Quantity(float(tokens2[0].strip()),"atm")
                    chebyshev.Pmax = Quantity(float(tokens2[1].strip()),"atm")
                if 'TCHEB' in line or 'PCHEB' in line:
                    pass
                elif chebyshev.degreeT == 0 or chebyshev.degreeP == 0:
                    tokens2 = tokens[1].split()
                    chebyshev.degreeT = int(float(tokens2[0].strip()))
                    chebyshev.degreeP = int(float(tokens2[1].strip()))
                    chebyshev.coeffs = numpy.zeros((chebyshev.degreeT,chebyshev.degreeP), numpy.float64)
                else:
                    tokens2 = tokens[1].split()
                    chebyshevCoeffs.extend([float(t.strip()) for t in tokens2])
                    
            elif 'PLOG' in line or 'plog' in line:
                # Pressure-dependent Arrhenius parameters
                if pdepArrhenius is None:
                    pdepArrhenius = []
                tokens = tokens[1].split()
                pdepArrhenius.append([float(tokens[0].strip()), Arrhenius(
                    A = (float(tokens[1].strip()),kunits),
                    n = float(tokens[2].strip()),
                    Ea = (float(tokens[3].strip()) * energyFactor,"kcal/mol"),
                    T0 = (1,"K"),
                )])

            else:
                # Assume a list of collider efficiencies
                for collider, efficiency in zip(tokens[0::2], tokens[1::2]):
                    efficiencies[speciesDict[collider.strip()].molecule[0]] = float(efficiency.strip())
    
        # Decide which kinetics to keep and store them on the reaction object
        # Only one of these should be true at a time!
        if chebyshev is not None:
            if chebyshev.Tmin is None or chebyshev.Tmax is None:
                raise ChemkinError('Missing TCHEB line for reaction {0}'.format(reaction))
            if chebyshev.Pmin is None or chebyshev.Pmax is None:
                raise ChemkinError('Missing PCHEB line for reaction {0}'.format(reaction))
            index = 0
            for t in range(chebyshev.degreeT):
                for p in range(chebyshev.degreeP):
                    chebyshev.coeffs[t,p] = chebyshevCoeffs[index]
                    index += 1
            # Don't forget to convert the Chebyshev coefficients to SI units!
            # This assumes that s^-1, cm^3/mol*s, etc. are compulsory
            chebyshev.coeffs[0,0] -= (len(reaction.reactants) - 1) * 6.0
            reaction.kinetics = chebyshev
        elif pdepArrhenius is not None:
            reaction.kinetics = PDepArrhenius(
                pressures = ([P for P, arrh in pdepArrhenius],"atm"),
                arrhenius = [arrh for P, arrh in pdepArrhenius],
            )
        elif troe is not None:
            troe.arrheniusHigh = arrheniusHigh
            troe.arrheniusLow = arrheniusLow
            troe.efficiencies = efficiencies
            reaction.kinetics = troe
        elif arrheniusLow is not None:
            reaction.kinetics = Lindemann(arrheniusHigh=arrheniusHigh, arrheniusLow=arrheniusLow)
            reaction.kinetics.efficiencies = efficiencies
        elif thirdBody:
            reaction.kinetics = ThirdBody(arrheniusLow=arrheniusHigh)
            reaction.kinetics.efficiencies = efficiencies
        elif reaction.duplicate:
            reaction.kinetics = arrheniusHigh
        else:
            raise ChemkinError('Unable to determine pressure-dependent kinetics for reaction {0}.'.format(reaction))
   
    return reaction