httk.atomistic.symmetry.canonical

A one-liner canonical form for noisy input: tolerant recognition composed with exact lifting.

canonical_asu() bridges the two layers. The tolerant layer (recognize_asu(), backed by spglib) snaps a measured structure onto a space group within a Cartesian tolerance. Because a measured structure can sit just inside or just outside a tolerance boundary, recognition is swept over a few symprec multiples from loosest to tightest, and the first member that fits within the base tolerance wins – so a looser member rescues a boundary flip without ever accepting more than the claimed noise. The exact layer then fixes that winner’s representation deterministically: by default (lift=False) it returns the canonical representative within the recognized group (setting, origin, orbit representatives, basis orientation all fixed) without searching upward; lift=True additionally runs canonicalize() to hunt higher pseudosymmetry the recognition missed.

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

Functions

canonical_asu(structure, *[, tolerance, factors, lift])

Return the canonical ASUStructure of a measured structure's symmetry.

Module Contents

httk.atomistic.symmetry.canonical.canonical_asu(structure, *, tolerance=None, factors=(Fraction(1, 5), 1, 5), lift=False)[source]

Return the canonical ASUStructure of a measured structure’s symmetry.

This is the noisy-input counterpart to canonicalize(): it recognizes the symmetry of a measured structure with spglib and then canonicalizes the result exactly.

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. Per-structure cost is essentially recognition-bound.

  • lift=True: it is additionally run through the exact upward search (canonicalize()) 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, so cross-platform variation is confined to which symmetry is accepted near a tolerance boundary, never to how an accepted symmetry is represented. Free-parameter values are least-squares fits of the measured coordinates, so two noisy measurements of the same crystal reach the same Wyckoff choices but 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, Ellipsis]) – 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).

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