Commit 92251513 authored by Mosè Giordano's avatar Mosè Giordano
Browse files

Add function to read SBML model from a string

parent 68e0e0b5
......@@ -18,7 +18,7 @@ include("utils.jl")
sbml(sym::Symbol) = dlsym(SBML_jll.libsbml_handle, sym)
export readSBML, getS, getLBs, getUBs, getOCs
export readSBML, readSBMLFromString, getS, getLBs, getUBs, getOCs
export set_level_and_version, libsbml_convert, convert_simplify_math
end # module
......@@ -71,6 +71,34 @@ function get_optional_double(x::VPtr, is_sym, get_sym)::Maybe{Float64}
end
end
function _readSBML(
symbol::Symbol,
fn::String,
sbml_conversion = document -> nothing,
report_severities = ["Fatal", "Error"],
)::SBML.Model
doc = ccall(sbml(symbol), VPtr, (Cstring,), fn)
try
get_error_messages(
doc,
AssertionError("Opening SBML document has reported errors"),
report_severities,
)
sbml_conversion(doc)
if 0 == ccall(sbml(:SBMLDocument_isSetModel), Cint, (VPtr,), doc)
throw(AssertionError("SBML document contains no model"))
end
model = ccall(sbml(:SBMLDocument_getModel), VPtr, (VPtr,), doc)
return extractModel(model)
finally
ccall(sbml(:SBMLDocument_free), Nothing, (VPtr,), doc)
end
end
"""
readSBML(
fn::String,
......@@ -89,6 +117,8 @@ single parameter, which is the C pointer to the loaded SBML document (C type
`report_severities` switches on and off reporting of certain errors; see the
documentation of [`get_error_messages`](@ref) for details.
To read from a string instead of a file, use [`readSBMLFromString`](@ref).
# Example
```
m = readSBML("my_model.xml", doc -> begin
......@@ -97,32 +127,37 @@ m = readSBML("my_model.xml", doc -> begin
end)
```
"""
function readSBML(
readSBML(
fn::String,
sbml_conversion = document -> nothing;
report_severities = ["Fatal", "Error"],
)::SBML.Model
doc = ccall(sbml(:readSBML), VPtr, (Cstring,), fn)
try
get_error_messages(
doc,
AssertionError("Opening SBML document has reported errors"),
report_severities,
)
)::SBML.Model = _readSBML(:readSBML, fn, sbml_conversion, report_severities)
sbml_conversion(doc)
"""
readSBML(
str::String,
sbml_conversion = document -> nothing;
report_severities = ["Fatal", "Error"],
)::SBML.Model
if 0 == ccall(sbml(:SBMLDocument_isSetModel), Cint, (VPtr,), doc)
throw(AssertionError("SBML document contains no model"))
end
Read the SBML from the string `str` and return the contained `SBML.Model`.
model = ccall(sbml(:SBMLDocument_getModel), VPtr, (VPtr,), doc)
The `sbml_conversion` is a function that does an in-place modification of the
single parameter, which is the C pointer to the loaded SBML document (C type
`SBMLDocument*`). Several functions for doing that are prepared, including
[`set_level_and_version`](@ref), [`libsbml_convert`](@ref), and
[`convert_simplify_math`](@ref).
return extractModel(model)
finally
ccall(sbml(:SBMLDocument_free), Nothing, (VPtr,), doc)
end
end
`report_severities` switches on and off reporting of certain errors; see the
documentation of [`get_error_messages`](@ref) for details.
To read from a file instead of a string, use [`readSBML`](@ref).
"""
readSBMLFromString(
str::AbstractString,
sbml_conversion = document -> nothing;
report_severities = ["Fatal", "Error"],
)::SBML.Model = _readSBML(:readSBMLFromString, String(str), sbml_conversion, report_severities)
get_notes(x::VPtr)::Maybe{String} = get_optional_string(x, :SBase_getNotesString)
get_annotation(x::VPtr)::Maybe{String} = get_optional_string(x, :SBase_getAnnotationString)
......
......@@ -58,7 +58,7 @@ sbmlfiles = [
),
]
@testset "Loading of models from various sources" begin
@testset "Loading of models from various sources - $(reader)" for reader in (readSBML, readSBMLFromString)
for (sbmlfile, url, hash, expected_mets, expected_rxns) in sbmlfiles
if !isfile(sbmlfile)
Downloads.download(url, sbmlfile)
......@@ -70,7 +70,11 @@ sbmlfiles = [
end
@testset "Loading of $sbmlfile" begin
mdl = readSBML(sbmlfile)
mdl = if reader === readSBML
readSBML(sbmlfile)
else
readSBMLFromString(readchomp(sbmlfile))
end
@test typeof(mdl) == Model
......@@ -82,6 +86,10 @@ sbmlfiles = [
end
end
@testset "readSBMLFromString" begin
@test_logs (:error, r"^SBML reported error") @test_throws AssertionError readSBMLFromString("")
end
@testset "Time variables in math" begin
# this test is here mainly for keeping a magical constant that we need for
# parsing time synced with libsbml source
......
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