Skip to main content

Molecular symmetry detection and symmetrization

Project description

MolSymPy

MolSymPy is an open-source Python package for molecular symmetry analysis in atomistic simulations. It is built natively on top of the Atomic Simulation Environment (ASE) and operates directly on ase.Atoms objects, enabling seamless integration with atomistic simulation workflows.

Features

  • Geometric idealization — project nearly-symmetric structures onto their exact symmetry elements and orient the molecular frame by aligning principal and secondary symmetry axes with the Cartesian coordinate system.
  • Point group detection — identify molecular point groups in Schoenflies notation, including the two infinite-order linear groups (C∞v and D∞h).
  • Symmetry-inequivalent atoms — determine symmetry-inequivalent atoms using a path-compressed union-find algorithm operating on the complete symmetry permutation map.
  • Reference database — companion collection of molecular and atomic-cluster geometries spanning the principal point groups, available in both raw and idealized forms.

Performance-critical routines are accelerated through Numba just-in-time compilation, providing efficient execution with no compilation requirements at install time.

Installation

pip install molsympy

Requirements: Python ≥ 3.10, NumPy ≥ 1.24, Numba ≥ 0.61, ASE ≥ 3.22.

Quick start

Point group detection

from ase.build import molecule
from molsympy import get_point_group

cyclopropane = molecule('C3H6_D3h')
print(get_point_group(cyclopropane))  # D3h

Symmetry-inequivalent atoms

from molsympy.collections import symmetrized
from molsympy import get_inequivalent

mol = symmetrized['C3h_1']
unique, parent = get_inequivalent(mol, geom_tol=0.05, eigen_tol=0.01)
print(unique)   # [0, 1, 2, 9, 10]
print(parent)   # [0, 1, 2, 1, 0, 2, 1, 0, 2, 9, 10, 9, 10, 9, 10]

Symmetrization

from molsympy.collections import unsymmetrized
from molsympy import symmetrize, get_point_group

atoms = unsymmetrized['C0v_1']   # by point-group key
atoms = unsymmetrized['CNH']     # equivalent: lookup by molecular formula
print(atoms.positions)

sym = symmetrize(atoms)
print(sym.positions)
print(get_point_group(sym))   # C*v

Symmetry candidates (subgroup fan-out)

from ase.build import molecule
from molsympy import generate_symmetry_candidates

benzene = molecule('C6H6')                      # D6h
for s in generate_symmetry_candidates(benzene):
    print(s.pg, s.rmsd)                         # D6h, D3h, C6h, C6v, ...

API reference

get_point_group(mol, geom_tol=0.05, eigen_tol=None) → str

Determine the point group of a molecule.

Parameter Type Description
mol ase.Atoms Input molecule.
geom_tol float Geometric tolerance in Å (default 0.05).
eigen_tol float | None Relative tolerance for moment-of-inertia eigenvalues. Estimated automatically when None.

Returns the Schoenflies symbol as a string (e.g. "C2v", "D3h", "Oh").


symmetrize(mol, geom_tol=0.05, eigen_tol=None) → ase.Atoms

Project a nearly-symmetric structure onto exact point-group symmetry.

Each set of symmetry-equivalent atoms (SEA) is handled by projecting a representative atom onto the symmetry element that fixes it, then mapping the remaining SEA members via the stored matrix representation of the connecting symmetry operation.


get_inequivalent(mol, geom_tol=0.3, eigen_tol=None) → (np.ndarray, np.ndarray)

Find symmetry-inequivalent atoms.

Returns (unique, parent) where unique contains one representative index per equivalence class and parent[i] is the representative of atom i.


is_planar(mol, geom_tol=0.05) → bool

Check whether all atoms lie in a common plane.


generate_symmetry_candidates(mol, geom_tol=0.05, eigen_tol=None, sort_by=0) → list[SymmetryResult]

Generate symmetry-consistent geometries for all subgroups compatible with the detected point group.

Each SymmetryResult contains:

  • mol — the symmetrized ase.Atoms object
  • pg — the Schoenflies symbol
  • rmsd — RMSD (Å) between original and symmetrized structure

sort_by=0 sorts by group size (descending) then RMSD (ascending); sort_by=1 sorts by RMSD first.

Reference database

MolSymPy ships a companion database of molecular and atomic-cluster geometries indexed by point group:

from molsympy.collections import symmetrized, unsymmetrized

