Skip to content

Commit

Permalink
remove the mandatory ID from the SBML events
Browse files Browse the repository at this point in the history
Closes #254

SBML says that IDs on events are actually not mandatory, this softens the data
structure so that the ID-less events are supported. The vector-of-pairs
implementation is chosen for backwards compatibility (iteration through a
vector of pairs should work precisely like iteration through the dictionary
that was there before). Notably, this might look like a breaking change _but_
it is not -- the main use case that is broken by this commit is indexing the
events by ID, which was actually broken already.
  • Loading branch information
exaexa committed Aug 28, 2023
1 parent 7188293 commit 4191514
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 7 deletions.
2 changes: 1 addition & 1 deletion 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.4.1"
version = "1.5.0"

[deps]
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
Expand Down
10 changes: 6 additions & 4 deletions src/readsbml.jl
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ function get_model(mdl::VPtr)::SBML.Model
end

# events
events = Dict{String,Event}()
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)
Expand Down Expand Up @@ -662,8 +662,9 @@ function get_model(mdl::VPtr)::SBML.Model
math = trig_math_ptr == C_NULL ? nothing : parse_math(trig_math_ptr),
)

events[unsafe_string(ccall(sbml(:Event_getId), Cstring, (VPtr,), ev))] =
SBML.Event(;
push!(
events,
get_optional_string(ev, :Event_getId) => SBML.Event(;
use_values_from_trigger_time = ccall(
sbml(:Event_getUseValuesFromTriggerTime),
Cint,
Expand All @@ -673,7 +674,8 @@ function get_model(mdl::VPtr)::SBML.Model
name = get_optional_string(ev, :Event_getName),
trigger,
event_assignments,
)
),
)
end

# Rules
Expand Down
2 changes: 1 addition & 1 deletion src/structs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ Base.@kwdef struct Model
active_objective::Maybe{String} = nothing
gene_products::Dict{String,GeneProduct} = Dict()
function_definitions::Dict{String,FunctionDefinition} = Dict()
events::Dict{String,Event} = Dict()
events::Vector{Pair{Maybe{String},Event}} = Pair{Maybe{String},Event}[]
name::Maybe{String} = nothing
id::Maybe{String} = nothing
metaid::Maybe{String} = nothing
Expand Down
2 changes: 1 addition & 1 deletion src/writesbml.jl
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ function model_to_sbml!(doc::VPtr, mdl::Model)::VPtr
# Add events
for (id, event) in mdl.events
event_ptr = ccall(sbml(:Model_createEvent), VPtr, (VPtr,), model)
set_string!(event_ptr, :Event_setId, id)
isnothing(id) || set_string!(event_ptr, :Event_setId, id)
set_bool!(
event_ptr,
:Event_setUseValuesFromTriggerTime,
Expand Down
22 changes: 22 additions & 0 deletions test/loaddynamicmodels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,28 @@ sbmlfiles = [
("reaction1", SBML.MathApply("*", [SBML.MathApply("*", [compartment, k2]), S1])),
("S1", 0.01125),
),
# case 00928 with an ID-less event
(
joinpath(@__DIR__, "data", "00928-sbml-l3v2.xml"),
SBML.test_suite_url(928, level = 3, version = 2),
"d2a95aee820712696a2056bb09fd7d3befcd99e331809105e12ee081073a4985",
x -> nothing,
1,
(
"reaction1",
SBML.MathApply(
"*",
SBML.Math[
SBML.MathApply(
"*",
SBML.Math[SBML.MathIdent("C"), SBML.MathIdent("k1")],
),
SBML.MathIdent("S1"),
],
),
),
("S1", 0.0),
),
]

@testset "Loading of models from sbml_test_suite" begin
Expand Down

0 comments on commit 4191514

Please sign in to comment.