Source code for aiida_pythonjob_ins.data.mixins
"""Mixins for the Euphonic-wrapping Data classes.
Kept separate from the JSON-storage base (:class:`EuphonicJSONData`) so that a
capability like ``to_structure()`` is only present on Data classes that actually
wrap an object with a ``.crystal`` (e.g. ``ForceConstants``,
``QpointPhononModes``) -- and not, say, a future ``Spectrum1DCollectionData``,
which has no crystal.
"""
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable
from aiida.orm import StructureData
from aiida_pythonjob_ins.conversions import crystal_to_structure
[docs]
@runtime_checkable
class SupportsToStructure(Protocol):
"""Structural type for a node that can yield its crystal as a StructureData.
Used to type the generic ``extract_structure`` calcfunction.
"""
[docs]
def to_structure(self) -> StructureData: ...
[docs]
class CrystalStructureMixin:
"""Add ``to_structure()`` to a Data class wrapping an object with ``.crystal``.
Mix in *alongside* :class:`EuphonicJSONData` (which provides ``get_object()``),
e.g. ``class ForceConstantsData(CrystalStructureMixin, EuphonicJSONData)``.
"""
if TYPE_CHECKING:
# Provided at runtime by the host Data class (EuphonicJSONData); declared
# here only so type checkers know the mixin relies on it.
def get_object(self) -> Any: ...
[docs]
def to_structure(self) -> StructureData:
"""Extract the wrapped object's ``.crystal`` as a native ``StructureData``.
Delegates to :func:`~aiida_pythonjob_ins.conversions.crystal_to_structure`
(the single Crystal -> StructureData converter).
"""
return crystal_to_structure(self.get_object().crystal)