pythonobjectserializationpicklemdanalysis

How to use pickle to dump a universe object from MDAnalysis module?


I tried to use pickle to dump a MDAnalysis.universe object, but I got error mmessage like

Traceback (most recent call last):
  File "convert.py", line 9, in <module>
    blob = pickle.dumps(u)
  File "/usr/lib/python2.7/pickle.py", line 1374, in dumps
    Pickler(file, protocol).dump(obj)
  File "/usr/lib/python2.7/pickle.py", line 224, in dump
    self.save(obj)
  File "/usr/lib/python2.7/pickle.py", line 331, in save
    self.save_reduce(obj=obj, *rv)
  File "/usr/lib/python2.7/pickle.py", line 419, in save_reduce
    save(state)
  File "/usr/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib/python2.7/pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "/usr/lib/python2.7/pickle.py", line 663, in _batch_setitems
    save(v)
  File "/usr/lib/python2.7/pickle.py", line 306, in save
    rv = reduce(self.proto)
  File "/usr/lib/python2.7/copy_reg.py", line 84, in _reduce_ex
    dict = getstate()
TypeError: 'AtomGroup' object is not callable

any suggestion would be appreciated!


Solution

  • Updated answer (for MDAnalysis ≥ 2.0)

    Since MDAnalysis 2.0.0 (August 2021), Universes can be pickled.

    import MDAnalysis as mda
    import pickle
    u = mda.Universe(topology, trajectory)
    pickle.dump(u, open("universe.pkl", "wb"))
    
    # load pickled universe
    u_pickled = pickle.load(open("universe.pkl", "rb"))
    
    # test that we get same positions
    (u_pickled.atoms.positions == u.atoms.positions).all()
    # -> True
    
    # but that universes are different
    u == u_pickled
    # -> False
    

    See also Parallelizing Analysis in the User Guide.


    Old answer

    MDAnalysis.Universe objects contain some objects that cannot be serialized and pickled by the standard mechanisms, such as open file descriptors. One would need to write specialized __getstate__() and __setstate__() methods as described in the Pickle protocol but none of this is implemented as of the current 0.8.1 (April 2014) release.

    The specific error is explained by Manel in his comment on MDAnalysis Issue 173: Pickle searches for a __getstate__() method. Although that is not implemented, Universe, which manages manages its own attributes to generate "virtual attributes" on the fly, interprets this as an atom selection and eventually returns an empty AtomGroup instance. This, in turn, is called because pickle believes that it is the local implementation of __getstate__. AtomGroup, however, is not callable and the error results.

    As you probably noticed you got a quicker response by asking on the MDAnalysis user list or by filing an issue — Stackoverflow is typically lower on the list of developers for answering such specific questions.