-
Notifications
You must be signed in to change notification settings - Fork 45
/
test_petab_import.py
182 lines (149 loc) · 5.93 KB
/
test_petab_import.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
"""
This is for testing the petab import.
"""
import os
import unittest
import amici
import benchmark_models_petab as models
import numpy as np
import petab
import pytest
import pypesto
import pypesto.optimize
import pypesto.petab
from .test_sbml_conversion import ATOL, RTOL
class PetabImportTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.petab_problems = []
cls.petab_importers = []
cls.obj_edatas = []
def test_0_import(self):
for model_name in ["Zheng_PNAS2012", "Boehm_JProteomeRes2014"]:
# test yaml import for one model:
yaml_config = os.path.join(
models.MODELS_DIR, model_name, model_name + '.yaml'
)
petab_problem = petab.Problem.from_yaml(yaml_config)
self.petab_problems.append(petab_problem)
def test_1_compile(self):
for petab_problem in self.petab_problems:
importer = pypesto.petab.PetabImporter(petab_problem)
self.petab_importers.append(importer)
# check model
model = importer.create_model(force_compile=False)
# observable ids
model_obs_ids = list(model.getObservableIds())
problem_obs_ids = list(petab_problem.get_observable_ids())
self.assertEqual(set(model_obs_ids), set(problem_obs_ids))
# also other checks would be possible here
def test_2_simulate(self):
for petab_importer in self.petab_importers:
obj = petab_importer.create_objective()
edatas = petab_importer.create_edatas()
self.obj_edatas.append((obj, edatas))
# run function
x_nominal = petab_importer.petab_problem.x_nominal_scaled
ret = obj(x_nominal)
self.assertTrue(np.isfinite(ret))
def test_3_optimize(self):
# run optimization
for obj_edatas, importer in zip(self.obj_edatas, self.petab_importers):
obj = obj_edatas[0]
optimizer = pypesto.optimize.ScipyOptimizer(
options={'maxiter': 10}
)
problem = importer.create_problem(obj)
startpoints = importer.create_startpoint_method()
result = pypesto.optimize.minimize(
problem=problem,
optimizer=optimizer,
n_starts=2,
startpoint_method=startpoints,
progress_bar=False,
)
self.assertTrue(np.isfinite(result.optimize_result.fval[0]))
def test_check_gradients(self):
"""Test objective FD-gradient check function."""
# Check gradients of simple model (should always be a true positive)
model_name = "Bachmann_MSB2011"
petab_problem = pypesto.petab.PetabImporter.from_yaml(
os.path.join(models.MODELS_DIR, model_name, model_name + '.yaml')
)
objective = petab_problem.create_objective()
objective.amici_solver.setSensitivityMethod(
amici.SensitivityMethod_forward
)
objective.amici_solver.setAbsoluteTolerance(1e-10)
objective.amici_solver.setRelativeTolerance(1e-12)
self.assertFalse(
petab_problem.check_gradients(multi_eps=[1e-3, 1e-4, 1e-5])
)
def test_plist_mapping():
"""Test that the AMICI objective created via PEtab correctly maps
gradient entries when some parameters are not estimated (realized via
edata.plist)."""
model_name = "Boehm_JProteomeRes2014"
petab_problem = pypesto.petab.PetabImporter.from_yaml(
os.path.join(models.MODELS_DIR, model_name, model_name + '.yaml')
)
# define test parameter
par = np.asarray(petab_problem.petab_problem.x_nominal_scaled)
problem = petab_problem.create_problem()
objective = problem.objective
# check that x_names are correctly subsetted
assert objective.x_names == [
problem.x_names[ix] for ix in problem.x_free_indices
]
objective.amici_solver.setSensitivityMethod(
amici.SensitivityMethod_forward
)
objective.amici_solver.setAbsoluteTolerance(1e-10)
objective.amici_solver.setRelativeTolerance(1e-12)
df = objective.check_grad_multi_eps(
par[problem.x_free_indices], multi_eps=[1e-3, 1e-4, 1e-5]
)
print("relative errors gradient: ", df.rel_err.values)
print("absolute errors gradient: ", df.abs_err.values)
assert np.all((df.rel_err.values < RTOL) | (df.abs_err.values < ATOL))
def test_max_sensi_order():
"""Test that the AMICI objective created via PEtab exposes derivatives
correctly."""
model_name = "Boehm_JProteomeRes2014"
problem = pypesto.petab.PetabImporter.from_yaml(
os.path.join(models.MODELS_DIR, model_name, model_name + '.yaml')
)
# define test parameter
par = problem.petab_problem.x_nominal_scaled
npar = len(par)
# auto-computed max_sensi_order and fim_for_hess
objective = problem.create_objective()
hess = objective(par, sensi_orders=(2,))
assert hess.shape == (npar, npar)
assert (hess != 0).any()
objective.amici_solver.setSensitivityMethod(
amici.SensitivityMethod_adjoint
)
with pytest.raises(ValueError):
objective(par, sensi_orders=(2,))
objective.amici_solver.setSensitivityMethod(
amici.SensitivityMethod_forward
)
# fix max_sensi_order to 1
objective = problem.create_objective(max_sensi_order=1)
objective(par, sensi_orders=(1,))
with pytest.raises(ValueError):
objective(par, sensi_orders=(2,))
# do not use FIM
objective = problem.create_objective(fim_for_hess=False)
with pytest.raises(ValueError):
objective(par, sensi_orders=(2,))
# only allow computing function values
objective = problem.create_objective(max_sensi_order=0)
objective(par)
with pytest.raises(ValueError):
objective(par, sensi_orders=(1,))
if __name__ == '__main__':
suite = unittest.TestSuite()
suite.addTest(PetabImportTest())
unittest.main()