Essential Dynamics Analysis

Synopsis

This example shows how to perform essential dynamics analysis of molecular dynamics (MD) trajectories. A EDA instance that stores covariance matrix and principal modes that describes the essential dynamics of the system observed in the simulation will be built. EDA and principal modes (Mode) can be used as input to functions in dynamics module for further analysis.

User needs to provide trajectory in DCD file format and PDB file of the system.

Example input:

Setup environment

We start by importing everything from ProDy:

In [1]: from prody import *

In [2]: from pylab import *

In [3]: ion()

Parse reference structure

The PDB file provided with this example contains and X-ray structure which will be useful in a number of places, so let’s start with parsing this file first:

In [4]: structure = parsePDB('mdm2.pdb')

In [5]: structure
Out[5]: <AtomGroup: mdm2 (1449 atoms)>

This function returned a AtomGroup instance that stores all atomic data parsed from the PDB file.

EDA calculations

Essential dynamics analysis (EDA or PCA) of a trajectory can be performed in two ways.

Small files

If you are analyzing a small trajectory, you can use an Ensemble instance obtained by parsing the trajectory at once using parseDCD():

In [6]: ensemble = parseDCD('mdm2.dcd')

In [7]: ensemble.setCoords(structure)

In [8]: ensemble.setAtoms(structure.calpha)

In [9]: ensemble
Out[9]: <Ensemble: mdm2 (0:500:1) (500 conformations; selected 85 of 1449 atoms)>

In [10]: ensemble.superpose()

In [11]: eda_ensemble = EDA('MDM2 Ensemble')

In [12]: eda_ensemble.buildCovariance( ensemble )

In [13]: eda_ensemble.calcModes()

In [14]: eda_ensemble
Out[14]: <EDA: MDM2 Ensemble (20 modes; 85 atoms)>

Large files

If you are analyzing a large trajectory, you can pass the trajectory instance to the PCA.buildCovariance() method as follows:

In [15]: dcd = DCDFile('mdm2.dcd')

In [16]: dcd.link(structure)

In [17]: dcd.setAtoms(structure.calpha)

In [18]: dcd
Out[18]: <DCDFile: mdm2 (linked to AtomGroup mdm2; next 0 of 500 frames; selected 85 of 1449 atoms)>

In [19]: eda_trajectory = EDA('MDM2 Trajectory')

In [20]: eda_trajectory.buildCovariance( dcd )

In [21]: eda_trajectory.calcModes()

In [22]: eda_trajectory
Out[22]: <EDA: MDM2 Trajectory (20 modes; 85 atoms)>

Comparison

In [23]: printOverlapTable(eda_ensemble[:3], eda_trajectory[:3])
Overlap Table
                       EDA MDM2 Trajectory
                         #1     #2     #3
EDA MDM2 Ensemble #1   +1.00   0.00   0.00
EDA MDM2 Ensemble #2    0.00  +1.00   0.00
EDA MDM2 Ensemble #3    0.00   0.00  +1.00

Overlap values of +1 along the diagonal of the table shows that top ranking 3 essential (principal) modes are the same.

Multiple files

It is also possible to analyze multiple trajectory files without concatenating them. In this case we will use data from two independent simulations

In [24]: trajectory = Trajectory('mdm2.dcd')

In [25]: trajectory.addFile('mdm2sim2.dcd')

In [26]: trajectory
Out[26]: <Trajectory: mdm2 (2 files; next 0 of 1000 frames; 1449 atoms)>

In [27]: trajectory.link(structure)

In [28]: trajectory.setCoords(structure)

In [29]: trajectory.setAtoms(structure.calpha)

In [30]: trajectory
Out[30]: <Trajectory: mdm2 (linked to AtomGroup mdm2; 2 files; next 0 of 1000 frames; selected 85 of 1449 atoms)>

In [31]: eda = EDA('mdm2')

In [32]: eda.buildCovariance( trajectory )

In [33]: eda.calcModes()

In [34]: eda
Out[34]: <EDA: mdm2 (20 modes; 85 atoms)>

Save your work

You can save your work using ProDy function saveModel(). This will allow you to avoid repeating calculations when you return to your work later:

In [35]: saveModel(eda)
Out[35]: 'mdm2.eda.npz'

loadModel() function can be used to load this object without any loss.

Analysis

Let’s print fraction of variance for top raking 4 essential modes:

In [36]: for mode in eda_trajectory[:4]:
   ....:     print(calcFractVariance(mode).round(2))
   ....: 
0.26
0.11
0.08
0.06

You can find more analysis functions in Dynamics Analysis.

Plotting

Now, let’s project the trajectories onto top three essential modes:

In [37]: mdm2ca_sim1 = trajectory[:500]

In [38]: mdm2ca_sim1.superpose()

In [39]: mdm2ca_sim2 = trajectory[500:]

In [40]: mdm2ca_sim2.superpose()

# We project independent trajectories in different color
In [41]: showProjection(mdm2ca_sim1, eda[:3], color='red', marker='.');

In [42]: showProjection(mdm2ca_sim2, eda[:3], color='blue', marker='.');

# Now let's mark the beginning of the trajectory with a circle
In [43]: showProjection(mdm2ca_sim1[0], eda[:3], color='red', marker='o', ms=12);

In [44]: showProjection(mdm2ca_sim2[0], eda[:3], color='blue', marker='o', ms=12);

# Now let's mark the end of the trajectory with a square
In [45]: showProjection(mdm2ca_sim1[-1], eda[:3], color='red', marker='s', ms=12);

In [46]: showProjection(mdm2ca_sim2[-1], eda[:3], color='blue', marker='s', ms=12);
../../_images/trajectory_analysis_eda_projection.png

You can find more plotting functions in Dynamics Analysis and Measurement Tools modules.

Visualization

The above projection is shown for illustration. Interpreting the essential modes and projection of snapshots onto them is case dependent. One should know what kind of motion the top essential modes describe. You can use Normal Mode Wizard for visualizing essential mode shapes and fluctuations along these modes.

We can write essential modes in NMD Format for NMWiz as follows:

In [47]: writeNMD('mdm2_eda.nmd', eda[:3], structure.select('calpha'))
Out[47]: 'mdm2_eda.nmd'