You've managed to finally find out how the atoms are spatially arranged on your newly-discovered molecular entity. Through, say, spectroscopic means, you are now in possession of a bunch of atom coordinates, atom types, bond lengths, bond types, and whatnot for your molecule. You are now interested in determining the point group (symmetry group) of your molecule.

For simple molecules like methane ($T_d$) or benzene ($D_{6h}$), it is a simple matter of visual inspection to determine the point group in which a molecule belongs. However, this isn't so feasible when the molecule is a bit on the large side.

Given a molecule stored in some convenient data format (*.pdb, *.mol, etc.), how do you algorithmically determine the molecule's symmetry group?

  • 3
    $\begingroup$ For what it's worth, VMD includes a plugin for this purpose called SymmetryTool. $\endgroup$ Dec 1, 2011 at 9:38

6 Answers 6


My primary experience is with crystal structures, and there is only a finite number of point symmetries that show up in a crystal. So, the algorithm I would use is slightly different than what you'd use in a molecule. But, it is unlikely with a large molecule that the continuous symmetries will show up, like the axial symmetry in H$_2$ or CO$_2$, so the methods should overlap quite well. When determining the symmetry in a system, there are two different, but related, symmetries to consider: local and global.

Local Symmetry

Local symmetry is the symmetry of the local environment around a specific point. In particular, the symmetry at each atomic location determines the local atomic splitting and to some extent the chemical environment, and is a subgroup of the global symmetry. For example, in benzene the local symmetry consists of two reflection planes and a $C_2$ axis ($180^\circ$ rotation symmetry). (Obviously, only two of the operations are necessary to generate the entire local point group.)

enter image description here

From an algorithmic perspective, what we've done is to first find the nearest neighbors of the target atom, and then enumerate all the ways we can rotate that environment about the central atom and have it remain the same. More mathematically, it is solving for all orthogonal matrices, $\mathbf{A}$, such that

$$\mathbf{A}(\vec{x}_i - \vec{x}_c) = \vec{x}_j - \vec{x}_c$$

where $\vec{x}_i$ and $\vec{x}_j$ are the positions of atoms of the same species and $\vec{x}_c$ is the position of the central, or target, atom. But, I'd look at simpler forms first, like whether or not a reflection plane exists, prior to trying to solve for $\mathbf{A}$ in general.

Another thought is to use the angular momentum matrices as generators of rotation, then

$$\mathbf{A} = \exp(i \phi \hat{n}\cdot\vec{\mathbf{L}})$$

where $\hat{n} \in \mathbb{R}^3$ is a unit vector about which a rotation of with angle $\phi$ is performed, and $\vec{\mathbf{L}} = (\mathbf{L}_x,\ \mathbf{L}_y,\ \mathbf{L}_z)$ is the vector of three dimensional angular momentum matrices. $\mathbf{A}$ would then have only 3 unknowns.

Global Symmetry

Where the local symmetry determines the environment around a single atom, the global symmetry dictates how the atoms interchange with each other. The first step in determining the global symmetry is to determine the equivalent atoms. First, determine the types of and the relative directions to the nearest neighbor (and second nearest, or higher, if desired) atoms. Two atoms are then equivalent, if their neighbors have the same spatial arrangements. This is straightforward to calculate.

The second step is roughly the same as that found in the local symmetry case, except that the center of mass of the molecule is likely the symmetry center. At this point, if the local symmetries have been determined, only a few unique operations may need to be found to generate the entire group. For example, in the B20 crystal structure, each atom has a local $C_3$ symmetry, and the full point group is generated by including a 2-fold ($180^\circ$ rotation) screw axis which transforms one atom into another. In benzene, two operations are required: a 6-fold ($60^\circ$) rotation through the central axis and a reflection plane bisecting a bond.

Edit: For the B20 structure, you can use two of the $C_3$ axes, instead, to generate the full group. This should allow you to avoid having to figure out a way to automatically determine the screw axis.

Caution: A caution on using the ideas in the local symmetry section in the global section, to be a symmetry operation, the environment must also be transformed. So, that if you find $\mathbf{A}$, from above, it will only give a candidate symmetry as the transformation may not similarly change the environment appropriately, and further checks are needed. For instance, if the benzene ring had hydrogen atoms sticking out of the plane of the ring along one side, then the reflection plane bisecting the carbon-carbon bond would be fine, but a $180^\circ$ rotation similarly bisecting the bond would not because it would not reproduce the local environment.

Edit - Translations: There is one other complication that the above discussion on local symmetry ignores: translations. Formally, the correct symmetry operation is

$$\mathbf{A}(\vec{x}_i - \vec{x}_c) + \vec{t} = \vec{x}_j - \vec{x}_c$$

where $\mathbf{A}$ and $\vec{x}_k$, as above, and $\vec{t}$ is an arbitrary translation. In a symmorphic crystal,

