From 4becfd0c2c234ff7ac4d85c32ed4a74fa04b13db Mon Sep 17 00:00:00 2001 From: Mohit Ak Date: Mon, 26 Oct 2026 02:39:26 -0400 Subject: [PATCH] Fix TimeInterpolatedPotential evaluating to zero after pickling TimeInterpolatedWrapper stored 0.0 as G in _params, and __reduce__ passes _params[0] back as G, so the unpickled wrapper interpolated with G = 0. Pass the real G to init(). Fixes #542 --- CHANGES.rst | 3 +++ src/gala/potential/potential/builtin/cytimeinterp.pyx | 2 +- tests/regression/test_potential_timeinterpolated_539.py | 8 +++++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 603b44cf1..981776940 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -27,6 +27,9 @@ New Features Bug fixes --------- +- Fixed ``TimeInterpolatedPotential`` returning zero energy, gradient, and density + after being pickled or deep-copied. + - Fixed ``find_actions_o2gf()`` raising an error whenever any toy action or angle was NaN. NaN samples are now dropped with a warning, and it raises only if more than half of the samples are NaN. diff --git a/src/gala/potential/potential/builtin/cytimeinterp.pyx b/src/gala/potential/potential/builtin/cytimeinterp.pyx index 9b6df6398..2ba076175 100644 --- a/src/gala/potential/potential/builtin/cytimeinterp.pyx +++ b/src/gala/potential/potential/builtin/cytimeinterp.pyx @@ -283,7 +283,7 @@ cdef class TimeInterpolatedWrapper(CPotentialWrapper): self.interp_state.wrapped_potential = self.wrapped_potential.cpotential self.init( - [0.0], # value of G doesn't matter for this wrapper + [G], np.zeros(n_dim, dtype=np.float64), # placeholder origin np.eye(n_dim, dtype=np.float64), # placeholder rotation n_dim=n_dim diff --git a/tests/regression/test_potential_timeinterpolated_539.py b/tests/regression/test_potential_timeinterpolated_539.py index 6651b4375..2af24f3e6 100644 --- a/tests/regression/test_potential_timeinterpolated_539.py +++ b/tests/regression/test_potential_timeinterpolated_539.py @@ -23,4 +23,10 @@ def test_timeinterpolated_pickle(tmpdir): pickle.dump(pot, f) with open(tmpdir.join("time_interp_pot.pkl"), "rb") as f: - pot = pickle.load(f) + new_pot = pickle.load(f) + + q = [8.0, 1.0, 0.5] * u.kpc + for t in [0.0, 3.3, 10.0] * u.Gyr: + assert u.allclose(new_pot.energy(q, t=t), pot.energy(q, t=t)) + assert u.allclose(new_pot.gradient(q, t=t), pot.gradient(q, t=t)) + assert u.allclose(new_pot.density(q, t=t), pot.density(q, t=t))