diff --git a/pyerrors/obs.py b/pyerrors/obs.py index df22a36c..24ef3720 100644 --- a/pyerrors/obs.py +++ b/pyerrors/obs.py @@ -1,4 +1,5 @@ import warnings +import hashlib import pickle from math import gcd from functools import reduce @@ -684,6 +685,15 @@ class Obs: else: return '{:.0f}({:2.0f})'.format(self.value, self._dvalue) + def __hash__(self): + hash_tuple = (np.array([self.value]).astype(np.float32).data.tobytes(),) + hash_tuple += tuple([o.astype(np.float32).data.tobytes() for o in self.deltas.values()]) + hash_tuple += tuple([np.array([o.errsq()]).astype(np.float32).data.tobytes() for o in self.covobs.values()]) + hash_tuple += tuple([o.encode() for o in self.names]) + m = hashlib.md5() + [m.update(o) for o in hash_tuple] + return int(m.hexdigest(), 16) & 0xFFFFFFFF + # Overload comparisons def __lt__(self, other): return self.value < other diff --git a/tests/obs_test.py b/tests/obs_test.py index 1665ef62..d58933c9 100644 --- a/tests/obs_test.py +++ b/tests/obs_test.py @@ -950,3 +950,16 @@ def test_cobs_array(): cobs * np.identity(4) np.identity(4) / cobs cobs / np.ones((4, 4)) + + +def test_hash(): + obs = pe.pseudo_Obs(0.3, 0.1, "test") + pe.Obs([np.random.normal(2.3, 0.2, 200)], ["test2"], [range(1, 400, 2)]) + o1 = obs + pe.cov_Obs(0.0, 0.1, "co") + pe.cov_Obs(0.0, 0.8, "co2") + o2 = obs + pe.cov_Obs(0.0, 0.2, "co") + pe.cov_Obs(0.0, 0.8, "co2") + + for i_obs in [obs, o1, o2]: + assert hash(i_obs) == hash(i_obs ** 2 / i_obs) == hash(1 * i_obs) + assert hash(i_obs) == hash((1 + 1e-16) * i_obs) + assert hash(i_obs) != hash((1 + 1e-7) * i_obs) + assert hash(obs) != hash(o1) + assert hash(o1) != hash(o2)