Source code for httk.atomistic.models.formula.structure

"""Backend projecting a structure into its elemental composition."""

from fractions import Fraction
from functools import cached_property
from typing import Any, Self

from httk.core import unwrap

from httk.atomistic.composition import project_composition
from httk.atomistic.models.formula.backend import ChemicalFormulaBackend
from httk.atomistic.models.formula.composition import Composition
from httk.atomistic.models.formula.diagnostics import CompositionDiagnostic
from httk.atomistic.models.structure.backend import StructureBackend
from httk.atomistic.models.structure.view import StructureView


[docs] class StructureComposition(ChemicalFormulaBackend): r"""Project a structure only when composition data is accessed. :param obj: The structure to adapt. :param \*\*hints: Backend-selection hints. """ _structure: StructureBackend @classmethod def _backend_adopt(cls, obj: Any, **hints: Any) -> Self | None: r"""Adopt a structure composition source. :param obj: The source object to adopt. :param \**hints: Backend-selection hints. :return: An initialized backend, or ``None`` when this backend declines ``obj``. """ if hints and hints.get("kind", "structure") != "structure": return None if isinstance(obj, StructureBackend): return cls(obj, **hints) if isinstance(obj, StructureView): return cls(obj, **hints) if getattr(obj, "_backend", None) is not None else None return None def __init__(self, obj: Any, **hints: Any) -> None: self._structure = obj if isinstance(obj, StructureBackend) else obj._backend @cached_property def _composition(self) -> Composition: return project_composition(self._structure) @property
[docs] def amounts(self) -> tuple[tuple[str, Fraction], ...]: """Return the projected elemental amounts.""" return self._composition.amounts
@property
[docs] def uncertainties(self) -> tuple[tuple[str, Fraction | None], ...]: """Return the projected amount precisions.""" return self._composition.uncertainties
@property
[docs] def complete(self) -> bool: """Return whether all represented elemental material is known.""" return self._composition.complete
@property
[docs] def exact(self) -> bool: """Return whether the projected amounts are exact.""" return self._composition.exact
@property
[docs] def normalized(self) -> bool: """Return whether the projected composition is normalized.""" return self._composition.normalized
@property
[docs] def normalization_status(self) -> str: """Return the projected composition's normalization status.""" return self._composition.normalization_status
@property
[docs] def diagnostics(self) -> tuple[CompositionDiagnostic, ...]: """Return diagnostics produced during projection.""" return self._composition.diagnostics
[docs] def unwrap(self) -> Any: """Return the original structure.""" return unwrap(self._structure)