From cc30e84326e889c1d1b153fb2119ae6a225a8db7 Mon Sep 17 00:00:00 2001
From: Mirek Kratochvil <exa.exa@gmail.com>
Date: Thu, 1 Apr 2021 09:27:59 +0200
Subject: [PATCH] fix the nice FBA variants (again)

Closes #39
---
 src/analysis/fba.jl  | 29 +++++++++++++++++++++++++++++
 test/analysis/fba.jl | 11 +++++------
 2 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/src/analysis/fba.jl b/src/analysis/fba.jl
index 69041d35a..9cb3c4a43 100644
--- a/src/analysis/fba.jl
+++ b/src/analysis/fba.jl
@@ -13,6 +13,35 @@ Returns a solved model from [`optimize_model`](@ref).
 flux_balance_analysis(model::M, optimizer) where {M<:MetabolicModel} =
     optimize_model(model, optimizer; sense = MOI.MAX_SENSE)
 
+"""
+    flux_balance_analysis_vec(args...)::Maybe{Vector{Float64}}
+
+A variant of FBA that returns a vector of fluxes in the same order as reactions
+of the model, if the solution is found.
+Arguments are passed to [`flux_balance_analysis`](@ref).
+"""
+function flux_balance_analysis_vec(args...)::Maybe{Vector{Float64}}
+    (optmodel, vars) = flux_balance_analysis(args...)
+
+    termination_status(optmodel) in [MOI.OPTIMAL, MOI.LOCALLY_SOLVED] || return nothing
+    value.(vars)
+end
+
+"""
+    flux_balance_analysis_dict(model::M, args...)::Maybe{Dict{String, Float64}} where {M <: MetabolicModel}
+
+A variant of FBA that returns a dictionary assigning fluxes to reactions, if
+the solution is found. Arguments are passed to [`flux_balance_analysis`](@ref).
+"""
+function flux_balance_analysis_dict(
+    model::M,
+    args...,
+)::Maybe{Dict{String,Float64}} where {M<:MetabolicModel}
+    v = flux_balance_analysis_vec(model, args...)
+    isnothing(v) && return nothing
+    Dict(zip(reactions(model), v))
+end
+
 """
     fba(model::CobraModel, optimizer; objective_func::Union{Reaction, Array{Reaction, 1}}=Reaction[], weights=Float64[], solver_attributes=Dict{Any, Any}(), constraints=Dict{String, Tuple{Float64,Float64}}())
 
diff --git a/test/analysis/fba.jl b/test/analysis/fba.jl
index 6a1689171..c83facca9 100644
--- a/test/analysis/fba.jl
+++ b/test/analysis/fba.jl
@@ -34,12 +34,11 @@
     @test cp.c' * sol ≈ expected_optimum
 
     # test the "nicer output" variants
-    @test_broken false # reminder to implement these methods
-    # fluxes_vec = flux_balance_analysis_vec(cp, GLPK.Optimizer)
-    # @test_broken all(fluxes_vec .== sol)
-    # fluxes_dict = flux_balance_analysis_dict(cp, GLPK.Optimizer)
-    # rxns = reactions(cp)
-    # @test all([fluxes_dict[rxns[i]] == sol[i] for i in eachindex(rxns)])
+    fluxes_vec = flux_balance_analysis_vec(cp, GLPK.Optimizer)
+    @test all(fluxes_vec .== sol)
+    fluxes_dict = flux_balance_analysis_dict(cp, GLPK.Optimizer)
+    rxns = reactions(cp)
+    @test all([fluxes_dict[rxns[i]] == sol[i] for i in eachindex(rxns)])
 end
 
 @testset "Flux balance analysis with CobraModel" begin
-- 
GitLab