Skip to content

Commit 9ef2e36

Browse files
Fabian Fröhlichdweindl
andauthored
add ExpData __repr__ (#1948)
* add edata __repr__ fixes #1941 * add test * improve tests * fix * fix test * added __repr__ to SwigPtrView * fix counts * add info from SimulationParameters * fixup * Update python/sdist/amici/numpy.py Co-authored-by: Daniel Weindl <[email protected]> Co-authored-by: Daniel Weindl <[email protected]>
1 parent f12f830 commit 9ef2e36

File tree

3 files changed

+108
-5
lines changed

3 files changed

+108
-5
lines changed

python/sdist/amici/numpy.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,14 @@ def __deepcopy__(self, memo):
141141
other._cache = copy.deepcopy(self._cache)
142142
return other
143143

144+
def __repr__(self):
145+
"""
146+
String representation of the object
147+
148+
:returns: string representation
149+
"""
150+
return f'<{self.__class__.__name__}({self._swigptr})>'
151+
144152

145153
class ReturnDataView(SwigPtrView):
146154
"""

python/tests/test_swig_interface.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -406,12 +406,31 @@ def test_model_instance_settings_custom_x0(pysb_example_presimulation_module):
406406

407407
def test_solver_repr():
408408
for solver in (amici.CVodeSolver(), amici.IDASolver()):
409-
assert "maxsteps" in str(solver)
410-
assert "maxsteps" in repr(solver)
411-
412409
solver_ptr = amici.SolverPtr(solver.this)
413-
assert "maxsteps" in str(solver_ptr)
414-
assert "maxsteps" in repr(solver_ptr)
410+
for s in (solver, solver_ptr):
411+
assert "maxsteps" in str(s)
412+
assert "maxsteps" in repr(s)
415413
# avoid double delete!!
416414
solver_ptr.release()
417415

416+
417+
def test_edata_repr():
418+
ny = 1
419+
nz = 2
420+
ne = 3
421+
nt = 4
422+
edata = amici.ExpData(ny, nz, ne, range(nt))
423+
edata_ptr = amici.ExpDataPtr(edata.this)
424+
expected_strs = (
425+
f'{nt}x{ny} time-resolved datapoints',
426+
f'{ne}x{nz} event-resolved datapoints',
427+
f'(0/{ny * nt} measurements',
428+
f'(0/{nz * ne} measurements'
429+
)
430+
for e in [edata, edata_ptr]:
431+
for expected_str in expected_strs:
432+
assert expected_str in str(e)
433+
assert expected_str in repr(e)
434+
# avoid double delete!!
435+
edata_ptr.release()
436+

swig/edata.i

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,81 @@ using namespace amici;
88

99
%ignore ConditionContext;
1010

11+
// ExpData.__repr__
12+
%pythoncode %{
13+
def _edata_repr(self: "ExpData"):
14+
n_data_y = sum(
15+
self.isSetObservedData(it, iy)
16+
for it in range(self.nt()) for
17+
iy in range(self.nytrue())
18+
)
19+
n_sigma_y = sum(
20+
self.isSetObservedDataStdDev(it, iy)
21+
for it in range(self.nt())
22+
for iy in range(self.nytrue())
23+
)
24+
n_data_z = sum(
25+
self.isSetObservedEvents(ie, iz)
26+
for ie in range(self.nmaxevent())
27+
for iz in range(self.nztrue())
28+
)
29+
n_sigma_z = sum(
30+
self.isSetObservedEventsStdDev(ie, iz)
31+
for ie in range(self.nmaxevent())
32+
for iz in range(self.nztrue())
33+
)
34+
35+
custom_simulation_settings = []
36+
if self.pscale:
37+
custom_simulation_settings.append(f"parameter scales")
38+
if self.fixedParameters:
39+
custom_simulation_settings.append(f"constants")
40+
if self.fixedParametersPreequilibration:
41+
custom_simulation_settings.append(f"pre-equilibration condition")
42+
if self.t_presim:
43+
tmp = f"pre-simulation condition (t={self.t_presim})"
44+
if self.fixedParametersPresimulation:
45+
tmp += " with custom constants"
46+
custom_simulation_settings.append(tmp)
47+
if self.reinitializeFixedParameterInitialStates and self.reinitialization_state_idxs_sim:
48+
custom_simulation_settings.append(f"{len(self.reinitialization_state_idxs_sim)} reinitialized states (simulation)")
49+
if self.reinitializeFixedParameterInitialStates and self.reinitialization_state_idxs_presim:
50+
custom_simulation_settings.append(f"{len(self.reinitialization_state_idxs_presim)} reinitialized states (presimulation)")
51+
if self.parameters:
52+
custom_simulation_settings.append(f"parameters")
53+
if self.x0:
54+
custom_simulation_settings.append(f"initial states")
55+
if self.sx0:
56+
custom_simulation_settings.append(f"initial state sensitivities")
57+
58+
if custom_simulation_settings:
59+
custom_simulation_settings = " with custom " + ", ".join(custom_simulation_settings)
60+
else:
61+
custom_simulation_settings = " without custom settings"
62+
63+
return "\n".join([
64+
self.this.__repr__()[:-1],
65+
f" condition {id} starting at t={self.tstart_}" + custom_simulation_settings,
66+
f" {self.nt()}x{self.nytrue()} time-resolved datapoints",
67+
f" ({n_data_y}/{self.nt()*self.nytrue()} measurements & {n_sigma_y}/{self.nt()*self.nytrue()} sigmas set)",
68+
f" {self.nmaxevent()}x{self.nztrue()} event-resolved datapoints",
69+
f" ({n_data_z}/{self.nmaxevent()*self.nztrue()} measurements & {n_sigma_z}/{self.nmaxevent()*self.nztrue()} sigmas set)",
70+
">"
71+
])
72+
%}
73+
%extend amici::ExpData {
74+
%pythoncode %{
75+
def __repr__(self):
76+
return _edata_repr(self)
77+
%}
78+
};
79+
%extend std::unique_ptr<amici::ExpData> {
80+
%pythoncode %{
81+
def __repr__(self):
82+
return _edata_repr(self)
83+
%}
84+
};
85+
86+
1187
// Process symbols in header
1288
%include "amici/edata.h"

0 commit comments

Comments
 (0)