$$\vec{t} = n_1 \vec{a}_1 + n_2 \vec{a}_2 + n_3 \vec{a}_3$$

where $\vec{a}_i$ is a primitive lattice translation and $n_i \in \mathbb{Z}$, so the point group and translations are completely separable. In a non-symmorphic crystal, $\vec{t}$ can consist of non-primitive translations. The difference between the two is simply that for a symmorphic crystal, a single center of rotation can be found, but for non-symmorphic crystals, this is not true. A molecular system is likely to be "non-symmorphic" in this latter sense, and require the addition of translations to fully realize the group.

  • 1
    $\begingroup$ @J.M., I added a caution on using the ideas in the local symmetry case blindly in the global case. In the global case, there is the added stricture that the local environment must also be transformed by the symmetry operation, and I don't think I had made it clear. $\endgroup$
    – rcollyer
    Dec 1, 2011 at 17:08
  • $\begingroup$ @J.M., I forgot to include any discussion on translations and their effect on the symmetry operations. I have included a brief addendum. $\endgroup$
    – rcollyer
    Dec 7, 2011 at 18:02
  • $\begingroup$ I see. I had always thought an algorithm for doing this would somehow put a molecule or crystal into a "standard orientation" (whatever that might mean) before checking neighbors and such. $\endgroup$
    – J. M.
    Dec 7, 2011 at 18:08
  • 1
    $\begingroup$ @J.M., for a crystal, there are two "standard orientations:" the crystal lattice and the primitive lattice, and they may not be the same, like in a face-centered cubic system. For a molecule, I'd probably use the center of mass as the origin, and then diagonalize the moment of inertia tensor to "properly align" it. That would not, however, eliminate the need for multiple rotation centers, if the more general symmetry operation is required, like a screw axis in a crystal. $\endgroup$
    – rcollyer
    Dec 7, 2011 at 19:07
  • $\begingroup$ The hyperlink in the first sentence goes to a page that in my opinion is not useful, and also not representative of the text displayed in the hyperlink. $\endgroup$ Apr 30, 2023 at 3:52

There's old code for the purpose that's used in a few packages, called SYMMOL. The algorithm it uses is described in the following paper:

T. Pilati and A. Forni, "SYMMOL: a program to find the maximum symmetry group in an atom cluster, given a prefixed tolerance", J. Appl. Cryst. 1998. 31, 503-504.

Basically, it determines the centre of inertia, then applies possible symmetry operations and attempts to determine whether a transformation vector exists to map the operated geometry onto the original within a given tolerance. The code itself is no longer available from the authors' site, but it is available (with a set of example input files) here.


I'm happy to answer that there's a high-quality open source code for this:


libmsym is a C library dealing with point group symmetry in molecules. It can determine, symmetrize and generate molecules of any point group. It can also generate symmetry adapted linear combinations of atomic orbitals for a subset of all point groups and orbital angular momentum (l), and project orbitals into the irreducible representation with the larges component.

I have adapted libmysm into Avogadro and a release should come out later in August 2015.

I believe the author is currently working on finishing a manuscript about the details. I'll revise this answer when it's published.


If you're still interested in this, I have a python script that will give you the (Abelian) point group (and symmetrically non redundant) atoms of any molecule within a specified tolerance.

The difference between my routine and a lot of others I've seen available is that the initial orientation is not important, making it useful to run in the results of geometry optimisations where you haven't specified an initial point group (as often, making an assumption like this can limit the geometry, forcing it to be symmetric and giving non equilibrium ground state.)

If you're still interested, let me know, I'll share it here.

  • 1
    $\begingroup$ I would definitely be interested in this script. Are you willing to make it open source (e.g., through GitHub?) $\endgroup$ Feb 10, 2015 at 3:54
  • $\begingroup$ @GeoffHutchison I'll have a play around with it, as it's inside a larger program (it currently is part of a program which runs molpro automatically to try and minimize geometry, and then extracts the generated geometries and orients them). Will be reasonably simple to extract it and clean it up a little. $\endgroup$
    – will
    Feb 10, 2015 at 11:17
  • $\begingroup$ Thanks. I'd be happy to clean it up as needed. There's definitely a demand for this kind of tool. $\endgroup$ Feb 10, 2015 at 13:51

I once wrote a small Python script to detect the point group symmetry for a molecule. If you're interested, please see https://github.com/sunqm/pyscf/blob/master/pyscf/symm/geom.py

  • 1
    $\begingroup$ It appears that the OP is more interested in the approach than just the code. It would be helpful if you could describe your approach in more detail. $\endgroup$
    – Paul
    Feb 26, 2015 at 15:20

There are some software packages, such as Materials Studio, that can automatically identify the point group of a molecule for you. However if you want to figure it out yourself, there is a nice flowchart that will will walk you through the process. You can also look at the Otterbein symmetry website for some tutorials and and interactive demos.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.