ANM calculations are carried out in the same way as GNM calculations except that the ANM uses the Hessian matrix rather than the Kirchhoff matrix. There are also additional analysis options arising from the modes being 3D, such as visualization thereof in VMD using the normal mode wizard (NMWiz) and the comparison of ANM modes with the transition vectors between experimental structures.
from prody import *
from numpy import *
from matplotlib.pyplot import *
confProDy(auto_show=False)
confProDy(auto_secondary=True)
First we parse a structure from the PDB. We will use the open structure of adenylate kinase and also parse the closed structure for comparison afterwards.
open_aa = parsePDB('4ake', compressed=False)
open_ca = open_aa.select('calpha and chain A')
open_ca
closed_aa = parsePDB('1ake', compressed=False)
closed_ca = closed_aa.select('calpha and chain A')
closed_ca
Next, we instantiate an object of ANM class for the open structure.
anm_open = ANM('open_AKE')
We then build the Hessian matrix and calculate normal modes.
anm_open.buildHessian(open_ca)
anm_open.calcModes()
We can show mode shapes, square fluctuations, and cross-correlations as we did with GNM. Let's start with the first nonzero mode:
figure(dpi=100)
showMode(anm_open[0]);
legend();
figure(dpi=100)
showSqFlucts(anm_open[0]);
If we want to calculate mean square fluctuations using computed modes, then we do not need to select any specific mode.
figure(dpi=100)
showSqFlucts(anm_open); # MSFs based on "computed modes"
figure(dpi=100)
showCrossCorr(anm_open[0]);
# cross-correlation based on "computed modes"
figure(dpi=100)
showCrossCorr(anm_open);
In order to visualize ANM modes in NMWiz, we need to write them into a .nmd file using writeNMD
.
writeNMD('anm_open_ake', anm_open, open_ca)
First we will align the open and closed structures before visualizing them together in VMD. Since the chains of these two structures match, we do not need to find the mathcing atoms in these chains. Let's first look at the RMSD between the resolved structures.
calcRMSD(closed_ca, open_ca)
Alignment of the closed structure onto the open one can be easily done using the function superpose
:
aligned_closed_ca, T = superpose(closed_ca, open_ca)
RMSD between these structures is minimized after this alignment as we will see below:
calcRMSD(aligned_closed_ca, open_ca)
writePDB('1akeA_ca_alg.pdb', aligned_closed_ca)
writePDB('4akeA_ca.pdb', open_ca)
We can now run VMD from jupyter notebook using an exclamation mark to tell the jupyter notebook that it is a command run by the operating system not by the python kernel.
We can easily calculate the deformation vector describing the change between two structures of the protein AKE, and then systematically compare it with ANM modes. Because the chains of these structures match and we have already aligned them, it is straightforward to calculate the deformation vector using calcDeformVector
.
defvec = calcDeformVector(open_ca, aligned_closed_ca)
We then show the overlap or correlation cosine between the ANM modes and the deformation vector. The cumulative overlap is the square root of the sum of squared overlaps.
figure(dpi=100)
showOverlap(defvec.getNormed(), anm_open)
showCumulOverlap(defvec.getNormed(), anm_open, 'r');
We observe that the first nonzero mode in the above figure, whose index is 0, overlaps best with the transition described by the deformation vector. Therefore, we can use this mode to generate a trajectory by the method traverseMode
. This takes steps in both directions starting from the provided structure to generate conformers along the mode chosen.
Let's first generate a trajectory along this mode based on $C^\alpha$ atoms, and then calculate RMSD between the last conformer in the trajectory and the closed structure to see how close we can get to the latter. Remember RMSD between aligned structures is 7.13 $\mathring{A}$.
ca_mode1 = traverseMode(anm_open[0], open_ca, rmsd=5.0)
ca_mode1.setAtoms(open_ca)
calcRMSD(aligned_closed_ca, ca_mode1[-1])
Let's generate a similar trajectory for all atom this time. In order to do that, we can extend $C^\alpha$-based ANM to all atoms by the function extendModel
.
aa_anm, aa_atoms = extendModel(anm_open, open_ca, open_aa)
The next step is to use traverseMode
again to generate conformers along the extended mode.
aa_mode1 = traverseMode(aa_anm[0], aa_atoms)
aa_mode1.setAtoms(aa_atoms)
writePDB('4ake_all_atom_mode1.pdb', aa_mode1)
writeNMD('4ake_all_atom_anm', aa_anm, aa_atoms)
We can now visualize both in VMD.