# coding: utf-8
# Distributed under the terms of the MIT License.
""" This file implements some light wrappers to
the Atomic Simulation Environment (ASE).
"""
import copy
from typing import Union
from matador.utils.chem_utils import get_stoich
from matador.utils.cell_utils import get_spacegroup_spg
from matador.crystal import Crystal
__all__ = ["ase2dict", "doc2ase"]
[docs]def ase2dict(atoms, as_model=False) -> Union[dict, Crystal]:
"""Return a matador document (dictionary or :obj:`Crystal`)
from an `ase.Atoms` object.
Parameters:
atoms (ase.Atoms): input structure.
Keyword arguments:
as_model (bool): if `True`, return a
Crystal instead of a dictionary.
Returns:
Union[dict, Crystal]: matador output.
"""
from matador.utils.cell_utils import cart2abc
doc = {}
# sort atoms, then their positions
doc["atom_types"] = atoms.get_chemical_symbols()
inds = [i[0] for i in sorted(enumerate(doc["atom_types"]), key=lambda x: x[1])]
doc["positions_frac"] = atoms.get_scaled_positions().tolist()
doc["positions_frac"] = [doc["positions_frac"][ind] for ind in inds]
doc["atom_types"] = [doc["atom_types"][ind] for ind in inds]
try:
doc["lattice_cart"] = atoms.get_cell().tolist()
except AttributeError:
doc["lattice_cart"] = atoms.get_cell().array.tolist()
doc["lattice_abc"] = cart2abc(doc["lattice_cart"])
doc["num_atoms"] = len(doc["atom_types"])
doc["stoichiometry"] = get_stoich(doc["atom_types"])
doc["cell_volume"] = atoms.get_volume()
doc["elems"] = {atom for atom in doc["atom_types"]}
doc["num_fu"] = doc["num_atoms"] / int(
sum(doc["stoichiometry"][i][1] for i in range(len(doc["stoichiometry"])))
)
doc["space_group"] = get_spacegroup_spg(doc, symprec=0.001)
if hasattr(atoms, "info"):
doc["ase_info"] = copy.deepcopy(atoms.info)
if as_model:
doc = Crystal(doc)
return doc
[docs]def doc2ase(doc: Union[dict, Crystal], add_keys_to_info=True):
"""Convert matador document to simple ASE object.
Parameters:
doc (dict/:obj:`Crystal`): matador document or
`Crystal` containing the structure.
Keyword arguments:
add_keys_to_info (bool): whether or not to add the keys from the
matador document to the info section of the Atoms object.
"""
from ase import Atoms
atoms = Atoms(
symbols=doc["atom_types"],
scaled_positions=doc["positions_frac"],
cell=doc["lattice_cart"],
pbc=True,
)
if add_keys_to_info:
if isinstance(doc, Crystal):
atoms.info["matador"] = doc._data
else:
atoms.info["matador"] = copy.deepcopy(doc)
if "_id" in atoms.info["matador"]:
atoms.info["matador"]["_id"] = str(atoms.info["matador"]["_id"])
return atoms