def get_nan_statistics(model_name: str, model_path: str,
                       dG0_json_path: str) -> None:
    dG0s = json_load(dG0_json_path)
    model = cobra.io.read_sbml_model(model_path)

    num_with_dG0 = 0
    num_dG0_free_exchange_reactions = 0
    num_community_exchanges_with_dG0_0 = 0
    num_is_dG0_free_transporter = 0
    num_is_deactivated_nan_reaction = 0
    dG0s_split_keys = []
    for key in dG0s.keys():
        if "_" in key:
            new_key = "_".join(key.split("_")[:-1])
        else:
            new_key = key
        dG0s_split_keys.append(new_key)
    for reaction in model.reactions:
        if "_DASH_" in reaction.id:
            reaction.id = reaction.id.replace("_DASH_", "__")
        if "_LPAREN_" in reaction.id:
            reaction.id = reaction.id.replace("_LPAREN_", "_")
        if "_RPAREN_" in reaction.id:
            reaction.id = reaction.id.replace("_RPAREN_", "")

        if reaction.id.startswith("EX_") or reaction.id.startswith("EX_C_"):
            num_dG0_free_exchange_reactions += 1
        elif reaction.id.startswith("EXCHG_"):
            num_community_exchanges_with_dG0_0 += 1
        elif ("_" in reaction.id) and ("_".join(reaction.id.split("_")[:-1])
                                       in dG0s_split_keys):
            num_with_dG0 += 1
        elif reaction.id in dG0s_split_keys:
            num_with_dG0 += 1
        elif ("tpp_"
              in reaction.id + "_") or ("t1pp_" in reaction.id + "_") or (
                  "tex_" in reaction.id +
                  "_") or reaction.id.endswith("tpp") or "_".join(
                      reaction.id.split("_")[:-1]).endswith("tex"):
            num_is_dG0_free_transporter += 1
        else:
            num_is_deactivated_nan_reaction += 1

    num_reactions = len(model.reactions)
    print("~" + model_name + "~")
    print("Total number metabolites: " + str(len(model.metabolites)))
    print("Total number reactions: " + str(num_reactions))
    print(num_with_dG0 + num_community_exchanges_with_dG0_0 +
          num_dG0_free_exchange_reactions + num_is_dG0_free_transporter +
          num_is_deactivated_nan_reaction)
    print_statistics("Reactions with dG0: ", num_with_dG0, num_reactions)
    print_statistics("EXCHG reactions with dG0=0: ",
                     num_community_exchanges_with_dG0_0, num_reactions)
    print_statistics("EX/EX_C_ reactions with free dG0: ",
                     num_dG0_free_exchange_reactions, num_reactions)
    print_statistics("Selected transport reactions with free dG0: ",
                     num_is_dG0_free_transporter, num_reactions)
    print_statistics("Deactivated NaN reactions: ",
                     num_is_deactivated_nan_reaction, num_reactions)
Пример #2
0
    exchange_reaction_id_prefix="EX_C_",
    input_metabolite_ids=[(x + "\b").replace("_p\b", "")
                          for x in essential_in_metabolites],
    output_metabolite_ids=[
        (x + "\b").replace("_p\b", "").replace("_c\b", "").replace("\b", "")
        for x in essential_out_metabolites + potential_product_metabolite_ids
    ])
community_model = generate_community_model_with_no_growth(
    community, {
        "ecoli1": 0.5,
        "ecoli2": 0.5
    })

# Separate from commmodelpy: Create dG0 dictionary for ecolicore2double
dG0_data_dict = json_load(
    "./publication_runs/ecoli_models/model_reaction_id_to_dG0_mapping_jsons/reaction_id_to_dG0_mapping_for_ecolicore.json"
)

thermodynamically_excluded_metabolites = ["h2o", "h"]
for reaction in community_model.reactions:
    if reaction.id.startswith("EXCHG_"):
        exclude_reaction = False
        for excluded_metabolite in thermodynamically_excluded_metabolites:
            if reaction.id.endswith("_to_" + excluded_metabolite):
                exclude_reaction = True
        if not exclude_reaction:
            dG0_data_dict[reaction.id] = {}
            dG0_data_dict[reaction.id]["dG0"] = 0
            dG0_data_dict[reaction.id]["uncertainty"] = 0
        is_essential = False
        for essential_metabolite in all_essential_metabolites:
Пример #3
0
            1 / 3,
        })
        model.add_reactions([new_pseudo_reaction_1, new_pseudo_reaction_2])

