Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
LCSB-BioCore
SBML.jl
Commits
21794da5
Commit
21794da5
authored
Apr 13, 2021
by
Miroslav Kratochvil
Browse files
make string extraction a bit more error-proof
parent
b8863bb4
Changes
1
Show whitespace changes
Inline
Side-by-side
src/readsbml.jl
View file @
21794da5
const
VPtr
=
Ptr
{
Cvoid
}
const
VPtr
=
Ptr
{
Cvoid
}
"""
function get_string(x::VPtr, fn_sym)::Maybe{String}
C-call the SBML function `fn_sym` with a single parameter `x`, interpret the
result as a string and return it, or throw exception in case the pointer is
NULL.
"""
function
get_string
(
x
::
VPtr
,
fn_sym
)
::
String
str
=
ccall
(
sbml
(
fn_sym
),
Cstring
,
(
VPtr
,),
x
)
if
str
!=
C_NULL
return
unsafe_string
(
str
)
else
throw
(
DomainError
(
x
,
"Calling
$
fn_sym returned NULL, valid string expected."
))
end
end
"""
function get_optional_string(x::VPtr, fn_sym)::Maybe{String}
Like [`get_string`](@Ref), but returns `nothing` instead of throwing an
exception.
This is used to get notes and annotations and several other things (see
`getNotes`, `getAnnotations`)
"""
function
get_optional_string
(
x
::
VPtr
,
fn_sym
)
::
Maybe
{
String
}
str
=
ccall
(
sbml
(
fn_sym
),
Cstring
,
(
VPtr
,),
x
)
if
str
!=
C_NULL
return
unsafe_string
(
str
)
else
return
nothing
end
end
"""
"""
function readSBML(fn::String)::Model
function readSBML(fn::String)::Model
...
@@ -12,7 +46,7 @@ function readSBML(fn::String)::Model
...
@@ -12,7 +46,7 @@ function readSBML(fn::String)::Model
n_errs
=
ccall
(
sbml
(
:
SBMLDocument_getNumErrors
),
Cuint
,
(
VPtr
,),
doc
)
n_errs
=
ccall
(
sbml
(
:
SBMLDocument_getNumErrors
),
Cuint
,
(
VPtr
,),
doc
)
for
i
=
0
:
n_errs
-
1
for
i
=
0
:
n_errs
-
1
err
=
ccall
(
sbml
(
:
SBMLDocument_getError
),
VPtr
,
(
VPtr
,
Cuint
),
doc
,
i
)
err
=
ccall
(
sbml
(
:
SBMLDocument_getError
),
VPtr
,
(
VPtr
,
Cuint
),
doc
,
i
)
msg
=
unsafe
_string
(
ccall
(
sbml
(
:
XMLError_getMessage
)
,
Cstring
,
(
VPtr
,),
err
))
msg
=
get
_string
(
err
,
:
XMLError_getMessage
)
@warn
"SBML reported error:
$
msg"
@warn
"SBML reported error:
$
msg"
end
end
if
n_errs
>
0
if
n_errs
>
0
...
@@ -31,24 +65,8 @@ function readSBML(fn::String)::Model
...
@@ -31,24 +65,8 @@ function readSBML(fn::String)::Model
end
end
end
end
"""
getNotes
(
x
::
VPtr
)
::
Maybe
{
String
}
=
get_optional_string
(
x
,
:
SBase_getNotesString
)
function getOptionalString(x::VPtr, fn_sym)::Maybe{String}
getAnnotation
(
x
::
VPtr
)
::
Maybe
{
String
}
=
get_optional_string
(
x
,
:
SBase_getAnnotationString
)
C-call the SBML function `fn_sym` with a single parameter `x`, interpret the result as a nullable string pointer and return appropriately.
This is used to get notes and annotations and several other things (see `getNotes`, `getAnnotations`)
"""
function
getOptionalString
(
x
::
VPtr
,
fn_sym
)
::
Maybe
{
String
}
str
=
ccall
(
sbml
(
fn_sym
),
Cstring
,
(
VPtr
,),
x
)
if
str
!=
C_NULL
return
unsafe_string
(
str
)
else
return
nothing
end
end
getNotes
(
x
::
VPtr
)
::
Maybe
{
String
}
=
getOptionalString
(
x
,
:
SBase_getNotesString
)
getAnnotation
(
x
::
VPtr
)
::
Maybe
{
String
}
=
getOptionalString
(
x
,
:
SBase_getAnnotationString
)
"""
"""
function getAssociation(x::VPtr)::GeneProductAssociation
function getAssociation(x::VPtr)::GeneProductAssociation
...
@@ -61,9 +79,7 @@ function getAssociation(x::VPtr)::GeneProductAssociation
...
@@ -61,9 +79,7 @@ function getAssociation(x::VPtr)::GeneProductAssociation
# way, so we use a bit of a hack.
# way, so we use a bit of a hack.
typecode
=
ccall
(
sbml
(
:
SBase_getTypeCode
),
Cint
,
(
VPtr
,),
x
)
typecode
=
ccall
(
sbml
(
:
SBase_getTypeCode
),
Cint
,
(
VPtr
,),
x
)
if
typecode
==
808
# SBML_FBC_GENEPRODUCTREF
if
typecode
==
808
# SBML_FBC_GENEPRODUCTREF
return
GPARef
(
return
GPARef
(
get_string
(
x
,
:
GeneProductRef_getGeneProduct
))
unsafe_string
(
ccall
(
sbml
(
:
GeneProductRef_getGeneProduct
),
Cstring
,
(
VPtr
,),
x
)),
)
elseif
typecode
==
809
# SBML_FBC_AND
elseif
typecode
==
809
# SBML_FBC_AND
return
GPAAnd
([
return
GPAAnd
([
getAssociation
(
getAssociation
(
...
@@ -96,7 +112,7 @@ function extractModel(mdl::VPtr)::Model
...
@@ -96,7 +112,7 @@ function extractModel(mdl::VPtr)::Model
parameters = Dict{String,Float64}()
parameters = Dict{String,Float64}()
for i = 1:ccall(sbml(:Model_getNumParameters), Cuint, (VPtr,), mdl)
for i = 1:ccall(sbml(:Model_getNumParameters), Cuint, (VPtr,), mdl)
p = ccall(sbml(:Model_getParameter), VPtr, (VPtr, Cuint), mdl, i - 1)
p = ccall(sbml(:Model_getParameter), VPtr, (VPtr, Cuint), mdl, i - 1)
id =
unsafe
_string(
ccall(sbml(
:Parameter_getId)
, Cstring, (VPtr,), p))
id =
get
_string(
p,
:Parameter_getId)
v = ccall(sbml(:Parameter_getValue), Cdouble, (VPtr,), p)
v = ccall(sbml(:Parameter_getValue), Cdouble, (VPtr,), p)
parameters[id] = v
parameters[id] = v
end
end
...
@@ -105,7 +121,7 @@ function extractModel(mdl::VPtr)::Model
...
@@ -105,7 +121,7 @@ function extractModel(mdl::VPtr)::Model
units = Dict{String,Vector{UnitPart}}()
units = Dict{String,Vector{UnitPart}}()
for i = 1:ccall(sbml(:Model_getNumUnitDefinitions), Cuint, (VPtr,), mdl)
for i = 1:ccall(sbml(:Model_getNumUnitDefinitions), Cuint, (VPtr,), mdl)
ud = ccall(sbml(:Model_getUnitDefinition), VPtr, (VPtr, Cuint), mdl, i - 1)
ud = ccall(sbml(:Model_getUnitDefinition), VPtr, (VPtr, Cuint), mdl, i - 1)
id =
unsafe
_string(
ccall(sbml(
:UnitDefinition_getId)
, Cstring, (VPtr,), ud))
id =
get
_string(
ud,
:UnitDefinition_getId)
units[id] = [
units[id] = [
begin
begin
u = ccall(sbml(:UnitDefinition_getUnit), VPtr, (VPtr, Cuint), ud, j - 1)
u = ccall(sbml(:UnitDefinition_getUnit), VPtr, (VPtr, Cuint), ud, j - 1)
...
@@ -128,13 +144,9 @@ function extractModel(mdl::VPtr)::Model
...
@@ -128,13 +144,9 @@ function extractModel(mdl::VPtr)::Model
# parse out compartment names
# parse out compartment names
compartments = [
compartments = [
unsafe_string(
get_string(
ccall(
sbml(:Compartment_getId),
Cstring,
(VPtr,),
ccall(sbml(:Model_getCompartment), VPtr, (VPtr, Cuint), mdl, i - 1),
ccall(sbml(:Model_getCompartment), VPtr, (VPtr, Cuint), mdl, i - 1),
)
,
:Compartment_getId
,
) for i = 1:ccall(sbml(:Model_getNumCompartments), Cuint, (VPtr,), mdl)
) for i = 1:ccall(sbml(:Model_getNumCompartments), Cuint, (VPtr,), mdl)
]
]
...
@@ -149,22 +161,15 @@ function extractModel(mdl::VPtr)::Model
...
@@ -149,22 +161,15 @@ function extractModel(mdl::VPtr)::Model
# if the FBC plugin is present, try to get the chemical formula and charge
# if the FBC plugin is present, try to get the chemical formula and charge
if 0 !=
if 0 !=
ccall(sbml(:FbcSpeciesPlugin_isSetChemicalFormula), Cint, (VPtr,), sp_fbc)
ccall(sbml(:FbcSpeciesPlugin_isSetChemicalFormula), Cint, (VPtr,), sp_fbc)
formula = unsafe_string(
formula = get_string(sp_fbc, :FbcSpeciesPlugin_getChemicalFormula)
ccall(
sbml(:FbcSpeciesPlugin_getChemicalFormula),
Cstring,
(VPtr,),
sp_fbc,
),
)
end
end
if 0 != ccall(sbml(:FbcSpeciesPlugin_isSetCharge), Cint, (VPtr,), sp_fbc)
if 0 != ccall(sbml(:FbcSpeciesPlugin_isSetCharge), Cint, (VPtr,), sp_fbc)
charge = ccall(sbml(:FbcSpeciesPlugin_getCharge), Cint, (VPtr,), sp_fbc)
charge = ccall(sbml(:FbcSpeciesPlugin_getCharge), Cint, (VPtr,), sp_fbc)
end
end
end
end
species[
unsafe
_string(
ccall(sbml(
:Species_getId)
, Cstring, (VPtr,), sp))
] = Species(
species[
get
_string(
sp,
:Species_getId)] = Species(
unsafe
_string(
ccall(sbml(
:Species_getName),
Cstring, (VPtr,), sp)),
get
_string(
sp,
:Species_getName),
unsafe
_string(
ccall(sbml(
:Species_getCompartment),
Cstring, (VPtr,), sp)),
get
_string(
sp,
:Species_getCompartment),
formula,
formula,
charge,
charge,
getNotes(sp),
getNotes(sp),
...
@@ -186,9 +191,8 @@ function extractModel(mdl::VPtr)::Model
...
@@ -186,9 +191,8 @@ function extractModel(mdl::VPtr)::Model
)
)
for j = 1:ccall(sbml(:Objective_getNumFluxObjectives), Cuint, (VPtr,), o)
for j = 1:ccall(sbml(:Objective_getNumFluxObjectives), Cuint, (VPtr,), o)
fo = ccall(sbml(:Objective_getFluxObjective), VPtr, (VPtr, Cuint), o, j - 1)
fo = ccall(sbml(:Objective_getFluxObjective), VPtr, (VPtr, Cuint), o, j - 1)
objectives_fbc[unsafe_string(
objectives_fbc[get_string(fo, :FluxObjective_getReaction)] =
ccall(sbml(:FluxObjective_getReaction), Cstring, (VPtr,), fo),
ccall(sbml(:FluxObjective_getCoefficient), Cdouble, (VPtr,), fo)
)] = ccall(sbml(:FluxObjective_getCoefficient), Cdouble, (VPtr,), fo)
end
end
end
end
end
end
...
@@ -206,11 +210,9 @@ function extractModel(mdl::VPtr)::Model
...
@@ -206,11 +210,9 @@ function extractModel(mdl::VPtr)::Model
if kl != C_NULL
if kl != C_NULL
for j = 1:ccall(sbml(:KineticLaw_getNumParameters), Cuint, (VPtr,), kl)
for j = 1:ccall(sbml(:KineticLaw_getNumParameters), Cuint, (VPtr,), kl)
p = ccall(sbml(:KineticLaw_getParameter), VPtr, (VPtr, Cuint), kl, j - 1)
p = ccall(sbml(:KineticLaw_getParameter), VPtr, (VPtr, Cuint), kl, j - 1)
id =
unsafe
_string(
ccall(sbml(
:Parameter_getId)
, Cstring, (VPtr,), p))
id =
get
_string(
p,
:Parameter_getId)
pval = () -> ccall(sbml(:Parameter_getValue), Cdouble, (VPtr,), p)
pval = () -> ccall(sbml(:Parameter_getValue), Cdouble, (VPtr,), p)
punit =
punit = () -> get_string(p, :Parameter_getUnits)
() ->
unsafe_string(ccall(sbml(:Parameter_getUnits), Cstring, (VPtr,), p))
if id == "
LOWER_BOUND
"
if id == "
LOWER_BOUND
"
lb = (pval(), punit())
lb = (pval(), punit())
elseif id == "
UPPER_BOUND
"
elseif id == "
UPPER_BOUND
"
...
@@ -229,15 +231,13 @@ function extractModel(mdl::VPtr)::Model
...
@@ -229,15 +231,13 @@ function extractModel(mdl::VPtr)::Model
# can make something out of it.
# can make something out of it.
re_fbc = ccall(sbml(:SBase_getPlugin), VPtr, (VPtr, Cstring), re, "
fbc
")
re_fbc = ccall(sbml(:SBase_getPlugin), VPtr, (VPtr, Cstring), re, "
fbc
")
if re_fbc != C_NULL
if re_fbc != C_NULL
fbcb =
fbcb = get_optional_string(re_fbc, :FbcReactionPlugin_getLowerFluxBound)
ccall(sbml(:FbcReactionPlugin_getLowerFluxBound), Cstring, (VPtr,), re_fbc)
if !isnothing(fbcb) && haskey(parameters, fbcb)
if fbcb != C_NULL && haskey(parameters, unsafe_string(fbcb))
lb = (parameters[fbcb], "
[
fbc
]
")
lb = (parameters[unsafe_string(fbcb)], "
[
fbc
]
")
end
end
fbcb =
fbcb = get_optional_string(re_fbc, :FbcReactionPlugin_getUpperFluxBound)
ccall(sbml(:FbcReactionPlugin_getUpperFluxBound), Cstring, (VPtr,), re_fbc)
if !isnothing(fbcb) && haskey(parameters, fbcb)
if fbcb != C_NULL && haskey(parameters, unsafe_string(fbcb))
ub = (parameters[fbcb], "
[
fbc
]
")
ub = (parameters[unsafe_string(fbcb)], "
[
fbc
]
")
end
end
end
end
...
@@ -245,9 +245,7 @@ function extractModel(mdl::VPtr)::Model
...
@@ -245,9 +245,7 @@ function extractModel(mdl::VPtr)::Model
stoi = Dict{String,Float64}()
stoi = Dict{String,Float64}()
add_stoi =
add_stoi =
(sr, factor) ->
(sr, factor) ->
stoi[unsafe_string(
stoi[get_string(sr, :SpeciesReference_getSpecies)] =
ccall(sbml(:SpeciesReference_getSpecies), Cstring, (VPtr,), sr),
)] =
ccall(sbml(:SpeciesReference_getStoichiometry), Cdouble, (VPtr,), sr) *
ccall(sbml(:SpeciesReference_getStoichiometry), Cdouble, (VPtr,), sr) *
factor
factor
...
@@ -277,7 +275,7 @@ function extractModel(mdl::VPtr)::Model
...
@@ -277,7 +275,7 @@ function extractModel(mdl::VPtr)::Model
end
end
end
end
reid =
unsafe
_string(
ccall(sbml(
:Reaction_getId)
, Cstring, (VPtr,), re))
reid =
get
_string(
re,
:Reaction_getId)
reactions[reid] = Reaction(
reactions[reid] = Reaction(
stoi,
stoi,
lb,
lb,
...
@@ -301,12 +299,12 @@ function extractModel(mdl::VPtr)::Model
...
@@ -301,12 +299,12 @@ function extractModel(mdl::VPtr)::Model
i - 1,
i - 1,
)
)
id = get
O
ptional
S
tring(gp, :GeneProduct_getId) # IDs don't need to be set
id = get
_o
ptional
_s
tring(gp, :GeneProduct_getId) # IDs don't need to be set
if id != nothing
if id != nothing
gene_products[id] = GeneProduct(
gene_products[id] = GeneProduct(
get
O
ptional
S
tring(gp, :GeneProduct_getName),
get
_o
ptional
_s
tring(gp, :GeneProduct_getName),
get
O
ptional
S
tring(gp, :GeneProduct_getLabel),
get
_o
ptional
_s
tring(gp, :GeneProduct_getLabel),
getNotes(gp),
getNotes(gp),
getAnnotation(gp),
getAnnotation(gp),
)
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment