From 316d94dc9266188939b221dd17e7d59304ae58f3 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Wed, 15 Nov 2023 12:37:12 +0100 Subject: [PATCH 1/3] Easier access to timepoints via ExpDataView (#2193) ExpDataView provides convenient access to measurements and the like as numpy arrays. However, accessing the associated timepoints is currently only possible via `ExpDataView(...)._swigptr.ts_` which returns an amici.amici.DoubleVector. That's awkward. Now: ```python amici.ExpDataView(amici.ExpData(1, 2, 3, [4, 5, 6])).ts Out[3]: array([4., 5., 6.]) ``` Resolves #2191 --- python/sdist/amici/numpy.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/sdist/amici/numpy.py b/python/sdist/amici/numpy.py index d9b34b6447..7a917d6c98 100644 --- a/python/sdist/amici/numpy.py +++ b/python/sdist/amici/numpy.py @@ -343,6 +343,7 @@ class ExpDataView(SwigPtrView): """ _field_names = [ + "ts", "observedData", "observedDataStdDev", "observedEvents", @@ -363,7 +364,9 @@ def __init__(self, edata: Union[ExpDataPtr, ExpData]): f"Unsupported pointer {type(edata)}, must be" f"amici.ExpDataPtr!" ) - self._field_dimensions = { # observables + self._field_dimensions = { + "ts": [edata.nt()], + # observables "observedData": [edata.nt(), edata.nytrue()], "observedDataStdDev": [edata.nt(), edata.nytrue()], # event observables @@ -378,6 +381,7 @@ def __init__(self, edata: Union[ExpDataPtr, ExpData]): len(edata.fixedParametersPreequilibration) ], } + edata.ts = edata.ts_ edata.observedData = edata.getObservedData() edata.observedDataStdDev = edata.getObservedDataStdDev() edata.observedEvents = edata.getObservedEvents() From eccdc1f31362fb47319df9cc87891e9f3d3f0804 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Wed, 15 Nov 2023 14:38:01 +0100 Subject: [PATCH 2/3] Nicer __repr__ for ReturnDataView (#2192) Previously: ``` >)> ``` Now: ``` ``` --- python/sdist/amici/numpy.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python/sdist/amici/numpy.py b/python/sdist/amici/numpy.py index 7a917d6c98..03786dc262 100644 --- a/python/sdist/amici/numpy.py +++ b/python/sdist/amici/numpy.py @@ -297,6 +297,10 @@ def __getitem__( return super().__getitem__(item) + def __repr__(self): + status = amici.simulation_status_to_str(self._swigptr.status) + return f"<{self.__class__.__name__}(id={self._swigptr.id!r}, status={status})>" + def by_id( self, entity_id: str, field: str = None, model: Model = None ) -> np.array: From 187362a93fc397548ebe9f524d48a3de6dda116e Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Wed, 15 Nov 2023 17:13:35 +0100 Subject: [PATCH 3/3] Fix ExpData equality operator for Python (#2194) Wasn't automatically handled by swig for unclear reasons. Works now. Fixes #2190. --- python/tests/test_swig_interface.py | 9 +++++++++ swig/edata.i | 3 +++ 2 files changed, 12 insertions(+) diff --git a/python/tests/test_swig_interface.py b/python/tests/test_swig_interface.py index b1afa0b76b..8c895eb852 100644 --- a/python/tests/test_swig_interface.py +++ b/python/tests/test_swig_interface.py @@ -442,3 +442,12 @@ def test_edata_repr(): assert expected_str in repr(e) # avoid double delete!! edata_ptr.release() + + +def test_edata_equality_operator(): + e1 = amici.ExpData(1, 2, 3, [3]) + e2 = amici.ExpData(1, 2, 3, [3]) + assert e1 == e2 + # check that comparison with other types works + # this is not implemented by swig by default + assert e1 != 1 diff --git a/swig/edata.i b/swig/edata.i index 59dcb4fa8a..5dd46c95ee 100644 --- a/swig/edata.i +++ b/swig/edata.i @@ -74,6 +74,9 @@ def _edata_repr(self: "ExpData"): %pythoncode %{ def __repr__(self): return _edata_repr(self) + +def __eq__(self, other): + return other.__class__ == self.__class__ and __eq__(self, other) %} }; %extend std::unique_ptr {