print("Test TC model with FBA...")
with model:
    model.reactions.get_by_id("EX_C_glc__D_exchg").lower_bound = -10
    print("TC model FBA solution:")
    fba_solution = model.optimize()
    # print(model.summary())
    # for reaction in model.reactions:
    #     if not reaction.id.startswith("EXCHG_"):
    #         continue
    #     if fba_solution.fluxes[reaction.id] != 0:
    #         print(f"{reaction.id}: {fba_solution.fluxes[reaction.id] }")
    print("~~~")

# Store model as SBML
cobra.io.write_sbml_model(
    model,
    "./publication_runs/ecoli_models/publication_sbmls_and_dG0_jsons/iML1515doubleTC_model.xml"
)

# Write new dG0 data
dG0_data_dict = json_load(
    "./publication_runs/ecoli_models/publication_sbmls_and_dG0_jsons/iML1515double_dG0.json"
)
json_write(
    "./publication_runs/ecoli_models/publication_sbmls_and_dG0_jsons/iML1515doubleTC_dG0.json",
    dG0_data_dict)
def create_reaction_id_to_dG0_mapping_json(model: cobra.Model, json_path: str) -> None:
    """Creates a reaction ID<->dG0 mapping using the Equilibrator API.

    This function uses the pregenerated BIGG ID to MetaNetX ID mapping, and
    lets the Equilibrator API calculate the dG0 values for each reaction using
    the MetaNetX IDs for the metabolites.

    This function is specifically written for the E. coli models used in CommModelPy's
    publication as its selection of dG0 values is based on BiGG identifiers and as it
    contains specific dG0 corrections for special reactions as referenced in the
    comments of this function.
    However, the general basis of this function can be easily adapted for other types of models.

    Arguments:
    * model: cobra.Model ~ The cobrapy model instance for which the dG0 mapping shall be created.
    * json_path: str ~ The path to the dG0 JSON that is going to be created.

    Output:
    * No variable but a JSON file with the mapping at json_path
    """
    bigg_id_to_metanetx_id = json_load("./publication_runs/ecoli_models/bigg_id_to_metanetx_mapping_json/bigg_id_to_metanetx_id_mapping_from_iML1515.json")
    reaction_id_dG0_mapping: Dict[str, Dict[str, float]] = {}
    cc = ComponentContribution()
    cc.p_h = Q_(7.0)
    cc.ionic_strength = Q_("0.25M")
    cc.temperature = Q_("298.15K")
    cc.p_mg = Q_(3.0)
    reaction_ids_without_dG0: List[str] = []
    for reaction in model.reactions:
        print("==dG0 GENERATION ATTEMPT FOR REACTION "+reaction.id+"==")
        # Exclude exchange reactions
        if reaction.id.startswith("EX_"):
            print("INFO: Reaction is identified as exchange reaction.")
            print("      No dG0 for this reaction!")
            reaction_ids_without_dG0.append(reaction.id)
            continue
        # Exclude special transport reactions
        if ("tpp_" in reaction.id+"_") or ("t1pp_" in reaction.id+"_") or ("tex_" in reaction.id+"_") or reaction.id.endswith("tex"):
            # tpp: Facilitated transport or (proton) symport
            # t1pp: Facilitated transport or (proton) symport
            # tex: "Via diffusion"
            print("INFO: Reaction is identified as special transport reaction.")
            print("      No dG0 for this reaction!")
            reaction_ids_without_dG0.append(reaction.id)
            continue
        # Exclude demand reactions
        if (reaction.id.startswith("DM_")):
            print("INFO: Reaction is identified as sink (demand) reaction.")
            print("      No dG0 for this reaction!")
            reaction_ids_without_dG0.append(reaction.id)
            continue

        educt_strings: List[str] = []
        product_strings: List[str] = []
        is_metanetx_id_missing = False
        for metabolite in reaction.metabolites.keys():
            base_metabolite_id = "".join(metabolite.id.split("_")[:-1])

            if base_metabolite_id.endswith("BIO"):
                base_metabolite_id = base_metabolite_id[:-len("BIO")]

            if base_metabolite_id not in bigg_id_to_metanetx_id.keys():
                is_metanetx_id_missing = True
                break

            if reaction.metabolites[metabolite] < 0:
                educt_strings.append(str(-reaction.metabolites[metabolite]) + " " + bigg_id_to_metanetx_id[base_metabolite_id])
            else:
                product_strings.append(str(reaction.metabolites[metabolite]) + " " + bigg_id_to_metanetx_id[base_metabolite_id])
        if is_metanetx_id_missing:
            print("INFO: MetanetX ID missing for " + base_metabolite_id)
            print("      No dG0 can be given for this reaction!")
            reaction_ids_without_dG0.append(reaction.id)
            continue
        educt_string = " + ".join(educt_strings)
        product_string = " + ".join(product_strings)
        reaction_string = educt_string + " = " + product_string
        print("Reaction string with MetanetX IDs: " + reaction_string)
        try:
            parsed_reaction = cc.parse_reaction_formula(reaction_string)
        except Exception as e:
            print("INFO: Equilibrator reaction parsing error")
            print(e)
            print("      No dG0 can be given for this reaction!")
            reaction_ids_without_dG0.append(reaction.id)
            continue
        try:
            dG0 = cc.standard_dg_prime(parsed_reaction)
            if dG0.m.s > 10000:
                print("INFO: dG0 standard deviation too high")
                print("      No dG0 can be given for this reaction!")
                reaction_ids_without_dG0.append(reaction.id)
                continue
            else:
                reaction_id_dG0_mapping[reaction.id+"_ecoli1"] = {}
                reaction_id_dG0_mapping[reaction.id+"_ecoli1"]["dG0"] = dG0.m.n
                reaction_id_dG0_mapping[reaction.id+"_ecoli1"]["uncertainty"] = 0
                reaction_id_dG0_mapping[reaction.id+"_ecoli2"] = {}
                reaction_id_dG0_mapping[reaction.id+"_ecoli2"]["dG0"] = dG0.m.n
                reaction_id_dG0_mapping[reaction.id+"_ecoli2"]["uncertainty"] = 0
                reaction_id_dG0_mapping[reaction.id+"_ecoli3"] = {}
                reaction_id_dG0_mapping[reaction.id+"_ecoli3"]["dG0"] = dG0.m.n
                reaction_id_dG0_mapping[reaction.id+"_ecoli3"]["uncertainty"] = 0
            print("dG0 calculation successful \\o/")
            print(f"dG0: {dG0}")
        except Exception as e:
            print("INFO:")
            print(e)
            print("      No dG0 can be given for this reaction!")
            reaction_ids_without_dG0.append(reaction.id)
            continue

        # Membrane-bound reaction corrections according to formula 9 in
        # Hamilton, J. J., Dwivedi, V., & Reed, J. L. (2013).
        # Quantitative assessment of thermodynamic constraints on
        # the solution space of genome-scale metabolic models.
        # Biophysical journal, 105(2), 512-522.
        # Formula is:
        # c_j * F * dPsi - 2.3 * h_j * R * T * dpH
        # c_j = net charge transported from outside to inside
        # h_j = Number of protons transported across membrane
        F = 0.10026  # kJ/mV/mol, or 0.02306; kcal/mV/mol
        dPsi = -130  # mV
        dpH = 0.4  # dimensionless
        R = 8.314e-3  # kJ⋅K⁻1⋅mol⁻1
        T = 298.15  # K
        # c_j and h_j are taken from supplementary table 3
        # of the mentioned publication (Hamilton et al., 2013)
        c_j = 0.0
        h_j = 0.0
        # ATP synthase
        if reaction.id.startswith("ATPS4"):
            c_j = 4.0
            h_j = 4.0
        # NADH dehydrogenases
        elif reaction.id.startswith("NADH16"):
            c_j = -3.5
            h_j = -3.5
        elif reaction.id.startswith("NADH17"):
            c_j = -2.0
            h_j = -2.0
        elif reaction.id.startswith("NADH18"):
            c_j = -2.8
            h_j = -2.8
        # Cytochrome dehydrogenases
        elif reaction.id.startswith("CYTBD"):
            c_j = -2.0
            h_j = -2.0
        elif reaction.id.startswith("CYTBO3"):
            c_j = -2.5
            h_j = -2.5

        if (c_j != 0) and (h_j != 0):
            print("Correcting dG0 for special membrane-bound reaction...")
            dG0_correction = c_j * F * dPsi - 2.3 * h_j * R * T * dpH
            print(f"Correction factor is {dG0_correction}")
            reaction_id_dG0_mapping[reaction.id+"_ecoli1"]["dG0"] += dG0_correction
            reaction_id_dG0_mapping[reaction.id+"_ecoli2"]["dG0"] += dG0_correction
            reaction_id_dG0_mapping[reaction.id+"_ecoli3"]["dG0"] += dG0_correction
            print("New dG0 is " + str(reaction_id_dG0_mapping[reaction.id+"_ecoli1"]["dG0"]))

    num_reactions_without_dG0 = len(reaction_ids_without_dG0)
    print("\n==FINAL STATISTICS==")
    print("No dG0 for the following reactions:")
    print("\n".join(reaction_ids_without_dG0))
    print("Total number: ", str(num_reactions_without_dG0))
    print("Fraction from all reactions: ", num_reactions_without_dG0/len(model.reactions))

    json_write(json_path, reaction_id_dG0_mapping)