PyCoMo CycleBreaker
This tutorial show-cases the use of CycleBreaker. Here, efmtool is used to enumerate all WONCY cycles (witout net conversion cycles), and then binary variables are used to forbid all reactions of a cycle being active at the same time - in turn breaking the cycle.
The expected runtime for this notebook is less than 10 minutes.
[1]:
import cobra
[2]:
import pycomo
pycomo.configure_logger(level="info")
2026-03-15 13:31:31,852 - PyCoMo - INFO - Logger initialized.
[3]:
conf = cobra.Configuration()
conf.solver = "gurobi"
conf.processes = 8
Model import
We are using two genome-scale models of the AGORA2 collection:
Bacteroides stercoris ERR2230062
Blautia torques ERR1022325
[4]:
test_model_dir = "../data/use_case/cyclebreaker"
named_models = pycomo.load_named_models_from_dir(test_model_dir, file_format="mat")
Set parameter Username
Set parameter LicenseID to value 2696585
Academic license - for non-commercial use only - expires 2026-08-19
No defined compartments in model model. Compartments will be deduced heuristically using regular expressions.
Using regular expression found the following compartments:c, e, p
No defined compartments in model model. Compartments will be deduced heuristically using regular expressions.
Using regular expression found the following compartments:c, e
[5]:
named_models
[5]:
{'Bacteroides_stercoris_ERR2230062': <Model model at 0x7f29fd6d3a00>,
'Blautia_torques_ERR1022325': <Model model at 0x7f29fda5c100>}
[6]:
single_org_models = []
for name, model in named_models.items():
print(name)
single_org_model = pycomo.SingleOrganismModel(model, name)
single_org_models.append(single_org_model)
Bacteroides_stercoris_ERR2230062
Read LP format model from file /tmp/tmp2p6n4a2_.lp
Reading time = 0.01 seconds
: 1174 rows, 2510 columns, 10030 nonzeros
Blautia_torques_ERR1022325
Read LP format model from file /tmp/tmp9f2lyns4.lp
Reading time = 0.01 seconds
: 1034 rows, 2358 columns, 10044 nonzeros
[7]:
community_name = "cyclebreaker_test"
com_model_obj = pycomo.CommunityModel(single_org_models, community_name)
[8]:
com_model_obj.summary()
2026-03-15 13:31:39,148 - PyCoMo - INFO - No community model generated yet. Generating now:
Read LP format model from file /tmp/tmpm8nnnw4k.lp
Reading time = 0.01 seconds
: 1174 rows, 2510 columns, 10030 nonzeros
2026-03-15 13:31:41,165 - PyCoMo - INFO - Identified biomass reaction from objective: bio1
2026-03-15 13:31:41,166 - PyCoMo - INFO - Note: no products in the objective function, adding biomass to it.
Read LP format model from file /tmp/tmp0w0qe80u.lp
Reading time = 0.01 seconds
: 1034 rows, 2358 columns, 10044 nonzeros
2026-03-15 13:31:59,241 - PyCoMo - INFO - Identified biomass reaction from objective: bio1
2026-03-15 13:31:59,242 - PyCoMo - INFO - Note: no products in the objective function, adding biomass to it.
Read LP format model from file /tmp/tmpwwgf8mec.lp
Reading time = 0.03 seconds
: 2829 rows, 5946 columns, 20512 nonzeros
Read LP format model from file /tmp/tmps2dub8ux.lp
Reading time = 0.06 seconds
: 5927 rows, 12308 columns, 42154 nonzeros
2026-03-15 13:32:27,862 - PyCoMo - WARNING - Not all reactions in the model are mass and charge balanced. To check which reactions are imbalanced, please run the get_unbalanced_reactions method of this CommunityModel object
2026-03-15 13:32:27,863 - PyCoMo - INFO - Generated community model.
[8]:
Objective
1.0 community_biomass = 1.0
Uptake
| Metabolite | Reaction | Flux | C-Number | C-Flux |
|---|---|---|---|---|
| _26dap_M_medium | EX__26dap_M_medium | 0.02501 | 7 | 0.16% |
| ade_medium | EX_ade_medium | 0.1476 | 5 | 0.69% |
| ala_D_medium | EX_ala_D_medium | 0.1313 | 3 | 0.37% |
| ala_L_medium | EX_ala_L_medium | 0.322 | 3 | 0.91% |
| arg_L_medium | EX_arg_L_medium | 0.2467 | 6 | 1.39% |
| asn_L_medium | EX_asn_L_medium | 0.2008 | 4 | 0.75% |
| asp_L_medium | EX_asp_L_medium | 0.3608 | 4 | 1.36% |
| ca2_medium | EX_ca2_medium | 0.003096 | 0 | 0.00% |
| cgly_medium | EX_cgly_medium | 0.003096 | 5 | 0.01% |
| cl_medium | EX_cl_medium | 0.003096 | 0 | 0.00% |
| cobalt2_medium | EX_cobalt2_medium | 0.003096 | 0 | 0.00% |
| csn_medium | EX_csn_medium | 0.207 | 4 | 0.78% |
| cu2_medium | EX_cu2_medium | 0.003096 | 0 | 0.00% |
| cys_L_medium | EX_cys_L_medium | 0.08234 | 3 | 0.23% |
| fe2_medium | EX_fe2_medium | 0.006193 | 0 | 0.00% |
| fe3_medium | EX_fe3_medium | 0.003096 | 0 | 0.00% |
| fol_medium | EX_fol_medium | 0.00929 | 19 | 0.17% |
| gln_L_medium | EX_gln_L_medium | 0.2222 | 5 | 1.04% |
| glu_L_medium | EX_glu_L_medium | 0.2689 | 5 | 1.26% |
| glyleu_medium | EX_glyleu_medium | 0.4606 | 8 | 3.46% |
| gncore2_medium | EX_gncore2_medium | 0.0587 | 30 | 1.65% |
| gua_medium | EX_gua_medium | 0.1486 | 5 | 0.70% |
| his_L_medium | EX_his_L_medium | 0.07926 | 6 | 0.45% |
| ile_L_medium | EX_ile_L_medium | 0.327 | 6 | 1.84% |
| k_medium | EX_k_medium | 0.003096 | 0 | 0.00% |
| lys_L_medium | EX_lys_L_medium | 0.2854 | 6 | 1.61% |
| metala_medium | EX_metala_medium | 0.1309 | 8 | 0.98% |
| mg2_medium | EX_mg2_medium | 0.003096 | 0 | 0.00% |
| mn2_medium | EX_mn2_medium | 0.003096 | 0 | 0.00% |
| mqn7_medium | EX_mqn7_medium | 0.003096 | 46 | 0.13% |
| mqn8_medium | EX_mqn8_medium | 0.003096 | 51 | 0.15% |
| nac_medium | EX_nac_medium | 0.006193 | 6 | 0.03% |
| o2_medium | EX_o2_medium | 10.09 | 0 | 0.00% |
| ocdca_medium | EX_ocdca_medium | 0.08518 | 18 | 1.44% |
| phe_L_medium | EX_phe_L_medium | 0.1545 | 9 | 1.31% |
| pheme_medium | EX_pheme_medium | 0.003096 | 34 | 0.10% |
| pi_medium | EX_pi_medium | 1.018 | 0 | 0.00% |
| pnto_R_medium | EX_pnto_R_medium | 0.006193 | 9 | 0.05% |
| pro_L_medium | EX_pro_L_medium | 0.1844 | 5 | 0.87% |
| ptrc_medium | EX_ptrc_medium | 0.003096 | 4 | 0.01% |
| ribflv_medium | EX_ribflv_medium | 0.006193 | 17 | 0.10% |
| ser_L_medium | EX_ser_L_medium | 0.2607 | 3 | 0.73% |
| so4_medium | EX_so4_medium | 0.003096 | 0 | 0.00% |
| spmd_medium | EX_spmd_medium | 0.003096 | 7 | 0.02% |
| stys_medium | EX_stys_medium | 0.04594 | 24 | 1.04% |
| sucr_medium | EX_sucr_medium | 6.375 | 12 | 71.86% |
| thm_medium | EX_thm_medium | 0.003097 | 12 | 0.03% |
| thr_L_medium | EX_thr_L_medium | 0.2111 | 4 | 0.79% |
| trp_L_medium | EX_trp_L_medium | 0.0472 | 11 | 0.49% |
| tyr_L_medium | EX_tyr_L_medium | 0.1207 | 9 | 1.02% |
| zn2_medium | EX_zn2_medium | 0.003096 | 0 | 0.00% |
Secretion
| Metabolite | Reaction | Flux | C-Number | C-Flux |
|---|---|---|---|---|
| Blautia_torques_ERR1022325_biomass_Blautia_torques_ERR1022325_c | Blautia_torques_ERR1022325_EX_biomass_e_Blautia_torques_ERR1022325_c | -1 | 0 | 0.00% |
| T_antigen_medium | EX_T_antigen_medium | -0.0587 | 14 | 1.19% |
| ac_medium | EX_ac_medium | -22.08 | 2 | 63.90% |
| co2_medium | EX_co2_medium | -1.024 | 1 | 1.48% |
| for_medium | EX_for_medium | -23.11 | 1 | 33.43% |
| h2o_medium | EX_h2o_medium | -1.089 | 0 | 0.00% |
| h_medium | EX_h_medium | -43.61 | 0 | 0.00% |
| nh4_medium | EX_nh4_medium | -0.09402 | 0 | 0.00% |
| cpd11416_medium | community_biomass | -1 | 0 | 0.00% |
Cycle enumeration
[9]:
cycles = pycomo.helper.cyclebreaker.enumerate_cycles_in_com_model(com_model_obj)
CycleBreaker
Test flux without medium
Check how many external reactions can carry flux without a medium present. These reactionse are part of a cycle.
[10]:
com_model_obj.medium = {}
[11]:
fva_no_medium = com_model_obj.run_fva(fva_mu_c=0) # FVA on all external reactions
2026-03-15 13:33:36,635 - PyCoMo - INFO - Logger initialized.
Set parameter Username
Set parameter LicenseID to value 2696585
Academic license - for non-commercial use only - expires 2026-08-19
Read LP format model from file /tmp/tmpiy9cqh6s.lp
Reading time = 0.06 seconds
: 5928 rows, 12309 columns, 42153 nonzeros
2026-03-15 13:33:39,428 - PyCoMo - INFO - Logger initialized.
Set parameter Username
Set parameter LicenseID to value 2696585
Academic license - for non-commercial use only - expires 2026-08-19
Read LP format model from file /tmp/tmpg6fq4jdx.lp
Reading time = 0.07 seconds
: 5928 rows, 12309 columns, 42153 nonzeros
2026-03-15 13:33:42,196 - PyCoMo - INFO - Logger initialized.
Set parameter Username
Set parameter LicenseID to value 2696585
Academic license - for non-commercial use only - expires 2026-08-19
Read LP format model from file /tmp/tmp9wj5v4ut.lp
Reading time = 0.06 seconds
: 5928 rows, 12309 columns, 42153 nonzeros
2026-03-15 13:33:44,613 - PyCoMo - INFO - Logger initialized.
Set parameter Username
Set parameter LicenseID to value 2696585
Academic license - for non-commercial use only - expires 2026-08-19
Read LP format model from file /tmp/tmp0q0k7log.lp
Reading time = 0.06 seconds
: 5928 rows, 12309 columns, 42153 nonzeros
2026-03-15 13:33:47,450 - PyCoMo - INFO - Logger initialized.
Set parameter Username
Set parameter LicenseID to value 2696585
Academic license - for non-commercial use only - expires 2026-08-19
Read LP format model from file /tmp/tmplyu86s_s.lp
Reading time = 0.07 seconds
: 5928 rows, 12309 columns, 42153 nonzeros
2026-03-15 13:33:50,041 - PyCoMo - INFO - Logger initialized.
Set parameter Username
Set parameter LicenseID to value 2696585
Academic license - for non-commercial use only - expires 2026-08-19
Read LP format model from file /tmp/tmpenjlf0do.lp
Reading time = 0.06 seconds
: 5928 rows, 12309 columns, 42153 nonzeros
2026-03-15 13:33:52,938 - PyCoMo - INFO - Logger initialized.
Set parameter Username
Set parameter LicenseID to value 2696585
Academic license - for non-commercial use only - expires 2026-08-19
Read LP format model from file /tmp/tmp3sz51bpl.lp
Reading time = 0.06 seconds
: 5928 rows, 12309 columns, 42153 nonzeros
2026-03-15 13:33:56,294 - PyCoMo - INFO - Logger initialized.
Set parameter Username
Set parameter LicenseID to value 2696585
Academic license - for non-commercial use only - expires 2026-08-19
Read LP format model from file /tmp/tmpdyqilvrf.lp
Reading time = 0.07 seconds
: 5928 rows, 12309 columns, 42153 nonzeros
2026-03-15 13:34:02,169 - PyCoMo - INFO - Processed 20.75% of fva steps
2026-03-15 13:34:05,838 - PyCoMo - INFO - Processed 41.49% of fva steps
2026-03-15 13:34:09,342 - PyCoMo - INFO - Processed 62.24% of fva steps
2026-03-15 13:34:12,723 - PyCoMo - INFO - Processed 82.99% of fva steps
2026-03-15 13:34:15,344 - PyCoMo - INFO - Processed 100.0% of fva steps
Check how many reactions can carry flux (i.e. are not 0)
[12]:
fva_no_medium[(
~fva_no_medium["min_flux"].apply(pycomo.helper.utils.close_to_zero, t=10**-5)
) | (
~fva_no_medium["max_flux"].apply(pycomo.helper.utils.close_to_zero, t=10**-5)
)]
[12]:
| reaction_id | min_flux | max_flux | |
|---|---|---|---|
| Bacteroides_stercoris_ERR2230062_TF_gln_L_Bacteroides_stercoris_ERR2230062_e | Bacteroides_stercoris_ERR2230062_TF_gln_L_Bact... | -500.0 | 500.0 |
| Bacteroides_stercoris_ERR2230062_TF_glu_L_Bacteroides_stercoris_ERR2230062_e | Bacteroides_stercoris_ERR2230062_TF_glu_L_Bact... | -500.0 | 500.0 |
| Bacteroides_stercoris_ERR2230062_TF_h2o_Bacteroides_stercoris_ERR2230062_e | Bacteroides_stercoris_ERR2230062_TF_h2o_Bacter... | -500.0 | 500.0 |
| Bacteroides_stercoris_ERR2230062_TF_nh4_Bacteroides_stercoris_ERR2230062_e | Bacteroides_stercoris_ERR2230062_TF_nh4_Bacter... | -500.0 | 500.0 |
| Blautia_torques_ERR1022325_TF_gln_L_Blautia_torques_ERR1022325_e | Blautia_torques_ERR1022325_TF_gln_L_Blautia_to... | -500.0 | 500.0 |
| Blautia_torques_ERR1022325_TF_glu_L_Blautia_torques_ERR1022325_e | Blautia_torques_ERR1022325_TF_glu_L_Blautia_to... | -500.0 | 500.0 |
| Blautia_torques_ERR1022325_TF_h2o_Blautia_torques_ERR1022325_e | Blautia_torques_ERR1022325_TF_h2o_Blautia_torq... | -500.0 | 500.0 |
| Blautia_torques_ERR1022325_TF_nh4_Blautia_torques_ERR1022325_e | Blautia_torques_ERR1022325_TF_nh4_Blautia_torq... | -500.0 | 500.0 |
Add CycleBreaker constraints
[13]:
pycomo.helper.cyclebreaker.add_cycle_breaker_constraints_for_all_cycles(com_model_obj, cycles)
[14]:
fva_cyclebreaker = com_model_obj.run_fva(fva_mu_c=0) # FVA on all external reactions
2026-03-15 13:34:20,846 - PyCoMo - INFO - Logger initialized.
Set parameter Username
Set parameter LicenseID to value 2696585
Academic license - for non-commercial use only - expires 2026-08-19
Read LP format model from file /tmp/tmpwq8e71ns.lp
Reading time = 0.07 seconds
: 6195 rows, 12464 columns, 43877 nonzeros
2026-03-15 13:34:23,254 - PyCoMo - INFO - Logger initialized.
Set parameter Username
Set parameter LicenseID to value 2696585
Academic license - for non-commercial use only - expires 2026-08-19
Read LP format model from file /tmp/tmpneaszex6.lp
Reading time = 0.06 seconds
: 6195 rows, 12464 columns, 43877 nonzeros
2026-03-15 13:34:26,081 - PyCoMo - INFO - Logger initialized.
Set parameter Username
Set parameter LicenseID to value 2696585
Academic license - for non-commercial use only - expires 2026-08-19
Read LP format model from file /tmp/tmp_dpf9zf4.lp
Reading time = 0.06 seconds
: 6195 rows, 12464 columns, 43877 nonzeros
2026-03-15 13:34:28,830 - PyCoMo - INFO - Logger initialized.
Set parameter Username
Set parameter LicenseID to value 2696585
Academic license - for non-commercial use only - expires 2026-08-19
Read LP format model from file /tmp/tmpq5ytleyx.lp
Reading time = 0.06 seconds
: 6195 rows, 12464 columns, 43877 nonzeros
2026-03-15 13:34:31,703 - PyCoMo - INFO - Logger initialized.
Set parameter Username
Set parameter LicenseID to value 2696585
Academic license - for non-commercial use only - expires 2026-08-19
Read LP format model from file /tmp/tmpb97o7bim.lp
Reading time = 0.07 seconds
: 6195 rows, 12464 columns, 43877 nonzeros
2026-03-15 13:34:34,635 - PyCoMo - INFO - Logger initialized.
Set parameter Username
Set parameter LicenseID to value 2696585
Academic license - for non-commercial use only - expires 2026-08-19
Read LP format model from file /tmp/tmp3qgzdj9k.lp
Reading time = 0.06 seconds
: 6195 rows, 12464 columns, 43877 nonzeros
2026-03-15 13:34:38,118 - PyCoMo - INFO - Logger initialized.
Set parameter Username
Set parameter LicenseID to value 2696585
Academic license - for non-commercial use only - expires 2026-08-19
Read LP format model from file /tmp/tmp6v3uryre.lp
Reading time = 0.07 seconds
: 6195 rows, 12464 columns, 43877 nonzeros
2026-03-15 13:34:41,010 - PyCoMo - INFO - Logger initialized.
Set parameter Username
Set parameter LicenseID to value 2696585
Academic license - for non-commercial use only - expires 2026-08-19
Read LP format model from file /tmp/tmp_j33m9f_.lp
Reading time = 0.06 seconds
: 6195 rows, 12464 columns, 43877 nonzeros
2026-03-15 13:37:35,349 - PyCoMo - INFO - Processed 20.75% of fva steps
2026-03-15 13:37:35,379 - PyCoMo - INFO - Processed 41.49% of fva steps
2026-03-15 13:37:35,409 - PyCoMo - INFO - Processed 62.24% of fva steps
2026-03-15 13:37:46,608 - PyCoMo - INFO - Processed 82.99% of fva steps
2026-03-15 13:37:46,621 - PyCoMo - INFO - Processed 100.0% of fva steps
[15]:
fva_cyclebreaker[(
~fva_cyclebreaker["min_flux"].apply(pycomo.helper.utils.close_to_zero, t=10**-5)
) | (
~fva_cyclebreaker["max_flux"].apply(pycomo.helper.utils.close_to_zero, t=10**-5)
)]
[15]:
| reaction_id | min_flux | max_flux |
|---|
Now all cycles are broken and none of the cycle reactions can carry flux!
[ ]: