httk.atomistic.symmetry.canonical

Canonical forms for noisy input: tolerant recognition composed with exact normalization.

canonical_asu() bridges the two layers. Before tolerant recognition, the exact unit-cell geometry is put in an anonymous P1 frame, giving spglib one deterministic basis, origin, and site order for every exact re-expression of the same measured structure. The tolerant layer (recognize_asu(), backed by spglib) then snaps that stable input onto a space group within a Cartesian tolerance. The exact layer selects an anonymous protostructure-first representative. canonical_asu_legacy() retains the metric-first convention.

This module is deliberately outside lift.py: lift imports recognition (for its tolerance helpers) and stays spglib-free, while this composer imports both.

Attributes

Functions

canonical_asu_legacy(structure, *[, tolerance, ...])

Return the legacy metric-first canonical ASU of a measured structure's symmetry.

canonicalize(…)

Canonicalize a structure or classification without general upward symmetry search.

Module Contents

httk.atomistic.symmetry.canonical.canonical_asu_legacy(structure, *, tolerance=None, factors=(Fraction(1, 5), 1, 5), lift=False, preserve_chirality=True)

Return the legacy metric-first canonical ASU of a measured structure’s symmetry.

This is the noisy-input counterpart to canonicalize_legacy(): it first normalizes the exact measured geometry in P1, recognizes its symmetry with spglib, and then canonicalizes the recognized result exactly. P1 preconditioning prevents spglib’s tolerance-boundary result from depending on an equivalent input shear, origin shift, or site ordering.

An ASUStructure input is expanded to its unit cell first and the symmetry is re-recognized from the actual coordinates – always from the geometry, never the declared label. Re-recognition can raise a declared symmetry (a hand-written low-symmetry cell whose coordinates in fact support more) and can also lower it (a declared symmetry the coordinates do not support at the derived tolerance).

Recognition is swept over the base * factor symprecs from loosest to tightest. A member is accepted only when its recognized model reproduces every input site within the base tolerance (never the swept one), by an injective same-species match, and matches the per-species site counts. The first accepted member wins – by the same operation-count monotonicity the loosest fitting member is the highest-symmetry one – so recognition (and the expensive stage) runs once in the common case, and a looser member still rescues a tolerance-boundary flip a tighter one fails.

lift selects the expensive stage applied to that winner:

  • lift=False (default): it is mapped to the deterministic canonical representative within its recognized group – the exact terminal representation (setting, origin, orbit representatives, basis orientation all fixed), returned without searching upward. The result is the canonical form of the recognized symmetry; no pseudosymmetry above it is sought.

  • lift=True: it is additionally run through the exact upward search (canonicalize_legacy()) to find higher pseudosymmetry the recognition missed. This is exact but can be expensive – minutes and beyond for low-symmetry, many-atom cells.

Tolerance bound: the recognition stage is held to the base tolerance – every returned atom sits within base of the input. Under lift=False that is the whole bound (no further hops). Under lift=True each lift hop can move coordinates and snap the metric by up to another base and the residual/path are not re-checked here, so the returned structure’s distance from the input is bounded roughly by base * (1 + hops).

Determinism: the recognition stage is floating-point/spglib-based, so its outcome is reproducible on one platform but may differ across floating-point architectures or spglib builds. The exact stage is platform-independent and erases spglib’s representational freedom for ordinary rational crystallographic Gram matrices, so cross-platform variation is confined to which symmetry is accepted near a tolerance boundary, never to how an accepted symmetry is represented. An exact non-rational Gram whose canonical Cartesian factor requires nested radicals outside the supported surd field remains idempotent but can retain its input’s global Cartesian rotation. Free-parameter values come from row-Hermite chart projection of the measured coordinates, so two noisy measurements of the same crystal can reach the same Wyckoff choices with slightly different rational parameter values.

Parameters:
  • structure (httk.atomistic.models.structure.like.StructureLike) – The measured structure, UnitcellStructure or ASUStructure.

  • tolerance (float | None) – The base Cartesian tolerance, or None to derive it from the structure’s stated precision (structure_tolerance()).

  • factors (tuple[fractions.Fraction | float | int, ...]) – Multipliers for the recognition symprec sweep; each candidate symprec is base * factor.

  • lift (bool) – Whether to search upward for pseudosymmetry above the recognized group (default False: return the canonical representative of the recognized symmetry).

  • preserve_chirality (bool) – How enantiomorphic space groups are canonicalized. By default (True) the recognized group is kept, so a genuinely chiral crystal retains its handedness. When False a result landing in the higher member of one of the 11 enantiomorphic pairs (76/78, 91/95, 92/96, 144/145, 151/153, 152/154, 169/170, 171/172, 178/179, 180/181, 212/213) is mapped to the LOWER-numbered member by an exact chirality-flipping transformation (fractional coordinates f -> (-f) mod 1 with the cell basis unchanged – the Cartesian inversion r -> -r – and the group swapped to its partner), so an enantiomorphic pair shares one canonical representative and the canonical labels of the two partners coincide. The exact bridge normalize_chirality() maps a preserved (True) result to the normalized (False) one directly, without re-canonicalizing. A structure carrying site moments is never flipped (axial vectors are out of scope under improper maps) and is left in its own group regardless of this flag.

Returns:

The canonical asymmetric unit.

Raises:
  • ImportError – If spglib is unavailable when symmetry must be searched (the error names the httk-atomistic[default] extra).

  • ValueError – If recognition fails or is rejected at every swept tolerance.

Return type:

httk.atomistic.models.structure.asu.ASUStructure

httk.atomistic.symmetry.canonical.canonicalize(structure: httk.atomistic.models.bareprototype.backend.BarePrototypeBackend, *, symmetry: Literal['detect', 'declared'] = 'detect', tolerance: float | None = None, factors: tuple[fractions.Fraction | float | int, ...] = (Fraction(1, 5), 1, 5), preserve_chirality: bool = True, timeout: float | None = 120.0) → httk.atomistic.models.bareprototype.bareprototype.BarePrototype
httk.atomistic.symmetry.canonical.canonicalize(structure: httk.atomistic.models.bareprotostructure.backend.BareProtostructureBackend, *, symmetry: Literal['detect', 'declared'] = 'detect', tolerance: float | None = None, factors: tuple[fractions.Fraction | float | int, ...] = (Fraction(1, 5), 1, 5), preserve_chirality: bool = True, timeout: float | None = 120.0) → httk.atomistic.models.bareprotostructure.bareprotostructure.BareProtostructure
httk.atomistic.symmetry.canonical.canonicalize(structure: httk.atomistic.models.prototype.backend.PrototypeBackend, *, symmetry: Literal['detect', 'declared'] = 'detect', tolerance: float | None = None, factors: tuple[fractions.Fraction | float | int, ...] = (Fraction(1, 5), 1, 5), preserve_chirality: bool = True, timeout: float | None = 120.0) → httk.atomistic.models.prototype.prototype.Prototype
httk.atomistic.symmetry.canonical.canonicalize(structure: httk.atomistic.models.protostructure.backend.ProtostructureBackend, *, symmetry: Literal['detect', 'declared'] = 'detect', tolerance: float | None = None, factors: tuple[fractions.Fraction | float | int, ...] = (Fraction(1, 5), 1, 5), preserve_chirality: bool = True, timeout: float | None = 120.0) → httk.atomistic.models.protostructure.protostructure.Protostructure
httk.atomistic.symmetry.canonical.canonicalize(structure: httk.atomistic.models.structure.like.StructureLike, *, symmetry: Literal['detect', 'declared'] = 'detect', tolerance: float | None = None, factors: tuple[fractions.Fraction | float | int, ...] = (Fraction(1, 5), 1, 5), preserve_chirality: bool = True, timeout: float | None = 120.0) → httk.atomistic.models.structure.asu.ASUStructure

Canonicalize a structure or classification without general upward symmetry search.

Structure inputs use anonymous framing, spglib recognition, and the exact protostructure terminal. symmetry="declared" instead uses an already materialized ASU’s symmetry without recognition. Classification inputs use their available group/occupation information and transform carried examples. Their result has the corresponding classification type. No return value is selected from a time-truncated candidate set. canonical_asu is an alias.

Parameters:
  • structure – A structure-like source or one of the four classification families.

  • symmetry – "detect" for structure recognition, or "declared" for an exact ASU. Classification values always use their carried symmetry model.

  • tolerance – Cartesian recognition tolerance, or the precision-derived default. Only valid for structure recognition.

  • factors – Multipliers in the recognition tolerance sweep; only default values are accepted outside structure recognition.

  • preserve_chirality – Whether to retain enantiomorphic handedness.

  • timeout – Cooperative seconds for the operation; None disables the deadline. A native call or individual arithmetic operation cannot be preempted.

Returns:

An ASUStructure for structure inputs, or the matching standalone classification.

Raises:
  • CanonicalizationLimitError – If the operation exceeds its limit; no partial result is returned.

  • TypeError – If declared mode is given an input without a materialized exact ASU.

  • ValueError – If options or the input are unsupported, or recognition fails.

  • ImportError – If structure recognition requires unavailable spglib.

httk.atomistic.symmetry.canonical.canonical_asu