Source code for aiida_atomistic.data.structure.structure
from aiida.orm.nodes.data import Data
from aiida_atomistic.data.structure.models import MutableStructureModel, ImmutableStructureModel
from aiida_atomistic.data.structure.setter_mixin import SetterMixin
from aiida_atomistic.data.structure.getter_mixin import GetterMixin
import warnings
[docs]
class StructureData(Data, GetterMixin):
[docs]
_model = ImmutableStructureModel
def __init__(self, sites:list[dict]=None, kinds:list[dict]=None, **kwargs):
from aiida_atomistic.data.structure.utils_kinds import sites_from_kinds
if sites is not None and kinds is not None:
warnings.warn("Provided both `sites` and `kinds` information. Dropping the `sites` information and using only `kinds`.")
sites = sites_from_kinds(kinds)
elif kinds is not None:
sites = sites_from_kinds(kinds)
[docs]
self._properties = self._model(sites=sites, **kwargs)
super().__init__()
#if validate_kinds:
# if self.kinds is not None: self.validate_kinds()
attributes = self.properties.model_dump(exclude_unset=True, exclude_none=True, warnings=False)
if self.properties.kind_names is not None:
from aiida_atomistic.data.structure.utils_kinds import compress_properties_by_kind
compressed = compress_properties_by_kind(attributes)
attributes.update(compressed)
attributes.pop("sites", None)
attributes.pop("kinds", None)
for prop, value in attributes.items():
self.base.attributes.set(prop, value)
@property
[docs]
def properties(self):
if self.is_stored:
from aiida_atomistic.data.structure.utils import build_sites_from_expanded_properties
if "kind_names" in self.base.attributes.all:
from aiida_atomistic.data.structure.utils_kinds import rebuild_site_lists_from_kind_lists
attribute_lists_dict = rebuild_site_lists_from_kind_lists(self.base.attributes.all)
attributes = build_sites_from_expanded_properties(attribute_lists_dict)
else:
attributes = build_sites_from_expanded_properties(self.base.attributes.all)
properties = self._model(**attributes)
return properties
else:
return self._properties
@classmethod
[docs]
def from_builder(cls, builder: 'StructureBuilder'):
from aiida_atomistic.data.structure.structure import StructureBuilder
if not isinstance(builder, StructureBuilder):
raise ValueError(f"Input builder should be of type StructureBuilder, not {type(builder)}")
return cls(**builder.to_dict())
[docs]
def to_builder(self) -> 'StructureBuilder':
return StructureBuilder(**self.to_dict())
[docs]
def __repr__(self) -> str:
"""Return a concise string representation of the structure."""
from aiida_atomistic.data.structure.utils import get_structure_repr
# Build UUID string without calling super().__repr__() to avoid recursion
if self.is_stored:
uuid_str = f'<{self.__class__.__name__}: uuid: {self.uuid} (pk: {self.pk})>'
else:
uuid_str = f'<{self.__class__.__name__}: uuid: {self.uuid} (unstored)>'
prop_repr_str = get_structure_repr(self)
return uuid_str + f'\n {prop_repr_str.replace("ImmutableStructureModel","")}'
[docs]
def __str__(self) -> str:
"""Return a string representation of the structure for print()."""
return self.__repr__()
[docs]
class StructureBuilder(GetterMixin, SetterMixin):
[docs]
_model = MutableStructureModel
def __init__(self, sites:list[dict]=None, kinds:list[dict]=None, **kwargs):
from aiida_atomistic.data.structure.utils_kinds import sites_from_kinds
if sites is not None and kinds is not None:
warnings.warn("Provided both `sites` and `kinds` information. Dropping the `sites` information and using only `kinds`.")
sites = sites_from_kinds(kinds)
elif kinds is not None:
sites = sites_from_kinds(kinds)
[docs]
self._properties = self._model(sites=sites, **kwargs)
super().__init__()
@property
[docs]
def properties(self):
return self._properties
@classmethod
[docs]
def from_aiida(cls, aiida: 'StructureData'):
if not isinstance(aiida, StructureBuilder):
raise ValueError(f"Input aiida should be of type StructureBuilder, not {type(aiida)}")
return cls(**aiida.to_dict())
[docs]
def to_aiida(self) -> 'StructureData':
return StructureData(**self.to_dict())
[docs]
def __repr__(self) -> str:
"""Return a concise string representation of the structure."""
from aiida_atomistic.data.structure.utils import get_structure_repr
prop_repr_str = get_structure_repr(self)
return super().__repr__() + f'\n {prop_repr_str.replace("MutableStructureModel","")}'
[docs]
def __str__(self) -> str:
"""Return a string representation of the structure for print()."""
return self.__repr__()