Automatic Schoenflies point group determination from molecular coordinates and character table generation
Project description
pyrrhotite
Automatic Schoenflies point group determination from molecular coordinates.
Given a molecular geometry in .xyz format, pyrrhotite identifies the molecule's Schoenflies point group symbol by numerically detecting all present symmetry elements (rotations, reflections, inversions, and improper rotations).
Python adaptation of the C++ library by Luuk Kempen (https://gitlab.com/lkkmpn/schoenflies).
Installation
pip install pyrrhotite
Requirements: Python 3.10+
Quick start
from pyrrhotite import Structure, Symmetry
s = Structure("molecule.xyz")
sym = Symmetry(s)
print(sym.get_point_group().get_label().get_name()) # e.g. "C3v"
Or from the command line:
pyrrhotite molecule.xyz
pyrrhotite -v -ct ammonia.xyz # verbose + character table
What is a point group?
A point group is the complete set of symmetry operations that leave a molecule's geometry unchanged. Every molecule belongs to exactly one point group, and its label (e.g. C₂ᵥ, D₆ₕ, Td, Oₕ) encodes its full symmetry in compact notation.
Point group symmetry determines which molecular orbitals can mix, which vibrational modes are IR- or Raman-active, and how a molecule interacts with polarised light.
Usage
Python library
Point group determination
from pyrrhotite import Structure, Symmetry
s = Structure("ammonia.xyz")
sym = Symmetry(s)
pg = sym.get_point_group()
print(pg.get_label().get_name()) # "C3v"
print(pg.get_order()) # 6 (total number of symmetry operations)
Character table
# Print with rich formatting (falls back to plain if rich is not installed)
pg.print_character_table()
# Plain text
pg.print_character_table(plain=True)
# ε-notation for cyclic / Sn groups
pg.print_character_table(complex=True)
# Access the data directly
print(pg.get_irreps()) # list of IrrepLabel objects
print(pg.get_characters()) # list[list[float]] — [irrep][operation class]
print(pg.get_unique_operations()) # conjugacy classes (excluding E)
Character table for any group — no XYZ needed
from pyrrhotite.point_groups.character_table_generator import (
parse_point_group_name,
get_or_generate_point_group,
print_character_table_for,
)
print_character_table_for("D4h")
label = parse_point_group_name("C12v")
pg = get_or_generate_point_group(label)
pg.print_character_table()
Accepts all 18 Schoenflies classes: C1, Cs, Ci, Cn, Cnh, Cnv, Sn, Dn, Dnh, Dnd, T, Td, Th, O, Oh, I, Ih, Cinfv / C∞v, Dinfh / D∞h.
Rotor classification and principal axes
print(sym.get_rotor_class()) # RotorClass.ProlateSymmetricTop
pm = sym.get_principal_moments() # np.ndarray shape (3,) — Ia ≤ Ib ≤ Ic in u·Å²
axes = sym.get_principal_axes() # np.ndarray shape (3, 3) — eigenvectors as columns
cart = sym.get_cartesian_axes() # 3×3 matrix [x | y | z] in the conventional frame
Symmetry operations
manager = sym.get_operation_manager()
for op in manager.get_operations():
print(op.get_label().get_short_name()) # "C3", "C3^2", "σv", "i", …
print(op.get_axis()) # unit-vector axis / plane normal
print(op.get_error()) # worst-case atom mis-mapping distance (Å)
manager.get_proper_rotations()
manager.get_improper_rotations()
manager.get_reflections()
manager.get_inversions()
Basis functions
from pyrrhotite.point_groups.basis_functions import compute_basis_functions
basis = compute_basis_functions(pg)
# Returns dict[irrep_name, {"linear": [...], "quadratic": [...]}]
for irrep, funcs in basis.items():
print(irrep, funcs["linear"], funcs["quadratic"])
Element data
from pyrrhotite.periodic_table import get_element, get_atomic_number
el = get_element(6)
print(el.symbol) # "C"
print(el.mass) # 12.011
n = get_atomic_number("Fe") # 26
Command-line tool
pyrrhotite molecule.xyz
pyrrhotite tests/files/*.xyz
pyrrhotite -v ammonia.xyz # rotor class + all operations
pyrrhotite -ct ammonia.xyz # character table
pyrrhotite -ct --complex ammonia.xyz
pyrrhotite -m ammonia.xyz # principal moments and axes
pyrrhotite -od ammonia.xyz # atoms on each symmetry element
pyrrhotite -v -ct -m -od ammonia.xyz
pyrrhotite -g C3v # character table with no XYZ file
pyrrhotite -g D6h --plain
| Flag | Description |
|---|---|
-v, --verbose |
Show rotor class and all found symmetry operations |
-ct, --character-table |
Print the full character table (with basis functions) |
--complex |
Use ε-notation in the character table |
-m, --moments |
Show principal moments of inertia and Cartesian axes matrix |
-od, --operations-detail |
List atoms lying on each symmetry axis or mirror plane |
--plain |
Force plain-text output (suppress rich formatting) |
-g NAME, --group NAME |
Print character table for a named group without an XYZ file |
Example output (pyrrhotite -v -ct --plain ammonia.xyz):
ammonia.xyz
Point group : C3v
Rotor class : ProlateSymmetricTop
Operations : 4 found
C3
C3^2
σv (×3)
C3v | E | 2 C3 | 3 σv | Lin/Rot | Quadratic
--------------------------------------------------------------
A1 | 1 | 1 | 1 | z | z², x²+y²
A2 | 1 | 1 | -1 | Rz |
E | 2 | -1 | 0 | x, y, Rx, Ry | x²-y², xy, xz, yz
Input format
Standard .xyz files (coordinates in Ångströms):
3
Water molecule
O 0.000000 0.000000 0.119748
H 0.000000 0.756950 -0.478993
H 0.000000 -0.756950 -0.478993
The molecule does not need to be pre-centred; coordinates are translated to the centre of mass automatically.
Supported point groups
| Family | Groups |
|---|---|
| Non-axial | C₁, Cᵢ, Cₛ |
| Cyclic | C₂ – C₁₀ |
| Cyclic with σₕ | C₂ₕ – C₁₀ₕ |
| Cyclic with σᵥ | C₂ᵥ – C₆ᵥ |
| Improper axes | S₄, S₆, S₈ |
| Dihedral | D₂ – D₆ |
| Dihedral with σₕ | D₂ₕ – D₁₀ₕ, D∞ₕ |
| Dihedral with σd | D₃d – D₁₀d |
| Cubic | T, Td, Tₕ, O, Oₕ |
| Icosahedral | I, Iₕ |
| Linear | C∞ᵥ, D∞ₕ |
How the algorithm works
- Inertia tensor → principal axes. The 3×3 inertia tensor is diagonalised via
numpy.linalg.eigh, yielding three principal moments and axes. - Rotor classification. Degeneracy of the moments classifies the molecule into one of five types (Linear, Spherical Top, Prolate Symmetric Top, Oblate Symmetric Top, Asymmetric Top), pruning the candidate search space.
- Symmetry element detection. Candidate axes are generated from principal axes, atom positions, and pair midpoints. Each candidate is tested by applying the transformation matrix and checking that every atom maps onto a same-element atom within a tolerance of 10% of the distance to the symmetry element.
- Point group matching. Detected operation counts are compared against a library of 54+ predefined point groups. The group with the smallest non-negative surplus of operations is selected.
- Axis assignment and labelling. The Cartesian frame is standardised (z along the highest-order proper rotation; x to maximise atoms in the xz-plane) and operations are labelled (σₕ, σᵥ, σd, C₂′, C₂′′).
Known limitations
- Maximum Cₙ order searched is 8.
- Character tables for polyhedral groups (T, Td, Th, O, Oh, I, Ih) and linear groups are hardcoded; all axial groups are generated analytically.
- Fixed 10% tolerance — slightly distorted geometries may be misclassified.
- Single isolated molecules only; crystal structures and space groups are not supported.
Running tests
python -m pytest tests/ -v
License
GNU General Public License v3.0 — see LICENSE for details.
References
- Original C++ implementation by Luuk Kempen: https://gitlab.com/lkkmpn/schoenflies
- Johansson, M. P. & Veryazov, V. (2017). Automatic procedure for generating symmetry adapted wavefunctions. Journal of Cheminformatics, 9, 36. https://doi.org/10.1186/s13321-017-0193-3
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyrrhotite-0.1.2.tar.gz.
File metadata
- Download URL: pyrrhotite-0.1.2.tar.gz
- Upload date:
- Size: 92.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
70fc695f2e79b0813b54d4c4e5266bc6f06cba6bb360564f8b5eb5a8a0cc83de
|
|
| MD5 |
ffe1a39a0ff240c0082aa34053de2071
|
|
| BLAKE2b-256 |
c2d8b0b26259be08e50966cfdb786ddd8665617fe1ef5485ee7fb52689cec0f7
|
Provenance
The following attestation bundles were made for pyrrhotite-0.1.2.tar.gz:
Publisher:
build_wheels.yml on Code-Tomas-Dadikozyan/pyrrhotite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyrrhotite-0.1.2.tar.gz -
Subject digest:
70fc695f2e79b0813b54d4c4e5266bc6f06cba6bb360564f8b5eb5a8a0cc83de - Sigstore transparency entry: 1721389140
- Sigstore integration time:
-
Permalink:
Code-Tomas-Dadikozyan/pyrrhotite@6d212105519e2a9586db382fb515f7bc854d1560 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/Code-Tomas-Dadikozyan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build_wheels.yml@6d212105519e2a9586db382fb515f7bc854d1560 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyrrhotite-0.1.2-py3-none-any.whl.
File metadata
- Download URL: pyrrhotite-0.1.2-py3-none-any.whl
- Upload date:
- Size: 94.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e2c29f42f7211232ecfcabe1219d1aecbd5ae8075178fe676d6f9aaa46f969b9
|
|
| MD5 |
50633bc35f6a84564ded970e238f9b29
|
|
| BLAKE2b-256 |
30489f3b50171f92d6516203e6acc0d22f5f920729ac2cc489b4ecfaf67c59c7
|
Provenance
The following attestation bundles were made for pyrrhotite-0.1.2-py3-none-any.whl:
Publisher:
build_wheels.yml on Code-Tomas-Dadikozyan/pyrrhotite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyrrhotite-0.1.2-py3-none-any.whl -
Subject digest:
e2c29f42f7211232ecfcabe1219d1aecbd5ae8075178fe676d6f9aaa46f969b9 - Sigstore transparency entry: 1721389350
- Sigstore integration time:
-
Permalink:
Code-Tomas-Dadikozyan/pyrrhotite@6d212105519e2a9586db382fb515f7bc854d1560 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/Code-Tomas-Dadikozyan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build_wheels.yml@6d212105519e2a9586db382fb515f7bc854d1560 -
Trigger Event:
push
-
Statement type: