Source code for httk.atomistic.models.protostructure.view

"""Lazy refined protostructure presentation view."""

from typing import Any, Self

from httk.core import MISSING, unwrap

from httk.atomistic.models.protostructure.backend import ProtostructureBackend
from httk.atomistic.models.protostructure.protostructure import Protostructure
from httk.atomistic.models.protostructure.view_base import ProtostructureViewBase


[docs] class ProtostructureView(ProtostructureViewBase, Protostructure): r"""Present an existing refined protostructure lazily. Raw structures and plain labels require a bare view; refinement must be constructed explicitly with a representative or discriminator. A bare projection view retaining a refined source can recover that source here. :param obj: Existing refined classification. :param \*\*hints: Reserved hints; recognition arguments are rejected. """ _backend: ProtostructureBackend _resolved_protostructure: Protostructure | None _DEFERRED_FIELDS = frozenset({"_spacegroup", "_occupations", "_representative", "_discriminator"}) def __new__(cls, obj: Any = MISSING, **hints: Any) -> Self: if obj is MISSING: return super().__new__(cls) if hints: raise ValueError("ProtostructureView does not accept recognition arguments") if isinstance(obj, cls): return obj instance = super().__new__(cls) instance._backend = cls._prepare_backend(obj, hints) instance._resolved_protostructure = None return instance def __init__(self, obj: Any, **hints: Any) -> None: pass def __getattribute__(self, name: str) -> Any: if name in type(self)._DEFERRED_FIELDS: namespace = object.__getattribute__(self, "__dict__") if name not in namespace: object.__getattribute__(self, "_effective_protostructure")() return object.__getattribute__(self, name) def _effective_protostructure(self) -> Protostructure: cached = object.__getattribute__(self, "_resolved_protostructure") if cached is not None: return cached backend = object.__getattribute__(self, "_backend") if type(backend) is Protostructure: resolved = backend elif hasattr(backend, "resolve"): resolved = backend.resolve() else: resolved = Protostructure( backend.spacegroup, backend.occupations, representative=backend.representative, discriminator=backend.discriminator, ) state = dict(resolved.__dict__) state["_resolved_protostructure"] = resolved object.__getattribute__(self, "__dict__").update(state) return resolved
[docs] def unwrap(self) -> Any: """Return the raw object behind the backend. :return: The unwrapped source object. """ return unwrap(self._backend)
[docs] def unview(self) -> Protostructure: """Return the refined protostructure as a standalone value. :return: The protostructure value. """ return self._effective_protostructure()
def __getstate__(self) -> dict[str, Any]: state = { "backend": self._backend, } if self._resolved_protostructure is not None: state["resolved"] = self._resolved_protostructure return state def __setstate__(self, state: dict[str, Any]) -> None: self._backend = state["backend"] self._resolved_protostructure = None resolved = state.get("resolved") if resolved is not None: state_copy = dict(resolved.__dict__) state_copy["_resolved_protostructure"] = resolved object.__getattribute__(self, "__dict__").update(state_copy)