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!

[ ]: