OSBModelValidation 0.2.18__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- OSBModelValidation-0.2.18.dist-info/METADATA +184 -0
- OSBModelValidation-0.2.18.dist-info/RECORD +98 -0
- OSBModelValidation-0.2.18.dist-info/WHEEL +5 -0
- OSBModelValidation-0.2.18.dist-info/entry_points.txt +2 -0
- OSBModelValidation-0.2.18.dist-info/top_level.txt +1 -0
- omv/__init__.py +8 -0
- omv/analyzers/__init__.py +21 -0
- omv/analyzers/activation.py +24 -0
- omv/analyzers/analyzer.py +80 -0
- omv/analyzers/dryrun.py +13 -0
- omv/analyzers/input_resistance.py +47 -0
- omv/analyzers/morphology.py +16 -0
- omv/analyzers/rates.py +97 -0
- omv/analyzers/resting.py +37 -0
- omv/analyzers/spikes.py +113 -0
- omv/analyzers/temperature.py +12 -0
- omv/analyzers/timeseries.py +57 -0
- omv/analyzers/utils/__init__.py +0 -0
- omv/analyzers/utils/filenode.py +73 -0
- omv/analyzers/utils/timeseries.py +293 -0
- omv/autogen.py +106 -0
- omv/common/__init__.py +0 -0
- omv/common/inout.py +154 -0
- omv/engines/__init__.py +53 -0
- omv/engines/arbor_.py +57 -0
- omv/engines/brian1.py +59 -0
- omv/engines/brian2_.py +57 -0
- omv/engines/eden_.py +63 -0
- omv/engines/engine.py +111 -0
- omv/engines/genesis.py +86 -0
- omv/engines/getarbor.py +15 -0
- omv/engines/getbrian1.py +42 -0
- omv/engines/getbrian2.py +17 -0
- omv/engines/geteden.py +17 -0
- omv/engines/getgenesis.py +56 -0
- omv/engines/getjlems.py +20 -0
- omv/engines/getjnml.py +48 -0
- omv/engines/getlibsbml.py +13 -0
- omv/engines/getmoose.py +15 -0
- omv/engines/getnest.py +62 -0
- omv/engines/getnetpyne.py +52 -0
- omv/engines/getneuroconstruct.py +31 -0
- omv/engines/getnml2.py +26 -0
- omv/engines/getnrn.py +60 -0
- omv/engines/getoctave.py +11 -0
- omv/engines/getpylems.py +13 -0
- omv/engines/getpyneuroml.py +14 -0
- omv/engines/getpynn.py +40 -0
- omv/engines/jlems.py +48 -0
- omv/engines/jneuroml.py +101 -0
- omv/engines/jneuromlbrian.py +65 -0
- omv/engines/jneuromlbrian2.py +61 -0
- omv/engines/jneuromleden.py +61 -0
- omv/engines/jneuromlmoose.py +63 -0
- omv/engines/jneuromlnetpyne.py +73 -0
- omv/engines/jneuromlnetpyne_np2.py +45 -0
- omv/engines/jneuromlnetpyne_np4.py +45 -0
- omv/engines/jneuromlnrn.py +78 -0
- omv/engines/jneuromlpynnnrn.py +75 -0
- omv/engines/jneuromlvalidate.py +62 -0
- omv/engines/jneuromlvalidatev1.py +58 -0
- omv/engines/moose_.py +86 -0
- omv/engines/nestsli.py +84 -0
- omv/engines/netpyne_.py +120 -0
- omv/engines/netpyne__np2.py +47 -0
- omv/engines/netpyne__np4.py +47 -0
- omv/engines/neuron_.py +205 -0
- omv/engines/octave.py +51 -0
- omv/engines/pylems.py +57 -0
- omv/engines/pylemsnml2.py +59 -0
- omv/engines/pynest.py +111 -0
- omv/engines/pyneuroconstruct.py +67 -0
- omv/engines/pyneuroml_.py +55 -0
- omv/engines/pyneuromlvalidatesbml.py +83 -0
- omv/engines/pyneuron.py +94 -0
- omv/engines/pynn.py +63 -0
- omv/engines/pynnbrian1.py +59 -0
- omv/engines/pynnbrian2.py +60 -0
- omv/engines/pynnnest.py +56 -0
- omv/engines/pynnneuroml.py +57 -0
- omv/engines/pynnneuron.py +94 -0
- omv/engines/utils/__init__.py +21 -0
- omv/engines/utils/genesis_utils.g +26 -0
- omv/engines/utils/wdir.py +15 -0
- omv/experiment.py +18 -0
- omv/find_tests.py +126 -0
- omv/omt_mep_parser.py +59 -0
- omv/omv_util.py +439 -0
- omv/parse_omt.py +118 -0
- omv/tally.py +112 -0
- omv/test/__init__.py +0 -0
- omv/test/test_rates.py +38 -0
- omv/test/test_types.py +29 -0
- omv/validation/__init__.py +0 -0
- omv/validation/rx_validator.py +35 -0
- omv/validation/utils.py +51 -0
- omv/validation/validate.py +53 -0
- omv/validation/validate_mep.py +15 -0
omv/parse_omt.py
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
from omv.engines import OMVEngines
|
|
2
|
+
from omv.engines.engine import EngineInstallationError, EngineExecutionError
|
|
3
|
+
from omv.omt_mep_parser import OMVTestParser
|
|
4
|
+
from omv.common.inout import inform, check, trim_path
|
|
5
|
+
from omv.tally import Tallyman
|
|
6
|
+
import sys
|
|
7
|
+
import platform
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def parse_omt(omt_path, do_not_run=False, engine_version=None, ignore_non_py3=False):
|
|
11
|
+
inform("")
|
|
12
|
+
action = "Running"
|
|
13
|
+
if do_not_run:
|
|
14
|
+
action = "Checking"
|
|
15
|
+
inform(
|
|
16
|
+
action + " the tests defined in ",
|
|
17
|
+
trim_path(omt_path),
|
|
18
|
+
underline="=",
|
|
19
|
+
center=False,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
mepomt = OMVTestParser(omt_path)
|
|
23
|
+
if not mepomt.engine in OMVEngines:
|
|
24
|
+
inform(
|
|
25
|
+
"Error! Unrecognised engine: %s (try running: omv list-engines)"
|
|
26
|
+
% mepomt.engine
|
|
27
|
+
)
|
|
28
|
+
exit(1)
|
|
29
|
+
engine = OMVEngines[mepomt.engine](
|
|
30
|
+
mepomt.modelpath, do_not_check_install=do_not_run, engine_version=engine_version
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
experiments = [exp for exp in mepomt.generate_exps(engine)]
|
|
34
|
+
|
|
35
|
+
tally = Tallyman(mepomt)
|
|
36
|
+
|
|
37
|
+
inform(
|
|
38
|
+
"Found %i experiment(s) to run on engine: %s "
|
|
39
|
+
% (len(experiments), engine.name),
|
|
40
|
+
indent=1,
|
|
41
|
+
)
|
|
42
|
+
# print('%s, %s, %s'%(platform.python_version_tuple()[0],ignore_non_py3,engine.python3_compatible))
|
|
43
|
+
|
|
44
|
+
if (
|
|
45
|
+
platform.python_version_tuple()[0] == "3"
|
|
46
|
+
and ignore_non_py3
|
|
47
|
+
and not engine.python3_compatible
|
|
48
|
+
):
|
|
49
|
+
inform(
|
|
50
|
+
"Not running experiment(s) on: %s, as this is Python %s and engine is not Python 3 compatible..."
|
|
51
|
+
% (engine.name, platform.python_version()),
|
|
52
|
+
indent=1,
|
|
53
|
+
)
|
|
54
|
+
tally.report_passing_if_no_exps = True
|
|
55
|
+
|
|
56
|
+
elif not do_not_run:
|
|
57
|
+
try:
|
|
58
|
+
engine.run()
|
|
59
|
+
some_failed = False
|
|
60
|
+
for exp in experiments:
|
|
61
|
+
inform("Running checks for experiment: ", exp.name, indent=1)
|
|
62
|
+
inform("")
|
|
63
|
+
results = exp.check_all()
|
|
64
|
+
inform(
|
|
65
|
+
"{:<30}{:^20}".format("Observable", "Test Passed"),
|
|
66
|
+
underline="-",
|
|
67
|
+
indent=3,
|
|
68
|
+
)
|
|
69
|
+
for rn, rv in results.items():
|
|
70
|
+
if sys.version_info >= (3, 0):
|
|
71
|
+
inform("{:<30}{:^20}".format(rn, check(rv)), indent=3)
|
|
72
|
+
else:
|
|
73
|
+
inform("{:<30}{:^20}".format(rn, check(rv)), indent=3)
|
|
74
|
+
if not rv:
|
|
75
|
+
some_failed = True
|
|
76
|
+
tally.add_experiment(exp, results)
|
|
77
|
+
|
|
78
|
+
if some_failed:
|
|
79
|
+
inform("+++++++++++++++++++++ Error info ++++++++++++++++++", indent=3)
|
|
80
|
+
inform(" Return code: %s" % engine.returncode, indent=3)
|
|
81
|
+
if hasattr(engine, "stdout"):
|
|
82
|
+
if isinstance(engine.stdout, str):
|
|
83
|
+
out = engine.stdout
|
|
84
|
+
else:
|
|
85
|
+
out = str(engine.stdout.decode())
|
|
86
|
+
inform(
|
|
87
|
+
" Output: %s"
|
|
88
|
+
% out.replace(
|
|
89
|
+
"\n", "\n[omv] %s:%s > " % (mepomt.omt_path, exp.name)
|
|
90
|
+
),
|
|
91
|
+
indent=3,
|
|
92
|
+
)
|
|
93
|
+
inform("+++++++++++++++++++++++++++++++++++++++++++++++++++", indent=3)
|
|
94
|
+
|
|
95
|
+
except (EngineInstallationError, EngineExecutionError):
|
|
96
|
+
# TODO: serialize exception info
|
|
97
|
+
inform(
|
|
98
|
+
"ERROR running engine ",
|
|
99
|
+
engine.name,
|
|
100
|
+
indent=1,
|
|
101
|
+
underline="-",
|
|
102
|
+
overline="-",
|
|
103
|
+
)
|
|
104
|
+
inform("+++++++++++++++++++++ Error info ++++++++++++++++++", indent=3)
|
|
105
|
+
inform(" Return code: %s" % engine.returncode, indent=3)
|
|
106
|
+
if hasattr(engine, "stdout"):
|
|
107
|
+
if isinstance(engine.stdout, str):
|
|
108
|
+
out = engine.stdout
|
|
109
|
+
else:
|
|
110
|
+
out = str(engine.stdout.decode())
|
|
111
|
+
inform(
|
|
112
|
+
" Output: %s"
|
|
113
|
+
% out.replace("\n", "\n[omv] %s > " % (mepomt.omt_path)),
|
|
114
|
+
indent=3,
|
|
115
|
+
)
|
|
116
|
+
inform("+++++++++++++++++++++++++++++++++++++++++++++++++++", indent=3)
|
|
117
|
+
|
|
118
|
+
return tally
|
omv/tally.py
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
from collections import OrderedDict
|
|
2
|
+
from omv.common.inout import trim_path
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Tallyman(object):
|
|
6
|
+
def __init__(self, mepomt):
|
|
7
|
+
self.omt = mepomt.omt_path
|
|
8
|
+
self.mep = mepomt.mep_path
|
|
9
|
+
self.engine = mepomt.engine
|
|
10
|
+
self.modelpath = mepomt.modelpath
|
|
11
|
+
self.experiments = {}
|
|
12
|
+
self.report_passing_if_no_exps = False
|
|
13
|
+
|
|
14
|
+
def all_passed(self):
|
|
15
|
+
alltrue = True if any(self.experiments) else self.report_passing_if_no_exps
|
|
16
|
+
for res in self.experiments.values():
|
|
17
|
+
alltrue = alltrue and all(res.values())
|
|
18
|
+
return alltrue
|
|
19
|
+
|
|
20
|
+
def add_experiment(self, exp, results):
|
|
21
|
+
self.experiments[exp.name] = results
|
|
22
|
+
|
|
23
|
+
def __lt__(self, other):
|
|
24
|
+
if other.mep == None:
|
|
25
|
+
return True
|
|
26
|
+
return self.omt < other.omt
|
|
27
|
+
|
|
28
|
+
def serialize(self):
|
|
29
|
+
s = OrderedDict({"engine": self.engine})
|
|
30
|
+
s["MEP file"] = self.mep
|
|
31
|
+
s["OMT file"] = self.omt
|
|
32
|
+
s["Model path"] = self.modelpath
|
|
33
|
+
s["Experiments"] = self.experiments
|
|
34
|
+
s["All Passed"] = self.all_passed()
|
|
35
|
+
# return dump(s, default_flow_style=False)
|
|
36
|
+
return s
|
|
37
|
+
|
|
38
|
+
def __repr__(self):
|
|
39
|
+
return str(self.serialize())
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class TallyHolder(object):
|
|
43
|
+
tallies = {}
|
|
44
|
+
all_engines = []
|
|
45
|
+
|
|
46
|
+
def add(self, tally):
|
|
47
|
+
if not tally.engine in self.all_engines:
|
|
48
|
+
self.all_engines.append(tally.engine)
|
|
49
|
+
|
|
50
|
+
mp = trim_path(tally.modelpath)
|
|
51
|
+
|
|
52
|
+
if not mp in self.tallies:
|
|
53
|
+
self.tallies[mp] = {}
|
|
54
|
+
|
|
55
|
+
mptallies = self.tallies[mp]
|
|
56
|
+
|
|
57
|
+
if not tally.engine in mptallies:
|
|
58
|
+
mptallies[tally.engine] = []
|
|
59
|
+
|
|
60
|
+
mptallies[tally.engine].append(tally)
|
|
61
|
+
|
|
62
|
+
def summary(self):
|
|
63
|
+
width1 = 60
|
|
64
|
+
border = "+" + "-" * width1 + "+"
|
|
65
|
+
header = "|" + " " * width1 + "| "
|
|
66
|
+
|
|
67
|
+
totals = {}
|
|
68
|
+
for engine in self.all_engines:
|
|
69
|
+
border += "-" * (len(engine) + 2) + "+"
|
|
70
|
+
header += engine + " | "
|
|
71
|
+
totals[engine] = 0
|
|
72
|
+
|
|
73
|
+
summary = "%s\n%s\n%s\n" % (border, header, border)
|
|
74
|
+
|
|
75
|
+
for mp in self.tallies.keys():
|
|
76
|
+
mp_ = mp
|
|
77
|
+
max = width1 - 2
|
|
78
|
+
if len(mp_) > max:
|
|
79
|
+
pre = 8
|
|
80
|
+
mp_ = "%s(...)%s" % (mp_[:pre], mp_[-1 * (max - pre - 6) :])
|
|
81
|
+
|
|
82
|
+
summary += "| " + mp_ + " " * (width1 - len(mp_) - 2) + " | "
|
|
83
|
+
|
|
84
|
+
mptallies = self.tallies[mp]
|
|
85
|
+
|
|
86
|
+
for engine in self.all_engines:
|
|
87
|
+
if not engine in mptallies:
|
|
88
|
+
info = "%s" % (" ")
|
|
89
|
+
summary += " " * (len(engine) - len(info) - 2) + info + " | "
|
|
90
|
+
else:
|
|
91
|
+
tals = mptallies[engine]
|
|
92
|
+
for t in tals:
|
|
93
|
+
if t.engine == engine:
|
|
94
|
+
info = "%s" % (len(t.experiments))
|
|
95
|
+
if not t.mep:
|
|
96
|
+
info += "d"
|
|
97
|
+
if not t.all_passed():
|
|
98
|
+
info += "X"
|
|
99
|
+
totals[engine] += len(t.experiments)
|
|
100
|
+
summary += (
|
|
101
|
+
" " * (len(engine) - len(info) - 2) + info + " | "
|
|
102
|
+
)
|
|
103
|
+
summary += "\n"
|
|
104
|
+
|
|
105
|
+
summary += border + "\n" + "| Totals: " + " " * (width1 - 9) + "| "
|
|
106
|
+
|
|
107
|
+
for engine in self.all_engines:
|
|
108
|
+
info = "%s" % (totals[engine])
|
|
109
|
+
summary += " " * (len(engine) - len(info) - 2) + info + " | "
|
|
110
|
+
|
|
111
|
+
summary += "\n" + border
|
|
112
|
+
return summary
|
omv/test/__init__.py
ADDED
|
File without changes
|
omv/test/test_rates.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from omv.common.inout import set_verbosity
|
|
2
|
+
|
|
3
|
+
from omv.analyzers.utils.timeseries import *
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_rates():
|
|
7
|
+
set_verbosity(2)
|
|
8
|
+
|
|
9
|
+
tsNone = []
|
|
10
|
+
tsA = [0.1]
|
|
11
|
+
tsB = [0.1, 0.2]
|
|
12
|
+
|
|
13
|
+
ts1 = [0.1, 0.2, 0.3, 0.40]
|
|
14
|
+
ts2 = [0.1, 0.3, 0.50]
|
|
15
|
+
|
|
16
|
+
methods = [ISI_BASED_SPIKERATE_CALC, DURATION_BASED_SPIKERATE_CALC]
|
|
17
|
+
|
|
18
|
+
for method in methods:
|
|
19
|
+
opts = [tsNone, tsA, tsB, ts1, ts2, {"0": ts1}, {"0": ts1, "1": ts2}]
|
|
20
|
+
exp = {}
|
|
21
|
+
exp[ISI_BASED_SPIKERATE_CALC] = [0, 0, 10, 10, 0, 10, 5]
|
|
22
|
+
exp[DURATION_BASED_SPIKERATE_CALC] = [0, 4, 8, 8, 4, 8, 6]
|
|
23
|
+
|
|
24
|
+
for i in range(len(opts)):
|
|
25
|
+
opt = opts[i]
|
|
26
|
+
start_time = 0
|
|
27
|
+
end_time = 0.25
|
|
28
|
+
r = get_spike_rate(opt, method, start_time, end_time)
|
|
29
|
+
inform(
|
|
30
|
+
" > Rate in %s->%s (%s) for %s: %s\n"
|
|
31
|
+
% (start_time, end_time, method, opt, r),
|
|
32
|
+
indent=2,
|
|
33
|
+
)
|
|
34
|
+
assert r == exp[method][i]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
if __name__ == "__main__":
|
|
38
|
+
test_rates()
|
omv/test/test_types.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import glob
|
|
2
|
+
from os.path import splitext, basename, normpath
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def _walk_testdir(root, validator):
|
|
6
|
+
for f in glob.glob(root + "/test/*.yaml"):
|
|
7
|
+
print("found test document", f)
|
|
8
|
+
fname = splitext(basename(f))[0]
|
|
9
|
+
try:
|
|
10
|
+
target = fname[: fname.rindex(".")]
|
|
11
|
+
except ValueError:
|
|
12
|
+
target = fname
|
|
13
|
+
|
|
14
|
+
schema_src = normpath("".join([root, "/", target, ".yaml"]))
|
|
15
|
+
print("using schema", schema_src)
|
|
16
|
+
assert validator.validate(schema_src, f)
|
|
17
|
+
print("valid!\n")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_base():
|
|
21
|
+
from ..validation.rx_validator import RXSchemaValidator as v
|
|
22
|
+
|
|
23
|
+
_walk_testdir("../schemata/types/base", v())
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_derived():
|
|
27
|
+
from ..validation.validate import OMVValidator as o
|
|
28
|
+
|
|
29
|
+
_walk_testdir("../schemata/types", o())
|
|
File without changes
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import pyrx
|
|
2
|
+
import yaml
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class RXSchemaValidator(object):
|
|
6
|
+
def __init__(self):
|
|
7
|
+
self.rx = pyrx.Factory({"register_core_types": True})
|
|
8
|
+
|
|
9
|
+
def generate_schema(self, schema_src):
|
|
10
|
+
schema = self.parse_yaml_file(schema_src)
|
|
11
|
+
print("generating schema from %s" % schema)
|
|
12
|
+
return self.rx.make_schema(schema)
|
|
13
|
+
|
|
14
|
+
def parse_yaml_file(self, fname):
|
|
15
|
+
with open(fname) as f:
|
|
16
|
+
y = yaml.safe_load(f)
|
|
17
|
+
return y
|
|
18
|
+
|
|
19
|
+
def validate(self, schema_src, doc_src):
|
|
20
|
+
doc = self.parse_yaml_file(doc_src)
|
|
21
|
+
print("validating document %s" % doc)
|
|
22
|
+
return self.generate_schema(schema_src).check(doc)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
if __name__ == "__main__":
|
|
26
|
+
import sys
|
|
27
|
+
|
|
28
|
+
try:
|
|
29
|
+
schema_src, doc_src = sys.argv[1:]
|
|
30
|
+
except:
|
|
31
|
+
print("usage: validate_rx.py schema.yaml document.yaml")
|
|
32
|
+
sys.exit(1)
|
|
33
|
+
|
|
34
|
+
s = RXSchemaValidator()
|
|
35
|
+
print(s.validate(schema_src, doc_src))
|
omv/validation/utils.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
def topological_sort(source):
|
|
2
|
+
"""perform topo sort on elements.
|
|
3
|
+
|
|
4
|
+
:arg source: list of ``(name, [list of dependancies])`` pairs
|
|
5
|
+
:returns: list of names, with dependancies listed first
|
|
6
|
+
"""
|
|
7
|
+
pending = [
|
|
8
|
+
(name, set(deps)) for name, deps in source
|
|
9
|
+
] # copy deps so we can modify set in-place
|
|
10
|
+
emitted = []
|
|
11
|
+
while pending:
|
|
12
|
+
next_pending = []
|
|
13
|
+
next_emitted = []
|
|
14
|
+
for entry in pending:
|
|
15
|
+
name, deps = entry
|
|
16
|
+
deps.difference_update(emitted) # remove deps we emitted last pass
|
|
17
|
+
if deps: # still has deps? recheck during next pass
|
|
18
|
+
next_pending.append(entry)
|
|
19
|
+
else: # no more deps? time to emit
|
|
20
|
+
yield name
|
|
21
|
+
emitted.append(
|
|
22
|
+
name
|
|
23
|
+
) # <-- not required, but helps preserve original ordering
|
|
24
|
+
next_emitted.append(
|
|
25
|
+
name
|
|
26
|
+
) # remember what we emitted for difference_update() in next pass
|
|
27
|
+
if (
|
|
28
|
+
not next_emitted
|
|
29
|
+
): # all entries have unmet deps, one of two things is wrong...
|
|
30
|
+
raise ValueError(
|
|
31
|
+
"cyclic or missing dependancy detected: %r" % (next_pending,)
|
|
32
|
+
)
|
|
33
|
+
pending = next_pending
|
|
34
|
+
emitted = next_emitted
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def all_types_in_schema(d):
|
|
38
|
+
for k, v in d.items():
|
|
39
|
+
if isinstance(v, dict):
|
|
40
|
+
for x in all_types_in_schema(v):
|
|
41
|
+
yield x
|
|
42
|
+
elif isinstance(v, list):
|
|
43
|
+
for el in v:
|
|
44
|
+
for x in all_types_in_schema(el):
|
|
45
|
+
yield x
|
|
46
|
+
else:
|
|
47
|
+
try:
|
|
48
|
+
if v.startswith("/omv"):
|
|
49
|
+
yield v
|
|
50
|
+
except AttributeError:
|
|
51
|
+
pass
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from os.path import splitext, basename
|
|
2
|
+
from omv.validation.rx_validator import RXSchemaValidator
|
|
3
|
+
from omv.validation.utils import topological_sort, all_types_in_schema
|
|
4
|
+
from pkg_resources import resource_filename
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class OMVValidator(RXSchemaValidator):
|
|
8
|
+
def __init__(self):
|
|
9
|
+
super(OMVValidator, self).__init__()
|
|
10
|
+
self.add_osb_prefix()
|
|
11
|
+
self.register_osb_types()
|
|
12
|
+
|
|
13
|
+
def add_osb_prefix(self):
|
|
14
|
+
self.prefix = "tag:opensourcebrain.org,2014:schemata/omv/"
|
|
15
|
+
self.rx.add_prefix("omv", self.prefix)
|
|
16
|
+
|
|
17
|
+
def register_osb_types(self):
|
|
18
|
+
self.omv_types = {}
|
|
19
|
+
from glob import glob
|
|
20
|
+
|
|
21
|
+
typedir = resource_filename("omv", "schemata/types/")
|
|
22
|
+
for omv in glob(typedir + "*.yaml") + glob(typedir + "/base/*.yaml"):
|
|
23
|
+
tag = self.prefix + splitext(basename(omv))[0]
|
|
24
|
+
print("registering", tag)
|
|
25
|
+
self.omv_types[tag] = self.parse_yaml_file(omv)
|
|
26
|
+
|
|
27
|
+
for tag in self.sort_types_by_dependencies(self.omv_types):
|
|
28
|
+
schema = self.omv_types[tag]
|
|
29
|
+
print("learning", tag)
|
|
30
|
+
print("with schema", schema)
|
|
31
|
+
self.rx.learn_type(tag, schema)
|
|
32
|
+
|
|
33
|
+
def sort_types_by_dependencies(self, tag_schema_map):
|
|
34
|
+
alldeps = []
|
|
35
|
+
for tag, schema in tag_schema_map.items():
|
|
36
|
+
depset = set([self.prefix + v[5:] for v in all_types_in_schema(schema)])
|
|
37
|
+
alldeps.append((tag, depset))
|
|
38
|
+
|
|
39
|
+
return topological_sort(alldeps)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
if __name__ == "__main__":
|
|
43
|
+
import sys
|
|
44
|
+
|
|
45
|
+
try:
|
|
46
|
+
schema_src, doc_src = sys.argv[1:]
|
|
47
|
+
except:
|
|
48
|
+
print("usage: validate.py schema.yaml document.yaml")
|
|
49
|
+
sys.exit(1)
|
|
50
|
+
|
|
51
|
+
s = OMVValidator()
|
|
52
|
+
# print('validating document againt schema'
|
|
53
|
+
print(s.validate(schema_src, doc_src))
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
import sys
|
|
3
|
+
from omv.validation.validate import OMVValidator
|
|
4
|
+
from pkg_resources import resource_filename
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def validate(mep_src):
|
|
8
|
+
s = OMVValidator()
|
|
9
|
+
print("Validating document againt mep schema: ")
|
|
10
|
+
schema = resource_filename("omv", "schemata/mep.yaml")
|
|
11
|
+
print(s.validate(schema, mep_src))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
if __name__ == "__main__":
|
|
15
|
+
validate(sys.argv[1])
|