coupling — J-Coupling Prediction
The synth_pdb.coupling module predicts ³J(HN–Hα) scalar coupling constants for protein structures using the Karplus equation. These couplings are sensitive to the backbone φ torsion angle and are a key restraint in NMR structure validation.
Scientific Background
The Karplus Equation
The relationship between the ³J coupling and the dihedral angle is given by:
where θ = φ − 60° for L-amino acids (H–N–Cα–H dihedral). The synth_nmr engine uses the Vuister & Bax (1993) parameterisation:
| Coefficient | Value |
|---|---|
| A | 6.51 Hz |
| B | −1.76 Hz |
| C | 1.60 Hz |
Secondary Structure Sensitivity
| Secondary Structure | φ (°) | ³J (Hz) |
|---|---|---|
| α-helix | −60 | ~4.1 |
| β-strand | −135 | ~9.4 |
| PPII | −75 | ~6.1 |
| Extended | ±180 | ~4.1 |
Proline Residues
Proline (PRO) and D-proline (DPR) form a secondary amine in the peptide bond and therefore lack an amide proton. The ³J(HN–Hα) coupling is physically undefined for these residues. synth_pdb.coupling automatically excludes them from the output.
D-Amino Acids
For D-amino acids the stereochemical inversion means:
This correction is applied automatically to all D-residue codes (DAL, DAR, … DVA).
API Reference
coupling
Coupling utilities for synth-pdb.
This module now provides compatibility shims that re-export from the synth-nmr package. For direct usage of NMR functionality, consider using synth-nmr directly: pip install synth-nmr from synth_nmr import calculate_hn_ha_coupling, predict_couplings_from_structure
The J-coupling (scalar coupling) is a fundamental NMR parameter that provides information about the chemical bonding and local geometry of a molecule. In proteins, the 3J(HN-HA) coupling is particularly useful as it relates to the phi torsion angle via the Karplus equation.
See: https://github.com/elkins/synth-nmr
Attributes
calculate_hn_ha_coupling = _j.calculate_hn_ha_coupling_from_phi
module-attribute
Functions
predict_couplings_from_structure(structure)
Predict 3J_HNHa coupling constants from a Biotite AtomArray.
This function wraps the synth-nmr engine and provides biophysical enhancements: 1. Filters out residues that physically lack a backbone amide proton (e.g., Proline). 2. Corrects the Karplus equation phase for D-amino acids by inverting the phi angle.
EDUCATIONAL NOTE - The Karplus Equation and 3J(HN-HA) Couplings
The 3J(HN-HA) scalar coupling is a through-bond magnetic interaction between the backbone amide proton (HN) and the alpha proton (HA). This coupling is highly sensitive to the intervening H-N-CA-H dihedral angle (theta), which is geometrically related to the backbone Ramachandran Phi (phi) angle.
The relationship is empirically described by the Karplus equation
3J(theta) = A * cos^2(theta) - B * cos(theta) + C
For typical L-amino acids, theta ~ phi - 60deg. This means: - In an ideal alpha-helix (phi ~ -60deg), theta ~ -120deg, yielding small couplings (3-5 Hz). - In a beta-sheet (phi ~ -120deg to -140deg), theta ~ 180deg, yielding large couplings (8-10 Hz).
EDUCATIONAL NOTE - Proline and Secondary Amines
Proline (PRO) and its D-isomer (DPR) are unique among standard amino acids because their sidechain cyclizes onto the backbone nitrogen, forming a secondary amine. Consequently, the nitrogen atom lacks an attached hydrogen when incorporated into a peptide bond. Without an amide proton, there is no H-N-CA-H spin system, and thus the 3J(HN-HA) coupling is physically undefined. Our shim layer explicitly strips these residues from the results.
EDUCATIONAL NOTE - D-Amino Acids and Stereochemistry
D-amino acids are non-superimposable mirror images of natural L-amino acids. Because the Karplus equation is parameterized for the natural L-configuration, directly feeding a D-amino acid's phi angle into the standard Karplus curve yields incorrect results (e.g., predicting ~6.3 Hz instead of ~3.8 Hz for a D-alpha helix where phi ~ +60deg).
Due to mirror symmetry, the geometric relationship inverts: theta_D(phi) = -theta_L(-phi). Therefore, we can accurately predict the D-amino acid coupling by evaluating the L-parameterized Karplus equation at the negated phi angle: J_D(phi) = J_L(-phi).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
structure
|
Any
|
Biotite AtomArray |
required |
Returns:
| Type | Description |
|---|---|
dict[str, dict[int, float]]
|
Dict keyed by Chain ID -> Residue ID -> J-coupling value (Hz). |
Source code in synth_pdb/coupling.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | |
Usage Examples
Low-level: single φ angle
from synth_pdb.coupling import calculate_hn_ha_coupling
j_helix = calculate_hn_ha_coupling(-60.0) # → ~3.9 Hz
j_sheet = calculate_hn_ha_coupling(-135.0) # → ~8.9 Hz
print(f"Helix: {j_helix:.2f} Hz, Sheet: {j_sheet:.2f} Hz")
Structure-level: all residues
import io
import biotite.structure.io.pdb as pdb_io
from synth_pdb.generator import generate_pdb_content
from synth_pdb.coupling import predict_couplings_from_structure
pdb_content = generate_pdb_content(sequence_str="LKELEKELELK")
structure = pdb_io.PDBFile.read(io.StringIO(pdb_content)).get_structure(model=1)
couplings = predict_couplings_from_structure(structure)
# Iterate over all chains and residues
for chain_id, residues in couplings.items():
for res_id, j_val in residues.items():
print(f"Chain {chain_id}, Residue {res_id}: {j_val:.2f} Hz")
Validation against experimental data
import numpy as np
from synth_pdb.coupling import predict_couplings_from_structure
# Experimental 3J couplings for Ubiquitin (Vuister & Bax 1993, Table 1)
exp_j = {2: 5.5, 3: 7.2, 4: 6.8, 5: 5.1, 7: 8.3, 8: 4.9}
couplings = predict_couplings_from_structure(structure)
chain_A = couplings.get("A", {})
obs, pred = [], []
for res_id, exp_val in exp_j.items():
if res_id in chain_A:
obs.append(exp_val)
pred.append(chain_A[res_id])
mae = float(np.mean(np.abs(np.array(obs) - np.array(pred))))
print(f"MAE vs experimental: {mae:.2f} Hz (literature target < 2.0 Hz)")
References
-
Vuister, G.W. & Bax, A. (1993). Quantitative J correlation: a new approach for measuring homonuclear three-bond J(HN–Hα) coupling constants in ¹⁵N-enriched proteins. J Am Chem Soc, 115, 7772–7777. DOI: 10.1021/ja00070a024
-
Karplus, M. (1963). Vicinal proton coupling in nuclear magnetic resonance. J Am Chem Soc, 85, 2870–2871. DOI: 10.1021/ja00901a059