Molecular Symmetry
symmetry.py module
Symmetry operations as 3×3 matrices, character tables of 55 point groups, and the MolSym class: atom tracking, representations (atoms, atomic orbitals, bond stretchings, cartesian displacements), reduction into irreducible representations, symmetry of molecular orbitals, IR / Raman activity and 3D visualization of the symmetry elements.
Two ways of using the module
2. Symmetry operations
3. Character tables
4. The MolSym class
5. Representations and their reduction
API reference
Two ways of using the module
Without a molecular geometry |
With a molecular geometry |
|
|---|---|---|
What you work on |
symmetry operations, point groups, character tables, representations given by their characters |
a molecule: atoms, orbitals, bonds, vibrations |
Tools |
functions |
the |
Typical questions |
What is the product of two operations? What is the inverse of \(C_3\)? What does the character table of D6h look like? How does a given representation reduce? |
Which operations exchange which atoms? What are the symmetries of the SALCs, of the π MOs, of the vibrations? How many IR bands? |
Sections |
2, 3 |
4, 5, 6 |
No geometry, pymatgen or py3Dmol is needed for the first use.
1. Principle
1.1 Symmetry operations as matrices
A symmetry operation leaves the molecule unchanged: each atom is sent onto an atom of the same element. With the origin at the center of mass, every operation is a linear transformation of the atomic coordinates, i.e. a 3×3 orthogonal matrix \(R\):
proper operations (identity \(E\), rotations \(C_n^k\)): \(\det R = +1\)
improper operations (reflections \(\sigma\), inversion \(i\), improper rotations \(S_n^k\)): \(\det R = -1\)
The product of two operations is the product of their matrices, and the inverse of an operation is the transpose of its matrix (\(R^{-1} = R^{T}\)).
1.2 Atom tracking
Applying \(R\) to the coordinates and looking for the atom that sits at each new position gives a permutation of the atoms. This atom tracking is the heart of the module:
the molecule belongs to the group if every operation of the group gives a permutation (no atom lands on an empty position)
the number of atoms that stay in place is the character of the atomic representation \(\Gamma_\mathrm{atoms}\)
the characters of all the other representations (atomic orbitals, bonds, displacements) follow from the same tracking
1.3 Reduction
A representation \(\Gamma\) with characters \(\chi(R)\) is decomposed into irreducible representations \(\Gamma_i\) with the reduction formula:
where \(h\) is the order of the group and \(g_c\) the number of operations in class \(c\).
2. Symmetry operations
No molecular geometry is needed in this section.
Function |
Operation |
|---|---|
|
\(E\) |
|
\(i\) |
|
rotation \(C_n^k\) (angle \(2\pi k/n\)) |
|
reflection through a plane |
|
improper rotation \(S_n^k = \sigma_⟂ C_n^k\) |
|
inverse of an operation (\(= M^T\)) |
|
name of an operation given as a matrix |
|
LaTeX display of a matrix, with exact entries (\(\frac{1}{2}\), \(\frac{\sqrt{3}}{2}\)…) when possible |
axis:"x","y","z"or any direction, e.g.(1, 1, 1)plane:"xy","xz","yz"or, for any other plane, its normal vector, e.g.(1, -1, 0)for the diagonal plane containing \(z\) and the bisector of \(x\) and \(y\) (\(\sigma_d\) of CH4, D4h…)
from pyphyschemtools import Cn, sigma, Sn, inv, identify, show_matrix
C3 = Cn(3)
identify(C3 @ C3) # 'C3²(z)'
identify(inv(C3), with_inverse=True) # 'C3²(z) = C3⁻¹(z)'
identify(sigma("xz") @ sigma("yz")) # 'C2(z)'
identify(Sn(6) @ Sn(6) @ Sn(6)) # 'i'
show_matrix(C3)
Names given by identify:
axes:
C3(z),C2(x),C3(1,1,1); an axis lying in the \(xy\) plane at an angle \(\varphi\) from \(x\):C2(xy,30°)planes:
σ(xy),σ(xz),σ(yz); a vertical plane containing \(z\) and the direction at \(\varphi\) from \(x\):σ(z,60°); any other plane is given by its normal:σ⊥(1,1,1)powers:
C3²,S4³,S3⁵…
3. Character tables
No molecular geometry is needed in this section.
character_table(group, functions=True, complex=False) returns the character table as a pandas DataFrame, with the basis functions (linear functions and rotations, quadratic functions). available_groups() lists the 55 point groups:
Family |
Groups |
|---|---|
low symmetry |
C1, Cs, Ci |
Cn |
C2 … C8 |
S2n |
S4, S6, S8 |
Cnv, Cnh, Dn, Dnh, Dnd |
n = 2 … 8 |
cubic, icosahedral |
T, Th, Td, O, Oh, I, Ih |
other names are accepted with a message, e.g. S3 = C3h (for odd \(n\), \(S_n\) contains \(\sigma_h\) and \(C_n\)), C3i = S6
the tables of the textbooks (n ≤ 6) are written explicitly; the other axial groups are built automatically, and the construction has been checked against the explicit tables
every table has been checked: classes, orthogonality of the rows, \(\sum d_i^2 = h\), Mulliken labels (\(g/u\), \('/''\)), reduction of \(\Gamma_{xyz}\)
the basis functions are not copied from the textbooks: they are computed with the projection operators
Complex conjugate pairs. In the groups C3…C8, S4, S6, S8, C3h…C8h, T and Th, some irreducible representations come in pairs with complex conjugate characters (\(\varepsilon = e^{2\pi i/n}\)). By default, each pair is given as a single real row (sum of the two characters, e.g. \(2, -1, -1\) for C3), marked with *; it counts as one pair in the reductions. With complex=True, the two components ¹E and ²E are given separately.
Finding the point group. point_group_flowchart(group=None, lang="En") draws the usual decision tree (linear? several \(C_n\) with \(n \geq 3\)? highest-order \(C_n\)? \(n\) \(C_2\) perpendicular to \(C_n\)? \(\sigma_h\)? \(n\) \(\sigma_d\) or \(\sigma_v\)? \(S_{2n}\)?…). If a group is given, the path leading to it is highlighted. MolSym.flowchart() does the same for the group of the molecule.
Reduction without a molecule. A representation given by its characters (one per class, in the order of the columns of the character table) can be reduced, and the IR / Raman activity of its components obtained, without any geometry:
from pyphyschemtools import reduce_representation, ir_raman_activity
reduce_representation("C3v", [4, 1, 2]) # Γ = 2A1 + E
ir_raman_activity("Td", [9, 0, 1, -1, 3]) # IR active: 2T2 | Raman active: A1 + E + 2T2
The methods MolSym.reduce() and MolSym.activity() do the same, with the point group of the molecule.
If the coefficients \(n_i\) are not integers, the characters do not correspond to a representation of the group (typing error, wrong group…): a warning is printed, followed by the decomposition with its non-integer coefficients, e.g. reduce_representation("Td", [9, 0, 1, -1, 5]) → Γ = 1.5 A1 - 0.5 A2 + 1 E - 0.5 T1 + 2.5 T2.
4. The MolSym class
4.1 Building a MolSym molecule
A MolSym molecule is built from its 3D structure (position of each atom). MolSym does not read structures itself: it delegates this task to molView (Chem3D module), and gets the atoms and their coordinates from it.
Input |
Call |
Typical use |
|---|---|---|
SMILES |
|
most molecules: 3D structure from PubChem, or generated by RDKit |
file (xyz, pdb, mol…) |
|
your own structures, or the models of |
PubChem CID, COD… |
|
any structure read by |
symbols and coordinates |
|
coordinates typed by hand, e.g. to see the effect of the orientation |
from pyphyschemtools import get_ppct_data
from pyphyschemtools import MolSym
from pyphyschemtools import molView
water = MolSym.from_molView(molView("O", source="smiles", display_now=False))
sf6 = MolSym.from_molView(molView(get_ppct_data("Symmetry/SF6_model.xyz"), source="file", display_now=False))
print(water.group, sf6.group) # C2v & Oh
It is also possible to type the coordinates by hand. It may be useful for small molecules, for educational reasons:
from pyphyschemtools import MolSym
water_xz = MolSym(["O", "H", "H"],
[[0, 0, 0.117], [0.757, 0, -0.469], [-0.757, 0, -0.469]],
"C2v")
The SMILES → 3D step needs a geometry optimization (force fields MMFF94 or UFF of RDKit), which fails for hypervalent compounds (SF6, PF5…) and organometallic compounds (ferrocene…): use an xyz file. A SMILES does not describe conformations either (e.g. the orientation of the OH groups of B(OH)3). Idealized models are provided in data_examples/Symmetry/: SF6, PF5, SF5Cl, cis/trans-SF4Cl2, mer/fac-SF3Cl3, B(OH)3, Fe(CO)5, eclipsed and staggered ferrocene, cerocene, ethylene, benzene.
from_molView(mv, group=None, display_now=False, **kwargs): molView already displays the molecule (its own display_now argument); display_now=True displays it again, in the standard orientation of its point group (see show()). The other arguments are those of MolSym (below).
4.2 Point group and orientation
Point group not given (
group=None, default):MolSymdelegates the symmetry analysis to pymatgen (PointGroupAnalyzer), which gives the point group and the symmetry operations of the molecule. The molecule is then placed in the standard orientation of its point group and symmetrized. This is the simplest way to proceed, and the only one for a structure of unknown orientation, e.g. from PubChem.Point group given (e.g.
"C2v"): the molecule is expected to be in the standard orientation of this group (see Conventions): principal axis along \(z\), molecular plane \(yz\) for C2v, etc. In this case, pymatgen is not needed: the module only checks the symmetry and, among the equivalent standard orientations, chooses the conventional one (e.g. water in the \(xz\) plane is moved to the \(yz\) plane). If the molecule is not in a standard frame, the module calls pymatgen to reorient it (if pymatgen is installed); otherwise, a warning is printed: the molecule does not belong to the group, or it is not in the standard orientation.orientation()tells where the molecule is: shape (linear, planar…), molecular plane, principal axis.
The coordinates are always translated to the center of mass. With standard_orientation=True (default), they are also symmetrized (average of the images of each atom over the group): this is needed for the 3D structures of PubChem or RDKit, which are not exactly symmetric. The initial (centred) coordinates are kept in coords_input. With standard_orientation=False, the coordinates are kept as given (no reorientation, no symmetrization), which is useful to show what happens when a molecule is not in the standard orientation.
4.3 Arguments
Argument |
Meaning |
|---|---|
|
chemical symbols, cartesian coordinates (Å) |
|
Schoenflies symbol; if |
|
places the molecule in the standard orientation of its point group, as the “Standard orientation” of Gaussian, and symmetrizes it |
|
tolerance (Å) of the symmetry detection (pymatgen) and of the symmetrization |
|
tolerance (Å) used to decide that two atoms coincide |
|
language of the messages ( |
|
prints, at the creation of the molecule, its point group and whether it was already in the standard orientation or has been placed in it |
Attributes. At its creation, the molecule prints its point group, e.g. Point group C2v (detected by pymatgen), stored in the attribute group. Molecule placed in the standard orientation of C2v and symmetrized. The results are stored in attributes:
Attribute |
Content |
|---|---|
|
Schoenflies symbol of the point group, e.g. |
|
chemical symbols; labels of the atoms ( |
|
coordinates (Å) used by the module, in the standard orientation |
|
initial coordinates, centred on the center of mass |
|
labels of the classes (columns of the character table); order \(h\) of the group |
4.4 Main methods
Method |
Result |
|---|---|
|
shape (linear, planar…), molecular plane, principal axis |
|
flowchart of the point groups, with the path leading to the group of the molecule |
|
atom tracking, e.g. |
|
atoms that stay in place; test of an operation |
|
sets of symmetry-equivalent atoms |
|
matrices of the operations of the group (LaTeX) |
|
matrix of an operation in a basis of atomic orbitals, and its trace (character); see the syntax of the bases |
|
character table, with the row \(\Gamma_\mathrm{atoms}\) |
|
representations (see below) |
|
reduction, IR / Raman activity of any representation |
|
irreducible representation of molecular orbitals |
|
3D views (py3Dmol) |
op is a class label of the character table ("C2", "σv(xz)", "C2'"…) or any 3×3 matrix.
The methods that display a result (orientation, reduce, gamma_*, activity, orbital_symmetry…) return nothing with show=True (default), to avoid an echo in a notebook. Use show=False to get the result (characters, dict, DataFrame) without display.
5. Representations and their reduction
5.1 Principle
A basis of functions attached to the molecule (atomic orbitals, bonds, displacements…) spans a representation of the point group. For an operation \(R\), the character \(\chi(R)\) is the trace of the matrix of \(R\) in this basis. It can be obtained without writing the matrix: only the functions that stay in place count.
\(R\,u_i = +u_i\): contribution \(+1\)
\(R\,u_i = -u_i\): contribution \(-1\)
\(R\,u_i = u_j\), another function of the basis (e.g. the similar function of another atom): contribution \(0\)
In particular, an atom that moves contributes 0, and an atom that stays in place contributes:
Basis |
Method |
Contribution of a fixed atom |
|---|---|---|
atoms (one s function per atom) |
|
\(1\) |
atomic orbitals of angular momentum \(l\) |
|
\(\chi_l(R)\) |
cartesian displacements |
|
\(\chi_{xyz}(R) = \mathrm{tr}\,R\) |
with, for a rotation of angle \(\theta\):
(\(\chi_0 = 1\) for s, \(\chi_1 = \mathrm{tr}\,R\) for p).
The representation is then reduced into irreducible representations with reduce() (see 1.3).
5.2 Atomic orbitals
gamma_orbitals(basis) gives, for each set of equivalent atoms and each shell, the characters and the symmetries of the symmetry-adapted linear combinations (SALCs), i.e. the building blocks of a molecular orbital diagram. Without argument, the basis set is made of the valence orbitals of all the atoms:
water.gamma_orbitals() # O 2s: A1; O 2p: A1 + B1 + B2; H 1s: A1 + B2
benzene.gamma_orbitals({"C": "pz"}) # π system: A2u + B2g + E1g + E2u
representation_matrix(op, basis) displays the matrix of an operation in the same basis, and its trace.
Syntax of the bases. The basis is described by the shells carried by each atom:
Shell |
Orbitals |
|---|---|
|
one s orbital |
|
\(p_x\), \(p_y\), \(p_z\) |
|
\(d_{z^2}\), \(d_{xz}\), \(d_{yz}\), \(d_{x^2-y^2}\), \(d_{xy}\) |
|
\(f_{z^3}\), \(f_{xz^2}\), \(f_{yz^2}\), \(f_{z(x^2-y^2)}\), \(f_{xyz}\), \(f_{x(x^2-3y^2)}\), \(f_{y(3x^2-y^2)}\) |
|
a single p orbital, e.g. the p orbital perpendicular to a planar molecule (π basis) |
|
two p orbitals, e.g. the p orbitals lying in the molecular plane (σ basis); |
The shells are given:
Form |
Meaning |
Example |
|---|---|---|
|
valence shells of each element: s for H and He; s, p for the main group elements; s, p, d for the d block; s, p, d, f for the f block |
|
a string |
the same shells on all the atoms; the shells can be written together or separated by spaces |
|
a list |
the same, as a list |
|
a dict |
the shells of each element; an element that is absent (or |
|
Partial p shells. A set of p orbitals spans a representation only if no symmetry operation mixes it with the other p orbitals. In a planar molecule, the p orbital perpendicular to the molecular plane is always fine: "pz" for benzene (plane \(xy\) in the standard orientation of D6h), "px" for water (plane \(yz\) in C2v). Use orientation() to know the molecular plane. On the contrary, \(p_x\) alone is mixed with \(p_y\) by the \(C_6\) rotation of benzene: {"C": "s px"} raises an error, and the in-plane orbitals must be given together, "pxy" or "px py". In groups that do not mix them (e.g. C2v), "px" and "py" are kept separate: water.gamma_orbitals(["s", "px", "py"]) gives one row for each.
5.3 Simple molecular orbitals
orbital_symmetry(C, atoms, shell) gives the irreducible representation of a molecular orbital, and orbital_symmetries(coeffs, energies, atoms, shell) labels all the MOs of a set, the degenerate MOs being grouped.
The MOs must be expanded on one atomic orbital per atom, all of the same type (shell = "s", "px", "py" or "pz"). They may come from any calculation: Hückel π MOs on the pz orbitals, combinations of the 1s orbitals of hydrogen atoms, or the corresponding coefficients of an ab initio / DFT calculation. But MOs that mix several orbitals on the same atom (s, p, d…) are not handled.
Argument |
Format |
|---|---|
|
one MO: 1D array of length \(n\); a set of degenerate MOs: 2D array of shape \((n, m)\), one column per MO |
|
2D array of shape \((n, N_\mathrm{MO})\), one column per MO (e.g. |
|
one energy per column of |
|
indices (in the molecule) of the \(n\) atoms carrying the basis orbitals, in the order of the coefficients; all the symmetry-equivalent atoms must be included |
|
|
|
degeneracy threshold, and tolerance on the symmetry of numerical coefficients |
from pyphyschemtools.huckel import HMO
h = HMO("c1ccccc1")
benzene.orbital_symmetries(h.c_MOs, h.E_MOs, atoms=[0, 1, 2, 3, 4, 5], shell="pz")
# A2u (x = 2), E1g (x = 1), E2u (x = -1), B2g (x = -2)
A set of degenerate MOs must be given as a whole: a single component of a degenerate pair does not span a representation, and orbital_symmetry raises an error.
5.4 Vibrations
gamma_3N() and gamma_vib() (non-linear molecules) give the representation of the 3N cartesian displacements and of the 3N − 6 vibrational modes, followed by their IR / Raman activity:
gamma_bonds(bonds) gives the representation spanned by bond stretchings (a bond sent onto itself contributes 1), e.g. the number of ν(CO) bands of a metal carbonyl: feco5.gamma_bonds(["C-O"]) → \(2A_1' + E' + A_2''\), 2 IR active bands. The bonds are detected from the distances (covalent radii), or given as element pairs (["C-H"]) or as atom indices ([(0, 1), (0, 2)]).
activity(chi): an irreducible representation is IR active if it transforms as \(x\), \(y\) or \(z\), Raman active if it transforms as a quadratic function.
water.gamma_vib() # 2A1 + B2; IR active: 2A1 + B2; Raman active: 2A1 + B2
ch4.gamma_vib() # A1 + E + 2T2; IR active: 2T2; Raman active: A1 + E + 2T2
6. Visualization
show(labels=False, axes=False): the molecule alone, in its standard orientationshow_elements(op=None, labels=False, axes=True): molecule and symmetry elements, for one class ("C3"), several classes (["S4", "C2"]) or all the elements (proper axes, planes, inversion center)show_operation(op): molecule before (left) and after (right) the operation, each atom keeping its label; the two views are linked
Colors: \(C_2\) red, \(C_3\) green, \(C_4\) blue, \(C_5\) orange, \(C_6\) purple, \(C_8\) brown; \(S_n\) axes dashed; planes in translucent blue; inversion center in black; cartesian axes \(x\), \(y\), \(z\) in grey.
7. Conventions
Standard orientation (Mulliken conventions):
Group |
Orientation |
|---|---|
general |
principal axis along \(z\) |
C2v |
\(C_2\) along \(z\), molecular plane \(yz\) |
D2h |
\(C_2\) axes along \(x\), \(y\), \(z\); \(z\) through the largest number of atoms; \(x\) perpendicular to the molecular plane |
Dnh, Dnd, Cnv |
one \(C_2'\) axis (or \(\sigma_v\) plane) along \(x\); \(C_2'\) and \(\sigma_v\) through the largest number of atoms |
D2d |
\(S_4\) along \(z\), \(C_2'\) along \(x\) and \(y\), \(\sigma_d\) planes on the diagonals |
T, Th, Td |
\(C_2\) (\(S_4\)) axes along \(x\), \(y\), \(z\), \(C_3\) along \((1,1,1)\) |
O, Oh |
\(C_4\) axes along \(x\), \(y\), \(z\) |
I, Ih |
\(C_2\) axes along \(x\), \(y\), \(z\), \(C_5\) along \((0, 1, \varphi)\) |
These conventions decide the labels of some irreducible representations (\(B_1\)/\(B_2\) in C2v, \(B_{1u}\)/\(B_{2u}\)/\(B_{3u}\) in D2h, \(B_{1u}\)/\(B_{2u}\) in D6h…). The textbooks do not all follow the same convention: check the orientation with orientation() before comparing with a table.
8. Limitations
linear molecules (C∞v, D∞h) are not handled: use the subgroups C2v and D2h
gamma_vib()assumes a non-linear molecule (3N − 6 modes)pymatgen is needed for the point group detection and for the standard orientation of a molecule that is not in a standard frame
PubChem provides no 3D structure for some compounds (hypervalent compounds such as SF6, organometallic compounds): idealized models are provided in
data_examples/Symmetry/(SF6, Fe(CO)5, ferrocene eclipsed and staggered, cerocene, ethylene, benzene)
API reference
Molecular symmetry for teaching purposes.
Symmetry operations are written as 3x3 matrices and applied to the atomic coordinates of a molecule. Tracking where each atom goes after an operation gives the characters of the atomic representation Γ_atoms, which can then be reduced with the character table of the point group.
- pyphyschemtools.symmetry.Cn(n, axis='z', k=1)[source]
Proper rotation C_n^k about an axis passing through the origin.
- Parameters:
n (int) – order of the axis (rotation angle 360°/n).
axis (str or array-like) – “x”, “y”, “z” (default) or a direction, e.g. (1, 1, 1).
k (int) – power of the operation (rotation angle k*360°/n).
- Returns:
3x3 rotation matrix.
- Return type:
np.ndarray
- class pyphyschemtools.symmetry.MolSym(symbols, coords, group=None, tol=0.05, lang='En', standard_orientation=True, sym_tolerance=0.3, verbose=True)[source]
Bases:
objectSymmetry analysis of a molecule: atom tracking under the symmetry operations of its point group, atomic representation Γ_atoms and its reduction into irreducible representations.
By default (standard_orientation=True), the molecule is placed in the standard orientation of its point group, as the “Standard orientation” of Gaussian: principal axis along z; for C2v, molecular plane = yz; for Dnh, one C2’ axis along x, through the largest number of atoms. If the molecule is not already in a standard frame, its symmetry operations are given by pymatgen. The coordinates are translated to the center of mass and symmetrized; the initial ones are kept in coords_input.
- Parameters:
symbols (list of str) – chemical symbols of the atoms.
coords (array-like) – Cartesian coordinates, shape (n_atoms, 3), in Å.
group (str) – Schoenflies symbol of the point group (see available_groups()); if None, detected with pymatgen.
tol (float) – tolerance (Å) used to decide that two atoms coincide.
lang (str) – language of the messages and tables (“En” (default) or “Fr”).
standard_orientation (bool) – if True (default), places the molecule in the standard orientation of its point group.
sym_tolerance (float) – tolerance (Å) of the symmetry detection (pymatgen) and of the symmetrization.
verbose (bool) – if True (default), prints the point group and the orientation of the molecule at its creation.
- group
Schoenflies symbol of the point group, e.g. “C2v”.
- Type:
str
- symbols
chemical symbols of the atoms.
- Type:
list
- atom_labels
labels of the atoms, e.g. [“O0”, “H1”, “H2”].
- Type:
list
- coords
coordinates (Å) used by the module (standard orientation).
- Type:
np.ndarray
- coords_input
initial coordinates, centred on the center of mass.
- Type:
np.ndarray
- labels
labels of the classes of operations (columns of the character table).
- Type:
list
- order
order h of the group (number of operations).
- Type:
int
- activity(chi, show=True)[source]
IR and Raman activity of the irreducible representations contained in a representation: IR active if the irrep transforms as x, y or z, Raman active if it transforms as a quadratic function (x², xy…).
- Parameters:
chi (array-like) – characters of the representation, one per class.
show (bool) – if True, prints the active irreps. With show=True, nothing is returned (no echo in a notebook); use show=False to get the result.
- Returns:
{“IR”: […], “Raman”: […]}, irreps with their multiplicities.
- Return type:
dict
- apply(op)[source]
Coordinates of the atoms after a symmetry operation.
- Parameters:
op (str or np.ndarray) – class label (e.g. “C2”, “σv”) or 3x3 matrix.
- Returns:
transformed coordinates, shape (n_atoms, 3).
- Return type:
np.ndarray
- bonds(scale=1.25)[source]
Bonds detected from the distances: d(A-B) < scale x (r_cov(A) + r_cov(B)), with the covalent radii of RDKit.
- Returns:
list of tuples (i, j), i < j.
- character_table(gamma=True, functions=True, complex=False)[source]
Character table of the point group, as a pandas DataFrame.
- Parameters:
gamma (bool) – if True, adds the row Γ_atoms at the bottom of the table.
functions (bool) – if True, adds the columns of the basis functions.
complex (bool) – if True, complex form of the pairs of complex conjugate irreps.
- equivalent_atoms()[source]
Sets of symmetry-equivalent atoms (orbits of the group).
- Returns:
list of lists of atom indices.
- flowchart()[source]
Flowchart (decision tree) of the point groups, with the path leading to the group of the molecule.
- classmethod from_molView(mv, group=None, display_now=False, **kwargs)[source]
Builds the molecule from a molView object (Chem3D module). MolSym does not read structures itself: molView reads a SMILES (3D structure from PubChem or generated by RDKit), a file (xyz, pdb, mol…), a PubChem CID…
MolSym.from_molView(molView(“O”, source=”smiles”, display_now=False)) MolSym.from_molView(molView(“SF6_model.xyz”, source=”file”, display_now=False)) MolSym.from_molView(molView(962, source=”cid”, display_now=False))
The point group is detected with pymatgen (unless given), then the molecule is placed in the standard orientation of its point group and symmetrized (3D structures from PubChem or RDKit are not exactly symmetric).
- Parameters:
mv (molView) – molecule loaded with molView.
group (str) – Schoenflies symbol; if None, detected with pymatgen.
display_now (bool) – if True, displays the molecule in 3D, in its standard orientation (see show). False by default, since molView already displays the molecule (its own display_now argument).
**kwargs – passed to MolSym (tol, lang, standard_orientation, sym_tolerance, verbose).
- gamma_3N(show=True)[source]
Representation spanned by the 3N cartesian displacements of the atoms: χ_3N(R) = (number of atoms that stay in place) x χ_xyz(R), where χ_xyz(R) = trace of the matrix of R.
- Parameters:
show (bool) – if True, displays Γ_atoms, Γ_xyz and Γ_3N with their reductions. With show=True, nothing is returned (no echo in a notebook); use show=False to get the characters.
- Returns:
characters of Γ_3N, one per class (show=False).
- Return type:
np.ndarray
- gamma_atoms(show=True)[source]
Characters of the atomic representation Γ_atoms: for each class, the number of atoms that stay in place under the operation.
- Parameters:
show (bool) – if True, displays the table with the fixed atoms. With show=True, nothing is returned (no echo in a notebook); use show=False to get the result.
- Returns:
characters of Γ_atoms, one per class.
- Return type:
np.ndarray
- gamma_bonds(bonds=None, show=True)[source]
Representation spanned by bond stretchings (internal coordinates): for an operation R, a bond that is sent onto itself (possibly with its two ends exchanged) contributes 1, a bond that moves contributes 0. The reduction, given for each set of equivalent bonds, gives the symmetries of the stretching vibrational modes (e.g. the number of IR / Raman active ν(CO) bands of a metal carbonyl).
- Parameters:
bonds (list) – bonds to consider, as pairs of atom indices [(0, 1), …], or as element pairs [“C-H”, “C-O”]; if None, all the bonds detected from the distances (see bonds()).
show (bool) – if True, displays the table of the characters and of the reductions. With show=True, nothing is returned (no echo in a notebook); use show=False to get the result.
- Returns:
characters of the total representation, one per class.
- Return type:
np.ndarray
- gamma_orbitals(basis='valence', show=True)[source]
Representation spanned by a basis of atomic orbitals, and its reduction for each set of equivalent atoms and each shell (s, p, d, f): the symmetries of the symmetry-adapted linear combinations (SALCs), i.e. the building blocks of a molecular orbital diagram.
For an operation R, an atom that stays in place contributes χ_l(R): 1 for s, the trace of R for p (p orbitals transform as x, y, z), etc.; an atom that moves contributes 0.
- Parameters:
basis (str or dict) – “valence” (default): s for H and He, s and p for the main group elements, s, p, d for the d block, s, p, d, f for the f block; or the same shells on all the atoms, e.g. “s”, “pz”, “sp”, [“s”, “px”, “py”]; or a dict giving the shells of each element, e.g. {“C”: “sp”, “H”: “s”} or {“Fe”: “spd”, “C”: “p”, “H”: “”}. “px”, “py” or “pz” alone: the p orbitals perpendicular to the molecular plane, i.e. a π basis, e.g. {“C”: “pz”} for benzene (molecular plane xy in the standard orientation of D6h), {“C”: “px”} for a planar C2v molecule (molecular plane yz); “pxy”, “pxz”, “pyz”: the p orbitals lying in the molecular plane (σ basis), e.g. {“C”: “s pxy”, “H”: “s”} for benzene.
show (bool) – if True, displays the table of the characters and of the reductions. With show=True, nothing is returned (no echo in a notebook); use show=False to get the result.
- Returns:
characters of the total representation, one per class.
- Return type:
np.ndarray
- gamma_vib(show=True)[source]
Representation of the 3N-6 vibrational modes (non-linear molecule): Γ_vib = Γ_3N - Γ_trans - Γ_rot, with χ_trans(R) = trace(R) (x, y, z) and χ_rot(R) = det(R) x trace(R) (Rx, Ry, Rz: axial vectors), followed by the IR / Raman activity of the modes.
- Parameters:
show (bool) – if True, displays Γ_3N, Γ_trans, Γ_rot and Γ_vib with their reductions, and the IR / Raman activity. With show=True, nothing is returned (no echo in a notebook); use show=False to get the characters.
- Returns:
characters of Γ_vib, one per class (show=False).
- Return type:
np.ndarray
- matrices(op=None, all_operations=False, exact=True)[source]
Displays the matrices of the symmetry operations of the group (LaTeX).
- Parameters:
op (str or list of str) – class label(s) (e.g. “C3”, [“C2”, “σv”]); if None, all the classes.
all_operations (bool) – if False (default), one representative per class; if True, all the operations of the class(es), named by identify.
exact (bool) – if True, exact forms of the entries (1/2, √3/2…) when possible.
- orbital_symmetries(coeffs, energies, atoms=None, shell='pz', tol=0.0001, show=True)[source]
Irreducible representations of all the MOs of a set, degenerate MOs being grouped. The MOs are expanded on ONE atomic orbital per atom, all of the same type (s, px, py or pz), e.g. the π MOs of a Hückel calculation; see orbital_symmetry().
- Parameters:
coeffs (array-like) – coefficients, 2D array of shape (n, number of MOs): one row per atom of atoms (same order), one column per MO (e.g. HMO.c_MOs).
energies (array-like) – energies of the MOs, one per column of coeffs (or Hückel x values, e.g. HMO.E_MOs), used to group the degenerate MOs; they do not need to be sorted.
atoms (list) – indices (in the molecule) of the n atoms carrying the basis orbitals, in the order of the rows of coeffs (default: all the atoms).
shell (str) – “s”, “px”, “py” or “pz”.
tol (float) – two MOs are degenerate if their energies differ by less than tol; also used to check the symmetry of the MOs.
show (bool) – if True, displays the table. With show=True, nothing is returned; use show=False to get the DataFrame.
- Returns:
MOs (column indices), energy, irrep (show=False).
- Return type:
pandas.DataFrame
- orbital_symmetry(C, atoms=None, shell='pz', tol=0.0001, show=True)[source]
Irreducible representation of a molecular orbital (or of a set of degenerate MOs) expanded on ONE atomic orbital per atom, all of the same type (s, px, py or pz): e.g. a Hückel π MO on the pz orbitals, or an MO built from the 1s orbitals of hydrogen atoms. The MOs may come from any calculation (Hückel, or the corresponding coefficients of an ab initio / DFT calculation), as long as the basis is one orbital per atom: MOs mixing several orbitals on the same atom (s, p and d…) are not handled.
- Parameters:
C (array-like) – coefficients of the MO, 1D array of length n (one coefficient per atom of atoms, in the same order), or of a set of degenerate MOs, 2D array of shape (n, number of MOs), one column per MO.
atoms (list) – indices (in the molecule) of the n atoms carrying the basis orbitals, in the order of the coefficients (default: all the atoms). All the atoms equivalent by symmetry must be included.
shell (str) – “s”, “px”, “py” or “pz”: orbital on each atom (for a π system, the p orbital perpendicular to the molecular plane, see orientation()).
tol (float) – tolerance used to check that the MOs span a representation (numerical coefficients of a quantum chemistry code are not exact).
show (bool) – if True, prints the characters and the irrep. With show=True, nothing is returned (no echo in a notebook); use show=False to get the result.
- Returns:
the irreducible representation(s), e.g. “E1g” (show=False).
- Return type:
str
- orientation(show=True)[source]
Describes the orientation of the molecule in the cartesian frame: shape (linear, planar or not), molecular plane (xy, xz, yz or other) or axis, and principal axis of the point group.
- Parameters:
show (bool) – if True, prints the description and returns nothing; if False, returns the dict without printing.
- Returns:
{“shape”: …, “plane”: …, “axis”: …, “principal_axis”: …}
- Return type:
dict
- reduce(chi=None, show=True)[source]
Reduction of a representation into irreducible representations: n_i = (1/h) Σ_classes g_c χ(c) χ_i(c). A pair of complex conjugate irreps (row marked * in the character table) is counted as a whole.
- Parameters:
chi (array-like) – characters of the representation, one per class (default: Γ_atoms of the molecule).
show (bool) – if True, prints the decomposition (e.g. Γ = 2A1 + B2). With show=True, nothing is returned (no echo in a notebook); use show=False to get the result.
- Returns:
number of times each irreducible representation appears.
- Return type:
dict
- representation_matrix(op, basis='s', atoms=None, show=True)[source]
Matrix of a symmetry operation in a basis of atomic orbitals. For a basis of s orbitals, it is the permutation matrix of the atoms; for p orbitals, each block is the 3x3 matrix of the operation itself. The trace of the matrix is the character of the operation.
- Parameters:
op (str or np.ndarray) – class label (e.g. “C2”) or 3x3 matrix.
basis (str, list or dict) – orbitals on each atom, as in gamma_orbitals: “s” (default), “p”, “sp”, “d”, “f”, “valence”, “pz”, [“s”, “px”], or a dict per element, e.g. {“O”: “sp”, “H”: “s”}.
atoms (list) – atoms carrying the basis orbitals (default: all the atoms).
show (bool) – if True, displays the matrix (LaTeX), the basis and the trace; if False, returns the matrix without display.
- Returns:
the matrix (show=False).
- Return type:
np.ndarray
- show(labels=False, axes=False, width=500, height=400)[source]
Interactive 3D view (py3Dmol) of the molecule alone, in its standard orientation.
- Parameters:
labels (bool) – if True, shows the atom labels (O0, H1…).
axes (bool) – if True, shows the cartesian axes x, y, z.
width (int) – size of the viewer in pixels.
height (int) – size of the viewer in pixels.
- show_elements(op=None, labels=False, axes=True, width=500, height=400)[source]
Interactive 3D view (py3Dmol) of the molecule and of its symmetry elements.
- Parameters:
op (str or list of str) – class label(s) (e.g. “C3”, [“S4”, “C2”]): shows only the elements of these classes. If None, shows all the proper axes, planes and the inversion center (can be crowded for high symmetry groups).
labels (bool) – if True, shows the atom labels (O0, H1…).
width (int) – size of the viewer in pixels.
height (int) – size of the viewer in pixels.
Colors: C2 red, C3 green, C4 blue, C5 orange, C6 purple, C8 brown; Sn axes dashed; planes in translucent blue; inversion center in black.
- show_operation(op, highlight=None, axes=True, width=700, height=350)[source]
Interactive 3D view (py3Dmol) of the molecule before (left) and after (right) a symmetry operation. Each atom keeps its label, so that the atom tracking can be read on the figure. The two views are linked.
- Parameters:
op (str) – class label (e.g. “C3”, “σv”); the representative of the class is used.
highlight (int or list of int) – atom(s) to follow: a translucent yellow sphere marks the atom before the operation (left) and the place where it arrives after the operation (right).
axes (bool) – if True, shows the cartesian axes x, y, z.
width (int) – size of the viewer in pixels.
height (int) – size of the viewer in pixels.
- symmetry_elements(op=None)[source]
Symmetry elements of the molecule (axes, planes, inversion center).
- Parameters:
op (str or list of str) – class label(s) (e.g. “C3”, [“S4”, “C2”]): elements of these classes only. If None, all the elements: proper axes (labelled by their highest order), planes and inversion center.
- Returns:
list of tuples (type, vector, label), type being ‘axis’, ‘improper’, ‘plane’ or ‘center’.
- track(op, verbose=True)[source]
Atom tracking: for each atom, the index of the atom on which it lands after the symmetry operation.
- Parameters:
op (str or np.ndarray) – class label (e.g. “C2”, “σv”) or 3x3 matrix.
verbose (bool) – if True, prints the tracking (e.g. H1 → H2).
- Returns:
- destination index of each atom, or None for an atom that lands
on no atom of the same element (the operation is then not a symmetry operation of the molecule).
- Return type:
list
- pyphyschemtools.symmetry.Sn(n, axis='z', k=1)[source]
Improper rotation S_n^k: rotation C_n^k followed by a reflection through the plane perpendicular to the axis.
- Parameters:
n (int) – order of the axis.
axis (str or array-like) – “x”, “y”, “z” (default) or a direction, e.g. (1, 1, 1).
k (int) – power of the operation.
- pyphyschemtools.symmetry.available_groups()[source]
List of the point groups whose character table is available.
- pyphyschemtools.symmetry.character_table(group, functions=True, lang='En', complex=False)[source]
Character table of a point group, as a pandas DataFrame.
Pairs of complex conjugate irreducible representations (groups C3…C8, S4, S6, S8, C3h…C8h, T, Th) are given by default as a single real row (sum of the two characters), marked with *. With complex=True, the two components are given separately (¹E, ²E), with ε = exp(2πi/n).
- Parameters:
group (str) – Schoenflies symbol of the point group (see available_groups()).
functions (bool) – if True, adds the columns of the basis functions (linear functions and rotations, quadratic functions).
lang (str) – language of the messages (“En” (default) or “Fr”).
complex (bool) – if True, complex form of the pairs of complex conjugate irreps.
- pyphyschemtools.symmetry.identify(M, tol=1e-06, with_inverse=False)[source]
Name of a symmetry operation given as a 3x3 matrix: E, i, σ(xy), C3(z), C3²(z), S4³(z), C3(1,1,1)…
Vertical planes and axes lying in the xy plane are located by the angle φ of their direction in the xy plane, measured from x: σ(z,60°) is the plane containing z and the direction at 60° from x (σ(z,0°) = σ(xz), σ(z,90°) = σ(yz)); C2(xy,30°) is the C2 axis in the xy plane at 30° from x. Other planes are given by their normal: σ⊥(1,1,1).
The direction of an axis is oriented so that its first non-zero component is positive, and the rotation angle follows the right-hand rule.
- Parameters:
M (np.ndarray) – 3x3 matrix.
with_inverse (bool) – if True, also gives the inverse notation when the operation is the inverse of the generator: ‘C3²(z) = C3⁻¹(z)’.
Examples
>>> identify(Cn(3) @ Cn(3)) 'C3²(z)' >>> identify(sigma((0, 0, 1)) @ Cn(2)) 'i'
- pyphyschemtools.symmetry.inv(M)[source]
Inverse of a symmetry operation. The matrix is orthogonal, so its inverse is its transpose: inv(Cn(3)) = C3⁻¹ = C3².
- pyphyschemtools.symmetry.ir_raman_activity(group, chi, show=True, lang='En')[source]
IR and Raman activity of the irreducible representations contained in a representation of a point group, without any molecule: IR active if the irrep transforms as x, y or z, Raman active if it transforms as a quadratic function (x², xy…).
- Parameters:
group (str) – Schoenflies symbol of the point group.
chi (array-like) – characters of the representation, one per class.
show (bool) – if True, prints the active irreps and returns nothing; if False, returns the result without printing.
lang (str) – language of the messages (“En” (default) or “Fr”).
- Returns:
{“IR”: […], “Raman”: […]}, irreps with their multiplicities (show=False).
- Return type:
dict
- pyphyschemtools.symmetry.point_group_flowchart(group=None, lang='En', ax=None)[source]
Flowchart (decision tree) to find the point group of a molecule. If a group is given, the path leading to it is highlighted.
- Parameters:
group (str) – Schoenflies symbol of the point group to highlight (optional).
lang (str) – “En” (default) or “Fr”.
ax (matplotlib.axes.Axes) – axes to draw in (optional).
- Returns:
matplotlib.figure.Figure
- pyphyschemtools.symmetry.reduce_representation(group, chi, show=True, lang='En')[source]
Reduction of a representation of a point group into irreducible representations, without any molecule: n_i = (1/h) Σ_classes g_c χ(c) χ_i(c)*. A pair of complex conjugate irreps (row marked * in the character table) is counted as a whole.
- Parameters:
group (str) – Schoenflies symbol of the point group.
chi (array-like) – characters of the representation, one per class, in the order of the columns of character_table(group).
show (bool) – if True, prints the decomposition (e.g. Γ = 2A1 + B2) and returns nothing; if False, returns the result without printing.
lang (str) – language of the messages (“En” (default) or “Fr”).
- Returns:
number of times each irreducible representation appears (show=False).
- Return type:
dict
Example
>>> reduce_representation("C3v", [4, 1, 2]) Γ = 2A1 + E
- pyphyschemtools.symmetry.show_matrix(M, name=None, exact=True)[source]
Displays a 3x3 symmetry operation as a LaTeX matrix, with its name.
- Parameters:
M (np.ndarray) – 3x3 matrix.
name (str) – name of the operation; if None, given by identify(M).
exact (bool) – if True, exact forms of the entries (1/2, √3/2…) when possible.
- pyphyschemtools.symmetry.sigma(plane='xy')[source]
Reflection σ through a plane containing the origin.
- Parameters:
plane (str or array-like) – “xy”, “xz” or “yz”, or, for any other plane, the vector normal to the plane, e.g. (1, -1, 0) for the diagonal plane containing z and the bisector of x and y (σd of CH4, D4h…).
- Returns:
3x3 reflection matrix.
- Return type:
np.ndarray
Examples
>>> sigma("xy") # σh when the principal axis is z >>> sigma((1, -1, 0)) # σd containing z and the direction (1, 1, 0)