Source code for aiida_pythonjob_ins.data.crystal
"""AiiDA Data node wrapping a Euphonic ``Crystal`` object.
``Crystal`` is euphonic's crystal-structure representation (cell, atom positions,
species, masses). This node is the bridge between euphonic's representation and
AiiDA's native ``StructureData``, and the single home for those conversions.
https://euphonic.readthedocs.io/en/stable/
"""
from __future__ import annotations
from typing import ClassVar, Self
from aiida.orm import StructureData
from euphonic import Crystal
from aiida_pythonjob_ins.conversions import (
crystal_to_structure,
structure_to_crystal,
)
from .base import EuphonicJSONData
[docs]
class EuphonicCrystalData(EuphonicJSONData):
"""Store a Euphonic ``Crystal`` object as an AiiDA node.
Note: this deliberately does *not* use ``CrystalStructureMixin`` -- the wrapped
object *is* the crystal (it has no ``.crystal`` attribute), so ``to_structure``
is defined directly here.
"""
_euphonic_cls: ClassVar[type] = Crystal
[docs]
def get_crystal(self) -> Crystal:
"""Return the wrapped :class:`euphonic.Crystal`."""
return self.get_object()
[docs]
def to_structure(self) -> StructureData:
"""Convert to a native AiiDA ``StructureData`` (no ASE)."""
return crystal_to_structure(self.get_crystal())
[docs]
def to_spglib_cell(self) -> tuple:
"""Return the spglib ``(lattice, positions, numbers)`` tuple.
Delegates to euphonic's own ``Crystal.to_spglib_cell``.
"""
return self.get_crystal().to_spglib_cell()
[docs]
@classmethod
def from_structure(cls, structure: StructureData) -> Self:
"""Build a node from a native AiiDA ``StructureData``."""
return cls(structure_to_crystal(structure))