def find_metabolites_consumed_with_closed_bounds(model): """ Return metabolites that can be consumed when boundary reactions are closed. Reverse case from 'find_metabolites_produced_with_closed_bounds', just like metabolites should not be produced from nothing, mass should not simply be removed from the model. Parameters ---------- model : cobra.Model The metabolic model under investigation. """ mets_consumed = list() helpers.close_boundaries_sensibly(model) for met in model.metabolites: with model: exch = model.add_boundary(met, type='irrex', reaction_id='IRREX', lb=-1, ub=0) if helpers.run_fba(model, exch.id, direction='min') < 0: mets_consumed.append(met) return mets_consumed
def find_stoichiometrically_balanced_cycles(model): u""" Find metabolic reactions in stoichiometrically balanced cycles (SBCs). Identify forward and reverse cycles by closing all exchanges and using FVA. Parameters ---------- model : cobra.Model The metabolic model under investigation. Notes ----- "SBCs are artifacts of metabolic reconstructions due to insufficient constraints (e.g., thermodynamic constraints and regulatory constraints) [1]_." They are defined by internal reactions that carry flux in spite of closed exchange reactions. References ---------- .. [1] Thiele, I., & Palsson, B. Ø. (2010, January). A protocol for generating a high-quality genome-scale metabolic reconstruction. Nature protocols. Nature Publishing Group. http://doi.org/10.1038/nprot.2009.203 """ helpers.close_boundaries_sensibly(model) fva_result = flux_variability_analysis(model, loopless=False) return fva_result.index[(fva_result["minimum"] == -1) | (fva_result["maximum"] == 1)].tolist()
def find_metabolites_produced_with_closed_bounds(model): """ Return metabolites that can be produced when boundary reactions are closed. Parameters ---------- model : cobra.Model The metabolic model under investigation. """ mets_produced = list() helpers.close_boundaries_sensibly(model) for met in model.metabolites: with model: exch = model.add_boundary(met, type='irrex', reaction_id='IRREX', lb=0, ub=1) if helpers.run_fba(model, exch.id) > 0: mets_produced.append(met) return mets_produced
def detect_energy_generating_cycles(model, metabolite_id): u""" Detect erroneous energy-generating cycles for a a single metabolite. The function will first build a dissipation reaction corresponding to the input metabolite. This reaction is then set as the objective for optimization, after closing all exchanges. If the reaction was able to carry flux, an erroneous energy-generating cycle must be present. In this case a list of reactions with a flux greater than zero is returned. Otherwise, the function returns False. Parameters ---------- model : cobra.Model The metabolic model under investigation. metabolite_id : str The identifier of an energy metabolite. Notes ----- "[...] energy generating cycles (EGC) [...] charge energy metabolites without a source of energy. [...] To efficiently identify the existence of diverse EGCs, we first add a dissipation reaction to the metabolic network for each metabolite used to transmit cellular energy; e.g., for ATP, the irreversible reaction ATP + H2O → ADP + P + H+ is added. These dissipation reactions close any existing energy-generating cycles, thereby converting them to type-III pathways. Fluxes through any of the dissipation reactions at steady state indicate the generation of energy through the metabolic network. Second, all uptake reactions are constrained to zero. The sum of the fluxes through the energy dissipation reactions is now maximized using FBA. For a model without EGCs, these reactions cannot carry any flux without the uptake of nutrients. [1]_." References ---------- .. [1] Fritzemeier, C. J., Hartleb, D., Szappanos, B., Papp, B., & Lercher, M. J. (2017). Erroneous energy-generating cycles in published genome scale metabolic networks: Identification and removal. PLoS Computational Biology, 13(4), 1–14. http://doi.org/10.1371/journal.pcbi.1005494 """ main_comp = helpers.find_compartment_id_in_model(model, 'c') met = helpers.find_met_in_model(model, metabolite_id, main_comp)[0] dissipation_rxn = Reaction('Dissipation') if metabolite_id in ['MNXM3', 'MNXM63', 'MNXM51', 'MNXM121', 'MNXM423']: # build nucleotide-type dissipation reaction dissipation_rxn.add_metabolites({ helpers.find_met_in_model(model, 'MNXM2', main_comp)[0]: -1, helpers.find_met_in_model(model, 'MNXM1', main_comp)[0]: 1, helpers.find_met_in_model(model, 'MNXM9', main_comp)[0]: 1, }) elif metabolite_id in ['MNXM6', 'MNXM10']: # build nicotinamide-type dissipation reaction dissipation_rxn.add_metabolites( {helpers.find_met_in_model(model, 'MNXM1', main_comp)[0]: 1}) elif metabolite_id in [ 'MNXM38', 'MNXM208', 'MNXM191', 'MNXM223', 'MNXM7517', 'MNXM12233', 'MNXM558' ]: # build redox-partner-type dissipation reaction dissipation_rxn.add_metabolites( {helpers.find_met_in_model(model, 'MNXM1', main_comp)[0]: 2}) elif metabolite_id == 'MNXM21': dissipation_rxn.add_metabolites({ helpers.find_met_in_model(model, 'MNXM2', main_comp)[0]: -1, helpers.find_met_in_model(model, 'MNXM1', main_comp)[0]: 1, helpers.find_met_in_model(model, 'MNXM26', main_comp)[0]: 1, }) elif metabolite_id == 'MNXM89557': dissipation_rxn.add_metabolites({ helpers.find_met_in_model(model, 'MNXM2', main_comp)[0]: -1, helpers.find_met_in_model(model, 'MNXM1', main_comp)[0]: 2, helpers.find_met_in_model(model, 'MNXM15', main_comp)[0]: 1, }) dissipation_product = helpers.find_met_in_model( model, ENERGY_COUPLES[metabolite_id], main_comp)[0] dissipation_rxn.add_metabolites({met: -1, dissipation_product: 1}) helpers.close_boundaries_sensibly(model) model.add_reactions([dissipation_rxn]) model.objective = dissipation_rxn solution = model.optimize(raise_error=True) if solution.objective_value > 0.0: return solution.fluxes[solution.fluxes.abs() > 0.0].index. \ drop(["Dissipation"]).tolist() else: return []
def detect_energy_generating_cycles(model, metabolite_id): u""" Detect erroneous energy-generating cycles for a a single metabolite. The function will first build a dissipation reaction corresponding to the input metabolite. This reaction is then set as the objective for optimization, after closing all exchanges. If the reaction was able to carry flux, an erroneous energy-generating cycle must be present. In this case a list of reactions with a flux greater than zero is returned. Otherwise, the function returns False. Parameters ---------- model : cobra.Model The metabolic model under investigation. metabolite_id : str The identifier of an energy metabolite. Notes ----- "[...] energy generating cycles (EGC) [...] charge energy metabolites without a source of energy. [...] To efficiently identify the existence of diverse EGCs, we first add a dissipation reaction to the metabolic network for each metabolite used to transmit cellular energy; e.g., for ATP, the irreversible reaction ATP + H2O → ADP + P + H+ is added. These dissipation reactions close any existing energy-generating cycles, thereby converting them to type-III pathways. Fluxes through any of the dissipation reactions at steady state indicate the generation of energy through the metabolic network. Second, all uptake reactions are constrained to zero. The sum of the fluxes through the energy dissipation reactions is now maximized using FBA. For a model without EGCs, these reactions cannot carry any flux without the uptake of nutrients. [1]_." References ---------- .. [1] Fritzemeier, C. J., Hartleb, D., Szappanos, B., Papp, B., & Lercher, M. J. (2017). Erroneous energy-generating cycles in published genome scale metabolic networks: Identification and removal. PLoS Computational Biology, 13(4), 1–14. http://doi.org/10.1371/journal.pcbi.1005494 """ met = model.metabolites.get_by_id(metabolite_id) dissipation_product = model.metabolites.get_by_id(ENERGY_COUPLES[met.id]) dissipation_rxn = Reaction('Dissipation') model = helpers.close_boundaries_sensibly(model) model.add_reactions([dissipation_rxn]) if met.id in ['atp_c', 'ctp_c', 'gtp_c', 'utp_c', 'itp_c']: # build nucleotide-type dissipation reaction dissipation_rxn.reaction = "h2o_c --> h_c + pi_c" elif met.id in ['nadph_c', 'nadh_c']: # build nicotinamide-type dissipation reaction dissipation_rxn.reaction = "--> h_c" elif met.id in [ 'fadh2_c', 'fmnh2_c', 'q8h2_c', 'mql8_c', 'mql6_c', 'mql7_c', 'dmmql8_c' ]: # build redox-partner-type dissipation reaction dissipation_rxn.reaction = "--> 2 h_c" elif met.id == 'accoa_c': dissipation_rxn.reaction = "h2o_c --> h_c + ac_c" elif met.id == 'glu__L_c': dissipation_rxn.reaction = "h2o_c --> 2 h_c + nh3_c" elif met.id == 'h_p': pass dissipation_rxn.add_metabolites({met.id: -1, dissipation_product: 1}) model.objective = dissipation_rxn solution = model.optimize() if solution.status == 'infeasible': raise RuntimeError("The model cannot be solved as the solver status is" "infeasible. This may be a bug.") elif solution.objective_value > 0.0: return solution.fluxes[solution.fluxes.abs() > 0.0].index. \ drop(["Dissipation"]).tolist() else: return []