Exemple #1
0
def get_dGr0_prime(sparse):
    try:
        r = Reaction(sparse)
        if not r.check_full_reaction_balancing():
            return np.nan, np.nan, 'unbalanbed reaction'
        dG0_prime, dG0_std = equilibrator.dG0_prime(r)
        return dG0_prime, dG0_std, ''
    except ValueError as e:
        return np.nan, np.nan, 'value error: ' + str(e)
    except KeyError as e:
        return np.nan, np.nan, 'key error: ' + str(e)
    def test_reduction_potential(self):
        kegg_id_to_coeff = {'C00036': -1, 'C00149': 1}  # oxaloacetate = malate
        reaction = Reaction(kegg_id_to_coeff)

        cc = ComponentContribution(pH=7.0, ionic_strength=0.1)
        E0_prime_mV, E0_uncertainty = cc.E0_prime(reaction)

        self.assertAlmostEqual(E0_prime_mV, -175.2, 1)
        self.assertAlmostEqual(E0_uncertainty, 5.3, 1)
    def test_reaction_balancing(self):
        warnings.simplefilter('ignore', ResourceWarning)

        kegg_id_to_coeff = {'C00011' : -1, 'C00001' : -1, 'C01353' : 1}
        reaction = Reaction(kegg_id_to_coeff)
        self.assertTrue(reaction.check_full_reaction_balancing())

        kegg_id_to_coeff = {'C00036' : -1, 'C00149' : 1}  # oxaloacetate = malate
        reaction = Reaction(kegg_id_to_coeff)
        self.assertAlmostEqual(reaction.check_half_reaction_balancing(), 2.0)

        kegg_id_to_coeff = {'C00031' : -1, 'C00469' : 2}  # missing two CO2
        reaction = Reaction(kegg_id_to_coeff)
        self.assertDictEqual(reaction._get_reaction_atom_balance(),
                             {'O': -4, 'C': -2, 'e-': -44})
Exemple #4
0
    def get_eQ_reaction_from_rid(
        self, r_id: str, pickaxe: Pickaxe = None, db_name: str = None
    ) -> Union[PhasedReaction, None]:
        """Get an eQuilibrator reaction object from an r_id.

        Parameters
        ----------
        r_id : str
            Reaction id to get object for.
        pickaxe : Pickaxe
            pickaxe object to look for the compound in, by default None.
        db_name : str
            Database to look for reaction in.

        Returns
        -------
        PhasedReaction
            eQuilibrator reactiono to calculate ∆Gr with.
        """
        if pickaxe:
            if r_id in pickaxe.reactions:
                reaction_info = pickaxe.reactions[r_id]
            else:
                return None
        elif db_name:
            mine = self.client[db_name]
            reaction_info = mine.reactions.find_one({"_id": r_id})
            if not reaction_info:
                return None
        else:
            return None

        reactants = reaction_info["Reactants"]
        products = reaction_info["Products"]

        lhs = " + ".join(f"{r[0]} {r[1]}" for r in reactants)
        rhs = " + ".join(f"{p[0]} {p[1]}" for p in products)
        reaction_string = " => ".join([lhs, rhs])

        compounds = set([r[1] for r in reactants])
        compounds.update(tuple(p[1] for p in products))

        eQ_compound_dict = {
            c_id: self.get_eQ_compound_from_cid(c_id, pickaxe, db_name)
            for c_id in compounds
        }

        if not all(eQ_compound_dict.values()):
            return None

        if "X73bc8ef21db580aefe4dbc0af17d4013961d9d17" not in compounds:
            eQ_compound_dict["water"] = self._water

        eq_reaction = Reaction.parse_formula(eQ_compound_dict.get, reaction_string)

        return eq_reaction
    def test_atp_hydrolysis(self):
        formula = ' C00002 + C00001  <= C00008 +   C00009'
        kegg_ids = set(('C00002', 'C00001', 'C00008', 'C00009'))
        try:
            reaction = Reaction.parse_formula(formula)
        except ValueError as e:
            self.fail('unable to parse the formula\n' + str(e))

        self.assertSetEqual(set(reaction.kegg_ids()), kegg_ids)
        for kegg_id in kegg_ids:
            self.assertIsNotNone(reaction.get_compound(kegg_id))
            self.assertNotEqual(reaction.get_coeff(kegg_id), 0)
        self.assertIsNone(reaction.get_compound('C00003'))
        self.assertEqual(reaction.get_coeff('C00003'), 0)
 def get_best_match(self, parsed_query):
     kegg_id_to_coeff = []
     for coeff, name in parsed_query.substrates:
         comp_matches = self._compound_matcher.match(name)
         if comp_matches is None:
             raise ParseError('Cannot match this substrate at all: ' + name)
         kegg_id_to_coeff.append((comp_matches.CID.iat[0], -coeff))
     for coeff, name in parsed_query.products:
         comp_matches = self._compound_matcher.match(name)
         if comp_matches is None:
             raise ParseError('Cannot match this product at all: ' + name)
         kegg_id_to_coeff.append((comp_matches.CID.iat[0], coeff))
     
     return Reaction(dict(kegg_id_to_coeff))
    def test_gibbs_energy(self):
        kegg_id_to_coeff = {
            'C00002': -1,
            'C00001': -1,
            'C00008': 1,
            'C00009': 1
        }  # ATP + H2O = ADP + Pi
        reaction = Reaction(kegg_id_to_coeff)

        cc = ComponentContribution(pH=7.0, ionic_strength=0.1)
        dG0_prime, dG0_uncertainty = cc.dG0_prime(reaction)

        self.assertAlmostEqual(dG0_prime, -26.4, 1)
        self.assertAlmostEqual(dG0_uncertainty, 0.6, 1)
