Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for groups extension #260

Merged
merged 13 commits into from
Dec 11, 2023
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
75 changes: 58 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 @@ -742,7 +783,7 @@ function get_model(mdl::VPtr)::SBML.Model
events,
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
36 changes: 36 additions & 0 deletions src/structs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,41 @@ end
"""
$(TYPEDEF)

# Fields
$(TYPEDFIELDS)
"""
Base.@kwdef struct Member
exaexa marked this conversation as resolved.
Show resolved Hide resolved
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)

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).
exaexa marked this conversation as resolved.
Show resolved Hide resolved
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