From ff86a416fb35b6ef97050e5538731a11a874479f Mon Sep 17 00:00:00 2001 From: CompatHelper Julia Date: Mon, 10 Jun 2024 01:18:11 +0000 Subject: [PATCH 1/7] CompatHelper: bump compat for AbstractFBCModels to 0.3, (keep existing compat) --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 9ba9a8ae..fbe84ea2 100644 --- a/Project.toml +++ b/Project.toml @@ -17,7 +17,7 @@ SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3" [compat] -AbstractFBCModels = "0.2.2" +AbstractFBCModels = "0.2.2, 0.3" Aqua = "0.7" Clarabel = "0.6" ConstraintTrees = "1.1" From 0d66747044263a8901dd4676cf27b49475a8b46c Mon Sep 17 00:00:00 2001 From: Mirek Kratochvil Date: Mon, 10 Jun 2024 14:43:09 +0200 Subject: [PATCH 2/7] add coupling support (needs tests) --- Project.toml | 2 +- src/frontend/balance.jl | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index fbe84ea2..b394b270 100644 --- a/Project.toml +++ b/Project.toml @@ -17,7 +17,7 @@ SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3" [compat] -AbstractFBCModels = "0.2.2, 0.3" +AbstractFBCModels = "0.3" Aqua = "0.7" Clarabel = "0.6" ConstraintTrees = "1.1" diff --git a/src/frontend/balance.jl b/src/frontend/balance.jl index 51ba0906..2611d9e9 100644 --- a/src/frontend/balance.jl +++ b/src/frontend/balance.jl @@ -52,6 +52,9 @@ function flux_balance_constraints( stoi = A.stoichiometry(model) bal = A.balance(model) obj = A.objective(model) + cpls = Symbol.(A.couplings(model)) + cT = SparseArrays.SparseMtrisCSC(A.coupling(model)') + clbs, cubs = A.coupling_bounds(model) # The iteration through stoichiometry would be better done with eachrow(), # unfortunately it seems to be enormously inefficient on column-major @@ -70,6 +73,14 @@ function flux_balance_constraints( bound = C.EqualTo(b), ) for (met, row_idx, b) in zip(mets, 1:stoiT.n, bal) ) * + :coupling^C.ConstraintTree( + cpl => C.Constraint( + value = let i = cT.colptr[row_idx], e = cT.colptr[row_idx+1] - 1 + C.LinearValue(idxs = cT.rowval[i:e], weights = cT.nzval[i:e]) + end, + bound = clb == cub ? C.EqualTo(clb) : C.Between(clb, cub), + ) for (cpl, row_idx, clb, cub) in zip(cpls, 1:cT.n, clbs, cubs) + ) * :objective^C.Constraint(C.LinearValue(SparseArrays.sparse(obj))), ) From 9c3ff362ba71be3625dea7235126fefc6246f30e Mon Sep 17 00:00:00 2001 From: Mirek Kratochvil Date: Tue, 11 Jun 2024 13:44:16 +0200 Subject: [PATCH 3/7] reorganize docs a bit --- .../{02-flux-balance-analysis.jl => 02a-flux-balance-analysis.jl} | 0 .../{02a-optimizer-parameters.jl => 02b-optimizer-parameters.jl} | 0 .../{02b-model-modifications.jl => 02c-model-modifications.jl} | 0 ...onstraint-modifications.jl => 02d-constraint-modifications.jl} | 0 ...x-variability-analysis.jl => 03a-flux-variability-analysis.jl} | 0 ...simonious-flux-balance.jl => 03b-parsimonious-flux-balance.jl} | 0 docs/src/examples/{09-envelopes.jl => 03c-envelopes.jl} | 0 .../examples/{08-community-models.jl => 04-community-models.jl} | 0 ...-adjustment.jl => 05a-minimization-of-metabolic-adjustment.jl} | 0 ...yme-constrained-models.jl => 05b-enzyme-constrained-models.jl} | 0 docs/src/examples/{06-mmdf.jl => 05c-mmdf.jl} | 0 .../examples/{07-loopless-models.jl => 05d-loopless-models.jl} | 0 docs/src/examples/{10-knockouts.jl => 05e-knockouts.jl} | 0 docs/src/examples/{11-sampling.jl => 06a-sampling.jl} | 0 docs/src/examples/{12-screening.jl => 06b-screening.jl} | 0 15 files changed, 0 insertions(+), 0 deletions(-) rename docs/src/examples/{02-flux-balance-analysis.jl => 02a-flux-balance-analysis.jl} (100%) rename docs/src/examples/{02a-optimizer-parameters.jl => 02b-optimizer-parameters.jl} (100%) rename docs/src/examples/{02b-model-modifications.jl => 02c-model-modifications.jl} (100%) rename docs/src/examples/{02c-constraint-modifications.jl => 02d-constraint-modifications.jl} (100%) rename docs/src/examples/{02d-flux-variability-analysis.jl => 03a-flux-variability-analysis.jl} (100%) rename docs/src/examples/{03-parsimonious-flux-balance.jl => 03b-parsimonious-flux-balance.jl} (100%) rename docs/src/examples/{09-envelopes.jl => 03c-envelopes.jl} (100%) rename docs/src/examples/{08-community-models.jl => 04-community-models.jl} (100%) rename docs/src/examples/{04-minimization-of-metabolic-adjustment.jl => 05a-minimization-of-metabolic-adjustment.jl} (100%) rename docs/src/examples/{05-enzyme-constrained-models.jl => 05b-enzyme-constrained-models.jl} (100%) rename docs/src/examples/{06-mmdf.jl => 05c-mmdf.jl} (100%) rename docs/src/examples/{07-loopless-models.jl => 05d-loopless-models.jl} (100%) rename docs/src/examples/{10-knockouts.jl => 05e-knockouts.jl} (100%) rename docs/src/examples/{11-sampling.jl => 06a-sampling.jl} (100%) rename docs/src/examples/{12-screening.jl => 06b-screening.jl} (100%) diff --git a/docs/src/examples/02-flux-balance-analysis.jl b/docs/src/examples/02a-flux-balance-analysis.jl similarity index 100% rename from docs/src/examples/02-flux-balance-analysis.jl rename to docs/src/examples/02a-flux-balance-analysis.jl diff --git a/docs/src/examples/02a-optimizer-parameters.jl b/docs/src/examples/02b-optimizer-parameters.jl similarity index 100% rename from docs/src/examples/02a-optimizer-parameters.jl rename to docs/src/examples/02b-optimizer-parameters.jl diff --git a/docs/src/examples/02b-model-modifications.jl b/docs/src/examples/02c-model-modifications.jl similarity index 100% rename from docs/src/examples/02b-model-modifications.jl rename to docs/src/examples/02c-model-modifications.jl diff --git a/docs/src/examples/02c-constraint-modifications.jl b/docs/src/examples/02d-constraint-modifications.jl similarity index 100% rename from docs/src/examples/02c-constraint-modifications.jl rename to docs/src/examples/02d-constraint-modifications.jl diff --git a/docs/src/examples/02d-flux-variability-analysis.jl b/docs/src/examples/03a-flux-variability-analysis.jl similarity index 100% rename from docs/src/examples/02d-flux-variability-analysis.jl rename to docs/src/examples/03a-flux-variability-analysis.jl diff --git a/docs/src/examples/03-parsimonious-flux-balance.jl b/docs/src/examples/03b-parsimonious-flux-balance.jl similarity index 100% rename from docs/src/examples/03-parsimonious-flux-balance.jl rename to docs/src/examples/03b-parsimonious-flux-balance.jl diff --git a/docs/src/examples/09-envelopes.jl b/docs/src/examples/03c-envelopes.jl similarity index 100% rename from docs/src/examples/09-envelopes.jl rename to docs/src/examples/03c-envelopes.jl diff --git a/docs/src/examples/08-community-models.jl b/docs/src/examples/04-community-models.jl similarity index 100% rename from docs/src/examples/08-community-models.jl rename to docs/src/examples/04-community-models.jl diff --git a/docs/src/examples/04-minimization-of-metabolic-adjustment.jl b/docs/src/examples/05a-minimization-of-metabolic-adjustment.jl similarity index 100% rename from docs/src/examples/04-minimization-of-metabolic-adjustment.jl rename to docs/src/examples/05a-minimization-of-metabolic-adjustment.jl diff --git a/docs/src/examples/05-enzyme-constrained-models.jl b/docs/src/examples/05b-enzyme-constrained-models.jl similarity index 100% rename from docs/src/examples/05-enzyme-constrained-models.jl rename to docs/src/examples/05b-enzyme-constrained-models.jl diff --git a/docs/src/examples/06-mmdf.jl b/docs/src/examples/05c-mmdf.jl similarity index 100% rename from docs/src/examples/06-mmdf.jl rename to docs/src/examples/05c-mmdf.jl diff --git a/docs/src/examples/07-loopless-models.jl b/docs/src/examples/05d-loopless-models.jl similarity index 100% rename from docs/src/examples/07-loopless-models.jl rename to docs/src/examples/05d-loopless-models.jl diff --git a/docs/src/examples/10-knockouts.jl b/docs/src/examples/05e-knockouts.jl similarity index 100% rename from docs/src/examples/10-knockouts.jl rename to docs/src/examples/05e-knockouts.jl diff --git a/docs/src/examples/11-sampling.jl b/docs/src/examples/06a-sampling.jl similarity index 100% rename from docs/src/examples/11-sampling.jl rename to docs/src/examples/06a-sampling.jl diff --git a/docs/src/examples/12-screening.jl b/docs/src/examples/06b-screening.jl similarity index 100% rename from docs/src/examples/12-screening.jl rename to docs/src/examples/06b-screening.jl From 5bc59bb841205291dd849634a7e16bf7051eb705 Mon Sep 17 00:00:00 2001 From: Mirek Kratochvil Date: Tue, 11 Jun 2024 13:58:41 +0200 Subject: [PATCH 4/7] explain coupling --- docs/src/examples/02c-model-modifications.jl | 26 ++++++++++++++++++- .../examples/02d-constraint-modifications.jl | 2 +- src/frontend/balance.jl | 2 +- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/docs/src/examples/02c-model-modifications.jl b/docs/src/examples/02c-model-modifications.jl index 5971e39d..d6662ba5 100644 --- a/docs/src/examples/02c-model-modifications.jl +++ b/docs/src/examples/02c-model-modifications.jl @@ -37,7 +37,7 @@ # disadvantage is that the "common" FBC model interface does not easily express # various complicated constructions (communities, reaction coupling, enzyme # constraints, etc.) -- see the [example about modifying the -# constraints](02c-constraint-modifications.md) for more details. +# constraints](02d-constraint-modifications.md) for more details. # # ## Getting the base model @@ -167,3 +167,27 @@ sort(collect(flux_changes), by = last) #md # !!! tip "Always use a uniquely defined flux solutions for flux comparisons" #md # Since the usual flux balance allows a lot of freedom in the "solved" flux and the only value that is "reproducible" by the analysis is the objective, one should never compare the flux distributions directly. Typically, that may result in false-positive (and sometimes false-negative) differences. Use e.g. [parsimonious FBA](03-parsimonious-flux-balance.md) to obtain uniquely determined and safely comparable flux solutions. + +# ## Coupling constraints +# +# Some model types support additional constraints over the reaction fluxes, +# which are historically called "coupling". These allow to e.g. place a bound +# on a total flux through several reactions. +# +# Canonical model supports these as "couplings": + +model.couplings["total_energy_intake"] = CM.Coupling( + lower_bound = 0, + upper_bound = 5, + reaction_weights = Dict("EX_glc__D_e" => -1.0, "EX_fru_e" => -1.0, "EX_pyr_e" => -1.0), +) + +# The values of any coupling constraints can be inspected directly in the +# solved model: + +solution_with_coupling = flux_balance_analysis(model, optimizer = GLPK.Optimizer) + +solution_with_coupling.coupling.total_energy_intake + +@test 0 <= solution_with_coupling.coupling.total_energy_intake <= 5 #src +@test isapprox(solution_with_coupling.objective, 0.4155977750928965, atol = TEST_TOLERANCE) #src diff --git a/docs/src/examples/02d-constraint-modifications.jl b/docs/src/examples/02d-constraint-modifications.jl index c08ff023..f07705a3 100644 --- a/docs/src/examples/02d-constraint-modifications.jl +++ b/docs/src/examples/02d-constraint-modifications.jl @@ -17,7 +17,7 @@ # # Making adjustments to the constraint system # # In the [previous example about model -# adjustments](02b-model-modifications.md), we noted that some constraint +# adjustments](02c-model-modifications.md), we noted that some constraint # systems may be too complex to be changed within the limits of the usual FBC # model view, and we may require a sharper tool to do the changes we need. This # example shows how to do that by modifying the constraint systems that are diff --git a/src/frontend/balance.jl b/src/frontend/balance.jl index 2611d9e9..6b3e549a 100644 --- a/src/frontend/balance.jl +++ b/src/frontend/balance.jl @@ -53,7 +53,7 @@ function flux_balance_constraints( bal = A.balance(model) obj = A.objective(model) cpls = Symbol.(A.couplings(model)) - cT = SparseArrays.SparseMtrisCSC(A.coupling(model)') + cT = SparseArrays.SparseMatrixCSC(A.coupling(model)') clbs, cubs = A.coupling_bounds(model) # The iteration through stoichiometry would be better done with eachrow(), From fb4d4bc9de122052bfcb4ddf033ce37f3c074e2d Mon Sep 17 00:00:00 2001 From: Mirek Kratochvil Date: Tue, 11 Jun 2024 14:07:56 +0200 Subject: [PATCH 5/7] bump cache action version --- .github/workflows/ci.yml | 2 +- .github/workflows/docs.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3f2fb612..5228884d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - - uses: julia-actions/cache@v1 + - uses: julia-actions/cache@v2 - uses: julia-actions/julia-buildpkg@latest - run: | git config --global user.name Tester diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index fe694736..bae1c13f 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -19,7 +19,7 @@ jobs: - uses: julia-actions/setup-julia@latest with: version: '1.9' - - uses: julia-actions/cache@v1 + - uses: julia-actions/cache@v2 - name: Install dependencies run: julia --color=yes --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' - name: Build and deploy From 41a240040d0a33dc36b5d0f7de2e2dc6f2c03009 Mon Sep 17 00:00:00 2001 From: Mirek Kratochvil Date: Tue, 11 Jun 2024 14:17:35 +0200 Subject: [PATCH 6/7] fix link --- docs/src/examples/02c-model-modifications.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/examples/02c-model-modifications.jl b/docs/src/examples/02c-model-modifications.jl index d6662ba5..3d60ef62 100644 --- a/docs/src/examples/02c-model-modifications.jl +++ b/docs/src/examples/02c-model-modifications.jl @@ -166,7 +166,7 @@ flux_changes = sort(collect(flux_changes), by = last) #md # !!! tip "Always use a uniquely defined flux solutions for flux comparisons" -#md # Since the usual flux balance allows a lot of freedom in the "solved" flux and the only value that is "reproducible" by the analysis is the objective, one should never compare the flux distributions directly. Typically, that may result in false-positive (and sometimes false-negative) differences. Use e.g. [parsimonious FBA](03-parsimonious-flux-balance.md) to obtain uniquely determined and safely comparable flux solutions. +#md # Since the usual flux balance allows a lot of freedom in the "solved" flux and the only value that is "reproducible" by the analysis is the objective, one should never compare the flux distributions directly. Typically, that may result in false-positive (and sometimes false-negative) differences. Use e.g. [parsimonious FBA](03b-parsimonious-flux-balance.md) to obtain uniquely determined and safely comparable flux solutions. # ## Coupling constraints # From 0bf414e4bed6db13ea27014a97747bd2e821fa3e Mon Sep 17 00:00:00 2001 From: Mirek Kratochvil Date: Wed, 12 Jun 2024 07:57:36 +0200 Subject: [PATCH 7/7] upd README link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 98df3018..daffb90d 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ [docs-img-dev]: https://img.shields.io/badge/docs-latest-0af.svg [docs-url-dev]: https://cobrexa.github.io/COBREXA.jl/dev/ [docs-url-examples]: https://cobrexa.github.io/COBREXA.jl/dev/examples/ -[docs-url-fba]: https://cobrexa.github.io/COBREXA.jl/dev/examples/02-flux-balance-analysis/ +[docs-url-fba]: https://cobrexa.github.io/COBREXA.jl/dev/examples/02a-flux-balance-analysis/ [docker-url]: https://github.com/COBREXA/COBREXA.jl/pkgs/container/cobrexa.jl [docker-img]: https://ghcr-badge.egpl.dev/cobrexa/cobrexa.jl/size?color=%2362a0ea&tag=latest&label=docker&trim=