Commit 15e5e45e authored by Miroslav Kratochvil's avatar Miroslav Kratochvil
Browse files

stoichiometry_matrix always efficiently returns a sparse matrix

parent 1bd9216f
""" """
function stoichiometry_matrix(m::SBML.Model; zeros=spzeros)::Tuple{Vector{String},Vector{String},AbstractMatrix{Float64}} function stoichiometry_matrix(m::SBML.Model)
Extract the vector of species (aka metabolite) identifiers, vector of reaction Extract the vector of species (aka metabolite) identifiers, vector of reaction
identifiers, and the (dense) stoichiometry matrix from an existing `SBML.Model`. identifiers, and a sparse stoichiometry matrix (of type `SparseMatrixCSC` from
Returns a tuple with these values. `SparseArrays` package) from an existing `SBML.Model`. Returns a 3-tuple with
these values.
The matrix is sparse by default (initially constructed by
`SparseArrays.spzeros`). You can fill in a custom empty matrix constructed to
argument `zeros`; e.g. running with `zeros=zeros` will produce a dense matrix.
""" """
function stoichiometry_matrix( function stoichiometry_matrix(m::SBML.Model)
m::SBML.Model; rows = collect(keys(m.species))
zeros = spzeros, cols = collect(keys(m.reactions))
)::Tuple{Vector{String},Vector{String},AbstractMatrix{Float64}} row_idx = Dict(k => i for (i, k) in enumerate(rows))
rows = [k for k in keys(m.species)] col_idx = Dict(k => i for (i, k) in enumerate(cols))
cols = [k for k in keys(m.reactions)]
rowsd = Dict(k => i for (i, k) in enumerate(rows)) nnz = 0
S = zeros(Float64, length(rows), length(cols)) for (_, r) in m.reactions
for col = 1:length(cols) for _ in r.reactants
s = m.reactions[cols[col]].reactants nnz += 1
S[getindex.(Ref(rowsd), keys(s)), col] .-= values(s) end
s = m.reactions[cols[col]].products for _ in r.products
S[getindex.(Ref(rowsd), keys(s)), col] .+= values(s) nnz += 1
SI = Int[]
RI = Int[]
SV = Float64[]
sizehint!(SI, nnz)
sizehint!(RI, nnz)
sizehint!(SV, nnz)
for (rid, r) in m.reactions
ridx = col_idx[rid]
for (sid, stoi) in r.reactants
push!(SI, row_idx[sid])
push!(RI, ridx)
push!(SV, -stoi)
for (sid, stoi) in r.products
push!(SI, row_idx[sid])
push!(RI, ridx)
push!(SV, stoi)
end end
return rows, cols, S return rows, cols, SparseArrays.sparse(SI, RI, SV, length(rows), length(cols))
end end
""" """
...@@ -28,9 +28,7 @@ end ...@@ -28,9 +28,7 @@ end
mets, rxns, S = stoichiometry_matrix(mdl) mets, rxns, S = stoichiometry_matrix(mdl)
@test typeof(S) <: AbstractMatrix{Float64} @test typeof(S) <: SparseMatrixCSC{Float64}
@test typeof(stoichiometry_matrix(mdl; zeros = spzeros)[3]) <: SparseMatrixCSC{Float64}
@test typeof(stoichiometry_matrix(mdl; zeros = zeros)[3]) == Matrix{Float64}
@test length(mets) == 77 @test length(mets) == 77
@test length(rxns) == 77 @test length(rxns) == 77
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment