Skip to content

hall_symbol

Hall space group symbols.

A Hall symbol (Hall, Acta Cryst. A37, 517, 1981) lists generators explicitly:

[-]L  N1 [N2 [N3 [N4]]]  [V]

L is the lattice centring (P A B C I R S T F), with a leading '-' adding the inversion at the origin. Each N is a matrix symbol: an optional '-' for an improper rotation, the order (1 2 3 4 6), an optional axis (x y z, ' or " for 2-fold face diagonals, * for the 3-fold body diagonal) and translation symbols (a b c n u v w d, or a screw digit). V is a change of basis, either an origin shift in twelfths "(0 0 1)" or an operation "(x,y,z+1/4)" (Grosse-Kunstleve, Acta Cryst. A55, 383, 1999).

All arithmetic is exact: rotations are integer matrices and translations Fractions.

hall_generators(symbol)

The generators of a Hall symbol as exact Seitz pairs.

Returns:

Type Description

the generators, as (rotation, translation) pairs of an integer

(3, 3) matrix and three Fractions, in the basis before any change

of basis; and the change of basis as such a pair, or None

Source code in chmpy/crystal/hall_symbol.py
def hall_generators(symbol: str):
    """The generators of a Hall symbol as exact Seitz pairs.

    Returns:
        the generators, as (rotation, translation) pairs of an integer
        (3, 3) matrix and three `Fraction`s, in the basis before any change
        of basis; and the change of basis as such a pair, or None
    """
    symbol = symbol.strip()
    change = None
    if "(" in symbol:
        start = symbol.index("(")
        if not symbol.endswith(")"):
            raise ValueError(f"Unbalanced change of basis in {symbol!r}")
        change = _change_of_basis(symbol[start:])
        symbol = symbol[:start]
    tokens = symbol.split()
    if not tokens:
        raise ValueError("Empty Hall symbol")
    lattice = tokens[0]
    centrosymmetric = lattice.startswith("-")
    letter = lattice.lstrip("-").upper()
    if letter not in _CENTRING or len(lattice) - centrosymmetric != 1:
        raise ValueError(f"Invalid Hall lattice symbol {lattice!r}")
    if not 1 <= len(tokens) - 1 <= 4:
        raise ValueError(f"A Hall symbol has one to four matrix symbols: {symbol!r}")

    identity = np.eye(3, dtype=int)
    generators = [(identity, tuple(Fraction(x) for x in t)) for t in _CENTRING[letter]]
    if centrosymmetric:
        generators.append((-identity, (Fraction(0),) * 3))
    previous_order = previous_axis = None
    for position, token in enumerate(tokens[1:]):
        op, order, axis = _matrix(token, position, previous_order, previous_axis)
        if order != 1:
            previous_order = order
            if axis in _AXIS_INDEX:
                previous_axis = axis
        generators.append(op)
    return generators, change

parse_hall_symbol(symbol)

All operations of the space group a Hall symbol describes.

One operation per coset of the integer lattice, so centring translations are included (as in SpaceGroup.symmetry_operations).

Parameters:

Name Type Description Default
symbol str

Hall symbol, e.g. "-P 2ybc" or "P 31 2 (0 0 4)"

required

Returns:

Type Description
list[SymmetryOperation]

list of SymmetryOperation, sorted by integer code

Source code in chmpy/crystal/hall_symbol.py
def parse_hall_symbol(symbol: str) -> list[SymmetryOperation]:
    """All operations of the space group a Hall symbol describes.

    One operation per coset of the integer lattice, so centring translations
    are included (as in `SpaceGroup.symmetry_operations`).

    Args:
        symbol: Hall symbol, e.g. "-P 2ybc" or "P 31 2 (0 0 4)"

    Returns:
        list of SymmetryOperation, sorted by integer code
    """
    generators, change = hall_generators(symbol)
    ops = _expand([_as_twelfths(g) for g in generators])
    if change is not None:
        change = _as_twelfths(change)
        change_inv = _inverse(change)
        ops = [_compose(change, _compose(op, change_inv)) for op in ops]
    result = [
        SymmetryOperation(np.reshape(r, (3, 3)), np.array(t, dtype=float) / 12)
        for r, t in ops
    ]
    return sorted(result, key=lambda op: op.integer_code)