Skip to content

Commit

Permalink
Merge pull request #260 from LCSB-BioCore/mk-groups
Browse files Browse the repository at this point in the history
add support for groups extension
  • Loading branch information
exaexa authored Dec 11, 2023
2 parents 64ec00b + 1d95e0f commit b9a9f34
Show file tree
Hide file tree
Showing 8 changed files with 280 additions and 104 deletions.
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "SBML"
uuid = "e5567a89-2604-4b09-9718-f5f78e97c3bb"
authors = ["Mirek Kratochvil <[email protected]>", "LCSB R3 team <[email protected]>"]
version = "1.5.1"
version = "1.6"

[deps]
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
Expand All @@ -16,7 +16,7 @@ ConstructionBase = "1.3"
DocStringExtensions = "0.8, 0.9"
IfElse = "0.1"
SBML_jll = "5.19.5"
Symbolics = "3, 4"
Symbolics = "5"
Unitful = "1"
julia = "1.6"

Expand Down
76 changes: 59 additions & 17 deletions src/readsbml.jl
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ readSBMLFromString(

get_notes(x::VPtr)::Maybe{String} = get_optional_string(x, :SBase_getNotesString)
get_annotation(x::VPtr)::Maybe{String} = get_optional_string(x, :SBase_getAnnotationString)
get_metaid(x::VPtr)::Maybe{String} = get_optional_string(x, :SBase_getMetaId)

"""
$(TYPEDSIGNATURES)
Expand Down Expand Up @@ -293,7 +294,7 @@ get_parameter(p::VPtr)::Pair{String,Parameter} =
value = get_optional_double(p, :Parameter_isSetValue, :Parameter_getValue),
units = get_optional_string(p, :Parameter_getUnits),
constant = get_optional_bool(p, :Parameter_isSetConstant, :Parameter_getConstant),
metaid = get_optional_string(p, :SBase_getMetaId),
metaid = get_metaid(p),
notes = get_notes(p),
annotation = get_annotation(p),
sbo = get_sbo_term(p),
Expand All @@ -309,6 +310,8 @@ valid [`SBML.Model`](@ref) structure.
function get_model(mdl::VPtr)::SBML.Model
# get the FBC plugin pointer (FbcModelPlugin_t)
mdl_fbc = ccall(sbml(:SBase_getPlugin), VPtr, (VPtr, Cstring), mdl, "fbc")
# and the Groups plugin pointer (GroupModelPlugin_t)
mdl_groups = ccall(sbml(:SBase_getPlugin), VPtr, (VPtr, Cstring), mdl, "groups")

# get the parameters
parameters = Dict{String,Parameter}()
Expand Down Expand Up @@ -364,7 +367,7 @@ function get_model(mdl::VPtr)::SBML.Model
),
size = get_optional_double(co, :Compartment_isSetSize, :Compartment_getSize),
units = get_optional_string(co, :Compartment_getUnits),
metaid = get_optional_string(co, :SBase_getMetaId),
metaid = get_metaid(co),
notes = get_notes(co),
annotation = get_annotation(co),
sbo = get_sbo_term(co),
Expand Down Expand Up @@ -423,7 +426,7 @@ function get_model(mdl::VPtr)::SBML.Model
:Species_getHasOnlySubstanceUnits,
),
constant = get_optional_bool(sp, :Species_isSetConstant, :Species_getConstant),
metaid = get_optional_string(sp, :SBase_getMetaId),
metaid = get_metaid(sp),
notes = get_notes(sp),
annotation = get_annotation(sp),
sbo = get_sbo_term(sp),
Expand Down Expand Up @@ -567,7 +570,7 @@ function get_model(mdl::VPtr)::SBML.Model
gene_product_association = association,
kinetic_math = math,
reversible,
metaid = get_optional_string(re, :SBase_getMetaId),
metaid = get_metaid(re),
notes = get_notes(re),
annotation = get_annotation(re),
sbo = get_sbo_term(re),
Expand All @@ -593,7 +596,7 @@ function get_model(mdl::VPtr)::SBML.Model
gene_products[id] = GeneProduct(
label = get_string(gp, :GeneProduct_getLabel),
name = get_optional_string(gp, :GeneProduct_getName),
metaid = get_optional_string(gp, :SBase_getMetaId),
metaid = get_metaid(gp),
notes = get_notes(gp),
annotation = get_annotation(gp),
sbo = get_sbo_term(gp),
Expand All @@ -614,7 +617,7 @@ function get_model(mdl::VPtr)::SBML.Model
function_definitions[get_string(fd, :FunctionDefinition_getId)] =
FunctionDefinition(
name = get_optional_string(fd, :FunctionDefinition_getName),
metaid = get_optional_string(fd, :SBase_getMetaId),
metaid = get_metaid(fd),
body = def,
notes = get_notes(fd),
annotation = get_annotation(fd),
Expand All @@ -625,8 +628,8 @@ function get_model(mdl::VPtr)::SBML.Model

initial_assignments = Dict{String,Math}()
num_ias = ccall(sbml(:Model_getNumInitialAssignments), Cuint, (VPtr,), mdl)
for n = 0:(num_ias-1)
ia = ccall(sbml(:Model_getInitialAssignment), VPtr, (VPtr, Cuint), mdl, n)
for i = 0:(num_ias-1)
ia = ccall(sbml(:Model_getInitialAssignment), VPtr, (VPtr, Cuint), mdl, i)
sym = ccall(sbml(:InitialAssignment_getSymbol), Cstring, (VPtr,), ia)
math_ptr = ccall(sbml(:InitialAssignment_getMath), VPtr, (VPtr,), ia)
if math_ptr != C_NULL
Expand All @@ -637,8 +640,8 @@ function get_model(mdl::VPtr)::SBML.Model
# events
events = Pair{Maybe{String},Event}[]
num_events = ccall(sbml(:Model_getNumEvents), Cuint, (VPtr,), mdl)
for n = 0:(num_events-1)
ev = ccall(sbml(:Model_getEvent), VPtr, (VPtr, Cuint), mdl, n)
for i = 0:(num_events-1)
ev = ccall(sbml(:Model_getEvent), VPtr, (VPtr, Cuint), mdl, i)

event_assignments = EventAssignment[]
for j = 0:(ccall(sbml(:Event_getNumEventAssignments), Cuint, (VPtr,), ev)-1)
Expand Down Expand Up @@ -684,11 +687,11 @@ function get_model(mdl::VPtr)::SBML.Model
)
end

# Rules
# rules
rules = Rule[]
num_rules = ccall(sbml(:Model_getNumRules), Cuint, (VPtr,), mdl)
for n = 0:(num_rules-1)
rule_ptr = ccall(sbml(:Model_getRule), VPtr, (VPtr, Cuint), mdl, n)
for i = 0:(num_rules-1)
rule_ptr = ccall(sbml(:Model_getRule), VPtr, (VPtr, Cuint), mdl, i)
type = if ccall(sbml(:Rule_isAlgebraic), Bool, (VPtr,), rule_ptr)
AlgebraicRule
elseif ccall(sbml(:Rule_isAssignment), Bool, (VPtr,), rule_ptr)
Expand All @@ -711,11 +714,11 @@ function get_model(mdl::VPtr)::SBML.Model
end
end

# Constraints
# constraints
constraints = Constraint[]
num_constraints = ccall(sbml(:Model_getNumConstraints), Cuint, (VPtr,), mdl)
for n = 0:(num_constraints-1)
constraint_ptr = ccall(sbml(:Model_getConstraint), VPtr, (VPtr, Cuint), mdl, n)
for i = 0:(num_constraints-1)
constraint_ptr = ccall(sbml(:Model_getConstraint), VPtr, (VPtr, Cuint), mdl, i)
xml_ptr = ccall(sbml(:Constraint_getMessage), VPtr, (VPtr,), constraint_ptr)
message = get_string_from_xmlnode(xml_ptr)
math_ptr = ccall(sbml(:Constraint_getMath), VPtr, (VPtr,), constraint_ptr)
Expand All @@ -726,6 +729,44 @@ function get_model(mdl::VPtr)::SBML.Model
end
end

# groups (these require the groups extension)
groups = Dict{String,Group}()
if mdl_groups != C_NULL
num_groups =
ccall(sbml(:GroupsModelPlugin_getNumGroups), Cuint, (VPtr,), mdl_groups)
for i = 0:(num_groups-1)
grp =
ccall(sbml(:GroupsModelPlugin_getGroup), VPtr, (VPtr, Cuint), mdl_groups, i)
members = Member[
let mem = ccall(sbml(:Group_getMember), VPtr, (VPtr, Cuint), grp, mi)
Member(;
id = get_optional_string(mem, :Member_getId),
metaid = get_metaid(mem),
name = get_optional_string(mem, :Member_getName),
id_ref = get_optional_string(mem, :Member_getIdRef),
metaid_ref = get_optional_string(mem, :Member_getMetaIdRef),
notes = get_notes(mem),
annotation = get_annotation(mem),
sbo = get_sbo_term(mem),
cv_terms = get_cv_terms(mem),
)
end for
mi = 0:(ccall(sbml(:Group_getNumMembers), Cuint, (VPtr,), grp)-1)
]

groups[get_string(grp, :Group_getId)] = Group(;
metaid = get_metaid(grp),
kind = get_optional_string(grp, :Group_getKindAsString),
name = get_optional_string(grp, :Group_getName),
members,
notes = get_notes(grp),
annotation = get_annotation(grp),
sbo = get_sbo_term(grp),
cv_terms = get_cv_terms(grp),
)
end
end

return Model(;
parameters,
units,
Expand All @@ -740,9 +781,10 @@ function get_model(mdl::VPtr)::SBML.Model
gene_products,
function_definitions,
events,
groups,
name = get_optional_string(mdl, :Model_getName),
id = get_optional_string(mdl, :Model_getId),
metaid = get_optional_string(mdl, :SBase_getMetaId),
metaid = get_metaid(mdl),
conversion_factor = get_optional_string(mdl, :Model_getConversionFactor),
area_units = get_optional_string(mdl, :Model_getAreaUnits),
extent_units = get_optional_string(mdl, :Model_getExtentUnits),
Expand Down
46 changes: 41 additions & 5 deletions src/structs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -450,11 +450,46 @@ end
"""
$(TYPEDEF)
Structure that collects the model-related data. Contains `parameters`, `units`,
`compartments`, `species` and `reactions` and `gene_products`, and additional
`notes` and `annotation` (also present internally in some of the data fields).
The contained dictionaries are indexed by identifiers of the corresponding
objects.
# Fields
$(TYPEDFIELDS)
"""
Base.@kwdef struct Member
id::Maybe{String} = nothing
metaid::Maybe{String} = nothing
name::Maybe{String} = nothing
id_ref::Maybe{String} = nothing
metaid_ref::Maybe{String} = nothing
notes::Maybe{String} = nothing
annotation::Maybe{String} = nothing
sbo::Maybe{String} = nothing
cv_terms::Vector{CVTerm} = []
end

"""
$(TYPEDEF)
# Fields
$(TYPEDFIELDS)
"""
Base.@kwdef struct Group
metaid::Maybe{String} = nothing
kind::Maybe{String} = nothing
name::Maybe{String} = nothing
members::Vector{Member} = []
notes::Maybe{String} = nothing
annotation::Maybe{String} = nothing
sbo::Maybe{String} = nothing
cv_terms::Vector{CVTerm} = []
end

"""
$(TYPEDEF)
Julia representation of SBML Model structure, with the reactions, species,
units, compartments, and many other things.
Where available, all objects are contained in dictionaries indexed by SBML
identifiers.
# Fields
$(TYPEDFIELDS)
Expand All @@ -473,6 +508,7 @@ Base.@kwdef struct Model
gene_products::Dict{String,GeneProduct} = Dict()
function_definitions::Dict{String,FunctionDefinition} = Dict()
events::Vector{Pair{Maybe{String},Event}} = Pair{Maybe{String},Event}[]
groups::Dict{String,Group} = Dict()
name::Maybe{String} = nothing
id::Maybe{String} = nothing
metaid::Maybe{String} = nothing
Expand Down
Loading

0 comments on commit b9a9f34

Please sign in to comment.