Skip to content
This repository was archived by the owner on Oct 14, 2023. It is now read-only.
This repository was archived by the owner on Oct 14, 2023. It is now read-only.

Attractor identity changes when pickling & unpickling #1395

Description

@astrojuanlu

This manifests itself when doing something like this, as @MLopez-Ibanez hinted in #1377:

import pickle
from poliastro.examples import iss                                                                                                                                                                                                            
from poliastro.plotting.static import StaticOrbitPlotter

with open("/tmp/orbit.pkl", "wb") as fh:
    pickle.dump(iss, fh)
     
with open("/tmp/orbit.pkl", "rb") as fh:
    iss_pickle = pickle.load(fh)

fr = StaticOrbitPlotter()
fr.plot(iss)
fr.plot(iss_pickle)

which results in:

---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
<ipython-input-22-b48ffc98bf85> in <module>
     12 fr = StaticOrbitPlotter()
     13 fr.plot(iss)
---> 14 fr.plot(iss_pickle)

~/Projects/LSF/poliastro/library/src/poliastro/plotting/static.py in plot(self, orbit, label, color, trail)
    256             self.set_orbit_frame(orbit)
    257 
--> 258         lines = self._plot(orbit, label=label, color=color, trail=trail)
    259         lines = lines[0] + [lines[1]]
    260 

~/Projects/LSF/poliastro/library/src/poliastro/plotting/_base.py in _plot(self, orbit, label, color, trail)
    212         colors = self._get_colors(color, trail)
    213 
--> 214         self.set_attractor(orbit.attractor)
    215 
    216         orbit = orbit.change_plane(self.plane)

~/Projects/LSF/poliastro/library/src/poliastro/plotting/_base.py in set_attractor(self, attractor)
     57 
     58         """
---> 59         self._set_attractor(attractor)
     60 
     61     def _clear_attractor(self):

~/Projects/LSF/poliastro/library/src/poliastro/plotting/_base.py in _set_attractor(self, attractor)
     44             self._attractor = attractor
     45         elif attractor is not self._attractor:
---> 46             raise NotImplementedError(
     47                 f"Attractor has already been set to {self._attractor.name}"
     48             )

NotImplementedError: Attractor has already been set to Earth

And the underlying reason is that:

In [24]: iss
Out[24]: 6772 x 6790 km x 51.6 deg (GCRS) orbit around Earth (♁) at epoch 2013-03-18 12:00:00.000 (UTC)

In [25]: iss_pickle
Out[25]: 6772 x 6790 km x 51.6 deg (GCRS) orbit around Earth (♁) at epoch 2013-03-18 12:00:00.000 (UTC)

In [26]: iss.attractor
Out[26]: Earth (♁)

In [27]: iss_pickle.attractor
Out[27]: Earth (♁)

In [28]: from poliastro.bodies import Earth

In [29]: id(Earth)
Out[29]: 140338173428784

In [30]: id(iss.attractor)
Out[30]: 140338173428784

In [31]: id(iss_pickle.attractor)
Out[31]: 140336077697520

And therefore, code like this fails:

elif attractor is not self._attractor:

Rather than working around this issue, if we want to make bodies be singletons, we should implement proper pickling/unpickling methods for those. This problem in pandas is similar: pandas-dev/pandas#31847. Maybe a __reduce__ will suffice: https://docs.python.org/3/library/pickle.html#object.__reduce__

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions