Skip to main content

DihedralPlan

Compute dihedral angle for a single set of four atoms.

Constructor

from warp_md import DihedralPlan

plan = DihedralPlan(
    selection_a,
    selection_b,
    selection_c,
    selection_d,
    pbc="none",
    degrees=True,
    range360=False
)
selection_a
Selection
required
First atom
selection_b
Selection
required
Second atom
selection_c
Selection
required
Third atom
selection_d
Selection
required
Fourth atom
pbc
str
default:"none"
Periodic boundary conditions: "none" or "orthorhombic"
degrees
bool
default:"True"
Return angles in degrees (True) or radians (False)
range360
bool
default:"False"
Use range [0, 360) instead of [-180, 180)

Example

import warp_md as wmd

system = wmd.System("peptide.pdb")
traj = wmd.open_trajectory("md.nc", system)

# Calculate phi backbone dihedral
c_prev = system.select("resid 5 and name C")
n = system.select("resid 6 and name N")
ca = system.select("resid 6 and name CA")
c = system.select("resid 6 and name C")

plan = wmd.DihedralPlan(c_prev, n, ca, c, degrees=True)
phi = plan.run(traj, system)

print(f"Phi angle range: {phi.min():.1f}° to {phi.max():.1f}°")

MultiDihedralPlan

Compute multiple dihedral angles simultaneously.

Constructor

plan = MultiDihedralPlan(
    dihedral_groups,
    mass_weighted=False,
    pbc="none",
    degrees=True,
    range360=False
)
dihedral_groups
list
required
List of tuples, each containing 4 selections: [(sel_a, sel_b, sel_c, sel_d), ...]
mass_weighted
bool
default:"False"
Use center of mass for each selection
pbc
str
default:"none"
Periodic boundary conditions
degrees
bool
default:"True"
Output in degrees
range360
bool
default:"False"
Use [0, 360) range

run() Method

Returns: 2D array of shape (n_frames, n_dihedrals)

Example

# Calculate all backbone dihedrals for a residue
residue = 10

# Phi angle
phi_group = (
    system.select(f"resid {residue-1} and name C"),
    system.select(f"resid {residue} and name N"),
    system.select(f"resid {residue} and name CA"),
    system.select(f"resid {residue} and name C")
)

# Psi angle
psi_group = (
    system.select(f"resid {residue} and name N"),
    system.select(f"resid {residue} and name CA"),
    system.select(f"resid {residue} and name C"),
    system.select(f"resid {residue+1} and name N")
)

plan = wmd.MultiDihedralPlan(
    [phi_group, psi_group],
    degrees=True
)
angles = plan.run(traj, system)

phi = angles[:, 0]
psi = angles[:, 1]

# Ramachandran plot
import matplotlib.pyplot as plt
plt.scatter(phi, psi, alpha=0.5, s=1)
plt.xlabel("φ (degrees)")
plt.ylabel("ψ (degrees)")
plt.xlim(-180, 180)
plt.ylim(-180, 180)
plt.title(f"Ramachandran Plot - Residue {residue}")
plt.show()

PuckerPlan

Calculate sugar pucker phase and amplitude.

Constructor

plan = PuckerPlan(
    atoms,
    method="altona",
    pucker_type="5ring"
)
atoms
list
required
List of 5 selections for ring atoms (for ribose: C1’, C2’, C3’, C4’, O4’)
method
str
default:"altona"
Calculation method: "altona" or "cremer"
pucker_type
str
default:"5ring"
Ring type: "5ring" (ribose) or "6ring" (pyranose)

run() Method

Returns: 2D array of shape (n_frames, 2) containing:
  • Column 0: Phase angle (degrees)
  • Column 1: Amplitude (degrees for Altona, Å for Cremer-Pople)

Example

# Analyze RNA sugar pucker
residue = 5

atoms = [
    system.select(f"resid {residue} and name C1'"),
    system.select(f"resid {residue} and name C2'"),
    system.select(f"resid {residue} and name C3'"),
    system.select(f"resid {residue} and name C4'"),
    system.select(f"resid {residue} and name O4'")
]

plan = wmd.PuckerPlan(atoms, method="altona")
pucker_data = plan.run(traj, system)

phase = pucker_data[:, 0]
amplitude = pucker_data[:, 1]

# Classify pucker
c3_endo = np.sum((phase > 0) & (phase < 36))
c2_endo = np.sum((phase > 144) & (phase < 180))

print(f"C3'-endo: {c3_endo/len(phase)*100:.1f}%")
print(f"C2'-endo: {c2_endo/len(phase)*100:.1f}%")
Sugar pucker is critical for understanding nucleic acid structure. C3’-endo is typical for A-form RNA, while C2’-endo is typical for B-form DNA.

RotateDihedralPlan

Modify trajectory by rotating around a dihedral angle.

Constructor

plan = RotateDihedralPlan(
    selection_a,
    selection_b,
    angle_degrees
)
selection_a
Selection
required
First atom defining rotation axis
selection_b
Selection
required
Second atom defining rotation axis
angle_degrees
float
required
Rotation angle in degrees

Example

# Rotate side chain chi1 angle
ca = system.select("resid 50 and name CA")
cb = system.select("resid 50 and name CB")

plan = wmd.RotateDihedralPlan(ca, cb, angle_degrees=60.0)
modified_traj = plan.run(traj, system)
This plan modifies coordinates. The output should be written to a new trajectory file.

Additional Dihedral Plans

Additional dihedral analysis and manipulation plans:
  • SetDihedralPlan — Set dihedral angle to specific value
  • PermuteDihedralsPlan — Permute rotatable bonds systematically
  • DihedralRmsPlan — RMSD in dihedral space
  • MultiPuckerPlan — Analyze multiple sugar puckers simultaneously
  • TorsionDiffusionPlan — Torsional diffusion coefficients
  • ToroidalDiffusionPlan — Diffusion on toroidal manifolds
Use warp-md list-plans --category dihedrals for detailed documentation.

Build docs developers (and LLMs) love