# List available structures
print(unsymmetrized.names)   # ['C0v_1', 'C0v_2', ..., 'Td_3']
print(symmetrized.names)     # ['C0v_1', 'C0v_2', ..., 'Td_3']

# Load a structure by key  ('<PointGroup>_<index>')
mol_u = unsymmetrized['C3h_1']
mol_s = symmetrized['C3h_1']

# Iterate over all structures in a collection
for name in symmetrized.names:
    atoms = symmetrized[name]

The two collections are:

Object Content
symmetrized Idealized geometries with exact point-group symmetry
unsymmetrized Raw geometries with slight numerical distortions

Lookup by molecular formula

Every structure in the database can also be retrieved by its molecular formula. The key and the formula are interchangeable in all collection operations:

from molsympy.collections import symmetrized, unsymmetrized

# These two calls return the same structure
atoms = unsymmetrized['C0v_1']
atoms = unsymmetrized['CNH']     # equivalent

# Works with both collections
mol_u = unsymmetrized['H2O']     # same as unsymmetrized['C2v_1']
mol_s = symmetrized['H2O']       # same as symmetrized['C2v_1']

# The `in` operator accepts formulas too
print('SF6' in symmetrized)      # True
print('C0v_1' in unsymmetrized)  # True

# List all available formulas
print(unsymmetrized.formulas)    # ['B13', 'BF3', 'C18H12', ..., 'YB2C23N12H21O2F6']

The formula stored for each entry is the one embedded in the .npz database at build time (see Building the database from XYZ files). Each structure carries exactly one formula alias; looking up by key always works regardless of whether a formula is defined.

Building the database from XYZ files

from molsympy import build_npz

build_npz("unsymmetrized/", "MolSymPy_unsym.npz")
build_npz("symmetrized/",   "MolSymPy_sym.npz", strip_suffix="_sym")

To embed molecular formula aliases, place a tab-separated nombres.txt file in the parent directory of the XYZ folder (or pass the path explicitly via nombres_file). The first column must be the structure key and the second column the molecular formula; a header row Molecule ID\tMolecular formula is skipped automatically:

Molecule ID     Molecular formula
C0v_1           CNH
C0v_2           CO
C2v_1           H2O
...
from molsympy import build_npz

# nombres.txt is detected automatically when it sits next to the xyz directory
build_npz("unsymmetrized/", "MolSymPy_unsym.npz")
build_npz("symmetrized/",   "MolSymPy_sym.npz", strip_suffix="_sym")

# Or pass the path explicitly
build_npz("unsymmetrized/", "MolSymPy_unsym.npz", nombres_file="my_names.txt")

License

MIT — see LICENSE.

Authors

  • Sebastian Hernandez-Gutierrez — Departamento de Física Aplicada, Cinvestav-IPN, Mérida, México
  • Diego Roman-Montalvo — Departamento de Física Aplicada, Cinvestav-IPN, Mérida, México
  • Gabriel Merino — Departamento de Física Aplicada, Cinvestav-IPN, Mérida, México
  • Filiberto Ortiz-Chi — Secihti-Departamento de Física Aplicada, Cinvestav-IPN, Mérida, México

If you use MolSymPy in your research, please cite the associated manuscript

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

molsympy-0.1.2.tar.gz (278.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

molsympy-0.1.2-py3-none-any.whl (283.0 kB view details)

Uploaded Python 3

File details

Details for the file molsympy-0.1.2.tar.gz.

File metadata

  • Download URL: molsympy-0.1.2.tar.gz
  • Upload date:
  • Size: 278.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for molsympy-0.1.2.tar.gz
Algorithm Hash digest
SHA256 09d4759e4c369b0826c2097f606d5146d1b004431493168895c05951219d3d40
MD5 35e905907462262705d2bf89a93e018f
BLAKE2b-256 2d6b85de0bf073de1da9afa2101daddfa4ab778bbb9136f3282736d4a3a3c30f

See more details on using hashes here.

File details

Details for the file molsympy-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: molsympy-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 283.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for molsympy-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 09ab48306a5e4baca8613627dea6b317e9d70421a62787c5bdcfc8eab6ff805b
MD5 1613f361aaf384e71546d5a0a8a77e01
BLAKE2b-256 fd7d8ec82c7693d3e770e0262d6ec4e04b5f60fc39cfbfa075b277004b63e66a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page