Skip to content

Commit

Permalink
Merge pull request #290 from NeuroML/experimental
Browse files Browse the repository at this point in the history
Tested sedml validate changes
  • Loading branch information
pgleeson authored Dec 13, 2023
2 parents 9a56b68 + 064744d commit c102f3e
Show file tree
Hide file tree
Showing 10 changed files with 413 additions and 7 deletions.
42 changes: 37 additions & 5 deletions pyneuroml/pynml.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,18 @@
# continue to work
from pyneuroml.plot import generate_plot, generate_interactive_plot # noqa
else:
# Define a new method, which only gets called if a user explicitly tries to
# Define a new method, which only gets called if a user explicitly tries to
# run generate_plot (and so requires matplotlib). If it's never called, matplotlib
# doesn't get imported

def generate_plot(*args, **kwargs):
try:
import matplotlib
from pyneuroml.plot import generate_plot as gp

return gp(*args, **kwargs)

except Exception as e:

logger.error("Matplotlib not found!")
warnings.warn(
"""
Expand All @@ -87,10 +87,10 @@ def generate_interactive_plot(*args, **kwargs):
try:
import matplotlib
from pyneuroml.plot import generate_interactive_plot as gp

return gp(*args, **kwargs)

except Exception as e:

logger.error("Matplotlib not found!")
warnings.warn(
"""
Expand All @@ -102,6 +102,7 @@ def generate_interactive_plot(*args, **kwargs):
stacklevel=2,
)


DEFAULTS = {
"v": False,
"default_java_max_memory": "400M",
Expand Down Expand Up @@ -404,6 +405,11 @@ def parse_arguments():
action="store_true",
help=("Validate SBML file(s), unit consistency failure generates an error"),
)
mut_exc_opts.add_argument(
"-validate-sedml",
action="store_true",
help=("Validate SEDML file(s)"),
)

return parser.parse_args()

Expand Down Expand Up @@ -2213,6 +2219,32 @@ def evaluate_arguments(args):
logger.error(f"one or more SBML files failed to validate")
sys.exit(UNKNOWN_ERR)

# Deal with the SEDML validation option which doesn't call run_jneuroml
if args.validate_sedml:
try:
from pyneuroml.sedml import validate_sedml_files
except Exception:
logger.critical("Unable to import pyneuroml.sedml")
sys.exit(UNKNOWN_ERR)

if not len(args.input_files) >= 1:
logger.critical("No input files specified")
sys.exit(ARGUMENT_ERR)

try:
result = validate_sedml_files(args.input_files)
except Exception as e:
logger.critical(f"validate_sedml_files failed with {str(e)}")
sys.exit(UNKNOWN_ERR)

if result:
# All files validated ok (with possible warnings but no errors)
sys.exit(0)

# Errors of some kind were found in one or more files
logger.error(f"one or more SEDML files failed to validate")
sys.exit(UNKNOWN_ERR)