Exemple #8
0
 def get_best_match(self, parsed_query):
     kegg_id_to_coeff = defaultdict(int)
     for coeff, name in parsed_query.substrates:
         comp_matches = self._compound_matcher.match(name)
         if comp_matches is None:
             raise ParseError('Cannot match this substrate at all: ' + name)
         kegg_id_to_coeff[comp_matches.CID.iat[0]] -= coeff
     for coeff, name in parsed_query.products:
         comp_matches = self._compound_matcher.match(name)
         if comp_matches is None:
             raise ParseError('Cannot match this product at all: ' + name)
         kegg_id_to_coeff[comp_matches.CID.iat[0]] += coeff
     
     # if compounds appear more than once (e.g. on both sides of a reaction
     # we need to sum up the coresponding coefficients)
     kegg_id_to_coeff = dict(filter(lambda x: x[1], kegg_id_to_coeff.items()))
     
     return Reaction(kegg_id_to_coeff)
Exemple #9
0
def reaction_gibbs(equation, dfG_dict=None, pH=7.0, eq_api=None):
    """Calculate standard Gibbs reaction energy."""
    # Remove compartment tags from compound IDs
    equation = re.sub("_\[[a-z]{3}\]", "", equation)
    equation = re.sub("_[a-z]{1}", "", equation)
    if dfG_dict:
        s = parse_equation(equation)
        if None in [dfG_dict[c[1]] for c in s[0] + s[1]]:
            # Cannot calculate drG when dfG is missing
            return None
        else:
            p = sum([c[0] * Decimal(str(dfG_dict[c[1]])) for c in s[1]])
            r = sum([c[0] * Decimal(str(dfG_dict[c[1]])) for c in s[0]])
            return float(p - r)
    else:
        # Use Equilibrator API
        if not eq_api:
            eq_api = ComponentContribution(pH=pH, ionic_strength=0.1)
        rxn = Reaction.parse_formula(equation)
        return round(eq_api.dG0_prime(rxn)[0], 1)
    def test_gibbs_energy(self):
        warnings.simplefilter('ignore', ResourceWarning)

        kegg_id_to_coeff = {'C00002' : -1, 'C00001' : -1,
                            'C00008' :  1, 'C00009' :  1} # ATP + H2O = ADP + Pi
        kegg_id_to_conc  = {'C00002' : 1e-3,
                            'C00009' :  1e-4}
        reaction = Reaction(kegg_id_to_coeff)

        cc = ComponentContribution(pH=7.0, ionic_strength=0.1)
        dG0_prime, dG0_uncertainty = cc.dG0_prime(reaction)
        
        self.assertAlmostEqual(dG0_prime, -26.4, 1)
        self.assertAlmostEqual(dG0_uncertainty, 0.6, 1)
        
        dG_prime, _ = cc.dG_prime(reaction, kegg_id_to_conc)
        self.assertAlmostEqual(dG_prime, -32.1, 1)

        dGm_prime, _ = cc.dGm_prime(reaction)
        self.assertAlmostEqual(dGm_prime, -43.5, 1)
