Problems with partial PBCs on previously pickled structures

Hi all,

I recently upgraded pymatgen and noticed that the changes introduced to partial periodic boundary conditions in v2022.7.8 which were introduced by @gpetretto via pull request #2429 broke some functionality in my workflow.
I try to keep calls to the MaterialsProject API to a minimum, so I pickled and saved the structure objects previously locally. If it is found there it is loaded, otherwise, it is fetched from MP.
However, now, those pickled objects from the past do not have lattices with periodic boundary conditions, and thus they behave problematically and break my workflow.
Stuff like:

import pickle
with open('mp-30.txt', 'rb') as f:
    cu_bulk = pickle.load(f)
print(cu_bulk.sites)
print(cu_bulk.lattice.abc)
print(cu_bulk.as_dict())

results in:

[PeriodicSite: Cu (0.0000, 0.0000, 0.0000) [0.0000, 0.0000, 0.0000]]
(2.56061891665316, 2.56061891665316, 2.56061891665316)
Traceback (most recent call last):
  File "/fs/home/wolloch/git_test/structures/pickleTest.py", line 15, in <module>
    print(cu_bulk.as_dict())
  File "/home/michael/miniconda3/envs/pymatgentest/lib/python3.10/site-packages/pymatgen/core/structure.py", line 2361, in as_dict
    latt_dict = self._lattice.as_dict(verbosity=verbosity)
  File "/home/michael/miniconda3/envs/pymatgentest/lib/python3.10/site-packages/pymatgen/core/lattice.py", line 982, in as_dict
    "pbc": self._pbc,
AttributeError: 'Lattice' object has no attribute '_pbc'. Did you mean: 'pbc'?

I looked into the new code, but could not find a good solution to this problem. I guess it is more of an edge case, and easily avoided if one e.g. converts the pickled objects to dictionary representation with an older version of pymatgen, because when loading structures from dictionaries, the periodic boundary conditions are set correctly to (True, True, True) if they are not found in the dictionary.

So this post is more of a heads-up for other people that have potentially to deal with this issue. I do not believe that it needs to be fixed necessarily, but of course, if someone has an idea how to do it, it could not hurt.

All the best, Michael

mp-30.txt (713 Bytes)

1 Like

Thanks for the heads up! This is unfortunate.

Generally for serialization we recommend via JSON for this reason (because pickle can be brittle), using code like:

from monty.serialization import loadfn, dumpfn
dumpfn(your_objects_structures_etc, "your_file.json.gz")

However, this is not ideal for everyone – pickling objects is certainly much faster!

Perhaps we can resolve however by modifying the as_dict() for better backwards compatibility if _pbc isn’t present? I think this would be a good idea given that the Structure object is so widely used, I’ll see what I can do!

Best,

Matt