# These do not use the shared option where files are supplied
# They require the file name to be specified after
# TODO: handle these better
Expand Down
60 changes: 60 additions & 0 deletions pyneuroml/sedml/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""
use libsedml getErrorLog().getNumFailsWithSeverity(libsedml.LIBSEDML_SEV_ERROR) to validate SEDML file(s)
based on example here https://github.com/SED-ML/libSEDML/blob/master/examples/python/echo_sedml.py
"""

import os
import errno
import libsedml
from typing import List


def check_file(file_name):
"""
check string path points to a file and that we have read access to it
"""

if not os.path.isfile(file_name):
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), file_name)

if not os.access(file_name, os.R_OK):
raise IOError(f"Could not read file {file_name}")


def validate_sedml_files(input_files: List[str]) -> bool:
"""
validate SEDML file(s)
input_files is a list of one or more filepaths
"""

if not len(input_files) >= 1:
raise ValueError("No input files specified")

all_valid = True

for file_name in input_files:
# check file exists and is readable
check_file(file_name)

try:
doc = libsedml.readSedML(file_name)
except Exception:
raise IOError(f"readSedML failed trying to open the file {file_name}")

# readSedML does not check existance of model source files, do it ourselves here
for model in doc.getListOfModels():
# treat file path as relative to SEDML file
dir_name = os.path.dirname(file_name)
source_file = os.path.join(dir_name, model.getSource())

try:
check_file(source_file)
except Exception:
all_valid = False
print("Cannot find or access model source file {source_file}")

if doc.getErrorLog().getNumFailsWithSeverity(libsedml.LIBSEDML_SEV_ERROR) > 0:
all_valid = False
print(doc.getErrorLog().toString())

return all_valid
5 changes: 3 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,9 @@ plotly =
nsg =
pynsgr

sbml =
combine =
python-libsbml
python-libsedml

all =
pyNeuroML[neuron]
Expand All @@ -115,7 +116,7 @@ all =
pyNeuroML[vispy]
pyNeuroML[plotly]
pyNeuroML[nsg]
pyNeuroML[sbml]
pyNeuroML[combine]

dev =
pyNeuroML[all]
Expand Down
41 changes: 41 additions & 0 deletions tests/sedml/test_data/invalid_doc01.sedml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created by phraSED-ML version v0.5beta on 2015-12-01 15:44 with libSBML version 5.11.9. -->
<sedML xmlns="http://sed-ml.org/sed-ml/level1/version2" level="1" version="2">
<listOfSimulations>
<uniformTimeCourse id="sim1" initialTime="0" outputStartTime="0" outputEndTime="10" numberOfPoints="10">
<algorithm kisaoID="KISAO:0000019"/>
</uniformTimeCourse>
</listOfSimulationz>
<listOfModels>
<model id="mod1" language="urn:sedml:language:sbml.level-3.version-1" source="00001-sbml.xml"/>
</listOfModels>
<listOfTasks>
<task id="task1" modelReference="mod1" simulationReference="sim1"/>
</listOfTasks>
<listOfDataGenerators>
<dataGenerator id="report_0_0_0" name="time">
<listOfVariables>
<variable id="time" symbol="urn:sedml:symbol:time" taskReference="task1"/>
</listOfVariables>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<ci> time </ci>
</math>
</dataGenerator>
<dataGenerator id="report_0_0_1" name="a">
<listOfVariables>
<variable id="a" target="/sbml:sbml/sbml:model/descendant::*[@id='a']" taskReference="task1" modelReference="mod1"/>
</listOfVariables>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<ci> a </ci>
</math>
</dataGenerator>
</listOfDataGenerators>
<listOfOutputs>
<report id="report_0">
<listOfDataSets>
<dataSet id="report_0_0_0_dataset" label="time" dataReference="report_0_0_0"/>
<dataSet id="report_0_0_1_dataset" label="a" dataReference="report_0_0_1"/>
</listOfDataSets>
</report>
</listOfOutputs>
</sedML>
41 changes: 41 additions & 0 deletions tests/sedml/test_data/invalid_doc02.sedml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created by phraSED-ML version v0.5beta on 2015-12-01 15:44 with libSBML version 5.11.9. -->
<sedML xmlns="http://sed-ml.org/sed-ml/level1/version2" level="1" version="2">
<listOfSimulations>
<uniformTimeCourse id="sim1" initialTime="0" outputStartTime="0" outputEndTime="10" numberOfPoints="10">
<algorithm kisaoID="KISAO:0000019"/>
</uniformTimeCourse>
</listOfSimulations>
<listOfNoodles>
<model id="mod1" language="urn:sedml:language:sbml.level-3.version-1" source="00001-sbml.xml"/>
</listOfNoodles>
<listOfTasks>
<task id="task1" modelReference="mod1" simulationReference="sim1"/>
</listOfTasks>
<listOfDataGenerators>
<dataGenerator id="report_0_0_0" name="time">
<listOfVariables>
<variable id="time" symbol="urn:sedml:symbol:time" taskReference="task1"/>
</listOfVariables>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<ci> time </ci>
</math>
</dataGenerator>
<dataGenerator id="report_0_0_1" name="a">
<listOfVariables>
<variable id="a" target="/sbml:sbml/sbml:model/descendant::*[@id='a']" taskReference="task1" modelReference="mod1"/>
</listOfVariables>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<ci> a </ci>
</math>
</dataGenerator>
</listOfDataGenerators>
<listOfOutputs>
<report id="report_0">
<listOfDataSets>
<dataSet id="report_0_0_0_dataset" label="time" dataReference="report_0_0_0"/>
<dataSet id="report_0_0_1_dataset" label="a" dataReference="report_0_0_1"/>
</listOfDataSets>
</report>
</listOfOutputs>
</sedML>
41 changes: 41 additions & 0 deletions tests/sedml/test_data/missing_model_source.sedml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created by phraSED-ML version v0.5beta on 2015-12-01 15:44 with libSBML version 5.11.9. -->
<sedML xmlns="http://sed-ml.org/sed-ml/level1/version2" level="1" version="2">
<listOfSimulations>
<uniformTimeCourse id="sim1" initialTime="0" outputStartTime="0" outputEndTime="10" numberOfPoints="10">
<algorithm kisaoID="KISAO:0000019"/>
</uniformTimeCourse>
</listOfSimulations>
<listOfModels>
<model id="mod1" language="urn:sedml:language:sbml.level-3.version-1" source="nonexistant.sbml"/>
</listOfModels>
<listOfTasks>
<task id="task1" modelReference="mod1" simulationReference="sim1"/>
</listOfTasks>
<listOfDataGenerators>
<dataGenerator id="report_0_0_0" name="time">
<listOfVariables>
<variable id="time" symbol="urn:sedml:symbol:time" taskReference="task1"/>
</listOfVariables>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<ci> time </ci>
</math>
</dataGenerator>
<dataGenerator id="report_0_0_1" name="a">
<listOfVariables>
<variable id="a" target="/sbml:sbml/sbml:model/descendant::*[@id='a']" taskReference="task1" modelReference="mod1"/>
</listOfVariables>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<ci> a </ci>
</math>
</dataGenerator>
</listOfDataGenerators>
<listOfOutputs>
<report id="report_0">
<listOfDataSets>
<dataSet id="report_0_0_0_dataset" label="time" dataReference="report_0_0_0"/>
<dataSet id="report_0_0_1_dataset" label="a" dataReference="report_0_0_1"/>
</listOfDataSets>
</report>
</listOfOutputs>
</sedML>
41 changes: 41 additions & 0 deletions tests/sedml/test_data/no_read_access.sedml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created by phraSED-ML version v0.5beta on 2015-12-01 15:44 with libSBML version 5.11.9. -->
<sedML xmlns="http://sed-ml.org/sed-ml/level1/version2" level="1" version="2">
<listOfSimulations>
<uniformTimeCourse id="sim1" initialTime="0" outputStartTime="0" outputEndTime="10" numberOfPoints="10">
<algorithm kisaoID="KISAO:0000019"/>
</uniformTimeCourse>
</listOfSimulations>
<listOfModels>
<model id="mod1" language="urn:sedml:language:sbml.level-3.version-1" source="00001-sbml.xml"/>
</listOfModels>
<listOfTasks>
<task id="task1" modelReference="mod1" simulationReference="sim1"/>
</listOfTasks>
<listOfDataGenerators>
<dataGenerator id="report_0_0_0" name="time">
<listOfVariables>
<variable id="time" symbol="urn:sedml:symbol:time" taskReference="task1"/>
</listOfVariables>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<ci> time </ci>
</math>
</dataGenerator>
<dataGenerator id="report_0_0_1" name="a">
<listOfVariables>
<variable id="a" target="/sbml:sbml/sbml:model/descendant::*[@id='a']" taskReference="task1" modelReference="mod1"/>
</listOfVariables>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<ci> a </ci>
</math>
</dataGenerator>
</listOfDataGenerators>
<listOfOutputs>
<report id="report_0">
<listOfDataSets>
<dataSet id="report_0_0_0_dataset" label="time" dataReference="report_0_0_0"/>
<dataSet id="report_0_0_1_dataset" label="a" dataReference="report_0_0_1"/>
</listOfDataSets>
</report>
</listOfOutputs>
</sedML>
9 changes: 9 additions & 0 deletions tests/sedml/test_data/valid_doc.sbml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created by libAntimony version v2.8.1 on 2015-12-02 12:55 with libSBML version 5.11.9. -->
<sbml xmlns="http://www.sbml.org/sbml/level3/version1/core" xmlns:comp="http://www.sbml.org/sbml/level3/version1/comp/version1" level="3" version="1" comp:required="true">
<model id="__main" name="__main">
<listOfParameters>
<parameter id="a" value="3" constant="true"/>
</listOfParameters>
</model>
</sbml>
41 changes: 41 additions & 0 deletions tests/sedml/test_data/valid_doc.sedml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created by phraSED-ML version v0.5beta on 2015-12-01 15:44 with libSBML version 5.11.9. -->
<sedML xmlns="http://sed-ml.org/sed-ml/level1/version2" level="1" version="2">
<listOfSimulations>
<uniformTimeCourse id="sim1" initialTime="0" outputStartTime="0" outputEndTime="10" numberOfPoints="10">
<algorithm kisaoID="KISAO:0000019"/>
</uniformTimeCourse>
</listOfSimulations>
<listOfModels>
<model id="mod1" language="urn:sedml:language:sbml.level-3.version-1" source="valid_doc.sbml"/>
</listOfModels>
<listOfTasks>
<task id="task1" modelReference="mod1" simulationReference="sim1"/>
</listOfTasks>
<listOfDataGenerators>
<dataGenerator id="report_0_0_0" name="time">
<listOfVariables>
<variable id="time" symbol="urn:sedml:symbol:time" taskReference="task1"/>
</listOfVariables>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<ci> time </ci>
</math>
</dataGenerator>
<dataGenerator id="report_0_0_1" name="a">
<listOfVariables>
<variable id="a" target="/sbml:sbml/sbml:model/descendant::*[@id='a']" taskReference="task1" modelReference="mod1"/>
</listOfVariables>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<ci> a </ci>
</math>
</dataGenerator>
</listOfDataGenerators>
<listOfOutputs>
<report id="report_0">
<listOfDataSets>
<dataSet id="report_0_0_0_dataset" label="time" dataReference="report_0_0_0"/>
<dataSet id="report_0_0_1_dataset" label="a" dataReference="report_0_0_1"/>
</listOfDataSets>
</report>
</listOfOutputs>
</sedML>
Loading

0 comments on commit c102f3e

Please sign in to comment.