Exemple #11
0
def predict_dG(model, pH=7, ionic_strength=0.1, fn=None):
    eq_api = ComponentContribution(pH=7.0, ionic_strength=0.1)
    lst = []
    for r in model.reactions:
        kegg_string = build_kegg_string(r)
        if kegg_string:
            try:
                rxn = Reaction.parse_formula(kegg_string)
            except KeyError:
                print("eQuilibrator could not predict dG for {0}".format(r.id))
                continue
            # eq_api.dG0_prime(rxn)
            try:
                dgm = eq_api.dGm_prime(rxn)
                dg0 = eq_api.dG0_prime(rxn)
            except:
                print("eQuilibrator could not predict dG for {0}".format(r.id))
            else:
                if dgm[-1] > dGMm_STD_THRESHOLD:
                    print(
                        "eQuilibrator could not predict dG for {0} with a reasonable uncertainty"
                        .format(r.id))
                    continue
                print(r.id, dgm)
                lst.append([
                    r.id, r.name, r.annotation["kegg.reaction"],
                    parse_reversibility(r), *dg0, *dgm
                ])
    # Store as df
    df = pd.DataFrame(lst)
    df.columns = [
        "Rxn", "Rxn Name", "Rxn KEGG ID", "Reversibility in model",
        "dG0_prime", "dG0_prime_std", "dGm_prime", "dGm_prime_std"
    ]
    if not fn:
        fn = "eQuilibrator_reversibility.csv"
    df.to_csv(fn, index=False, sep=",")
    print("Found the dG for {0} of {1} reactions".format(
        len(lst), len(model.reactions)))
    return lst
    for rgt in rxn_cpds_array:
        if (rgt['compound'] not in seed_mnx_structural_map):
            OK = False
        else:
            mnx_id = seed_mnx_structural_map[rgt['compound']]

            if (rgt['coefficient'] < 0):
                lhs[mnx_id] = math.fabs(rgt['coefficient'])
            elif (rgt['coefficient'] > 0):
                rhs[mnx_id] = math.fabs(rgt['coefficient'])

    equation_str = ' + '.join([f'{value} {key}' for key, value in lhs.items()]) + \
        " = " + \
        ' + '.join([f'{value} {key}' for key, value in rhs.items()])

    equilibrator_reaction = Reaction.parse_formula(ccache.get_compound,
                                                   equation_str)

    try:
        result = equilibrator_calculator.standard_dg_prime(
            equilibrator_reaction)
        dG0_prime = str(result.value.to('kilocal / mole').magnitude)
        uncertainty = str(result.error.to('kilocal / mole').magnitude)

        ln_RI = equilibrator_calculator.ln_reversibility_index(
            equilibrator_reaction)
        if not type(ln_RI) == float:
            ln_RI = str(ln_RI.magnitude)

        output_handle.write("\t".join([rxn, dG0_prime, uncertainty, ln_RI]) +
                            "\n")
    except Exception as e:
Exemple #13
0
                        default=0.1)
    parser.add_argument('--ph', type=float, help='pH level', default=7.0)
    logging.getLogger().setLevel(logging.WARNING)

    args = parser.parse_args()

    sys.stderr.write('pH = %.1f\n' % args.ph)
    sys.stderr.write('I = %.1f M\n' % args.i)

    ids = []
    reactions = []
    with open('data/iJO1366_reactions.csv', 'r') as f:
        for row in csv.DictReader(f):
            ids.append(row['bigg.reaction'])
            try:
                reactions.append(Reaction.parse_formula(row['formula']))
            except ValueError as e:
                print('warning: cannot parse reaction %s because of %s' %
                      (row['bigg.reaction'], str(e)))
                reactions.append(Reaction({}))
                continue

    equilibrator = ComponentContribution(pH=args.ph, ionic_strength=args.i)

    dG0_prime, U = equilibrator.dG0_prime_multi(reactions)

    writer = csv.writer(args.outfile)
    header = [
        'reaction', 'pH', 'ionic strength [M]', 'dG\'0 [kJ/mol]',
        'uncertainty [kJ/mol]', 'ln(Reversibility Index)', 'comment'
    ]
Exemple #14
0
                                                ionic_strength=Q_("0.25M"),
                                                temperature=Q_("298.15K"))

structures_root = os.path.dirname(__file__) + "/../../Biochemistry/Structures/"
thermodynamics_root = os.path.dirname(
    __file__) + "/../../Biochemistry/Thermodynamics/"
file_name = structures_root + 'MetaNetX/Structures_in_ModelSEED_and_eQuilibrator.txt'
output_name = thermodynamics_root + 'eQuilibrator/MetaNetX_Compound_Energies.tbl'
output_handle = open(output_name, 'w')
mnx_inchikey_dict = dict()
with open(file_name) as file_handle:
    for line in file_handle.readlines():
        line = line.strip()
        (mnx, inchikey) = line.split('\t')

        equilibrator_reaction = Reaction.parse_formula(ccache.get_compound,
                                                       ' = ' + mnx)

        try:
            result = equilibrator_calculator.standard_dg_prime(
                equilibrator_reaction)
            dG0_prime = str(result.value.to('kilocal / mole').magnitude)
            uncertainty = str(result.error.to('kilocal / mole').magnitude)

            output_handle.write("\t".join([mnx, dG0_prime, uncertainty]) +
                                "\n")
        except Exception as e:
            output_handle.write("\t".join([mnx, "Unable to retrieve energy"]) +
                                "\n")
            print(e)
Exemple #15
0
#Main Script
eq_api = ComponentContribution(pH=7.5, ionic_strength=0.1)
#Load model data file
os.chdir(ECM_path+'/Models')
data  = pd.read_table('KEGGmodelScaffold.txt')
os.chdir(ECM_path)
i=0
output     = '!!SBtab TableName=Parameter TableType=Quantity Document=S. cervisiae central carbon metabolism SBtabVersion=1.0'+'\n'
output     = output+ '!QuantityType'+'\t'+'!Reaction'+'\t'+'!Compound'+'\t'+'!Value'+'\t'+'!Unit'+'\t'+'!Reaction:Identifiers:kegg.reaction'+'\t'+'!Compound:Identifiers:kegg.compound'+'\t'+'!ID'+'\n'
unit       = 'dimensionless'
compound   = ' '
compoundID = ' '
type       = 'equilibrium constant'

for formula in data.ReactionFormula:
    rxn         = Reaction.parse_formula(formula)
    name        = str(data.ID[i])
    KEGGID      = str(data.KEGGIDs[i])
    reactionStr = name#+'_'+KEGGID    
    parameterID = 'kEQ_'+name
    print(name)
    #Check if reaction is atomically balanced
    if not rxn.check_full_reaction_balancing():
        print('%s is not balanced' % name)
        #raw_input("Press the <ENTER> key to continue...")
        print(' ')
    i = i+1
    #Get standard Gibbs free energy for the rxn
    dG0_prime, dG0_uncertainty = eq_api.dG0_prime(rxn)
    if name == 'RIP1':
        dG0_prime = -38.46 #Edda Klipp's work
Exemple #16
0

###############################################################################
parser = MakeParser()
args = parser.parse_args()

logging.getLogger().setLevel(logging.WARNING)

sys.stderr.write('pH = %.1f\n' % args.ph)
sys.stderr.write('I = %.1f M\n' % args.i)
sys.stderr.write('Reaction: %s\n' % args.reaction)
sys.stderr.flush()

# parse the reaction
try:
    reaction = Reaction.parse_formula(args.reaction)
except ValueError as e:
    logging.error(str(e))
    sys.exit(-1)

equilibrator = ComponentContribution(pH=args.ph, ionic_strength=args.i)

n_e = reaction.check_half_reaction_balancing()
if n_e is None:
    logging.error('reaction is not chemically balanced')
    sys.exit(-1)
elif n_e == 0:
    dG0_prime, dG0_uncertainty = equilibrator.dG0_prime(reaction)
    sys.stdout.write(u'\u0394G\'\u00B0 = %.1f \u00B1 %.1f kJ/mol\n' %
                     (dG0_prime, dG0_uncertainty))
Exemple #17
0
def find_thermodynamic_reversibility_index(reactions):
    u"""
    Return the reversibility index of the given reactions.

    To determine the reversibility index, we calculate
    the reversibility index ln_gamma (see [1]_ section 3.5) of each reaction
    using the eQuilibrator API [2]_.

    Parameters
    ----------
        reactions: list of cobra.Reaction
            A list of reactions for which to calculate the reversibility index.

    Returns
    -------
    tuple
        list of cobra.Reaction, index pairs
            A list of pairs of reactions and their reversibility indexes.
        list of cobra.Reaction
            A list of reactions which contain at least one metabolite that
            could not be mapped to KEGG on the basis of its annotation.
        list of cobra.Reaction
            A list of reactions for which it is not possible to calculate the
            standard change in Gibbs free energy potential. Reasons of failure
            include that participating metabolites cannot be broken down with
            the group contribution method.
        list of cobra.Reaction
            A list of reactions that are not chemically or redox balanced.


    References
    ----------
    .. [1] Elad Noor, Arren Bar-Even, Avi Flamholz, Yaniv Lubling, Dan Davidi,
           Ron Milo; An integrated open framework for thermodynamics of
           reactions that combines accuracy and coverage, Bioinformatics,
           Volume 28, Issue 15, 1 August 2012, Pages 2037–2044,
           https://doi.org/10.1093/bioinformatics/bts317
    .. [2] https://pypi.org/project/equilibrator-api/

    """
    incomplete_mapping = []
    problematic_calculation = []
    reversibility_indexes = []
    unbalanced = []
    metabolite_mapping = {}

    for rxn in reactions:
        stoich = translate_reaction(rxn, metabolite_mapping)
        if len(stoich) < len(rxn.metabolites):
            incomplete_mapping.append(rxn)
            continue
        try:
            # Remove protons from stoichiometry.
            if "C00080" in stoich:
                del stoich["C00080"]
            eq_rxn = Reaction(stoich, rxn.id)
        except KeyError:
            incomplete_mapping.append(rxn)
            continue
        if eq_rxn.check_full_reaction_balancing():
            try:
                ln_rev_index = eq_rxn.reversibility_index()
            # TODO (Moritz Beber): Which exceptions can we expect here?
            except Exception:
                problematic_calculation.append(rxn)
                continue
            reversibility_indexes.append((rxn, ln_rev_index))
        else:
            unbalanced.append(rxn)
    reversibility_indexes.sort(key=lambda p: abs(p[1]), reverse=True)
    return (reversibility_indexes, incomplete_mapping, problematic_calculation,
            unbalanced)
Exemple #18
0
def find_thermodynamic_reversibility_index(reactions):
    u"""
    Return the reversibility index of the given reactions.

    To determine the reversibility index, we calculate
    the reversibility index ln_gamma (see [1]_ section 3.5) of each reaction
    using the eQuilibrator API [2]_.

    Parameters
    ----------
        reactions: list of cobra.Reaction
            A list of reactions for which to calculate the reversibility index.

    Returns
    -------
    tuple
        list of cobra.Reaction, index pairs
            A list of pairs of reactions and their reversibility indexes.
        list of cobra.Reaction
            A list of reactions which contain at least one metabolite that
            could not be mapped to KEGG on the basis of its annotation.
        list of cobra.Reaction
            A list of reactions for which it is not possible to calculate the
            standard change in Gibbs free energy potential. Reasons of failure
            include that participating metabolites cannot be broken down with
            the group contribution method.
        list of cobra.Reaction
            A list of reactions that are not chemically or redox balanced.


    References
    ----------
    .. [1] Elad Noor, Arren Bar-Even, Avi Flamholz, Yaniv Lubling, Dan Davidi,
           Ron Milo; An integrated open framework for thermodynamics of
           reactions that combines accuracy and coverage, Bioinformatics,
           Volume 28, Issue 15, 1 August 2012, Pages 2037–2044,
           https://doi.org/10.1093/bioinformatics/bts317
    .. [2] https://pypi.org/project/equilibrator-api/

    """
    incomplete_mapping = []
    problematic_calculation = []
    reversibility_indexes = []
    unbalanced = []
    metabolite_mapping = {}

    for rxn in reactions:
        stoich = translate_reaction(rxn, metabolite_mapping)
        if len(stoich) < len(rxn.metabolites):
            incomplete_mapping.append(rxn)
            continue
        try:
            # Remove protons from stoichiometry.
            if "C00080" in stoich:
                del stoich["C00080"]
            eq_rxn = Reaction(stoich, rxn.id)
        except KeyError:
            incomplete_mapping.append(rxn)
            continue
        if eq_rxn.check_full_reaction_balancing():
            try:
                ln_rev_index = eq_rxn.reversibility_index()
            # TODO (Moritz Beber): Which exceptions can we expect here?
            except Exception:
                problematic_calculation.append(rxn)
                continue
            reversibility_indexes.append((rxn, ln_rev_index))
        else:
            unbalanced.append(rxn)
    reversibility_indexes.sort(key=lambda p: abs(p[1]), reverse=True)
    return (
        reversibility_indexes, incomplete_mapping, problematic_calculation,
        unbalanced
    )