Skip to content

Commit 21b0ba4

Browse files
committed
add a basic test for sciml
1 parent fc9e750 commit 21b0ba4

2 files changed

Lines changed: 159 additions & 6 deletions

File tree

petab/v2/lint.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"CheckUndefinedExperiments",
4646
"CheckInitialChangeSymbols",
4747
"CheckMappingTable",
48+
"CheckHybridizationTable",
4849
"lint_problem",
4950
"default_validation_tasks",
5051
]
@@ -1186,10 +1187,24 @@ def get_placeholders(
11861187

11871188
#: Validation tasks that should be run PEtab SciML problems
11881189
sciml_validation_tasks = [
1190+
CheckProblemConfig(),
1191+
CheckModel(),
1192+
CheckUniquePrimaryKeys(),
1193+
CheckMeasurementModelId(),
1194+
CheckMeasuredObservablesDefined(),
1195+
CheckPosLogMeasurements(),
1196+
CheckOverridesMatchPlaceholders(),
1197+
CheckValidConditionTargets(),
1198+
CheckExperimentTable(),
1199+
CheckExperimentConditionsExist(),
1200+
CheckUndefinedExperiments(),
1201+
CheckObservablesDoNotShadowModelEntities(),
1202+
# CheckAllParametersPresentInParameterTable(),
1203+
CheckValidParameterInConditionOrParameterTable(),
1204+
CheckUnusedExperiments(),
1205+
CheckUnusedConditions(),
1206+
CheckPriorDistribution(),
1207+
CheckInitialChangeSymbols(),
1208+
CheckMappingTable(),
11891209
CheckHybridizationTable(),
1190-
] + list(
1191-
set(default_validation_tasks)
1192-
- {
1193-
CheckAllParametersPresentInParameterTable(),
1194-
}
1195-
)
1210+
]

tests/v2/test_sciml.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import numpy as np
2+
from pydantic import ConfigDict
3+
4+
from petab.v2.core import *
5+
from petab.v2.core import ModelFile, NeuralNetConfig
6+
from petab.v2.lint import sciml_validation_tasks
7+
from petab.v2.models.sbml_model import SbmlModel
8+
9+
10+
def _get_test_problem():
11+
problem = Problem()
12+
problem.validation_tasks = sciml_validation_tasks
13+
problem.config = ProblemConfig(
14+
format_version="2.0.0",
15+
model_files=ConfigDict(
16+
{"lv": ModelFile(location="lv.xml", language="sbml")}
17+
),
18+
parameter_files=["parameters.tsv"],
19+
measurement_files=["measurements.tsv"],
20+
observable_files=["observables.tsv"],
21+
experiment_files=["experiments.tsv"],
22+
mapping_files=["mappings.tsv"],
23+
extensions={
24+
"sciml": {
25+
"version": "0.1.0",
26+
"array_files": ["net1_ps.hdf5"],
27+
"hybridization_files": ["hybridizations.tsv"],
28+
"neural_nets": {
29+
"net1": NeuralNetConfig(
30+
location="net1.yaml",
31+
pre_initialization=False,
32+
format="YAML",
33+
)
34+
},
35+
}
36+
},
37+
)
38+
problem.model = SbmlModel.from_antimony("""
39+
model lv
40+
species A, B;
41+
A = 0.442;
42+
B = 4.63;
43+
alpha = 1.3;
44+
gamma_ = 0.8;
45+
-> A; alpha * A;
46+
B -> ; 1.8 * B;
47+
A -> ; 0.9 * A * B;
48+
-> B; gamma_;
49+
end
50+
""")
51+
problem.add_experiment("e1", 0, "")
52+
problem.add_mapping("net1_input1", "net1.inputs[0][0]")
53+
problem.add_mapping("net1_input2", "net1.inputs[0][1]")
54+
problem.add_mapping("net1_output1", "net1.outputs[0][0]")
55+
problem.add_mapping("net1_ps", "net1.parameters")
56+
problem.add_measurement("B_obs", time=1, measurement=1, experiment_id="e1")
57+
problem.add_observable("B_obs", "B", noise_formula="0.05")
58+
problem.add_parameter(
59+
"alpha", estimate=True, lb=0, ub=15, nominal_value=1.3
60+
)
61+
problem.add_parameter(
62+
"net1_ps", estimate=True, lb=-np.inf, ub=np.inf, nominal_value="array"
63+
)
64+
problem.add_hybridization("net1_input1", "A")
65+
problem.add_hybridization("net1_input2", "B")
66+
problem.add_hybridization("gamma_", "net1_output_1")
67+
problem.add_neural_network_from_dict(
68+
"net1",
69+
nn_dict={
70+
"nn_model_id": "net1",
71+
"inputs": [{"input_id": "input0"}],
72+
"layers": [
73+
{
74+
"layer_id": "layer1",
75+
"layer_type": "Linear",
76+
"args": {
77+
"in_features": 2,
78+
"out_features": 1,
79+
"bias": True,
80+
},
81+
}
82+
],
83+
"forward": [
84+
{
85+
"name": "net_input",
86+
"op": "placeholder",
87+
"target": "net_input",
88+
},
89+
{
90+
"name": "layer1",
91+
"op": "call_module",
92+
"target": "layer1",
93+
"args": ["net_input"],
94+
},
95+
{
96+
"name": "tanh",
97+
"op": "call_method",
98+
"target": "tanh",
99+
"args": ["layer1"],
100+
},
101+
],
102+
},
103+
)
104+
105+
# array data
106+
problem.add_array_data_from_dict(
107+
{
108+
"metadata": {"pytorch_format": True},
109+
"inputs": {},
110+
"parameters": {
111+
"net1": {
112+
"layer1": {
113+
"bias": np.random.randn(2),
114+
"weight": np.random.randn(2),
115+
}
116+
}
117+
},
118+
}
119+
)
120+
121+
# set the filenames
122+
problem.config.filepath = "problem.yaml"
123+
problem.model.rel_path = "lv.xml"
124+
problem.experiment_tables[0].rel_path = "experiments.tsv"
125+
problem.mapping_tables[0].rel_path = "mappings.tsv"
126+
problem.measurement_tables[0].rel_path = "measurements.tsv"
127+
problem.observable_tables[0].rel_path = "observables.tsv"
128+
problem.parameter_tables[0].rel_path = "parameters.tsv"
129+
problem.hybridization_tables[0].rel_path = "hybridizations.tsv"
130+
# problem.neural_networks[0].rel_path = "net1.yaml"
131+
# problem.array_data_files[0].rel_path = "net1_ps.hdf5"
132+
133+
return problem
134+
135+
136+
def test_lint():
137+
problem = _get_test_problem()
138+
assert problem.validate() == []

0 commit comments

Comments
 (0)