How to compute dihedrals#

Goal#

Calculate one or many dihedral angles from a trajectory or single structure.

Minimal example#

import numpy as np
from moleculekit.molecule import Molecule

mol = Molecule("3PTB")

# Atom indices defining the psi backbone dihedral of residue 17:
# N(17) - CA(17) - C(17) - N(18)
psi17 = [
    mol.atomselect("resid 17 and name N",  indexes=True)[0],
    mol.atomselect("resid 17 and name CA", indexes=True)[0],
    mol.atomselect("resid 17 and name C",  indexes=True)[0],
    mol.atomselect("resid 18 and name N",  indexes=True)[0],
]

# Read the current value (returns radians)
print(f"psi(17) before: {np.degrees(mol.getDihedral(psi17)):.1f}°")

# Set it to an extended-backbone value (180°) and read it back to confirm
mol.setDihedral(psi17, np.pi)
print(f"psi(17) after : {np.degrees(mol.getDihedral(psi17)):.1f}°")

Parameters that matter#

Method / argument

What it does

mol.getDihedral(atom_quad)

Returns the dihedral angle in radians for the four atom indices in atom_quad. Operates on the current mol.frame.

mol.setDihedral(atom_quad, radians, bonds=None, guessBonds=False)

Rotates the downstream half of the molecule around the central bond of the dihedral so the angle becomes radians. For a chain of modifications pass bonds=mol._getBonds() once to keep the bond table from being re-guessed on every call.

Common variations#

# The low-level function — useful when you have raw (4, 3) coords (e.g.
# from a numpy slice or a manually constructed array) and don't want to
# go through a Molecule
from moleculekit.dihedral import dihedralAngle

angle = dihedralAngle(mol.coords[psi17, :, 0])
# Compute the same dihedral across every frame of a trajectory
angles = np.array([
    dihedralAngle(mol.coords[psi17, :, f])
    for f in range(mol.numFrames)
])

Gotchas#

  • Both getDihedral and dihedralAngle return angles in radians; convert with np.degrees(angle) if you want degrees.

  • mol.getDihedral operates on the current mol.frame — set mol.frame = i first if you want a specific frame.

  • mol.setDihedral rotates the downstream side of the dihedral in place; the upstream side is held fixed. If the topology is ambiguous (the rotation would split the molecule wrong), the call may fail — guard against this by passing an explicit bonds= array.

  • For computing many dihedrals at once across a trajectory, prefer MetricDihedral from moleculekit.projections.metricdihedral — it batches the work efficiently.

See also#